Files
Jungfraujoch/reader/SMV.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

71 lines
3.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 <map>
#include <string>
#include <vector>
// SMV: the format ADSC Quantum detectors wrote, and which Rayonix and several others still write.
// A plain ASCII header of "KEY=value;" lines between braces, then the pixels - no container, no
// compression, no binary header to decode by offset. The header states its own length, so even
// that is not assumed.
//
// {
// HEADER_BYTES= 512; DIM=2; BYTE_ORDER=little_endian; TYPE=unsigned_short;
// SIZE1=3072; SIZE2=3072; PIXEL_SIZE=0.102588; DISTANCE=250.000000;
// OSC_START=325.000000; OSC_RANGE=0.200000; WAVELENGTH=0.999839;
// BEAM_CENTER_X=157.500000; BEAM_CENTER_Y=157.500000;
// }
//
// Note the beam centre is in MILLIMETRES, not pixels, and its convention is the one thing writers
// disagree about - see the comment on beam_x_mm in the struct.
namespace smv {
struct Header {
int64_t nx = 0; // SIZE1, the fast dimension
int64_t ny = 0; // SIZE2, the slow dimension
size_t data_offset = 0; // HEADER_BYTES
bool little_endian = true;
int64_t bytes_per_pixel = 2; // TYPE: unsigned_short
double pixel_x_m = 0;
double pixel_y_m = 0;
double distance_m = 0;
// BEAM_CENTER_X/Y, converted to pixels here. Writers disagree about this field more than about
// any other: it is in millimetres, and which of the two is the fast direction is a convention
// rather than a rule. Where a file also carries the ADSC-era synonyms (BEAM_CENTRE_X, or the
// MOSFLM-ordered pair) they are read too. A run whose centre is wrong is recoverable - the
// beam-centre estimator measures it from the data - but a wrong one is not detectable here.
double beam_x_px = 0;
double beam_y_px = 0;
double wavelength_A = 0;
double start_angle_deg = 0; // OSC_START, falling back to PHI
double angle_increment_deg = 0; // OSC_RANGE
double two_theta_deg = 0;
double exposure_s = 0;
std::string detector; // DETECTOR_SN, where stated
std::string axis_name = "phi";
std::map<std::string, std::string> raw; // every key, for anything not modelled above
};
// True if the path names something this reader can open: an SMV file, or a directory holding at
// least one. Reads a few hundred bytes at most.
bool CanRead(const std::string &path);
// The files of one sweep, in collection order. path is a directory, or one frame inside it.
std::vector<std::string> CollectSweep(const std::string &path);
// Header only - reads just the leading brace block. Cheap enough to call per frame.
Header ReadHeader(const std::string &path);
// Header + pixels. out is resized to nx * ny.
Header Read(const std::string &path, std::vector<int32_t> &out);
// The same, widening the stored pixels into memory the caller already has. scratch carries the
// raw bytes between frames so a worker walking a sweep allocates once.
Header ReadInto(const std::string &path, int32_t *out, size_t capacity, std::vector<uint8_t> &scratch);
} // namespace smv