9 if (dimensions.empty())
12 return std::transform_reduce(dimensions.begin(), dimensions.end(),
13 uint64_t(1), std::multiplies<>(),
19 if (dimensions.empty())
22 return std::transform_reduce(
23 dimensions.begin() + 1, dimensions.end(),
24 uint64_t(1), std::multiplies<>(),
30 return std::visit([](
const auto& vec) -> std::type_index {
31 return typeid(
typename std::decay_t<
decltype(vec)>::value_type);
38 std::visit([&](
const auto& input_vec,
auto& output_vec) {
39 using InputType =
typename std::decay_t<
decltype(input_vec)>::value_type;
40 using OutputType =
typename std::decay_t<
decltype(output_vec)>::value_type;
42 if constexpr (ProcessableData<InputType> && ProcessableData<OutputType>) {
43 std::vector<OutputType> temp_storage;
44 auto input_span = extract_from_variant<OutputType>(
input, temp_storage);
46 output_vec.resize(input_span.size());
47 std::copy(input_span.begin(), input_span.end(), output_vec.begin());
49 error<std::invalid_argument>(
52 std::source_location::current(),
53 "Unsupported type conversion from {} to {}",
54 typeid(InputType).
name(),
55 typeid(OutputType).
name());
62 const DataVariant& variant, std::vector<float>& storage)
64 return std::visit([&storage](
const auto& vec) -> std::span<const float> {
65 using T =
typename std::decay_t<
decltype(vec)>::value_type;
67 if constexpr (std::is_same_v<T, float>) {
68 return { vec.data(), vec.size() };
70 }
else if constexpr (std::is_same_v<T, uint8_t>) {
71 storage.resize(vec.size());
72 constexpr float k = 1.0F / 255.0F;
74 std::transform(Parallel::par_unseq,
75 vec.begin(), vec.end(), storage.begin(),
76 [](uint8_t v) { return static_cast<float>(v) * k; });
77 return { storage.data(), storage.size() };
79 }
else if constexpr (std::is_same_v<T, uint16_t>) {
80 storage.resize(vec.size());
81 constexpr float k = 1.0F / 65535.0F;
83 std::transform(Parallel::par_unseq,
84 vec.begin(), vec.end(), storage.begin(),
85 [](uint16_t v) { return static_cast<float>(v) * k; });
86 return { storage.data(), storage.size() };
98 [](
const auto& vec) -> std::pair<const uint8_t*, size_t> {
99 using T =
typename std::decay_t<
decltype(vec)>::value_type;
100 if constexpr (std::is_same_v<T, uint8_t>
101 || std::is_same_v<T, uint16_t>
102 || std::is_same_v<T, float>) {
104 reinterpret_cast<const uint8_t*
>(vec.data()),
105 vec.size() *
sizeof(T)
108 return {
nullptr, 0 };
117 [](
auto& vec) -> std::pair<uint8_t*, size_t> {
118 using T =
typename std::decay_t<
decltype(vec)>::value_type;
119 if constexpr (std::is_same_v<T, uint8_t>
120 || std::is_same_v<T, uint16_t>
121 || std::is_same_v<T, float>) {
123 reinterpret_cast<uint8_t*
>(vec.data()),
124 vec.size() *
sizeof(T)
127 return {
nullptr, 0 };
135 Parallel::transform(Parallel::par_unseq, src.begin(), src.end(), dst.begin(),
137 return static_cast<uint8_t>(std::clamp(v * 255.0F, 0.0F, 255.0F));
143 std::vector<uint8_t> out(src.size());
150 metadata[key] = std::move(
value);
155 auto it = std::ranges::find_if(dimensions,
158 return (it != dimensions.end()) ?
static_cast<int>(std::distance(dimensions.begin(), it)) : -1;
163 if (dimensions.empty()) {
167 size_t time_dims = 0, spatial_dims = 0, channel_dims = 0, frequency_dims = 0, depth_dims = 0, custom_dims = 0;
168 size_t total_spatial_elements = 1;
169 size_t total_channels = 0;
171 for (
const auto& dim : dimensions) {
184 if (dim.grouping->count == 3)
186 if (dim.grouping->count == 4)
190 if (dim.grouping->count == 16)
197 for (
const auto& dim : dimensions) {
206 total_spatial_elements *= dim.size;
210 total_channels += dim.size;
225 if (time_dims == 1 && spatial_dims == 0 && frequency_dims == 0) {
226 if (channel_dims == 0) {
229 if (channel_dims == 1) {
235 if (time_dims >= 1 && frequency_dims >= 1) {
236 if (spatial_dims == 0 && channel_dims <= 1) {
242 if (spatial_dims >= 2 && time_dims == 0) {
243 if (spatial_dims == 2) {
244 if (channel_dims == 0) {
247 if (channel_dims == 1 && total_channels >= 3) {
253 if (spatial_dims == 3) {
258 if (depth_dims == 1 && spatial_dims == 2) {
259 return time_dims >= 1
264 if (time_dims >= 1 && spatial_dims >= 2) {
265 if (spatial_dims == 2) {
266 if (channel_dims == 0 || (channel_dims == 1 && total_channels <= 1)) {
275 if (spatial_dims == 2 && time_dims == 0 && channel_dims >= 1) {
276 if (total_spatial_elements >= 64 && total_channels >= 1) {
285 const std::vector<DataDimension>& dimensions,
294 return std::visit([&base](
const auto& vec) {
295 using V =
typename std::decay_t<
decltype(vec)>::value_type;
297 if constexpr (ComplexData<V>) {
299 }
else if constexpr (IntegerData<V>) {
312 "Inferring structure from single DataVariant is not advisable as the method makes naive assumptions that can lead to massive computational errors. "
313 "If the variant is part of a container, region, or segment, please use the appropriate method instead. "
314 "If the variant is part of a vector, please use infer_from_data_variant_vector instead. "
315 "If you are sure you want to proceed, please ignore this warning.");
317 return std::visit([](
const auto& vec) -> std::vector<DataDimension> {
318 using ValueType =
typename std::decay_t<
decltype(vec)>::value_type;
320 std::vector<DataDimension> dims;
322 if constexpr (DecimalData<ValueType>) {
325 }
else if constexpr (ComplexData<ValueType>) {
328 }
else if constexpr (IntegerData<ValueType>) {
330 }
else if constexpr (GlmData<ValueType>) {
331 constexpr size_t components = glm_component_count<ValueType>();
334 if constexpr (GlmVec2Type<ValueType>) {
336 }
else if constexpr (GlmVec3Type<ValueType>) {
338 }
else if constexpr (GlmVec4Type<ValueType>) {
340 }
else if constexpr (GlmMatrixType<ValueType>) {
345 "glm_structured_data",
346 static_cast<uint64_t
>(vec.size()),
347 static_cast<uint8_t
>(components),
359 const std::vector<DataVariant>& variants)
363 "Inferring structure from DataVariant vector is not advisable as the method makes naive assumptions that can lead to massive computational errors. "
364 "If the variants are part of a container, region, or segment, please use the appropriate method instead. "
365 "If you are sure you want to proceed, please ignore this warning.");
367 if (variants.empty()) {
368 std::vector<DataDimension> dims;
373 std::vector<DataDimension> dimensions;
374 size_t variant_count = variants.size();
376 size_t first_variant_size = std::visit([](
const auto& vec) ->
size_t {
381 bool consistent_glm = std::ranges::all_of(variants, [](
const auto& variant) {
382 return std::visit([](
const auto& vec) ->
bool {
383 using ValueType =
typename std::decay_t<
decltype(vec)>::value_type;
384 return GlmData<ValueType>;
389 bool consistent_decimal = std::ranges::all_of(variants, [](
const auto& variant) {
390 return std::visit([](
const auto& vec) ->
bool {
391 using ValueType =
typename std::decay_t<
decltype(vec)>::value_type;
392 return MayaFlux::DecimalData<ValueType>;
397 bool consistent_complex = std::ranges::all_of(variants, [](
const auto& variant) {
398 return std::visit([](
const auto& vec) ->
bool {
399 using ValueType =
typename std::decay_t<
decltype(vec)>::value_type;
400 return MayaFlux::ComplexData<ValueType>;
405 bool consistent_integer = std::ranges::all_of(variants, [](
const auto& variant) {
406 return std::visit([](
const auto& vec) ->
bool {
407 using ValueType =
typename std::decay_t<
decltype(vec)>::value_type;
408 return MayaFlux::IntegerData<ValueType>;
413 if (consistent_glm) {
416 std::visit([&](
const auto& first_vec) {
417 using ValueType =
typename std::decay_t<
decltype(first_vec)>::value_type;
418 constexpr size_t components = glm_component_count<ValueType>();
421 if constexpr (GlmVec2Type<ValueType>) {
423 }
else if constexpr (GlmVec3Type<ValueType>) {
425 }
else if constexpr (GlmVec4Type<ValueType>) {
432 static_cast<uint8_t
>(components),
440 if (variant_count == 1) {
441 if (consistent_decimal) {
443 }
else if (consistent_complex) {
445 }
else if (consistent_integer) {
448 dimensions.emplace_back(
"unknown_data", first_variant_size, 1,
452 }
else if (variant_count == 2 && (consistent_decimal || consistent_complex || consistent_integer)) {
454 if (consistent_decimal) {
456 }
else if (consistent_complex) {
462 }
else if (variant_count <= 16 && (consistent_decimal || consistent_complex || consistent_integer)) {
464 if (consistent_decimal) {
466 }
else if (consistent_complex) {
472 }
else if (consistent_decimal || consistent_complex || consistent_integer) {
473 if (consistent_decimal) {
475 dimensions.emplace_back(
"block_samples", first_variant_size, 1,
477 }
else if (consistent_complex) {
486 dimensions.emplace_back(
"mixed_variants", variant_count, 1,
488 dimensions.emplace_back(
"variant_data", first_variant_size, 1,
#define MF_WARN(comp, ctx,...)
Core::GlobalInputConfig input
std::shared_ptr< Core::VKImage > output
@ Runtime
General runtime operations (default fallback)
@ Kakshya
Containers[Signalsource, Stream, File], Regions, DataProcessors.
void denormalise_to_uint8(std::span< const float > src, std::span< uint8_t > dst)
Convert a normalised float span back to uint8_t pixels.
std::vector< DataDimension > detect_data_dimensions(const DataVariant &data)
Detect data dimensions from a DataVariant.
std::span< const float > as_normalised_float(const DataVariant &variant, std::vector< float > &storage)
Extract a DataVariant holding pixel data as a normalised float span.
uint64_t calculate_frame_size(const std::vector< DataDimension > &dimensions)
Calculate the frame size (number of elements per frame) for a set of dimensions.
std::pair< const uint8_t *, size_t > variant_bytes(const DataVariant &v)
Get a pointer to the raw bytes of a DataVariant and its size.
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.
DataModality
Data modality types for cross-modal analysis.
@ DEPTH_MAP
[height, width, components] - range/disparity image
@ AUDIO_MULTICHANNEL
Multi-channel audio.
@ SPECTRAL_2D
2D spectral data (time + frequency)
@ AUDIO_1D
1D audio signal
@ VIDEO_DEPTH
[frames, height, width, components] - streaming range data
@ 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.
@ TEXTURE_2D
2D texture data
@ IMAGE_COLOR
2D RGB/RGBA image
@ IMAGE_2D
2D image (grayscale or single channel)
int find_dimension_by_role(const std::vector< DataDimension > &dimensions, DataDimension::Role role)
Find the index of a dimension by its semantic role.
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).
DataModality detect_data_modality(const std::vector< DataDimension > &dimensions)
Detects data modality from dimension information.
std::type_index get_variant_element_type(const DataVariant &data)
Return the native element type of a DataVariant as a type_index.
void safe_copy_data_variant(const DataVariant &input, DataVariant &output)
Safely copy data from a DataVariant to another DataVariant, handling type conversion.
uint64_t calculate_total_elements(const std::vector< DataDimension > &dimensions)
Calculate the total number of elements in an N-dimensional container.
std::pair< uint8_t *, size_t > variant_bytes_mutable(DataVariant &v)
Get a mutable pointer to the raw bytes of a DataVariant and its size.
Role
Semantic role of the dimension.
@ COLOR
Color data (RGB/RGBA)
@ FREQUENCY
Spectral/frequency axis.
@ SPATIAL_Y
Spatial Y axis.
@ TIME
Temporal progression (samples, frames, steps)
@ BITANGENT
Bitangent vectors.
@ TANGENT
Tangent vectors.
@ CUSTOM
User-defined or application-specific.
@ SPATIAL_Z
Spatial Z axis.
@ POSITION
Vertex positions (3D space)
@ DEPTH
Distance from the observation point (depth, disparity, range)
@ CHANNEL
Parallel streams (audio channels, color channels)
@ SPATIAL_X
Spatial X axis (images, tensors)
uint64_t size
Number of elements in this dimension.
Role role
Semantic hint for common operations.
static DataDimension spatial(uint64_t size, char axis, uint64_t stride=1, std::string name="spatial")
Convenience constructor for a spatial dimension.
static DataDimension grouped(std::string name, uint64_t element_count, uint8_t components_per_element, Role role=Role::CUSTOM)
Create dimension with component grouping.
static DataDimension frequency(uint64_t bins, std::string name="frequency")
Convenience constructor for a frequency dimension.
static DataDimension time(uint64_t samples, std::string name="time")
Convenience constructor for a temporal (time) dimension.
static DataDimension channel(uint64_t count, uint64_t stride=1)
Convenience constructor for a channel dimension.
Minimal dimension descriptor focusing on structure only.