trepr.analysis module¶
Data analysis functionality.
Key to reproducible science is automatic documentation of each analysis step applied to the data of a dataset. Each analysis step is selfcontained, meaning it contains every necessary information to perform the analysis task on a given dataset.
Analysis steps, in contrast to processing steps (see
trepr.processing
for details), operate on data of a
trepr.dataset.Dataset
, but don’t change its data. Rather,
some result is obtained that can be everything from a scalar to a full
(calculated) dataset, depending on the actual analysis task at hand.
In order to quantify the quality of a measured spectrum or to interpret it, it is often necessary to perform some analysis steps.
Due to inheritance from the aspecd.analysis
module all analysis steps
provided are fully selfdocumenting, i.e. they add all necessary information
to reproduce each analysis step to the aspecd.dataset.Dataset.history
attribute of the dataset.
Concrete analysis steps¶
Due to inheritance from the aspecd.analysis
module all analysis
steps defined there are available from within the trepr package.
Furthermore, a number of analysis steps specific for trEPR spectroscopy
have been implemented here.
The first block of analysis steps is concerned with evaluating the quality of the recorded data and revealing some possible problems during data acquisition:

Calculate the frequency drift and compare it with the step size.

Extract microwave frequency values recorded for each time trace.

Calculate the time spent for recording each time trace.
Other analysis steps are “true” analysis steps in terms of obtaining information from the data:

Perform FFT to extract transient nutation frequencies.
And the following classes have been extended with respect to the functionality available from the ASpecD classes:

Extract basic characteristics of a dataset.
Note to developers¶
Processing steps can be based on analysis steps, but not vice versa. Otherwise, we get cyclic dependencies what should obviously be avoided in order to keep code working.
Furthermore, if an analysis step returns a (calculated) dataset, use the
aspecd.analysis.AnalysisStep.create_dataset()
method to obtain an
empty instance of this dataset. This will automatically set some parameters
of the created dataset related to the analysis step.
Module documentation¶

class
trepr.analysis.
MWFrequencyDrift
¶ Bases:
aspecd.analysis.SingleAnalysisStep
Calculate the frequency drift and compare it with the step size.
In order to estimate the quality of a spectrum, it can be helpful to know the extent the frequency drifted during the measurement. Therefore, the frequency drift is converted into magnetic field units and can thus be compared to the step width of the magnetic field axis.
This requires the software used to record the trEPR data to save the microwave frequency value for each individual time trace. As often, trEPR spectra are recorded using individual software, this is merely a design question of the program.
Different outputs, e.g. a scalar value or a calculated dataset, are available, for details see below.

parameters
¶ All parameters necessary for this step.
 kind
str
Kind of characteristic to extract from the data
Valid values are “ratio” and “drift”.
In case of “ratio”, the ratio between drift and magnetic field step will be returned, in case of “drift”, the amplitude of the microwave frequency values converted into magnetic field units (mT).
Only relevant in case of “output” set to “value” or “dataset”.
Default: “ratio”
 output
str
Kind of output: value, dict. or dataset
Valid values are “value” (default), “dataset”, and “dict”. Usually, only values and datasets can be easily used within a recipe.
Default: “value”
 Type
 kind

result
¶ Results of the microwave frequency drift analysis.
Depending on the output option set via the “output” parameter, either a scalar value (ratio or drift), , a dict containing both values, or a dataset containing either the ratios or the drifts as function of the magnetic field.
In case of datasets, note that due to calculating a difference between microwave frequency points, the size of the data is 1 compared to the size of the original microwave frequency values.
 Type
Note
If you set the output to “dataset”, you will get a field axis with values centred between the original field values, as the microwave frequency drift analysis requires to calculate differences between points, hence returning vectors with one element less than the original vector.
Examples
For convenience, a series of examples in recipe style (for details of the recipedriven data analysis, see
aspecd.tasks
) is given below for how to make use of this class. The examples focus each on a single aspect.If you have recorded a dataset containing microwave frequency values for each individual time trace and are interested in the drift of the microwave frequency converted into magnetic field values, you can obtain a calculated dataset with the values and plot the results:
 kind: singleanalysis type: MWFrequencyDrift properties: parameters: kind: drift output: dataset result: mwfreqdrift  kind: singleplot type: SinglePlotter1D properties: parameters: tight_layout: true filename: mwfreqdrift.pdf apply_to: mwfreqdrift
While getting the absolute values is often quite helpful, dividing the values by the magnetic field step width (assuming an equidistant axis) allows to directly assess whether the drift is relevant for the particular dataset. Which ratio is tolerable depends on the kind of spectra, but it should be <1 (better <0.5). Obtaining the ratio of frequency drift (in magnetic field units) and the step width is similar to the example above, and again, plotting the results is quite helpful:
 kind: singleanalysis type: MWFrequencyDrift properties: parameters: kind: ratio output: dataset result: mwfreqratio  kind: singleplot type: SinglePlotter1D properties: parameters: tight_layout: true filename: mwfreqratio.pdf apply_to: mwfreqratio
