// SPDX-FileCopyrightText: 2026 Filip Leonarski, Paul Scherrer Institute // SPDX-License-Identifier: GPL-3.0-only #pragma once #include #include #include // The LCLS-I XTC container, as far as reading camera frames out of it needs: what the LCLS data // system (pdsdata) wrote at LCLS until 2023, and what serial-crystallography depositions from that // era (Rayonix at MFX and XPP) are archived as. // // A file is a sequence of datagrams. Each is a 40-byte header - the event's clock time and timestamp // (16 bytes, whose top bits name the transition: Configure, BeginRun, ..., L1Accept for an event), // an environment word, and the outermost Xtc header - followed by the Xtc's payload. An Xtc header is // five 32-bit words: damage, the source (two words), the type and version, and the extent, which // counts the header itself. A container (type Id_Xtc) holds further Xtcs one after another; anything // else is a leaf holding one data object. A camera image is a leaf of type Id_Frame (Camera::FrameV1): // width, height, bit depth and offset, 32 bits each, then the pixels row by row. Everything is // little-endian and uncompressed. // // A run is written as several streams (-s00, -s01, ...) by different recorders, each holding a // share of the events. Their order across streams is the event time, which this reader does not // reconstruct: stills are independent, so the streams are read one after another. namespace xtc { // One camera image: where its pixels start in which file. struct Frame { std::string file; uint64_t offset = 0; // of the first pixel uint32_t width = 0; uint32_t height = 0; }; // True if the path is an XTC file (or a directory holding one) - by its first datagram, not its name. bool CanRead(const std::string &path); // The event streams of the path: the file itself, or every XTC file in a directory, by name. The // "smalldata" copies (.smd.xtc) carry the events without their images and are left out. std::vector CollectStreams(const std::string &path); // Every L1Accept of the file that holds a 16-bit camera image, in file order. Where an event holds // images from more than one camera, the largest is taken - the diffraction detector. std::vector IndexFrames(const std::string &file); // Reads one image as 32-bit pixels into out (width*height values), through scratch. void ReadFrame(const Frame &frame, int32_t *out, std::vector &scratch); } // namespace xtc