Files
Jungfraujoch/reader/XTC.h
T
leonarski_fandClaude Opus 5.5 ae4786d14f WIP: LCLS-I XTC reader for single-panel camera stills (Rayonix), geometry from a DIALS .expt
Not yet compiled or tested: work stopped after the feasibility study.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-20 15:10:10 +02:00

51 lines
2.5 KiB
C++

// SPDX-FileCopyrightText: 2026 Filip Leonarski, Paul Scherrer Institute <filip.leonarski@psi.ch>
// SPDX-License-Identifier: GPL-3.0-only
#pragma once
#include <cstdint>
#include <string>
#include <vector>
// 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<std::string> 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<Frame> 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<uint8_t> &scratch);
} // namespace xtc