usansred package
usansred.io.read
- usansred.io.read.config_from_csv(csv_path: str) ReductionConfig[source]
Reads the reduction configuration from a CSV file.
Returns
- ReductionConfig
Validated reduction configuration.
- usansred.io.read.config_from_json(json_path: str) ReductionConfig[source]
Reads the reduction configuration from a JSON file.
Returns
- ReductionConfig
Validated reduction configuration.
usansred.io.save
Utility functions for USANS reduction. As we add utilities, perhaps we can split them into separater modules
- usansred.io.save.save_ascii(input_workspace, file_path, header=None, **saveascii)[source]
Save a workspace to an ASCII file.
Parameters
- input_workspacestr or Workspace
Input workspace to be summed before saving.
- file_pathstr or path-like
Destination file path for the ASCII output.
- headerstr, optional
Header text to insert or replace in the output file. If provided, and it does not start with
#, it is prefixed with#.- saveasciikwargs
Additional keyword arguments passed through to
mantid.simpleapi.SaveAscii. If argumentWriteSpectrumIDis not supplied, it defaults toFalse.
- usansred.io.save.save_summed_spectra(input_workspace, file_path, header=None)[source]
Save the summed spectra of a workspace to an ASCII file.
Parameters
- input_workspacestr or Workspace
Input workspace to be summed before saving.
- file_pathstr or path-like
Destination file path for the ASCII output.
- headerstr, optional
Header text to insert or replace in the output file. If provided, and it does not start with
#, it is prefixed with#.
usansred.models.data
- class usansred.models.data.EventCounts(detector: int = 0, monitor: int = 0, transmission: int = 0)[source]
Bases:
objectEvent counts associated with a single scan.
- class usansred.models.data.IQData(q: list[float] = <factory>, i: list[float] = <factory>, e: list[float] = <factory>, t: list[float] = <factory>)[source]
Bases:
objectDataclass for I-Q data associated with a single scan
I vs. Q (intensity vs. momentum transfer) is determined from the X-Y data.
- class usansred.models.data.MonitorData(xy_data: XYData = <factory>, iq_data: IQData = <factory>, filepath: str = '')[source]
Bases:
objectContainer for monitor data associated with a single scan.
usansred.models.reduction_config
Data model definitions for USANS reduction.
- class usansred.models.reduction_config.BackgroundConfig(*, name: ~typing.Annotated[str, ~annotated_types.MinLen(min_length=1)], start_scan_num: int, num_of_scans: ~typing.Annotated[int, ~annotated_types.Ge(ge=1)], exclude: list[int] = <factory>, thickness: ~typing.Annotated[float, ~annotated_types.Gt(gt=0)])[source]
Bases:
_ScanBaseBackground sample configuration.
A background is a measurement without the sample container, used to correct for instrument background and ambient scattering.
- model_config = {'extra': 'forbid'}
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- class usansred.models.reduction_config.EmptyCellConfig(*, name: ~typing.Annotated[str, ~annotated_types.MinLen(min_length=1)], start_scan_num: int, num_of_scans: ~typing.Annotated[int, ~annotated_types.Ge(ge=1)], exclude: list[int] = <factory>)[source]
Bases:
_ScanBaseConfiguration for an empty cell scan.
An empty cell is a measurement with a sample container present, but without any sample material. Used to help in the calculation of transmission coefficients and to correct for container scattering.
- model_config = {'extra': 'forbid'}
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- class usansred.models.reduction_config.ReductionConfig(*, samples: Annotated[list[SampleConfig], MinLen(min_length=1)], background: BackgroundConfig | None = None, empty_cell: EmptyCellConfig | None = None, save_all_harmonics: bool = False)[source]
Bases:
BaseModelTop-level configuration for a USANS reduction run.
- background: BackgroundConfig | None
- empty_cell: EmptyCellConfig | None
- model_config = {'extra': 'forbid'}
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- samples: Annotated[list[SampleConfig], FieldInfo(annotation=NoneType, required=True, description='List of sample configurations to reduce.', metadata=[MinLen(min_length=1)])]
- class usansred.models.reduction_config.SampleConfig(*, name: ~typing.Annotated[str, ~annotated_types.MinLen(min_length=1)], start_scan_num: int, num_of_scans: ~typing.Annotated[int, ~annotated_types.Ge(ge=1)], exclude: list[int] = <factory>, thickness: ~typing.Annotated[float, ~annotated_types.Gt(gt=0)])[source]
Bases:
_ScanBaseConfiguration for a single sample to reduce.
- model_config = {'extra': 'forbid'}
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
usansred.reduce
- class usansred.reduce.CombinedSample(**data: Any)[source]
Bases:
BaseModelCombine multiple Sample measurements at the raw (X,Y,E) scan level before converting to (Q,I,E).
Attributes
- namestr
Combined sample name.
- experimentExperiment
Experiment this combined sample belongs to.
- thicknessfloat
Sample thickness in cm.
- measurement_typeMeasurementType
Type of measurement (sample, background, or empty cell).
- combined_sampleslist[Sample]
Individual Sample objects whose scans will be combined.
- combined_scanslist[Scan]
Scans produced by the combination.
- combine() None[source]
Sum raw XY data from all combined samples scan-by-scan, then generate IQ data.
For each scan index, the monitor and detector XY data from every sample are accumulated. If a sample has fewer scans than others a warning is logged and it is skipped for that index. After accumulation the XY to IQ conversion is performed on the combined data and ready for reduction.
Raises
- AssertionError
If
combined_samplesis empty or none of them contain scans.
- experiment: Experiment
- measurement_type: MeasurementType
- model_config = {}
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- class usansred.reduce.Experiment(*, config_file: str, output_dir: str = '', prim_wave: float = 3.6, v_angle: float = 0.042, num_of_banks: int = 4, folder: str = '', samples: list[Sample] = <factory>, background: Sample | None = None, empty_cell: Sample | None = None)[source]
Bases:
BaseModelExperiment configuration for USANS data reduction
Attributes
- config_filestr
Path to the configuration file
- _configReductionConfig
Validated reduction configuration, always set after construction (private attribute)
- output_dirstr | None
Output folder for reduced data, default is current folder
- prim_wavefloat
Primary wavelength in Angstroms, default is 3.6
- v_anglefloat
Vertical angle, default is 0.042
- num_of_banksint
Number of detector banks, default is 4 (not expected to change)
- folderstr
Working folder for this experiment, derived from config file path (private attribute)
- sampleslist[Sample]
List of samples, populated from config file (private attribute)
- backgroundSample | None
Background sample, populated from config file if specified (private attribute)
- empty_cellSample | None
Empty cell sample, populated from config file if specified (private attribute)
- property config: ReductionConfig
Validated reduction configuration, always set after construction.
- dump_reduced_data()[source]
Dump reduced data to txt files.
Output files are written for samples and the background, never for the empty cell.
- model_config = {}
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- class usansred.reduce.Sample(**data: Any)[source]
Bases:
BaseModelContainer for sample information, related scans, and data reduction methods
- property config
- counts: EventCounts
- property data
Main detector data, currently an alias for detector_data[0]
- property data_reduced: IQData | None
Reduced data, currently an alias for the first harmonic of the bg_subtracted data
Returns
- IQData | None
The background-subtracted first harmonic, or
Nonewhen no subtraction has been performed for this measurement.
- dump_data_to_csv(filepath: str, data: IQData | XYData, title: str | None = None)[source]
Dump IQ or XY data to a CSV file.
- dump_reduced_data_to_csv(detector_data: bool = True, scaled_data: bool = True, background_subtracted_data: bool = True) None[source]
Write this measurement’s reduced data to CSV text files in the experiment’s output directory.
Each flag enables one category of output file (all default to True; the reduction workflow in
Experiment.dump_reduced_dataalways uses the defaults). Higher harmonics with no data are skipped with a warning, but the first harmonic is required for thedetector_dataandscaled_datacategories.Parameters
- detector_databool
Write the stitched, monitor-normalized data,
UN_<name>_det_1_unscaled.txt. Withsave_all_harmonics, higher harmonics go toUN_<name>_det_<n>_unscaled.txt.- scaled_databool
Write the data rescaled by analyzer solid angle, sample thickness, and transmission,
UN_<name>_det_1.txt. Withsave_all_harmonics, higher harmonics go toUN_<name>_det_<n>.txt.- background_subtracted_databool
Write the background- (or empty-cell-) subtracted data,
UN_<name>_det_1_background_subtracted.txt. Withsave_all_harmonics, higher harmonics go toUN_<name>_det_<n>_background_subtracted.txt. Only written when a subtraction actually occurred (is_reducedis True).
Raises
- RuntimeError
If
detector_dataorscaled_datais requested but the first harmonic of the corresponding data is missing or empty.
- experiment: Experiment
- property label: str
Display label for log messages, e.g. ‘sample S115_dry’ or ‘empty cell EmptyPCell’.
- measurement_type: MeasurementType
- model_config = {}
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- normalize_by_monitor() None[source]
Normalize detector intensities by monitor counts for all scans.
- reduce() None[source]
Reduce this measurement’s scans.
Normalize each scan by its monitor counts, stitch the scans into one rocking curve per harmonic, center the curves on the analyzer motor angle of the unscattered beam, and rescale to momentum transfer in
1/angstrom. For samples, the background (or, in its absence, the empty cell) is then subtracted from every harmonic.
- rescale_data() None[source]
Rescale reflected data by the analyzer’s solid angle acceptance, by sample thickness, and by the transmission coefficient.
- rocking_curve_centering() float[source]
Center the stitched rocking curves by fitting a Gaussian peak to the rocking curve of the first harmonic.
Notice that the
qvalues of the stitched rocking curves are analyzer motor angles at this stage of reduction, not yet converted to Q values. The first harmonic is fit to a Gaussian over the mostly symmetric angle range[q_min, -q_min], whereq_minis the minimum analyzier motor angle. It will be a negative value. The center of the fitted Gaussian represents the value of the analyzer motor angle at which the analyzer reflects neutrons that have not been scattered by the sample. It should be very close to zero.Returns
- float
Fitted first-harmonic motor-angle center.
- stitch_scans()[source]
Stitch scan data from each detector bank into per-bank intensity curves.
For each detector bank (harmonic), combine all scans in
self.scansonto a single Intensity-versus-Q profile. Detector intensities and errors are expected to already be normalized byScan.normalize_by_monitorbefore being added to the stitched output.Notice that at this stage, the “Q” values are actually analyzer-motor angles, that is, detector bank
iq_data.qvalues are analyzer-motor angles (in arcsec units).If two or more scans contain the same “Q” value, their intensities are combined into one point using inverse-variance weighting, and the combined uncertainty is stored as the square root of the inverse summed weights.
After all scans for a bank are processed, the stitched points are sorted by Q
The method also generates log messages for the raw scan theta ranges and converted Q ranges in
1/angstromfor the first detector bank. Results are stored onself.detector_data; no value is returned.
- subtract_background(background: Sample) None[source]
Subtract background (or empty-cell) data from this sample’s data, harmonic by harmonic.
Harmonic
nof the background is subtracted from harmonicnof the sample, and never from a different harmonic:rescale_dataapplies the order-dependent angle-to-Q factor2 * pi * n / wavelengthto sample and background alike, androcking_curve_centeringapplies a single fitted motor-angle offset to every harmonic, so only same-order curves share a comparable momentum-transfer axis.Results are stored in
self.data_bg_subtracted, positionally aligned withself.data_scaled: harmonicnis entryn - 1. A harmonic that cannot be subtracted gets an emptyIQDataplaceholder so the indices never shift.Parameters
- backgroundSample
The background or empty-cell sample to subtract. Must be processed (stitched and scaled).
Raises
- RuntimeError
If the first harmonic is missing or empty for either this sample or the background.
- class usansred.reduce.Scan(**data: Any)[source]
Bases:
BaseModelA single scan (run) of a sample in an experiment
Attributes
- numberint
Scan (run) number
- countsEventCounts
Event counts object for this scan
- experimentExperiment
Experiment this scan belongs to
- monitor_dataMonitorData
Monitor data associated with this scan
- detector_datalist[MonitorData]
Detector data associated with this scan
- load_databool
Whether to load data files during initialization. Set to False when creating placeholder scans (e.g. for CombinedSample).
- convert_xy_to_iq(xy_data: XYData) IQData[source]
Convert XY data to IQ data
Directly copies x to q, y to i, and t. For error, calculates based on a Poisson-like statistical model:
err = sqrt(|y - 0.5| + 0.5)which ensures a minimum value to avoid zero error for low counts.
- counts: EventCounts
- detector_data: list[MonitorData]
- experiment: Experiment
- model_config = {}
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- monitor_data: MonitorData
- normalize_by_monitor() None[source]
Normalize detector intensities by monitor counts.
Each harmonic in the scan is normalized independently, and within each harmonic, the counts collected at the detector during the time the analyzer-motor remained at a particular angle are divided by the counts collected at the monitor during such time.
- usansred.reduce.horizontal_rocking_width(order: int) float[source]
FWHM (arcs) of the resolution function at the detector for a given reflection order
References
M. Agamalian et al., “Progress on The Time-of-Flight Ultra Small Angle Neutron Scattering Instrument at SNS”, J. Phys.: Conf. Ser. 1021 (2018) 012033.
Parameters
- orderint
Positive reflection order (a.k.a. harmonic or bank)
Returns
- float
Computed horizontal angular resolution.
- usansred.reduce.parse_args(argv: list[str] | None = None) Namespace[source]
Parse command-line arguments for USANS data reduction.
Parameters
- argvlist[str] | None, optional
Command-line arguments to parse, excluding the program name. When
None, arguments are read fromsys.argv.
Returns
- argparse.Namespace
Parsed arguments containing the setup-file path, output directory, and deprecated
logbincompatibility flag.
usansred.reduce_USANS
usansred.summary
summary.py: summary of the reduced data.
- usansred.summary.generate_report(config_file_path: str, data_dir: str | None = None, output_dir: str | None = None)[source]
Generate report from a reduction config file.
Parameters
- config_file_pathstr
Path to the configuration file (CSV or JSON).
- data_dirstr | None
Directory where the reduced data are stored. If None, use the reduced dir in the config file directory.
- output_dirstr | None
Where to save the report. If None, use data_folder/reduced.