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>
58 lines
2.2 KiB
C++
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
|