From 51794204be6b849561464dfbbc72088d6c6d7208 Mon Sep 17 00:00:00 2001 From: "Aaron S. Brewster" Date: Thu, 18 Jan 2024 16:40:23 -0800 Subject: [PATCH] Add spectrum_required=False to FormatXTC (#674) New parameter and updated behavior to account for occasional dropped spectra in the XTC stream, when spectra a used to produce a calibrated average wavelength. If spectrum_required=True, and the FEE spectrometer is not found in an event, get_spectrum will raise a RuntimeError. If spectrum_required = False and spectra calibration constants (spectrum_eV_per_pixel and spectrum_eV_offset) are provided, wavelength_offset can be used to apply a general correction for any events with a dropped spectrum. If the spectrum is present and calibration constants are provided, wavelength_offset is ignored. --- newsfragments/674.feature | 1 + src/dxtbx/format/FormatXTC.py | 31 ++++++++++++++++++++++++++----- 2 files changed, 27 insertions(+), 5 deletions(-) create mode 100644 newsfragments/674.feature diff --git a/newsfragments/674.feature b/newsfragments/674.feature new file mode 100644 index 000000000..8eca3c80b --- /dev/null +++ b/newsfragments/674.feature @@ -0,0 +1 @@ +Better handle spectra calibration for bad data in XTC format using new parameter: spectrum_required diff --git a/src/dxtbx/format/FormatXTC.py b/src/dxtbx/format/FormatXTC.py index d77539128..e405c6baf 100644 --- a/src/dxtbx/format/FormatXTC.py +++ b/src/dxtbx/format/FormatXTC.py @@ -61,7 +61,13 @@ .help = Correction factor, needed during 2014 wavelength_offset = None .type = float - .help = Optional constant shift to apply to each wavelength + .help = Optional constant shift to apply to each wavelength. Note, if \ + spectrum_required = False and spectra calibration constants \ + (spectrum_eV_per_pixel and spectrum_eV_offset) are provided, \ + wavelength_offset can be used to apply a general correction \ + for any events with a dropped spectrum. If the spectrum is \ + present and calibration constants are provided, \ + wavelength_offset is ignored. spectrum_address = FEE-SPEC0 .type = str .help = Address for incident beam spectrometer @@ -82,6 +88,10 @@ spectrum_pedestal = None .type = path .help = Path to pickled pedestal file to subtract from the pedestal + spectrum_required = False + .type = bool + .help = Raise an exception for any event where the spectrum is not \ + available. filter { evr_address = evr1 .type = str @@ -113,7 +123,6 @@ def nullify_format_instance(self): @abstract class FormatXTC(FormatMultiImage, FormatStill, Format): def __init__(self, image_file, **kwargs): - if not self.understand(image_file): raise IncorrectFormatError(self, image_file) self.lazy = kwargs.get("lazy", True) @@ -407,11 +416,11 @@ def _beam(self, index=None): wavelength = serialtbx.detector.xtc.evt_wavelength( evt, delta_k=self.params.wavelength_delta_k ) + if self.params.wavelength_offset is not None: + wavelength += self.params.wavelength_offset if wavelength is None: self._beam_cache = None else: - if self.params.wavelength_offset is not None: - wavelength += self.params.wavelength_offset self._beam_cache = self._beam_factory.simple(wavelength) s, nsec = evt.get(psana.EventId).time() evttime = time.gmtime(s) @@ -424,6 +433,14 @@ def _beam(self, index=None): return self._beam_cache def get_spectrum(self, index=None): + if index is None: + index = 0 + spectrum = self._spectrum(index) + if not spectrum and self.params.spectrum_required: + raise RuntimeError("No spectrum in shot %d" % index) + return spectrum + + def _spectrum(self, index=None): if index is None: index = 0 if self.params.spectrum_eV_per_pixel is None: @@ -467,7 +484,11 @@ def get_spectrum(self, index=None): x = ( self.params.spectrum_eV_per_pixel * np.array(range(len(y))) ) + self.params.spectrum_eV_offset - return Spectrum(flex.double(x), flex.double(y)) + try: + sp = Spectrum(flex.double(x), flex.double(y)) + except RuntimeError: + return None + return sp def get_goniometer(self, index=None): return None