from maxrf4u import calibrate, DataStack
Calibration
Inconveniently, MA-XRF data does not always include information about the energy calibration of the spectra. Although it is clear that the channel energies will roughly range between zero and the tube voltage, we need more precise numbers for the upcoming calculations. Thus, a very first step in the data analysis is to obtain a precise energy calibration in keV units (kilo-electron-Volt) for a given dataset. Fortunately, XRF spectra, (at least for drawings), typically have two clearly recognizable features that allow for energy calibration of the detector channels.
Two steps
The automatic precise energy calibration is done in two steps.
In the first step the dominant broad Compton peak is observed in the sum spectrum. The position of this peak can not be used for the calibration directly due to an unknown (detector angle specific) Compton shift, but it serves as a landmark. Right next to the Compton peak a small peak is found. In our lab an x-ray tube with a Rhodium anode is used. This peak can now be attributed to elastic scattering of the strong Rhodium K-alpha emission peak present in the x-ray tube spectrum at 20.21 keV.
In the second step of the calibration process the iron K-alpha emission peak is located in the max spectrum. Essentially all artifacts like paper contain iron, with a known strong emission K-alpha line at 6.403 keV.
As a first requisite step in any further data analysis the function calibrate()
is called. The user is prompted to inspect and save the result.
= calibrate('RP-T-1898-A-3689.datastack', tube_keV=40) x_keVs
Write instrument energy calibration to datastack file [y/n]? y
Writing channel energies (keV) to: RP-T-1898-A-3689.datastack
Also writing instrument Compton anode peak energy (keV) to: RP-T-1898-A-3689.datastack
In further analysis our stored energy calibration can now be accessed using the .read('maxrf_energies')
method which returns an array with 4096 energy values.
= DataStack('RP-T-1898-A-3689.datastack')
ds = ds.read('maxrf_energies')
x_keVs
print('Energies: ', x_keVs)
print(f'Number of energy channels: {len(x_keVs)}')
Energies: [-0.98188629 -0.97185221 -0.96181812 ... 40.08763102 40.09766511
40.1076992 ]
Number of energy channels: 4096
Now that we have an energy calibration, we can move to the next step in our data analysis.
FUNCTIONS
compton_shift
compton_shift (keV_in, theta)
*Compute Compton shift for photon energies keV_in
and scatter angle theta
.
Assuming single scattering.
Returns: keV_out*
find_instrument_peaks
find_instrument_peaks (y_sum, prominence=0.1, tube_keV=40)
*Locate key instrument peaks:
1) left hand sensor peak index
2) anode Compton peak index
3) right hand (rhodium) anode Ka peak index
in sum spectrum `y_sum`.
Assumes anode material is rhodium, and Compton peak energy is first peak below (uncalibrated) 20 keV, based on tube keV.
Returns: [left_peak_i, compton_peak_i, right_peak_i]*
detector_angle
detector_angle (keV0, keV1)
*Calculate detector scatter angle theta
(degrees)
From Compton peak energy keV0
and anode energy keV1
, assuming a single scattering event.
Returns: theta (degrees)*
calibrate
calibrate (datastack_file, anode='Rh', prominence=0.1, tube_keV=40)
*Automatic two step energy energy calibration.
In step 1 a preliminary calibration is done assuming that the
sensor peak is located at 0 keV and the Rhodium anode Ka peak is next to it’s high and broad Compton scattering peak in the sum spectrum.
This preliminary calibration the enables the identification of Fe_Ka peak in the max spectrum and a second precise calibration.
Asks user confirmation to store energy calibration in datastack file.
Returns: x_keVs*