ClusterFile

Use frames() to iterate over complete frames, including empty frames and frames whose clusters are all rejected by ROI or noise filtering. Each result keeps its stored frame number; missing frame numbers are not synthesized.

using ClusterType = aare::Cluster<int32_t, 3, 3>;
aare::ClusterFile<ClusterType> file("clusters.clust");
for (auto &frame : file.frames()) {
    process_frame(frame.frame_number(), frame);
}

Use chunks() for the constructor’s chunk size, or chunks(10000) to request a different size for that traversal. The size must be positive and counts selected clusters after filtering. Chunks may split or combine frames, so their frame numbers are not reliable per-cluster metadata. Empty chunks are not yielded; only the final chunk can contain fewer clusters than requested. Both ranges apply the configured gain map and report incomplete files as errors, just like the explicit read methods.

Ranges borrow the file and consume its current position without rewinding. Constructing a range does not read; begin() reads the first result and increment reads the next. Breaking a loop does not read ahead. Use one traversal at a time and separate files for independent cursors. Switching to frame reads after a chunk stops partway through a frame raises an error until the remaining clusters in that frame have been read.

The file must outlive its ranges and iterators and must not be moved while they are in use. Iterators are move only and support C++17 range-based loops, not algorithms requiring copyable STL input iterators. References to a result last until advancement or iterator destruction. Move a result out with auto retained = std::move(frame) to retain it. Frame iteration reuses the current vector’s storage when it has not been moved out.

template<typename ClusterType, typename Enable = std::enable_if_t<is_cluster_v<ClusterType>>>
class ClusterFile

Read and write legacy binary cluster files.

Each frame is stored as:

  int32_t frame_number
  uint32_t number_of_clusters
  ClusterType clusters[number_of_clusters]

The format stores clusters as their native in-memory representation and has no metadata describing the cluster dimensions, value type, coordinate type, padding, or byte order. Readers must therefore use the same ClusterType and a compatible platform ABI as the writer.

Public Types

using FrameRange = ReadRange<true>
using ChunkRange = ReadRange<false>

Public Functions

inline ClusterFile(const std::filesystem::path &fname, size_t chunk_size = 1000, const std::string &mode = "r")

Open a cluster file.

Parameters:
  • fname – Path to the file.

  • chunk_size – Maximum number of selected clusters per chunk step.

  • mode – File mode: “r” to read, “w” to truncate and write, or “a” to append.

Throws:

std::runtime_error – If the mode is unsupported or the file cannot be opened.

inline FrameRange frames() &

Iterate over complete frames from the current file position.

Empty and fully filtered frames are yielded with their stored frame numbers. Reading stops only at a clean end of file. Advancing uses read_frame(), including its error for a prior partial-frame read.

FrameRange frames() && = delete
inline ChunkRange chunks() &

Iterate using the chunk size supplied to the constructor.

ChunkRange chunks() && = delete
inline ChunkRange chunks(size_t chunk_size) &

Iterate over chunks from the current file position.

Note

Chunks can span frames; their frame numbers are not per-cluster metadata. Advancing uses read_clusters() and propagates its errors. Only the final chunk can be short. Empty chunks are not yielded.

Parameters:

chunk_size – Maximum number of selected clusters per step.

Throws:

std::invalid_argument – If chunk_size is zero.

ChunkRange chunks(size_t) && = delete
inline ClusterVector<ClusterType> read_clusters(size_t n_clusters)

Read up to n_clusters without preserving frame boundaries.

Note

The returned vector may combine data from several frames, so its frame number must not be used as per-cluster metadata.

Parameters:

n_clusters – Maximum number of selected clusters to return.

Throws:

std::runtime_error – If the file is not open for reading, an I/O error occurs, or an incomplete frame header or cluster record is read.

Returns:

A cluster vector that may contain fewer clusters at a clean end of file.

inline std::optional<ClusterVector<ClusterType>> read_frame()

Read the next complete frame.

Note

A complete frame produces an engaged optional even when it contains no clusters or all of its clusters are removed by the configured filters.

