Experiment

Experiment is the data-access layer that sits between a loader (for example ORNLSpiceLoader) and the analysis classes. It loads scans from disk, looks them up by scan number, and derives per-scan quantities such as peak centers, (h, k, l), and momentum transfer.

Overview

Source module:

tavi.library.experiment.experiment

Primary class:

class tavi.library.experiment.experiment.Experiment(mode: ~tavi.library.experiment.enum.FixedEnergyMode = FixedEnergyMode.FIX_Ef, fixed_energy: float = 0, loader: ~tavi.library.storage.loader.interface.base.AbstractLoader = <tavi.library.storage.loader.ornl_spice_loader.ORNLSpiceLoader object>)[source]

Experiment class.

create_sample(ub_path: str) Sample[source]

Can create a sample from a specific ub file if exist.

get_closest_to_center_data_point(scan_identifier: dict, fit_package: FitPackage, model_dict: list[tuple[ModelName, dict[str, Any]]]) DataPoint[source]

Get the motor angles closest to the center of fitted data.

get_data_from_scan_number(scan_identifier: dict) RawScan[source]

Get scan object from a scan number.

Parameters:

scan_identifier – Dict with “scan_num” and optional “IPTS” / “exp_num” keys used to locate the scan.

Returns:

The matching RawScan.

Raises:

ValueError – If zero or more than one scan matches.

get_delta_q(scan_identifier: dict) ndarray[source]

Get delta q of a scan.

get_ei_ef(e: float) tuple[float, float][source]

Get (ei, ef) given the complementary energy.

get_hkl(scan_identifier: dict, use_title: bool = True, model_dict: list[tuple[ModelName, dict[str, Any]]] = []) ndarray[source]

Extract the (h, k, l) from a scan title, rounded to 2 decimals.

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

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

get_peak_center(scan_identifier: dict, fit_package: FitPackage, model_dict: list[tuple[ModelName, dict[str, Any]]]) DataPoint[source]

Find the center of the peak. It’s used in refining UB matrix, which can be compared with SPICE results for validation.

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

Get psi. Angle between ki and Q.

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

Get two_theta, only q_norm is required.

load_file(file_path: str) None[source]

Load a single scan.

Directly using ORNL loader for now. will implement rounded approach later.

load_folder(folder_path: str) None[source]

Load all SPICE .dat files in a folder of scans.

set_fixed_energy(e: float) None[source]

Set ei or ef based on mode.

Fixed-Energy Mode

An Experiment is created in a fixed-energy mode (fixed \(E_i\) or fixed \(E_f\)) with the corresponding energy value. That mode determines how get_ei_ef maps a fitted energy transfer back to incident/scattered energies, and which energy is held constant when peaks are located.

Method Notes

load_file / load_folder

  • Ingest a single scan file or every scan in a directory into the experiment.

get_peak_center

  • Fits the scan(s) and returns a list[DataPoint] – one per fitted peak center. Inelastic scans may yield more than one DataPoint.

  • Takes a FitPackage and a model_dict (see Fit Package).

get_hkl / get_delta_q / get_two_theta / get_psi

  • Derive reciprocal-space and angular quantities for a located scan.

create_sample

  • Builds a Sample (oriented lattice + UB) from a UB configuration file.

Minimal Example

from tavi.library.experiment.experiment import Experiment
from tavi.library.experiment.enum import FixedEnergyMode
from tavi.library.fit.fit import FitPackage, ModelName

experiment = Experiment(mode=FixedEnergyMode.FIX_Ef, fixed_energy=14.503)
experiment.load_folder("/path/to/exp1091/Datafiles")

# One DataPoint per fitted peak; flatten across scans into a single list.
scan_list = [531, 532, 533]
peaks = [
    dp
    for i in scan_list
    for dp in experiment.get_peak_center(
        {"scan_num": i}, FitPackage.lmfit, [(ModelName.Gaussian, dict(guess=True))]
    )
]
print(peaks[0].hkl, peaks[0].ei, peaks[0].ef)