// SPDX-FileCopyrightText: 2026 Filip Leonarski, Paul Scherrer Institute // SPDX-License-Identifier: GPL-3.0-only #pragma once #include #include #include #include "JFJochReader.h" #include "XTC.h" // Reads serial-crystallography stills straight from LCLS-I XTC files: one camera image per event, // from a single-panel detector such as the Rayonix CCDs at MFX and XPP. A multi-panel detector // (CSPAD, ePix, JUNGFRAU at LCLS) is stored as raw per-module data with its own calibration, and is // not read here. // // What the XTC states is used: the photon energy of every event's electron-beam record (the run is // read at their mean) and, for a Rayonix, the pixel size from its model and binning. The distance is // not recorded, and the beam centre is not either: the panel is placed square-on with its middle on // the beam, the run measures the centre, and the distance (and whatever the XTC did not state) is // given on the command line. // // The images are stills: no goniometer. Each is decoded on demand, the camera's stated pixel offset // taken off. A damaged or compressed image is left out, and so is an event the file ends inside. class JFJochXTCReader : public JFJochReader { std::vector frames_; std::shared_ptr dataset_; std::optional photon_energy_eV_; std::optional pixel_um_; float adu_per_photon_ = 1.0f; bool counts_in_photons_ = false; bool LoadImage_i(std::shared_ptr &dataset, DataMessage &message, std::vector &buffer, int64_t image_number, bool update_dataset) override; template CompressedImage DecodeInto(int64_t image_number, Buffer &buffer, std::vector &scratch) const; public: ~JFJochXTCReader() override = default; static bool CanRead(const std::string &path); // The event streams, read in the order given, their frames one after another. void ReadFiles(const std::vector &streams); // What the XTC stated; anything it did not is the caller's to give. [[nodiscard]] bool HasWavelength() const { return photon_energy_eV_.has_value(); } [[nodiscard]] bool HasPixelSize() const { return pixel_um_.has_value(); } // Converts to photons with this gain from here on (detector units per photon). void ApplyGain(float adu_per_photon); [[nodiscard]] bool CountsInPhotons() const { return counts_in_photons_; } [[nodiscard]] uint64_t GetNumberOfImages() const override; void Close() override; bool ReadRawImage(int64_t image_number, JFJochReaderRawImage &image) override; [[nodiscard]] std::vector ReadSpots(int64_t image) const override; };