Source code for drtsans.mono.gpsans.cg2_spice_to_nexus
from drtsans.mono.convert_xml_to_nexus import EventNexusConverter
import os
import numpy as np
[docs]
class CG2EventNexusConvert(EventNexusConverter):
"""
SPICE to NeXus converter
"""
def __init__(self):
"""
initialization
work for 48 banks
"""
super(CG2EventNexusConvert, self).__init__("CG2", "CG2", 48)
def _map_detector_and_counts(self):
# map to bank
for bank_id in range(1, self._num_banks + 1):
# create TofHistogram instance
start_pid, end_pid = self.get_pid_range(bank_id)
pix_ids = np.arange(start_pid, end_pid + 1)
counts = self._spice_detector_counts[start_pid : end_pid + 1]
self._bank_pid_dict[bank_id] = pix_ids
self._bank_counts_dict[bank_id] = counts
[docs]
def get_pid_range(self, bank_id):
"""Set GPSANS bank and pixel ID relation
Parameters
----------
bank_id: int
bank ID from 1 to 48
Returns
-------
tuple
start PID, end PID (assuming PID are consecutive in a bank and end PID is inclusive)
"""
# Check input valid
if bank_id < 1 or bank_id > 48:
raise RuntimeError(f"CG2 (GP-SANS) has 88 banks indexed from 1 to 48. " f"Bank {bank_id} is out of range.")
# calculate starting PID
if bank_id <= 24:
# from 1 to 24: front panel
start_pid = (bank_id - 1) * 2 * 1024
else:
# from 25 to 48: back panel
start_pid = ((bank_id - 25) * 2 + 1) * 1024
# calculate end PID
end_pid = start_pid + 1023
return start_pid, end_pid
[docs]
def convert_spice_to_nexus(
ipts_number,
exp_number,
scan_number,
pt_number,
template_nexus,
output_dir=None,
spice_dir=None,
):
"""Convert one SPICE to NeXus
Parameters
----------
ipts_number: int
IPTS
exp_number: int
experiment number
scan_number: int
scan
pt_number: int
pt
template_nexus: str
path to a GPSANS nED event Nexus file especially for IDF
output_dir: None or str
output directory of the converted data
spice_dir: None or str
data file directory for SPICE file. None using default
Returns
-------
str
generated event Nexus file
"""
# Set the SPICE dir
if spice_dir is None:
# Build the default path to the SPICE files
spice_dir = f"/HFIR/CG2/IPTS-{ipts_number}/exp{exp_number}/Datafiles"
print(f"[INFO] SPICE file will be read from to directory {spice_dir}")
# verify path
assert os.path.exists(spice_dir), f"SPICE data directory {spice_dir} cannot be found"
spice_data_file = os.path.join(spice_dir, f"CG2_exp{exp_number}_scan{scan_number:04}_{pt_number:04}.xml")
assert os.path.exists(spice_data_file), f"SPICE file {spice_data_file} cannot be located"
# Template Nexus file
template_nexus_file = template_nexus
assert os.path.exists(template_nexus_file), f"Template NeXus file {template_nexus_file} cannot be located"
# Specify the default output directory
if output_dir is None:
output_dir = f"/HFIR/CG2/IPTS-{ipts_number}/shared/spice_nexus/Exp{exp_number}"
if not os.path.exists(output_dir):
raise RuntimeError(
f"Output NeXus directory {output_dir} does not exist."
f"Create directory {output_dir} and grand access to all IPTS users"
)
# output file name
out_nexus_file = f"CG2_{exp_number:04}{scan_number:04}{pt_number:04}.nxs.h5"
out_nexus_file = os.path.join(output_dir, out_nexus_file)
print(f"[INFO] NeXus file will be written to {out_nexus_file}")
# Load meta data and convert to NeXus format
das_log_map = {
"CG2:CS:SampleToSi": ("sample_to_flange", "mm"), # same
"sample_detector_distance": ("sdd", "m"), # same
"wavelength": ("lambda", "angstroms"), # angstroms -> A
"wavelength_spread": ("dlambda", "fraction"), # fraction -> None
"source_aperture_diameter": ("source_aperture_size", "mm"), # same
"sample_aperture_diameter": ("sample_aperture_size", "mm"), # same
"detector_trans_Readback": ("detector_trans", "mm"), # same
"source_distance": (
"source_distance",
"m",
), # same. source-aperture-sample-aperture
"beamtrap_diameter": ("beamtrap_diameter", "mm"), # not there
"dcal_Readback": ("dcal", "mm"), # required by pixel calibration
"attenuator": ("attenuator_pos", "mm"), # special
}
# init converter
converter = CG2EventNexusConvert()
# load instrument definition (IDF)
converter.load_idf(template_nexus_file)
# load SPICE (xml file)
converter.load_sans_xml(spice_data_file, das_log_map)
# generate event nexus
converter.generate_event_nexus(out_nexus_file)
return out_nexus_file