Files
Jungfraujoch/reader/MarCCD.h
T
leonarski_f 30b6800289
Build Packages / build:windows:nocuda (push) Successful in 17m20s
Build Packages / build:windows:cuda (push) Successful in 19m52s
Build Packages / build:viewer-tgz:cpu (push) Successful in 9m38s
Build Packages / build:viewer-tgz:cuda (push) Successful in 11m18s
Build Packages / build:rugnux-tgz (x86_64) (push) Successful in 9m34s
Build Packages / build:rugnux:aarch64 (cross) (push) Successful in 5m42s
Build Packages / HDF5 consumer tests (DIALS, XDS) (push) Successful in 20m33s
Build Packages / Create release (push) Successful in 33s
Build Packages / build:rugnux:windows (push) Successful in 12m0s
Build Packages / build:rpm (rocky8_nocuda) (push) Successful in 15m42s
Build Packages / build:rpm (ubuntu2204_nocuda) (push) Successful in 14m59s
Build Packages / build:rpm (rocky9_nocuda) (push) Successful in 16m8s
Build Packages / build:rpm (ubuntu2404_nocuda) (push) Successful in 14m35s
Build Packages / build:rpm (rocky8_sls9) (push) Successful in 16m55s
Build Packages / build:rpm (rocky9_sls9) (push) Successful in 16m58s
Build Packages / Generate python client (push) Successful in 16s
Build Packages / build:rpm (rocky8) (push) Successful in 15m21s
Build Packages / Build documentation (push) Successful in 54s
Build Packages / build:rpm (rocky9) (push) Successful in 16m23s
Build Packages / build:rpm (ubuntu2204) (push) Successful in 12m2s
Build Packages / build:rpm (ubuntu2404) (push) Successful in 10m6s
Build Packages / Unit tests (push) Successful in 1h10m26s
v1.0.0-rc.171 (#81)
* Rugnux: basic support for CCD images (marCCD, SMV) and for gzipped miniCBF.
* `jfjoch_viewer`: opens the CCD formats, and fixes to the dataset plots.
* Documentation updates.

Reviewed-on: #81
Co-authored-by: Filip Leonarski <filip.leonarski@psi.ch>
2026-09-17 14:42:52 +02:00

67 lines
2.9 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>
// marCCD: an ordinary uncompressed TIFF whose 3072-byte instrument header sits in the gap between
// the TIFF header and the pixels. The image is read through libtiff, which the build already
// carries; the instrument header is a fixed-offset block of little-endian int32, so it is read
// directly. Rayonix MX-series and mar Mosaic detectors both write it, under half a dozen file
// extensions (.mccd, .img, .tif, or a bare frame number).
//
// Every value the header stores is an integer times a fixed scale: lengths in micrometres or
// nanometres, angles in millidegrees, the wavelength in 1e-5 A. They are converted here, so the
// rest of the code sees metres, degrees and angstroms like every other reader.
namespace marccd {
// Byte offset of the instrument header when the file does not say. Every writer seen puts it here
// and states it in TIFF tag 34710 as well.
inline constexpr uint32_t DEFAULT_HEADER_OFFSET = 1024;
// The private TIFF tag in which marCCD states where its own header begins.
inline constexpr uint16_t TIFFTAG_MARCCD_HEADER_OFFSET = 34710;
struct Header {
std::string detector; // from the TIFF Model/Software tags where they say anything
int64_t nx = 0; // fast dimension (columns)
int64_t ny = 0; // slow dimension (rows)
double pixel_x_m = 0;
double pixel_y_m = 0;
double distance_m = 0;
double beam_x_px = 0;
double beam_y_px = 0;
double wavelength_A = 0;
double start_angle_deg = 0;
double angle_increment_deg = 0;
double two_theta_deg = 0;
double exposure_s = 0;
int64_t saturated_value = 0;
std::string axis_name = "phi"; // the circle that moved between start and end
};
// True if the path names something this reader can open: a marCCD file, or a directory holding at
// least one. Reads a few kB at most.
bool CanRead(const std::string &path);
// The files of one sweep, in collection order. path is a directory, or one frame inside the sweep
// to take the whole sweep from. Empty where there is none.
std::vector<std::string> CollectSweep(const std::string &path);
// Header only - reads the first few kB of the file. Cheap enough to call per frame for the
// rotation angles.
Header ReadHeader(const std::string &path);
// Header + pixels of one file. out is resized to nx * ny.
Header Read(const std::string &path, std::vector<int32_t> &out);
// The same, widening the stored uint16 into memory the caller already has. scratch carries the
// 16-bit strip between frames, so a worker walking a sweep allocates once. Throws if the image
// does not fit in capacity pixels.
Header ReadInto(const std::string &path, int32_t *out, size_t capacity, std::vector<uint8_t> &scratch);
} // namespace marccd