Skip to content

Commit f6e7c4e

Browse files
daniloeflDanilo Ferreira de Lima
andauthored
Correct transmission calculation (#449)
* Correct transmission calculation to include polarization effect. --------- Co-authored-by: Danilo Ferreira de Lima <danilo.enoque.ferreira.de.lima@xfel.de>
1 parent 062c5ca commit f6e7c4e

2 files changed

Lines changed: 52 additions & 6 deletions

File tree

docs/changelog.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,8 @@ Fixed:
4747
[DataArray][xarray.DataArray] inputs as well (!419).
4848
- Fix incorrect time units when using [OpticalLaserDelay][extra.components.OpticalLaserDelay]
4949
with pre-2022 BAM data (!425).
50+
- [CookieboxCalibration][extra.applications.CookieboxCalibration] takes polarization into account
51+
when calculating transmission.
5052

5153
Changed:
5254

src/extra/applications/cookiebox.py

Lines changed: 50 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -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+
174190
class 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

Comments
 (0)