If you are only interested in the values of the maximum drift amplitude and maximum ratio, change the parameter
output
from “dataset” to “value”.See also
trepr.analysis.MWFrequencyValues
Extract microwave frequency values recorded for each time trace.
Changed in version 0.2: New parameter
output
controlling output format andkind
controlling the kind of result. Fix with calculating the ratio. Renamed class from MwFreqAnalysis.
static
applicable
(dataset)¶ Check whether the processing step is applicable to the given dataset.
To be able to perform a microwave frequency drift analysis, the values for the microwave frequency for each individual time trace need to be recorded and available from the dataset.


class
trepr.analysis.
TimeStampAnalysis
¶ Bases:
aspecd.analysis.SingleAnalysisStep
Calculate the time spent for recording each time trace.
Can be helpful for debugging the spectrometer and for assessing whether delays during data acquisition are responsible for artifacts in a recorded dataset.
This requires the software used to record the trEPR data to save the time stamp for each individual time trace. As often, trEPR spectra are recorded using individual software, this is merely a design question of the program.

parameters
¶ All parameters necessary for this step.
 kind
str
Kind of characteristic to extract from the data
Valid values are “delta” and “time”.
In case of “delta”, the time difference (delta) in seconds between adjacent magnetic field points will be returned, in case of “time”, the time (in seconds) for each time trace since start of the measurement will be returned.
Default: “delta”
 output
str
Kind of output: value, dict. or dataset
Valid values are “value” (default), “dataset”, and “dict”. Usually, only values and datasets can be easily used within a recipe.
Default: “value”
 Type
 kind

result
¶ Results of the microwave frequency drift analysis.
Depending on the output option set via the “output” parameter, either a scalar value (ratio or drift), , a dict containing both values, or a dataset containing either the ratios or the drifts as function of the magnetic field.
In case of datasets, note that due to calculating a difference between microwave frequency points, the size of the data is 1 compared to the size of the original microwave frequency values.
Note
If you set the output to “dataset” and the kind to “delta”, you will get a field axis with one value less than the original field axis, as the analysis requires to calculate differences between points, hence returning vectors with one element less than the original vector.
Examples
For convenience, a series of examples in recipe style (for details of the recipedriven data analysis, see
aspecd.tasks
) is given below for how to make use of this class. The examples focus each on a single aspect.If you have recorded a dataset containing time stamps for each individual time trace and are interested in the time spent between adjacent magnetic field points, you can obtain a calculated dataset with the values and plot the results:
 kind: singleanalysis type: TimeStampAnalysis properties: parameters: kind: delta output: dataset result: timedelta  kind: singleplot type: SinglePlotter1D properties: parameters: tight_layout: true filename: timedelta.pdf apply_to: timedelta
Please note that depending on the mode of measurement you will get different times between adjacent field points. In case of a background signal regularly recorded every nth trace during measurement, you will regularly see about twice the time spent, and if you do not record linearly (up or down), but inward or outward with respect to the magnetic field axis, this will be reflected in the time deltas as well.
Sometimes you may be interested in the relative times rather than the time deltas. This can be achieved similarly to the example above. Simply change “kind” from “delta” to “time”:
 kind: singleanalysis type: TimeStampAnalysis properties: parameters: kind: time output: dataset result: timevalues  kind: singleplot type: SinglePlotter1D properties: parameters: tight_layout: true properties: drawing: marker: '*' filename: timevalues.pdf apply_to: timevalues
To better see the individual time points, here, additional markers are added to the plot. In case of outward measurement scheme, you will see a vshaped result.
Changed in version 0.2: New parameter
output
controlling output format. Returns time deltas in seconds.
static
applicable
(dataset)¶ Check whether the processing step is applicable to the given dataset.
To be able to perform a time stamp analysis, time stamps need to be available for each individual time trace of the dataset.


class
trepr.analysis.
BasicCharacteristics
¶ Bases:
aspecd.analysis.BasicCharacteristics
Extract basic characteristics of a dataset.
This class extends the ASpecD class by the possibility to return axes values and indices for only one axis in case of ND datasets with N>1.
Currently a workaround, the functionality may move upwards in the ASpecD framework eventually.

parameters
¶ All parameters necessary for this step.
Additionally to those from
aspecd.analysis.BasicCharacteristics
, the following parameters are allowed: axis
int
Number of the axis to return the axes values or indices for.
 Type
 axis
New in version 0.2.


