99#include <unordered_map>
110static_assert(
sizeof(
RoiPeak) == 8,
"RoiPeak must be 8 bytes to match the .roi format");
117template <
typename TData>
134 uint32_t getRoiHalfWidth()
const {
return half_width_; }
139 if (b == 0)
throw std::runtime_error(
"ROIBinSplit: bin_factor must be >= 1");
142 uint32_t getBinFactor()
const {
return bin_; }
154 void setDims(
const std::array<size_t, 3>& dims)
override {
155 if (dims_from_header_ || dims[0] == 0)
return;
158 void setDims(
size_t x,
size_t y = 1,
size_t z = 1) {
159 setDims(std::array<size_t, 3>{x, y, z});
162 size_t getNumPeaks()
const {
return peaks_.size(); }
163 size_t getBoxArea()
const {
return size_t(2 * half_width_ + 1) * (2 * half_width_ + 1); }
164 size_t getBgNx()
const {
return (dims_[0] + bin_ - 1) / bin_; }
165 size_t getBgNy()
const {
return (dims_[1] + bin_ - 1) / bin_; }
166 size_t getBgCount()
const {
return getBgNx() * getBgNy() * dims_[2]; }
167 size_t getRoiCount()
const {
return peaks_.size() * getBoxArea(); }
176 bool isInverse()
const override {
return is_inverse_; }
183 size_t getNumInputs()
const override {
return is_inverse_ ? 3 : 1; }
184 size_t getNumOutputs()
const override {
return is_inverse_ ? 1 : 3; }
187 return is_inverse_ ? std::vector<std::string>{
"output"}
188 : std::vector<std::string>{
"roi",
"bg",
"peaks"};
191 std::string
getName()
const override {
return "ROIBinSplit"; }
198 if (is_inverse_)
return elemType();
199 switch (output_index) {
200 case 0:
return elemType();
201 case 1:
return elemType();
202 default:
return static_cast<uint8_t
>(DataType::UINT8);
206 if (!is_inverse_)
return elemType();
207 switch (input_index) {
208 case 0:
return elemType();
209 case 1:
return elemType();
210 default:
return static_cast<uint8_t
>(DataType::UINT8);
218 const std::vector<void*>& inputs,
219 const std::vector<void*>& outputs,
220 const std::vector<size_t>& sizes
228 return peaks_.size() *
sizeof(
RoiPeak);
233 const std::vector<size_t>& input_sizes
236 return {dims_[0] * dims_[1] * dims_[2] *
sizeof(TData)};
239 return {getRoiCount() *
sizeof(TData),
240 getBgCount() *
sizeof(TData),
241 peaks_.size() *
sizeof(
RoiPeak)};
244 std::unordered_map<std::string, size_t>
247 return {{
"output", dims_[0] * dims_[1] * dims_[2] *
sizeof(TData)}};
248 return {{
"roi", getRoiCount() *
sizeof(TData)},
249 {
"bg", getBgCount() *
sizeof(TData)},
250 {
"peaks", peaks_.size() *
sizeof(
RoiPeak)}};
254 if (is_inverse_)
return (index == 0)
255 ? dims_[0] * dims_[1] * dims_[2] *
sizeof(TData) : 0;
257 case 0:
return getRoiCount() *
sizeof(TData);
258 case 1:
return getBgCount() *
sizeof(TData);
259 case 2:
return peaks_.size() *
sizeof(
RoiPeak);
268 if (max_size < kHeaderSize)
return 0;
270 auto put32 = [&](uint32_t v) { std::memcpy(buf + off, &v, 4); off += 4; };
271 auto put16 = [&](uint16_t v) { std::memcpy(buf + off, &v, 2); off += 2; };
272 put32(
static_cast<uint32_t
>(dims_[0]));
273 put32(
static_cast<uint32_t
>(dims_[1]));
274 put32(
static_cast<uint32_t
>(dims_[2]));
275 put32(
static_cast<uint32_t
>(peaks_.size()));
276 put16(
static_cast<uint16_t
>(half_width_));
277 put16(
static_cast<uint16_t
>(bin_));
278 buf[off++] = elemType();
284 if (size < kHeaderSize)
return;
286 auto get32 = [&]() { uint32_t v; std::memcpy(&v, buf + off, 4); off += 4;
return v; };
287 auto get16 = [&]() { uint16_t v; std::memcpy(&v, buf + off, 2); off += 2;
return v; };
288 dims_[0] = get32(); dims_[1] = get32(); dims_[2] = get32();
289 dims_from_header_ =
true;
290 const uint32_t npeaks = get32();
291 half_width_ = get16();
295 peaks_.assign(npeaks,
RoiPeak{0, 0, 0});
301 saved_dims_ = dims_; saved_hw_ = half_width_;
302 saved_bin_ = bin_; saved_npeaks_ = peaks_.size();
311 if (!state_saved_)
return;
312 dims_ = saved_dims_; half_width_ = saved_hw_; bin_ = saved_bin_;
313 if (peaks_.size() != saved_npeaks_) peaks_.resize(saved_npeaks_);
318 static constexpr size_t kHeaderSize = 22;
320 static constexpr uint8_t elemType() {
321 return static_cast<uint8_t
>(
sizeof(TData) == 4 ? DataType::FLOAT32
326 void computeOverlapFraction();
328 bool is_inverse_ =
false;
329 bool dims_from_header_ =
false;
330 bool state_saved_ =
false;
331 std::array<size_t, 3> dims_ = {0, 0, 1};
332 uint32_t half_width_ = 4;
334 double overlap_frac_ = 0.0;
336 std::vector<RoiPeak> peaks_;
337 RoiPeak* d_peaks_ =
nullptr;
339 std::array<size_t, 3> saved_dims_ = {0, 0, 1};
340 uint32_t saved_hw_ = 4;
341 uint32_t saved_bin_ = 1;
342 size_t saved_npeaks_ = 0;
345extern template class ROIBinSplitStage<float>;
346extern template class ROIBinSplitStage<double>;
Definition roibin_split_stage.h:118
size_t getActualOutputSize(int index) const override
Definition roibin_split_stage.h:253
std::vector< std::string > getOutputNames() const override
Definition roibin_split_stage.h:186
size_t serializeHeader(size_t, uint8_t *buf, size_t max_size) const override
Definition roibin_split_stage.h:267
void onFinalize(size_t estimated_inlen, MemoryPool *pool) override
void execute(fz::stream_t stream, MemoryPool *pool, const std::vector< void * > &inputs, const std::vector< void * > &outputs, const std::vector< size_t > &sizes) override
void restoreState() override
Definition roibin_split_stage.h:310
std::unordered_map< std::string, size_t > getActualOutputSizesByName() const override
Definition roibin_split_stage.h:245
void setBinFactor(uint32_t b)
Definition roibin_split_stage.h:138
void setPeaks(const std::vector< RoiPeak > &peaks)
Supply peaks directly (used by tests).
void setInverse(bool inv) override
Definition roibin_split_stage.h:175
void setDims(const std::array< size_t, 3 > &dims) override
Definition roibin_split_stage.h:154
double getRoiOverlapFraction() const
Definition roibin_split_stage.h:172
uint8_t getInputDataType(size_t input_index) const override
Definition roibin_split_stage.h:205
bool isGraphCompatible() const override
Definition roibin_split_stage.h:180
std::vector< size_t > estimateOutputSizes(const std::vector< size_t > &input_sizes) const override
Definition roibin_split_stage.h:232
size_t getMaxHeaderSize(size_t) const override
Definition roibin_split_stage.h:298
uint16_t getStageTypeId() const override
Definition roibin_split_stage.h:193
std::vector< std::string > getRunNotes() const override
std::string getName() const override
Definition roibin_split_stage.h:191
void setPeaksFile(const std::string &path)
void setRoiHalfWidth(uint32_t hw)
ROI box half-width in pixels; the box is (2*hw+1)^2. Default 4 → 9x9.
Definition roibin_split_stage.h:133
uint8_t getOutputDataType(size_t output_index) const override
Definition roibin_split_stage.h:197
size_t estimateDeviceFootprintBytes(size_t) const override
Definition roibin_split_stage.h:227
void deserializeHeader(const uint8_t *buf, size_t size) override
Definition roibin_split_stage.h:283
void saveState() override
Definition roibin_split_stage.h:300
Definition algorithms.h:48
@ ROIBIN_SPLIT
Region-of-interest / binned-background split (ROIBIN-style dual-error-bound branching)
DataType
Element data type identifiers used in buffer and stage descriptors.
Definition fzm_format.h:118
Base class interface for all compression stages.
One Bragg-peak record, matching the on-disk .roi layout exactly (8 bytes).
Definition roibin_split_stage.h:105
uint16_t x
fast-axis pixel coordinate
Definition roibin_split_stage.h:107
uint16_t y
slow-axis pixel coordinate
Definition roibin_split_stage.h:108
uint32_t z
frame index (slowest axis)
Definition roibin_split_stage.h:106
Backend-neutral GPU type aliases.