diff --git a/xgm.py b/xgm.py index 91f6f2fd55a0dabb206f7a182d620b230e0b24e7..86415110902eda26b7cb166115057908bc8f43f1 100644 --- a/xgm.py +++ b/xgm.py @@ -565,3 +565,67 @@ def calibrateTIM(data, rollingWindow=200, mcp=1, plot=False, use_apd=True, intst plt.tight_layout() return F + +''' TIM calibration table + Dict with key= photon energy and value= array of polynomial coefficients for each MCP (1,2,3). + The polynomials correspond to a fit of the logarithm of the calibration factor as a function + of MCP voltage. If P is a polynomial and V the MCP voltage, the calibration factor (in microjoule + per APD signal) is given by -exp(P(V)). + This table was generated from the calibration of March 2019, proposal 900074, semester 201930, + runs 69 - 111 (Ni edge): https://in.xfel.eu/elog/SCS+Beamline/2323 + runs 113 - 153 (Co edge): https://in.xfel.eu/elog/SCS+Beamline/2334 + runs 163 - 208 (Fe edge): https://in.xfel.eu/elog/SCS+Beamline/2349 +''' +tim_calibration_table = { + 705.5: np.array([ + [-6.85344690e-12, 5.00931986e-08, -1.27206912e-04, 1.15596821e-01, -3.15215367e+01], + [ 1.25613942e-11, -5.41566381e-08, 8.28161004e-05, -7.27230153e-02, 3.10984925e+01], + [ 1.14094964e-12, 7.72658935e-09, -4.27504907e-05, 4.07253378e-02, -7.00773062e+00]]), + 779: np.array([ + [ 4.57610777e-12, -2.33282497e-08, 4.65978738e-05, -6.43305156e-02, 3.73958623e+01], + [ 2.96325102e-11, -1.61393276e-07, 3.32600044e-04, -3.28468195e-01, 1.28328844e+02], + [ 1.14521506e-11, -5.81980336e-08, 1.12518434e-04, -1.19072484e-01, 5.37601559e+01]]), + 851: np.array([ + [ 3.15774215e-11, -1.71452934e-07, 3.50316512e-04, -3.40098861e-01, 1.31064501e+02], + [5.36341958e-11, -2.92533156e-07, 6.00574534e-04, -5.71083140e-01, 2.10547161e+02], + [ 3.69445588e-11, -1.97731342e-07, 3.98203522e-04, -3.78338599e-01, 1.41894119e+02]]) +} + +def timFactorFromVoltage(voltage, photonEnergy=None, mcp=1): + ''' Returns an energy calibration factor for TIM integrated peak signal (APD) + according to calibration from March 2019, proposal 900074, semester 201930, + runs 69 - 111 (Ni edge): https://in.xfel.eu/elog/SCS+Beamline/2323 + runs 113 - 153 (Co edge): https://in.xfel.eu/elog/SCS+Beamline/2334 + runs 163 - 208 (Fe edge): https://in.xfel.eu/elog/SCS+Beamline/2349 + Uses the tim_calibration_table declared above. + + Inputs: + voltage: MCP voltage in volts. + photonEnergy: FEL photon energy in eV. Calibration factor is linearly + interpolated between the known values from the calibration table. + If None, takes the median photon energy from the calibration table. + mcp: MCP channel (1, 2, or 3). + + Output: + f: calibration factor in microjoule per APD signal + ''' + energies = np.sort([key for key in tim_calibration_table]) + if photonEnergy is None: + photonEnergy = np.median(energies) + if photonEnergy not in photon_energies: + if photonEnergy > energies.max(): + photonEnergy = energies.max() + elif photonEnergy < energies.min(): + photonEnergy = energies.min() + else: + idx = np.searchsorted(photon_energies, energy) - 1 + polyA = np.poly1d(tim_calibration_table[energies[idx]][mcp-1]) + polyB = np.poly1d(tim_calibration_table[energies[idx+1]][mcp-1]) + fA = -np.exp(polyA(voltage)) + fB = -np.exp(polyB(voltage)) + f = fA + (fB-fA)/(energies[idx+1]-energies[idx])*(photonEnergy - energies[idx]) + return f + poly = np.poly1d(tim_calibration_table[photonEnergy][mcp-1]) + f = -np.exp(poly(voltage)) + return f + \ No newline at end of file