Files
Jungfraujoch/reader/JFJochCBFReader.h
T
leonarski_f 6dfe065365
Build Packages / Create release (push) Successful in 16s
Build Packages / build:rugnux:aarch64 (cross) (push) Successful in 8m27s
Build Packages / build:rugnux-tgz (x86_64) (push) Successful in 9m15s
Build Packages / build:viewer-tgz:cpu (push) Successful in 10m11s
Build Packages / build:viewer-tgz:cuda (push) Successful in 12m6s
Build Packages / build:rpm (rocky8_nocuda) (push) Successful in 15m44s
Build Packages / build:rpm (rocky9_nocuda) (push) Successful in 16m1s
Build Packages / build:windows:nocuda (push) Successful in 17m29s
Build Packages / build:windows:cuda (push) Successful in 19m58s
Build Packages / HDF5 consumer tests (DIALS, XDS) (push) Successful in 24m7s
Build Packages / build:rpm (ubuntu2404_nocuda) (push) Successful in 19m8s
Build Packages / build:rugnux:windows (push) Successful in 10m58s
Build Packages / build:rpm (ubuntu2204_nocuda) (push) Successful in 20m46s
Build Packages / Generate python client (push) Successful in 53s
Build Packages / build:rpm (rocky8_sls9) (push) Successful in 20m13s
Build Packages / Build documentation (push) Successful in 1m36s
Build Packages / build:rpm (rocky9_sls9) (push) Successful in 19m57s
Build Packages / build:rpm (rocky8) (push) Successful in 18m7s
Build Packages / build:rpm (rocky9) (push) Successful in 18m54s
Build Packages / build:rpm (ubuntu2204) (push) Successful in 19m32s
Build Packages / build:rpm (ubuntu2404) (push) Successful in 17m30s
Build Packages / Unit tests (push) Successful in 1h39m2s
v1.0.0-rc.172 (#82)
* Fixed `jfjoch_broker` cancelling every data collection with a CUDA "out of memory" error after long operation: GPU memory no longer leaks with each collection.
* Rugnux scales a rotation sweep until the per-frame scales settle instead of for a fixed three rounds, and says so when they did not - merged intensities, and the space group, resolution cut and frame rejection read off them, change accordingly; `--scaling-iterations` is now the cap on that loop (default 100).
* Rugnux places every frame of a marCCD, SMV or miniCBF series at the spindle angle its own header states, so a series with missing frames, or with angles written modulo 360, is no longer read at the wrong geometry or refused.
* Every rotation run writes two diagnostic files beside its reflections: `<prefix>_detector.jpg`, the detector projection with the pixel mask and the detected beam-stop shadow drawn on it, and `<prefix>_plot.txt`, one row per image.

Reviewed-on: #82
Co-authored-by: Filip Leonarski <filip.leonarski@psi.ch>
2026-09-22 06:48:37 +02:00

62 lines
2.7 KiB
C++

// SPDX-FileCopyrightText: 2026 Filip Leonarski, Paul Scherrer Institute <filip.leonarski@psi.ch>
// SPDX-License-Identifier: GPL-3.0-only
#pragma once
#include <string>
#include <vector>
#include "JFJochReader.h"
#include "MiniCBF.h"
// Reads a rotation sweep straight from a directory of PILATUS miniCBF files - the form most
// facilities still archive - with no conversion step and no libcbf.
//
// The sweep's geometry comes from the first file's header; the rotation angle of each image comes
// from its own header, which costs only the bytes up to the binary separator. Images are decoded on
// demand, one per call, so any number of workers can read at once - there is no global lock as there
// is on the HDF5 path, HDF5 not being thread-safe.
//
// A raw CBF carries no analysis results, so this reader has no spots, no reflections and no snapshots;
// the dataset it builds is the geometry, the mask and nothing else, exactly as a plain DECTRIS file
// with no /entry/MX would give.
class JFJochCBFReader : public JFJochReader {
std::vector<std::string> files_;
std::shared_ptr<JFJochReaderDataset> dataset_;
minicbf::Header header0_;
bool LoadImage_i(std::shared_ptr<JFJochReaderDataset> &dataset,
DataMessage &message,
std::vector<uint8_t> &buffer,
int64_t image_number,
bool update_dataset) override;
// Decodes one image into the caller's byte buffer (RawByteBuffer or std::vector<uint8_t>) and
// returns the image that points at it. The compressed file is read through scratch, which the
// caller keeps between frames.
template <class Buffer>
CompressedImage DecodeInto(int64_t image_number, Buffer &buffer, std::vector<uint8_t> &scratch) const;
public:
~JFJochCBFReader() override = default;
// True if the path names something this reader can open: a miniCBF file, or a directory holding
// at least one. Cheap - it reads a few kB at most.
static bool CanRead(const std::string &path);
// path is a directory of *.cbf, or one *.cbf inside the sweep to take the whole directory from.
void ReadFiles(const std::string &path);
[[nodiscard]] uint64_t GetNumberOfImages() const override;
void Close() override;
// Whether the sweep really has an image at this point. A deposited series can be missing frames,
// and they are kept as gaps so that every image keeps the spindle angle its own header states;
// ReadRawImage hands such a slot back as "nothing to read".
[[nodiscard]] bool HasImage(int64_t image_number) const;
bool ReadRawImage(int64_t image_number, JFJochReaderRawImage &image) override;
[[nodiscard]] std::vector<SpotToSave> ReadSpots(int64_t image) const override;
};