GHK_0.9.8h_Py3.7.py

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

mercurial