class
trepr.analysis.
MWFrequencyValues
¶ Bases:
aspecd.analysis.SingleAnalysisStep
Extract microwave frequency values recorded for each time trace.
trEPR measurements can take a rather long time, up to 1224 hours, and the stability of the microwave frequency is not always guaranteed. Crucial here is that the frequency drift is small compared to the magnetic field step width.
What does that mean practically? Using the resonance condition of magnetic resonance, one can convert magnetic field values in frequencies, and as a rule of thumb, 1 mT = 28 MHz. Therefore, if the microwave frequency drifted by < 1 MHz during the experiment, in most cases (except of experiments with very high field resolution) you should be safe and there is no reason to expect distortions of the spectra shape due to a drift in microwave frequency.
Not all software used to record trEPR data does record the MW frequency for each individual time trace, though. Therefore, only those datasets containing the microwave frequency values can be analysed.
The analysis step returns a calculated dataset with the magnetic field axis as the first axis and the microwave frequency values as data.
Examples
For convenience, a series of examples in recipe style (for details of the recipedriven data analysis, see
aspecd.tasks
) is given below for how to make use of this class. The examples focus each on a single aspect.If you have recorded a dataset containing microwave frequency values for each individual time trace and are interested in the drift of the microwave frequency, you can extract the microwave frequency values as function of the magnetic field as a calculated dataset:
 kind: singleanalysis type: MWFrequencyValues result: mwfreq
To plot the data contained in the newly obtained calculated dataset, simply proceed with a plotter of your choice:
 kind: singleplot type: SinglePlotter1D properties: filename: mwfreq.pdf apply_to: mwfreq
Don’t be surprised if the drift seems not to be linear or even appears to be discontinuous. Depending on how you have recorded your data, i.e. what scheme of sampling the magnetic field axes you have used, this is perfectly normal.
See also
trepr.analysis.MWFrequencyDrift
Calculate the frequency drift and compare it with the step size.
New in version 0.2.

static
applicable
(dataset)¶ Check whether the processing step is applicable to the given dataset.
To be able to extract the microwave frequency values for each individual time trace, these values need to be available from the dataset.

class
trepr.analysis.
TransientNutationFFT
¶ Bases:
aspecd.analysis.SingleAnalysisStep
Perform FFT to extract transient nutation frequencies.
A trEPR time trace showing transient nutations can be described by a zeroorder Bessel function of first kind. Due to relaxation, the Bessel function is damped with an exponential.
One way to extract the transient nutation frequencies is to perform a 1D discrete Fourier transform (using the FFT algorithm) along the time axis. In case of 2D datasets, this means to perform the FFT for each time trace individually.
In any case, the analysis step will return a calculated dataset with the data representing the FFT for all time traces. Here, the scipy function
scipy.fft.rfft()
returning realvalued results gets used.In case the time trace has been recorded for negative times (pretrigger), the FFT will only be performed starting at t = 0.
Generally, if full time traces including the raising flank are analysed, it is best to cut the time traces from the left up to the extremum (maximum of the absolute value) to suppress lowfrequency background of the resulting FT. This is the default behaviour and can be controlled using the
start_in_extremum
parameter (see below). In case of 2D datasets, the global extremum will be used for all time traces.As long as the oscillation clearly dominates the time trace(s), i.e. the signal intensity crossing the zero line multiple times, there should be no need for further preprocessing. Things are different, however, if the time trace is dominated by an exponential decay and the oscillation merely modulates this decay. In this case, you will usually need to subtract the exponential decay from the data to obtain meaningful results from the FFT. This can be done by setting the parameter
subtract_decay
(see below).Additionally, sometimes the frequency domain signal after the Fourier transform exhibits prominent side lobes. This can be suppressed by apodising the data before Fourier transform using a window function. Windows can be set using the
window
parameter, and if a window requires additional parameters, use thewindow_parameters
parameter to supply them.Choosing the optimal window and taking informed decisions requires a lot of background knowledge. Just bear in mind that different windows can have different effects on the resulting signal in the frequency domain, including shifting the maxima. Therefore, as long as you are only interested in clearly distinct frequencies rather than arbitrarily exact absolute frequencies, apodisation is perfectly fine. Distinguishing between paramagnetic species with different spin multiplicity should not be affected by whatever window you apply.
As a side note: An alternative way to analyse transient nutations would be to fit a damped Bessel function of first kind to the data. Thus one can extract both, frequency and relaxation rate directly from the data. Note, however, that this will only be possible if the oscillation clearly dominates the time trace. In cases where the oscillation merely resides on top of a dominating exponential decay, this will typically not be possible.

parameters
¶ All parameters necessary for this step.
 start_in_extremum
bool
Whether to cut the time trace(s) from the left at the extremum.
Extremum here means the maximum of the absolute values of the data of the dataset.
Default: True
 padding
