MayaFlux 0.5.0
Digital-First Multimedia Processing Framework
Loading...
Searching...
No Matches
NDimensionalContainer.hpp
Go to the documentation of this file.
1#pragma once
2
3#include "NDData/NDData.hpp"
4
5namespace MayaFlux::Kakshya {
6
7/**
8 * @brief Forward declarations for region structures used in N-dimensional data containers.
9 */
10struct Region;
11struct RegionGroup;
12struct RegionSegment;
13
14/**
15 * @brief Container structure for consistent dimension ordering.
16 *
17 * Provides standard indices and layout structures for common data types,
18 * supporting digital-first, data-driven workflows. These structures are
19 * not tied to analog metaphors, but instead facilitate generic, flexible
20 * processing of multi-dimensional data.
21 */
22struct MAYAFLUX_API ContainerDataStructure {
23
24 // Image/Video structures
25 // static constexpr size_t FRAME_DIM = 0;
26 // static constexpr size_t COLOR_DIM = 3;
27
28 // Spectral structures
29 // static constexpr size_t TIME_WINDOW_DIM = 0;
30
31 std::vector<DataDimension> dimensions;
32
33 std::optional<size_t> time_dims;
34 std::optional<size_t> channel_dims;
35 std::optional<size_t> height_dims;
36 std::optional<size_t> width_dims;
37 std::optional<size_t> frequency_dims;
38
39 DataModality modality {};
40 MemoryLayout memory_layout = MemoryLayout::ROW_MAJOR;
41 OrganizationStrategy organization = OrganizationStrategy::PLANAR;
42
43 /**
44 * @brief Construct a container structure with specified parameters.
45 * @param mod Data modality type
46 * @param org Organization strategy (default: PLANAR)
47 * @param layout Memory layout (default: ROW_MAJOR)
48 */
50 OrganizationStrategy org = OrganizationStrategy::PLANAR,
51 MemoryLayout layout = MemoryLayout::ROW_MAJOR);
52
54
55 /**
56 * @brief Get the expected dimension roles for this structure's modality.
57 * @return Vector of dimension roles in order
58 */
59 [[nodiscard]] std::vector<DataDimension::Role> get_expected_dimension_roles() const;
60
61 /**
62 * @brief Create structure for planar audio data.
63 * @return Containerstructure configured for planar audio
64 */
65 static ContainerDataStructure audio_planar();
66
67 /**
68 * @brief Create structure for interleaved audio data.
69 * @return Containerstructure configured for interleaved audio
70 */
71 static ContainerDataStructure audio_interleaved();
72
73 /**
74 * @brief Create structure for planar image data.
75 * @return Containerstructure configured for planar images
76 */
77 static ContainerDataStructure image_planar();
78
79 /**
80 * @brief Create structure for interleaved image data.
81 * @return Containerstructure configured for interleaved images
82 */
83 static ContainerDataStructure image_interleaved();
84
85 /**
86 * @brief Calculate expected number of data variants for given dimensions.
87 * @param dimensions Vector of dimension descriptors
88 * @return Expected number of DataVariant objects needed
89 */
90 [[nodiscard]] size_t get_expected_variant_count(const std::vector<DataDimension>& dimensions) const;
91
92 /**
93 * @brief Calculate size of a specific variant in the organization.
94 * @param dimensions Vector of dimension descriptors
95 * @param modality Data modality type
96 * @param organization Organization strategy
97 * @param variant_index Index of the variant (0-based)
98 * @return Number of elements in the specified variant
99 */
100 [[nodiscard]] static uint64_t get_variant_size(const std::vector<DataDimension>& dimensions,
101 DataModality modality, OrganizationStrategy organization, size_t variant_index = 0);
102 [[nodiscard]] uint64_t get_variant_size() const { return get_variant_size(dimensions, modality, organization); }
103
104 /**
105 * @brief Validate that dimensions match this structure's expectations.
106 * @param dimensions Vector of dimension descriptors to validate
107 * @return true if dimensions are valid for this structure
108 */
109 [[nodiscard]] bool validate_dimensions(const std::vector<DataDimension>& dimensions) const;
110
111 /**
112 * @brief Find the index of a dimension with the specified role.
113 * @param dimensions Vector of dimension descriptors to search
114 * @param role Dimension role to find
115 * @return Index of the dimension with the specified role
116 */
117 [[nodiscard]] size_t get_dimension_index_for_role(const std::vector<DataDimension>& dimensions,
118 DataDimension::Role role) const;
119
120 /**
121 * @brief Get total elements across all dimensions.
122 * @param dimensions Vector of dimension descriptors
123 * @return Total number of elements
124 */
125 [[nodiscard]] static uint64_t get_total_elements(const std::vector<DataDimension>& dimensions);
126 [[nodiscard]] uint64_t get_total_elements() const { return get_total_elements(dimensions); }
127
128 /**
129 * @brief Extract sample count from dimensions.
130 * @param dimensions Vector of dimension descriptors
131 * @return Number of samples in the temporal dimension
132 */
133 [[nodiscard]] static uint64_t get_samples_count(const std::vector<DataDimension>& dimensions);
134 [[nodiscard]] uint64_t get_samples_count() const { return get_samples_count(dimensions); }
135
136 /**
137 * @brief Get samples per channel (time dimension only).
138 * @param dimensions Vector of dimension descriptors
139 * @return Number of samples per channel
140 */
141 [[nodiscard]] static uint64_t get_samples_count_per_channel(const std::vector<DataDimension>& dimensions);
142 [[nodiscard]] uint64_t get_samples_count_per_channel() const { return get_samples_count_per_channel(dimensions); }
143
144 /**
145 * @brief Extract channel count from dimensions.
146 * @param dimensions Vector of dimension descriptors
147 * @return Number of channels
148 */
149 [[nodiscard]] static uint64_t get_channel_count(const std::vector<DataDimension>& dimensions);
150 [[nodiscard]] uint64_t get_channel_count() const { return get_channel_count(dimensions); }
151
152 /**
153 * @brief Get pixel count (spatial dimensions only).
154 * @param dimensions Vector of dimension descriptors
155 * @return Number of pixels
156 */
157 [[nodiscard]] static uint64_t get_pixels_count(const std::vector<DataDimension>& dimensions);
158 [[nodiscard]] uint64_t get_pixels_count() const { return get_pixels_count(dimensions); }
159
160 /**
161 * @brief Extract height from image/video dimensions.
162 * @param dimensions Vector of dimension descriptors
163 * @return Height in pixels
164 */
165 [[nodiscard]] static uint64_t get_height(const std::vector<DataDimension>& dimensions);
166 [[nodiscard]] uint64_t get_height() const { return get_height(dimensions); }
167
168 /**
169 * @brief Extract width from image/video dimensions.
170 * @param dimensions Vector of dimension descriptors
171 * @return Width in pixels
172 */
173 [[nodiscard]] static uint64_t get_width(const std::vector<DataDimension>& dimensions);
174 [[nodiscard]] uint64_t get_width() const { return get_width(dimensions); }
175
176 /**
177 * @brief Extract frame count from video dimensions.
178 * @param dimensions Vector of dimension descriptors
179 * @return Number of frames
180 */
181 [[nodiscard]] static size_t get_frame_count(const std::vector<DataDimension>& dimensions);
182 [[nodiscard]] size_t get_frame_count() const { return get_frame_count(dimensions); }
183
184 /**
185 * @brief Extract the size of non time dimensions (channel, spatial, frequency)
186 * @param dimensions Vector of dimension descriptors
187 * @return cumulative size of non time dimensions
188 */
189 [[nodiscard]] static size_t get_frame_size(const std::vector<DataDimension>& dimensions);
190 [[nodiscard]] size_t get_frame_size() const { return get_frame_size(dimensions); }
191};
192
193/**
194 * @class NDDataContainer
195 * @brief Abstract interface for N-dimensional data containers.
196 *
197 * NDDataContainer provides a dimension-agnostic API for accessing and manipulating
198 * multi-dimensional data (audio, video, tensors, etc). It is designed for digital-first,
199 * data-driven workflows, enabling flexible, efficient, and generic processing of
200 * structured data without imposing analog metaphors or legacy constraints.
201 *
202 * Key features:
203 * - Arbitrary dimension support (not limited to 2D or 3D)
204 * - Explicit memory layout control (row-major/column-major)
205 * - Region-based access for efficient subsetting and streaming
206 * - Thread-safe locking for concurrent processing
207 * - Support for multiple data types and precisions
208 * - Designed for composability with processors, buffers, and computational nodes
209 *
210 * This interface is the foundation for all high-level data containers in Maya Flux,
211 * enabling advanced workflows such as real-time streaming, offline analysis, and
212 * hybrid computational models.
213 */
214class MAYAFLUX_API NDDataContainer {
215public:
216 virtual ~NDDataContainer() = default;
217
218 /**
219 * @brief Get the dimensions describing the structure of the data.
220 * @return Vector of DataDimension objects (one per axis)
221 */
222 [[nodiscard]] virtual std::vector<DataDimension> get_dimensions() const = 0;
223
224 /**
225 * @brief Get the total number of elements in the container.
226 * @return Product of all dimension sizes
227 */
228 [[nodiscard]] virtual uint64_t get_total_elements() const = 0;
229
230 /**
231 * @brief Get the memory layout used by this container.
232 * @return Current memory layout (row-major or column-major)
233 */
234 [[nodiscard]] virtual MemoryLayout get_memory_layout() const = 0;
235
236 /**
237 * @brief Set the memory layout for this container.
238 * @param layout New memory layout to use
239 * @note May trigger data reorganization if implementation supports both layouts
240 */
241 virtual void set_memory_layout(MemoryLayout layout) = 0;
242
243 /**
244 * @brief Get the number of elements that constitute one "frame".
245 * For audio: channels per sample. For images: pixels per frame.
246 * @return Number of elements per frame
247 */
248 [[nodiscard]] virtual uint64_t get_frame_size() const = 0;
249
250 /**
251 * @brief Get the number of frames in the primary (temporal) dimension.
252 * @return Number of frames
253 */
254 [[nodiscard]] virtual uint64_t get_num_frames() const = 0;
255
256 /**
257 * @brief Get data for a specific region.
258 * @param region The region to extract data from
259 * @return std::vector<DataVariant> containing the region's data
260 */
261 [[nodiscard]] virtual std::vector<DataVariant> get_region_data(const Region& region) const = 0;
262
263 /**
264 * @brief Get data for multiple regions efficiently.
265 * @param regions Vector of regions to extract data from
266 * @return Vector of DataVariant vectors, one per region
267 */
268 [[nodiscard]] virtual std::vector<DataVariant> get_region_group_data(const RegionGroup& regions) const = 0;
269
270 /**
271 * @brief Get data for multiple region segments efficiently.
272 * @param segments Vector of region segments to extract data from
273 * @return Vector of DataVariant vectors, one per segment
274 */
275 [[nodiscard]] virtual std::vector<DataVariant> get_segments_data(const std::vector<RegionSegment>& segments) const = 0;
276
277 /**
278 * @brief Set data for a specific region.
279 * @param region The region to write data to
280 * @param data The data to write
281 */
282 virtual void set_region_data(const Region& region, const std::vector<DataVariant>& data) = 0;
283
284 /**
285 * @brief Get a single frame of data efficiently.
286 * @param frame_index Index of the frame (in the temporal dimension)
287 * @return Span of data representing one complete frame
288 */
289 [[nodiscard]] auto get_frame(uint64_t frame_index) const -> FrameView
290 {
291 return FrameView(get_frame_span_impl(frame_index));
292 }
293
294 /**
295 * @brief Get multiple frames efficiently.
296 * @param output Buffer to write frames into
297 * @param start_frame First frame index
298 * @param num_frames Number of frames to retrieve
299 */
300 template <DataVariantElement T>
301 void get_frames(std::span<T> output, uint64_t start_frame, uint64_t num_frames) const
302 {
303 get_frames_impl(output.data(), output.size(), start_frame, num_frames, typeid(T));
304 }
305
306 /**
307 * @brief Get a single frame of data as a typed span.
308 * @tparam T Element type to interpret the frame data as
309 * @param frame_index Index of the frame (in the temporal dimension)
310 * @return Span of data representing one complete frame, interpreted as type T
311 */
312 template <DataVariantElement T>
313 [[nodiscard]] auto get_frame_as(uint64_t frame_index) const -> std::span<const T>
314 {
315 return get_frame(frame_index).template as<T>();
316 }
317
318 /**
319 * @brief Get multiple frames efficiently as a typed span.
320 *
321 * Convenience wrapper over get_frames() for callers that know the element
322 * type statically but hold the output buffer as a plain vector rather than
323 * a typed span. Deduces T from the vector element type; no visitor, no
324 * type query needed at the call site.
325 *
326 * @tparam T Element type. Must satisfy DataVariantElement and match the
327 * container's native element type. The impl silently no-ops or
328 * errors on mismatch depending on the container.
329 * @param output Destination vector. Resized to num_frames * frame_size
330 * by the caller before passing; content is overwritten.
331 * @param start_frame First frame index.
332 * @param num_frames Number of frames to retrieve.
333 */
334 template <DataVariantElement T>
335 void get_frames_as(std::vector<T>& output, uint64_t start_frame, uint64_t num_frames) const
336 {
337 get_frames_impl(output.data(), output.size(), start_frame, num_frames, typeid(T));
338 }
339
340 /**
341 * @brief Runtime query for the native scalar element type of this container.
342 *
343 * Mirrors FrameView::element_type(). Typical return values:
344 * - typeid(uint8_t) -- 8-bit image / video / window
345 * - typeid(uint16_t) -- 16-bit image
346 * - typeid(float) -- HDR image
347 * - typeid(double) -- audio / plot
348 *
349 * Use this to branch once before calling get_value_at<T>() when the
350 * container's native type is not statically known at the call site.
351 */
352 [[nodiscard]] virtual std::type_index value_element_type() const = 0;
353
354 /**
355 * @brief Read a single element at the given N-dimensional coordinates.
356 *
357 * Returns a default-constructed T on coordinate out-of-range or type mismatch.
358 * No conversion is performed: T must match the container's native element type
359 * (query value_element_type() first when the type is not statically known).
360 *
361 * @tparam T Element type. Must satisfy DataVariantElement.
362 * @param coordinates N-dimensional coordinate vector.
363 * @return Native-typed value, zero-initialised on error.
364 */
365 template <DataVariantElement T>
366 [[nodiscard]] T get_value_at(const std::vector<uint64_t>& coordinates) const
367 {
368 T v {};
369 get_value_impl(coordinates, &v, typeid(T));
370 return v;
371 }
372
373 /**
374 * @brief Write a single element at the given N-dimensional coordinates.
375 *
376 * No-ops on coordinate out-of-range or type mismatch.
377 * T must match the container's native element type.
378 *
379 * @tparam T Element type. Must satisfy DataVariantElement.
380 * @param coordinates N-dimensional coordinate vector.
381 * @param value Value to write.
382 */
383 template <DataVariantElement T>
384 void set_value_at(const std::vector<uint64_t>& coordinates, T value)
385 {
386 set_value_impl(coordinates, &value, typeid(T));
387 }
388
389 /**
390 * @brief Add a named group of regions to the container.
391 * @param group RegionGroup to add
392 */
393 virtual void add_region_group(const RegionGroup& group) = 0;
394
395 /**
396 * @brief Get a region group by name.
397 * @param name Name of the region group
398 * @return Reference to the RegionGroup
399 */
400 [[nodiscard]] virtual RegionGroup get_region_group(const std::string& name) const = 0;
401
402 /**
403 * @brief Get all region groups in the container.
404 * @return Map of region group names to RegionGroup objects
405 */
406 [[nodiscard]] virtual std::unordered_map<std::string, RegionGroup> get_all_region_groups() const = 0;
407
408 /**
409 * @brief Remove a region group by name.
410 * @param name Name of the region group to remove
411 */
412 virtual void remove_region_group(const std::string& name) = 0;
413
414 /**
415 * @brief Check if a region is loaded in memory.
416 * @param region Region to check
417 * @return true if region is loaded, false otherwise
418 */
419 [[nodiscard]] virtual bool is_region_loaded(const Region& region) const = 0;
420
421 /**
422 * @brief Load a region into memory.
423 * @param region Region to load
424 */
425 virtual void load_region(const Region& region) = 0;
426
427 /**
428 * @brief Unload a region from memory.
429 * @param region Region to unload
430 */
431 virtual void unload_region(const Region& region) = 0;
432
433 /**
434 * @brief Convert coordinates to linear index based on current memory layout.
435 * @param coordinates N-dimensional coordinates
436 * @return Linear index into the underlying data storage
437 */
438 [[nodiscard]] virtual uint64_t coordinates_to_linear_index(const std::vector<uint64_t>& coordinates) const = 0;
439
440 /**
441 * @brief Convert linear index to coordinates based on current memory layout.
442 * @param linear_index Linear index into the underlying data storage
443 * @return N-dimensional coordinates
444 */
445 [[nodiscard]] virtual std::vector<uint64_t> linear_index_to_coordinates(uint64_t linear_index) const = 0;
446
447 /**
448 * @brief Clear all data in the container.
449 */
450 virtual void clear() = 0;
451
452 /**
453 * @brief Get a raw pointer to the underlying data storage.
454 * @return Pointer to raw data (type depends on DataVariant)
455 */
456 [[nodiscard]] virtual const void* get_raw_data() const = 0;
457
458 /**
459 * @brief Check if the container currently holds any data.
460 * @return true if data is present, false otherwise
461 */
462 [[nodiscard]] virtual bool has_data() const = 0;
463
464 /**
465 * @brief Get the data structure defining this container's layout.
466 * @return Reference to the ContainerDataStructure
467 */
468 [[nodiscard]] virtual ContainerDataStructure& get_structure() = 0;
469 [[nodiscard]] virtual const ContainerDataStructure& get_structure() const = 0;
470
471 /**
472 * @brief Set the data structure for this container.
473 * @param structure New ContainerDataStructure to apply
474 * @note This may trigger reorganization of existing data to match the new structure.
475 */
476 virtual void set_structure(ContainerDataStructure structure) = 0;
477
478protected:
479 /**
480 * @brief Implementation-specific method to retrieve a frame span.
481 * @param frame_index Index of the frame to retrieve
482 * @return DataSpanVariant representing the frame's data
483 */
484 [[nodiscard]] virtual auto get_frame_span_impl(uint64_t frame_index) const -> DataSpanVariant = 0;
485
486 /**
487 * @brief Implementation-specific method to retrieve multiple frames.
488 *
489 * Implementations write up to count * frame_size elements into output,
490 * starting from start_frame. The type parameter indicates the expected
491 * element type; implementations may choose to support or reject it based
492 * on their native data type, but must not write past the output buffer
493 * regardless.
494 *
495 * @param output Pointer to caller-owned buffer for frame data
496 * @param count Number of frames to retrieve (output buffer size in frames)
497 * @param start_frame First frame index to retrieve
498 * @param num_frames Number of frames to retrieve
499 * @param type Type information for the expected element type (e.g. float, uint8_t)
500 */
501 virtual void get_frames_impl(void* output, size_t count, uint64_t start_frame, uint64_t num_frames, const std::type_info& type) const = 0;
502
503 /**
504 * @brief Type-erased single-element read.
505 *
506 * Implementations copy the native element at @p coords into @p out
507 * if @p type matches their native type, otherwise no-op.
508 * @p out points to a caller-owned buffer of exactly sizeof(native type) bytes.
509 */
510 virtual void get_value_impl(const std::vector<uint64_t>& coords,
511 void* out,
512 const std::type_info& type) const = 0;
513
514 /**
515 * @brief Type-erased single-element write.
516 *
517 * Implementations copy from @p in into their storage at @p coords
518 * if @p type matches their native type, otherwise no-op.
519 * @p in points to a caller-owned buffer of exactly sizeof(native type) bytes.
520 */
521 virtual void set_value_impl(const std::vector<uint64_t>& coords,
522 const void* in,
523 const std::type_info& type) = 0;
524};
525
526} // namespace MayaFlux::Kakshya
size_t count
float value
std::shared_ptr< Core::VKImage > output
Zero-copy typed view over one frame of container storage.
Definition NDData.hpp:621
virtual std::vector< DataVariant > get_region_group_data(const RegionGroup &regions) const =0
Get data for multiple regions efficiently.
virtual void set_region_data(const Region &region, const std::vector< DataVariant > &data)=0
Set data for a specific region.
void get_frames_as(std::vector< T > &output, uint64_t start_frame, uint64_t num_frames) const
Get multiple frames efficiently as a typed span.
virtual void unload_region(const Region &region)=0
Unload a region from memory.
virtual void clear()=0
Clear all data in the container.
virtual void set_value_impl(const std::vector< uint64_t > &coords, const void *in, const std::type_info &type)=0
Type-erased single-element write.
virtual RegionGroup get_region_group(const std::string &name) const =0
Get a region group by name.
virtual void add_region_group(const RegionGroup &group)=0
Add a named group of regions to the container.
virtual void get_frames_impl(void *output, size_t count, uint64_t start_frame, uint64_t num_frames, const std::type_info &type) const =0
Implementation-specific method to retrieve multiple frames.
virtual const ContainerDataStructure & get_structure() const =0
virtual std::type_index value_element_type() const =0
Runtime query for the native scalar element type of this container.
virtual bool has_data() const =0
Check if the container currently holds any data.
void set_value_at(const std::vector< uint64_t > &coordinates, T value)
Write a single element at the given N-dimensional coordinates.
virtual std::vector< DataDimension > get_dimensions() const =0
Get the dimensions describing the structure of the data.
virtual void set_memory_layout(MemoryLayout layout)=0
Set the memory layout for this container.
virtual ContainerDataStructure & get_structure()=0
Get the data structure defining this container's layout.
void get_frames(std::span< T > output, uint64_t start_frame, uint64_t num_frames) const
Get multiple frames efficiently.
virtual void load_region(const Region &region)=0
Load a region into memory.
virtual void set_structure(ContainerDataStructure structure)=0
Set the data structure for this container.
T get_value_at(const std::vector< uint64_t > &coordinates) const
Read a single element at the given N-dimensional coordinates.
virtual std::unordered_map< std::string, RegionGroup > get_all_region_groups() const =0
Get all region groups in the container.
virtual bool is_region_loaded(const Region &region) const =0
Check if a region is loaded in memory.
virtual void remove_region_group(const std::string &name)=0
Remove a region group by name.
auto get_frame(uint64_t frame_index) const -> FrameView
Get a single frame of data efficiently.
virtual const void * get_raw_data() const =0
Get a raw pointer to the underlying data storage.
virtual std::vector< DataVariant > get_segments_data(const std::vector< RegionSegment > &segments) const =0
Get data for multiple region segments efficiently.
virtual auto get_frame_span_impl(uint64_t frame_index) const -> DataSpanVariant=0
Implementation-specific method to retrieve a frame span.
virtual std::vector< DataVariant > get_region_data(const Region &region) const =0
Get data for a specific region.
virtual MemoryLayout get_memory_layout() const =0
Get the memory layout used by this container.
virtual uint64_t coordinates_to_linear_index(const std::vector< uint64_t > &coordinates) const =0
Convert coordinates to linear index based on current memory layout.
virtual uint64_t get_frame_size() const =0
Get the number of elements that constitute one "frame".
auto get_frame_as(uint64_t frame_index) const -> std::span< const T >
Get a single frame of data as a typed span.
virtual void get_value_impl(const std::vector< uint64_t > &coords, void *out, const std::type_info &type) const =0
Type-erased single-element read.
virtual uint64_t get_total_elements() const =0
Get the total number of elements in the container.
virtual uint64_t get_num_frames() const =0
Get the number of frames in the primary (temporal) dimension.
virtual std::vector< uint64_t > linear_index_to_coordinates(uint64_t linear_index) const =0
Convert linear index to coordinates based on current memory layout.
Abstract interface for N-dimensional data containers.
typename detail::span_const_from_vector_variant< DataVariant >::type DataSpanVariant
Definition NDData.hpp:592
DataModality
Data modality types for cross-modal analysis.
Definition NDData.hpp:164
MemoryLayout
Memory layout for multi-dimensional data.
Definition NDData.hpp:65
OrganizationStrategy
Data organization strategy for multi-channel/multi-frame data.
Definition NDData.hpp:75
Container structure for consistent dimension ordering.
Role
Semantic role of the dimension.
Definition NDData.hpp:234
Organizes related signal regions into a categorized collection.
Represents a point or span in N-dimensional space.
Definition Region.hpp:73