GHK_0.9.8e5_Py3.7.py

changeset 51
10fb0fc3d79f
parent 49
7c14c9a085ba
child 52
6eb017aeb6fe
equal deleted inserted replaced
49:7c14c9a085ba 51:10fb0fc3d79f
1 # -*- coding: utf-8 -*-
2 """
3 Copyright 2016, 2019 Volker Freudenthaler
4
5 Licensed under the EUPL, Version 1.1 only (the "Licence").
6
7 You may not use this work except in compliance with the Licence.
8 A copy of the licence is distributed with the code. Alternatively, you may obtain
9 a copy of the Licence at:
10
11 https://joinup.ec.europa.eu/community/eupl/og_page/eupl
12
13 Unless required by applicable law or agreed to in writing, software distributed
14 under the Licence is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS
15 OF ANY KIND, either express or implied. See the Licence for the specific language governing
16 permissions and limitations under the Licence.
17
18 Equation reference: http://www.atmos-meas-tech-discuss.net/amt-2015-338/amt-2015-338.pdf
19 With equations code from Appendix C
20 Python 3.7, seaborn 0.9.0
21
22 Code description:
23
24 From measured lidar signals we cannot directly determine the desired backscatter coefficient (F11) and the linear depolarization ratio (LDR)
25 because of the cross talk between the channles and systematic errors of a lidar system.
26 http://www.atmos-meas-tech-discuss.net/amt-2015-338/amt-2015-338.pdf provides an analytical model for the description of these errors,
27 with which the measured signals can be corrected.
28 This code simulates the lidar measurements with "assumed true" model parameters from an input file, and calculates the correction parameters (G,H, and K).
29 The "assumed true" system parameters are the ones we think are the right ones, but in reality these parameters probably deviate from the assumed truth due to
30 uncertainties. The uncertainties of the "assumed true" parameters can be described in the input file. Then this code calculates the lidar signals and the
31 gain ratio eta* with all possible combinations of "errors", which represents the distribution of "possibly real" signals, and "corrects" them with the "assumed true"
32 GHK parameters (GT0, GR0, HT0, HR0, and K0) to derive finally the distributions of "possibly real" linear depolarization ratios (LDRCorr),
33 which are plotted for five different input linear depolarization ratios (LDRtrue). The red bars in the plots represent the input values of LDRtrue.
34 A complication arises from the fact that the correction parameter K = eta*/eta (Eq. 83) can depend on the LDR during the calibration measurement, i.e. LDRcal or aCal
35 in the code (see e.g. Eqs. (103), (115), and (141); mind the mistake in Eq. (116)). Therefor values of K for LDRcal = 0.004, 0.2, and 0.45 are calculated for
36 "assumed true" system parameters and printed in the output file behind the GH parameters. The full impact of the LDRcal dependent K can be considered in the error
37 calculation by specifying a range of possible LDRcal values in the input file. For the real calibration measurements a calibration range with low or no aerosol
38 content should be chosen, and the default in the input file is a range of LDRcal between 0.004 and 0.014 (i.e. 0.009 +-0.005).
39
40 Tip: In case you run the code with Spyder, all output text and plots can be displayed together in an IPython console, which can be saved as an html file.
41
42 Ver. 0.9.7: includes the random error (signal noise) of the calibration and standard measurements
43 Changes:
44 Line 1687 Eta = (TaR * TiR) / (TaT * TiT)
45 Line 1691 K = Etax / Eta # K of the real system; but correction in Line 1721 with K0 / Etax
46 should work with nTCalT = nTCalR = 0
47 Ver. 0.9.7b:
48 ToDo: include error due to TCalT und TCalR => determination of NCalT and NCalR etc. in error calculation line 1741ff
49 combined error loops iNI and INCal for signals
50 Ver. 0.9.7c: individual error loops for each of the six signals
51 Ver. 0.9.7c2: different calculation of the signal noise errors
52 Ver. 0.9.7c3: n.a.different calculation of the signal noise errors
53 Ver. 0.9.7c4: test to speed up the loops for error calculation by moving them just before the actual calculation: still some code errors
54 Ver. 0.9.8:
55 - correct calculation of Eta for cleaned anaylsers considering the combined transmission Eta = (TaT* TiT)(1 + cos2RotaT * DaT * DiT) and (TaR * TiR)(1 + cos2RotaR * DaR * DiR) according to the papers supplement Eqs. (S.10.10.1) ff
56 - calculation of the PLDR from LDR and BSR, BSR, and LDRm
57 - ND-filters can be added for the calibration measurements in the transmitted (TCalT) and the reflected path (TCalR) in order to include their uncertainties in the error calculation.
58 Ver. 0.9.8b: change from "TTa = TiT * TaT" to "TTa = TiT * TaT * ATPT" etc. (compare ver 0.9.8 with 0.9.8b) removes
59 - the strong Tp dependence of the errors
60 - the factor 2 in the GH parameters
61 - see c:\technik\Optik\Polarizers\DepCal\ApplOpt\GH-parameters-190114.odt
62 Ver. 0.9.8c: includes error of Etax
63 Ver. 0.9.8d: Eta0, K0 etc in error loop replaced by Eta0y, K0y etc. Changes in signal noise calculations
64 Ver. 0.9.8e: ambiguous laser spec. DOLP (no discrimination between left and right circular polarisation) replaced by Stokes parameters Qin, Uin
65 Ver. 0.9.8e2: Added plot of LDRsim, Etax, Etapx, Etamx; LDRCorr and aLDRcorr consistently named
66 Ver. 0.9.8e3: Change of OutputFile name; Change of Ir and It noise if (CalcFrom0deg) = False; (Different calculation of error contributions tested but not implemented)
67 Ver. 0.9.8e4: text changed for y=+-1 (see line 274 ff and line 1044 ff
68 Ver. 0.9.8e5: changed: LDRunCorr = LDRsim / Etax
69
70 ========================================================
71 simulation: LDRsim = Ir / It with variable parameters (possible truths)
72 G,H,Eta,Etax,K
73 It = TaT * TiT * ATP1 * TiO * TiE * (GT + atrue * HT)
74 LDRsim = Ir / It
75 consistency test: is forward simulation and correction consistent?
76 LDRCorr = (LDRsim / Eta * (GT + HT) - (GR + HR)) / ((GR - HR) - LDRsim / Eta * (GT - HT)) => atrue?
77 assumed true: G0,H0,Eta0,Etax0,K0 => actual retrievals of LDRCorr
78 => correct possible truths with assumed true G0,H0,Eta0
79 measure: It, Ir, EtaX
80 LDRunCorr = LDRsim / Etax
81 correct it with G0,H0,K0:
82 LDRCorr = (LDRsim / (Etax / K0) * (GT0 + HT0) - (GR0 + HR0)) / ((GR0 - HR0) - LDRsim0 / (Etax / K0) * (GT0 - HT0))
83 """
84 # Comment: The code might works with Python 2.7 with the help of following line, which enables Python2 to correctly interpret the Python 3 print statements.
85 from __future__ import print_function
86 # !/usr/bin/env python3
87
88 import os
89 import sys
90
91 from scipy.stats import kurtosis
92 from scipy.stats import skew
93 # use: kurtosis(data, fisher=True,bias=False) => 0; skew(data,bias=False) => 0
94 # Comment: the seaborn library makes nicer plots, but the code works also without it.
95 import numpy as np
96 import matplotlib.pyplot as plt
97
98 try:
99 import seaborn as sns
100
101 sns_loaded = True
102 except ImportError:
103 sns_loaded = False
104
105 # from time import clock # python 2
106 from timeit import default_timer as clock
107
108 # from matplotlib.backends.backend_pdf import PdfPages
109 # pdffile = '{}.pdf'.format('path')
110 # pp = PdfPages(pdffile)
111 ## pp.savefig can be called multiple times to save to multiple pages
112 # pp.savefig()
113 # pp.close()
114
115 from contextlib import contextmanager
116
117 @contextmanager
118 def redirect_stdout(new_target):
119 old_target, sys.stdout = sys.stdout, new_target # replace sys.stdout
120 try:
121 yield new_target # run some code with the replaced stdout
122 finally:
123 sys.stdout.flush()
124 sys.stdout = old_target # restore to the previous value
125
126 '''
127 real_raw_input = vars(__builtins__).get('raw_input',input)
128 '''
129 try:
130 import __builtin__
131
132 input = getattr(__builtin__, 'raw_input')
133 except (ImportError, AttributeError):
134 pass
135
136 from distutils.util import strtobool
137
138
139 def user_yes_no_query(question):
140 sys.stdout.write('%s [y/n]\n' % question)
141 while True:
142 try:
143 return strtobool(input().lower())
144 except ValueError:
145 sys.stdout.write('Please respond with \'y\' or \'n\'.\n')
146
147
148 # if user_yes_no_query('want to exit?') == 1: sys.exit()
149
150 abspath = os.path.abspath(__file__)
151 dname = os.path.dirname(abspath)
152 fname = os.path.basename(abspath)
153 os.chdir(dname)
154
155 # PrintToOutputFile = True
156
157 sqr05 = 0.5 ** 0.5
158
159 # ---- Initial definition of variables; the actual values will be read in with exec(open('./optic_input.py').read()) below
160 # Do you want to calculate the errors? If not, just the GHK-parameters are determined.
161 Error_Calc = True
162 LID = "internal"
163 EID = "internal"
164 # --- IL Laser IL and +-Uncertainty
165 Qin, dQin, nQin = 1., 0.0, 0 # second Stokes vector parameter; default 1 => linear polarization
166 Vin, dVin, nVin = 0., 0.0, 0 # fourth Stokes vector parameter
167 RotL, dRotL, nRotL = 0.0, 0.0, 1 # alpha; rotation of laser polarization in degrees; default 0
168 # IL = 1e5 #photons in the laser beam, including detection efficiency of the telescope, atmodspheric and r^2 attenuation
169 # --- ME Emitter and +-Uncertainty
170 DiE, dDiE, nDiE = 0., 0.00, 1 # Diattenuation
171 TiE = 1. # Unpolarized transmittance
172 RetE, dRetE, nRetE = 0., 180.0, 0 # Retardance in degrees
173 RotE, dRotE, nRotE = 0., 0.0, 0 # beta: Rotation of optical element in degrees
174 # --- MO Receiver Optics including telescope
175 DiO, dDiO, nDiO = -0.055, 0.003, 1
176 TiO = 0.9
177 RetO, dRetO, nRetO = 0., 180.0, 2
178 RotO, dRotO, nRotO = 0., 0.1, 1 # gamma
179 # --- PBS MT transmitting path defined with (TS,TP); and +-Uncertainty
180 TP, dTP, nTP = 0.98, 0.02, 1
181 TS, dTS, nTS = 0.001, 0.001, 1
182 TiT = 0.5 * (TP + TS)
183 DiT = (TP - TS) / (TP + TS)
184 # PolFilter
185 RetT, dRetT, nRetT = 0., 180., 0
186 ERaT, dERaT, nERaT = 0.001, 0.001, 1
187 RotaT, dRotaT, nRotaT = 0., 3., 1
188 DaT = (1 - ERaT) / (1 + ERaT)
189 TaT = 0.5 * (1 + ERaT)
190 # --- PBS MR reflecting path defined with (RS,RP); and +-Uncertainty
191 RS_RP_depend_on_TS_TP = False
192 if (RS_RP_depend_on_TS_TP):
193 RP, dRP, nRP = 1 - TP, 0.0, 0
194 RS, dRS, nRS = 1 - TS, 0.0, 0
195 else:
196 RP, dRP, nRP = 0.05, 0.01, 1
197 RS, dRS, nRS = 0.98, 0.01, 1
198 TiR = 0.5 * (RP + RS)
199 DiR = (RP - RS) / (RP + RS)
200 # PolFilter
201 RetR, dRetR, nRetR = 0., 180., 0
202 ERaR, dERaR, nERaR = 0.001, 0.001, 1
203 RotaR, dRotaR, nRotaR = 90., 3., 1
204 DaR = (1 - ERaR) / (1 + ERaR)
205 TaR = 0.5 * (1 + ERaR)
206
207 # +++ Orientation of the PBS with respect to the reference plane (see Polarisation-orientation.png and Polarisation-orientation-2.png in /system_settings)
208 # Y = +1: PBS incidence plane is parallel to reference plane and polarisation in reference plane is finally transmitted.
209 # Y = -1: PBS incidence plane is perpendicular to reference plane and polarisation in reference plane is finally reflected.
210 Y = 1.
211
212 # Calibrator = type defined by matrix values
213 LocC = 4 # location of calibrator: behind laser = 1; behind emitter = 2; before receiver = 3; before PBS = 4
214
215 # --- Additional attenuation (transmission of the ND-filter) during the calibration
216 TCalT, dTCalT, nTCalT = 1, 0., 0 # transmitting path; error calc not working yet
217 TCalR, dTCalR, nTCalR = 1, 0., 0 # reflecting path; error calc not working yet
218
219 # *** signal noise error calculation
220 # --- number of photon counts in the signal summed up in the calibration range during the calibration measurements
221 NCalT = 1e6 # default 1e6, assumed the same in +45° and -45° signals
222 NCalR = 1e6 # default 1e6, assumed the same in +45° and -45° signals
223 NILfac = 1.0 # duration of standard (0°) measurement relative to calibration measurements
224 nNCal = 0 # error nNCal: one-sigma in steps to left and right for calibration signals
225 nNI = 0 # error nNI: one-sigma in steps to left and right for 0° signals
226 NI = 50000 #number of photon counts in the parallel 0°-signal
227 eFacT = 1.0 # rel. amplification of transmitted channel, approximate values are sufficient; def. = 1
228 eFacR = 10.0
229 IoutTp0, IoutTp, dIoutTp0 = 0.5, 0.5, 0.0
230 IoutTm0, IoutTm, dIoutTm0 = 0.5, 0.5, 0.0
231 IoutRp0, IoutRp, dIoutRp0 = 0.5, 0.5, 0.0
232 IoutRm0, IoutRm, dIoutRm0 = 0.5, 0.5, 0.0
233 It0, It, dIt0 = 1 , 1, 0
234 Ir0, Ir, dTr0 = 1 , 1, 0
235 CalcFrom0deg = True
236
237 TypeC = 3 # linear polarizer calibrator
238 # example with extinction ratio 0.001
239 DiC, dDiC, nDiC = 1.0, 0., 0 # ideal 1.0
240 TiC = 0.5 # ideal 0.5
241 RetC, dRetC, nRetC = 0.0, 0.0, 0
242 RotC, dRotC, nRotC = 0.0, 0.1, 0 # constant calibrator offset epsilon
243 RotationErrorEpsilonForNormalMeasurements = False # is in general False for TypeC == 3 calibrator
244
245 # Rotation error without calibrator: if False, then epsilon = 0 for normal measurements
246 RotationErrorEpsilonForNormalMeasurements = True
247 # BSR backscatter ratio
248 # BSR, dBSR, nBSR = 10, 0.05, 1
249 BSR = np.zeros(5)
250 BSR = [1.1, 2, 5, 10., 50.]
251 # theoretical molecular LDR LDRm
252 LDRm, dLDRm, nLDRm = 0.004, 0.001, 1
253 # LDRCal assumed atmospheric linear depolarization ratio during the calibration measurements (first guess)
254 LDRCal0, dLDRCal, nLDRCal = 0.25, 0.04, 1
255 LDRCal = LDRCal0
256 # measured LDRm will be corrected with calculated parameters
257 LDRmeas = 0.015
258 # LDRtrue for simulation of measurement => LDRsim
259 LDRtrue = 0.004
260 LDRtrue2 = 0.004
261 LDRunCorr = 1.
262 # Initialize other values to 0
263 ER, nER, dER = 0.001, 0, 0.001
264 K = 0.
265 Km = 0.
266 Kp = 0.
267 LDRCorr = 0.
268 Eta = 0.
269 Ir = 0.
270 It = 0.
271 h = 1.
272
273 Loc = ['', 'behind laser', 'behind emitter', 'before receiver', 'before PBS']
274 Type = ['', 'mechanical rotator', 'hwp rotator', 'linear polarizer', 'qwp rotator', 'circular polarizer',
275 'real HWP +-22.5°']
276
277 bPlotEtax = False
278
279 # end of initial definition of variables
280 # *******************************************************************************************************************************
281 # --- Read actual lidar system parameters from optic_input.py (must be in the programs sub-directory 'system_settings')
282 # *******************************************************************************************************************************
283
284 # InputFile = 'optic_input_0.9.8e4-PollyXT_Lacros.py'
285 InputFile = 'optic_input_example_lidar_ver0.9.8e.py'
286
287 # *******************************************************************************************************************************
288
289 '''
290 print("From ", dname)
291 print("Running ", fname)
292 print("Reading input file ", InputFile, " for")
293 '''
294 input_path = os.path.join('.', 'system_settings', InputFile)
295 # this works with Python 2 and 3!
296 exec(open(input_path).read(), globals())
297 # end of read actual system parameters
298
299
300 # --- Manual Parameter Change ---
301 # (use for quick parameter changes without changing the input file )
302 # DiO = 0.
303 # LDRtrue = 0.45
304 # LDRtrue2 = 0.004
305 # Y = -1
306 # LocC = 4 #location of calibrator: 1 = behind laser; 2 = behind emitter; 3 = before receiver; 4 = before PBS
307 # #TypeC = 6 Don't change the TypeC here
308 # RotationErrorEpsilonForNormalMeasurements = True
309 # LDRCal = 0.25
310 # # --- Errors
311 Qin0, dQin, nQin = Qin, dQin, nQin
312 Vin0, dVin, nVin = Vin, dVin, nVin
313 RotL0, dRotL, nRotL = RotL, dRotL, nRotL
314
315 DiE0, dDiE, nDiE = DiE, dDiE, nDiE
316 RetE0, dRetE, nRetE = RetE, dRetE, nRetE
317 RotE0, dRotE, nRotE = RotE, dRotE, nRotE
318
319 DiO0, dDiO, nDiO = DiO, dDiO, nDiO
320 RetO0, dRetO, nRetO = RetO, dRetO, nRetO
321 RotO0, dRotO, nRotO = RotO, dRotO, nRotO
322
323 DiC0, dDiC, nDiC = DiC, dDiC, nDiC
324 RetC0, dRetC, nRetC = RetC, dRetC, nRetC
325 RotC0, dRotC, nRotC = RotC, dRotC, nRotC
326
327 TP0, dTP, nTP = TP, dTP, nTP
328 TS0, dTS, nTS = TS, dTS, nTS
329 RetT0, dRetT, nRetT = RetT, dRetT, nRetT
330
331 ERaT0, dERaT, nERaT = ERaT, dERaT, nERaT
332 RotaT0, dRotaT, nRotaT = RotaT, dRotaT, nRotaT
333
334 RP0, dRP, nRP = RP, dRP, nRP
335 RS0, dRS, nRS = RS, dRS, nRS
336 RetR0, dRetR, nRetR = RetR, dRetR, nRetR
337
338 ERaR0, dERaR, nERaR = ERaR, dERaR, nERaR
339 RotaR0, dRotaR, nRotaR = RotaR, dRotaR, nRotaR
340
341 LDRCal0, dLDRCal, nLDRCal = LDRCal, dLDRCal, nLDRCal
342
343 # BSR0, dBSR, nBSR = BSR, dBSR, nBSR
344 LDRm0, dLDRm, nLDRm = LDRm, dLDRm, nLDRm
345 # ---------- End of manual parameter change
346
347 RotL, RotE, RetE, DiE, RotO, RetO, DiO, RotC, RetC, DiC = RotL0, RotE0, RetE0, DiE0, RotO0, RetO0, DiO0, RotC0, RetC0, DiC0
348 TP, TS, RP, RS, ERaT, RotaT, RetT, ERaR, RotaR, RetR = TP0, TS0, RP0, RS0, ERaT0, RotaT0, RetT0, ERaR0, RotaR0, RetR0
349 LDRCal = LDRCal0
350 DTa0, TTa0, DRa0, TRa0, LDRsimx, LDRCorr = 0., 0., 0., 0., 0., 0.
351 TCalT0, TCalR0 = TCalT, TCalR
352
353 TiT = 0.5 * (TP + TS)
354 DiT = (TP - TS) / (TP + TS)
355 ZiT = (1. - DiT ** 2) ** 0.5
356 TiR = 0.5 * (RP + RS)
357 DiR = (RP - RS) / (RP + RS)
358 ZiR = (1. - DiR ** 2) ** 0.5
359
360 C2aT = np.cos(np.deg2rad(2. * RotaT))
361 C2aR = np.cos(np.deg2rad(2. * RotaR))
362 ATPT = float(1. + C2aT * DaT * DiT)
363 ARPT = float(1. + C2aR * DaR * DiR)
364 TTa = TiT * TaT * ATPT # unpolarized transmission
365 TRa = TiR * TaR * ARPT # unpolarized transmission
366 Eta0 = TRa / TTa
367
368 # --- alternative texts for output
369 dY = ['perpendicular', '', 'parallel']
370 dY2 = ['reflected', '', 'transmitted']
371 if ((abs(RotL) < 45 and Y == 1) or (abs(RotL) >= 45 and Y == -1)):
372 dY3 = "the parallel laser polarisation is detected in the transmitted channel."
373 else:
374 dY3 = "the parallel laser polarisation is detected in the reflected channel."
375
376 # --- check input errors
377 if ((Qin ** 2 + Vin ** 2) ** 0.5) > 1:
378 print("Error: degree of polarisation of laser > 1. Check Qin and Vin! ")
379 sys.exit()
380
381 # --- this subroutine is for the calculation of the PLDR from LDR, BSR, and LDRm -------------------
382 def CalcPLDR(LDR, BSR, LDRm):
383 PLDR = (BSR * (1. + LDRm) * LDR - LDRm * (1. + LDR)) / (BSR * (1. + LDRm) - (1. + LDR))
384 return (PLDR)
385 # --- this subroutine is for the calculation with certain fixed parameters ------------------------
386 def Calc(TCalT, TCalR, NCalT, NCalR, Qin, Vin, RotL, RotE, RetE, DiE, RotO, RetO, DiO,
387 RotC, RetC, DiC, TP, TS, RP, RS,
388 ERaT, RotaT, RetT, ERaR, RotaR, RetR, LDRCal):
389 # ---- Do the calculations of bra-ket vectors
390 h = -1. if TypeC == 2 else 1
391 # from input file: assumed LDRCal for calibration measurements
392 aCal = (1. - LDRCal) / (1. + LDRCal)
393 atrue = (1. - LDRtrue) / (1. + LDRtrue)
394
395 # angles of emitter and laser and calibrator and receiver optics
396 # RotL = alpha, RotE = beta, RotO = gamma, RotC = epsilon
397 S2a = np.sin(2 * np.deg2rad(RotL))
398 C2a = np.cos(2 * np.deg2rad(RotL))
399 S2b = np.sin(2 * np.deg2rad(RotE))
400 C2b = np.cos(2 * np.deg2rad(RotE))
401 S2ab = np.sin(np.deg2rad(2 * RotL - 2 * RotE))
402 C2ab = np.cos(np.deg2rad(2 * RotL - 2 * RotE))
403 S2g = np.sin(np.deg2rad(2 * RotO))
404 C2g = np.cos(np.deg2rad(2 * RotO))
405
406 # Laser with Degree of linear polarization DOLP
407 IinL = 1.
408 QinL = Qin
409 UinL = 0.
410 VinL = Vin
411 # VinL = (1. - DOLP ** 2) ** 0.5
412
413 # Stokes Input Vector rotation Eq. E.4
414 A = C2a * QinL - S2a * UinL
415 B = S2a * QinL + C2a * UinL
416 # Stokes Input Vector rotation Eq. E.9
417 C = C2ab * QinL - S2ab * UinL
418 D = S2ab * QinL + C2ab * UinL
419
420 # emitter optics
421 CosE = np.cos(np.deg2rad(RetE))
422 SinE = np.sin(np.deg2rad(RetE))
423 ZiE = (1. - DiE ** 2) ** 0.5
424 WiE = (1. - ZiE * CosE)
425
426 # Stokes Input Vector after emitter optics equivalent to Eq. E.9 with already rotated input vector from Eq. E.4
427 # b = beta
428 IinE = (IinL + DiE * C)
429 QinE = (C2b * DiE * IinL + A + S2b * (WiE * D - ZiE * SinE * VinL))
430 UinE = (S2b * DiE * IinL + B - C2b * (WiE * D - ZiE * SinE * VinL))
431 VinE = (-ZiE * SinE * D + ZiE * CosE * VinL)
432
433 # Stokes Input Vector before receiver optics Eq. E.19 (after atmosphere F)
434 IinF = IinE
435 QinF = aCal * QinE
436 UinF = -aCal * UinE
437 VinF = (1. - 2. * aCal) * VinE
438
439 # receiver optics
440 CosO = np.cos(np.deg2rad(RetO))
441 SinO = np.sin(np.deg2rad(RetO))
442 ZiO = (1. - DiO ** 2) ** 0.5
443 WiO = (1. - ZiO * CosO)
444
445 # calibrator
446 CosC = np.cos(np.deg2rad(RetC))
447 SinC = np.sin(np.deg2rad(RetC))
448 ZiC = (1. - DiC ** 2) ** 0.5
449 WiC = (1. - ZiC * CosC)
450
451 # Stokes Input Vector before the polarising beam splitter Eq. E.31
452 A = C2g * QinE - S2g * UinE
453 B = S2g * QinE + C2g * UinE
454
455 IinP = (IinE + DiO * aCal * A)
456 QinP = (C2g * DiO * IinE + aCal * QinE - S2g * (WiO * aCal * B + ZiO * SinO * (1. - 2. * aCal) * VinE))
457 UinP = (S2g * DiO * IinE - aCal * UinE + C2g * (WiO * aCal * B + ZiO * SinO * (1. - 2. * aCal) * VinE))
458 VinP = (ZiO * SinO * aCal * B + ZiO * CosO * (1. - 2. * aCal) * VinE)
459
460 # -------------------------
461 # F11 assuemd to be = 1 => measured: F11m = IinP / IinE with atrue
462 # F11sim = TiO*(IinE + DiO*atrue*A)/IinE
463 # -------------------------
464
465 # analyser
466 if (RS_RP_depend_on_TS_TP):
467 RS = 1. - TS
468 RP = 1. - TP
469
470 TiT = 0.5 * (TP + TS)
471 DiT = (TP - TS) / (TP + TS)
472 ZiT = (1. - DiT ** 2) ** 0.5
473 TiR = 0.5 * (RP + RS)
474 DiR = (RP - RS) / (RP + RS)
475 ZiR = (1. - DiR ** 2) ** 0.5
476 CosT = np.cos(np.deg2rad(RetT))
477 SinT = np.sin(np.deg2rad(RetT))
478 CosR = np.cos(np.deg2rad(RetR))
479 SinR = np.sin(np.deg2rad(RetR))
480
481 DaT = (1. - ERaT) / (1. + ERaT)
482 DaR = (1. - ERaR) / (1. + ERaR)
483 TaT = 0.5 * (1. + ERaT)
484 TaR = 0.5 * (1. + ERaR)
485
486 S2aT = np.sin(np.deg2rad(h * 2 * RotaT))
487 C2aT = np.cos(np.deg2rad(2 * RotaT))
488 S2aR = np.sin(np.deg2rad(h * 2 * RotaR))
489 C2aR = np.cos(np.deg2rad(2 * RotaR))
490
491 # Analyzer As before the PBS Eq. D.5; combined PBS and cleaning pol-filter
492 ATPT = (1. + C2aT * DaT * DiT) # unpolarized transmission correction
493 TTa = TiT * TaT * ATPT # unpolarized transmission
494 ATP1 = 1.
495 ATP2 = Y * (DiT + C2aT * DaT) / ATPT
496 ATP3 = Y * S2aT * DaT * ZiT * CosT / ATPT
497 ATP4 = S2aT * DaT * ZiT * SinT / ATPT
498 ATP = np.array([ATP1, ATP2, ATP3, ATP4])
499 DTa = ATP2 * Y
500
501 ARPT = (1 + C2aR * DaR * DiR) # unpolarized transmission correction
502 TRa = TiR * TaR * ARPT # unpolarized transmission
503 ARP1 = 1
504 ARP2 = Y * (DiR + C2aR * DaR) / ARPT
505 ARP3 = Y * S2aR * DaR * ZiR * CosR / ARPT
506 ARP4 = S2aR * DaR * ZiR * SinR / ARPT
507 ARP = np.array([ARP1, ARP2, ARP3, ARP4])
508 DRa = ARP2 * Y
509
510
511 # ---- Calculate signals and correction parameters for diffeent locations and calibrators
512 if LocC == 4: # Calibrator before the PBS
513 # print("Calibrator location not implemented yet")
514
515 # S2ge = np.sin(np.deg2rad(2*RotO + h*2*RotC))
516 # C2ge = np.cos(np.deg2rad(2*RotO + h*2*RotC))
517 S2e = np.sin(np.deg2rad(h * 2 * RotC))
518 C2e = np.cos(np.deg2rad(2 * RotC))
519 # rotated AinP by epsilon Eq. C.3
520 ATP2e = C2e * ATP2 + S2e * ATP3
521 ATP3e = C2e * ATP3 - S2e * ATP2
522 ARP2e = C2e * ARP2 + S2e * ARP3
523 ARP3e = C2e * ARP3 - S2e * ARP2
524 ATPe = np.array([ATP1, ATP2e, ATP3e, ATP4])
525 ARPe = np.array([ARP1, ARP2e, ARP3e, ARP4])
526 # Stokes Input Vector before the polarising beam splitter Eq. E.31
527 A = C2g * QinE - S2g * UinE
528 B = S2g * QinE + C2g * UinE
529 # C = (WiO*aCal*B + ZiO*SinO*(1-2*aCal)*VinE)
530 Co = ZiO * SinO * VinE
531 Ca = (WiO * B - 2 * ZiO * SinO * VinE)
532 # C = Co + aCal*Ca
533 # IinP = (IinE + DiO*aCal*A)
534 # QinP = (C2g*DiO*IinE + aCal*QinE - S2g*C)
535 # UinP = (S2g*DiO*IinE - aCal*UinE + C2g*C)
536 # VinP = (ZiO*SinO*aCal*B + ZiO*CosO*(1-2*aCal)*VinE)
537 IinPo = IinE
538 QinPo = (C2g * DiO * IinE - S2g * Co)
539 UinPo = (S2g * DiO * IinE + C2g * Co)
540 VinPo = ZiO * CosO * VinE
541
542 IinPa = DiO * A
543 QinPa = QinE - S2g * Ca
544 UinPa = -UinE + C2g * Ca
545 VinPa = ZiO * (SinO * B - 2 * CosO * VinE)
546
547 IinP = IinPo + aCal * IinPa
548 QinP = QinPo + aCal * QinPa
549 UinP = UinPo + aCal * UinPa
550 VinP = VinPo + aCal * VinPa
551 # Stokes Input Vector before the polarising beam splitter rotated by epsilon Eq. C.3
552 # QinPe = C2e*QinP + S2e*UinP
553 # UinPe = C2e*UinP - S2e*QinP
554 QinPoe = C2e * QinPo + S2e * UinPo
555 UinPoe = C2e * UinPo - S2e * QinPo
556 QinPae = C2e * QinPa + S2e * UinPa
557 UinPae = C2e * UinPa - S2e * QinPa
558 QinPe = C2e * QinP + S2e * UinP
559 UinPe = C2e * UinP - S2e * QinP
560
561 # Calibration signals and Calibration correction K from measurements with LDRCal / aCal
562 if (TypeC == 2) or (TypeC == 1): # rotator calibration Eq. C.4
563 # parameters for calibration with aCal
564 AT = ATP1 * IinP + h * ATP4 * VinP
565 BT = ATP3e * QinP - h * ATP2e * UinP
566 AR = ARP1 * IinP + h * ARP4 * VinP
567 BR = ARP3e * QinP - h * ARP2e * UinP
568 # Correction parameters for normal measurements; they are independent of LDR
569 if (not RotationErrorEpsilonForNormalMeasurements): # calibrator taken out
570 IS1 = np.array([IinPo, QinPo, UinPo, VinPo])
571 IS2 = np.array([IinPa, QinPa, UinPa, VinPa])
572 GT = np.dot(ATP, IS1)
573 GR = np.dot(ARP, IS1)
574 HT = np.dot(ATP, IS2)
575 HR = np.dot(ARP, IS2)
576 else:
577 IS1 = np.array([IinPo, QinPo, UinPo, VinPo])
578 IS2 = np.array([IinPa, QinPa, UinPa, VinPa])
579 GT = np.dot(ATPe, IS1)
580 GR = np.dot(ARPe, IS1)
581 HT = np.dot(ATPe, IS2)
582 HR = np.dot(ARPe, IS2)
583 elif (TypeC == 3) or (TypeC == 4): # linear polariser calibration Eq. C.5
584 # parameters for calibration with aCal
585 AT = ATP1 * IinP + ATP3e * UinPe + ZiC * CosC * (ATP2e * QinPe + ATP4 * VinP)
586 BT = DiC * (ATP1 * UinPe + ATP3e * IinP) - ZiC * SinC * (ATP2e * VinP - ATP4 * QinPe)
587 AR = ARP1 * IinP + ARP3e * UinPe + ZiC * CosC * (ARP2e * QinPe + ARP4 * VinP)
588 BR = DiC * (ARP1 * UinPe + ARP3e * IinP) - ZiC * SinC * (ARP2e * VinP - ARP4 * QinPe)
589 # Correction parameters for normal measurements; they are independent of LDR
590 if (not RotationErrorEpsilonForNormalMeasurements): # calibrator taken out
591 IS1 = np.array([IinPo, QinPo, UinPo, VinPo])
592 IS2 = np.array([IinPa, QinPa, UinPa, VinPa])
593 GT = np.dot(ATP, IS1)
594 GR = np.dot(ARP, IS1)
595 HT = np.dot(ATP, IS2)
596 HR = np.dot(ARP, IS2)
597 else:
598 IS1e = np.array([IinPo + DiC * QinPoe, DiC * IinPo + QinPoe, ZiC * (CosC * UinPoe + SinC * VinPo),
599 -ZiC * (SinC * UinPoe - CosC * VinPo)])
600 IS2e = np.array([IinPa + DiC * QinPae, DiC * IinPa + QinPae, ZiC * (CosC * UinPae + SinC * VinPa),
601 -ZiC * (SinC * UinPae - CosC * VinPa)])
602 GT = np.dot(ATPe, IS1e)
603 GR = np.dot(ARPe, IS1e)
604 HT = np.dot(ATPe, IS2e)
605 HR = np.dot(ARPe, IS2e)
606 elif (TypeC == 6): # diattenuator calibration +-22.5° rotated_diattenuator_X22x5deg.odt
607 # parameters for calibration with aCal
608 AT = ATP1 * IinP + sqr05 * DiC * (ATP1 * QinPe + ATP2e * IinP) + (1. - 0.5 * WiC) * (
609 ATP2e * QinPe + ATP3e * UinPe) + ZiC * (sqr05 * SinC * (ATP3e * VinP - ATP4 * UinPe) + ATP4 * CosC * VinP)
610 BT = sqr05 * DiC * (ATP1 * UinPe + ATP3e * IinP) + 0.5 * WiC * (
611 ATP2e * UinPe + ATP3e * QinPe) - sqr05 * ZiC * SinC * (ATP2e * VinP - ATP4 * QinPe)
612 AR = ARP1 * IinP + sqr05 * DiC * (ARP1 * QinPe + ARP2e * IinP) + (1. - 0.5 * WiC) * (
613 ARP2e * QinPe + ARP3e * UinPe) + ZiC * (sqr05 * SinC * (ARP3e * VinP - ARP4 * UinPe) + ARP4 * CosC * VinP)
614 BR = sqr05 * DiC * (ARP1 * UinPe + ARP3e * IinP) + 0.5 * WiC * (
615 ARP2e * UinPe + ARP3e * QinPe) - sqr05 * ZiC * SinC * (ARP2e * VinP - ARP4 * QinPe)
616 # Correction parameters for normal measurements; they are independent of LDR
617 if (not RotationErrorEpsilonForNormalMeasurements): # calibrator taken out
618 IS1 = np.array([IinPo, QinPo, UinPo, VinPo])
619 IS2 = np.array([IinPa, QinPa, UinPa, VinPa])
620 GT = np.dot(ATP, IS1)
621 GR = np.dot(ARP, IS1)
622 HT = np.dot(ATP, IS2)
623 HR = np.dot(ARP, IS2)
624 else:
625 IS1e = np.array([IinPo + DiC * QinPoe, DiC * IinPo + QinPoe, ZiC * (CosC * UinPoe + SinC * VinPo),
626 -ZiC * (SinC * UinPoe - CosC * VinPo)])
627 IS2e = np.array([IinPa + DiC * QinPae, DiC * IinPa + QinPae, ZiC * (CosC * UinPae + SinC * VinPa),
628 -ZiC * (SinC * UinPae - CosC * VinPa)])
629 GT = np.dot(ATPe, IS1e)
630 GR = np.dot(ARPe, IS1e)
631 HT = np.dot(ATPe, IS2e)
632 HR = np.dot(ARPe, IS2e)
633 else:
634 print("Calibrator not implemented yet")
635 sys.exit()
636
637 elif LocC == 3: # C before receiver optics Eq.57
638
639 # S2ge = np.sin(np.deg2rad(2*RotO - 2*RotC))
640 # C2ge = np.cos(np.deg2rad(2*RotO - 2*RotC))
641 S2e = np.sin(np.deg2rad(2. * RotC))
642 C2e = np.cos(np.deg2rad(2. * RotC))
643
644 # As with C before the receiver optics (rotated_diattenuator_X22x5deg.odt)
645 AF1 = np.array([1., C2g * DiO, S2g * DiO, 0.])
646 AF2 = np.array([C2g * DiO, 1. - S2g ** 2 * WiO, S2g * C2g * WiO, -S2g * ZiO * SinO])
647 AF3 = np.array([S2g * DiO, S2g * C2g * WiO, 1. - C2g ** 2 * WiO, C2g * ZiO * SinO])
648 AF4 = np.array([0., S2g * SinO, -C2g * SinO, CosO])
649
650 ATF = (ATP1 * AF1 + ATP2 * AF2 + ATP3 * AF3 + ATP4 * AF4)
651 ARF = (ARP1 * AF1 + ARP2 * AF2 + ARP3 * AF3 + ARP4 * AF4)
652 ATF2 = ATF[1]
653 ATF3 = ATF[2]
654 ARF2 = ARF[1]
655 ARF3 = ARF[2]
656
657 # rotated AinF by epsilon
658 ATF1 = ATF[0]
659 ATF4 = ATF[3]
660 ATF2e = C2e * ATF[1] + S2e * ATF[2]
661 ATF3e = C2e * ATF[2] - S2e * ATF[1]
662 ARF1 = ARF[0]
663 ARF4 = ARF[3]
664 ARF2e = C2e * ARF[1] + S2e * ARF[2]
665 ARF3e = C2e * ARF[2] - S2e * ARF[1]
666
667 ATFe = np.array([ATF1, ATF2e, ATF3e, ATF4])
668 ARFe = np.array([ARF1, ARF2e, ARF3e, ARF4])
669
670 QinEe = C2e * QinE + S2e * UinE
671 UinEe = C2e * UinE - S2e * QinE
672
673 # Stokes Input Vector before receiver optics Eq. E.19 (after atmosphere F)
674 IinF = IinE
675 QinF = aCal * QinE
676 UinF = -aCal * UinE
677 VinF = (1. - 2. * aCal) * VinE
678
679 IinFo = IinE
680 QinFo = 0.
681 UinFo = 0.
682 VinFo = VinE
683
684 IinFa = 0.
685 QinFa = QinE
686 UinFa = -UinE
687 VinFa = -2. * VinE
688
689 # Stokes Input Vector before receiver optics rotated by epsilon Eq. C.3
690 QinFe = C2e * QinF + S2e * UinF
691 UinFe = C2e * UinF - S2e * QinF
692 QinFoe = C2e * QinFo + S2e * UinFo
693 UinFoe = C2e * UinFo - S2e * QinFo
694 QinFae = C2e * QinFa + S2e * UinFa
695 UinFae = C2e * UinFa - S2e * QinFa
696
697 # Calibration signals and Calibration correction K from measurements with LDRCal / aCal
698 if (TypeC == 2) or (TypeC == 1): # rotator calibration Eq. C.4
699 # parameters for calibration with aCal
700 AT = ATF1 * IinF + ATF4 * h * VinF
701 BT = ATF3e * QinF - ATF2e * h * UinF
702 AR = ARF1 * IinF + ARF4 * h * VinF
703 BR = ARF3e * QinF - ARF2e * h * UinF
704 # Correction parameters for normal measurements; they are independent of LDR
705 if (not RotationErrorEpsilonForNormalMeasurements):
706 GT = ATF1 * IinE + ATF4 * VinE
707 GR = ARF1 * IinE + ARF4 * VinE
708 HT = ATF2 * QinE - ATF3 * UinE - ATF4 * 2 * VinE
709 HR = ARF2 * QinE - ARF3 * UinE - ARF4 * 2 * VinE
710 else:
711 GT = ATF1 * IinE + ATF4 * h * VinE
712 GR = ARF1 * IinE + ARF4 * h * VinE
713 HT = ATF2e * QinE - ATF3e * h * UinE - ATF4 * h * 2 * VinE
714 HR = ARF2e * QinE - ARF3e * h * UinE - ARF4 * h * 2 * VinE
715 elif (TypeC == 3) or (TypeC == 4): # linear polariser calibration Eq. C.5
716 # p = +45°, m = -45°
717 IF1e = np.array([IinF, ZiC * CosC * QinFe, UinFe, ZiC * CosC * VinF])
718 IF2e = np.array([DiC * UinFe, -ZiC * SinC * VinF, DiC * IinF, ZiC * SinC * QinFe])
719 AT = np.dot(ATFe, IF1e)
720 AR = np.dot(ARFe, IF1e)
721 BT = np.dot(ATFe, IF2e)
722 BR = np.dot(ARFe, IF2e)
723
724 # Correction parameters for normal measurements; they are independent of LDR --- the same as for TypeC = 6
725 if (not RotationErrorEpsilonForNormalMeasurements): # calibrator taken out
726 IS1 = np.array([IinE, 0., 0., VinE])
727 IS2 = np.array([0., QinE, -UinE, -2. * VinE])
728 GT = np.dot(ATF, IS1)
729 GR = np.dot(ARF, IS1)
730 HT = np.dot(ATF, IS2)
731 HR = np.dot(ARF, IS2)
732 else:
733 IS1e = np.array([IinFo + DiC * QinFoe, DiC * IinFo + QinFoe, ZiC * (CosC * UinFoe + SinC * VinFo),
734 -ZiC * (SinC * UinFoe - CosC * VinFo)])
735 IS2e = np.array([IinFa + DiC * QinFae, DiC * IinFa + QinFae, ZiC * (CosC * UinFae + SinC * VinFa),
736 -ZiC * (SinC * UinFae - CosC * VinFa)])
737 GT = np.dot(ATFe, IS1e)
738 GR = np.dot(ARFe, IS1e)
739 HT = np.dot(ATFe, IS2e)
740 HR = np.dot(ARFe, IS2e)
741
742 elif (TypeC == 6): # diattenuator calibration +-22.5° rotated_diattenuator_X22x5deg.odt
743 # parameters for calibration with aCal
744 IF1e = np.array([IinF + sqr05 * DiC * QinFe, sqr05 * DiC * IinF + (1. - 0.5 * WiC) * QinFe,
745 (1. - 0.5 * WiC) * UinFe + sqr05 * ZiC * SinC * VinF,
746 -sqr05 * ZiC * SinC * UinFe + ZiC * CosC * VinF])
747 IF2e = np.array([sqr05 * DiC * UinFe, 0.5 * WiC * UinFe - sqr05 * ZiC * SinC * VinF,
748 sqr05 * DiC * IinF + 0.5 * WiC * QinFe, sqr05 * ZiC * SinC * QinFe])
749 AT = np.dot(ATFe, IF1e)
750 AR = np.dot(ARFe, IF1e)
751 BT = np.dot(ATFe, IF2e)
752 BR = np.dot(ARFe, IF2e)
753
754 # Correction parameters for normal measurements; they are independent of LDR
755 if (not RotationErrorEpsilonForNormalMeasurements): # calibrator taken out
756 # IS1 = np.array([IinE,0,0,VinE])
757 # IS2 = np.array([0,QinE,-UinE,-2*VinE])
758 IS1 = np.array([IinFo, 0., 0., VinFo])
759 IS2 = np.array([0., QinFa, UinFa, VinFa])
760 GT = np.dot(ATF, IS1)
761 GR = np.dot(ARF, IS1)
762 HT = np.dot(ATF, IS2)
763 HR = np.dot(ARF, IS2)
764 else:
765 IS1e = np.array([IinFo + DiC * QinFoe, DiC * IinFo + QinFoe, ZiC * (CosC * UinFoe + SinC * VinFo),
766 -ZiC * (SinC * UinFoe - CosC * VinFo)])
767 IS2e = np.array([IinFa + DiC * QinFae, DiC * IinFa + QinFae, ZiC * (CosC * UinFae + SinC * VinFa),
768 -ZiC * (SinC * UinFae - CosC * VinFa)])
769 # IS1e = np.array([IinFo,0,0,VinFo])
770 # IS2e = np.array([0,QinFae,UinFae,VinFa])
771 GT = np.dot(ATFe, IS1e)
772 GR = np.dot(ARFe, IS1e)
773 HT = np.dot(ATFe, IS2e)
774 HR = np.dot(ARFe, IS2e)
775
776 else:
777 print('Calibrator not implemented yet')
778 sys.exit()
779
780 elif LocC == 2: # C behind emitter optics Eq.57 -------------------------------------------------------
781 # print("Calibrator location not implemented yet")
782 S2e = np.sin(np.deg2rad(2. * RotC))
783 C2e = np.cos(np.deg2rad(2. * RotC))
784
785 # AS with C before the receiver optics (see document rotated_diattenuator_X22x5deg.odt)
786 AF1 = np.array([1, C2g * DiO, S2g * DiO, 0.])
787 AF2 = np.array([C2g * DiO, 1. - S2g ** 2 * WiO, S2g * C2g * WiO, -S2g * ZiO * SinO])
788 AF3 = np.array([S2g * DiO, S2g * C2g * WiO, 1. - C2g ** 2 * WiO, C2g * ZiO * SinO])
789 AF4 = np.array([0., S2g * SinO, -C2g * SinO, CosO])
790
791 ATF = (ATP1 * AF1 + ATP2 * AF2 + ATP3 * AF3 + ATP4 * AF4)
792 ARF = (ARP1 * AF1 + ARP2 * AF2 + ARP3 * AF3 + ARP4 * AF4)
793 ATF1 = ATF[0]
794 ATF2 = ATF[1]
795 ATF3 = ATF[2]
796 ATF4 = ATF[3]
797 ARF1 = ARF[0]
798 ARF2 = ARF[1]
799 ARF3 = ARF[2]
800 ARF4 = ARF[3]
801
802 # AS with C behind the emitter
803 # terms without aCal
804 ATE1o, ARE1o = ATF1, ARF1
805 ATE2o, ARE2o = 0., 0.
806 ATE3o, ARE3o = 0., 0.
807 ATE4o, ARE4o = ATF4, ARF4
808 # terms with aCal
809 ATE1a, ARE1a = 0., 0.
810 ATE2a, ARE2a = ATF2, ARF2
811 ATE3a, ARE3a = -ATF3, -ARF3
812 ATE4a, ARE4a = -2. * ATF4, -2. * ARF4
813 # rotated AinEa by epsilon
814 ATE2ae = C2e * ATF2 + S2e * ATF3
815 ATE3ae = -S2e * ATF2 - C2e * ATF3
816 ARE2ae = C2e * ARF2 + S2e * ARF3
817 ARE3ae = -S2e * ARF2 - C2e * ARF3
818
819 ATE1 = ATE1o
820 ATE2e = aCal * ATE2ae
821 ATE3e = aCal * ATE3ae
822 ATE4 = (1 - 2 * aCal) * ATF4
823 ARE1 = ARE1o
824 ARE2e = aCal * ARE2ae
825 ARE3e = aCal * ARE3ae
826 ARE4 = (1 - 2 * aCal) * ARF4
827
828 # rotated IinE
829 QinEe = C2e * QinE + S2e * UinE
830 UinEe = C2e * UinE - S2e * QinE
831
832 # Calibration signals and Calibration correction K from measurements with LDRCal / aCal
833 if (TypeC == 2) or (TypeC == 1): # +++++++++ rotator calibration Eq. C.4
834 AT = ATE1o * IinE + (ATE4o + aCal * ATE4a) * h * VinE
835 BT = aCal * (ATE3ae * QinEe - ATE2ae * h * UinEe)
836 AR = ARE1o * IinE + (ARE4o + aCal * ARE4a) * h * VinE
837 BR = aCal * (ARE3ae * QinEe - ARE2ae * h * UinEe)
838
839 # Correction parameters for normal measurements; they are independent of LDR
840 if (not RotationErrorEpsilonForNormalMeasurements):
841 # Stokes Input Vector before receiver optics Eq. E.19 (after atmosphere F)
842 GT = ATE1o * IinE + ATE4o * h * VinE
843 GR = ARE1o * IinE + ARE4o * h * VinE
844 HT = ATE2a * QinE + ATE3a * h * UinEe + ATE4a * h * VinE
845 HR = ARE2a * QinE + ARE3a * h * UinEe + ARE4a * h * VinE
846 else:
847 GT = ATE1o * IinE + ATE4o * h * VinE
848 GR = ARE1o * IinE + ARE4o * h * VinE
849 HT = ATE2ae * QinE + ATE3ae * h * UinEe + ATE4a * h * VinE
850 HR = ARE2ae * QinE + ARE3ae * h * UinEe + ARE4a * h * VinE
851
852 elif (TypeC == 3) or (TypeC == 4): # +++++++++ linear polariser calibration Eq. C.5
853 # p = +45°, m = -45°
854 AT = ATE1 * IinE + ZiC * CosC * (ATE2e * QinEe + ATE4 * VinE) + ATE3e * UinEe
855 BT = DiC * (ATE1 * UinEe + ATE3e * IinE) + ZiC * SinC * (ATE4 * QinEe - ATE2e * VinE)
856 AR = ARE1 * IinE + ZiC * CosC * (ARE2e * QinEe + ARE4 * VinE) + ARE3e * UinEe
857 BR = DiC * (ARE1 * UinEe + ARE3e * IinE) + ZiC * SinC * (ARE4 * QinEe - ARE2e * VinE)
858
859 # Correction parameters for normal measurements; they are independent of LDR
860 if (not RotationErrorEpsilonForNormalMeasurements):
861 # Stokes Input Vector before receiver optics Eq. E.19 (after atmosphere F)
862 GT = ATE1o * IinE + ATE4o * VinE
863 GR = ARE1o * IinE + ARE4o * VinE
864 HT = ATE2a * QinE + ATE3a * UinE + ATE4a * VinE
865 HR = ARE2a * QinE + ARE3a * UinE + ARE4a * VinE
866 else:
867 D = IinE + DiC * QinEe
868 A = DiC * IinE + QinEe
869 B = ZiC * (CosC * UinEe + SinC * VinE)
870 C = -ZiC * (SinC * UinEe - CosC * VinE)
871 GT = ATE1o * D + ATE4o * C
872 GR = ARE1o * D + ARE4o * C
873 HT = ATE2a * A + ATE3a * B + ATE4a * C
874 HR = ARE2a * A + ARE3a * B + ARE4a * C
875
876 elif (TypeC == 6): # real HWP calibration +-22.5° rotated_diattenuator_X22x5deg.odt
877 # p = +22.5°, m = -22.5°
878 IE1e = np.array([IinE + sqr05 * DiC * QinEe, sqr05 * DiC * IinE + (1 - 0.5 * WiC) * QinEe,
879 (1 - 0.5 * WiC) * UinEe + sqr05 * ZiC * SinC * VinE,
880 -sqr05 * ZiC * SinC * UinEe + ZiC * CosC * VinE])
881 IE2e = np.array([sqr05 * DiC * UinEe, 0.5 * WiC * UinEe - sqr05 * ZiC * SinC * VinE,
882 sqr05 * DiC * IinE + 0.5 * WiC * QinEe, sqr05 * ZiC * SinC * QinEe])
883 ATEe = np.array([ATE1, ATE2e, ATE3e, ATE4])
884 AREe = np.array([ARE1, ARE2e, ARE3e, ARE4])
885 AT = np.dot(ATEe, IE1e)
886 AR = np.dot(AREe, IE1e)
887 BT = np.dot(ATEe, IE2e)
888 BR = np.dot(AREe, IE2e)
889
890 # Correction parameters for normal measurements; they are independent of LDR
891 if (not RotationErrorEpsilonForNormalMeasurements): # calibrator taken out
892 GT = ATE1o * IinE + ATE4o * VinE
893 GR = ARE1o * IinE + ARE4o * VinE
894 HT = ATE2a * QinE + ATE3a * UinE + ATE4a * VinE
895 HR = ARE2a * QinE + ARE3a * UinE + ARE4a * VinE
896 else:
897 D = IinE + DiC * QinEe
898 A = DiC * IinE + QinEe
899 B = ZiC * (CosC * UinEe + SinC * VinE)
900 C = -ZiC * (SinC * UinEe - CosC * VinE)
901 GT = ATE1o * D + ATE4o * C
902 GR = ARE1o * D + ARE4o * C
903 HT = ATE2a * A + ATE3a * B + ATE4a * C
904 HR = ARE2a * A + ARE3a * B + ARE4a * C
905
906 else:
907 print('Calibrator not implemented yet')
908 sys.exit()
909
910 else:
911 print("Calibrator location not implemented yet")
912 sys.exit()
913
914 # Determination of the correction K of the calibration factor.
915 IoutTp = TTa * TiC * TiO * TiE * (AT + BT)
916 IoutTm = TTa * TiC * TiO * TiE * (AT - BT)
917 IoutRp = TRa * TiC * TiO * TiE * (AR + BR)
918 IoutRm = TRa * TiC * TiO * TiE * (AR - BR)
919 # --- Results and Corrections; electronic etaR and etaT are assumed to be 1
920 Etapx = IoutRp / IoutTp
921 Etamx = IoutRm / IoutTm
922 Etax = (Etapx * Etamx) ** 0.5
923
924 Eta = (TRa / TTa) # = TRa / TTa; Eta = Eta*/K Eq. 84 => K = Eta* / Eta; equation corrected according to the papers supplement Eqs. (S.10.10.1) ff
925 K = Etax / Eta
926
927 # For comparison with Volkers Libreoffice Müller Matrix spreadsheet
928 # Eta_test_p = (IoutRp/IoutTp)
929 # Eta_test_m = (IoutRm/IoutTm)
930 # Eta_test = (Eta_test_p*Eta_test_m)**0.5
931
932 # ----- random error calculation ----------
933 # noise must be calculated with the photon counts of measured signals;
934 # relative standard deviation of calibration signals with LDRcal; assumed to be statisitcally independent
935 # normalised noise errors
936 if (CalcFrom0deg):
937 dIoutTp = (NCalT * IoutTp) ** -0.5
938 dIoutTm = (NCalT * IoutTm) ** -0.5
939 dIoutRp = (NCalR * IoutRp) ** -0.5
940 dIoutRm = (NCalR * IoutRm) ** -0.5
941 else:
942 dIoutTp = (NCalT ** -0.5)
943 dIoutTm = (NCalT ** -0.5)
944 dIoutRp = (NCalR ** -0.5)
945 dIoutRm = (NCalR ** -0.5)
946 # Forward simulated 0°-signals with LDRCal with atrue; from input file
947
948 It = TTa * TiO * TiE * (GT + atrue * HT)
949 Ir = TRa * TiO * TiE * (GR + atrue * HR)
950 # relative standard deviation of standard signals with LDRmeas; assumed to be statisitcally independent
951 if (CalcFrom0deg): # this works!
952 dIt = ((It * NI * eFacT) ** -0.5)
953 dIr = ((Ir * NI * eFacR) ** -0.5)
954 '''
955 dIt = ((NCalT * It / IoutTp * NILfac / TCalT) ** -0.5)
956 dIr = ((NCalR * Ir / IoutRp * NILfac / TCalR) ** -0.5)
957 '''
958 else: # does this work? Why not as above?
959 dIt = ((NCalT * 2 * NILfac / TCalT ) ** -0.5)
960 dIr = ((NCalR * 2 * NILfac / TCalR) ** -0.5)
961
962 # ----- Forward simulated LDRsim = 1/Eta*Ir/It # simulated LDR* with Y from input file
963 LDRsim = Ir / It # simulated uncorrected LDR with Y from input file
964 # Corrected LDRsimCorr from forward simulated LDRsim (atrue)
965 # LDRsimCorr = (1./Eta*LDRsim*(GT+HT)-(GR+HR))/((GR-HR)-1./Eta*LDRsim*(GT-HT))
966 '''
967 if ((Y == -1.) and (abs(RotL0) < 45)) or ((Y == +1.) and (abs(RotL0) > 45)):
968 LDRsimx = 1. / LDRsim / Etax
969 else:
970 LDRsimx = LDRsim / Etax
971 '''
972 LDRsimx = LDRsim
973
974 # The following is correct without doubt
975 # LDRCorr = (LDRsim/(Etax/K)*(GT+HT)-(GR+HR))/((GR-HR)-LDRsim/(Etax/K)*(GT-HT))
976
977 # The following is a test whether the equations for calibration Etax and normal signal (GHK, LDRsim) are consistent
978 LDRCorr = (LDRsim / (Etax / K) * (GT + HT) - (GR + HR)) / ((GR - HR) - LDRsim / (Etax / K) * (GT - HT))
979 # here we could also use Eta instead of Etax / K => how to test whether Etax is correct? => comparison with MüllerMatrix simulation!
980 # Without any correction: only measured It, Ir, EtaX are used
981 LDRunCorr = LDRsim / Etax
982 # LDRunCorr = (LDRsim / Etax * (GT / abs(GT) + HT / abs(HT)) - (GR / abs(GR) + HR / abs(HR))) / ((GR / abs(GR) - HR / abs(HR)) - LDRsim / Etax * (GT / abs(GT) - HT / abs(HT)))
983
984 #LDRCorr = LDRsimx # for test only
985
986 F11sim = 1 / (TiO * TiE) * ((HR * Eta * It - HT * Ir) / (HR * GT - HT * GR)) # IL = 1, Etat = Etar = 1 ; AMT Eq.64; what is Etax/K? => see about 20 lines above: = Eta
987
988 return (IoutTp, IoutTm, IoutRp, IoutRm, It, Ir, dIoutTp, dIoutTm, dIoutRp, dIoutRm, dIt, dIr,
989 GT, HT, GR, HR, K, Eta, LDRsimx, LDRCorr, DTa, DRa, TTa, TRa, F11sim, LDRunCorr)
990
991
992
993 # *******************************************************************************************************************************
994
995 # --- CALC with assumed true parameters from the input file
996 LDRtrue = LDRtrue2
997 IoutTp0, IoutTm0, IoutRp0, IoutRm0, It0, Ir0, dIoutTp0, dIoutTm0, dIoutRp0, dIoutRm0, dIt0, dIr0, \
998 GT0, HT0, GR0, HR0, K0, Eta0, LDRsimx, LDRCorr, DTa0, DRa0, TTa0, TRa0, F11sim0, LDRunCorr = \
999 Calc(TCalT, TCalR, NCalT, NCalR, Qin0, Vin0, RotL0, RotE0, RetE0, DiE0,
1000 RotO0, RetO0, DiO0, RotC0, RetC0, DiC0, TP0, TS0, RP0, RS0,
1001 ERaT0, RotaT0, RetT0, ERaR0, RotaR0, RetR0, LDRCal0)
1002 Etax0 = K0 * Eta0
1003 Etapx0 = IoutRp0 / IoutTp0
1004 Etamx0 = IoutRm0 / IoutTm0
1005 # --- Print parameters to console and output file
1006 OutputFile = 'output_' + InputFile[0:-3] + '_' + fname[0:-3] +'.dat'
1007 with open('output_files\\' + OutputFile, 'w') as f:
1008 with redirect_stdout(f):
1009 print("From ", dname)
1010 print("Running ", fname)
1011 print("Reading input file ", InputFile) # , " for Lidar system :", EID, ", ", LID)
1012 print("for Lidar system: ", EID, ", ", LID)
1013 # --- Print iput information*********************************
1014 print(" --- Input parameters: value ±error / ±steps ----------------------")
1015 print("{0:7}{1:17} {2:6.4f}±{3:7.4f}/{4:2d}".format("Laser: ", "Qin =", Qin0, dQin, nQin))
1016 print("{0:7}{1:17} {2:6.4f}±{3:7.4f}/{4:2d}".format("", "Vin =", Vin0, dVin, nVin))
1017 print("{0:7}{1:17} {2:6.4f}±{3:7.4f}/{4:2d}".format("", "Rotation alpha = ", RotL0, dRotL, nRotL))
1018 print("{0:7}{1:15} {2:8.4f} {3:17}".format("", "=> DOP", ((Qin ** 2 + Vin ** 2) ** 0.5), " (degree of polarisation)"))
1019
1020 print("Optic: Diatt., Tunpol, Retard., Rotation (deg)")
1021 print("{0:12} {1:7.4f} ±{2:7.4f} /{8:2d}, {3:7.4f}, {4:3.0f}±{5:3.0f}/{9:2d}, {6:7.4f}±{7:7.4f}/{10:2d}".format(
1022 "Emitter ", DiE0, dDiE, TiE, RetE0, dRetE, RotE0, dRotE, nDiE, nRetE, nRotE))
1023 print("{0:12} {1:7.4f} ±{2:7.4f} /{8:2d}, {3:7.4f}, {4:3.0f}±{5:3.0f}/{9:2d}, {6:7.4f}±{7:7.4f}/{10:2d}".format(
1024 "Receiver ", DiO0, dDiO, TiO, RetO0, dRetO, RotO0, dRotO, nDiO, nRetO, nRotO))
1025 print("{0:12} {1:9.6f}±{2:9.6f}/{8:2d}, {3:7.4f}, {4:3.0f}±{5:3.0f}/{9:2d}, {6:7.4f}±{7:7.4f}/{10:2d}".format(
1026 "Calibrator ", DiC0, dDiC, TiC, RetC0, dRetC, RotC0, dRotC, nDiC, nRetC, nRotC))
1027 print("{0:12}".format(" Pol.-filter ------ "))
1028 print("{0:12}{1:7.4f}±{2:7.4f}/{3:2d}, {4:7.4f}±{5:7.4f}/{6:2d}".format(
1029 "ERT, RotT :", ERaT0, dERaT, nERaT, RotaT0, dRotaT, nRotaT))
1030 print("{0:12}{1:7.4f}±{2:7.4f}/{3:2d}, {4:7.4f}±{5:7.4f}/{6:2d}".format(
1031 "ERR, RotR :", ERaR0, dERaR, nERaR, RotaR0, dRotaR, nRotaR))
1032 print("{0:12}".format(" PBS ------ "))
1033 print("{0:12}{1:7.4f}±{2:7.4f}/{3:2d}, {4:7.4f}±{5:7.4f}/{6:2d}".format(
1034 "TP,TS :", TP0, dTP, nTP, TS0, dTS, nTS))
1035 print("{0:12}{1:7.4f}±{2:7.4f}/{3:2d}, {4:7.4f}±{5:7.4f}/{6:2d}".format(
1036 "RP,RS :", RP0, dRP, nRP, RS0, dRS, nRS))
1037 print("{0:12}{1:7.4f},{2:7.4f}, {3:7.4f},{4:7.4f}, {5:1.0f}".format(
1038 "DT,TT,DR,TR,Y :", DiT, TiT, DiR, TiR, Y))
1039 print("{0:12}".format(" Combined PBS + Pol.-filter ------ "))
1040 print("{0:12}{1:7.4f},{2:7.4f}, {3:7.4f},{4:7.4f}".format(
1041 "DT,TT,DR,TR :", DTa0, TTa0, DRa0, TRa0))
1042 print("{0:26}: {1:6.3f}± {2:5.3f}/{3:2d}".format(
1043 "LDRCal during calibration in calibration range", LDRCal0, dLDRCal, nLDRCal))
1044 print("{0:12}".format(" --- Additional ND filter attenuation (transmission) during the calibration ---"))
1045 print("{0:12}{1:7.4f}±{2:7.4f}/{3:2d}, {4:7.4f}±{5:7.4f}/{6:2d}".format(
1046 "TCalT,TCalR :", TCalT0, dTCalT, nTCalT, TCalR0, dTCalR, nTCalR))
1047 print()
1048 print(Type[TypeC],"calibrator is located", Loc[LocC])
1049 print("Rotation error epsilon is considered also for normal measurements = ", RotationErrorEpsilonForNormalMeasurements)
1050 print("The PBS incidence plane is ", dY[int(Y + 1)], "to the reference plane" )
1051 print("The laser polarisation in the reference plane is finally", dY2[int(Y + 1)], "=>", dY3)
1052 print("RS_RP_depend_on_TS_TP = ", RS_RP_depend_on_TS_TP)
1053 # end of print actual system parameters
1054 # ******************************************************************************
1055
1056
1057 print()
1058
1059 K0List = np.zeros(7)
1060 LDRsimxList = np.zeros(7)
1061 LDRCalList = 0.0, 0.004, 0.02, 0.1, 0.2, 0.3, 0.45
1062 # The loop over LDRCalList is ony for checking whether and how much the LDR depends on the LDRCal during calibration and whether the corrections work.
1063 # Still with assumed true parameters in input file
1064
1065 '''
1066 facIt = NCalT / TCalT0 * NILfac
1067 facIr = NCalR / TCalR0 * NILfac
1068 '''
1069 facIt = NI * eFacT
1070 facIr = NI * eFacR
1071 if (bPlotEtax):
1072 # check error signals
1073 # dIs are relative stdevs
1074 print("LDRCal, IoutTp, IoutTm, IoutRp, IoutRm, It, Ir, dIoutTp,dIoutTm,dIoutRp,dIoutRm,dIt, dIr")
1075
1076 for i, LDRCal in enumerate(LDRCalList):
1077 IoutTp, IoutTm, IoutRp, IoutRm, It, Ir, dIoutTp, dIoutTm, dIoutRp, dIoutRm, dIt, dIr, \
1078 GT0, HT0, GR0, HR0, K0, Eta0, LDRsimx, LDRCorr, DTa0, DRa0, TTa0, TRa0, F11sim0, LDRunCorr = \
1079 Calc(TCalT0, TCalR0, NCalT, NCalR, Qin0, Vin0, RotL0, RotE0, RetE0, DiE0,
1080 RotO0, RetO0, DiO0, RotC0, RetC0, DiC0, TP0, TS0, RP0, RS0,
1081 ERaT0, RotaT0, RetT0, ERaR0, RotaR0, RetR0, LDRCal)
1082 K0List[i] = K0
1083 LDRsimxList[i] = LDRsimx
1084
1085 if (bPlotEtax):
1086 # check error signals
1087 print( "{:0.2f}, {:0.4f}, {:0.4f}, {:0.4f}, {:0.4f}, {:0.4f}, {:0.4f}, {:0.4f}, {:0.4f}, {:0.4f}, {:0.4f}, {:0.4f}, {:0.4f}".format(LDRCal, IoutTp * NCalT, IoutTm * NCalT, IoutRp * NCalR, IoutRm * NCalR, It * facIt, Ir * facIr, dIoutTp, dIoutTm, dIoutRp, dIoutRm, dIt, dIr))
1088 #print( "{:0.4f}, {:0.4f}, {:0.4f}, {:0.4f}, {:0.4f}, {:0.4f}, {:0.4f}, {:0.4f}, {:0.4f}, {:0.4f}, {:0.4f}, {:0.4f}".format(IoutTp, IoutTm, IoutRp, IoutRm, It, Ir, dIoutTp, dIoutTm, dIoutRp, dIoutRm, dIt, dIr))
1089 # end check error signals
1090 print('===========================================================================================================')
1091 print("{0:8},{1:8},{2:8},{3:8},{4:9},{5:8},{6:9},{7:9},{8:9},{9:9},{10:9}".format(
1092 " GR", " GT", " HR", " HT", " K(0.000)", " K(0.004)", " K(0.02)", " K(0.1)", " K(0.2)", " K(0.3)", " K(0.45)"))
1093 print("{0:8.5f},{1:8.5f},{2:8.5f},{3:8.5f},{4:9.5f},{5:9.5f},{6:9.5f},{7:9.5f},{8:9.5f},{9:9.5f},{10:9.5f}".format(
1094 GR0, GT0, HR0, HT0, K0List[0], K0List[1], K0List[2], K0List[3], K0List[4], K0List[5], K0List[6]))
1095 print('===========================================================================================================')
1096 print()
1097 print("Errors from neglecting GHK corrections and/or calibration:")
1098 print("{0:>10},{1:>10},{2:>10},{3:>10},{4:>10},{5:>10}".format(
1099 "LDRtrue", "LDRunCorr", "1/LDRunCorr", "LDRsimx", "1/LDRsimx", "LDRCorr"))
1100
1101 aF11sim0 = np.zeros(5)
1102 LDRrange = np.zeros(5)
1103 LDRsim0 = np.zeros(5)
1104 LDRrange = [0.004, 0.02, 0.1, 0.3, 0.45] # list
1105 LDRrange[0] = LDRtrue2 # value in the input file; default 0.004
1106
1107 # The loop over LDRtrueList is only for checking how much the uncorrected LDRsimx deviates from LDRtrue ... and whether the corrections work.
1108 # LDRsimx = LDRsim = Ir / It or 1/LDRsim
1109 # Still with assumed true parameters in input file
1110 for i, LDRtrue in enumerate(LDRrange):
1111 #for LDRtrue in LDRrange:
1112 IoutTp, IoutTm, IoutRp, IoutRm, It, Ir, dIoutTp, dIoutTm, dIoutRp, dIoutRm, dIt, dIr, \
1113 GT0, HT0, GR0, HR0, K0, Eta0, LDRsimx, LDRCorr, DTa0, DRa0, TTa0, TRa0, F11sim0, LDRunCorr = \
1114 Calc(TCalT0, TCalR0, NCalT, NCalR, Qin0, Vin0, RotL0, RotE0, RetE0, DiE0,
1115 RotO0, RetO0, DiO0, RotC0, RetC0, DiC0, TP0, TS0, RP0, RS0,
1116 ERaT0, RotaT0, RetT0, ERaR0, RotaR0, RetR0, LDRCal0)
1117 print("{0:10.5f},{1:10.5f},{2:10.5f},{3:10.5f},{4:10.5f},{5:10.5f}".format(LDRtrue, LDRunCorr, 1/LDRunCorr, LDRsimx, 1/LDRsimx, LDRCorr))
1118 aF11sim0[i] = F11sim0
1119 LDRsim0[i] = Ir / It
1120 # the assumed true aF11sim0 results will be used below to calc the deviation from the real signals
1121 print("LDRsimx = LDR of the nominal system directly from measured signals without calibration and GHK-corrections")
1122 print("LDRunCorr = LDR of the nominal system directly from measured signals with calibration but without GHK-corrections; electronic amplifications = 1 assumed")
1123 print("LDRCorr = LDR calibrated and GHK-corrected")
1124 print()
1125 print("Errors from signal noise:")
1126 print("Signal counts: NI, NCalT, NCalR, NILfac, nNCal, nNI, stdev(NI)/NI = {0:10.0f},{1:10.0f},{2:10.0f},{3:3.0f},{4:2.0f},{5:2.0f},{6:8.5f}".format(
1127 NI, NCalT, NCalR, NILfac, nNCal, nNI, 1.0 / NI ** 0.5))
1128 print()
1129 print()
1130 '''# das muß wieder weg
1131 print("IoutTp, IoutTm, IoutRp, IoutRm, It , Ir , dIoutTp, dIoutTm, dIoutRp, dIoutRm, dIt, dIr")
1132 LDRCal = 0.01
1133 for i, LDRtrue in enumerate(LDRrange):
1134 IoutTp, IoutTm, IoutRp, IoutRm, It, Ir, dIoutTp, dIoutTm, dIoutRp, dIoutRm, dIt, dIr, \
1135 GT0, HT0, GR0, HR0, K0, Eta0, LDRsimx, LDRCorr, DTa0, DRa0, TTa0, TRa0, F11sim0, LDRunCorr = \
1136 Calc(TCalT0, TCalR0, NCalT, NCalR, DOLP0, RotL0, RotE0, RetE0, DiE0,
1137 RotO0, RetO0, DiO0, RotC0, RetC0, DiC0, TP0, TS0, RP0, RS0,
1138 ERaT0, RotaT0, RetT0, ERaR0, RotaR0, RetR0, LDRCal0)
1139 print( "{:0.4f}, {:0.4f}, {:0.4f}, {:0.4f}, {:0.4f}, {:0.4f}, {:0.4f}, {:0.4f}, {:0.4f}, {:0.4f}, {:0.4f}, {:0.4f}".format(
1140 IoutTp * NCalT, IoutTm * NCalT, IoutRp * NCalR, IoutRm * NCalR, It * facIt, Ir * facIr,
1141 dIoutTp, dIoutTm, dIoutRp, dIoutRm, dIt, dIr))
1142 aF11sim0[i] = F11sim0
1143 # the assumed true aF11sim0 results will be used below to calc the deviation from the real signals
1144 # bis hierher weg
1145 '''
1146
1147 file = open('output_files\\' + OutputFile, 'r')
1148 print(file.read())
1149 file.close()
1150
1151 # --- CALC again assumed truth with LDRCal0 and with assumed true parameters in input file to reset all 0-values
1152 LDRtrue = LDRtrue2
1153 IoutTp0, IoutTm0, IoutRp0, IoutRm0, It0, Ir0, dIoutTp0, dIoutTm0, dIoutRp0, dIoutRm0, dIt0, dIr0, \
1154 GT0, HT0, GR0, HR0, K0, Eta0, LDRsimx, LDRCorr, DTa0, DRa0, TTa0, TRa0, F11sim0, LDRunCorr = \
1155 Calc(TCalT0, TCalR0, NCalT, NCalR, Qin0, Vin0, RotL0, RotE0, RetE0, DiE0,
1156 RotO0, RetO0, DiO0, RotC0, RetC0, DiC0, TP0, TS0, RP0, RS0,
1157 ERaT0, RotaT0, RetT0, ERaR0, RotaR0, RetR0, LDRCal0)
1158 Etax0 = K0 * Eta0
1159 Etapx0 = IoutRp0 / IoutTp0
1160 Etamx0 = IoutRm0 / IoutTm0
1161 '''
1162 if(PrintToOutputFile):
1163 f = open('output_ver7.dat', 'w')
1164 old_target = sys.stdout
1165 sys.stdout = f
1166
1167 print("something")
1168
1169 if(PrintToOutputFile):
1170 sys.stdout.flush()
1171 f.close
1172 sys.stdout = old_target
1173 '''
1174 if (Error_Calc):
1175 # --- CALC again assumed truth with LDRCal0 and with assumed true parameters in input file to reset all 0-values
1176 LDRtrue = LDRtrue2
1177 IoutTp0, IoutTm0, IoutRp0, IoutRm0, It0, Ir0, dIoutTp0, dIoutTm0, dIoutRp0, dIoutRm0, dIt0, dIr0, \
1178 GT0, HT0, GR0, HR0, K0, Eta0, LDRsimx, LDRCorr, DTa0, DRa0, TTa0, TRa0, F11sim0, LDRunCorr = \
1179 Calc(TCalT0, TCalR0, NCalT, NCalR, Qin0, Vin0, RotL0, RotE0, RetE0, DiE0,
1180 RotO0, RetO0, DiO0, RotC0, RetC0, DiC0, TP0, TS0, RP0, RS0,
1181 ERaT0, RotaT0, RetT0, ERaR0, RotaR0, RetR0, LDRCal0)
1182 Etax0 = K0 * Eta0
1183 Etapx0 = IoutRp0 / IoutTp0
1184 Etamx0 = IoutRm0 / IoutTm0
1185
1186 # --- Start Error calculation with variable parameters ------------------------------------------------------------------
1187 # error nNCal: one-sigma in steps to left and right for calibration signals
1188 # error nNI: one-sigma in steps to left and right for 0° signals
1189
1190 iN = -1
1191 N = ((nTCalT * 2 + 1) * (nTCalR * 2 + 1) *
1192 (nNCal * 2 + 1) ** 4 * (nNI * 2 + 1) ** 2 *
1193 (nQin * 2 + 1) * (nVin * 2 + 1) * (nRotL * 2 + 1) *
1194 (nRotE * 2 + 1) * (nRetE * 2 + 1) * (nDiE * 2 + 1) *
1195 (nRotO * 2 + 1) * (nRetO * 2 + 1) * (nDiO * 2 + 1) *
1196 (nRotC * 2 + 1) * (nRetC * 2 + 1) * (nDiC * 2 + 1) *
1197 (nTP * 2 + 1) * (nTS * 2 + 1) * (nRP * 2 + 1) * (nRS * 2 + 1) * (nERaT * 2 + 1) * (nERaR * 2 + 1) *
1198 (nRotaT * 2 + 1) * (nRotaR * 2 + 1) * (nRetT * 2 + 1) * (nRetR * 2 + 1) * (nLDRCal * 2 + 1))
1199 print("number of system variations N = ", N, " ", end="")
1200
1201 if N > 1e6:
1202 if user_yes_no_query('Warning: processing ' + str(
1203 N) + ' samples will take very long. Do you want to proceed?') == 0: sys.exit()
1204 if N > 5e6:
1205 if user_yes_no_query('Warning: the memory required for ' + str(N) + ' samples might be ' + '{0:5.1f}'.format(
1206 N / 4e6) + ' GB. Do you anyway want to proceed?') == 0: sys.exit()
1207
1208 # if user_yes_no_query('Warning: processing' + str(N) + ' samples will take very long. Do you want to proceed?') == 0: sys.exit()
1209
1210 # --- Arrays for plotting ------
1211 LDRmin = np.zeros(5)
1212 LDRmax = np.zeros(5)
1213 LDRstd = np.zeros(5)
1214 LDRmean = np.zeros(5)
1215 LDRmedian = np.zeros(5)
1216 LDRskew = np.zeros(5)
1217 LDRkurt = np.zeros(5)
1218 LDRsimmin = np.zeros(5)
1219 LDRsimmax = np.zeros(5)
1220 LDRsimmean = np.zeros(5)
1221
1222 F11min = np.zeros(5)
1223 F11max = np.zeros(5)
1224 Etaxmin = np.zeros(5)
1225 Etaxmax = np.zeros(5)
1226
1227 aQin = np.zeros(N)
1228 aVin = np.zeros(N)
1229 aERaT = np.zeros(N)
1230 aERaR = np.zeros(N)
1231 aRotaT = np.zeros(N)
1232 aRotaR = np.zeros(N)
1233 aRetT = np.zeros(N)
1234 aRetR = np.zeros(N)
1235 aTP = np.zeros(N)
1236 aTS = np.zeros(N)
1237 aRP = np.zeros(N)
1238 aRS = np.zeros(N)
1239 aDiE = np.zeros(N)
1240 aDiO = np.zeros(N)
1241 aDiC = np.zeros(N)
1242 aRotC = np.zeros(N)
1243 aRetC = np.zeros(N)
1244 aRotL = np.zeros(N)
1245 aRetE = np.zeros(N)
1246 aRotE = np.zeros(N)
1247 aRetO = np.zeros(N)
1248 aRotO = np.zeros(N)
1249 aLDRCal = np.zeros(N)
1250 aNCalTp = np.zeros(N)
1251 aNCalTm = np.zeros(N)
1252 aNCalRp = np.zeros(N)
1253 aNCalRm = np.zeros(N)
1254 aNIt = np.zeros(N)
1255 aNIr = np.zeros(N)
1256 aTCalT = np.zeros(N)
1257 aTCalR = np.zeros(N)
1258
1259 # each np.zeros((LDRrange, N)) array has the same N-dependency
1260 aLDRcorr = np.zeros((5, N))
1261 aLDRsim = np.zeros((5, N))
1262 aF11corr = np.zeros((5, N))
1263 aPLDR = np.zeros((5, N))
1264 aEtax = np.zeros((5, N))
1265 aEtapx = np.zeros((5, N))
1266 aEtamx = np.zeros((5, N))
1267
1268 # np.zeros((GHKs, N))
1269 aGHK = np.zeros((5, N))
1270
1271 atime = clock()
1272 dtime = clock()
1273
1274 # --- Calc Error signals
1275 # ---- Do the calculations of bra-ket vectors
1276 h = -1. if TypeC == 2 else 1
1277
1278 for iLDRCal in range(-nLDRCal, nLDRCal + 1):
1279 # from input file: LDRCal for calibration measurements
1280 LDRCal = LDRCal0
1281 if nLDRCal > 0:
1282 LDRCal = LDRCal0 + iLDRCal * dLDRCal / nLDRCal
1283 # provides the intensities of the calibration measurements at various LDRCal for signal noise errors
1284 # IoutTp, IoutTm, IoutRp, IoutRm, dIoutTp, dIoutTm, dIoutRp, dIoutRm
1285
1286 aCal = (1. - LDRCal) / (1. + LDRCal)
1287 for iQin, iVin, iRotL, iRotE, iRetE, iDiE \
1288 in [(iQin, iVin, iRotL, iRotE, iRetE, iDiE)
1289 for iQin in range(-nQin, nQin + 1)
1290 for iVin in range(-nVin, nVin + 1)
1291 for iRotL in range(-nRotL, nRotL + 1)
1292 for iRotE in range(-nRotE, nRotE + 1)
1293 for iRetE in range(-nRetE, nRetE + 1)
1294 for iDiE in range(-nDiE, nDiE + 1)]:
1295
1296 if nQin > 0: Qin = Qin0 + iQin * dQin / nQin
1297 if nVin > 0: Vin = Vin0 + iVin * dVin / nVin
1298 if nRotL > 0: RotL = RotL0 + iRotL * dRotL / nRotL
1299 if nRotE > 0: RotE = RotE0 + iRotE * dRotE / nRotE
1300 if nRetE > 0: RetE = RetE0 + iRetE * dRetE / nRetE
1301 if nDiE > 0: DiE = DiE0 + iDiE * dDiE / nDiE
1302
1303 if ((Qin ** 2 + Vin ** 2) ** 0.5) > 1.0:
1304 print("Error: degree of polarisation of laser > 1. Check Qin and Vin! ")
1305 sys.exit()
1306 # angles of emitter and laser and calibrator and receiver optics
1307 # RotL = alpha, RotE = beta, RotO = gamma, RotC = epsilon
1308 S2a = np.sin(2 * np.deg2rad(RotL))
1309 C2a = np.cos(2 * np.deg2rad(RotL))
1310 S2b = np.sin(2 * np.deg2rad(RotE))
1311 C2b = np.cos(2 * np.deg2rad(RotE))
1312 S2ab = np.sin(np.deg2rad(2 * RotL - 2 * RotE))
1313 C2ab = np.cos(np.deg2rad(2 * RotL - 2 * RotE))
1314
1315 # Laser with Degree of linear polarization DOLP
1316 IinL = 1.
1317 QinL = Qin
1318 UinL = 0.
1319 VinL = Vin
1320 # VinL = (1. - DOLP ** 2) ** 0.5
1321
1322 # Stokes Input Vector rotation Eq. E.4
1323 A = C2a * QinL - S2a * UinL
1324 B = S2a * QinL + C2a * UinL
1325 # Stokes Input Vector rotation Eq. E.9
1326 C = C2ab * QinL - S2ab * UinL
1327 D = S2ab * QinL + C2ab * UinL
1328
1329 # emitter optics
1330 CosE = np.cos(np.deg2rad(RetE))
1331 SinE = np.sin(np.deg2rad(RetE))
1332 ZiE = (1. - DiE ** 2) ** 0.5
1333 WiE = (1. - ZiE * CosE)
1334
1335 # Stokes Input Vector after emitter optics equivalent to Eq. E.9 with already rotated input vector from Eq. E.4
1336 # b = beta
1337 IinE = (IinL + DiE * C)
1338 QinE = (C2b * DiE * IinL + A + S2b * (WiE * D - ZiE * SinE * VinL))
1339 UinE = (S2b * DiE * IinL + B - C2b * (WiE * D - ZiE * SinE * VinL))
1340 VinE = (-ZiE * SinE * D + ZiE * CosE * VinL)
1341
1342 # -------------------------
1343 # F11 assuemd to be = 1 => measured: F11m = IinP / IinE with atrue
1344 # F11sim = (IinE + DiO*atrue*(C2g*QinE - S2g*UinE))/IinE
1345 # -------------------------
1346
1347 for iRotO, iRetO, iDiO, iRotC, iRetC, iDiC, iTP, iTS, iRP, iRS, iERaT, iRotaT, iRetT, iERaR, iRotaR, iRetR \
1348 in [
1349 (iRotO, iRetO, iDiO, iRotC, iRetC, iDiC, iTP, iTS, iRP, iRS, iERaT, iRotaT, iRetT, iERaR, iRotaR, iRetR)
1350 for iRotO in range(-nRotO, nRotO + 1)
1351 for iRetO in range(-nRetO, nRetO + 1)
1352 for iDiO in range(-nDiO, nDiO + 1)
1353 for iRotC in range(-nRotC, nRotC + 1)
1354 for iRetC in range(-nRetC, nRetC + 1)
1355 for iDiC in range(-nDiC, nDiC + 1)
1356 for iTP in range(-nTP, nTP + 1)
1357 for iTS in range(-nTS, nTS + 1)
1358 for iRP in range(-nRP, nRP + 1)
1359 for iRS in range(-nRS, nRS + 1)
1360 for iERaT in range(-nERaT, nERaT + 1)
1361 for iRotaT in range(-nRotaT, nRotaT + 1)
1362 for iRetT in range(-nRetT, nRetT + 1)
1363 for iERaR in range(-nERaR, nERaR + 1)
1364 for iRotaR in range(-nRotaR, nRotaR + 1)
1365 for iRetR in range(-nRetR, nRetR + 1)]:
1366
1367 if nRotO > 0: RotO = RotO0 + iRotO * dRotO / nRotO
1368 if nRetO > 0: RetO = RetO0 + iRetO * dRetO / nRetO
1369 if nDiO > 0: DiO = DiO0 + iDiO * dDiO / nDiO
1370 if nRotC > 0: RotC = RotC0 + iRotC * dRotC / nRotC
1371 if nRetC > 0: RetC = RetC0 + iRetC * dRetC / nRetC
1372 if nDiC > 0: DiC = DiC0 + iDiC * dDiC / nDiC
1373 if nTP > 0: TP = TP0 + iTP * dTP / nTP
1374 if nTS > 0: TS = TS0 + iTS * dTS / nTS
1375 if nRP > 0: RP = RP0 + iRP * dRP / nRP
1376 if nRS > 0: RS = RS0 + iRS * dRS / nRS
1377 if nERaT > 0: ERaT = ERaT0 + iERaT * dERaT / nERaT
1378 if nRotaT > 0: RotaT = RotaT0 + iRotaT * dRotaT / nRotaT
1379 if nRetT > 0: RetT = RetT0 + iRetT * dRetT / nRetT
1380 if nERaR > 0: ERaR = ERaR0 + iERaR * dERaR / nERaR
1381 if nRotaR > 0: RotaR = RotaR0 + iRotaR * dRotaR / nRotaR
1382 if nRetR > 0: RetR = RetR0 + iRetR * dRetR / nRetR
1383
1384 # print("{0:5.2f}, {1:5.2f}, {2:5.2f}, {3:10d}".format(RotL, RotE, RotO, iN))
1385
1386 # receiver optics
1387 CosO = np.cos(np.deg2rad(RetO))
1388 SinO = np.sin(np.deg2rad(RetO))
1389 ZiO = (1. - DiO ** 2) ** 0.5
1390 WiO = (1. - ZiO * CosO)
1391 S2g = np.sin(np.deg2rad(2 * RotO))
1392 C2g = np.cos(np.deg2rad(2 * RotO))
1393 # calibrator
1394 CosC = np.cos(np.deg2rad(RetC))
1395 SinC = np.sin(np.deg2rad(RetC))
1396 ZiC = (1. - DiC ** 2) ** 0.5
1397 WiC = (1. - ZiC * CosC)
1398
1399 # analyser
1400 # For POLLY_XTs
1401 if (RS_RP_depend_on_TS_TP):
1402 RS = 1.0 - TS
1403 RP = 1.0 - TP
1404 TiT = 0.5 * (TP + TS)
1405 DiT = (TP - TS) / (TP + TS)
1406 ZiT = (1. - DiT ** 2.) ** 0.5
1407 TiR = 0.5 * (RP + RS)
1408 DiR = (RP - RS) / (RP + RS)
1409 ZiR = (1. - DiR ** 2.) ** 0.5
1410 CosT = np.cos(np.deg2rad(RetT))
1411 SinT = np.sin(np.deg2rad(RetT))
1412 CosR = np.cos(np.deg2rad(RetR))
1413 SinR = np.sin(np.deg2rad(RetR))
1414
1415 # cleaning pol-filter
1416 DaT = (1.0 - ERaT) / (1.0 + ERaT)
1417 DaR = (1.0 - ERaR) / (1.0 + ERaR)
1418 TaT = 0.5 * (1.0 + ERaT)
1419 TaR = 0.5 * (1.0 + ERaR)
1420
1421 S2aT = np.sin(np.deg2rad(h * 2.0 * RotaT))
1422 C2aT = np.cos(np.deg2rad(2.0 * RotaT))
1423 S2aR = np.sin(np.deg2rad(h * 2.0 * RotaR))
1424 C2aR = np.cos(np.deg2rad(2.0 * RotaR))
1425
1426 # Analyzer As before the PBS Eq. D.5; combined PBS and cleaning pol-filter
1427 ATPT = (1 + C2aT * DaT * DiT) # unpolarized transmission correction
1428 TTa = TiT * TaT * ATPT # unpolarized transmission
1429 ATP1 = 1.0
1430 ATP2 = Y * (DiT + C2aT * DaT) / ATPT
1431 ATP3 = Y * S2aT * DaT * ZiT * CosT / ATPT
1432 ATP4 = S2aT * DaT * ZiT * SinT / ATPT
1433 ATP = np.array([ATP1, ATP2, ATP3, ATP4])
1434 DTa = ATP2 * Y
1435
1436 ARPT = (1 + C2aR * DaR * DiR) # unpolarized transmission correction
1437 TRa = TiR * TaR * ARPT # unpolarized transmission
1438 ARP1 = 1
1439 ARP2 = Y * (DiR + C2aR * DaR) / ARPT
1440 ARP3 = Y * S2aR * DaR * ZiR * CosR / ARPT
1441 ARP4 = S2aR * DaR * ZiR * SinR / ARPT
1442 ARP = np.array([ARP1, ARP2, ARP3, ARP4])
1443 DRa = ARP2 * Y
1444
1445 # ---- Calculate signals and correction parameters for diffeent locations and calibrators
1446 if LocC == 4: # Calibrator before the PBS
1447 # print("Calibrator location not implemented yet")
1448
1449 # S2ge = np.sin(np.deg2rad(2*RotO + h*2*RotC))
1450 # C2ge = np.cos(np.deg2rad(2*RotO + h*2*RotC))
1451 S2e = np.sin(np.deg2rad(h * 2 * RotC))
1452 C2e = np.cos(np.deg2rad(2 * RotC))
1453 # rotated AinP by epsilon Eq. C.3
1454 ATP2e = C2e * ATP2 + S2e * ATP3
1455 ATP3e = C2e * ATP3 - S2e * ATP2
1456 ARP2e = C2e * ARP2 + S2e * ARP3
1457 ARP3e = C2e * ARP3 - S2e * ARP2
1458 ATPe = np.array([ATP1, ATP2e, ATP3e, ATP4])
1459 ARPe = np.array([ARP1, ARP2e, ARP3e, ARP4])
1460 # Stokes Input Vector before the polarising beam splitter Eq. E.31
1461 A = C2g * QinE - S2g * UinE
1462 B = S2g * QinE + C2g * UinE
1463 # C = (WiO*aCal*B + ZiO*SinO*(1-2*aCal)*VinE)
1464 Co = ZiO * SinO * VinE
1465 Ca = (WiO * B - 2 * ZiO * SinO * VinE)
1466 # C = Co + aCal*Ca
1467 # IinP = (IinE + DiO*aCal*A)
1468 # QinP = (C2g*DiO*IinE + aCal*QinE - S2g*C)
1469 # UinP = (S2g*DiO*IinE - aCal*UinE + C2g*C)
1470 # VinP = (ZiO*SinO*aCal*B + ZiO*CosO*(1-2*aCal)*VinE)
1471 IinPo = IinE
1472 QinPo = (C2g * DiO * IinE - S2g * Co)
1473 UinPo = (S2g * DiO * IinE + C2g * Co)
1474 VinPo = ZiO * CosO * VinE
1475
1476 IinPa = DiO * A
1477 QinPa = QinE - S2g * Ca
1478 UinPa = -UinE + C2g * Ca
1479 VinPa = ZiO * (SinO * B - 2 * CosO * VinE)
1480
1481 IinP = IinPo + aCal * IinPa
1482 QinP = QinPo + aCal * QinPa
1483 UinP = UinPo + aCal * UinPa
1484 VinP = VinPo + aCal * VinPa
1485 # Stokes Input Vector before the polarising beam splitter rotated by epsilon Eq. C.3
1486 # QinPe = C2e*QinP + S2e*UinP
1487 # UinPe = C2e*UinP - S2e*QinP
1488 QinPoe = C2e * QinPo + S2e * UinPo
1489 UinPoe = C2e * UinPo - S2e * QinPo
1490 QinPae = C2e * QinPa + S2e * UinPa
1491 UinPae = C2e * UinPa - S2e * QinPa
1492 QinPe = C2e * QinP + S2e * UinP
1493 UinPe = C2e * UinP - S2e * QinP
1494
1495 # Calibration signals and Calibration correction K from measurements with LDRCal / aCal
1496 if (TypeC == 2) or (TypeC == 1): # rotator calibration Eq. C.4
1497 # parameters for calibration with aCal
1498 AT = ATP1 * IinP + h * ATP4 * VinP
1499 BT = ATP3e * QinP - h * ATP2e * UinP
1500 AR = ARP1 * IinP + h * ARP4 * VinP
1501 BR = ARP3e * QinP - h * ARP2e * UinP
1502 # Correction parameters for normal measurements; they are independent of LDR
1503 if (not RotationErrorEpsilonForNormalMeasurements): # calibrator taken out
1504 IS1 = np.array([IinPo, QinPo, UinPo, VinPo])
1505 IS2 = np.array([IinPa, QinPa, UinPa, VinPa])
1506 GT = np.dot(ATP, IS1)
1507 GR = np.dot(ARP, IS1)
1508 HT = np.dot(ATP, IS2)
1509 HR = np.dot(ARP, IS2)
1510 else:
1511 IS1 = np.array([IinPo, QinPo, UinPo, VinPo])
1512 IS2 = np.array([IinPa, QinPa, UinPa, VinPa])
1513 GT = np.dot(ATPe, IS1)
1514 GR = np.dot(ARPe, IS1)
1515 HT = np.dot(ATPe, IS2)
1516 HR = np.dot(ARPe, IS2)
1517 elif (TypeC == 3) or (TypeC == 4): # linear polariser calibration Eq. C.5
1518 # parameters for calibration with aCal
1519 AT = ATP1 * IinP + ATP3e * UinPe + ZiC * CosC * (ATP2e * QinPe + ATP4 * VinP)
1520 BT = DiC * (ATP1 * UinPe + ATP3e * IinP) - ZiC * SinC * (ATP2e * VinP - ATP4 * QinPe)
1521 AR = ARP1 * IinP + ARP3e * UinPe + ZiC * CosC * (ARP2e * QinPe + ARP4 * VinP)
1522 BR = DiC * (ARP1 * UinPe + ARP3e * IinP) - ZiC * SinC * (ARP2e * VinP - ARP4 * QinPe)
1523 # Correction parameters for normal measurements; they are independent of LDR
1524 if (not RotationErrorEpsilonForNormalMeasurements): # calibrator taken out
1525 IS1 = np.array([IinPo, QinPo, UinPo, VinPo])
1526 IS2 = np.array([IinPa, QinPa, UinPa, VinPa])
1527 GT = np.dot(ATP, IS1)
1528 GR = np.dot(ARP, IS1)
1529 HT = np.dot(ATP, IS2)
1530 HR = np.dot(ARP, IS2)
1531 else:
1532 IS1e = np.array(
1533 [IinPo + DiC * QinPoe, DiC * IinPo + QinPoe, ZiC * (CosC * UinPoe + SinC * VinPo),
1534 -ZiC * (SinC * UinPoe - CosC * VinPo)])
1535 IS2e = np.array(
1536 [IinPa + DiC * QinPae, DiC * IinPa + QinPae, ZiC * (CosC * UinPae + SinC * VinPa),
1537 -ZiC * (SinC * UinPae - CosC * VinPa)])
1538 GT = np.dot(ATPe, IS1e)
1539 GR = np.dot(ARPe, IS1e)
1540 HT = np.dot(ATPe, IS2e)
1541 HR = np.dot(ARPe, IS2e)
1542 elif (TypeC == 6): # diattenuator calibration +-22.5° rotated_diattenuator_X22x5deg.odt
1543 # parameters for calibration with aCal
1544 AT = ATP1 * IinP + sqr05 * DiC * (ATP1 * QinPe + ATP2e * IinP) + (1 - 0.5 * WiC) * (
1545 ATP2e * QinPe + ATP3e * UinPe) + ZiC * (
1546 sqr05 * SinC * (ATP3e * VinP - ATP4 * UinPe) + ATP4 * CosC * VinP)
1547 BT = sqr05 * DiC * (ATP1 * UinPe + ATP3e * IinP) + 0.5 * WiC * (
1548 ATP2e * UinPe + ATP3e * QinPe) - sqr05 * ZiC * SinC * (ATP2e * VinP - ATP4 * QinPe)
1549 AR = ARP1 * IinP + sqr05 * DiC * (ARP1 * QinPe + ARP2e * IinP) + (1 - 0.5 * WiC) * (
1550 ARP2e * QinPe + ARP3e * UinPe) + ZiC * (
1551 sqr05 * SinC * (ARP3e * VinP - ARP4 * UinPe) + ARP4 * CosC * VinP)
1552 BR = sqr05 * DiC * (ARP1 * UinPe + ARP3e * IinP) + 0.5 * WiC * (
1553 ARP2e * UinPe + ARP3e * QinPe) - sqr05 * ZiC * SinC * (ARP2e * VinP - ARP4 * QinPe)
1554 # Correction parameters for normal measurements; they are independent of LDR
1555 if (not RotationErrorEpsilonForNormalMeasurements): # calibrator taken out
1556 IS1 = np.array([IinPo, QinPo, UinPo, VinPo])
1557 IS2 = np.array([IinPa, QinPa, UinPa, VinPa])
1558 GT = np.dot(ATP, IS1)
1559 GR = np.dot(ARP, IS1)
1560 HT = np.dot(ATP, IS2)
1561 HR = np.dot(ARP, IS2)
1562 else:
1563 IS1e = np.array(
1564 [IinPo + DiC * QinPoe, DiC * IinPo + QinPoe, ZiC * (CosC * UinPoe + SinC * VinPo),
1565 -ZiC * (SinC * UinPoe - CosC * VinPo)])
1566 IS2e = np.array(
1567 [IinPa + DiC * QinPae, DiC * IinPa + QinPae, ZiC * (CosC * UinPae + SinC * VinPa),
1568 -ZiC * (SinC * UinPae - CosC * VinPa)])
1569 GT = np.dot(ATPe, IS1e)
1570 GR = np.dot(ARPe, IS1e)
1571 HT = np.dot(ATPe, IS2e)
1572 HR = np.dot(ARPe, IS2e)
1573 else:
1574 print("Calibrator not implemented yet")
1575 sys.exit()
1576
1577 elif LocC == 3: # C before receiver optics Eq.57
1578
1579 # S2ge = np.sin(np.deg2rad(2*RotO - 2*RotC))
1580 # C2ge = np.cos(np.deg2rad(2*RotO - 2*RotC))
1581 S2e = np.sin(np.deg2rad(2 * RotC))
1582 C2e = np.cos(np.deg2rad(2 * RotC))
1583
1584 # AS with C before the receiver optics (see document rotated_diattenuator_X22x5deg.odt)
1585 AF1 = np.array([1, C2g * DiO, S2g * DiO, 0])
1586 AF2 = np.array([C2g * DiO, 1 - S2g ** 2 * WiO, S2g * C2g * WiO, -S2g * ZiO * SinO])
1587 AF3 = np.array([S2g * DiO, S2g * C2g * WiO, 1 - C2g ** 2 * WiO, C2g * ZiO * SinO])
1588 AF4 = np.array([0, S2g * SinO, -C2g * SinO, CosO])
1589
1590 ATF = (ATP1 * AF1 + ATP2 * AF2 + ATP3 * AF3 + ATP4 * AF4)
1591 ARF = (ARP1 * AF1 + ARP2 * AF2 + ARP3 * AF3 + ARP4 * AF4)
1592 ATF1 = ATF[0]
1593 ATF2 = ATF[1]
1594 ATF3 = ATF[2]
1595 ATF4 = ATF[3]
1596 ARF1 = ARF[0]
1597 ARF2 = ARF[1]
1598 ARF3 = ARF[2]
1599 ARF4 = ARF[3]
1600
1601 # rotated AinF by epsilon
1602 ATF2e = C2e * ATF[1] + S2e * ATF[2]
1603 ATF3e = C2e * ATF[2] - S2e * ATF[1]
1604 ARF2e = C2e * ARF[1] + S2e * ARF[2]
1605 ARF3e = C2e * ARF[2] - S2e * ARF[1]
1606
1607 ATFe = np.array([ATF1, ATF2e, ATF3e, ATF4])
1608 ARFe = np.array([ARF1, ARF2e, ARF3e, ARF4])
1609
1610 QinEe = C2e * QinE + S2e * UinE
1611 UinEe = C2e * UinE - S2e * QinE
1612
1613 # Stokes Input Vector before receiver optics Eq. E.19 (after atmosphere F)
1614 IinF = IinE
1615 QinF = aCal * QinE
1616 UinF = -aCal * UinE
1617 VinF = (1. - 2. * aCal) * VinE
1618
1619 IinFo = IinE
1620 QinFo = 0.
1621 UinFo = 0.
1622 VinFo = VinE
1623
1624 IinFa = 0.
1625 QinFa = QinE
1626 UinFa = -UinE
1627 VinFa = -2. * VinE
1628
1629 # Stokes Input Vector before receiver optics rotated by epsilon Eq. C.3
1630 QinFe = C2e * QinF + S2e * UinF
1631 UinFe = C2e * UinF - S2e * QinF
1632 QinFoe = C2e * QinFo + S2e * UinFo
1633 UinFoe = C2e * UinFo - S2e * QinFo
1634 QinFae = C2e * QinFa + S2e * UinFa
1635 UinFae = C2e * UinFa - S2e * QinFa
1636
1637 # Calibration signals and Calibration correction K from measurements with LDRCal / aCal
1638 if (TypeC == 2) or (TypeC == 1): # rotator calibration Eq. C.4
1639 AT = ATF1 * IinF + ATF4 * h * VinF
1640 BT = ATF3e * QinF - ATF2e * h * UinF
1641 AR = ARF1 * IinF + ARF4 * h * VinF
1642 BR = ARF3e * QinF - ARF2e * h * UinF
1643
1644 # Correction parameters for normal measurements; they are independent of LDR
1645 if (not RotationErrorEpsilonForNormalMeasurements):
1646 GT = ATF1 * IinE + ATF4 * VinE
1647 GR = ARF1 * IinE + ARF4 * VinE
1648 HT = ATF2 * QinE - ATF3 * UinE - ATF4 * 2 * VinE
1649 HR = ARF2 * QinE - ARF3 * UinE - ARF4 * 2 * VinE
1650 else:
1651 GT = ATF1 * IinE + ATF4 * h * VinE
1652 GR = ARF1 * IinE + ARF4 * h * VinE
1653 HT = ATF2e * QinE - ATF3e * h * UinE - ATF4 * h * 2 * VinE
1654 HR = ARF2e * QinE - ARF3e * h * UinE - ARF4 * h * 2 * VinE
1655
1656 elif (TypeC == 3) or (TypeC == 4): # linear polariser calibration Eq. C.5
1657 # p = +45°, m = -45°
1658 IF1e = np.array([IinF, ZiC * CosC * QinFe, UinFe, ZiC * CosC * VinF])
1659 IF2e = np.array([DiC * UinFe, -ZiC * SinC * VinF, DiC * IinF, ZiC * SinC * QinFe])
1660
1661 AT = np.dot(ATFe, IF1e)
1662 AR = np.dot(ARFe, IF1e)
1663 BT = np.dot(ATFe, IF2e)
1664 BR = np.dot(ARFe, IF2e)
1665
1666 # Correction parameters for normal measurements; they are independent of LDR --- the same as for TypeC = 6
1667 if (not RotationErrorEpsilonForNormalMeasurements): # calibrator taken out
1668 IS1 = np.array([IinE, 0, 0, VinE])
1669 IS2 = np.array([0, QinE, -UinE, -2 * VinE])
1670
1671 GT = np.dot(ATF, IS1)
1672 GR = np.dot(ARF, IS1)
1673 HT = np.dot(ATF, IS2)
1674 HR = np.dot(ARF, IS2)
1675 else:
1676 IS1e = np.array(
1677 [IinFo + DiC * QinFoe, DiC * IinFo + QinFoe, ZiC * (CosC * UinFoe + SinC * VinFo),
1678 -ZiC * (SinC * UinFoe - CosC * VinFo)])
1679 IS2e = np.array(
1680 [IinFa + DiC * QinFae, DiC * IinFa + QinFae, ZiC * (CosC * UinFae + SinC * VinFa),
1681 -ZiC * (SinC * UinFae - CosC * VinFa)])
1682 GT = np.dot(ATFe, IS1e)
1683 GR = np.dot(ARFe, IS1e)
1684 HT = np.dot(ATFe, IS2e)
1685 HR = np.dot(ARFe, IS2e)
1686
1687 elif (TypeC == 6): # diattenuator calibration +-22.5° rotated_diattenuator_X22x5deg.odt
1688 # p = +22.5°, m = -22.5°
1689 IF1e = np.array([IinF + sqr05 * DiC * QinFe, sqr05 * DiC * IinF + (1 - 0.5 * WiC) * QinFe,
1690 (1 - 0.5 * WiC) * UinFe + sqr05 * ZiC * SinC * VinF,
1691 -sqr05 * ZiC * SinC * UinFe + ZiC * CosC * VinF])
1692 IF2e = np.array([sqr05 * DiC * UinFe, 0.5 * WiC * UinFe - sqr05 * ZiC * SinC * VinF,
1693 sqr05 * DiC * IinF + 0.5 * WiC * QinFe, sqr05 * ZiC * SinC * QinFe])
1694
1695 AT = np.dot(ATFe, IF1e)
1696 AR = np.dot(ARFe, IF1e)
1697 BT = np.dot(ATFe, IF2e)
1698 BR = np.dot(ARFe, IF2e)
1699
1700 # Correction parameters for normal measurements; they are independent of LDR
1701 if (not RotationErrorEpsilonForNormalMeasurements): # calibrator taken out
1702 # IS1 = np.array([IinE,0,0,VinE])
1703 # IS2 = np.array([0,QinE,-UinE,-2*VinE])
1704 IS1 = np.array([IinFo, 0, 0, VinFo])
1705 IS2 = np.array([0, QinFa, UinFa, VinFa])
1706 GT = np.dot(ATF, IS1)
1707 GR = np.dot(ARF, IS1)
1708 HT = np.dot(ATF, IS2)
1709 HR = np.dot(ARF, IS2)
1710 else:
1711 # IS1e = np.array([IinE,DiC*IinE,ZiC*SinC*VinE,ZiC*CosC*VinE])
1712 # IS2e = np.array([DiC*QinEe,QinEe,-ZiC*(CosC*UinEe+2*SinC*VinE),ZiC*(SinC*UinEe-2*CosC*VinE)])
1713 IS1e = np.array(
1714 [IinFo + DiC * QinFoe, DiC * IinFo + QinFoe, ZiC * (CosC * UinFoe + SinC * VinFo),
1715 -ZiC * (SinC * UinFoe - CosC * VinFo)])
1716 IS2e = np.array(
1717 [IinFa + DiC * QinFae, DiC * IinFa + QinFae, ZiC * (CosC * UinFae + SinC * VinFa),
1718 -ZiC * (SinC * UinFae - CosC * VinFa)])
1719 GT = np.dot(ATFe, IS1e)
1720 GR = np.dot(ARFe, IS1e)
1721 HT = np.dot(ATFe, IS2e)
1722 HR = np.dot(ARFe, IS2e)
1723
1724
1725 else:
1726 print('Calibrator not implemented yet')
1727 sys.exit()
1728
1729 elif LocC == 2: # C behind emitter optics Eq.57
1730 # print("Calibrator location not implemented yet")
1731 S2e = np.sin(np.deg2rad(2 * RotC))
1732 C2e = np.cos(np.deg2rad(2 * RotC))
1733
1734 # AS with C before the receiver optics (see document rotated_diattenuator_X22x5deg.odt)
1735 AF1 = np.array([1, C2g * DiO, S2g * DiO, 0])
1736 AF2 = np.array([C2g * DiO, 1 - S2g ** 2 * WiO, S2g * C2g * WiO, -S2g * ZiO * SinO])
1737 AF3 = np.array([S2g * DiO, S2g * C2g * WiO, 1 - C2g ** 2 * WiO, C2g * ZiO * SinO])
1738 AF4 = np.array([0, S2g * SinO, -C2g * SinO, CosO])
1739
1740 ATF = (ATP1 * AF1 + ATP2 * AF2 + ATP3 * AF3 + ATP4 * AF4)
1741 ARF = (ARP1 * AF1 + ARP2 * AF2 + ARP3 * AF3 + ARP4 * AF4)
1742 ATF1 = ATF[0]
1743 ATF2 = ATF[1]
1744 ATF3 = ATF[2]
1745 ATF4 = ATF[3]
1746 ARF1 = ARF[0]
1747 ARF2 = ARF[1]
1748 ARF3 = ARF[2]
1749 ARF4 = ARF[3]
1750
1751 # AS with C behind the emitter --------------------------------------------
1752 # terms without aCal
1753 ATE1o, ARE1o = ATF1, ARF1
1754 ATE2o, ARE2o = 0., 0.
1755 ATE3o, ARE3o = 0., 0.
1756 ATE4o, ARE4o = ATF4, ARF4
1757 # terms with aCal
1758 ATE1a, ARE1a = 0., 0.
1759 ATE2a, ARE2a = ATF2, ARF2
1760 ATE3a, ARE3a = -ATF3, -ARF3
1761 ATE4a, ARE4a = -2 * ATF4, -2 * ARF4
1762 # rotated AinEa by epsilon
1763 ATE2ae = C2e * ATF2 + S2e * ATF3
1764 ATE3ae = -S2e * ATF2 - C2e * ATF3
1765 ARE2ae = C2e * ARF2 + S2e * ARF3
1766 ARE3ae = -S2e * ARF2 - C2e * ARF3
1767
1768 ATE1 = ATE1o
1769 ATE2e = aCal * ATE2ae
1770 ATE3e = aCal * ATE3ae
1771 ATE4 = (1 - 2 * aCal) * ATF4
1772 ARE1 = ARE1o
1773 ARE2e = aCal * ARE2ae
1774 ARE3e = aCal * ARE3ae
1775 ARE4 = (1. - 2. * aCal) * ARF4
1776
1777 # rotated IinE
1778 QinEe = C2e * QinE + S2e * UinE
1779 UinEe = C2e * UinE - S2e * QinE
1780
1781 # --- Calibration signals and Calibration correction K from measurements with LDRCal / aCal
1782 if (TypeC == 2) or (TypeC == 1): # +++++++++ rotator calibration Eq. C.4
1783 AT = ATE1o * IinE + (ATE4o + aCal * ATE4a) * h * VinE
1784 BT = aCal * (ATE3ae * QinEe - ATE2ae * h * UinEe)
1785 AR = ARE1o * IinE + (ARE4o + aCal * ARE4a) * h * VinE
1786 BR = aCal * (ARE3ae * QinEe - ARE2ae * h * UinEe)
1787
1788 # Correction parameters for normal measurements; they are independent of LDR
1789 if (not RotationErrorEpsilonForNormalMeasurements):
1790 # Stokes Input Vector before receiver optics Eq. E.19 (after atmosphere F)
1791 GT = ATE1o * IinE + ATE4o * h * VinE
1792 GR = ARE1o * IinE + ARE4o * h * VinE
1793 HT = ATE2a * QinE + ATE3a * h * UinEe + ATE4a * h * VinE
1794 HR = ARE2a * QinE + ARE3a * h * UinEe + ARE4a * h * VinE
1795 else:
1796 GT = ATE1o * IinE + ATE4o * h * VinE
1797 GR = ARE1o * IinE + ARE4o * h * VinE
1798 HT = ATE2ae * QinE + ATE3ae * h * UinEe + ATE4a * h * VinE
1799 HR = ARE2ae * QinE + ARE3ae * h * UinEe + ARE4a * h * VinE
1800
1801 elif (TypeC == 3) or (TypeC == 4): # +++++++++ linear polariser calibration Eq. C.5
1802 # p = +45°, m = -45°
1803 AT = ATE1 * IinE + ZiC * CosC * (ATE2e * QinEe + ATE4 * VinE) + ATE3e * UinEe
1804 BT = DiC * (ATE1 * UinEe + ATE3e * IinE) + ZiC * SinC * (ATE4 * QinEe - ATE2e * VinE)
1805 AR = ARE1 * IinE + ZiC * CosC * (ARE2e * QinEe + ARE4 * VinE) + ARE3e * UinEe
1806 BR = DiC * (ARE1 * UinEe + ARE3e * IinE) + ZiC * SinC * (ARE4 * QinEe - ARE2e * VinE)
1807
1808 # Correction parameters for normal measurements; they are independent of LDR
1809 if (not RotationErrorEpsilonForNormalMeasurements):
1810 # Stokes Input Vector before receiver optics Eq. E.19 (after atmosphere F)
1811 GT = ATE1o * IinE + ATE4o * VinE
1812 GR = ARE1o * IinE + ARE4o * VinE
1813 HT = ATE2a * QinE + ATE3a * UinE + ATE4a * VinE
1814 HR = ARE2a * QinE + ARE3a * UinE + ARE4a * VinE
1815 else:
1816 D = IinE + DiC * QinEe
1817 A = DiC * IinE + QinEe
1818 B = ZiC * (CosC * UinEe + SinC * VinE)
1819 C = -ZiC * (SinC * UinEe - CosC * VinE)
1820 GT = ATE1o * D + ATE4o * C
1821 GR = ARE1o * D + ARE4o * C
1822 HT = ATE2a * A + ATE3a * B + ATE4a * C
1823 HR = ARE2a * A + ARE3a * B + ARE4a * C
1824
1825 elif (TypeC == 6): # real HWP calibration +-22.5° rotated_diattenuator_X22x5deg.odt
1826 # p = +22.5°, m = -22.5°
1827 IE1e = np.array([IinE + sqr05 * DiC * QinEe, sqr05 * DiC * IinE + (1 - 0.5 * WiC) * QinEe,
1828 (1. - 0.5 * WiC) * UinEe + sqr05 * ZiC * SinC * VinE,
1829 -sqr05 * ZiC * SinC * UinEe + ZiC * CosC * VinE])
1830 IE2e = np.array([sqr05 * DiC * UinEe, 0.5 * WiC * UinEe - sqr05 * ZiC * SinC * VinE,
1831 sqr05 * DiC * IinE + 0.5 * WiC * QinEe, sqr05 * ZiC * SinC * QinEe])
1832 ATEe = np.array([ATE1, ATE2e, ATE3e, ATE4])
1833 AREe = np.array([ARE1, ARE2e, ARE3e, ARE4])
1834 AT = np.dot(ATEe, IE1e)
1835 AR = np.dot(AREe, IE1e)
1836 BT = np.dot(ATEe, IE2e)
1837 BR = np.dot(AREe, IE2e)
1838
1839 # Correction parameters for normal measurements; they are independent of LDR
1840 if (not RotationErrorEpsilonForNormalMeasurements): # calibrator taken out
1841 GT = ATE1o * IinE + ATE4o * VinE
1842 GR = ARE1o * IinE + ARE4o * VinE
1843 HT = ATE2a * QinE + ATE3a * UinE + ATE4a * VinE
1844 HR = ARE2a * QinE + ARE3a * UinE + ARE4a * VinE
1845 else:
1846 D = IinE + DiC * QinEe
1847 A = DiC * IinE + QinEe
1848 B = ZiC * (CosC * UinEe + SinC * VinE)
1849 C = -ZiC * (SinC * UinEe - CosC * VinE)
1850 GT = ATE1o * D + ATE4o * C
1851 GR = ARE1o * D + ARE4o * C
1852 HT = ATE2a * A + ATE3a * B + ATE4a * C
1853 HR = ARE2a * A + ARE3a * B + ARE4a * C
1854 else:
1855 print('Calibrator not implemented yet')
1856 sys.exit()
1857
1858 for iTCalT, iTCalR, iNCalTp, iNCalTm, iNCalRp, iNCalRm, iNIt, iNIr \
1859 in [
1860 (iTCalT, iTCalR, iNCalTp, iNCalTm, iNCalRp, iNCalRm, iNIt, iNIr)
1861 for iTCalT in range(-nTCalT, nTCalT + 1) # Etax
1862 for iTCalR in range(-nTCalR, nTCalR + 1) # Etax
1863 for iNCalTp in range(-nNCal, nNCal + 1) # noise error of calibration signals => Etax
1864 for iNCalTm in range(-nNCal, nNCal + 1) # noise error of calibration signals => Etax
1865 for iNCalRp in range(-nNCal, nNCal + 1) # noise error of calibration signals => Etax
1866 for iNCalRm in range(-nNCal, nNCal + 1) # noise error of calibration signals => Etax
1867 for iNIt in range(-nNI, nNI + 1)
1868 for iNIr in range(-nNI, nNI + 1)]:
1869
1870 # Calibration signals with aCal => Determination of the correction K of the real calibration factor
1871 IoutTp = TTa * TiC * TiO * TiE * (AT + BT)
1872 IoutTm = TTa * TiC * TiO * TiE * (AT - BT)
1873 IoutRp = TRa * TiC * TiO * TiE * (AR + BR)
1874 IoutRm = TRa * TiC * TiO * TiE * (AR - BR)
1875
1876 if nTCalT > 0: TCalT = TCalT0 + iTCalT * dTCalT / nTCalT
1877 if nTCalR > 0: TCalR = TCalR0 + iTCalR * dTCalR / nTCalR
1878 # signal noise errors
1879 # ----- random error calculation ----------
1880 # noise must be calculated from/with the actually measured signals; influence of TCalT, TCalR errors on noise are not considered ?
1881 # actually measured signal counts are in input file and don't change
1882 # relative standard deviation of calibration signals with LDRcal; assumed to be statisitcally independent
1883 # error nNCal: one-sigma in steps to left and right for calibration signals
1884 if nNCal > 0:
1885 if (CalcFrom0deg):
1886 dIoutTp = (NCalT * IoutTp) ** -0.5
1887 dIoutTm = (NCalT * IoutTm) ** -0.5
1888 dIoutRp = (NCalR * IoutRp) ** -0.5
1889 dIoutRm = (NCalR * IoutRm) ** -0.5
1890 else:
1891 dIoutTp = dIoutTp0 * (IoutTp / IoutTp0)
1892 dIoutTm = dIoutTm0 * (IoutTm / IoutTm0)
1893 dIoutRp = dIoutRp0 * (IoutRp / IoutRp0)
1894 dIoutRm = dIoutRm0 * (IoutRm / IoutRm0)
1895 # print(iTCalT, iTCalR, iNCalTp, iNCalTm, iNCalRp, iNCalRm, iNIt, iNIr, IoutTp, dIoutTp)
1896 IoutTp = IoutTp * (1. + iNCalTp * dIoutTp / nNCal)
1897 IoutTm = IoutTm * (1. + iNCalTm * dIoutTm / nNCal)
1898 IoutRp = IoutRp * (1. + iNCalRp * dIoutRp / nNCal)
1899 IoutRm = IoutRm * (1. + iNCalRm * dIoutRm / nNCal)
1900
1901 IoutTp = IoutTp * TCalT / TCalT0
1902 IoutTm = IoutTm * TCalT / TCalT0
1903 IoutRp = IoutRp * TCalR / TCalR0
1904 IoutRm = IoutRm * TCalR / TCalR0
1905 # --- Results and Corrections; electronic etaR and etaT are assumed to be 1 for true and assumed true systems
1906 # calibration factor
1907 Eta = (TRa / TTa) # = TRa / TTa; Eta = Eta*/K Eq. 84; corrected according to the papers supplement Eqs. (S.10.10.1) ff
1908 # possibly real calibration factor
1909 Etapx = IoutRp / IoutTp
1910 Etamx = IoutRm / IoutTm
1911 Etax = (Etapx * Etamx) ** 0.5
1912 K = Etax / Eta
1913 # print("{0:6.3f},{1:6.3f},{2:6.3f},{3:6.3f},{4:6.3f},{5:6.3f},{6:6.3f},{7:6.3f},{8:6.3f},{9:6.3f},{10:6.3f}".format(AT, BT, AR, BR, DiC, ZiC, RetO, TP, TS, Kp, Km))
1914 # print("{0:6.3f},{1:6.3f},{2:6.3f},{3:6.3f}".format(DiC, ZiC, Kp, Km))
1915
1916 # For comparison with Volkers Libreoffice Müller Matrix spreadsheet
1917 # Eta_test_p = (IoutRp/IoutTp)
1918 # Eta_test_m = (IoutRm/IoutTm)
1919 # Eta_test = (Eta_test_p*Eta_test_m)**0.5
1920 '''
1921 for iIt, iIr \
1922 in [(iIt, iIr)
1923 for iIt in range(-nNI, nNI + 1)
1924 for iIr in range(-nNI, nNI + 1)]:
1925 '''
1926
1927 iN = iN + 1
1928 if (iN == 10001):
1929 ctime = clock()
1930 print(" estimated time ", "{0:4.2f}".format(N / 10000 * (ctime - atime)), "sec ") # , end="")
1931 print("\r elapsed time ", "{0:5.0f}".format((ctime - atime)), "sec ", end="\r")
1932 ctime = clock()
1933 if ((ctime - dtime) > 10):
1934 print("\r elapsed time ", "{0:5.0f}".format((ctime - atime)), "sec ", end="\r")
1935 dtime = ctime
1936
1937 # *** loop for different real LDRs **********************************************************************
1938 iLDR = -1
1939 for LDRTrue in LDRrange:
1940 iLDR = iLDR + 1
1941 atrue = (1. - LDRTrue) / (1. + LDRTrue)
1942 # ----- Forward simulated signals and LDRsim with atrue; from input file; not considering TiC.
1943 It = TTa * TiO * TiE * (GT + atrue * HT) # TaT*TiT*TiC*TiO*IinL*(GT+atrue*HT)
1944 Ir = TRa * TiO * TiE * (GR + atrue * HR) # TaR*TiR*TiC*TiO*IinL*(GR+atrue*HR)
1945 # # signal noise errors; standard deviation of signals; assumed to be statisitcally independent
1946 # because the signals depend on LDRtrue, the errors dIt and dIr must be calculated for each LDRtrue
1947 if (CalcFrom0deg):
1948 '''
1949 dIt = ((NCalT * It / IoutTp * NILfac / TCalT) ** -0.5)
1950 dIr = ((NCalR * Ir / IoutRp * NILfac / TCalR) ** -0.5)
1951 '''
1952 dIt = ((It * NI * eFacT) ** -0.5)
1953 dIr = ((Ir * NI * eFacR) ** -0.5)
1954 else:
1955 dIt = ((It * NI * eFacT) ** -0.5)
1956 dIr = ((Ir * NI * eFacR) ** -0.5)
1957 '''
1958 # does this work? Why not as above?
1959 dIt = ((NCalT * 2. * NILfac / TCalT ) ** -0.5)
1960 dIr = ((NCalR * 2. * NILfac / TCalR) ** -0.5)
1961 '''
1962 # error nNI: one-sigma in steps to left and right for 0° signals
1963 if nNI > 0:
1964 It = It * (1. + iNIt * dIt / nNI)
1965 Ir = Ir * (1. + iNIr * dIr / nNI)
1966
1967 # LDRsim = 1/Eta*Ir/It # simulated LDR* with Y from input file
1968 LDRsim = Ir / It # simulated uncorrected LDR with Y from input file
1969
1970 # ----- Backward correction
1971 # Corrected LDRCorr with assumed true G0,H0,K0,Eta0 from forward simulated (real) LDRsim(atrue)
1972 LDRCorr = (LDRsim / (Etax / K0) * (GT0 + HT0) - (GR0 + HR0)) / ((GR0 - HR0) - LDRsim / (Etax / K0) * (GT0 - HT0))
1973
1974 # The following is a test whether the equations for calibration Etax and normal signal (GHK, LDRsim) are consistent
1975 # LDRCorr = (LDRsim / Eta * (GT + HT) - (GR + HR)) / ((GR - HR) - LDRsim / Eta * (GT - HT))
1976 # Without any correction
1977 LDRunCorr = LDRsim / Etax
1978 # LDRunCorr = (LDRsim / Etax * (GT / abs(GT) + HT / abs(HT)) - (GR / abs(GR) + HR / abs(HR))) / ((GR / abs(GR) - HR / abs(HR)) - LDRsim / Etax * (GT / abs(GT) - HT / abs(HT)))
1979
1980
1981 '''
1982 # -- F11corr from It and Ir and calibration EtaX
1983 Text1 = "!!! EXPERIMENTAL !!! F11corr from It and Ir with calibration EtaX: x-axis: F11corr(LDRtrue) / F11corr(LDRtrue = 0.004) - 1"
1984 F11corr = 1 / (TiO * TiE) * (
1985 (HR0 * Etax / K0 * It / TTa - HT0 * Ir / TRa) / (HR0 * GT0 - HT0 * GR0)) # IL = 1 Eq.(64); Etax/K0 = Eta0.
1986 '''
1987 # Corrected F11corr with assumed true G0,H0,K0 from forward simulated (real) It and Ir (atrue)
1988 Text1 = "!!! EXPERIMENTAL !!! F11corr from real It and Ir with real calibration EtaX: x-axis: F11corr(LDRtrue) / aF11sim0(LDRtrue) - 1"
1989 F11corr = 1 / (TiO * TiE) * (
1990 (HR0 * Etax / K0 * It / TTa - HT0 * Ir / TRa) / (HR0 * GT0 - HT0 * GR0)) # IL = 1 Eq.(64); Etax/K0 = Eta0.
1991
1992 # Text1 = "F11corr from It and Ir without corrections but with calibration EtaX: x-axis: F11corr(LDRtrue) devided by F11corr(LDRtrue = 0.004)"
1993 # F11corr = 0.5/(TiO*TiE)*(Etax*It/TTa+Ir/TRa) # IL = 1 Eq.(64)
1994
1995 # -- It from It only with atrue without corrections - for BERTHA (and PollyXTs)
1996 # Text1 = " x-axis: IT(LDRtrue) / IT(LDRtrue = 0.004) - 1"
1997 # F11corr = It/(TaT*TiT*TiO*TiE) #/(TaT*TiT*TiO*TiE*(GT0+atrue*HT0))
1998 # ! see below line 1673ff
1999
2000 aF11corr[iLDR, iN] = F11corr
2001 aLDRcorr[iLDR, iN] = LDRCorr # LDRCorr # LDRsim # for test only
2002 aLDRsim[iLDR, iN] = LDRsim # LDRCorr # LDRsim # for test only
2003 # aPLDR[iLDR, iN] = CalcPLDR(LDRCorr, BSR[iLDR], LDRm0)
2004 aEtax[iLDR, iN] = Etax
2005 aEtapx[iLDR, iN] = Etapx
2006 aEtamx[iLDR, iN] = Etamx
2007
2008 aGHK[0, iN] = GR
2009 aGHK[1, iN] = GT
2010 aGHK[2, iN] = HR
2011 aGHK[3, iN] = HT
2012 aGHK[4, iN] = K
2013
2014 aLDRCal[iN] = iLDRCal
2015 aQin[iN] = iQin
2016 aVin[iN] = iVin
2017 aERaT[iN] = iERaT
2018 aERaR[iN] = iERaR
2019 aRotaT[iN] = iRotaT
2020 aRotaR[iN] = iRotaR
2021 aRetT[iN] = iRetT
2022 aRetR[iN] = iRetR
2023
2024 aRotL[iN] = iRotL
2025 aRotE[iN] = iRotE
2026 aRetE[iN] = iRetE
2027 aRotO[iN] = iRotO
2028 aRetO[iN] = iRetO
2029 aRotC[iN] = iRotC
2030 aRetC[iN] = iRetC
2031 aDiO[iN] = iDiO
2032 aDiE[iN] = iDiE
2033 aDiC[iN] = iDiC
2034 aTP[iN] = iTP
2035 aTS[iN] = iTS
2036 aRP[iN] = iRP
2037 aRS[iN] = iRS
2038 aTCalT[iN] = iTCalT
2039 aTCalR[iN] = iTCalR
2040
2041 aNCalTp[iN] = iNCalTp # IoutTp, IoutTm, IoutRp, IoutRm => Etax
2042 aNCalTm[iN] = iNCalTm # IoutTp, IoutTm, IoutRp, IoutRm => Etax
2043 aNCalRp[iN] = iNCalRp # IoutTp, IoutTm, IoutRp, IoutRm => Etax
2044 aNCalRm[iN] = iNCalRm # IoutTp, IoutTm, IoutRp, IoutRm => Etax
2045 aNIt[iN] = iNIt # It, Tr
2046 aNIr[iN] = iNIr # It, Tr
2047
2048 # --- END loop
2049 btime = clock()
2050 # print("\r done in ", "{0:5.0f}".format(btime - atime), "sec. => producing plots now .... some more seconds ..."), # , end="\r");
2051 print(" done in ", "{0:5.0f}".format(btime - atime), "sec. => producing plots now .... some more seconds ...")
2052 # --- Plot -----------------------------------------------------------------
2053 print("Errors from GHK correction uncertainties:")
2054 if (sns_loaded):
2055 sns.set_style("whitegrid")
2056 sns.set_palette("bright6", 6)
2057 # for older seaborn versions use:
2058 # sns.set_palette("bright", 6)
2059
2060 '''
2061 fig2 = plt.figure()
2062 plt.plot(aLDRcorr[2,:],'b.')
2063 plt.plot(aLDRcorr[3,:],'r.')
2064 plt.plot(aLDRcorr[4,:],'g.')
2065 #plt.plot(aLDRcorr[6,:],'c.')
2066 plt.show
2067 '''
2068
2069 # Plot LDR
2070 def PlotSubHist(aVar, aX, X0, daX, iaX, naX):
2071 # aVar is the name of the parameter and aX is the subset of aLDRcorr which is coloured in the plot
2072 # example: PlotSubHist("DOLP", aDOLP, DOLP0, dDOLP, iDOLP, nDOLP)
2073 fig, ax = plt.subplots(nrows=1, ncols=5, sharex=True, sharey=True, figsize=(25, 2))
2074 iLDR = -1
2075 for LDRTrue in LDRrange:
2076 aXmean = np.zeros(2 * naX + 1)
2077 iLDR = iLDR + 1
2078 LDRmin[iLDR] = np.amin(aLDRcorr[iLDR, :])
2079 LDRmax[iLDR] = np.amax(aLDRcorr[iLDR, :])
2080 if (LDRmax[iLDR] > 10): LDRmax[iLDR] = 10
2081 if (LDRmin[iLDR] < -10): LDRmin[iLDR] = -10
2082 Rmin = LDRmin[iLDR] * 0.995 # np.min(aLDRcorr[iLDR,:]) * 0.995
2083 Rmax = LDRmax[iLDR] * 1.005 # np.max(aLDRcorr[iLDR,:]) * 1.005
2084
2085 # Determine mean distance of all aXmean from each other for each iLDR
2086 meanDist = 0.0
2087 for iaX in range(-naX, naX + 1):
2088 # mean LDRCorr value for certain error (iaX) of parameter aVar
2089 aXmean[iaX + naX] = np.mean(aLDRcorr[iLDR, aX == iaX])
2090 # relative to absolute spread of LDRCorrs
2091 meanDist = (np.max(aXmean) - np.min(aXmean)) / (LDRmax[iLDR] - LDRmin[iLDR]) * 100
2092
2093 plt.subplot(1, 5, iLDR + 1)
2094 (n, bins, patches) = plt.hist(aLDRcorr[iLDR, :],
2095 bins=100, log=False,
2096 range=[Rmin, Rmax],
2097 alpha=0.5, density=False, color='0.5', histtype='stepfilled')
2098
2099 for iaX in range(-naX, naX + 1):
2100 # mean LDRCorr value for certain error (iaX) of parameter aVar
2101 plt.hist(aLDRcorr[iLDR, aX == iaX],
2102 range=[Rmin, Rmax],
2103 bins=100, log=False, alpha=0.3, density=False, histtype='stepfilled',
2104 label=str(round(X0 + iaX * daX / naX, 5)))
2105
2106 if (iLDR == 2):
2107 leg = plt.legend()
2108 leg.get_frame().set_alpha(0.1)
2109
2110 plt.tick_params(axis='both', labelsize=10)
2111 plt.plot([LDRTrue, LDRTrue], [0, np.max(n)], 'r-', lw=2)
2112 plt.gca().set_title("{0:3.0f}%".format(meanDist))
2113 plt.gca().set_xlabel('LDRtrue', color="red")
2114
2115 # plt.ylabel('frequency', fontsize=10)
2116 # plt.xlabel('LDRCorr', fontsize=10)
2117 # fig.tight_layout()
2118 fig.suptitle(LID + ' with ' + str(Type[TypeC]) + ' ' + str(Loc[LocC]) + ' - ' + aVar + ' error contribution', fontsize=14, y=1.10)
2119 # plt.show()
2120 # fig.savefig(LID + '_' + aVar + '.png', dpi=150, bbox_inches='tight', pad_inches=0)
2121 # plt.close
2122 return
2123
2124 def PlotLDRsim(aVar, aX, X0, daX, iaX, naX):
2125 # aVar is the name of the parameter and aX is the subset of aLDRsim which is coloured in the plot
2126 # example: PlotSubHist("DOLP", aDOLP, DOLP0, dDOLP, iDOLP, nDOLP)
2127 fig, ax = plt.subplots(nrows=1, ncols=5, sharex=True, sharey=True, figsize=(25, 2))
2128 iLDR = -1
2129 for LDRTrue in LDRrange:
2130 aXmean = np.zeros(2 * naX + 1)
2131 iLDR = iLDR + 1
2132 LDRsimmin[iLDR] = np.amin(aLDRsim[iLDR, :])
2133 LDRsimmax[iLDR] = np.amax(aLDRsim[iLDR, :])
2134 # print("LDRsimmin[iLDR], LDRsimmax[iLDR] = ", LDRsimmin[iLDR], LDRsimmax[iLDR])
2135 # if (LDRsimmax[iLDR] > 10): LDRsimmax[iLDR] = 10
2136 # if (LDRsimmin[iLDR] < -10): LDRsimmin[iLDR] = -10
2137 Rmin = LDRsimmin[iLDR] * 0.995 # np.min(aLDRsim[iLDR,:]) * 0.995
2138 Rmax = LDRsimmax[iLDR] * 1.005 # np.max(aLDRsim[iLDR,:]) * 1.005
2139 # print("Rmin, Rmax = ", Rmin, Rmax)
2140
2141 # Determine mean distance of all aXmean from each other for each iLDR
2142 meanDist = 0.0
2143 for iaX in range(-naX, naX + 1):
2144 # mean LDRCorr value for certain error (iaX) of parameter aVar
2145 aXmean[iaX + naX] = np.mean(aLDRsim[iLDR, aX == iaX])
2146 # relative to absolute spread of LDRCorrs
2147 meanDist = (np.max(aXmean) - np.min(aXmean)) / (LDRsimmax[iLDR] - LDRsimmin[iLDR]) * 100
2148
2149 plt.subplot(1, 5, iLDR + 1)
2150 (n, bins, patches) = plt.hist(aLDRsim[iLDR, :],
2151 bins=100, log=False,
2152 range=[Rmin, Rmax],
2153 alpha=0.5, density=False, color='0.5', histtype='stepfilled')
2154
2155 for iaX in range(-naX, naX + 1):
2156 # mean LDRCorr value for certain error (iaX) of parameter aVar
2157 plt.hist(aLDRsim[iLDR, aX == iaX],
2158 range=[Rmin, Rmax],
2159 bins=100, log=False, alpha=0.3, density=False, histtype='stepfilled',
2160 label=str(round(X0 + iaX * daX / naX, 5)))
2161
2162 if (iLDR == 2):
2163 leg = plt.legend()
2164 leg.get_frame().set_alpha(0.1)
2165
2166 plt.tick_params(axis='both', labelsize=10)
2167 plt.plot([LDRsim0[iLDR], LDRsim0[iLDR]], [0, np.max(n)], 'r-', lw=2)
2168 plt.gca().set_title("{0:3.0f}%".format(meanDist))
2169 plt.gca().set_xlabel('LDRsim0', color="red")
2170
2171 fig.suptitle('LDRsim - ' +LID + ' with ' + str(Type[TypeC]) + ' ' + str(Loc[LocC]) + ' - ' + aVar + ' error contribution', fontsize=14, y=1.10)
2172 return
2173
2174
2175 # Plot Etax
2176 def PlotEtax(aVar, aX, X0, daX, iaX, naX):
2177 # aVar is the name of the parameter and aX is the subset of aLDRcorr which is coloured in the plot
2178 # example: PlotSubHist("DOLP", aDOLP, DOLP0, dDOLP, iDOLP, nDOLP)
2179 fig, ax = plt.subplots(nrows=1, ncols=5, sharex=True, sharey=True, figsize=(25, 2))
2180 iLDR = -1
2181 for LDRTrue in LDRrange:
2182 aXmean = np.zeros(2 * naX + 1)
2183 iLDR = iLDR + 1
2184 Etaxmin = np.amin(aEtax[iLDR, :])
2185 Etaxmax = np.amax(aEtax[iLDR, :])
2186 Rmin = Etaxmin * 0.995 # np.min(aLDRcorr[iLDR,:]) * 0.995
2187 Rmax = Etaxmax * 1.005 # np.max(aLDRcorr[iLDR,:]) * 1.005
2188
2189 # Determine mean distance of all aXmean from each other for each iLDR
2190 meanDist = 0.0
2191 for iaX in range(-naX, naX + 1):
2192 # mean Etax value for certain error (iaX) of parameter aVar
2193 aXmean[iaX + naX] = np.mean(aEtax[iLDR, aX == iaX])
2194 # relative to absolute spread of Etax
2195 meanDist = (np.max(aXmean) - np.min(aXmean)) / (Etaxmax - Etaxmin) * 100
2196
2197 plt.subplot(1, 5, iLDR + 1)
2198 (n, bins, patches) = plt.hist(aEtax[iLDR, :],
2199 bins=50, log=False,
2200 range=[Rmin, Rmax],
2201 alpha=0.5, density=False, color='0.5', histtype='stepfilled')
2202 for iaX in range(-naX, naX + 1):
2203 plt.hist(aEtax[iLDR, aX == iaX],
2204 range=[Rmin, Rmax],
2205 bins=50, log=False, alpha=0.3, density=False, histtype='stepfilled',
2206 label=str(round(X0 + iaX * daX / naX, 5)))
2207 if (iLDR == 2):
2208 leg = plt.legend()
2209 leg.get_frame().set_alpha(0.1)
2210 plt.tick_params(axis='both', labelsize=10)
2211 plt.plot([Etax0, Etax0], [0, np.max(n)], 'r-', lw=2)
2212 plt.gca().set_title("{0:3.0f}%".format(meanDist))
2213 plt.gca().set_xlabel('Etax0', color="red")
2214 fig.suptitle('Etax - ' + LID + ' with ' + str(Type[TypeC]) + ' ' + str(Loc[LocC]) + ' - ' + aVar + ' error contribution', fontsize=14, y=1.10)
2215 return
2216
2217 def PlotEtapx(aVar, aX, X0, daX, iaX, naX):
2218 # aVar is the name of the parameter and aX is the subset of aLDRcorr which is coloured in the plot
2219 # example: PlotSubHist("DOLP", aDOLP, DOLP0, dDOLP, iDOLP, nDOLP)
2220 fig, ax = plt.subplots(nrows=1, ncols=5, sharex=True, sharey=True, figsize=(25, 2))
2221 iLDR = -1
2222 for LDRTrue in LDRrange:
2223 aXmean = np.zeros(2 * naX + 1)
2224 iLDR = iLDR + 1
2225 Etapxmin = np.amin(aEtapx[iLDR, :])
2226 Etapxmax = np.amax(aEtapx[iLDR, :])
2227 Rmin = Etapxmin * 0.995 # np.min(aLDRcorr[iLDR,:]) * 0.995
2228 Rmax = Etapxmax * 1.005 # np.max(aLDRcorr[iLDR,:]) * 1.005
2229
2230 # Determine mean distance of all aXmean from each other for each iLDR
2231 meanDist = 0.0
2232 for iaX in range(-naX, naX + 1):
2233 # mean Etapx value for certain error (iaX) of parameter aVar
2234 aXmean[iaX + naX] = np.mean(aEtapx[iLDR, aX == iaX])
2235 # relative to absolute spread of Etapx
2236 meanDist = (np.max(aXmean) - np.min(aXmean)) / (Etapxmax - Etapxmin) * 100
2237
2238 plt.subplot(1, 5, iLDR + 1)
2239 (n, bins, patches) = plt.hist(aEtapx[iLDR, :],
2240 bins=50, log=False,
2241 range=[Rmin, Rmax],
2242 alpha=0.5, density=False, color='0.5', histtype='stepfilled')
2243 for iaX in range(-naX, naX + 1):
2244 plt.hist(aEtapx[iLDR, aX == iaX],
2245 range=[Rmin, Rmax],
2246 bins=50, log=False, alpha=0.3, density=False, histtype='stepfilled',
2247 label=str(round(X0 + iaX * daX / naX, 5)))
2248 if (iLDR == 2):
2249 leg = plt.legend()
2250 leg.get_frame().set_alpha(0.1)
2251 plt.tick_params(axis='both', labelsize=10)
2252 plt.plot([Etapx0, Etapx0], [0, np.max(n)], 'r-', lw=2)
2253 plt.gca().set_title("{0:3.0f}%".format(meanDist))
2254 plt.gca().set_xlabel('Etapx0', color="red")
2255 fig.suptitle('Etapx - ' + LID + ' with ' + str(Type[TypeC]) + ' ' + str(Loc[LocC]) + ' - ' + aVar + ' error contribution', fontsize=14, y=1.10)
2256 return
2257
2258 def PlotEtamx(aVar, aX, X0, daX, iaX, naX):
2259 # aVar is the name of the parameter and aX is the subset of aLDRcorr which is coloured in the plot
2260 # example: PlotSubHist("DOLP", aDOLP, DOLP0, dDOLP, iDOLP, nDOLP)
2261 fig, ax = plt.subplots(nrows=1, ncols=5, sharex=True, sharey=True, figsize=(25, 2))
2262 iLDR = -1
2263 for LDRTrue in LDRrange:
2264 aXmean = np.zeros(2 * naX + 1)
2265 iLDR = iLDR + 1
2266 Etamxmin = np.amin(aEtamx[iLDR, :])
2267 Etamxmax = np.amax(aEtamx[iLDR, :])
2268 Rmin = Etamxmin * 0.995 # np.min(aLDRcorr[iLDR,:]) * 0.995
2269 Rmax = Etamxmax * 1.005 # np.max(aLDRcorr[iLDR,:]) * 1.005
2270
2271 # Determine mean distance of all aXmean from each other for each iLDR
2272 meanDist = 0.0
2273 for iaX in range(-naX, naX + 1):
2274 # mean Etamx value for certain error (iaX) of parameter aVar
2275 aXmean[iaX + naX] = np.mean(aEtamx[iLDR, aX == iaX])
2276 # relative to absolute spread of Etamx
2277 meanDist = (np.max(aXmean) - np.min(aXmean)) / (Etamxmax - Etamxmin) * 100
2278
2279 plt.subplot(1, 5, iLDR + 1)
2280 (n, bins, patches) = plt.hist(aEtamx[iLDR, :],
2281 bins=50, log=False,
2282 range=[Rmin, Rmax],
2283 alpha=0.5, density=False, color='0.5', histtype='stepfilled')
2284 for iaX in range(-naX, naX + 1):
2285 plt.hist(aEtamx[iLDR, aX == iaX],
2286 range=[Rmin, Rmax],
2287 bins=50, log=False, alpha=0.3, density=False, histtype='stepfilled',
2288 label=str(round(X0 + iaX * daX / naX, 5)))
2289 if (iLDR == 2):
2290 leg = plt.legend()
2291 leg.get_frame().set_alpha(0.1)
2292 plt.tick_params(axis='both', labelsize=10)
2293 plt.plot([Etamx0, Etamx0], [0, np.max(n)], 'r-', lw=2)
2294 plt.gca().set_title("{0:3.0f}%".format(meanDist))
2295 plt.gca().set_xlabel('Etamx0', color="red")
2296 fig.suptitle('Etamx - ' + LID + ' with ' + str(Type[TypeC]) + ' ' + str(Loc[LocC]) + ' - ' + aVar + ' error contribution', fontsize=14, y=1.10)
2297 return
2298
2299 # calc contribution of the error of aVar = aX to aY for each LDRtrue
2300 def Contribution(aVar, aX, X0, daX, iaX, naX, aY, Ysum, widthSum):
2301 # aVar is the name of the parameter and aX is the subset of aY which is coloured in the plot
2302 # example: Contribution("DOLP", aDOLP, DOLP0, dDOLP, iDOLP, nDOLP, aLDRcorr, DOLPcontr)
2303 iLDR = -1
2304 # Ysum, widthSum = np.zeros(5)
2305 meanDist = np.zeros(5) # iLDR
2306 widthDist = np.zeros(5) # iLDR
2307 for LDRTrue in LDRrange:
2308 aXmean = np.zeros(2 * naX + 1)
2309 aXwidth = np.zeros(2 * naX + 1)
2310 iLDR = iLDR + 1
2311 # total width of distribution
2312 aYmin = np.amin(aY[iLDR, :])
2313 aYmax = np.amax(aY[iLDR, :])
2314 aYwidth = aYmax - aYmin
2315 # Determine mean distance of all aXmean from each other for each iLDR
2316 for iaX in range(-naX, naX + 1):
2317 # mean LDRCorr value for all errors iaX of parameter aVar
2318 aXmean[iaX + naX] = np.mean(aY[iLDR, aX == iaX])
2319 aXwidth[iaX + naX] = np.max(aY[iLDR, aX == iaX]) - np.min(aY[iLDR, aX == iaX])
2320 # relative to absolute spread of LDRCorrs
2321 meanDist[iLDR] = (np.max(aXmean) - np.min(aXmean)) / aYwidth * 1000
2322 # meanDist[iLDR] = (aYwidth - aXwidth[naX]) / aYwidth * 1000
2323 widthDist[iLDR] = (np.max(aXwidth) - aXwidth[naX]) / aYwidth * 1000
2324
2325 print("{:12}{:5.0f} {:5.0f} {:5.0f} {:5.0f} {:5.0f} {:5.0f} {:5.0f} {:5.0f} {:5.0f} {:5.0f}"\
2326 .format(aVar,meanDist[0],meanDist[1],meanDist[2],meanDist[3],meanDist[4],widthDist[0],widthDist[1],widthDist[2],widthDist[3],widthDist[4]))
2327 Ysum = Ysum + meanDist
2328 widthSum = widthSum + widthDist
2329 return(Ysum, widthSum)
2330
2331 # print(.format(LDRrangeA[iLDR],))
2332
2333 # error contributions to a certain output aY; loop over all variables
2334 def Contribution_aY(aYvar, aY):
2335 Ysum = np.zeros(5)
2336 widthSum = np.zeros(5)
2337 # meanDist = np.zeros(5) # iLDR
2338 LDRrangeA = np.array(LDRrange)
2339 print()
2340 print(aYvar + ": contribution to the total error (per mill)")
2341 print(" of individual parameter errors of combined parameter errors")
2342 print(" at LDRtrue {:5.3f} {:5.3f} {:5.3f} {:5.3f} {:5.3f} {:5.3f} {:5.3f} {:5.3f} {:5.3f} {:5.3f}"\
2343 .format(LDRrangeA[0],LDRrangeA[1],LDRrangeA[2],LDRrangeA[3],LDRrangeA[4],LDRrangeA[0],LDRrangeA[1],LDRrangeA[2],LDRrangeA[3],LDRrangeA[4]))
2344 print()
2345 if (nQin > 0): Ysum, widthSum = Contribution("Qin", aQin, Qin0, dQin, iQin, nQin, aY, Ysum, widthSum)
2346 if (nVin > 0): Ysum, widthSum = Contribution("Vin", aVin, Vin0, dVin, iVin, nVin, aY, Ysum, widthSum)
2347 if (nRotL > 0): Ysum, widthSum = Contribution("RotL", aRotL, RotL0, dRotL, iRotL, nRotL, aY, Ysum, widthSum)
2348 if (nRetE > 0): Ysum, widthSum = Contribution("RetE", aRetE, RetE0, dRetE, iRetE, nRetE, aY, Ysum, widthSum)
2349 if (nRotE > 0): Ysum, widthSum = Contribution("RotE", aRotE, RotE0, dRotE, iRotE, nRotE, aY, Ysum, widthSum)
2350 if (nDiE > 0): Ysum, widthSum = Contribution("DiE", aDiE, DiE0, dDiE, iDiE, nDiE, aY, Ysum, widthSum)
2351 if (nRetO > 0): Ysum, widthSum = Contribution("RetO", aRetO, RetO0, dRetO, iRetO, nRetO, aY, Ysum, widthSum)
2352 if (nRotO > 0): Ysum, widthSum = Contribution("RotO", aRotO, RotO0, dRotO, iRotO, nRotO, aY, Ysum, widthSum)
2353 if (nDiO > 0): Ysum, widthSum = Contribution("DiO", aDiO, DiO0, dDiO, iDiO, nDiO, aY, Ysum, widthSum)
2354 if (nDiC > 0): Ysum, widthSum = Contribution("DiC", aDiC, DiC0, dDiC, iDiC, nDiC, aY, Ysum, widthSum)
2355 if (nRotC > 0): Ysum, widthSum = Contribution("RotC", aRotC, RotC0, dRotC, iRotC, nRotC, aY, Ysum, widthSum)
2356 if (nRetC > 0): Ysum, widthSum = Contribution("RetC", aRetC, RetC0, dRetC, iRetC, nRetC, aY, Ysum, widthSum)
2357 if (nTP > 0): Ysum, widthSum = Contribution("TP", aTP, TP0, dTP, iTP, nTP, aY, Ysum, widthSum)
2358 if (nTS > 0): Ysum, widthSum = Contribution("TS", aTS, TS0, dTS, iTS, nTS, aY, Ysum, widthSum)
2359 if (nRP > 0): Ysum, widthSum = Contribution("RP", aRP, RP0, dRP, iRP, nRP, aY, Ysum, widthSum)
2360 if (nRS > 0): Ysum, widthSum = Contribution("RS", aRS, RS0, dRS, iRS, nRS, aY, Ysum, widthSum)
2361 if (nRetT > 0): Ysum, widthSum = Contribution("RetT", aRetT, RetT0, dRetT, iRetT, nRetT, aY, Ysum, widthSum)
2362 if (nRetR > 0): Ysum, widthSum = Contribution("RetR", aRetR, RetR0, dRetR, iRetR, nRetR, aY, Ysum, widthSum)
2363 if (nERaT > 0): Ysum, widthSum = Contribution("ERaT", aERaT, ERaT0, dERaT, iERaT, nERaT, aY, Ysum, widthSum)
2364 if (nERaR > 0): Ysum, widthSum = Contribution("ERaR", aERaR, ERaR0, dERaR, iERaR, nERaR, aY, Ysum, widthSum)
2365 if (nRotaT > 0): Ysum, widthSum = Contribution("RotaT", aRotaT, RotaT0, dRotaT, iRotaT, nRotaT, aY, Ysum, widthSum)
2366 if (nRotaR > 0): Ysum, widthSum = Contribution("RotaR", aRotaR, RotaR0, dRotaR, iRotaR, nRotaR, aY, Ysum, widthSum)
2367 if (nLDRCal > 0): Ysum, widthSum = Contribution("LDRCal", aLDRCal, LDRCal0, dLDRCal, iLDRCal, nLDRCal, aY, Ysum, widthSum)
2368 if (nTCalT > 0): Ysum, widthSum = Contribution("TCalT", aTCalT, TCalT0, dTCalT, iTCalT, nTCalT, aY, Ysum, widthSum)
2369 if (nTCalR > 0): Ysum, widthSum = Contribution("TCalR", aTCalR, TCalR0, dTCalR, iTCalR, nTCalR, aY, Ysum, widthSum)
2370 if (nNCal > 0): Ysum, widthSum = Contribution("CalNoiseTp", aNCalTp, 0, 1, iNCalTp, nNCal, aY, Ysum, widthSum)
2371 if (nNCal > 0): Ysum, widthSum = Contribution("CalNoiseTm", aNCalTm, 0, 1, iNCalTm, nNCal, aY, Ysum, widthSum)
2372 if (nNCal > 0): Ysum, widthSum = Contribution("CalNoiseRp", aNCalRp, 0, 1, iNCalRp, nNCal, aY, Ysum, widthSum)
2373 if (nNCal > 0): Ysum, widthSum = Contribution("CalNoiseRm", aNCalRm, 0, 1, iNCalRm, nNCal, aY, Ysum, widthSum)
2374 if (nNI > 0): Ysum, widthSum = Contribution("SigNoiseIt", aNIt, 0, 1, iNIt, nNI, aY, Ysum, widthSum)
2375 if (nNI > 0): Ysum, widthSum = Contribution("SigNoiseIr", aNIr, 0, 1, iNIr, nNI, aY, Ysum, widthSum)
2376 print("{:12}{:5.0f} {:5.0f} {:5.0f} {:5.0f} {:5.0f} {:5.0f} {:5.0f} {:5.0f} {:5.0f} {:5.0f}"\
2377 .format("Sum ",Ysum[0],Ysum[1],Ysum[2],Ysum[3],Ysum[4],widthSum[0],widthSum[1],widthSum[2],widthSum[3],widthSum[4]))
2378
2379
2380 # Plot LDR histograms
2381 if (nQin > 0): PlotSubHist("Qin", aQin, Qin0, dQin, iQin, nQin)
2382 if (nVin > 0): PlotSubHist("Vin", aVin, Vin0, dVin, iVin, nVin)
2383 if (nRotL > 0): PlotSubHist("RotL", aRotL, RotL0, dRotL, iRotL, nRotL)
2384 if (nRetE > 0): PlotSubHist("RetE", aRetE, RetE0, dRetE, iRetE, nRetE)
2385 if (nRotE > 0): PlotSubHist("RotE", aRotE, RotE0, dRotE, iRotE, nRotE)
2386 if (nDiE > 0): PlotSubHist("DiE", aDiE, DiE0, dDiE, iDiE, nDiE)
2387 if (nRetO > 0): PlotSubHist("RetO", aRetO, RetO0, dRetO, iRetO, nRetO)
2388 if (nRotO > 0): PlotSubHist("RotO", aRotO, RotO0, dRotO, iRotO, nRotO)
2389 if (nDiO > 0): PlotSubHist("DiO", aDiO, DiO0, dDiO, iDiO, nDiO)
2390 if (nDiC > 0): PlotSubHist("DiC", aDiC, DiC0, dDiC, iDiC, nDiC)
2391 if (nRotC > 0): PlotSubHist("RotC", aRotC, RotC0, dRotC, iRotC, nRotC)
2392 if (nRetC > 0): PlotSubHist("RetC", aRetC, RetC0, dRetC, iRetC, nRetC)
2393 if (nTP > 0): PlotSubHist("TP", aTP, TP0, dTP, iTP, nTP)
2394 if (nTS > 0): PlotSubHist("TS", aTS, TS0, dTS, iTS, nTS)
2395 if (nRP > 0): PlotSubHist("RP", aRP, RP0, dRP, iRP, nRP)
2396 if (nRS > 0): PlotSubHist("RS", aRS, RS0, dRS, iRS, nRS)
2397 if (nRetT > 0): PlotSubHist("RetT", aRetT, RetT0, dRetT, iRetT, nRetT)
2398 if (nRetR > 0): PlotSubHist("RetR", aRetR, RetR0, dRetR, iRetR, nRetR)
2399 if (nERaT > 0): PlotSubHist("ERaT", aERaT, ERaT0, dERaT, iERaT, nERaT)
2400 if (nERaR > 0): PlotSubHist("ERaR", aERaR, ERaR0, dERaR, iERaR, nERaR)
2401 if (nRotaT > 0): PlotSubHist("RotaT", aRotaT, RotaT0, dRotaT, iRotaT, nRotaT)
2402 if (nRotaR > 0): PlotSubHist("RotaR", aRotaR, RotaR0, dRotaR, iRotaR, nRotaR)
2403 if (nLDRCal > 0): PlotSubHist("LDRCal", aLDRCal, LDRCal0, dLDRCal, iLDRCal, nLDRCal)
2404 if (nTCalT > 0): PlotSubHist("TCalT", aTCalT, TCalT0, dTCalT, iTCalT, nTCalT)
2405 if (nTCalR > 0): PlotSubHist("TCalR", aTCalR, TCalR0, dTCalR, iTCalR, nTCalR)
2406 if (nNCal > 0): PlotSubHist("CalNoiseTp", aNCalTp, 0, 1, iNCalTp, nNCal)
2407 if (nNCal > 0): PlotSubHist("CalNoiseTm", aNCalTm, 0, 1, iNCalTm, nNCal)
2408 if (nNCal > 0): PlotSubHist("CalNoiseRp", aNCalRp, 0, 1, iNCalRp, nNCal)
2409 if (nNCal > 0): PlotSubHist("CalNoiseRm", aNCalRm, 0, 1, iNCalRm, nNCal)
2410 if (nNI > 0): PlotSubHist("SigNoiseIt", aNIt, 0, 1, iNIt, nNI)
2411 if (nNI > 0): PlotSubHist("SigNoiseIr", aNIr, 0, 1, iNIr, nNI)
2412 plt.show()
2413 plt.close
2414
2415
2416
2417 # --- Plot LDRmin, LDRmax
2418 iLDR = -1
2419 for LDRTrue in LDRrange:
2420 iLDR = iLDR + 1
2421 LDRmin[iLDR] = np.amin(aLDRcorr[iLDR, :])
2422 LDRmax[iLDR] = np.amax(aLDRcorr[iLDR, :])
2423 LDRstd[iLDR] = np.std(aLDRcorr[iLDR, :])
2424 LDRmean[iLDR] = np.mean(aLDRcorr[iLDR, :])
2425 LDRmedian[iLDR] = np.median(aLDRcorr[iLDR, :])
2426 LDRskew[iLDR] = skew(aLDRcorr[iLDR, :],bias=False)
2427 LDRkurt[iLDR] = kurtosis(aLDRcorr[iLDR, :],fisher=True,bias=False)
2428
2429 fig2 = plt.figure()
2430 LDRrangeA = np.array(LDRrange)
2431 if((np.amax(LDRmax - LDRrangeA)-np.amin(LDRmin - LDRrangeA)) < 0.001):
2432 plt.ylim(-0.001,0.001)
2433 plt.plot(LDRrangeA, LDRmax - LDRrangeA, linewidth=2.0, color='b')
2434 plt.plot(LDRrangeA, LDRmin - LDRrangeA, linewidth=2.0, color='g')
2435
2436 plt.xlabel('LDRtrue', fontsize=18)
2437 plt.ylabel('LDRTrue-LDRmin, LDRTrue-LDRmax', fontsize=14)
2438 plt.title(LID + ' ' + str(Type[TypeC]) + ' ' + str(Loc[LocC]), fontsize=18)
2439 # plt.ylimit(-0.07, 0.07)
2440 plt.show()
2441 plt.close
2442
2443 # --- Save LDRmin, LDRmax to file
2444 # http://stackoverflow.com/questions/4675728/redirect-stdout-to-a-file-in-python
2445 with open('output_files\\' + OutputFile, 'a') as f:
2446 # with open('output_files\\' + LID + '-' + InputFile[0:-3] + '-LDR_min_max.dat', 'w') as f:
2447 with redirect_stdout(f):
2448 print("Lidar ID: " + LID)
2449 print()
2450 print("minimum and maximum values of the distributions of possibly measured LDR for different LDRtrue")
2451 print("LDRtrue , LDRmin, LDRmax")
2452 for i in range(len(LDRrangeA)):
2453 print("{0:7.4f},{1:7.4f},{2:7.4f}".format(LDRrangeA[i], LDRmin[i], LDRmax[i]))
2454 print()
2455 # Print LDR statistics
2456 print("LDRtrue , mean , median, max-mean, min-mean, std, excess_kurtosis, skewness")
2457 iLDR = -1
2458 LDRrangeA = np.array(LDRrange)
2459 for LDRTrue in LDRrange:
2460 iLDR = iLDR + 1
2461 print("{0:8.5f},{1:8.5f},{2:8.5f}, {3:8.5f},{4:8.5f},{5:8.5f}, {6:8.5f},{7:8.5f}"\
2462 .format(LDRrangeA[iLDR], LDRmean[iLDR], LDRmedian[iLDR], LDRmax[iLDR]-LDRrangeA[iLDR], \
2463 LDRmin[iLDR]-LDRrangeA[iLDR], LDRstd[iLDR], LDRkurt[iLDR], LDRskew[iLDR]))
2464 print()
2465 # Calculate and print statistics for calibration factors
2466 print("minimum and maximum values of the distributions of signal ratios and calibration factors for different LDRtrue")
2467 iLDR = -1
2468 LDRrangeA = np.array(LDRrange)
2469 print("LDRtrue , LDRsim, (max-min)/2, relerr")
2470 for LDRTrue in LDRrange:
2471 iLDR = iLDR + 1
2472 LDRsimmin[iLDR] = np.amin(aLDRsim[iLDR, :])
2473 LDRsimmax[iLDR] = np.amax(aLDRsim[iLDR, :])
2474 # LDRsimstd = np.std(aLDRsim[iLDR, :])
2475 LDRsimmean[iLDR] = np.mean(aLDRsim[iLDR, :])
2476 # LDRsimmedian = np.median(aLDRsim[iLDR, :])
2477 print("{0:8.5f}, {1:8.5f}, {2:8.5f}, {3:8.5f}".format(LDRrangeA[iLDR],LDRsimmean[iLDR],(LDRsimmax[iLDR]-LDRsimmin[iLDR])/2,(LDRsimmax[iLDR]-LDRsimmin[iLDR])/2/LDRsimmean[iLDR]))
2478 iLDR = -1
2479 print("LDRtrue , Etax , (max-min)/2, relerr")
2480 for LDRTrue in LDRrange:
2481 iLDR = iLDR + 1
2482 Etaxmin = np.amin(aEtax[iLDR, :])
2483 Etaxmax = np.amax(aEtax[iLDR, :])
2484 # Etaxstd = np.std(aEtax[iLDR, :])
2485 Etaxmean = np.mean(aEtax[iLDR, :])
2486 # Etaxmedian = np.median(aEtax[iLDR, :])
2487 print("{0:8.5f}, {1:8.5f}, {2:8.5f}, {3:8.5f}".format(LDRrangeA[iLDR], Etaxmean, (Etaxmax-Etaxmin)/2, (Etaxmax-Etaxmin)/2/Etaxmean))
2488 iLDR = -1
2489 print("LDRtrue , Etapx , (max-min)/2, relerr")
2490 for LDRTrue in LDRrange:
2491 iLDR = iLDR + 1
2492 Etapxmin = np.amin(aEtapx[iLDR, :])
2493 Etapxmax = np.amax(aEtapx[iLDR, :])
2494 # Etapxstd = np.std(aEtapx[iLDR, :])
2495 Etapxmean = np.mean(aEtapx[iLDR, :])
2496 # Etapxmedian = np.median(aEtapx[iLDR, :])
2497 print("{0:8.5f}, {1:8.5f}, {2:8.5f}, {3:8.5f}".format(LDRrangeA[iLDR], Etapxmean, (Etapxmax-Etapxmin)/2, (Etapxmax-Etapxmin)/2/Etapxmean))
2498 iLDR = -1
2499 print("LDRtrue , Etamx , (max-min)/2, relerr")
2500 for LDRTrue in LDRrange:
2501 iLDR = iLDR + 1
2502 Etamxmin = np.amin(aEtamx[iLDR, :])
2503 Etamxmax = np.amax(aEtamx[iLDR, :])
2504 # Etamxstd = np.std(aEtamx[iLDR, :])
2505 Etamxmean = np.mean(aEtamx[iLDR, :])
2506 # Etamxmedian = np.median(aEtamx[iLDR, :])
2507 print("{0:8.5f}, {1:8.5f}, {2:8.5f}, {3:8.5f}".format(LDRrangeA[iLDR], Etamxmean, (Etamxmax-Etamxmin)/2, (Etamxmax-Etamxmin)/2/Etamxmean))
2508
2509 # Print LDR statistics
2510 print("LDRtrue , mean , median, max-mean, min-mean, std, excess_kurtosis, skewness")
2511 iLDR = -1
2512 LDRrangeA = np.array(LDRrange)
2513 for LDRTrue in LDRrange:
2514 iLDR = iLDR + 1
2515 print("{0:8.5f},{1:8.5f},{2:8.5f}, {3:8.5f},{4:8.5f},{5:8.5f}, {6:8.5f},{7:8.5f}".format(LDRrangeA[iLDR], LDRmean[iLDR], LDRmedian[iLDR], LDRmax[iLDR]-LDRrangeA[iLDR], LDRmin[iLDR]-LDRrangeA[iLDR], LDRstd[iLDR],LDRkurt[iLDR],LDRskew[iLDR]))
2516
2517
2518 with open('output_files\\' + OutputFile, 'a') as f:
2519 # with open('output_files\\' + LID + '-' + InputFile[0:-3] + '-LDR_min_max.dat', 'a') as f:
2520 with redirect_stdout(f):
2521 Contribution_aY("LDRCorr", aLDRcorr)
2522 Contribution_aY("LDRsim", aLDRsim)
2523 Contribution_aY("EtaX, D90", aEtax)
2524 Contribution_aY("Etapx, +45°", aEtapx)
2525 Contribution_aY("Etamx -45°", aEtamx)
2526
2527
2528 # Plot other histograms
2529 if (bPlotEtax):
2530
2531 if (nQin > 0): PlotLDRsim("Qin", aQin, Qin0, dQin, iQin, nQin)
2532 if (nVin > 0): PlotLDRsim("Vin", aVin, Vin0, dVin, iVin, nVin)
2533 if (nRotL > 0): PlotLDRsim("RotL", aRotL, RotL0, dRotL, iRotL, nRotL)
2534 if (nRetE > 0): PlotLDRsim("RetE", aRetE, RetE0, dRetE, iRetE, nRetE)
2535 if (nRotE > 0): PlotLDRsim("RotE", aRotE, RotE0, dRotE, iRotE, nRotE)
2536 if (nDiE > 0): PlotLDRsim("DiE", aDiE, DiE0, dDiE, iDiE, nDiE)
2537 if (nRetO > 0): PlotLDRsim("RetO", aRetO, RetO0, dRetO, iRetO, nRetO)
2538 if (nRotO > 0): PlotLDRsim("RotO", aRotO, RotO0, dRotO, iRotO, nRotO)
2539 if (nDiO > 0): PlotLDRsim("DiO", aDiO, DiO0, dDiO, iDiO, nDiO)
2540 if (nDiC > 0): PlotLDRsim("DiC", aDiC, DiC0, dDiC, iDiC, nDiC)
2541 if (nRotC > 0): PlotLDRsim("RotC", aRotC, RotC0, dRotC, iRotC, nRotC)
2542 if (nRetC > 0): PlotLDRsim("RetC", aRetC, RetC0, dRetC, iRetC, nRetC)
2543 if (nTP > 0): PlotLDRsim("TP", aTP, TP0, dTP, iTP, nTP)
2544 if (nTS > 0): PlotLDRsim("TS", aTS, TS0, dTS, iTS, nTS)
2545 if (nRP > 0): PlotLDRsim("RP", aRP, RP0, dRP, iRP, nRP)
2546 if (nRS > 0): PlotLDRsim("RS", aRS, RS0, dRS, iRS, nRS)
2547 if (nRetT > 0): PlotLDRsim("RetT", aRetT, RetT0, dRetT, iRetT, nRetT)
2548 if (nRetR > 0): PlotLDRsim("RetR", aRetR, RetR0, dRetR, iRetR, nRetR)
2549 if (nERaT > 0): PlotLDRsim("ERaT", aERaT, ERaT0, dERaT, iERaT, nERaT)
2550 if (nERaR > 0): PlotLDRsim("ERaR", aERaR, ERaR0, dERaR, iERaR, nERaR)
2551 if (nRotaT > 0): PlotLDRsim("RotaT", aRotaT, RotaT0, dRotaT, iRotaT, nRotaT)
2552 if (nRotaR > 0): PlotLDRsim("RotaR", aRotaR, RotaR0, dRotaR, iRotaR, nRotaR)
2553 if (nLDRCal > 0): PlotLDRsim("LDRCal", aLDRCal, LDRCal0, dLDRCal, iLDRCal, nLDRCal)
2554 if (nTCalT > 0): PlotLDRsim("TCalT", aTCalT, TCalT0, dTCalT, iTCalT, nTCalT)
2555 if (nTCalR > 0): PlotLDRsim("TCalR", aTCalR, TCalR0, dTCalR, iTCalR, nTCalR)
2556 if (nNCal > 0): PlotLDRsim("CalNoiseTp", aNCalTp, 0, 1, iNCalTp, nNCal)
2557 if (nNCal > 0): PlotLDRsim("CalNoiseTm", aNCalTm, 0, 1, iNCalTm, nNCal)
2558 if (nNCal > 0): PlotLDRsim("CalNoiseRp", aNCalRp, 0, 1, iNCalRp, nNCal)
2559 if (nNCal > 0): PlotLDRsim("CalNoiseRm", aNCalRm, 0, 1, iNCalRm, nNCal)
2560 if (nNI > 0): PlotLDRsim("SigNoiseIt", aNIt, 0, 1, iNIt, nNI)
2561 if (nNI > 0): PlotLDRsim("SigNoiseIr", aNIr, 0, 1, iNIr, nNI)
2562 plt.show()
2563 plt.close
2564 print("---------------------------------------...producing more plots...------------------------------------------------------------------")
2565
2566 if (nQin > 0): PlotEtax("Qin", aQin, Qin0, dQin, iQin, nQin)
2567 if (nVin > 0): PlotEtax("Vin", aVin, Vin0, dVin, iVin, nVin)
2568 if (nRotL > 0): PlotEtax("RotL", aRotL, RotL0, dRotL, iRotL, nRotL)
2569 if (nRetE > 0): PlotEtax("RetE", aRetE, RetE0, dRetE, iRetE, nRetE)
2570 if (nRotE > 0): PlotEtax("RotE", aRotE, RotE0, dRotE, iRotE, nRotE)
2571 if (nDiE > 0): PlotEtax("DiE", aDiE, DiE0, dDiE, iDiE, nDiE)
2572 if (nRetO > 0): PlotEtax("RetO", aRetO, RetO0, dRetO, iRetO, nRetO)
2573 if (nRotO > 0): PlotEtax("RotO", aRotO, RotO0, dRotO, iRotO, nRotO)
2574 if (nDiO > 0): PlotEtax("DiO", aDiO, DiO0, dDiO, iDiO, nDiO)
2575 if (nDiC > 0): PlotEtax("DiC", aDiC, DiC0, dDiC, iDiC, nDiC)
2576 if (nRotC > 0): PlotEtax("RotC", aRotC, RotC0, dRotC, iRotC, nRotC)
2577 if (nRetC > 0): PlotEtax("RetC", aRetC, RetC0, dRetC, iRetC, nRetC)
2578 if (nTP > 0): PlotEtax("TP", aTP, TP0, dTP, iTP, nTP)
2579 if (nTS > 0): PlotEtax("TS", aTS, TS0, dTS, iTS, nTS)
2580 if (nRP > 0): PlotEtax("RP", aRP, RP0, dRP, iRP, nRP)
2581 if (nRS > 0): PlotEtax("RS", aRS, RS0, dRS, iRS, nRS)
2582 if (nRetT > 0): PlotEtax("RetT", aRetT, RetT0, dRetT, iRetT, nRetT)
2583 if (nRetR > 0): PlotEtax("RetR", aRetR, RetR0, dRetR, iRetR, nRetR)
2584 if (nERaT > 0): PlotEtax("ERaT", aERaT, ERaT0, dERaT, iERaT, nERaT)
2585 if (nERaR > 0): PlotEtax("ERaR", aERaR, ERaR0, dERaR, iERaR, nERaR)
2586 if (nRotaT > 0): PlotEtax("RotaT", aRotaT, RotaT0, dRotaT, iRotaT, nRotaT)
2587 if (nRotaR > 0): PlotEtax("RotaR", aRotaR, RotaR0, dRotaR, iRotaR, nRotaR)
2588 if (nLDRCal > 0): PlotEtax("LDRCal", aLDRCal, LDRCal0, dLDRCal, iLDRCal, nLDRCal)
2589 if (nTCalT > 0): PlotEtax("TCalT", aTCalT, TCalT0, dTCalT, iTCalT, nTCalT)
2590 if (nTCalR > 0): PlotEtax("TCalR", aTCalR, TCalR0, dTCalR, iTCalR, nTCalR)
2591 if (nNCal > 0): PlotEtax("CalNoiseTp", aNCalTp, 0, 1, iNCalTp, nNCal)
2592 if (nNCal > 0): PlotEtax("CalNoiseTm", aNCalTm, 0, 1, iNCalTm, nNCal)
2593 if (nNCal > 0): PlotEtax("CalNoiseRp", aNCalRp, 0, 1, iNCalRp, nNCal)
2594 if (nNCal > 0): PlotEtax("CalNoiseRm", aNCalRm, 0, 1, iNCalRm, nNCal)
2595 if (nNI > 0): PlotEtax("SigNoiseIt", aNIt, 0, 1, iNIt, nNI)
2596 if (nNI > 0): PlotEtax("SigNoiseIr", aNIr, 0, 1, iNIr, nNI)
2597 plt.show()
2598 plt.close
2599 print("---------------------------------------...producing more plots...------------------------------------------------------------------")
2600
2601 if (nQin > 0): PlotEtapx("Qin", aQin, Qin0, dQin, iQin, nQin)
2602 if (nVin > 0): PlotEtapx("Vin", aVin, Vin0, dVin, iVin, nVin)
2603 if (nRotL > 0): PlotEtapx("RotL", aRotL, RotL0, dRotL, iRotL, nRotL)
2604 if (nRetE > 0): PlotEtapx("RetE", aRetE, RetE0, dRetE, iRetE, nRetE)
2605 if (nRotE > 0): PlotEtapx("RotE", aRotE, RotE0, dRotE, iRotE, nRotE)
2606 if (nDiE > 0): PlotEtapx("DiE", aDiE, DiE0, dDiE, iDiE, nDiE)
2607 if (nRetO > 0): PlotEtapx("RetO", aRetO, RetO0, dRetO, iRetO, nRetO)
2608 if (nRotO > 0): PlotEtapx("RotO", aRotO, RotO0, dRotO, iRotO, nRotO)
2609 if (nDiO > 0): PlotEtapx("DiO", aDiO, DiO0, dDiO, iDiO, nDiO)
2610 if (nDiC > 0): PlotEtapx("DiC", aDiC, DiC0, dDiC, iDiC, nDiC)
2611 if (nRotC > 0): PlotEtapx("RotC", aRotC, RotC0, dRotC, iRotC, nRotC)
2612 if (nRetC > 0): PlotEtapx("RetC", aRetC, RetC0, dRetC, iRetC, nRetC)
2613 if (nTP > 0): PlotEtapx("TP", aTP, TP0, dTP, iTP, nTP)
2614 if (nTS > 0): PlotEtapx("TS", aTS, TS0, dTS, iTS, nTS)
2615 if (nRP > 0): PlotEtapx("RP", aRP, RP0, dRP, iRP, nRP)
2616 if (nRS > 0): PlotEtapx("RS", aRS, RS0, dRS, iRS, nRS)
2617 if (nRetT > 0): PlotEtapx("RetT", aRetT, RetT0, dRetT, iRetT, nRetT)
2618 if (nRetR > 0): PlotEtapx("RetR", aRetR, RetR0, dRetR, iRetR, nRetR)
2619 if (nERaT > 0): PlotEtapx("ERaT", aERaT, ERaT0, dERaT, iERaT, nERaT)
2620 if (nERaR > 0): PlotEtapx("ERaR", aERaR, ERaR0, dERaR, iERaR, nERaR)
2621 if (nRotaT > 0): PlotEtapx("RotaT", aRotaT, RotaT0, dRotaT, iRotaT, nRotaT)
2622 if (nRotaR > 0): PlotEtapx("RotaR", aRotaR, RotaR0, dRotaR, iRotaR, nRotaR)
2623 if (nLDRCal > 0): PlotEtapx("LDRCal", aLDRCal, LDRCal0, dLDRCal, iLDRCal, nLDRCal)
2624 if (nTCalT > 0): PlotEtapx("TCalT", aTCalT, TCalT0, dTCalT, iTCalT, nTCalT)
2625 if (nTCalR > 0): PlotEtapx("TCalR", aTCalR, TCalR0, dTCalR, iTCalR, nTCalR)
2626 if (nNCal > 0): PlotEtapx("CalNoiseTp", aNCalTp, 0, 1, iNCalTp, nNCal)
2627 if (nNCal > 0): PlotEtapx("CalNoiseTm", aNCalTm, 0, 1, iNCalTm, nNCal)
2628 if (nNCal > 0): PlotEtapx("CalNoiseRp", aNCalRp, 0, 1, iNCalRp, nNCal)
2629 if (nNCal > 0): PlotEtapx("CalNoiseRm", aNCalRm, 0, 1, iNCalRm, nNCal)
2630 if (nNI > 0): PlotEtapx("SigNoiseIt", aNIt, 0, 1, iNIt, nNI)
2631 if (nNI > 0): PlotEtapx("SigNoiseIr", aNIr, 0, 1, iNIr, nNI)
2632 plt.show()
2633 plt.close
2634 print("---------------------------------------...producing more plots...------------------------------------------------------------------")
2635
2636 if (nQin > 0): PlotEtamx("Qin", aQin, Qin0, dQin, iQin, nQin)
2637 if (nVin > 0): PlotEtamx("Vin", aVin, Vin0, dVin, iVin, nVin)
2638 if (nRotL > 0): PlotEtamx("RotL", aRotL, RotL0, dRotL, iRotL, nRotL)
2639 if (nRetE > 0): PlotEtamx("RetE", aRetE, RetE0, dRetE, iRetE, nRetE)
2640 if (nRotE > 0): PlotEtamx("RotE", aRotE, RotE0, dRotE, iRotE, nRotE)
2641 if (nDiE > 0): PlotEtamx("DiE", aDiE, DiE0, dDiE, iDiE, nDiE)
2642 if (nRetO > 0): PlotEtamx("RetO", aRetO, RetO0, dRetO, iRetO, nRetO)
2643 if (nRotO > 0): PlotEtamx("RotO", aRotO, RotO0, dRotO, iRotO, nRotO)
2644 if (nDiO > 0): PlotEtamx("DiO", aDiO, DiO0, dDiO, iDiO, nDiO)
2645 if (nDiC > 0): PlotEtamx("DiC", aDiC, DiC0, dDiC, iDiC, nDiC)
2646 if (nRotC > 0): PlotEtamx("RotC", aRotC, RotC0, dRotC, iRotC, nRotC)
2647 if (nRetC > 0): PlotEtamx("RetC", aRetC, RetC0, dRetC, iRetC, nRetC)
2648 if (nTP > 0): PlotEtamx("TP", aTP, TP0, dTP, iTP, nTP)
2649 if (nTS > 0): PlotEtamx("TS", aTS, TS0, dTS, iTS, nTS)
2650 if (nRP > 0): PlotEtamx("RP", aRP, RP0, dRP, iRP, nRP)
2651 if (nRS > 0): PlotEtamx("RS", aRS, RS0, dRS, iRS, nRS)
2652 if (nRetT > 0): PlotEtamx("RetT", aRetT, RetT0, dRetT, iRetT, nRetT)
2653 if (nRetR > 0): PlotEtamx("RetR", aRetR, RetR0, dRetR, iRetR, nRetR)
2654 if (nERaT > 0): PlotEtamx("ERaT", aERaT, ERaT0, dERaT, iERaT, nERaT)
2655 if (nERaR > 0): PlotEtamx("ERaR", aERaR, ERaR0, dERaR, iERaR, nERaR)
2656 if (nRotaT > 0): PlotEtamx("RotaT", aRotaT, RotaT0, dRotaT, iRotaT, nRotaT)
2657 if (nRotaR > 0): PlotEtamx("RotaR", aRotaR, RotaR0, dRotaR, iRotaR, nRotaR)
2658 if (nLDRCal > 0): PlotEtamx("LDRCal", aLDRCal, LDRCal0, dLDRCal, iLDRCal, nLDRCal)
2659 if (nTCalT > 0): PlotEtamx("TCalT", aTCalT, TCalT0, dTCalT, iTCalT, nTCalT)
2660 if (nTCalR > 0): PlotEtamx("TCalR", aTCalR, TCalR0, dTCalR, iTCalR, nTCalR)
2661 if (nNCal > 0): PlotEtamx("CalNoiseTp", aNCalTp, 0, 1, iNCalTp, nNCal)
2662 if (nNCal > 0): PlotEtamx("CalNoiseTm", aNCalTm, 0, 1, iNCalTm, nNCal)
2663 if (nNCal > 0): PlotEtamx("CalNoiseRp", aNCalRp, 0, 1, iNCalRp, nNCal)
2664 if (nNCal > 0): PlotEtamx("CalNoiseRm", aNCalRm, 0, 1, iNCalRm, nNCal)
2665 if (nNI > 0): PlotEtamx("SigNoiseIt", aNIt, 0, 1, iNIt, nNI)
2666 if (nNI > 0): PlotEtamx("SigNoiseIr", aNIr, 0, 1, iNIr, nNI)
2667 plt.show()
2668 plt.close
2669
2670 # Print Etax statistics
2671 Etaxmin = np.amin(aEtax[1, :])
2672 Etaxmax = np.amax(aEtax[1, :])
2673 Etaxstd = np.std(aEtax[1, :])
2674 Etaxmean = np.mean(aEtax[1, :])
2675 Etaxmedian = np.median(aEtax[1, :])
2676 print("Etax , max-mean, min-mean, median, mean ± std, eta")
2677 print("{0:8.5f} ±({1:8.5f},{2:8.5f}),{3:8.5f},{4:8.5f}±{5:8.5f},{6:8.5f}".format(Etax0, Etaxmax-Etax0, Etaxmin-Etax0, Etaxmedian, Etaxmean, Etaxstd, Etax0 / K0))
2678 print()
2679
2680 # Calculate and print statistics for calibration factors
2681 iLDR = -1
2682 LDRrangeA = np.array(LDRrange)
2683 print("LDR...., LDRsim, (max-min)/2, relerr")
2684 for LDRTrue in LDRrange:
2685 iLDR = iLDR + 1
2686 LDRsimmin[iLDR] = np.amin(aLDRsim[iLDR, :])
2687 LDRsimmax[iLDR] = np.amax(aLDRsim[iLDR, :])
2688 # LDRsimstd = np.std(aLDRsim[iLDR, :])
2689 LDRsimmean[iLDR] = np.mean(aLDRsim[iLDR, :])
2690 # LDRsimmedian = np.median(aLDRsim[iLDR, :])
2691 print("{0:8.5f}, {1:8.5f}, {2:8.5f}, {3:8.5f}".format(LDRrangeA[iLDR], LDRsimmean[iLDR], (LDRsimmax[iLDR]-LDRsimmin[iLDR])/2, (LDRsimmax[iLDR]-LDRsimmin[iLDR])/2/LDRsimmean[iLDR]))
2692 iLDR = -1
2693 print("LDR...., Etax , (max-min)/2, relerr")
2694 for LDRTrue in LDRrange:
2695 iLDR = iLDR + 1
2696 Etaxmin = np.amin(aEtax[iLDR, :])
2697 Etaxmax = np.amax(aEtax[iLDR, :])
2698 # Etaxstd = np.std(aEtax[iLDR, :])
2699 Etaxmean = np.mean(aEtax[iLDR, :])
2700 # Etaxmedian = np.median(aEtax[iLDR, :])
2701 print("{0:8.5f}, {1:8.5f}, {2:8.5f}, {3:8.5f}".format(LDRrangeA[iLDR], Etaxmean, (Etaxmax-Etaxmin)/2, (Etaxmax-Etaxmin)/2/Etaxmean))
2702 iLDR = -1
2703 print("LDR...., Etapx , (max-min)/2, relerr")
2704 for LDRTrue in LDRrange:
2705 iLDR = iLDR + 1
2706 Etapxmin = np.amin(aEtapx[iLDR, :])
2707 Etapxmax = np.amax(aEtapx[iLDR, :])
2708 # Etapxstd = np.std(aEtapx[iLDR, :])
2709 Etapxmean = np.mean(aEtapx[iLDR, :])
2710 # Etapxmedian = np.median(aEtapx[iLDR, :])
2711 print("{0:8.5f}, {1:8.5f}, {2:8.5f}, {3:8.5f}".format(LDRrangeA[iLDR], Etapxmean, (Etapxmax-Etapxmin)/2, (Etapxmax-Etapxmin)/2/Etapxmean))
2712 iLDR = -1
2713 print("LDR...., Etamx , (max-min)/2, relerr")
2714 for LDRTrue in LDRrange:
2715 iLDR = iLDR + 1
2716 Etamxmin = np.amin(aEtamx[iLDR, :])
2717 Etamxmax = np.amax(aEtamx[iLDR, :])
2718 # Etamxstd = np.std(aEtamx[iLDR, :])
2719 Etamxmean = np.mean(aEtamx[iLDR, :])
2720 # Etamxmedian = np.median(aEtamx[iLDR, :])
2721 print("{0:8.5f}, {1:8.5f}, {2:8.5f}, {3:8.5f}".format(LDRrangeA[iLDR], Etamxmean, (Etamxmax-Etamxmin)/2, (Etamxmax-Etamxmin)/2/Etamxmean))
2722
2723 f.close()
2724
2725
2726 '''
2727 # --- Plot F11 histograms
2728 print()
2729 print(" ############################################################################## ")
2730 print(Text1)
2731 print()
2732
2733 iLDR = 5
2734 for LDRTrue in LDRrange:
2735 iLDR = iLDR - 1
2736 #aF11corr[iLDR,:] = aF11corr[iLDR,:] / aF11corr[0,:] - 1.0
2737 aF11corr[iLDR,:] = aF11corr[iLDR,:] / aF11sim0[iLDR] - 1.0
2738 # Plot F11
2739 def PlotSubHistF11(aVar, aX, X0, daX, iaX, naX):
2740 fig, ax = plt.subplots(nrows=1, ncols=5, sharex=True, sharey=True, figsize=(25, 2))
2741 iLDR = -1
2742 for LDRTrue in LDRrange:
2743 iLDR = iLDR + 1
2744
2745 #F11min[iLDR] = np.min(aF11corr[iLDR,:])
2746 #F11max[iLDR] = np.max(aF11corr[iLDR,:])
2747 #Rmin = F11min[iLDR] * 0.995 # np.min(aLDRcorr[iLDR,:]) * 0.995
2748 #Rmax = F11max[iLDR] * 1.005 # np.max(aLDRcorr[iLDR,:]) * 1.005
2749
2750 #Rmin = 0.8
2751 #Rmax = 1.2
2752
2753 #plt.subplot(5,2,iLDR+1)
2754 plt.subplot(1,5,iLDR+1)
2755 (n, bins, patches) = plt.hist(aF11corr[iLDR,:],
2756 bins=100, log=False,
2757 alpha=0.5, density=False, color = '0.5', histtype='stepfilled')
2758
2759 for iaX in range(-naX,naX+1):
2760 plt.hist(aF11corr[iLDR,aX == iaX],
2761 bins=100, log=False, alpha=0.3, density=False, histtype='stepfilled', label = str(round(X0 + iaX*daX/naX,5)))
2762
2763 if (iLDR == 2): plt.legend()
2764
2765 plt.tick_params(axis='both', labelsize=9)
2766 #plt.plot([LDRTrue, LDRTrue], [0, np.max(n)], 'r-', lw=2)
2767
2768 #plt.title(LID + ' ' + aVar, fontsize=18)
2769 #plt.ylabel('frequency', fontsize=10)
2770 #plt.xlabel('LDRCorr', fontsize=10)
2771 #fig.tight_layout()
2772 fig.suptitle(LID + ' ' + str(Type[TypeC]) + ' ' + str(Loc[LocC]) + ' - ' + aVar, fontsize=14, y=1.05)
2773 #plt.show()
2774 #fig.savefig(LID + '_' + aVar + '.png', dpi=150, bbox_inches='tight', pad_inches=0)
2775 #plt.close
2776 return
2777
2778 if (nQin > 0): PlotSubHistF11("Qin", aQin, Qin0, dQin, iQin, nQin)
2779 if (nVin > 0): PlotSubHistF11("Vin", aVin, Vin0, dVin, iVin, nVin)
2780 if (nRotL > 0): PlotSubHistF11("RotL", aRotL, RotL0, dRotL, iRotL, nRotL)
2781 if (nRetE > 0): PlotSubHistF11("RetE", aRetE, RetE0, dRetE, iRetE, nRetE)
2782 if (nRotE > 0): PlotSubHistF11("RotE", aRotE, RotE0, dRotE, iRotE, nRotE)
2783 if (nDiE > 0): PlotSubHistF11("DiE", aDiE, DiE0, dDiE, iDiE, nDiE)
2784 if (nRetO > 0): PlotSubHistF11("RetO", aRetO, RetO0, dRetO, iRetO, nRetO)
2785 if (nRotO > 0): PlotSubHistF11("RotO", aRotO, RotO0, dRotO, iRotO, nRotO)
2786 if (nDiO > 0): PlotSubHistF11("DiO", aDiO, DiO0, dDiO, iDiO, nDiO)
2787 if (nDiC > 0): PlotSubHistF11("DiC", aDiC, DiC0, dDiC, iDiC, nDiC)
2788 if (nRotC > 0): PlotSubHistF11("RotC", aRotC, RotC0, dRotC, iRotC, nRotC)
2789 if (nRetC > 0): PlotSubHistF11("RetC", aRetC, RetC0, dRetC, iRetC, nRetC)
2790 if (nTP > 0): PlotSubHistF11("TP", aTP, TP0, dTP, iTP, nTP)
2791 if (nTS > 0): PlotSubHistF11("TS", aTS, TS0, dTS, iTS, nTS)
2792 if (nRP > 0): PlotSubHistF11("RP", aRP, RP0, dRP, iRP, nRP)
2793 if (nRS > 0): PlotSubHistF11("RS", aRS, RS0, dRS, iRS, nRS)
2794 if (nRetT > 0): PlotSubHistF11("RetT", aRetT, RetT0, dRetT, iRetT, nRetT)
2795 if (nRetR > 0): PlotSubHistF11("RetR", aRetR, RetR0, dRetR, iRetR, nRetR)
2796 if (nERaT > 0): PlotSubHistF11("ERaT", aERaT, ERaT0, dERaT, iERaT, nERaT)
2797 if (nERaR > 0): PlotSubHistF11("ERaR", aERaR, ERaR0, dERaR, iERaR, nERaR)
2798 if (nRotaT > 0): PlotSubHistF11("RotaT", aRotaT, RotaT0, dRotaT, iRotaT, nRotaT)
2799 if (nRotaR > 0): PlotSubHistF11("RotaR", aRotaR, RotaR0, dRotaR, iRotaR, nRotaR)
2800 if (nLDRCal > 0): PlotSubHistF11("LDRCal", aLDRCal, LDRCal0, dLDRCal, iLDRCal, nLDRCal)
2801 if (nTCalT > 0): PlotSubHistF11("TCalT", aTCalT, TCalT0, dTCalT, iTCalT, nTCalT)
2802 if (nTCalR > 0): PlotSubHistF11("TCalR", aTCalR, TCalR0, dTCalR, iTCalR, nTCalR)
2803 if (nNCal > 0): PlotSubHistF11("CalNoise", aNCal, 0, 1/nNCal, iNCal, nNCal)
2804 if (nNI > 0): PlotSubHistF11("SigNoise", aNI, 0, 1/nNI, iNI, nNI)
2805
2806
2807 plt.show()
2808 plt.close
2809
2810 '''
2811 '''
2812 # only histogram
2813 #print("******************* " + aVar + " *******************")
2814 fig, ax = plt.subplots(nrows=5, ncols=2, sharex=True, sharey=True, figsize=(10, 10))
2815 iLDR = -1
2816 for LDRTrue in LDRrange:
2817 iLDR = iLDR + 1
2818 LDRmin[iLDR] = np.min(aLDRcorr[iLDR,:])
2819 LDRmax[iLDR] = np.max(aLDRcorr[iLDR,:])
2820 Rmin = np.min(aLDRcorr[iLDR,:]) * 0.999
2821 Rmax = np.max(aLDRcorr[iLDR,:]) * 1.001
2822 plt.subplot(5,2,iLDR+1)
2823 (n, bins, patches) = plt.hist(aLDRcorr[iLDR,:],
2824 range=[Rmin, Rmax],
2825 bins=200, log=False, alpha=0.2, density=False, color = '0.5', histtype='stepfilled')
2826 plt.tick_params(axis='both', labelsize=9)
2827 plt.plot([LDRTrue, LDRTrue], [0, np.max(n)], 'r-', lw=2)
2828 plt.show()
2829 plt.close
2830 # --- End of Plot F11 histograms
2831 '''
2832
2833
2834 '''
2835 # --- Plot K over LDRCal
2836 fig3 = plt.figure()
2837 plt.plot(LDRCal0+aLDRCal*dLDRCal/nLDRCal,aGHK[4,:], linewidth=2.0, color='b')
2838
2839 plt.xlabel('LDRCal', fontsize=18)
2840 plt.ylabel('K', fontsize=14)
2841 plt.title(LID, fontsize=18)
2842 plt.show()
2843 plt.close
2844 '''
2845
2846 # Additional plot routines ======>
2847 '''
2848 #******************************************************************************
2849 # 1. Plot LDRCorrected - LDR(measured Icross/Iparallel)
2850 LDRa = np.arange(1.,100.)*0.005
2851 LDRCorra = np.arange(1.,100.)
2852 if Y == - 1.: LDRa = 1./LDRa
2853 LDRCorra = (1./Eta*LDRa*(GT+HT)-(GR+HR))/((GR-HR)-1./Eta*LDRa*(GT-HT))
2854 if Y == - 1.: LDRa = 1./LDRa
2855 #
2856 #fig = plt.figure()
2857 plt.plot(LDRa,LDRCorra-LDRa)
2858 plt.plot([0.,0.5],[0.,0.5])
2859 plt.suptitle('LDRCorrected - LDR(measured Icross/Iparallel)', fontsize=16)
2860 plt.xlabel('LDR', fontsize=18)
2861 plt.ylabel('LDRCorr - LDR', fontsize=16)
2862 #plt.savefig('test.png')
2863 #
2864 '''
2865 '''
2866 #******************************************************************************
2867 # 2. Plot LDRsim (simulated measurements without corrections = Icross/Iparallel) over LDRtrue
2868 LDRa = np.arange(1.,100.)*0.005
2869 LDRsima = np.arange(1.,100.)
2870
2871 atruea = (1.-LDRa)/(1+LDRa)
2872 Ita = TiT*TiO*IinL*(GT+atruea*HT)
2873 Ira = TiR*TiO*IinL*(GR+atruea*HR)
2874 LDRsima = Ira/Ita # simulated uncorrected LDR with Y from input file
2875 if Y == -1.: LDRsima = 1./LDRsima
2876 #
2877 #fig = plt.figure()
2878 plt.plot(LDRa,LDRsima)
2879 plt.plot([0.,0.5],[0.,0.5])
2880 plt.suptitle('LDRsim (simulated measurements without corrections = Icross/Iparallel) over LDRtrue', fontsize=10)
2881 plt.xlabel('LDRtrue', fontsize=18)
2882 plt.ylabel('LDRsim', fontsize=16)
2883 #plt.savefig('test.png')
2884 #
2885 '''

mercurial