int
Factor the original length of the time trace used for FFT should be elongated and padded with zeros (“zero filling”).
Usually, to reasonably resolve lower frequencies, a factor of 3–5 is useful.
Default: 1
 subtract_decay
bool
Whether to subtract a fitted exponential decay from each time trace.
Sometimes the time trace is dominated by an exponential decay rather than the transient nutation, i.e. the nutation appears as modulation on top of an exponential decay. In this case, the FFT will usually not allow for reliably extracting the nutation frequencies, due to a huge background at the lowfrequency end.
In this case, fitting and afterwards subtracting an exponential decay from each time trace helps a lot. As usually the exact form and parameters of the exponential decay are not known, here, an exponential decay with two parameters in the form
f(x) = a * exp(b * t)
gets used. While leading to quite reliable results in the FFT, the fitted parameters can usually not be interpreted.Default: False
 window
str
Name of the window for apodisation of the data.
Windows are often applied to the signal before Fourier transform to suppress artifacts (side lobes). Note, however, that applying windows might shift your frequencies, particularly in the lowfrequency range, towards higher frequency. Therefore, it is always good to compare nonwindowed and windowed signals if you need to extract reliable nutation frequencies from your data.
All types of windows supported by
scipy.signal.windows
can be used. See there for further details. If a window requires additional parameters, use the parameterwindow_parameters
. For details, see below.Internally, the function
scipy.signal.windows.get_window()
is used to obtain the respective window. Note that only the right half of the (symmetric) window is applied to the data.Default: None
 window_parameters
float
orlist
Parameters used for the window for apodising the data.
For details of data apodisation, see above.
Default: None
 Type
 start_in_extremum
Examples
For convenience, a series of examples in recipe style (for details of the recipedriven data analysis, see
aspecd.tasks
) is given below for how to make use of this class. The examples focus each on a single aspect.In its simplest form, you just apply the analysis step to a dataset and assign it to a result:
 kind: singleanalysis type: TransientNutationFFT result: fft
To plot the data contained in the newly obtained calculated dataset, simply proceed with a plotter of your choice (in this case for a 1D dataset):
 kind: singleplot type: SinglePlotter1D properties: filename: fft.pdf apply_to: fft
Often the resolution in the frequency domain is insufficient if only the original signal is used for Fourier transform. One way to overcome this problem is to apply padding (zerofilling) to the data. From experience, a factor of 35 compared to the original signal length is a good idea:
 kind: singleanalysis type: TransientNutationFFT properties: parameters: padding: 5 result: fft
In this case, the signal will be padded with zeros and be five times as long as the original signal.
Sometimes, time traces are dominated by an exponential decay rather than the oscillation. Fourier transform of such signals results in a large background particularly in the lowfrequency range, obfuscating the unequivocal extraction of the frequencies of the transient nutations. One way to deal with this problem is to automatically fit and subtract an exponential to each time trace prior to Fourier transform.
 kind: singleanalysis type: TransientNutationFFT properties: parameters: subtract_decay: true result: fft
Another aspect often occurring during Fourier transform is apodisation to suppress artifacts (side lobes) in the frequency domain. Here, a window function is multiplied to the data (before padding). You can choose from a large range of window functions, actually all window functions that are supported by
scipy.signal.windows
. Typical windows areHann
andHamming
, but it seems that acosine
window has less effects on the positions of the maxima in the frequency domain. kind: singleanalysis type: TransientNutationFFT properties: parameters: window: cosine result: fft
In any case, take care of the effects windows and apodisation may have to the signals in the frequency domain beyond suppressing artifacts. If you want to use a window requiring extra parameters, provide these parameters as scalar or list:
 kind: singleanalysis type: TransientNutationFFT properties: parameters: window: kaiser window_parameters: 3 result: fft
To compare the effect different windows have on the frequency spectrum, you can perform a series of transforms with different windows and compare the results graphically:
 kind: singleanalysis type: TransientNutationFFT properties: parameters: padding: 5 result: fft  kind: singleanalysis type: TransientNutationFFT properties: parameters: padding: 5 window: hann result: ffthann  kind: singleanalysis type: TransientNutationFFT properties: parameters: padding: 5 window: cosine result: fftcosine  kind: multiplot type: MultiPlotter1D properties: parameters: show_legend: true properties: drawings:  label: no window  label: Hann window  label: cosine window filename: fftcomparewindows.pdf apply_to:  fft  ffthann  fftcosine
Of course, you could compare other parameter settings as well in a similar manner.
New in version 0.2.

static
applicable
(dataset)¶ Check whether the processing step is applicable to the given dataset.
To be able to analyse transient nutations, a time axis needs to be present.
