XLD/XMCD Analysis HOWTO
Contents
1. Usage
2. Description
2.1 Top row
2.2 Options window
2.2.1 Normalization
2.2.2 Interpolation
2.2.3 Motor selection
2.3 Table
2.4 Analysis window
3. Extend the automatic assignment
3.1 Edit the experiments dictionary
3.2 Edit the drop down menu
3.3 Edit the selectExperiment function
Synopsis
Xray linear dichroism (XLD) and Xray magnetic circular dichroism (XMCD)
measurements as performed at Beamlines ID08 and ID12 of the ESRF
probe the sample with x-rays of two different polarizations. From two spectra
with different polarizations, one calculates the difference spectrum (the
XLD/XMCD spectrum) as well as the average spectrum (XAS spectrum). The present
plug-in aims to ease the evaluation process.
To assign the recorded spectra into two groups (labeled 'A' and 'B') depending
on their polarization, the plug-in displays meta data obtained from the spec file
and provides methods to automate the assignment process. A separate plot
window allows a preview on calculated XLD/XMCD spectra. Several options relevant
to the treatment of the data can be specified and saved. The results of an analysis
can be exported into spec-files.
up
From the open spec-File, select the relevant scans in the scan selection window
on the left side of your PyMca session. Assign the relevant counters to the
respective axes and load the scans in the plot window on the right. Load the plug-in
from the plug-in menu (gearbox item in the top row of the plot window).
Notice that if one selects a section of the data by zooming in before starting the
plug-in, only the data within that energy range is used for the analysis.
The selected spectra now appears in the table of the plug-in.
Per default, the spectra remain unassigned as indicated by the drop down menu showing
the entry 'Generic dichroism'. Either one selects an existing experiment from the
drop down menu (which also provides automatic division of spectra into groups) or does all
settings by hand using the options menu. The options menu also allows to determine
if and when a normalization is applied to the spectra and the specifics of the interpolation
carried out during the calculation.
If all necessary information is displayed in the table, the assignment of spectra to
either group 'A' or 'B' can be done by right-clicking on the table. A context menu appears
offering several ways to assign a selected spectrum a group.
Once a selection is made, the result of calculations is displayed immediately in the analysis window.
An average is calculated on the spectra that belong to groups 'A' and 'B' (curves labeled
avg_A resp. avg_B). The difference spectrum (curve labeled XMCD) is calculated as Avg(B)- Avg(A).
The XAS spectrum is calculated as the average of both groups: (Avg(A) + Avg(B))/2
The finished analysis can be saved in a spec file using the Save Button in the top button row
of the analysis window.
up
The plug-in consists of four elements: the top row of buttons, the table
listing the spectra and the analysis window. Another important element is the options
window.
The top row contains the following buttons in order from left to right: the Update
Button, the Options Button and the Experiment Selection.
Update Button
Loads plots from the main window of the PyMca session into the plug-in. Notice:
If the plot window of the main application is zoomed in or out, only the data
within the zoomed in energy range is considered for analysis. After zooming in
or out in the main application, the spectra in the plug-in should be updated.
Options Button
Allows to specify the plug-in behavior during the analysis. For information in
can be found in
section 2.2.
Experiment Selection:
The options for the experiments carried out at beamlines ID08 and ID12 are
embedded in the plug-in. Selecting one of the experiments sets these options
and divides the spectra automatically into groups 'A' and 'B'.
A new experimental configuration can be added using the 'Add new configuration'
option. A window will open and ask the user to name the configuration.
Once accepted, an option window is opened and can be used to define the experimental
configuration. This can be done by either loading an existing configuration
or by specifying it by hand.
The new experimental configuration can now be selected in the drop down menu and
remains there until the end of the PyMca session. It sets all options as specified,
however the spectra assignment into groups has still to be done by hand.
up
With the Options Window, the user can control the details of the analysis and
determine the information shown in the table. A configuration made in the Options
Window can be saved and an existing configuration can be loaded. Notice that once
the 'OK' button is clicked, the analysis is immediately recalculated.
The saved options are stored in a config file. If the result of a XLD/XMCD
analysis is saved a spec file, the current configuration is automatically
saved in a separate file.
up
One can select if and when a normalization is applied, the normalization method can
be specified. Either no normalization is applied at all or it is applied before
performing the averages over groups 'A' and 'B'. The third option is to perform
the normalization after averaging over both groups.
The following table explains the various normalization methods in detail.
Option |
Explanation |
(y-min(y)) /trapz(max(y)-min(y),x) |
Default selection. Subtracts the minimum value as offset from the spectrum
and normalizes it to its integral
|
y/max(y) |
Normalizes the curve to its maximum value
|
(y-min(y)) /(max(y)-min(y)) |
Subtracts the minimum value as offset from the spectrum and normalizes to the
resulting maximum, effectively putting all spectral values between zero and one
|
(y-min(y)) /sum(max(y)-min(y)) |
Similar to the default options, but uses the summation over all spectral values
instead of the integral
|
up
The plug-in performs an interpolation of the spectra selected to be used in the analysis
before calculation averages and differences. In the "Interpolation x-range" section the
user can select, which energy range is used for interpolation. To guarantee numerical
stability of the interpolation, the spectra are cleaned up before being copied from
the main application to the plug-in.
The clean up process consists of sorting the data with respect to the energy (i.e. x)
range as well as removing energies that have been measured twice.
One can chose between selecting one of the energy ranges that actually have been measured or
let the plug-in determine a equidistant energy range, which might be beneficial for further
analysis such as Savitzky-Golay smoothing. Options that conserve at least one measured
energy range are 'First curve in sequence' or 'Active curve' (i.e. taking the active curve in
the plot window of the main application).
up
The drop down menus allow to select the motors positions to be shown in the plug-in
table. Notice that all motors in the drop down menu are not hard coded in the plug-in
but are obtained dynamically from meta data in the spec file. Motor names are treated
case sensitive by the plug-in.
Motors for ID08 are:
phaseD, PhaseD, oxPS, magnet
Motors for ID12 are:
Phase, PhaseA, BRUKER, CRYO, OXFORD
Notice that ID12 also uses different counters to differ between polarizations.
up
The table, positioned beneath the top row, shows the spectra that are included
in the XLD/XMCD analysis. The table shows the group to which a curve is assigned,
the curves' legend, the scan number and the counter of a spectrum. The
remaining columns display settings of various physical or virtual motors that were
recorded during the course of the measurement and stored in the meta data of the
spec file.
Every column of the table can be used to sort it with respect to the values in this
column by double clicking the right top corner of the respective header section.
Right click on the table provides the user with a context menu with the following
options:
Perform Analysis
Although most calculation is triggered automatically upon selection of a set
of scans, selecting this option forces the plug-in to recalculate the XLD/XMCD spectrum.
Set as A resp. Set as B
Assigns a scan selected in the table to the respective group and triggers a
recalculation of the XLD/XMCD Analysis.
Enter sequence
Opens a window and allows to enter a sequence of letters ('A', 'B', 'D'). The
spectra in the table are sorted after their scan number and assigned into
groups 'A' and 'B' based on the sequence, 'D' leaves a spectrum unselected.
If no scan number is present, the spectra remain unsorted.
The length of the sequence does not need to match the number of spectra. If the
length of the sequence is smaller than the number of spectra, the plug-in assumes
the entered sequence as a pattern and repeats it.
Remove selection
Removes a scan from the selection, effectively setting its group to 'D'
Invert selection
Selects scans in the table that are not selected yet and deselects the selected
scans.
Remove curves
Removes curves from the table and the plot window in the main application.
up
The analysis window beneath the table shows the result of the XLD/XMCD analysis. Four
curves are displayed: the arithmetic averages over groups A and B, the XAS spectrum
(an arithmetic average over the averages of groups A and B) and the difference spectrum
(group B - group A) called the XMCD spectrum.
Notice that the XMCD spectrum usually is not in the same order of magnitude as the average
spectra and the XAS spectrum. Thus, the XMCD spectrum is plotted to the secondary y axis
on the right. In order to hide individual spectra, one can right-click on the legend and
select 'Hide curve'.
In the analysis window behaves exactly like the plot window of the main application. The
plot can be zoomed and the spectra can be manipulated using the usual tools of PyMca. Only
the save routine has been modified to the specific demands of XLD/XMCD analysis.
Save routine
The save icon in the analysis window allows the users to save all results of the XLD/XMCD
analysis at once in a single spec file. The data is divided into multiple columns. The
first column contains the energy range over which the analysis is carried out, followed
by the averages over groups 'A' and 'B'. The last two columns are occupied by the XLD/XMCD
spectra.
The save dialog also allows to enter a comment that will be written in the spec file.
If multiple datasets are analyzed consecutively, the results can be still saved in a single
spec file by selecting the 'Append to existing file' option. Every individual scan is saved
in a separate file, too. Therefore, the original file name is extended by an underscore and
the number of scans already present in the file to which the analysis is appended to.
Along with the data, the configuration from the options menu is also saved under the same
file name, but with the extension 'cfg'.
Buttons Add, Add all, Replace and Replace All
Allow to push the resulting spectra from the plug-in window to the plot window of the main
application. While 'Add' and 'Replace' only affect the active curve in the plug-in plot
window, 'Add all' and 'Replace all' copy all curves from the analysis to the main application.
Notice: If one plans to compare two or more analyzed spectra by consecutively pushing them
to the main window, the spectra should be renamed beforehand. The name for each analyzed
spectrum remains the same (avg_A, avg_B, XMCD, XAS) and moving spectra of the same name
to the plot window in the main application just replaces them there.
up
The scope of this paragraph is to explain the additions to the source code necessary to make to
define a new experiment. The paragraph assumes entry level knowledge of the Python programming
language.
Data measured on beamline ID08 or ID12 of the ESRF can automatically be assigned to one of groups 'A'
or 'B', as long as it is saved in spec files. By selecting one of the experiments from the drop down
menu in the top row, the XLD/XMCD plug-in sets the motors resp. counters controlling the polarization
in the options menu. This displays the respective values in the plug-ins table. To achieve the
automatic assignment, the plug-in reads the displayed values and guesses the affiliation of a
spectrum based on a set of rules.
up
The experiments dictionary contains the settings specific to an experiments. The options concern
the normalization settings and method, the interpolation settings and most importantly the motors
on which the assignment depends.
The following code fragment shows the exemplary entry 'Generic Dichroism' in the experiments
dictionary.
self.experimentsDict = {
'Generic Dichroism': {
'xrange': 0,
'normalization': 0,
'normalizationMethod': 'offsetAndArea',
'motor0': '',
'motor1': '',
'motor2': '',
'motor3': '',
'motor4': ''
},
...
}
Notice that every experiment is represented by a dictionary itself, with the different options
as keys and the respective settings as values. Valid values for each option, as well as the
necessary types are shown in the following table.
Option |
Type |
Values: Explanation |
xrange |
Int |
0: First curve in sequence
1: Active curve
2: Equidistant x-range |
normalization |
Int |
0: No normalization
1: Normalize after average
2: Normalize before average |
normalizationMethod |
String |
OffsetAndArea: Subtracts minimum and normalizes to the integral,
OffsetAndCounts: Subtracts minimum and normalizes to the sum,
OffsetAndMaximum: Subtracts minimum and normalizes to the maximum
NormToMaximum: Normalizes to the maximum
|
motor0, motor1, motor2, motor3, motor4 |
String |
Assumes knowledge of the motor settings in the experimental apparatus.
If unsure, consult the Motor Info plug-in or a Beamline Scientist.
|
Notice that up to five motors can be specified, however no motor must be specified. If a
motor is not needed, just set the variable to an empty string.
up
Now that a new experiment is present in the experiments dictionary, it can be added into
the selection of the drop down menu. The drop down menu itself is a QComboBox whose items are
added using the addItem member function. The explicit code to do so (at least in the initial
version of this program) looks as follows:
self.expCBox.addItems(
['Generic Dichroism',
'ID08: XLD 9 Tesla Magnet',
'ID08: XLD 5 Tesla Magnet',
'ID08: XMCD 9 Tesla Magnet',
'ID08: XMCD 5 Tesla Magnet',
'ID12: XLD (quater wave plate)',
'ID12: XMCD (Flipper)',
'ID12: XMCD',
'Add new configuration'])
It is important, that the registered string is the exact key of the experiment in the experiments
dictionary. New experiments should be added above the 'Add new configuration' option.
up
The selectExperiment function is called every time a item from the drop down menu is selected. In the process,
the selected option is passed on to the function as a string. Based on this string, the function then sets
the options as defined in the experiments dictionary. This triggers the table of the plug-in to display the
information, especially if motors are present in the options.
In a second step, the function reads all values shown in the tables motor columns (that is columns 4 to 8). If
needed (as in case of two of the ID12 experiments), the counter column (no. 3) might as well be read out.
The code fragment below shows the updating of the table and the readout.
self.updateTree()
values0 = numpy.array(
self.list.getColumn(4, convertType=float))
values1 = numpy.array(
self.list.getColumn(5, convertType=float))
values2 = numpy.array(
self.list.getColumn(6, convertType=float))
values3 = numpy.array(
self.list.getColumn(7, convertType=float))
values4 = numpy.array(
self.list.getColumn(8, convertType=float))
The table function getColumn returns the entries of a table column as a list while conserving the current order
of the table rows. The type of the list elements can be specified using the convertType option. The numpy
Arrays values0 to values4 now contain different motor positions, each values array has the length of the
number of scans in question
The next section consists of a succession of if/else statements to determine the specific experiment. Within
such a statement, the values from the table are reduced to a single vector named 'values' that determines
the affiliation of a spectrum to groups 'A' or 'B'. This array contains numerical values for every spectrum.
The second step here is to set a pivot element (or threshold value), so that if the value for a spectrum is
above this value, the spectrum belongs to group 'A' and below to group 'B'. New assignment routines must be
implemented here as a new elif block.
In case of the XLD experiment of ID08, the decision process is shown in the code fragment below.
if exp.startswith('ID08: XLD'):
values = values0
mask = numpy.where(numpy.isfinite(values))[0]
minmax = values.take(mask)
if len(minmax):
vmin = minmax.min()
vmax = minmax.max()
vpivot = .5 * (vmax + vmin)
else:
values = numpy.array(
[float('NaN')]*numOfSpectra)
In this case, the motor 'PhaseD' (or 'phaseD', depending on the magnet) determines the polarization on the sample
and is thus set in the options dictionary. All motor positions are then contained in numpy array 'values0'. Since no
further calculations are needed, we can directly assign 'values0' to 'values'. The pivot element in this case is
calculated as the average between maximal and minimal values in 'values'.
The last step of the assignment processes is to loop though the 'values' array and check if the element is
above or below threshold, as shown in the next code fragement.
seq = ''
for x in values:
if str(x) == 'nan':
seq += 'D'
elif x>vpivot:
seq += 'A'
else:
seq += 'B'
self.list.setSelectionToSequence(seq)
Notice that not-a-number float values in the 'values' array are set to the dummy identifier 'D' and thus are ignored in
the selection. The resulting sequence of this procedure is then passed on to the table function setToSequence, which
assigns the selection. Once a selection is made, a recalculation is triggered automatically.
up