@@ -171,6 +171,22 @@ def calc_mean(itr: Tuple[int, int], scan: Scan, xgm_data: xr.DataArray, tof: Dic
171171
172172 return out_data , out_xgm
173173
174+ def angular_dist (theta , beta , P1 , tilt ):
175+ """Electron angular distribution with Stokes parameter.
176+
177+ Args:
178+ theta: Emission angle
179+ beta: Beta parameter -1 < β < 2
180+ P1: First Stoke's parameter
181+ tilt: Tilt angle
182+
183+ Returns:
184+ Differential cross section dσ/dϑ
185+
186+ """
187+
188+ return (1 + (beta / 4 ) * (1 + 3 * P1 * np .cos (2 * (theta - tilt ))))
189+
174190class CookieboxCalibration (SerializableMixin ):
175191 """
176192 Calibrate a set of eTOFs read out using an ADQ digitizer device.
@@ -301,6 +317,14 @@ class CookieboxCalibration(SerializableMixin):
301317 Use `None` to guess it.
302318 stop_roi: End of the RoI, relative to the `first_pulse_offset`. Use `None` to guess it.
303319 parallel: Whether to average the input data in parallel.
320+ beta: Beta parameter.
321+ For l=0 electrons, set to 2 for linear polarization, 0 to circular polarization.
322+ tilt: Tilt angle for linear or elliptical polarization.
323+ It is assumed eTOF 0 makes an angle of 0 deg and therefore, the tilt
324+ refers to that angle. Under such assumption, set to 0 for horizontal polarization,
325+ or np.pi/2 for vertical linear polarization, if eTOF 0 is aligned
326+ to the horizontal plane.
327+ P1: First Stokes parameter. Set to 1 for linear or circular polarization.
304328 """
305329 def __init__ (self ,
306330 xgm_threshold : Union [str , float ]= 'median' ,
@@ -309,11 +333,17 @@ def __init__(self,
309333 stop_roi : Optional [int ]= None ,
310334 interleaved : Optional [bool ]= None ,
311335 parallel : bool = True ,
336+ beta : float = 2.0 ,
337+ tilt : float = 0.0 ,
338+ P1 : float = 1.0
312339 ):
313340 self ._init_auger_start_roi = auger_start_roi
314341 self ._init_start_roi = start_roi
315342 self ._init_stop_roi = stop_roi
316343 self .parallel = parallel
344+ self .beta = beta
345+ self .tilt = tilt
346+ self .P1 = P1
317347
318348 self ._xgm_threshold = xgm_threshold
319349
@@ -350,6 +380,9 @@ def __init__(self,
350380 "calibration_energies" ,
351381 "_tof_response" ,
352382 "parallel" ,
383+ "beta" ,
384+ "tilt" ,
385+ "P1" ,
353386 "_version" ,
354387 ]
355388 def _asdict (self ):
@@ -855,10 +888,21 @@ def calculate_calibration_and_transmission(self, tof_id: int):
855888 ee ,
856889 eo )
857890
858- # interpolate amplitude as given by the
859- # Auger+Valence (related to the cross section and pulse intensity)
860- # normalized by the XGM mean intensity
861- en = self .tof_fit_result [tof_id ].Aa [mask ][eidx ]/ self .calibration_mean_xgm [tof_id ][mask ][eidx ]
891+ # Transmission = (detected intensity in photoelectron)/(produced intensity)
892+ # Transmission = (detected ADU in photoelectron)/((pulse energy) (Auger-Meitner ADU) (dsigma/dtheta))
893+ # dsigma/dtheta = 1/2*(1.0 + beta*(3*cos(theta)^2 - 1.0)/2.0)
894+ theta = (2 * np .pi / 16 )* tof_id
895+ beta = self .beta
896+ tilt = self .tilt
897+ P1 = self .P1
898+
899+ dsig_dth = angular_dist (theta , beta , P1 , tilt )
900+ #0.5*(1 + beta*(3*np.cos(theta)**2 - 1)/2)
901+ detected = self .tof_fit_result [tof_id ].A
902+ #produced = self.calibration_mean_xgm[tof_id] * self.tof_fit_result[tof_id].Aa * dsig_dth
903+ produced = self .tof_fit_result [tof_id ].Aa * dsig_dth
904+ en = detected [mask ][eidx ]/ produced [mask ][eidx ]
905+ # interpolate normalization
862906 self .normalization [tof_id ] = np .interp (self .energy_axis ,
863907 ee ,
864908 en )
@@ -940,7 +984,7 @@ def plot_transmissions(self):
940984 a .plot (self .energy_axis , self .normalization [tof_id ], c = c , lw = lw , ls = ls , label = f"eTOF { tof_id } " )
941985 for a in ax :
942986 a .set (xlabel = "Energy [eV]" ,
943- ylabel = "Transmission [a.u.] " )
987+ ylabel = r"$\frac{\mathrm{detected}}{\mathrm{Auger-Meitner} \times \mathrm{polarization} \, \mathrm{effect}}$ " )
944988 a .legend (frameon = False , ncols = 2 )
945989
946990 def plot_offsets (self ):
@@ -1162,7 +1206,7 @@ def apply_correction(tof_id, tof_trace):
11621206
11631207 # interpolate
11641208 #bad = np.isnan(pulses)
1165- np .nan_to_num (pulses , copy = False )
1209+ pulses = np .nan_to_num (pulses , copy = True )
11661210 o = np .apply_along_axis (lambda arr : np .interp (self .energy_axis , e [::- 1 ], arr [::- 1 ], left = 0 , right = 0 ),
11671211 axis = 1 ,
11681212 arr = pulses )
0 commit comments