Files
Jungfraujoch/reader/CrystFELGeometry.h
T
leonarski_fandClaude Opus 5.5 ce528f3a14 rugnux: read stills through a CrystFEL geometry file (--crystfel-geometry)
A CrystFEL .geom (current and old syntax) is parsed for panels (pixel ranges, fs/ss, corners),
clen/coffset (a number, or an HDF5 path read as mm), res, adu_per_eV/adu_per_photon, max_adu,
no_index, bad regions (panel, whole-frame or lab-plane) and the HDF5 mask (mask/mask_file,
mask_good/mask_bad). JFJochCrystFELReader reads the frames the geometry's data path names - a 3D
stack (Cheetah CXI), one 2D frame per file, or one group per shot (/%/data) - from a file or a
directory, puts the panels on one flat image at their rounded positions with gaps and bad regions
masked, and converts to photons where a gain is stated (otherwise the pre-scan measures it). One
wavelength and one camera length per run: values taken from the files are averaged over the first
file. Panel positions are used as given. Frames stored as one deflate(+shuffle) chunk are read raw
under the HDF5 lock and decoded outside it.

Replaces the MPCCD-specific reader of the previous commit.

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

58 lines
2.2 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 <optional>
#include <string>
#include <vector>
// A CrystFEL detector geometry file (.geom), as far as it places pixels and says what they are worth:
// the panels with their pixel ranges in the stored frame, fast/slow-scan directions and corners, the
// camera length, the pixel size, the gain and the regions to leave out. Both the current syntax and
// the older one - global keys that only take effect for the panels that follow them, bad regions
// stated in whole-frame coordinates - are read.
//
// Every length is in pixels except clen and coffset, which are in metres. A value CrystFEL takes from
// the image file instead (clen = /path, photon_energy = /path) is kept as that path, for the reader
// to resolve.
namespace crystfel {
struct Panel {
std::string name;
int64_t min_fs = 0, max_fs = 0, min_ss = 0, max_ss = 0; // inclusive, in the stored frame
double fs_x = 1, fs_y = 0, ss_x = 0, ss_y = 1;
double corner_x = 0, corner_y = 0;
double res = 0; // pixels per metre
std::string clen; // metres, or an HDF5 path
double coffset = 0; // metres
std::optional<double> adu_per_eV;
std::optional<double> adu_per_photon;
std::optional<double> max_adu;
bool no_index = false;
};
// A region to leave out: either a pixel range on one panel (or, in the old syntax, on the whole
// frame), or a box in the laboratory plane, in pixels.
struct BadRegion {
std::string panel; // empty: fs/ss are whole-frame coordinates
bool in_lab = false;
double min_x = 0, max_x = 0, min_y = 0, max_y = 0;
int64_t min_fs = 0, max_fs = 0, min_ss = 0, max_ss = 0;
};
struct Geometry {
std::vector<Panel> panels;
std::vector<BadRegion> bad;
std::string data = "/data/data";
std::string photon_energy; // eV, or an HDF5 path
std::string mask; // HDF5 path, or empty
std::string mask_file; // file holding it, or empty for the image file itself
uint32_t mask_good = 0, mask_bad = 0;
};
Geometry Read(const std::string &filename);
} // namespace crystfel