Source code for drtsans.mono.spice_data
# Module containing multiple classes to work with SPICE data
from typing import NamedTuple, List, Tuple, Union
import os
# Functions exposed to the general user (public) API
__all__ = ["SpiceRun", "map_to_nexus"]
[docs]
class SpiceRun(NamedTuple):
# Beam line
beam_line: str
# IPTS number
ipts_number: int
# Experiment number
exp_number: int
# Scan number
scan_number: int
# Pt number
pt_number: int
@property
def hfir_ipts_dir(self):
"""Standard HFIR SPICE data directory
Returns
-------
str
Path to IPTS directory
"""
return f"/HFIR/{self.beam_line}/IPTS-{self.ipts_number}/"
[docs]
def locate_spice_file(self, data_dir=None, raise_if_not_exist=True):
"""Locate SPICE file
Parameters
----------
data_dir : str or None
None is by default
raise_if_not_exist: bool
raise RuntimeError if the file does not exist
Returns
-------
str
Path to the SPICE file
"""
# standard spice file name
spice_file_name = f"{self.beam_line}_exp{self.exp_number}_scan{self.scan_number:04}_{self.pt_number:04}.xml"
# data file path
if data_dir is None:
# default: on the HFIR data server
data_dir = os.path.join(self.hfir_ipts_dir, f"exp{self.exp_number}/Datafiles")
spice_file_path = os.path.join(data_dir, spice_file_name)
# check file existence
if raise_if_not_exist and not os.path.exists(spice_file_path):
raise RuntimeError(f"SPICE file {spice_file_name} cannot be found in directory {data_dir}")
return spice_file_path
@property
def unique_run_number(self):
"""Create a unique run number
Note: HFIR experiment has unique experiment number.
Returns
-------
int
run number
"""
return int(f"{self.exp_number}{self.scan_number:04}{self.pt_number:04}")
[docs]
def unique_nexus_name(self, nexus_dir=None, raise_if_not_exist=False):
"""
Parameters
----------
nexus_dir: str, None
Path to nexus file. If None
raise_if_not_exist: bool
Check the nexus file exists or not. Raise exception if it does not
Returns
-------
str
full path to Nexus file
"""
# standard base name
base_nexus_name = f"{self.beam_line}_{self.unique_run_number:012}.nxs.h5"
if nexus_dir is None:
# use standard defalt
nexus_dir = os.path.join(self.hfir_ipts_dir, f"shared/Exp{self.exp_number}")
nexus_path = os.path.join(nexus_dir, base_nexus_name)
if raise_if_not_exist and not os.path.exists(nexus_path):
raise RuntimeError(
f"Spice converted Nexus file {base_nexus_name} does not exist in " f"directory {nexus_dir}"
)
return nexus_path
[docs]
def map_to_nexus(
beam_line: str,
ipts_number: int,
exp_number: int,
scan_pt_list: List[Union[Tuple[int, int], None]],
nexus_dir: str = None,
) -> List[str]:
"""Map SPICE information to converted NeXus file path
Parameters
----------
beam_line: str
CG2 or CG3
ipts_number: int
IPTS number
exp_number: int
experiment number
scan_pt_list: tuple
scan number, pt number
nexus_dir: str or None
directory to locate nexus file. None with default
Returns
-------
~list
list of Nexus files with the same order with scan-pt
"""
nexus_list = list()
for scan_pt in scan_pt_list:
if scan_pt is None:
nexus_file = None
else:
scan, pt = scan_pt
nexus_file = SpiceRun(beam_line, ipts_number, exp_number, scan, pt).unique_nexus_name(
nexus_dir, raise_if_not_exist=True
)
nexus_list.append(nexus_file)
return nexus_list