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
* 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>
67 lines
2.9 KiB
C++
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
|