7#include <glm/gtc/type_ptr.hpp>
22template <
typename From,
typename To,
typename Enable =
void>
24 static std::span<To>
convert(std::span<From> ,
28 static_assert(always_false_v<From>,
"No conversion available for these types");
37 static std::span<T>
convert(std::span<T> source,
47template <
typename From,
typename To>
51 ArithmeticData<From> && ArithmeticData<To> && !std::is_same_v<From, To> && !GlmType<From> && !GlmType<To>>> {
53 std::span<From> source,
59 source.begin(), source.end(),
storage.begin(),
60 [](From val) { return static_cast<To>(val); });
68template <
typename From,
typename To>
72 ComplexData<From> && ArithmeticData<To> && !GlmType<From> && !GlmType<To>>> {
74 std::span<From> source,
80 for (
size_t i = 0; i < source.size(); ++i) {
83 storage[i] =
static_cast<To
>(std::abs(source[i]));
86 storage[i] =
static_cast<To
>(source[i].real());
89 storage[i] =
static_cast<To
>(source[i].imag());
92 storage[i] =
static_cast<To
>(std::norm(source[i]));
103template <
typename From,
typename To>
107 ArithmeticData<From> && ComplexData<To> && !GlmType<From> && !GlmType<To>>> {
109 std::span<From> source,
113 using ComplexValueType =
typename To::value_type;
116 for (
size_t i = 0; i < source.size(); ++i) {
117 storage[i] = To(
static_cast<ComplexValueType
>(source[i]), ComplexValueType { 0 });
126template <
typename From,
typename To>
130 GlmType<From> && ArithmeticData<To> && !GlmType<To>>> {
132 std::span<From> source,
136 constexpr size_t components = glm_component_count<From>();
137 using ComponentType = glm_component_type<From>;
139 storage.resize(source.size() * components);
142 for (
const auto& elem : source) {
143 const ComponentType*
ptr = glm::value_ptr(elem);
144 for (
size_t c = 0; c < components; ++c) {
155template <
typename From,
typename To>
159 ArithmeticData<From> && GlmType<To> && !GlmType<From>>> {
161 std::span<From> source,
165 constexpr size_t components = glm_component_count<To>();
166 using ComponentType = glm_component_type<To>;
168 if (source.size() % components != 0) {
169 error<std::invalid_argument>(
172 std::source_location::current(),
173 "Source size ({}) must be multiple of GLM component count ({})",
178 size_t element_count = source.size() / components;
181 for (
size_t i = 0; i < element_count; ++i) {
182 ComponentType temp[components];
183 for (
size_t c = 0; c < components; ++c) {
184 temp[c] =
static_cast<ComponentType
>(source[i * components + c]);
187 if constexpr (GlmVec2Type<To>) {
188 storage[i] = To(temp[0], temp[1]);
189 }
else if constexpr (GlmVec3Type<To>) {
190 storage[i] = To(temp[0], temp[1], temp[2]);
191 }
else if constexpr (GlmVec4Type<To>) {
192 storage[i] = To(temp[0], temp[1], temp[2], temp[3]);
193 }
else if constexpr (GlmMatrixType<To>) {
194 storage[i] = glm::make_mat4(temp);
204template <
typename From,
typename To>
208 GlmType<From> && GlmType<To> && !std::is_same_v<From, To> && (glm_component_count<From>() == glm_component_count<To>())>> {
210 std::span<From> source,
214 using FromComponent = glm_component_type<From>;
215 using ToComponent = glm_component_type<To>;
216 constexpr size_t components = glm_component_count<From>();
220 for (
size_t i = 0; i < source.size(); ++i) {
221 const FromComponent* src_ptr = glm::value_ptr(source[i]);
222 ToComponent temp[components];
224 for (
size_t c = 0; c < components; ++c) {
225 temp[c] =
static_cast<ToComponent
>(src_ptr[c]);
228 if constexpr (GlmVec2Type<To>) {
229 storage[i] = To(temp[0], temp[1]);
230 }
else if constexpr (GlmVec3Type<To>) {
231 storage[i] = To(temp[0], temp[1], temp[2]);
232 }
else if constexpr (GlmVec4Type<To>) {
233 storage[i] = To(temp[0], temp[1], temp[2], temp[3]);
234 }
else if constexpr (GlmMatrixType<To>) {
235 storage[i] = glm::make_mat4(temp);
244template <
typename From,
typename To>
248 ComplexData<From> && ComplexData<To> && !GlmType<From> && !GlmType<To> && !std::is_same_v<From, To>>> {
250 std::span<From> source,
254 using FromValue =
typename From::value_type;
255 using ToValue =
typename To::value_type;
258 for (
size_t i = 0; i < source.size(); ++i) {
259 const auto r =
static_cast<FromValue
>(source[i].real());
260 const auto im =
static_cast<FromValue
>(source[i].imag());
261 storage[i] = To(
static_cast<ToValue
>(r),
static_cast<ToValue
>(im));
302template <ProcessableData T>
303constexpr std::span<T>
extract_frame(std::span<T> data, uint64_t frame_index, uint64_t frame_size)
noexcept
305 uint64_t start = frame_index * frame_size;
306 uint64_t end = std::min(
static_cast<uint64_t
>(start + frame_size),
307 static_cast<uint64_t
>(data.size()));
309 if (start >= data.size()) {
313 return data.subspan(start, end - start);
324template <ProcessableData T>
326 const std::vector<std::span<T>>& channel_spans,
327 uint64_t frame_index,
328 std::vector<T>& output_buffer)
noexcept
330 output_buffer.clear();
331 output_buffer.reserve(channel_spans.size());
333 for (
const auto& channel_span : channel_spans) {
334 if (frame_index < channel_span.size()) {
335 output_buffer.push_back(channel_span[frame_index]);
337 output_buffer.push_back(T { 0 });
341 return std::span<T>(output_buffer.data(), output_buffer.size());
352template <
typename From,
typename To>
363template <
typename From,
typename To>
364 requires(ComplexData<From> && ArithmeticData<To>)
366 std::span<To> destination,
369 std::vector<To> temp_storage;
370 auto result =
convert_data(source, temp_storage, strategy);
371 std::copy_n(result.begin(), std::min(result.size(), destination.size()), destination.begin());
381template <ProcessableData T>
385 if (std::holds_alternative<std::vector<T>>(variant)) {
386 auto& vec = std::get<std::vector<T>>(variant);
387 return std::span<T>(vec.data(), vec.size());
390 return std::visit([&variant, strategy](
auto& data) -> std::span<T> {
391 using ValueType =
typename std::decay_t<
decltype(data)>::value_type;
393 if constexpr (is_convertible_data_v<ValueType, T>) {
394 std::vector<T> new_storage;
395 auto source_span = std::span<ValueType>(data.data(), data.size());
396 auto result =
convert_data(source_span, new_storage, strategy);
398 variant = std::move(new_storage);
399 auto& new_vec = std::get<std::vector<T>>(variant);
400 return std::span<T>(new_vec.data(), new_vec.size());
402 error<std::invalid_argument>(
405 std::source_location::current(),
406 "No conversion available from {} to {}",
407 typeid(ValueType).name(),
414template <ProcessableData T>
418 return convert_variant<T>(
const_cast<DataVariant&
>(variant), strategy);
421template <ProcessableData T>
423 const std::vector<DataVariant>& variants,
426 std::vector<std::span<T>> result;
427 result.reserve(variants.size());
429 for (
const auto& i : variants) {
430 result.push_back(convert_variant<T>(
const_cast<DataVariant&
>(i), strategy));
444template <ProcessableData From, ProcessableData To>
446 std::vector<To>& destination,
449 const size_t total_bytes = source.size() *
sizeof(From);
450 const size_t required_elements = (total_bytes +
sizeof(To) - 1) /
sizeof(To);
451 destination.resize(required_elements);
453 if constexpr (std::is_same_v<From, To>) {
454 destination.resize(source.size());
455 std::memcpy(destination.data(), source.data(), total_bytes);
456 return std::span<To>(destination.data(), source.size());
457 }
else if constexpr (std::is_trivially_copyable_v<From> && std::is_trivially_copyable_v<To> && (
sizeof(From) ==
sizeof(To))) {
459 std::memcpy(destination.data(), source.data(), total_bytes);
460 return std::span<To>(destination.data(), source.size());
463 std::vector<From> temp(source.begin(), source.end());
464 auto converted = convert_data<From, To>(std::span<const From>(temp), strategy);
465 destination.assign(converted.begin(), converted.end());
466 return std::span<To>(destination.data(), destination.size());
476template <ProcessableData T>
481 return std::visit([&
storage, strategy](
const auto& data) -> std::span<T> {
482 using ValueType =
typename std::decay_t<
decltype(data)>::value_type;
484 if constexpr (std::is_same_v<ValueType, T>) {
487 }
else if constexpr (is_convertible_data_v<ValueType, T>) {
488 auto source_span = std::span<const ValueType>(data.data(), data.size());
489 std::vector<ValueType> temp_source(source_span.begin(), source_span.end());
490 auto temp_span = std::span<ValueType>(temp_source.data(), temp_source.size());
493 error<std::invalid_argument>(
496 std::source_location::current(),
497 "No conversion available from {} to {}",
498 typeid(ValueType).name(),
515 return std::visit([pos](
const auto& data) -> std::optional<T> {
516 using DataType = std::decay_t<
decltype(data)>;
517 using ValueType =
typename DataType::value_type;
519 if (pos >= data.size()) {
523 if constexpr (std::is_same_v<ValueType, T>) {
525 }
else if constexpr (std::is_arithmetic_v<ValueType> && std::is_arithmetic_v<T>) {
526 return static_cast<T
>(data[pos]);
527 }
else if constexpr (std::is_same_v<ValueType, std::complex<float>> || std::is_same_v<ValueType, std::complex<double>>) {
528 if constexpr (std::is_arithmetic_v<T>) {
529 return static_cast<T
>(std::abs(data[pos]));
556 std::vector<T> temp_storage;
557 auto input_span = extract_from_variant<T>(
input, temp_storage);
558 auto output_span = get_typed_data<T>(
output);
559 std::copy_n(input_span.begin(), std::min(input_span.size(), output_span.size()),
560 output_span.begin());
572 return convert_variant<double>(data, strategy);
607 std::span<const float> src,
608 std::span<uint8_t> dst);
617 std::span<const float> src);
625void set_metadata_value(std::unordered_map<std::string, std::any>& metadata,
const std::string& key, std::any
value);
635std::optional<T>
get_metadata_value(
const std::unordered_map<std::string, std::any>& metadata,
const std::string& key)
637 auto it = metadata.find(key);
638 if (it != metadata.end()) {
640 return safe_any_cast<T>(it->second);
641 }
catch (
const std::bad_any_cast&) {
678 const std::vector<DataDimension>& dimensions,
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::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< 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.
std::span< T > extract_from_variant(const DataVariant &variant, std::vector< T > &storage, ComplexConversionStrategy strategy=ComplexConversionStrategy::MAGNITUDE)
Get typed span from DataVariant using concepts.
uint64_t calculate_frame_size(const std::vector< DataDimension > &dimensions)
Calculate the frame size (number of elements per frame) for a set of dimensions.
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::span< To > extract_data(std::span< const From > source, std::vector< To > &destination, ComplexConversionStrategy strategy=ComplexConversionStrategy::MAGNITUDE)
Concept-based data extraction with type conversion.
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.
std::span< double > convert_variant_to_double(DataVariant &data, ComplexConversionStrategy strategy=ComplexConversionStrategy::MAGNITUDE)
Convert variant to double span.
DataModality
Data modality types for cross-modal analysis.
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).
void convert_complex(std::span< From > source, std::span< To > destination, ComplexConversionStrategy strategy)
Legacy interface - redirects to convert_data.
DataModality detect_data_modality(const std::vector< DataDimension > &dimensions)
Detects data modality from dimension information.
void safe_copy_typed_variant(const DataVariant &input, DataVariant &output)
Safely copy data from a DataVariant to another DataVariant of a specific type.
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.
std::span< To > convert_data(std::span< From > source, std::vector< To > &storage, ComplexConversionStrategy strategy=ComplexConversionStrategy::MAGNITUDE)
Convert a span of one data type to another (with type conversion).
ComplexConversionStrategy
Strategy for converting complex numbers to real values.
@ SQUARED_MAGNITUDE
|z|² = real² + imag²
@ MAGNITUDE
|z| = sqrt(real² + imag²)
std::span< T > convert_variant(DataVariant &variant, ComplexConversionStrategy strategy=ComplexConversionStrategy::MAGNITUDE)
Get const span from DataVariant without conversion (zero-copy for matching types)
uint64_t calculate_total_elements(const std::vector< DataDimension > &dimensions)
Calculate the total number of elements in an N-dimensional container.
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::vector< std::span< T > > convert_variants(const std::vector< DataVariant > &variants, ComplexConversionStrategy strategy=ComplexConversionStrategy::MAGNITUDE)
static std::span< To > convert(std::span< From > source, std::vector< To > &storage, ComplexConversionStrategy=ComplexConversionStrategy::MAGNITUDE)
static std::span< To > convert(std::span< From > source, std::vector< To > &storage, ComplexConversionStrategy=ComplexConversionStrategy::MAGNITUDE)
static std::span< To > convert(std::span< From > source, std::vector< To > &storage, ComplexConversionStrategy=ComplexConversionStrategy::MAGNITUDE)
static std::span< To > convert(std::span< From > source, std::vector< To > &storage, ComplexConversionStrategy strategy)
static std::span< To > convert(std::span< From > source, std::vector< To > &storage, ComplexConversionStrategy=ComplexConversionStrategy::MAGNITUDE)
static std::span< To > convert(std::span< From > source, std::vector< To > &storage, ComplexConversionStrategy=ComplexConversionStrategy::MAGNITUDE)
static std::span< To > convert(std::span< From > source, std::vector< To > &storage, ComplexConversionStrategy=ComplexConversionStrategy::MAGNITUDE)
static std::span< T > convert(std::span< T > source, std::vector< T > &, ComplexConversionStrategy=ComplexConversionStrategy::MAGNITUDE)
static std::span< To > convert(std::span< From >, std::vector< To > &, ComplexConversionStrategy=ComplexConversionStrategy::MAGNITUDE)
Role
Semantic role of the dimension.