MayaFlux 0.1.0
Digital-First Multimedia Processing Framework
Loading...
Searching...
No Matches
DataIO.hpp
Go to the documentation of this file.
1#pragma once
2
5
6namespace MayaFlux::Yantra {
7
8/**
9 * @struct IO
10 * @brief Input/Output container for computation pipeline data flow with structure preservation.
11 * @tparam T Data type that satisfies ComputeData concept
12 *
13 * Encapsulates data with associated structure information and metadata for pipeline operations.
14 * The structure (dimensions and modality) is automatically inferred at construction time,
15 * ensuring that all data flowing through operations carries its dimensional context.
16 *
17 * Key Features:
18 * - Automatic structure inference from data type and content
19 * - Dimension and modality preservation through pipeline operations
20 * - Flexible metadata storage for operation-specific information
21 * - Move semantics for efficiency with large data
22 */
23template <ComputeData T = std::vector<Kakshya::DataVariant>>
24struct MAYAFLUX_API IO {
25 T data; ///< The actual computation data
26 std::vector<Kakshya::DataDimension> dimensions; ///< Data dimensional structure
27 Kakshya::DataModality modality {}; ///< Data modality (audio, image, spectral, etc.)
28 std::unordered_map<std::string, std::any> metadata; ///< Associated metadata
29 bool b_container_processing {};
30
31 std::optional<std::shared_ptr<Kakshya::SignalSourceContainer>> container; ///< Optional reference to container, required for regions
32
33 IO() = default; ///< Default constructor
34
35 /**
36 * @brief Construct from data by copy with automatic structure inference
37 * @param d Data to copy into the container
38 *
39 * Automatically infers dimensions and modality from the data type and content.
40 * For containers, uses their existing dimensional information.
41 * For other types, creates appropriate dimensional structures.
42 */
43 IO(const T& d)
44 : data(d)
45 {
46 auto [dims, mod] = infer_structure(d);
47 dimensions = std::move(dims);
48 modality = mod;
49 }
50
51 /**
52 * @brief Construct from data by copy with container reference and automatic structure inference
53 * @param d Data to copy into the container
54 * @param cont Shared pointer to the associated RegionLike Data
55 *
56 * This constructor is useful when the data is part of a larger container
57 * and we want to maintain a reference to that container for context.
58 */
59 IO(const T& d, const std::shared_ptr<Kakshya::SignalSourceContainer>& cont)
60 : data(d)
61 , container(cont)
62 {
63 auto [dims, mod] = infer_structure(d);
64 dimensions = std::move(dims);
65 modality = mod;
66 }
67
68 /**
69 * @brief Construct from data by move with automatic structure inference
70 * @param d Data to move into the container
71 *
72 * Automatically infers dimensions and modality before moving the data.
73 * More efficient for large data structures.
74 */
75 IO(T&& d)
76 : data(std::move(d))
77 {
78 // Note: We infer from data after it's moved, which should be fine
79 // since inference typically only needs type info and basic properties
80 auto [dims, mod] = infer_structure(data);
81 dimensions = std::move(dims);
82 modality = mod;
83 }
84
85 /**
86 * @brief Construct from data by move with automatic structure inference
87 * @param d Data to move into the container
88 * @param cont Shared pointer to the associated RegionLike Data
89 *
90 * Automatically infers dimensions and modality before moving the data.
91 * More efficient for large data structures.
92 */
93 IO(T&& d, const std::shared_ptr<Kakshya::SignalSourceContainer>& cont)
94 : data(std::move(d))
95 , container(cont)
96 {
97 auto [dims, mod] = infer_structure(data);
98 dimensions = std::move(dims);
99 modality = mod;
100 }
101
102 /**
103 * @brief Construct with move and explicit structure information
104 * @param d Data to move
105 * @param dims Explicit dimensional structure
106 * @param mod Explicit data modality
107 */
108 IO(T&& d, std::vector<Kakshya::DataDimension> dims, Kakshya::DataModality mod)
109 : data(std::move(d))
110 , dimensions(std::move(dims))
111 , modality(mod)
112 {
113 }
114
115 /**
116 * @brief Construct with move and explicit structure information
117 * @param d Data to move
118 * @param container Shared pointer to the associated RegionLike Data
119 * @param dims Explicit dimensional structure
120 * @param mod Explicit data modality
121 */
122 IO(T&& d, const std::shared_ptr<Kakshya::SignalSourceContainer> container, std::vector<Kakshya::DataDimension> dims, Kakshya::DataModality mod)
123 : data(std::move(d))
124 , container(container)
125 , dimensions(std::move(dims))
126 , modality(mod)
127 {
128 }
129
130 /**
131 * @brief Access underlying data (const)
132 * @return Const reference to the data
133 */
134 const T& operator*() const { return data; }
135
136 /**
137 * @brief Access underlying data (mutable)
138 * @return Mutable reference to the data
139 */
140 T& operator*() { return data; }
141
142 /**
143 * @brief Set or update the associated container reference
144 * @param cont Shared pointer to the new container
145 */
146 void set_container(const std::shared_ptr<Kakshya::SignalSourceContainer>& cont)
147 {
148 container = cont;
149 }
150
151 /**
152 * @brief Check if a container reference is associated
153 * @return True if a container is set
154 */
155 [[nodiscard]] bool has_container() const
156 {
157 return container.has_value();
158 }
159
160 /**
161 * @brief Check if processing is needed (for container types)
162 * @return True if processing is required before data extraction
163 */
164 [[nodiscard]] bool needs_processig() const
165 {
166 if constexpr (std::is_same_v<T, std::shared_ptr<Kakshya::SignalSourceContainer>>) {
167 return b_container_processing;
168 }
169 return false;
170 }
171
172 /**
173 * @brief Set whether processing is needed (for container types)
174 * @param val True if processing should be done before data extraction
175 */
177 {
178 if constexpr (std::is_same_v<T, std::shared_ptr<Kakshya::SignalSourceContainer>>) {
179 b_container_processing = val;
180 } else {
181 b_container_processing = false;
182 }
183 }
184
185 /**
186 * @brief Check if data has specific modality
187 * @param target_modality Modality to check for
188 * @return True if data matches the target modality
189 */
190 [[nodiscard]] bool has_modality(Kakshya::DataModality target_modality) const
191 {
192 return modality == target_modality;
193 }
194
195 /**
196 * @brief Get total number of elements across all dimensions
197 * @return Product of all dimension sizes
198 */
199 [[nodiscard]] uint64_t get_total_elements() const
200 {
201 uint64_t total = 1;
202 for (const auto& dim : dimensions) {
203 total *= dim.size;
204 }
205 return total;
206 }
207
208 /**
209 * @brief Find dimension by semantic role
210 * @param role Dimension role to search for
211 * @return Index of dimension with that role, or -1 if not found
212 */
214 {
215 return Kakshya::find_dimension_by_role(dimensions, role);
216 }
217
218 /**
219 * @brief Check if data is suitable for a specific type of processing
220 * @param required_modality Required data modality
221 * @param min_dimensions Minimum number of dimensions required
222 * @return True if data meets the requirements
223 */
224 [[nodiscard]] bool is_suitable_for_processing(Kakshya::DataModality required_modality,
225 size_t min_dimensions = 1) const
226 {
227 if constexpr (RequiresContainer<T>) {
228 if (!container.has_value()) {
229 return false;
230 }
231 }
232 return (modality == required_modality || required_modality == Kakshya::DataModality::UNKNOWN) && dimensions.size() >= min_dimensions;
233 }
234
235 /**
236 * @brief Update structure information (use carefully!)
237 * @param new_dims New dimensional structure
238 * @param new_modality New data modality
239 *
240 * This allows operations to update structure info when they transform
241 * the data in ways that change its dimensional characteristics.
242 */
243 void update_structure(std::vector<Kakshya::DataDimension> new_dims,
244 Kakshya::DataModality new_modality)
245 {
246 dimensions = std::move(new_dims);
247 modality = new_modality;
248 }
249
250 /**
251 * @brief Add or update metadata entry
252 * @param key Metadata key
253 * @param value Metadata value
254 */
255 template <typename ValueType>
256 void set_metadata(const std::string& key, ValueType&& value)
257 {
258 metadata[key] = std::forward<ValueType>(value);
259 }
260
261 /**
262 * @brief Get metadata entry with type safety
263 * @tparam ValueType Expected value type
264 * @param key Metadata key
265 * @return Optional value if found and correct type
266 */
267 template <typename ValueType>
268 std::optional<ValueType> get_metadata(const std::string& key) const
269 {
270 auto it = metadata.find(key);
271 if (it != metadata.end()) {
272 try {
273 return std::any_cast<ValueType>(it->second);
274 } catch (const std::bad_any_cast&) {
275 return std::nullopt;
276 }
277 }
278 return std::nullopt;
279 }
280};
281
282/**
283 * @class OpUnit
284 * @brief Abstract base class for operation units in recursive processing graphs.
285 * @tparam T Data type that satisfies ComputeData concept
286 *
287 * Represents a single computational node that can process data and maintain
288 * dependencies on other operation units. Forms the building blocks of
289 * computation pipelines with automatic dependency resolution.
290 */
291template <ComputeData T = std::vector<Kakshya::DataVariant>>
292class OpUnit {
293public:
294 virtual ~OpUnit() = default;
295
296 /**
297 * @brief Execute the operation on input data
298 * @param input Input data container with metadata
299 * @return Processed output data container
300 */
301 virtual IO<T> execute(const IO<T>& input) = 0;
302
303 /**
304 * @brief Get the name/identifier of this operation
305 * @return String name of the operation
306 */
307 [[nodiscard]] virtual std::string get_name() const = 0;
308
309 /**
310 * @brief Add a dependency operation unit
311 * @param dep Shared pointer to the dependency operation
312 *
313 * Dependencies are executed before this operation in the pipeline.
314 */
315 void add_dependency(std::shared_ptr<OpUnit<T>> dep)
316 {
317 dependencies.push_back(std::move(dep));
318 }
319
320 /**
321 * @brief Get all dependency operations
322 * @return Const reference to the dependencies vector
323 */
324 const auto& get_dependencies() const { return dependencies; }
325
326protected:
327 std::vector<std::shared_ptr<OpUnit<T>>> dependencies; ///< Operation dependencies
328};
329
330/// Helper to detect if a type is an IO
331template <typename>
332struct is_IO : std::false_type { };
333/// Specialization for IO types
334template <typename T>
335struct is_IO<IO<T>> : std::true_type { };
336
337/**
338 * @concept OperationReadyData
339 * @brief Concept to constrain types suitable for operation units
340 *
341 * Ensures that types used in operation units are either:
342 * - MultiVariant (universal data variant)
343 * - RegionLike (regions or region groups)
344 * - EigenMatrixLike (Eigen matrices/vectors)
345 * - IO (input/output containers with structure)
346 */
347template <typename T>
349
350using DataIO = IO<std::vector<Kakshya::DataVariant>>; ///< IO for universal data variant
352using RegionIO = IO<Kakshya::Region>; ///< IO for single regions
353using RegionGroupIO = IO<Kakshya::RegionGroup>; ///< IO for region groups
354using SegmentIO = IO<std::vector<Kakshya::RegionSegment>>; ///< IO for region segments
355
356}
virtual std::string get_name() const =0
Get the name/identifier of this operation.
virtual IO< T > execute(const IO< T > &input)=0
Execute the operation on input data.
virtual ~OpUnit()=default
const auto & get_dependencies() const
Get all dependency operations.
Definition DataIO.hpp:324
void add_dependency(std::shared_ptr< OpUnit< T > > dep)
Add a dependency operation unit.
Definition DataIO.hpp:315
std::vector< std::shared_ptr< OpUnit< T > > > dependencies
Operation dependencies.
Definition DataIO.hpp:327
Abstract base class for operation units in recursive processing graphs.
Definition DataIO.hpp:292
Concept for Eigen matrix types with double scalar.
Definition DataSpec.hpp:221
Concept to constrain types suitable for operation units.
Definition DataIO.hpp:348
DataModality
Data modality types for cross-modal analysis.
Definition NDData.hpp:78
Role
Semantic role of the dimension.
Definition NDData.hpp:145
bool has_container() const
Check if a container reference is associated.
Definition DataIO.hpp:155
bool is_suitable_for_processing(Kakshya::DataModality required_modality, size_t min_dimensions=1) const
Check if data is suitable for a specific type of processing.
Definition DataIO.hpp:224
void set_metadata(const std::string &key, ValueType &&value)
Add or update metadata entry.
Definition DataIO.hpp:256
const T & operator*() const
Access underlying data (const)
Definition DataIO.hpp:134
bool needs_processig() const
Check if processing is needed (for container types)
Definition DataIO.hpp:164
IO()=default
Default constructor.
T data
The actual computation data.
Definition DataIO.hpp:25
std::unordered_map< std::string, std::any > metadata
Associated metadata.
Definition DataIO.hpp:28
std::optional< ValueType > get_metadata(const std::string &key) const
Get metadata entry with type safety.
Definition DataIO.hpp:268
std::optional< std::shared_ptr< Kakshya::SignalSourceContainer > > container
Optional reference to container, required for regions.
Definition DataIO.hpp:31
IO(T &&d, std::vector< Kakshya::DataDimension > dims, Kakshya::DataModality mod)
Construct with move and explicit structure information.
Definition DataIO.hpp:108
T & operator*()
Access underlying data (mutable)
Definition DataIO.hpp:140
bool has_modality(Kakshya::DataModality target_modality) const
Check if data has specific modality.
Definition DataIO.hpp:190
IO(const T &d, const std::shared_ptr< Kakshya::SignalSourceContainer > &cont)
Construct from data by copy with container reference and automatic structure inference.
Definition DataIO.hpp:59
IO(T &&d)
Construct from data by move with automatic structure inference.
Definition DataIO.hpp:75
IO(const T &d)
Construct from data by copy with automatic structure inference.
Definition DataIO.hpp:43
void update_structure(std::vector< Kakshya::DataDimension > new_dims, Kakshya::DataModality new_modality)
Update structure information (use carefully!)
Definition DataIO.hpp:243
uint64_t get_total_elements() const
Get total number of elements across all dimensions.
Definition DataIO.hpp:199
IO(T &&d, const std::shared_ptr< Kakshya::SignalSourceContainer > &cont)
Construct from data by move with automatic structure inference.
Definition DataIO.hpp:93
int find_dimension_by_role(Kakshya::DataDimension::Role role) const
Find dimension by semantic role.
Definition DataIO.hpp:213
std::vector< Kakshya::DataDimension > dimensions
Data dimensional structure.
Definition DataIO.hpp:26
IO(T &&d, const std::shared_ptr< Kakshya::SignalSourceContainer > container, std::vector< Kakshya::DataDimension > dims, Kakshya::DataModality mod)
Construct with move and explicit structure information.
Definition DataIO.hpp:122
void set_container_processing(bool val)
Set whether processing is needed (for container types)
Definition DataIO.hpp:176
void set_container(const std::shared_ptr< Kakshya::SignalSourceContainer > &cont)
Set or update the associated container reference.
Definition DataIO.hpp:146
Input/Output container for computation pipeline data flow with structure preservation.
Definition DataIO.hpp:24
Helper to detect if a type is an IO.
Definition DataIO.hpp:332