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());
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>) {
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; });
79 }
else if constexpr (std::is_same_v<T, uint16_t>) {
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; });
97 Parallel::transform(Parallel::par_unseq, src.begin(), src.end(), dst.begin(),
99 return static_cast<uint8_t>(std::clamp(v * 255.0F, 0.0F, 255.0F));
105 std::vector<uint8_t> out(src.size());
112 metadata[key] = std::move(
value);
117 auto it = std::ranges::find_if(dimensions,
120 return (it != dimensions.end()) ?
static_cast<int>(std::distance(dimensions.begin(), it)) : -1;
125 if (dimensions.empty()) {
129 size_t time_dims = 0, spatial_dims = 0, channel_dims = 0, frequency_dims = 0, custom_dims = 0;
130 size_t total_spatial_elements = 1;
131 size_t total_channels = 0;
133 for (
const auto& dim : dimensions) {
146 if (dim.grouping->count == 3)
148 if (dim.grouping->count == 4)
152 if (dim.grouping->count == 16)
159 for (
const auto& dim : dimensions) {
168 total_spatial_elements *= dim.size;
172 total_channels += dim.size;
184 if (time_dims == 1 && spatial_dims == 0 && frequency_dims == 0) {
185 if (channel_dims == 0) {
187 }
else if (channel_dims == 1) {
194 if (time_dims >= 1 && frequency_dims >= 1) {
195 if (spatial_dims == 0 && channel_dims <= 1) {
201 if (spatial_dims >= 2 && time_dims == 0) {
202 if (spatial_dims == 2) {
203 if (channel_dims == 0) {
205 }
else if (channel_dims == 1 && total_channels >= 3) {
210 }
else if (spatial_dims == 3) {
215 if (time_dims >= 1 && spatial_dims >= 2) {
216 if (spatial_dims == 2) {
217 if (channel_dims == 0 || (channel_dims == 1 && total_channels <= 1)) {
226 if (spatial_dims == 2 && time_dims == 0 && channel_dims >= 1) {
227 if (total_spatial_elements >= 64 && total_channels >= 1) {
236 const std::vector<DataDimension>& dimensions,
245 return std::visit([&base](
const auto& vec) {
246 using V =
typename std::decay_t<
decltype(vec)>::value_type;
248 if constexpr (ComplexData<V>) {
250 }
else if constexpr (IntegerData<V>) {
263 "Inferring structure from single DataVariant is not advisable as the method makes naive assumptions that can lead to massive computational errors. "
264 "If the variant is part of a container, region, or segment, please use the appropriate method instead. "
265 "If the variant is part of a vector, please use infer_from_data_variant_vector instead. "
266 "If you are sure you want to proceed, please ignore this warning.");
268 return std::visit([](
const auto& vec) -> std::vector<DataDimension> {
269 using ValueType =
typename std::decay_t<
decltype(vec)>::value_type;
271 std::vector<DataDimension> dims;
273 if constexpr (DecimalData<ValueType>) {
276 }
else if constexpr (ComplexData<ValueType>) {
279 }
else if constexpr (IntegerData<ValueType>) {
281 }
else if constexpr (GlmData<ValueType>) {
282 constexpr size_t components = glm_component_count<ValueType>();
285 if constexpr (GlmVec2Type<ValueType>) {
287 }
else if constexpr (GlmVec3Type<ValueType>) {
289 }
else if constexpr (GlmVec4Type<ValueType>) {
291 }
else if constexpr (GlmMatrixType<ValueType>) {
296 "glm_structured_data",
297 static_cast<uint64_t
>(vec.size()),
298 static_cast<uint8_t
>(components),
310 const std::vector<DataVariant>& variants)
314 "Inferring structure from DataVariant vector is not advisable as the method makes naive assumptions that can lead to massive computational errors. "
315 "If the variants are part of a container, region, or segment, please use the appropriate method instead. "
316 "If you are sure you want to proceed, please ignore this warning.");
318 if (variants.empty()) {
319 std::vector<DataDimension> dims;
324 std::vector<DataDimension> dimensions;
325 size_t variant_count = variants.size();
327 size_t first_variant_size = std::visit([](
const auto& vec) ->
size_t {
332 bool consistent_glm = std::ranges::all_of(variants, [](
const auto& variant) {
333 return std::visit([](
const auto& vec) ->
bool {
334 using ValueType =
typename std::decay_t<
decltype(vec)>::value_type;
335 return GlmData<ValueType>;
340 bool consistent_decimal = std::ranges::all_of(variants, [](
const auto& variant) {
341 return std::visit([](
const auto& vec) ->
bool {
342 using ValueType =
typename std::decay_t<
decltype(vec)>::value_type;
343 return MayaFlux::DecimalData<ValueType>;
348 bool consistent_complex = std::ranges::all_of(variants, [](
const auto& variant) {
349 return std::visit([](
const auto& vec) ->
bool {
350 using ValueType =
typename std::decay_t<
decltype(vec)>::value_type;
351 return MayaFlux::ComplexData<ValueType>;
356 bool consistent_integer = std::ranges::all_of(variants, [](
const auto& variant) {
357 return std::visit([](
const auto& vec) ->
bool {
358 using ValueType =
typename std::decay_t<
decltype(vec)>::value_type;
359 return MayaFlux::IntegerData<ValueType>;
364 if (consistent_glm) {
367 std::visit([&](
const auto& first_vec) {
368 using ValueType =
typename std::decay_t<
decltype(first_vec)>::value_type;
369 constexpr size_t components = glm_component_count<ValueType>();
372 if constexpr (GlmVec2Type<ValueType>) {
374 }
else if constexpr (GlmVec3Type<ValueType>) {
376 }
else if constexpr (GlmVec4Type<ValueType>) {
383 static_cast<uint8_t
>(components),
391 if (variant_count == 1) {
392 if (consistent_decimal) {
394 }
else if (consistent_complex) {
396 }
else if (consistent_integer) {
399 dimensions.emplace_back(
"unknown_data", first_variant_size, 1,
403 }
else if (variant_count == 2 && (consistent_decimal || consistent_complex || consistent_integer)) {
405 if (consistent_decimal) {
407 }
else if (consistent_complex) {
413 }
else if (variant_count <= 16 && (consistent_decimal || consistent_complex || consistent_integer)) {
415 if (consistent_decimal) {
417 }
else if (consistent_complex) {
423 }
else if (consistent_decimal || consistent_complex || consistent_integer) {
424 if (consistent_decimal) {
426 dimensions.emplace_back(
"block_samples", first_variant_size, 1,
428 }
else if (consistent_complex) {
437 dimensions.emplace_back(
"mixed_variants", variant_count, 1,
439 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::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.
@ AUDIO_MULTICHANNEL
Multi-channel audio.
@ SPECTRAL_2D
2D spectral data (time + frequency)
@ AUDIO_1D
1D audio signal
@ 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.
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)
@ 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.