105#include <unordered_map>
116static_assert(
sizeof(
RoiPeak) == 8,
"RoiPeak must be 8 bytes to match the .roi format");
123template <
typename TData>
140 uint32_t getRoiHalfWidth()
const {
return half_width_; }
145 if (b == 0)
throw std::runtime_error(
"ROIBinSplit: bin_factor must be >= 1");
148 uint32_t getBinFactor()
const {
return bin_; }
160 void setDims(
const std::array<size_t, 3>& dims)
override {
161 if (dims_from_header_ || dims[0] == 0)
return;
164 void setDims(
size_t x,
size_t y = 1,
size_t z = 1) {
165 setDims(std::array<size_t, 3>{x, y, z});
168 size_t getNumPeaks()
const {
return peaks_.size(); }
169 size_t getBoxArea()
const {
return size_t(2 * half_width_ + 1) * (2 * half_width_ + 1); }
170 size_t getBgNx()
const {
return (dims_[0] + bin_ - 1) / bin_; }
171 size_t getBgNy()
const {
return (dims_[1] + bin_ - 1) / bin_; }
172 size_t getBgCount()
const {
return getBgNx() * getBgNy() * dims_[2]; }
173 size_t getRoiCount()
const {
return peaks_.size() * getBoxArea(); }
182 bool isInverse()
const override {
return is_inverse_; }
189 size_t getNumInputs()
const override {
return is_inverse_ ? 3 : 1; }
190 size_t getNumOutputs()
const override {
return is_inverse_ ? 1 : 3; }
193 return is_inverse_ ? std::vector<std::string>{
"output"}
194 : std::vector<std::string>{
"roi",
"bg",
"peaks"};
197 std::string
getName()
const override {
return "ROIBinSplit"; }
204 if (is_inverse_)
return elemType();
205 switch (output_index) {
206 case 0:
return elemType();
207 case 1:
return elemType();
208 default:
return static_cast<uint8_t
>(DataType::UINT8);
212 if (!is_inverse_)
return elemType();
213 switch (input_index) {
214 case 0:
return elemType();
215 case 1:
return elemType();
216 default:
return static_cast<uint8_t
>(DataType::UINT8);
224 const std::vector<void*>& inputs,
225 const std::vector<void*>& outputs,
226 const std::vector<size_t>& sizes
234 return peaks_.size() *
sizeof(
RoiPeak);
239 const std::vector<size_t>& input_sizes
242 return {dims_[0] * dims_[1] * dims_[2] *
sizeof(TData)};
245 return {getRoiCount() *
sizeof(TData),
246 getBgCount() *
sizeof(TData),
247 peaks_.size() *
sizeof(
RoiPeak)};
250 std::unordered_map<std::string, size_t>
253 return {{
"output", dims_[0] * dims_[1] * dims_[2] *
sizeof(TData)}};
254 return {{
"roi", getRoiCount() *
sizeof(TData)},
255 {
"bg", getBgCount() *
sizeof(TData)},
256 {
"peaks", peaks_.size() *
sizeof(
RoiPeak)}};
260 if (is_inverse_)
return (index == 0)
261 ? dims_[0] * dims_[1] * dims_[2] *
sizeof(TData) : 0;
263 case 0:
return getRoiCount() *
sizeof(TData);
264 case 1:
return getBgCount() *
sizeof(TData);
265 case 2:
return peaks_.size() *
sizeof(
RoiPeak);
274 if (max_size < kHeaderSize)
return 0;
276 auto put32 = [&](uint32_t v) { std::memcpy(buf + off, &v, 4); off += 4; };
277 auto put16 = [&](uint16_t v) { std::memcpy(buf + off, &v, 2); off += 2; };
278 put32(
static_cast<uint32_t
>(dims_[0]));
279 put32(
static_cast<uint32_t
>(dims_[1]));
280 put32(
static_cast<uint32_t
>(dims_[2]));
281 put32(
static_cast<uint32_t
>(peaks_.size()));
282 put16(
static_cast<uint16_t
>(half_width_));
283 put16(
static_cast<uint16_t
>(bin_));
284 buf[off++] = elemType();
290 if (size < kHeaderSize)
return;
292 auto get32 = [&]() { uint32_t v; std::memcpy(&v, buf + off, 4); off += 4;
return v; };
293 auto get16 = [&]() { uint16_t v; std::memcpy(&v, buf + off, 2); off += 2;
return v; };
294 dims_[0] = get32(); dims_[1] = get32(); dims_[2] = get32();
295 dims_from_header_ =
true;
296 const uint32_t npeaks = get32();
297 half_width_ = get16();
301 peaks_.assign(npeaks,
RoiPeak{0, 0, 0});
307 saved_dims_ = dims_; saved_hw_ = half_width_;
308 saved_bin_ = bin_; saved_npeaks_ = peaks_.size();
317 if (!state_saved_)
return;
318 dims_ = saved_dims_; half_width_ = saved_hw_; bin_ = saved_bin_;
319 if (peaks_.size() != saved_npeaks_) peaks_.resize(saved_npeaks_);
324 static constexpr size_t kHeaderSize = 22;
326 static constexpr uint8_t elemType() {
327 return static_cast<uint8_t
>(
sizeof(TData) == 4 ? DataType::FLOAT32
332 void computeOverlapFraction();
334 bool is_inverse_ =
false;
335 bool dims_from_header_ =
false;
336 bool state_saved_ =
false;
337 std::array<size_t, 3> dims_ = {0, 0, 1};
338 uint32_t half_width_ = 4;
340 double overlap_frac_ = 0.0;
342 std::vector<RoiPeak> peaks_;
343 RoiPeak* d_peaks_ =
nullptr;
345 std::array<size_t, 3> saved_dims_ = {0, 0, 1};
346 uint32_t saved_hw_ = 4;
347 uint32_t saved_bin_ = 1;
348 size_t saved_npeaks_ = 0;
351extern template class ROIBinSplitStage<float>;
352extern template class ROIBinSplitStage<double>;
Definition roibin_split_stage.h:124
size_t getActualOutputSize(int index) const override
Definition roibin_split_stage.h:259
std::vector< std::string > getOutputNames() const override
Definition roibin_split_stage.h:192
size_t serializeHeader(size_t, uint8_t *buf, size_t max_size) const override
Definition roibin_split_stage.h:273
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:316
std::unordered_map< std::string, size_t > getActualOutputSizesByName() const override
Definition roibin_split_stage.h:251
void setBinFactor(uint32_t b)
Definition roibin_split_stage.h:144
void setPeaks(const std::vector< RoiPeak > &peaks)
Supply peaks directly (used by tests).
void setInverse(bool inv) override
Definition roibin_split_stage.h:181
void setDims(const std::array< size_t, 3 > &dims) override
Definition roibin_split_stage.h:160
double getRoiOverlapFraction() const
Definition roibin_split_stage.h:178
uint8_t getInputDataType(size_t input_index) const override
Definition roibin_split_stage.h:211
bool isGraphCompatible() const override
Definition roibin_split_stage.h:186
std::vector< size_t > estimateOutputSizes(const std::vector< size_t > &input_sizes) const override
Definition roibin_split_stage.h:238
size_t getMaxHeaderSize(size_t) const override
Definition roibin_split_stage.h:304
uint16_t getStageTypeId() const override
Definition roibin_split_stage.h:199
std::vector< std::string > getRunNotes() const override
std::string getName() const override
Definition roibin_split_stage.h:197
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:139
uint8_t getOutputDataType(size_t output_index) const override
Definition roibin_split_stage.h:203
size_t estimateDeviceFootprintBytes(size_t) const override
Definition roibin_split_stage.h:233
void deserializeHeader(const uint8_t *buf, size_t size) override
Definition roibin_split_stage.h:289
void saveState() override
Definition roibin_split_stage.h:306
@ 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:139
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:111
uint16_t x
fast-axis pixel coordinate
Definition roibin_split_stage.h:113
uint16_t y
slow-axis pixel coordinate
Definition roibin_split_stage.h:114
uint32_t z
frame index (slowest axis)
Definition roibin_split_stage.h:112
Backend-neutral GPU type aliases.