Throws:

std::runtime_error – If the file is not open for reading, a prior partial-frame read left clusters unread, or the frame is incomplete.

Returns:

The selected clusters with the stored frame number set, or std::nullopt at a clean end of file before the next frame.

inline bool read_frame(ClusterVector<ClusterType> &clusters)

Read the next complete frame into an existing cluster vector.

Note

A complete frame is a successful read even when it contains no clusters or all of its clusters are removed by the configured filters.

Parameters:

clusters – Destination whose storage is reused when large enough. Existing clusters are replaced after a frame header is read and remain unchanged at a clean end of file.

Throws:

std::runtime_error – If the file is not open for reading, a prior partial-frame read left clusters unread, or a frame is incomplete.

Returns:

true when a complete frame was read, or false at a clean end of file before the next frame.

inline void write_frame(const ClusterVector<ClusterType> &clusters)

Write one frame to the file.

Parameters:

clusters – Clusters to write, including their frame number.

Throws:

std::runtime_error – If the file is not open for writing or any part of the frame cannot be written completely.

inline size_t chunk_size() const

Return the default number of selected clusters per chunk step.

inline size_t estimate_n_clusters() const

Estimate the number of clusters in the file from its size.

Frame-header bytes are included in the estimate, so it may exceed the actual number of clusters. The file position is not changed.

inline void set_roi(ROI roi)

Select clusters by their center coordinate when reading.

Parameters:

roi – Half-open region of interest: [xmin, xmax) x [ymin, ymax).

inline void set_noise_map(const NDView<int32_t, 2> noise_map)

Discard clusters that do not pass the noise thresholds.

Warning

The map must cover every cluster center coordinate in the file.

Parameters:

noise_map – Per-pixel noise indexed as [y, x]. The map is copied. A cluster is retained only when its central pixel exceeds the local noise, its highest 2x2 sum exceeds twice the noise, and its total sum exceeds three times the noise.

inline void set_gain_map(const NDView<double, 2> gain_map)

Apply a gain map to clusters selected while reading.

Note

Clusters whose complete footprint extends beyond the gain map are retained with all cluster data values set to zero.

Parameters:

gain_map – Per-pixel gain in ADU/energy, indexed as [y, x]. The map is copied and inverted internally.

inline void set_gain_map(const InvertedGainMap &gain_map)
inline void set_gain_map(const InvertedGainMap &&gain_map)
inline void close()

Close the file.

Calling close more than once is safe. The destructor closes an open file automatically.

inline int64_t tell()

Return the current byte position in the file.

Throws:

std::runtime_error – If the file is closed or its position cannot be determined.

template<bool ByFrame>
class ReadRange

Single-pass range over frames or chunks of selected clusters.

The range borrows the file and shares its current position with all other reads. Use only one traversal at a time. The file must outlive the range and its iterators and must not be moved while they are in use. Constructing a range does not read; begin() reads the first result. Calling begin() again starts at the file’s then-current position.

Public Functions

inline Iterator begin() const
inline Sentinel end() const
struct Sentinel
class Iterator

Move-only iterator for C++17 range-based loops.

References to the current vector are valid until the iterator is advanced or destroyed. Move the vector out to retain its storage. Frame iteration reuses storage when the vector is not moved out. This is not a copyable STL input iterator.

Public Types

using value_type = ClusterVector<ClusterType>

Public Functions

Iterator(const Iterator&) = delete
Iterator &operator=(const Iterator&) = delete
Iterator(Iterator&&) noexcept = default
Iterator &operator=(Iterator&&) noexcept = default
~Iterator() = default
inline value_type &operator*()
inline value_type *operator->()
inline Iterator &operator++()
inline void operator++(int)

Friends

inline friend bool operator==(const Iterator &it, Sentinel)
inline friend bool operator!=(const Iterator &it, Sentinel end)
inline friend bool operator==(Sentinel end, const Iterator &it)
inline friend bool operator!=(Sentinel end, const Iterator &it)