Concentration Correction#
Concentration correction compensates for variations in the sample amount (e.g. concentration, beam footprint) that occur between measurements. It works by dividing each signal and monitor by the corresponding signal and monitor of the correction scan.
The concentration_correction() method
chooses between two internal correctors based on the arguments you supply.
Simple concentration correction#
The SimpleConcentrationCorrector is activated by
passing only the indices or scans argument, without an extra
data_mappings dictionary:
measurement.concentration_correction(indices=101)
Internally, daxs reads the correction scan(s) from the same source as the
measurement scans. The corrector selects the division strategy based on how many
correction scans are provided relative to the measurement scans:
Situation |
Behaviour |
|---|---|
One correction scan with as many data points as there are measurement scans |
Each data point of the correction scan scales the corresponding measurement scan. |
One correction scan, but the numbers above do not match |
Every measurement scan is divided by the entire correction scan. |
As many correction scans as measurement scans |
Each correction scan is paired one-to-one with a measurement scan. |
Any other combination |
An error is raised. |
This strategy assumes that measurement scans and correction scan points share the same sequential order, which is usually true when samples are measured in a fixed sequence at the beamline.
Data-driven concentration correction#
The DataDrivenConcentrationCorrector is activated by
additionally supplying a data_mappings dictionary:
data_mappings = {
"sy": ".1/instrument/positioners/sy",
"owisz": ".1/instrument/positioners/owisz",
}
measurement.concentration_correction(indices=225, data_mappings=data_mappings)
Here data_mappings names one or more positioner counters. For each
measurement scan, daxs reads the positioner values that were recorded at
the time of that scan. It then searches the correction scan for the point
whose positioner values are closest in Euclidean distance and uses that point
as the correction factor.
This approach is more robust because it does not rely on scan order. As long as the sample returns to the same position (within numerical precision), the matching succeeds — even if the order in which positions were visited differs between the measurement and the correction scan.
Note
The keys in data_mappings must correspond to fields that were recorded
in the measurement scans (as additional entries in the source
data_mappings). The values must be paths to the equivalent counter
columns in the correction scan. See also the
Advanced Concentration Correction example.
Supplying pre-built scan objects#
Both correctors also accept pre-built Scan or
Scans objects via the scans argument, which is
useful when the correction data lives in a different file:
from daxs.sources import Hdf5Source
corr_source = Hdf5Source(other_file, selection=42, data_mappings={...})
measurement.concentration_correction(scans=corr_source.scans)
API reference#
See concentration_correction(),
SimpleConcentrationCorrector, and
DataDrivenConcentrationCorrector.