MayaFlux 0.1.0
Digital-First Multimedia Processing Framework
Loading...
Searching...
No Matches
DataUtils.hpp
Go to the documentation of this file.
1#pragma once
2
4
6#include "MayaFlux/Utils.hpp"
7
8#include <glm/gtc/type_ptr.hpp>
9#include <typeindex>
10
11namespace MayaFlux::Kakshya {
12
13template <typename From, typename To, typename Enable = void>
15 static std::span<To> convert(std::span<From> /*source*/,
16 std::vector<To>& /*storage*/,
18 {
19 static_assert(always_false_v<From>, "No conversion available for these types");
20 return {};
21 }
22};
23
24// === Specialization: Identity Conversion ===
25
26template <typename T>
27struct DataConverter<T, T> {
28 static std::span<T> convert(std::span<T> source,
29 std::vector<T>&,
31 {
32 return source;
33 }
34};
35
36// === Specialization: Arithmetic to Arithmetic (excluding GLM) ===
37
38template <typename From, typename To>
40 From, To,
41 std::enable_if_t<
42 ArithmeticData<From> && ArithmeticData<To> && !std::is_same_v<From, To> && !GlmType<From> && !GlmType<To>>> {
43 static std::span<To> convert(
44 std::span<From> source,
45 std::vector<To>& storage,
47 {
48 storage.resize(source.size());
49 std::transform(
50 source.begin(), source.end(), storage.begin(),
51 [](From val) { return static_cast<To>(val); });
52
53 return std::span<To>(storage.data(), storage.size());
54 }
55};
56
57// === Specialization: Complex to Arithmetic ===
58
59template <typename From, typename To>
61 From, To,
62 std::enable_if_t<
63 ComplexData<From> && ArithmeticData<To> && !GlmType<From> && !GlmType<To>>> {
64 static std::span<To> convert(
65 std::span<From> source,
66 std::vector<To>& storage,
68 {
69 storage.resize(source.size());
70
71 for (size_t i = 0; i < source.size(); ++i) {
72 switch (strategy) {
74 storage[i] = static_cast<To>(std::abs(source[i]));
75 break;
77 storage[i] = static_cast<To>(source[i].real());
78 break;
80 storage[i] = static_cast<To>(source[i].imag());
81 break;
83 storage[i] = static_cast<To>(std::norm(source[i]));
84 break;
85 }
86 }
87
88 return std::span<To>(storage.data(), storage.size());
89 }
90};
91
92// === Specialization: Arithmetic to Complex ===
93
94template <typename From, typename To>
96 From, To,
97 std::enable_if_t<
98 ArithmeticData<From> && ComplexData<To> && !GlmType<From> && !GlmType<To>>> {
99 static std::span<To> convert(
100 std::span<From> source,
101 std::vector<To>& storage,
103 {
104 using ComplexValueType = typename To::value_type;
105 storage.resize(source.size());
106
107 for (size_t i = 0; i < source.size(); ++i) {
108 storage[i] = To(static_cast<ComplexValueType>(source[i]), ComplexValueType { 0 });
109 }
110
111 return std::span<To>(storage.data(), storage.size());
112 }
113};
114
115// === Specialization: GLM to Arithmetic (Flattening) ===
116
117template <typename From, typename To>
119 From, To,
120 std::enable_if_t<
121 GlmType<From> && ArithmeticData<To> && !GlmType<To>>> {
122 static std::span<To> convert(
123 std::span<From> source,
124 std::vector<To>& storage,
126 {
127 constexpr size_t components = glm_component_count<From>();
128 using ComponentType = glm_component_type<From>;
129
130 storage.resize(source.size() * components);
131
132 size_t out_idx = 0;
133 for (const auto& elem : source) {
134 const ComponentType* ptr = glm::value_ptr(elem);
135 for (size_t c = 0; c < components; ++c) {
136 storage[out_idx++] = static_cast<To>(ptr[c]);
137 }
138 }
139
140 return std::span<To>(storage.data(), storage.size());
141 }
142};
143
144// === Specialization: Arithmetic to GLM (Structuring) ===
145
146template <typename From, typename To>
148 From, To,
149 std::enable_if_t<
150 ArithmeticData<From> && GlmType<To> && !GlmType<From>>> {
151 static std::span<To> convert(
152 std::span<From> source,
153 std::vector<To>& storage,
155 {
156 constexpr size_t components = glm_component_count<To>();
157 using ComponentType = glm_component_type<To>;
158
159 if (source.size() % components != 0) {
160 error<std::invalid_argument>(
163 std::source_location::current(),
164 "Source size ({}) must be multiple of GLM component count ({})",
165 source.size(),
166 components);
167 }
168
169 size_t element_count = source.size() / components;
170 storage.resize(element_count);
171
172 for (size_t i = 0; i < element_count; ++i) {
173 ComponentType temp[components];
174 for (size_t c = 0; c < components; ++c) {
175 temp[c] = static_cast<ComponentType>(source[i * components + c]);
176 }
177
178 if constexpr (GlmVec2Type<To>) {
179 storage[i] = To(temp[0], temp[1]);
180 } else if constexpr (GlmVec3Type<To>) {
181 storage[i] = To(temp[0], temp[1], temp[2]);
182 } else if constexpr (GlmVec4Type<To>) {
183 storage[i] = To(temp[0], temp[1], temp[2], temp[3]);
184 } else if constexpr (GlmMatrixType<To>) {
185 storage[i] = glm::make_mat4(temp);
186 }
187 }
188
189 return std::span<To>(storage.data(), storage.size());
190 }
191};
192
193// === Specialization: GLM to GLM (same component count) ===
194
195template <typename From, typename To>
197 From, To,
198 std::enable_if_t<
199 GlmType<From> && GlmType<To> && !std::is_same_v<From, To> && (glm_component_count<From>() == glm_component_count<To>())>> {
200 static std::span<To> convert(
201 std::span<From> source,
202 std::vector<To>& storage,
204 {
205 using FromComponent = glm_component_type<From>;
206 using ToComponent = glm_component_type<To>;
207 constexpr size_t components = glm_component_count<From>();
208
209 storage.resize(source.size());
210
211 for (size_t i = 0; i < source.size(); ++i) {
212 const FromComponent* src_ptr = glm::value_ptr(source[i]);
213 ToComponent temp[components];
214
215 for (size_t c = 0; c < components; ++c) {
216 temp[c] = static_cast<ToComponent>(src_ptr[c]);
217 }
218
219 if constexpr (GlmVec2Type<To>) {
220 storage[i] = To(temp[0], temp[1]);
221 } else if constexpr (GlmVec3Type<To>) {
222 storage[i] = To(temp[0], temp[1], temp[2]);
223 } else if constexpr (GlmVec4Type<To>) {
224 storage[i] = To(temp[0], temp[1], temp[2], temp[3]);
225 } else if constexpr (GlmMatrixType<To>) {
226 storage[i] = glm::make_mat4(temp);
227 }
228 }
229
230 return std::span<To>(storage.data(), storage.size());
231 }
232};
233
234// === Specialization: Complex -> Complex ===
235template <typename From, typename To>
237 From, To,
238 std::enable_if_t<
239 ComplexData<From> && ComplexData<To> && !GlmType<From> && !GlmType<To> && !std::is_same_v<From, To>>> {
240 static std::span<To> convert(
241 std::span<From> source,
242 std::vector<To>& storage,
244 {
245 using FromValue = typename From::value_type;
246 using ToValue = typename To::value_type;
247
248 storage.resize(source.size());
249 for (size_t i = 0; i < source.size(); ++i) {
250 const auto r = static_cast<FromValue>(source[i].real());
251 const auto im = static_cast<FromValue>(source[i].imag());
252 storage[i] = To(static_cast<ToValue>(r), static_cast<ToValue>(im));
253 }
254
255 return std::span<To>(storage.data(), storage.size());
256 }
257};
258
259/**
260 * @brief Calculate the total number of elements in an N-dimensional container.
261 * @param dimensions Dimension descriptors.
262 * @return Product of all dimension sizes.
263 */
264uint64_t calculate_total_elements(const std::vector<DataDimension>& dimensions);
265
266/**
267 * @brief Calculate the frame size (number of elements per frame) for a set of dimensions.
268 * @param dimensions Dimension descriptors.
269 * @return Frame size (product of all but the first dimension).
270 */
271uint64_t calculate_frame_size(const std::vector<DataDimension>& dimensions);
272
273/**
274 * @brief Get type index from DataVariant
275 */
276std::type_index get_variant_type_index(const DataVariant& data);
277
278/**
279 * @brief Extract a single frame of data from a span.
280 * @tparam T Data type.
281 * @param data Source data span.
282 * @param frame_index Index of the frame to extract.
283 * @param frame_size Number of elements per frame.
284 * @return Span containing the frame data.
285 */
286template <ProcessableData T>
287constexpr std::span<T> extract_frame(std::span<T> data, uint64_t frame_index, uint64_t frame_size) noexcept
288{
289 uint64_t start = frame_index * frame_size;
290 uint64_t end = std::min(static_cast<uint64_t>(start + frame_size),
291 static_cast<uint64_t>(data.size()));
292
293 if (start >= data.size()) {
294 return {};
295 }
296
297 return data.subspan(start, end - start);
298}
299
300/**
301 * @brief Extract a single frame from planar data (returns interleaved).
302 * @tparam T Data type.
303 * @param channel_spans Vector of spans, one per channel.
304 * @param frame_index Index of the frame to extract.
305 * @param output_buffer Buffer to store interleaved frame data.
306 * @return Span containing the interleaved frame data.
307 */
308template <ProcessableData T>
309std::span<T> extract_frame(
310 const std::vector<std::span<T>>& channel_spans,
311 uint64_t frame_index,
312 std::vector<T>& output_buffer) noexcept
313{
314 output_buffer.clear();
315 output_buffer.reserve(channel_spans.size());
316
317 for (const auto& channel_span : channel_spans) {
318 if (frame_index < channel_span.size()) {
319 output_buffer.push_back(channel_span[frame_index]);
320 } else {
321 output_buffer.push_back(T { 0 });
322 }
323 }
324
325 return std::span<T>(output_buffer.data(), output_buffer.size());
326}
327
328/**
329 * @brief Convert a span of one data type to another (with type conversion).
330 * @tparam From Source type.
331 * @tparam To Destination type.
332 * @param source Source data span.
333 * @param dest Destination data span.
334 * @return Span of converted data.
335 */
336template <typename From, typename To>
337std::span<To> convert_data(std::span<From> source,
338 std::vector<To>& storage,
340{
341 return DataConverter<From, To>::convert(source, storage, strategy);
342}
343
344/**
345 * @brief Legacy interface - redirects to convert_data
346 */
347template <typename From, typename To>
348 requires(ComplexData<From> && ArithmeticData<To>)
349void convert_complex(std::span<From> source,
350 std::span<To> destination,
352{
353 std::vector<To> temp_storage;
354 auto result = convert_data(source, temp_storage, strategy);
355 std::copy_n(result.begin(), std::min(result.size(), destination.size()), destination.begin());
356}
357
358/**
359 * @brief Get const span from DataVariant without conversion (zero-copy for matching types)
360 * @tparam T Data type (must match DataVariant contents)
361 * @param variant DataVariant to extract from
362 * @return Const span of type T
363 * @throws std::runtime_error if type doesn't match
364 */
365template <ProcessableData T>
366std::span<T> convert_variant(DataVariant& variant,
368{
369 if (std::holds_alternative<std::vector<T>>(variant)) {
370 auto& vec = std::get<std::vector<T>>(variant);
371 return std::span<T>(vec.data(), vec.size());
372 }
373
374 return std::visit([&variant, strategy](auto& data) -> std::span<T> {
375 using ValueType = typename std::decay_t<decltype(data)>::value_type;
376
377 if constexpr (is_convertible_data_v<ValueType, T>) {
378 std::vector<T> new_storage;
379 auto source_span = std::span<ValueType>(data.data(), data.size());
380 auto result = convert_data(source_span, new_storage, strategy);
381
382 variant = std::move(new_storage);
383 auto& new_vec = std::get<std::vector<T>>(variant);
384 return std::span<T>(new_vec.data(), new_vec.size());
385 } else {
386 error<std::invalid_argument>(
389 std::source_location::current(),
390 "No conversion available from {} to {}",
391 typeid(ValueType).name(),
392 typeid(T).name());
393 }
394 },
395 variant);
396}
397
398template <ProcessableData T>
399std::span<T> convert_variant(const DataVariant& variant,
401{
402 return convert_variant<T>(const_cast<DataVariant&>(variant), strategy);
403}
404
405template <ProcessableData T>
406std::vector<std::span<T>> convert_variants(
407 const std::vector<DataVariant>& variants,
409{
410 std::vector<std::span<T>> result;
411 result.reserve(variants.size());
412
413 for (const auto& i : variants) {
414 result.push_back(convert_variant<T>(const_cast<DataVariant&>(i), strategy));
415 }
416 return result;
417}
418
419/**
420 * @brief Concept-based data extraction with type conversion
421 * @tparam T Target type (must satisfy ProcessableData)
422 * @param variant Source DataVariant (may be modified for conversion)
423 * @return Span of converted data
424 *
425 * Performance advantage: Eliminates runtime type dispatch for supported types
426 * Uses constexpr branching for compile-time optimization
427 */
428template <ProcessableData From, ProcessableData To>
429std::span<To> extract_data(std::span<const From> source,
430 std::vector<To>& destination,
432{
433 const size_t total_bytes = source.size() * sizeof(From);
434 const size_t required_elements = (total_bytes + sizeof(To) - 1) / sizeof(To);
435 destination.resize(required_elements);
436
437 if constexpr (std::is_same_v<From, To>) {
438 destination.resize(source.size());
439 std::memcpy(destination.data(), source.data(), total_bytes);
440 return std::span<To>(destination.data(), source.size());
441 } else if constexpr (std::is_trivially_copyable_v<From> && std::is_trivially_copyable_v<To> && (sizeof(From) == sizeof(To))) {
442 // Bitwise reinterpretation allowed (e.g. int32_t <-> float)
443 std::memcpy(destination.data(), source.data(), total_bytes);
444 return std::span<To>(destination.data(), source.size());
445 } else {
446 // General case — use proper conversion
447 std::vector<From> temp(source.begin(), source.end());
448 auto converted = convert_data<From, To>(std::span<const From>(temp), strategy);
449 destination.assign(converted.begin(), converted.end());
450 return std::span<To>(destination.data(), destination.size());
451 }
452}
453
454/**
455 * @brief Get typed span from DataVariant using concepts
456 * @tparam T Data type (must satisfy ProcessableData)
457 * @param variant DataVariant to extract from
458 * @return Span of type T, or empty span if type doesn't match
459 */
460template <ProcessableData T>
461std::span<T> extract_from_variant(const DataVariant& variant,
462 std::vector<T>& storage,
464{
465 return std::visit([&storage, strategy](const auto& data) -> std::span<T> {
466 using ValueType = typename std::decay_t<decltype(data)>::value_type;
467
468 if constexpr (std::is_same_v<ValueType, T>) {
469 storage = data;
470 return std::span<T>(storage.data(), storage.size());
471 } else if constexpr (is_convertible_data_v<ValueType, T>) {
472 auto source_span = std::span<const ValueType>(data.data(), data.size());
473 std::vector<ValueType> temp_source(source_span.begin(), source_span.end());
474 auto temp_span = std::span<ValueType>(temp_source.data(), temp_source.size());
475 return convert_data(temp_span, storage, strategy);
476 } else {
477 // throw std::runtime_error("Cannot convert from " + std::string(typeid(ValueType).name()) + " to " + std::string(typeid(T).name()));
478 error<std::invalid_argument>(
481 std::source_location::current(),
482 "No conversion available from {} to {}",
483 typeid(ValueType).name(),
484 typeid(T).name());
485 }
486 },
487 variant);
488}
489
490/**
491 * @brief Extract a value of type T from a DataVariant at a specific position.
492 * @tparam T Desired type.
493 * @param variant DataVariant to extract from.
494 * @param pos Position in the data.
495 * @return Optional value of type T.
496 */
497template <typename T>
498std::optional<T> extract_from_variant_at(const DataVariant& variant, uint64_t pos)
499{
500 return std::visit([pos](const auto& data) -> std::optional<T> {
501 using DataType = std::decay_t<decltype(data)>;
502 using ValueType = typename DataType::value_type;
503
504 if (pos >= data.size()) {
505 return std::nullopt;
506 }
507
508 if constexpr (std::is_same_v<ValueType, T>) {
509 return data[pos];
510 } else if constexpr (std::is_arithmetic_v<ValueType> && std::is_arithmetic_v<T>) {
511 return static_cast<T>(data[pos]);
512 } else if constexpr (std::is_same_v<ValueType, std::complex<float>> || std::is_same_v<ValueType, std::complex<double>>) {
513 if constexpr (std::is_arithmetic_v<T>) {
514 return static_cast<T>(std::abs(data[pos]));
515 } else {
516 return std::nullopt;
517 }
518 } else {
519 return std::nullopt;
520 }
521 },
522 variant);
523}
524
525/**
526 * @brief Safely copy data from a DataVariant to another DataVariant, handling type conversion.
527 * @param input Source DataVariant.
528 * @param output Destination DataVariant.
529 */
530void safe_copy_data_variant(const DataVariant& input, DataVariant& output);
531
532/**
533 * @brief Safely copy data from a DataVariant to a span of doubles.
534 * @param input Source DataVariant.
535 * @param output Destination span of doubles.
536 * @throws std::runtime_error if complex types are involved.
537 */
538inline std::span<const double> safe_copy_data_variant_to_span(const DataVariant& input, std::vector<double>& output)
539{
540 return extract_from_variant(input, output);
541}
542
543/**
544 * @brief Safely copy data from a DataVariant to another DataVariant of a specific type.
545 * @tparam T Data type.
546 * @param input Source DataVariant.
547 * @param output Destination DataVariant.
548 */
549template <typename T>
551{
552 std::vector<T> temp_storage;
553 auto input_span = extract_from_variant<T>(input, temp_storage);
554 auto output_span = get_typed_data<T>(output);
555 std::copy_n(input_span.begin(), std::min(input_span.size(), output_span.size()),
556 output_span.begin());
557}
558
559/**
560 * @brief Convert variant to double span
561 * @param data Source DataVariant (may be modified for conversion)
562 * @param strategy Conversion strategy for complex numbers
563 * @return Span of double data
564 */
565inline std::span<double> convert_variant_to_double(DataVariant& data,
567{
568 return convert_variant<double>(data, strategy);
569}
570
571/**
572 * @brief Set a value in a metadata map (key-value).
573 * @param metadata Metadata map.
574 * @param key Key to set.
575 * @param value Value to set.
576 */
577void set_metadata_value(std::unordered_map<std::string, std::any>& metadata, const std::string& key, std::any value);
578
579/**
580 * @brief Get a value from a metadata map by key.
581 * @tparam T Expected type.
582 * @param metadata Metadata map.
583 * @param key Key to retrieve.
584 * @return Optional value if present and convertible.
585 */
586template <typename T>
587std::optional<T> get_metadata_value(const std::unordered_map<std::string, std::any>& metadata, const std::string& key)
588{
589 auto it = metadata.find(key);
590 if (it != metadata.end()) {
591 try {
592 return safe_any_cast<T>(it->second);
593 } catch (const std::bad_any_cast&) {
594 return std::nullopt;
595 }
596 }
597 return std::nullopt;
598}
599
600/**
601 * @brief Find the index of a dimension by its semantic role.
602 * @param dimensions Dimension descriptors.
603 * @param role Semantic role to search for.
604 * @return Index of the dimension, or -1 if not found.
605 */
606int find_dimension_by_role(const std::vector<DataDimension>& dimensions, DataDimension::Role role);
607
608/**
609 * @brief Detects data modality from dimension information
610 * @param dimensions Vector of data dimensions with role information
611 * @return Detected DataModality type
612 *
613 * Consolidates modality detection logic that was duplicated across analyzers.
614 * Uses dimension roles and count to determine appropriate processing approach.
615 */
616DataModality detect_data_modality(const std::vector<DataDimension>& dimensions);
617
618/**
619 * @brief Detect data dimensions from a DataVariant
620 * @param data DataVariant to analyze
621 * @return Vector of DataDimension descriptors
622 *
623 * This function analyzes the structure of the provided DataVariant and extracts
624 * dimension information, including size, stride, and semantic roles.
625 */
626std::vector<Kakshya::DataDimension> detect_data_dimensions(const DataVariant& data);
627
628/**
629 * @brief Detect data dimensions from a vector of DataVariants
630 * @param variants Vector of DataVariants to analyze
631 * @return Vector of DataDimension descriptors
632 *
633 * This function analyzes the structure of the provided vector of DataVariants and extracts
634 * dimension information, including size, stride, and semantic roles.
635 *
636 * WARNING: This method makes naive assumptions about the data structure and may lead to incorrect interpretations.
637 * It is recommended to use more specific methods when dealing with known containers, regions, or segments.
638 * Use this function only when absolutely necessary and be aware of potential computational errors.
639 */
640std::vector<Kakshya::DataDimension> detect_data_dimensions(const std::vector<Kakshya::DataVariant>& variants);
641}
@ Runtime
General runtime operations (default fallback)
@ Kakshya
Containers[Signalsource, Stream, File], Regions, DataProcessors.
void convert_complex(std::span< From > source, std::span< To > destination, Utils::ComplexConversionStrategy strategy)
Legacy interface - redirects to convert_data.
std::optional< T > extract_from_variant_at(const DataVariant &variant, uint64_t pos)
Extract a value of type T from a DataVariant at a specific position.
std::vector< std::span< T > > convert_variants(const std::vector< DataVariant > &variants, Utils::ComplexConversionStrategy strategy=Utils::ComplexConversionStrategy::MAGNITUDE)
std::span< T > convert_variant(DataVariant &variant, Utils::ComplexConversionStrategy strategy=Utils::ComplexConversionStrategy::MAGNITUDE)
Get const span from DataVariant without conversion (zero-copy for matching types)
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
constexpr std::span< T > extract_frame(std::span< T > data, uint64_t frame_index, uint64_t frame_size) noexcept
Extract a single frame of data from a span.
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:73
DataModality
Data modality types for cross-modal analysis.
Definition NDData.hpp:78
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
std::span< const double > safe_copy_data_variant_to_span(const DataVariant &input, std::vector< double > &output)
Safely copy data from a DataVariant to a span of doubles.
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_typed_variant(const DataVariant &input, DataVariant &output)
Safely copy data from a DataVariant to another DataVariant of a specific type.
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
std::span< double > convert_variant_to_double(DataVariant &data, Utils::ComplexConversionStrategy strategy=Utils::ComplexConversionStrategy::MAGNITUDE)
Convert variant to double span.
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
std::span< T > extract_from_variant(const DataVariant &variant, std::vector< T > &storage, Utils::ComplexConversionStrategy strategy=Utils::ComplexConversionStrategy::MAGNITUDE)
Get typed span from DataVariant using concepts.
std::span< To > extract_data(std::span< const From > source, std::vector< To > &destination, Utils::ComplexConversionStrategy strategy=Utils::ComplexConversionStrategy::MAGNITUDE)
Concept-based data extraction with type conversion.
std::optional< T > get_metadata_value(const std::unordered_map< std::string, std::any > &metadata, const std::string &key)
Get a value from a metadata map by key.
std::span< To > convert_data(std::span< From > source, std::vector< To > &storage, Utils::ComplexConversionStrategy strategy=Utils::ComplexConversionStrategy::MAGNITUDE)
Convert a span of one data type to another (with type conversion).
ComplexConversionStrategy
Strategy for converting complex numbers to real values.
Definition Utils.hpp:64
@ SQUARED_MAGNITUDE
|z|² = real² + imag²
@ MAGNITUDE
|z| = sqrt(real² + imag²)
static std::span< To > convert(std::span< From > source, std::vector< To > &storage, Utils::ComplexConversionStrategy=Utils::ComplexConversionStrategy::MAGNITUDE)
Definition DataUtils.hpp:99
static std::span< To > convert(std::span< From > source, std::vector< To > &storage, Utils::ComplexConversionStrategy=Utils::ComplexConversionStrategy::MAGNITUDE)
static std::span< To > convert(std::span< From > source, std::vector< To > &storage, Utils::ComplexConversionStrategy=Utils::ComplexConversionStrategy::MAGNITUDE)
Definition DataUtils.hpp:43
static std::span< To > convert(std::span< From > source, std::vector< To > &storage, Utils::ComplexConversionStrategy strategy)
Definition DataUtils.hpp:64
static std::span< To > convert(std::span< From > source, std::vector< To > &storage, Utils::ComplexConversionStrategy=Utils::ComplexConversionStrategy::MAGNITUDE)
static std::span< To > convert(std::span< From > source, std::vector< To > &storage, Utils::ComplexConversionStrategy=Utils::ComplexConversionStrategy::MAGNITUDE)
static std::span< To > convert(std::span< From > source, std::vector< To > &storage, Utils::ComplexConversionStrategy=Utils::ComplexConversionStrategy::MAGNITUDE)
static std::span< T > convert(std::span< T > source, std::vector< T > &, Utils::ComplexConversionStrategy=Utils::ComplexConversionStrategy::MAGNITUDE)
Definition DataUtils.hpp:28
static std::span< To > convert(std::span< From >, std::vector< To > &, Utils::ComplexConversionStrategy=Utils::ComplexConversionStrategy::MAGNITUDE)
Definition DataUtils.hpp:15
Role
Semantic role of the dimension.
Definition NDData.hpp:145