ORNLSpiceLoader

ORNLSpiceLoader loads ORNL SPICE scan files (.dat) into TAVI scan models. It parses:

  • scan values from the tabular section,

  • scan metadata from file headers,

  • TAVI-specific metadata used by the application layer,

  • optional UB configuration data from sibling UBConf files.

Overview

Source module:

tavi.library.storage.loader.ornl_spice_loader

Primary class:

class tavi.library.storage.loader.ornl_spice_loader.ORNLSpiceLoader(filestore: FileStoreInterface)[source]

Loader for ORNL Spice format scan files.

adapt_scan_data(uuid: UUID, values: ScanData, meta: ScanMetadata, tavi_meta: TaviMetadata, prov: Provenance) RawScan[source]

Adapt scan data.

create_provenance(file_path: str) Provenance[source]

Create provenance of the scan file.

fit_motor_angles(tavi_data: TaviData, scan_num: int, IPTS: int | None = None, exp_num: int | None = None, fit_package: FitPackage = FitPackage.lmfit, model_dict: list[tuple[ModelName, dict[str, Any]]] = []) list[MotorAngles][source]

Generate fitted motor positions, one MotorAngles per fitted peak center.

The scanned (default-x) motor is fit with model_dict; when it has a paired motor (omega for a 2theta scan, s1 for an s2 scan) that motor is fit too and centers are paired by sorted order. Motors that are not scanned use their mean over the scan. A list with one entry per fitted center is returned.

get_data_from_scan_number(tavi_data: TaviData, scan_num: int, IPTS: int | None = None, exp_num: int | None = None) RawScan[source]

Get scan object from a scan number.

Parameters:
  • tavi_data – Container of loaded raw scans to search.

  • scan_num – Scan number to look up.

  • IPTS – Optional IPTS proposal number to disambiguate across experiments.

  • exp_num – Optional experiment number to disambiguate within an IPTS.

Returns:

The matching RawScan.

Raises:

ValueError – If zero or more than one scan matches.

get_data_point_closest_to_center(tavi_data: TaviData, scan_num: int, IPTS: int | None = None, exp_num: int | None = None, fit_package: FitPackage = FitPackage.lmfit, model_dict: list[tuple[ModelName, dict[str, Any]]] = []) DataPoint[source]

Create a DataPoint from the scan row whose column value is closest to center.

get_delta_q(tavi_data: TaviData, scan_num: int, IPTS: int | None = None, exp_num: int | None = None, mode: FixedEnergyMode = FixedEnergyMode.FIX_Ef, fixed_energy: float = 0) ndarray[source]

Get delta q of a scan.

get_ei_ef(e: float, mode: FixedEnergyMode, fixed_energy: float) tuple[float, float][source]

Get (ei, ef) given the complementary energy.

get_hkl(tavi_data: TaviData, scan_num: int, IPTS: int | None = None, exp_num: int | None = None, use_title: bool = True, model_dict: list[tuple[ModelName, dict[str, Any]]] = []) ndarray[source]

Extract the (h, k, l), user can define if they want to just get hkl from a scan title, rounded to 2 decimals. or use a fitting function to fit.

e.g. “scan_title = (1.000019 -0.000008 0.499983) th4th, T = 4.3406 K”

-> array([ 1. , -0. , 0.5 ])

get_peak_center(tavi_data: TaviData, scan_num: int, IPTS: int | None = None, exp_num: int | None = None, mode: FixedEnergyMode = FixedEnergyMode.FIX_Ef, fixed_energy: float = 0, fit_package: FitPackage = FitPackage.lmfit, model_dict: list[tuple[ModelName, dict[str, Any]]] = []) list[DataPoint][source]

Create one DataPoint per fitted peak center in the scan.

get_psi(q_norm: float, ei: float, ef: float) float[source]

Get psi. Angle between ki and Q.

get_scan_type() RawScanType[source]

Get scan type (ORNLSpice).

get_score(file_path: str) float[source]

Get score for scan.

get_two_theta(q_norm: float, ei: float, ef: float) float[source]

Get two_theta, only q_norm is required.

load(file_path: str) Scan[source]

Load scan data.

load_hb1a_4c_ub(file_path: str) dict[source]

C sharp ub specific to ORNL/HB1A in 4 circle mode.

parse_external_metadata(file_path: str, ub_name: str) dict[str, Any][source]

Parse corresponding file in ubconf as external metadata.

parse_metadata(file_path: str) ScanMetadata[source]

Parse metadata.

parse_scan_values(file_path: str) ScanData[source]

Parse scan values.

parse_tavi_metadata(file_path: str) TaviMetadata[source]

Parse metadata.

Expected Data Layout

The loader expects a structure similar to:

exp815/
  Datafiles/
    HB1_exp0815_scan0003.dat
  UBConf/
    UB13Jun2019_41635PM.ini

The ubconf entry in the .dat header is used to resolve the UB file under the sibling UBConf directory.

Typical Loading Flow

ORNLSpiceLoader.load(path) performs these steps:

  1. Parse numeric scan arrays via parse_scan_values.

  2. Parse header metadata via parse_metadata.

  3. Parse TAVI metadata via parse_tavi_metadata.

  4. Build provenance via create_provenance.

  5. Resolve and parse external UB metadata via parse_external_metadata.

  6. Merge external UB data into metadata and return a RawScan.

Method Notes

parse_scan_values

  • Converts SPICE column names into valid attribute-like keys.

  • Handles empty/invalid measurement sections by returning empty arrays.

parse_metadata

  • Collects key/value header fields before # col_headers =.

  • Captures terminal status entries (for example scan completed/stopped).

parse_external_metadata

  • Supports INI-like UB files and legacy XML UB content.

  • Returns a plain dictionary that can be merged into scan metadata.

Minimal Example

from tavi.library.storage.loader.ornl_spice_loader import ORNLSpiceLoader
from tavi.library.storage.local_file_store import LocalFileStore

loader = ORNLSpiceLoader(LocalFileStore())
scan = loader.load("test_data/exp815/Datafiles/HB1_exp0815_scan0003.dat")

print(scan.uuid)
print(scan.metadata.ubconf)
print(scan.data.h[:3])