MayaFlux 0.4.0
Digital-First Multimedia Processing Framework
Loading...
Searching...
No Matches
DataUtils.cpp
Go to the documentation of this file.
1#include "DataUtils.hpp"
2
3namespace MayaFlux::Kakshya {
4
5uint64_t calculate_total_elements(const std::vector<DataDimension>& dimensions)
6{
7 if (dimensions.empty())
8 return 0;
9
10 return std::transform_reduce(dimensions.begin(), dimensions.end(),
11 uint64_t(1), std::multiplies<>(),
12 [](const DataDimension& dim) { return dim.size; });
13}
14
15uint64_t calculate_frame_size(const std::vector<DataDimension>& dimensions)
16{
17 if (dimensions.empty())
18 return 0;
19
20 return std::transform_reduce(
21 dimensions.begin() + 1, dimensions.end(),
22 uint64_t(1), std::multiplies<>(),
23 [](const DataDimension& dim) constexpr { return dim.size; });
24}
25
26std::type_index get_variant_type_index(const DataVariant& data)
27{
28 return std::visit([](const auto& vec) -> std::type_index {
29 return std::type_index(typeid(decltype(vec)));
30 },
31 data);
32}
33
35{
36 std::visit([&](const auto& input_vec, auto& output_vec) {
37 using InputType = typename std::decay_t<decltype(input_vec)>::value_type;
38 using OutputType = typename std::decay_t<decltype(output_vec)>::value_type;
39
40 if constexpr (ProcessableData<InputType> && ProcessableData<OutputType>) {
41 std::vector<OutputType> temp_storage;
42 auto input_span = extract_from_variant<OutputType>(input, temp_storage);
43
44 output_vec.resize(input_span.size());
45 std::copy(input_span.begin(), input_span.end(), output_vec.begin());
46 } else {
47 error<std::invalid_argument>(
50 std::source_location::current(),
51 "Unsupported type conversion from {} to {}",
52 typeid(InputType).name(),
53 typeid(OutputType).name());
54 }
55 },
56 input, output);
57}
58
59void set_metadata_value(std::unordered_map<std::string, std::any>& metadata, const std::string& key, std::any value)
60{
61 metadata[key] = std::move(value);
62}
63
64int find_dimension_by_role(const std::vector<DataDimension>& dimensions, DataDimension::Role role)
65{
66 auto it = std::ranges::find_if(dimensions,
67 [role](const DataDimension& dim) { return dim.role == role; });
68
69 return (it != dimensions.end()) ? static_cast<int>(std::distance(dimensions.begin(), it)) : -1;
70}
71
72DataModality detect_data_modality(const std::vector<DataDimension>& dimensions)
73{
74 if (dimensions.empty()) {
76 }
77
78 size_t time_dims = 0, spatial_dims = 0, channel_dims = 0, frequency_dims = 0, custom_dims = 0;
79 size_t total_spatial_elements = 1;
80 size_t total_channels = 0;
81
82 for (const auto& dim : dimensions) {
83 if (dim.grouping) {
84 switch (dim.role) {
95 if (dim.grouping->count == 3)
97 if (dim.grouping->count == 4)
99 break;
100 default:
101 if (dim.grouping->count == 16)
103 break;
104 }
105 }
106 }
107
108 for (const auto& dim : dimensions) {
109 switch (dim.role) {
111 time_dims++;
112 break;
116 spatial_dims++;
117 total_spatial_elements *= dim.size;
118 break;
120 channel_dims++;
121 total_channels += dim.size;
122 break;
124 frequency_dims++;
125 break;
127 default:
128 custom_dims++;
129 break;
130 }
131 }
132
133 if (time_dims == 1 && spatial_dims == 0 && frequency_dims == 0) {
134 if (channel_dims == 0) {
136 } else if (channel_dims == 1) {
137 return (total_channels <= 1) ? DataModality::AUDIO_1D : DataModality::AUDIO_MULTICHANNEL;
138 } else {
140 }
141 }
142
143 if (time_dims >= 1 && frequency_dims >= 1) {
144 if (spatial_dims == 0 && channel_dims <= 1) {
146 }
148 }
149
150 if (spatial_dims >= 2 && time_dims == 0) {
151 if (spatial_dims == 2) {
152 if (channel_dims == 0) {
154 } else if (channel_dims == 1 && total_channels >= 3) {
156 } else {
158 }
159 } else if (spatial_dims == 3) {
161 }
162 }
163
164 if (time_dims >= 1 && spatial_dims >= 2) {
165 if (spatial_dims == 2) {
166 if (channel_dims == 0 || (channel_dims == 1 && total_channels <= 1)) {
168 } else {
170 }
171 }
173 }
174
175 if (spatial_dims == 2 && time_dims == 0 && channel_dims >= 1) {
176 if (total_spatial_elements >= 64 && total_channels >= 1) {
178 }
179 }
180
182}
183
185 const std::vector<DataDimension>& dimensions,
186 const DataVariant& source)
187{
188 const DataModality base = detect_data_modality(dimensions);
189
190 if (base != DataModality::AUDIO_1D && base != DataModality::TENSOR_ND) {
191 return base;
192 }
193
194 return std::visit([&base](const auto& vec) {
195 using V = typename std::decay_t<decltype(vec)>::value_type;
196
197 if constexpr (ComplexData<V>) {
199 } else if constexpr (IntegerData<V>) {
201 } else {
202 return base;
203 }
204 },
205 source);
206}
207
208std::vector<DataDimension> detect_data_dimensions(const DataVariant& data)
209{
211 "{}\n{}\n{}\n{}",
212 "Inferring structure from single DataVariant is not advisable as the method makes naive assumptions that can lead to massive computational errors. "
213 "If the variant is part of a container, region, or segment, please use the appropriate method instead. "
214 "If the variant is part of a vector, please use infer_from_data_variant_vector instead. "
215 "If you are sure you want to proceed, please ignore this warning.");
216
217 return std::visit([](const auto& vec) -> std::vector<DataDimension> {
218 using ValueType = typename std::decay_t<decltype(vec)>::value_type;
219
220 std::vector<DataDimension> dims;
221
222 if constexpr (DecimalData<ValueType>) {
223 dims.emplace_back(DataDimension::time(vec.size()));
224
225 } else if constexpr (ComplexData<ValueType>) {
226 dims.emplace_back(DataDimension::frequency(vec.size()));
227
228 } else if constexpr (IntegerData<ValueType>) {
229 dims.emplace_back(DataDimension::spatial(vec.size(), 'x'));
230 } else if constexpr (GlmData<ValueType>) {
231 constexpr size_t components = glm_component_count<ValueType>();
233
234 if constexpr (GlmVec2Type<ValueType>) {
236 } else if constexpr (GlmVec3Type<ValueType>) {
238 } else if constexpr (GlmVec4Type<ValueType>) {
240 } else if constexpr (GlmMatrixType<ValueType>) {
242 }
243
244 dims.push_back(DataDimension::grouped(
245 "glm_structured_data",
246 static_cast<uint64_t>(vec.size()),
247 static_cast<uint8_t>(components),
248 role));
249 } else {
250 dims.emplace_back(DataDimension::time(vec.size()));
251 }
252
253 return dims;
254 },
255 data);
256}
257
258std::vector<DataDimension> detect_data_dimensions(
259 const std::vector<DataVariant>& variants)
260{
262 "{}\n{}\n{}",
263 "Inferring structure from DataVariant vector is not advisable as the method makes naive assumptions that can lead to massive computational errors. "
264 "If the variants are part of a container, region, or segment, please use the appropriate method instead. "
265 "If you are sure you want to proceed, please ignore this warning.");
266
267 if (variants.empty()) {
268 std::vector<DataDimension> dims;
269 dims.emplace_back("empty_variants", 0, 1, DataDimension::Role::CUSTOM);
270 return dims;
271 }
272
273 std::vector<DataDimension> dimensions;
274 size_t variant_count = variants.size();
275
276 size_t first_variant_size = std::visit([](const auto& vec) -> size_t {
277 return vec.size();
278 },
279 variants[0]);
280
281 bool consistent_glm = std::ranges::all_of(variants, [](const auto& variant) {
282 return std::visit([](const auto& vec) -> bool {
283 using ValueType = typename std::decay_t<decltype(vec)>::value_type;
284 return GlmData<ValueType>;
285 },
286 variant);
287 });
288
289 bool consistent_decimal = std::ranges::all_of(variants, [](const auto& variant) {
290 return std::visit([](const auto& vec) -> bool {
291 using ValueType = typename std::decay_t<decltype(vec)>::value_type;
292 return MayaFlux::DecimalData<ValueType>;
293 },
294 variant);
295 });
296
297 bool consistent_complex = std::ranges::all_of(variants, [](const auto& variant) {
298 return std::visit([](const auto& vec) -> bool {
299 using ValueType = typename std::decay_t<decltype(vec)>::value_type;
300 return MayaFlux::ComplexData<ValueType>;
301 },
302 variant);
303 });
304
305 bool consistent_integer = std::ranges::all_of(variants, [](const auto& variant) {
306 return std::visit([](const auto& vec) -> bool {
307 using ValueType = typename std::decay_t<decltype(vec)>::value_type;
308 return MayaFlux::IntegerData<ValueType>;
309 },
310 variant);
311 });
312
313 if (consistent_glm) {
314 dimensions.emplace_back(DataDimension::channel(variant_count));
315
316 std::visit([&](const auto& first_vec) {
317 using ValueType = typename std::decay_t<decltype(first_vec)>::value_type;
318 constexpr size_t components = glm_component_count<ValueType>();
319
321 if constexpr (GlmVec2Type<ValueType>) {
323 } else if constexpr (GlmVec3Type<ValueType>) {
325 } else if constexpr (GlmVec4Type<ValueType>) {
327 }
328
329 dimensions.emplace_back(DataDimension::grouped(
330 "glm_elements",
331 first_variant_size,
332 static_cast<uint8_t>(components),
333 role));
334 },
335 variants[0]);
336
337 return dimensions;
338 }
339
340 if (variant_count == 1) {
341 if (consistent_decimal) {
342 dimensions.emplace_back(DataDimension::time(first_variant_size, "samples"));
343 } else if (consistent_complex) {
344 dimensions.emplace_back(DataDimension::frequency(first_variant_size, "frequency_data"));
345 } else if (consistent_integer) {
346 dimensions.emplace_back(DataDimension::spatial(first_variant_size, 'x', 1, "data_points"));
347 } else {
348 dimensions.emplace_back("unknown_data", first_variant_size, 1,
350 }
351
352 } else if (variant_count == 2 && (consistent_decimal || consistent_complex || consistent_integer)) {
353 dimensions.emplace_back(DataDimension::channel(2));
354 if (consistent_decimal) {
355 dimensions.emplace_back(DataDimension::time(first_variant_size, "samples"));
356 } else if (consistent_complex) {
357 dimensions.emplace_back(DataDimension::frequency(first_variant_size, "bins"));
358 } else {
359 dimensions.emplace_back(DataDimension::spatial(first_variant_size, 'x', 1, "elements"));
360 }
361
362 } else if (variant_count <= 16 && (consistent_decimal || consistent_complex || consistent_integer)) {
363 dimensions.emplace_back(DataDimension::channel(variant_count));
364 if (consistent_decimal) {
365 dimensions.emplace_back(DataDimension::time(first_variant_size, "samples"));
366 } else if (consistent_complex) {
367 dimensions.emplace_back(DataDimension::frequency(first_variant_size, "bins"));
368 } else {
369 dimensions.emplace_back(DataDimension::spatial(first_variant_size, 'x', 1, "pixels"));
370 }
371
372 } else if (consistent_decimal || consistent_complex || consistent_integer) {
373 if (consistent_decimal) {
374 dimensions.emplace_back(DataDimension::time(variant_count, "time_blocks"));
375 dimensions.emplace_back("block_samples", first_variant_size, 1,
377 } else if (consistent_complex) {
378 dimensions.emplace_back(DataDimension::time(variant_count, "time_windows"));
379 dimensions.emplace_back(DataDimension::frequency(first_variant_size, "frequency_bins"));
380 } else {
381 dimensions.emplace_back(DataDimension::time(variant_count, "frames"));
382 dimensions.emplace_back(DataDimension::spatial(first_variant_size, 'x', 1, "frame_data"));
383 }
384
385 } else {
386 dimensions.emplace_back("mixed_variants", variant_count, 1,
388 dimensions.emplace_back("variant_data", first_variant_size, 1,
390 }
391
392 return dimensions;
393}
394
395}
#define MF_WARN(comp, ctx,...)
@ Runtime
General runtime operations (default fallback)
@ Kakshya
Containers[Signalsource, Stream, File], Regions, DataProcessors.
std::vector< DataDimension > detect_data_dimensions(const DataVariant &data)
Detect data dimensions from a DataVariant.
uint64_t calculate_frame_size(const std::vector< DataDimension > &dimensions)
Calculate the frame size (number of elements per frame) for a set of dimensions.
Definition DataUtils.cpp:15
std::variant< std::vector< double >, std::vector< float >, std::vector< uint8_t >, std::vector< uint16_t >, std::vector< uint32_t >, std::vector< std::complex< float > >, std::vector< std::complex< double > >, std::vector< glm::vec2 >, std::vector< glm::vec3 >, std::vector< glm::vec4 >, std::vector< glm::mat4 > > DataVariant
Multi-type data storage for different precision needs.
Definition NDData.hpp:76
DataModality
Data modality types for cross-modal analysis.
Definition NDData.hpp:81
@ AUDIO_MULTICHANNEL
Multi-channel audio.
@ SPECTRAL_2D
2D spectral data (time + frequency)
@ UNKNOWN
Unknown or undefined modality.
@ VOLUMETRIC_3D
3D volumetric data
@ VIDEO_GRAYSCALE
3D video (time + 2D grayscale)
@ VIDEO_COLOR
4D video (time + 2D + color)
@ TENSOR_ND
N-dimensional tensor.
@ IMAGE_COLOR
2D RGB/RGBA image
@ IMAGE_2D
2D image (grayscale or single channel)
std::type_index get_variant_type_index(const DataVariant &data)
Get type index from DataVariant.
Definition DataUtils.cpp:26
int find_dimension_by_role(const std::vector< DataDimension > &dimensions, DataDimension::Role role)
Find the index of a dimension by its semantic role.
Definition DataUtils.cpp:64
void set_metadata_value(std::unordered_map< std::string, std::any > &metadata, const std::string &key, std::any value)
Set a value in a metadata map (key-value).
Definition DataUtils.cpp:59
DataModality detect_data_modality(const std::vector< DataDimension > &dimensions)
Detects data modality from dimension information.
Definition DataUtils.cpp:72
void safe_copy_data_variant(const DataVariant &input, DataVariant &output)
Safely copy data from a DataVariant to another DataVariant, handling type conversion.
Definition DataUtils.cpp:34
uint64_t calculate_total_elements(const std::vector< DataDimension > &dimensions)
Calculate the total number of elements in an N-dimensional container.
Definition DataUtils.cpp:5
Role
Semantic role of the dimension.
Definition NDData.hpp:149
@ FREQUENCY
Spectral/frequency axis.
@ TIME
Temporal progression (samples, frames, steps)
@ CUSTOM
User-defined or application-specific.
@ POSITION
Vertex positions (3D space)
@ CHANNEL
Parallel streams (audio channels, color channels)
@ SPATIAL_X
Spatial X axis (images, tensors)
uint64_t size
Number of elements in this dimension.
Definition NDData.hpp:192
Role role
Semantic hint for common operations.
Definition NDData.hpp:194
static DataDimension spatial(uint64_t size, char axis, uint64_t stride=1, std::string name="spatial")
Convenience constructor for a spatial dimension.
Definition NDData.cpp:32
static DataDimension grouped(std::string name, uint64_t element_count, uint8_t components_per_element, Role role=Role::CUSTOM)
Create dimension with component grouping.
Definition NDData.cpp:72
static DataDimension frequency(uint64_t bins, std::string name="frequency")
Convenience constructor for a frequency dimension.
Definition NDData.cpp:27
static DataDimension time(uint64_t samples, std::string name="time")
Convenience constructor for a temporal (time) dimension.
Definition NDData.cpp:17
static DataDimension channel(uint64_t count, uint64_t stride=1)
Convenience constructor for a channel dimension.
Definition NDData.cpp:22
Minimal dimension descriptor focusing on structure only.
Definition NDData.hpp:142