23 std::vector<Kakshya::DataDimension> dims,
54 template <ComputeData T>
91 const std::shared_ptr<Kakshya::CompositeContainer>& container)
94 error<std::invalid_argument>(Journal::Component::Yantra, Journal::Context::Runtime,
95 std::source_location::current(),
"Cannot extract data from null CompositeContainer");
97 return container->get_data();
101 template <CompositeData T>
104 return extract_composite_data(datum.
data);
111 template <
typename T>
112 requires detail::is_composite_operation_data_v<T>
113 static std::pair<std::reference_wrapper<const Kakshya::CompositeArray>,
DataStructureInfo>
116 return { std::cref(extract_composite_data(compute_data)),
117 get_structure_info(compute_data) };
124 template <
typename ValueT,
typename T>
125 requires(detail::is_composite_operation_data_v<T>
128 const T& compute_data, std::string_view field_name)
130 return extract_composite_data(compute_data).template to_nddata<ValueT>(field_name);
138 template <
typename ValueT,
typename T>
139 requires(detail::is_composite_operation_data_v<T>
142 const T& compute_data, std::string_view field_name)
144 auto projection = project_composite_field<ValueT>(compute_data, field_name);
148 const auto&
values = std::get<std::vector<ValueT>>(projection->values);
152 result.values.push_back(
static_cast<double>(
value));
153 result.presence = std::get<std::vector<uint8_t>>(std::move(projection->presence));
154 result.dimensions = std::move(projection->dimensions);
155 result.modality = projection->modality;
156 result.source_structure = get_structure_info(compute_data);
157 result.field_name = field_name;
167 template <
typename ValueT,
typename T>
168 requires(detail::is_composite_operation_data_v<T>
173 const auto& source = extract_composite_data(compute_data);
178 const auto& current_layout = source.layout();
179 if (original_layout.stride_bytes() != current_layout.stride_bytes()
180 || original_layout.presence_bytes() != current_layout.presence_bytes()
181 || original_layout.fields().size() != current_layout.fields().size())
184 for (
size_t i = 0; i < current_layout.fields().
size(); ++i) {
185 const auto& original = original_layout.fields()[i];
186 const auto&
current = current_layout.fields()[i];
187 if (original.name !=
current.name || original.type !=
current.type
188 || original.offset_bytes !=
current.offset_bytes
189 || original.size_bytes !=
current.size_bytes)
193 const auto field_index = source.layout().find_field(projected.
field_name);
194 if (!field_index || source.layout().fields()[*field_index].type !=
typeid(ValueT)
195 || projected.
values.size() != source.size()
196 || projected.
presence.size() != source.size())
200 for (
size_t row = 0; row < source.size(); ++row) {
208 if constexpr (std::integral<ValueT>) {
210 || value < static_cast<double>(std::numeric_limits<ValueT>::lowest())
211 ||
value >
static_cast<double>(std::numeric_limits<ValueT>::max()))
213 }
else if constexpr (std::same_as<ValueT, float>) {
214 if (std::isfinite(
value)
215 && (
value < -
static_cast<double>(std::numeric_limits<float>::max())
216 ||
value >
static_cast<double>(std::numeric_limits<float>::max())))
224 return std::optional<Kakshya::CompositeArray>(std::move(result));
245 template <
typename T>
249 if constexpr (std::is_same_v<T, Kakshya::DataVariant>) {
250 auto const_span = Kakshya::convert_variant<double>(compute_data);
251 return std::span<double>(
const_cast<double*
>(const_span.data()), const_span.size());
253 if constexpr (is_eigen_matrix_v<T>) {
255 return Kakshya::convert_variant<double>(variant, s_complex_strategy);
259 return Kakshya::convert_variant_to_double(variant, s_complex_strategy);
268 template <
typename T>
270 static std::vector<std::span<double>>
extract_numeric_data(
const T& compute_data,
bool needs_processig =
false)
272 if constexpr (std::is_same_v<T, std::vector<Kakshya::DataVariant>>) {
273 return Kakshya::convert_variants<double>(compute_data, s_complex_strategy);
276 if constexpr (std::is_same_v<T, std::shared_ptr<Kakshya::SignalSourceContainer>>) {
277 if (needs_processig) {
278 if (compute_data->get_processing_state() != Kakshya::ProcessingState::PROCESSED) {
279 compute_data->process_default();
280 compute_data->update_processing_state(Kakshya::ProcessingState::PROCESSED);
282 std::vector<Kakshya::DataVariant> variant = compute_data->get_processed_data();
283 return Kakshya::convert_variants<double>(variant, s_complex_strategy);
285 std::vector<Kakshya::DataVariant> variant = compute_data->get_data();
286 return Kakshya::convert_variants<double>(variant, s_complex_strategy);
289 if constexpr (is_eigen_matrix_v<T>)
290 return extract_from_eigen_matrix(compute_data);
292 return std::vector<std::span<double>> {};
302 template <
typename T>
305 const T& compute_data,
306 const std::shared_ptr<Kakshya::SignalSourceContainer>& container)
309 error<std::invalid_argument>(Journal::Component::Yantra, Journal::Context::ContainerProcessing, std::source_location::current(),
"Null container provided for region extraction");
312 if constexpr (std::is_same_v<T, Kakshya::Region>) {
313 auto data = container->get_region_data(compute_data);
314 return Kakshya::convert_variants<double>(data);
316 }
else if constexpr (std::is_same_v<T, Kakshya::RegionGroup>) {
317 if (compute_data.regions.empty()) {
318 error<std::runtime_error>(Journal::Component::Yantra, Journal::Context::ContainerProcessing, std::source_location::current(),
"Empty RegionGroup cannot be extracted");
320 auto data = container->get_region_group_data(compute_data);
321 return Kakshya::convert_variants<double>(data);
323 }
else if constexpr (std::is_same_v<T, std::vector<Kakshya::RegionSegment>>) {
324 if (compute_data.empty()) {
325 error<std::runtime_error>(Journal::Component::Yantra, Journal::Context::ContainerProcessing, std::source_location::current(),
"Empty RegionSegment vector cannot be extracted");
327 auto data = container->get_segments_data(compute_data);
328 return Kakshya::convert_variants<double>(data);
362 return std::span<
const typename std::decay_t<
decltype(vec)>::value_type>(
363 vec.data(), vec.size());
378 const std::vector<Kakshya::DataVariant>& variants)
380 std::vector<Kakshya::DataSpanVariant> result;
381 result.reserve(variants.size());
382 for (
const auto& v : variants)
383 result.push_back(extract_native_data(v));
399 const std::shared_ptr<Kakshya::SignalSourceContainer>& container,
400 bool use_processed =
false)
402 if (!container || !container->has_data())
405 const auto& variants = use_processed
406 ? container->get_processed_data()
407 : container->get_data();
409 return extract_native_data(variants);
422 template <
typename EigenMatrix>
423 requires is_eigen_matrix_v<EigenMatrix>
425 -> std::vector<std::span<const typename EigenMatrix::Scalar>>
427 using Scalar =
typename EigenMatrix::Scalar;
428 std::vector<std::span<const Scalar>> result;
429 result.reserve(
static_cast<size_t>(matrix.cols()));
431 for (
int col = 0; col < matrix.cols(); ++col) {
432 result.emplace_back(matrix.col(col).data(),
static_cast<size_t>(matrix.rows()));
443 template <
typename T>
447 if constexpr (std::is_same_v<T, std::vector<Kakshya::DataVariant>>) {
451 if constexpr (std::is_same_v<T, std::shared_ptr<Kakshya::SignalSourceContainer>>) {
452 if (compute_data->get_processing_state() == Kakshya::ProcessingState::PROCESSED) {
453 return compute_data->get_processed_data();
455 return compute_data->get_data();
458 if constexpr (is_eigen_matrix_v<T>) {
459 return convert_eigen_matrix_to_variant(compute_data);
470 template <
typename T>
473 const T& compute_data,
474 const std::shared_ptr<Kakshya::SignalSourceContainer>& container)
476 if constexpr (std::is_same_v<T, Kakshya::Region>) {
477 return container->get_region_data(compute_data);
478 }
else if constexpr (std::is_same_v<T, Kakshya::RegionGroup>) {
479 return container->get_region_group_data(compute_data);
480 }
else if constexpr (std::is_same_v<T, std::vector<Kakshya::RegionSegment>>) {
481 return container->get_segments_data(compute_data);
491 template <OperationReadyData T>
496 info.
original_type = std::type_index(
typeid(std::decay_t<
decltype(compute_data.data)>));
497 info.dimensions = compute_data.dimensions;
498 info.modality = compute_data.modality;
499 if constexpr (
CompositeData<std::decay_t<
decltype(compute_data.data)>>)
500 info.composite_layout = extract_composite_data(compute_data.data).layout();
505 auto [dims, mod] = infer_structure(compute_data);
506 info.dimensions = std::move(dims);
509 info.composite_layout = extract_composite_data(compute_data).layout();
521 template <OperationReadyData T>
522 requires(!detail::is_composite_operation_data_v<T>)
528 info.
original_type = std::type_index(
typeid(std::decay_t<
decltype(compute_data.data)>));
529 info.dimensions = compute_data.dimensions;
530 info.modality = compute_data.modality;
533 if (!compute_data.has_container()) {
534 error<std::runtime_error>(Journal::Component::Yantra, Journal::Context::ContainerProcessing, std::source_location::current(),
"Container is required for region-like data extraction but not provided");
536 std::vector<std::span<double>> double_data = extract_numeric_data(compute_data.data, compute_data.container.value());
537 return std::make_tuple(double_data, info);
539 std::vector<std::span<double>> double_data = extract_numeric_data(compute_data.data, compute_data.needs_processig());
540 return std::make_tuple(double_data, info);
545 std::vector<std::span<double>> double_data = extract_numeric_data(compute_data);
546 auto [dimensions, modality] = infer_structure(compute_data);
547 info.dimensions = dimensions;
548 info.modality = modality;
550 return std::make_tuple(double_data, info);
580 template <OperationReadyData T>
581 requires(!detail::is_composite_operation_data_v<T>)
587 info.
original_type = std::type_index(
typeid(std::decay_t<
decltype(compute_data.data)>));
588 info.dimensions = compute_data.dimensions;
589 info.modality = compute_data.modality;
592 if (!compute_data.has_container()) {
593 error<std::runtime_error>(
594 Journal::Component::Yantra,
595 Journal::Context::ContainerProcessing,
596 std::source_location::current(),
597 "Container is required for region-like data extraction but not provided");
600 const auto region_variants = [&]() -> std::vector<Kakshya::DataVariant> {
601 if constexpr (std::is_same_v<std::decay_t<
decltype(compute_data.data)>,
Kakshya::Region>) {
602 return compute_data.container.value()->get_region_data(compute_data.data);
603 }
else if constexpr (std::is_same_v<std::decay_t<
decltype(compute_data.data)>,
Kakshya::RegionGroup>) {
604 return compute_data.container.value()->get_region_group_data(compute_data.data);
606 return compute_data.container.value()->get_segments_data(compute_data.data);
609 return { extract_native_data(region_variants), info };
611 auto spans = extract_native_data(compute_data.data);
612 return { std::move(spans), info };
617 auto spans = extract_native_data(compute_data);
618 auto [dimensions, modality] = infer_structure(compute_data);
619 info.dimensions = dimensions;
620 info.modality = modality;
621 return { std::move(spans), info };
632 template <ComputeData T>
637 if constexpr (std::is_same_v<T, std::vector<std::vector<double>>>) {
639 }
else if constexpr (std::is_same_v<T, Eigen::MatrixXd>) {
640 return recreate_eigen_matrix(double_data, structure_info);
641 }
else if constexpr (std::is_same_v<T, std::vector<Kakshya::DataVariant>>) {
642 std::vector<Kakshya::DataVariant> variants;
643 variants.reserve(double_data.size());
644 for (
const auto& vec : double_data) {
645 variants.emplace_back(vec);
648 }
else if constexpr (std::is_same_v<T, Kakshya::DataVariant>) {
649 auto data = Kakshya::interleave_channels<double>(double_data);
650 return reconstruct_data_variant_from_double(data, structure_info);
652 error<std::runtime_error>(Journal::Component::Yantra, Journal::Context::Runtime, std::source_location::current(),
"Reconstruction not implemented for target type {}", structure_info.
original_type.name());
664 template <
typename T>
669 using UnderlyingType = std::decay_t<decltype(std::declval<T>().data)>;
672 io_data.dimensions = structure_info.
dimensions;
673 io_data.modality = structure_info.
modality;
675 io_data.data = reconstruct_from_double<UnderlyingType>(double_data, structure_info);
687 template <OperationReadyData T>
688 requires(!detail::is_composite_operation_data_v<T>)
691 auto [data_spans, structure_info] = extract_structured_double(
input);
693 if (working_buffer.size() != data_spans.size()) {
694 working_buffer.resize(data_spans.size());
697 std::vector<std::span<double>> working_spans(working_buffer.size());
699 for (
size_t i = 0; i < data_spans.size(); i++) {
700 working_buffer[i].resize(data_spans[i].
size());
701 std::ranges::copy(data_spans[i], working_buffer[i].begin());
702 working_spans[i] = std::span<double>(working_buffer[i].data(), working_buffer[i].
size());
705 return std::make_tuple(working_spans, structure_info);
714 template <
typename EigenType>
717 std::vector<double> flat_data;
719 if constexpr (EigenType::IsVectorAtCompileTime) {
720 flat_data.resize(eigen_data.size());
721 for (
int i = 0; i < eigen_data.size(); ++i) {
722 flat_data[i] =
static_cast<double>(eigen_data(i));
725 flat_data.resize(eigen_data.size());
727 for (
int i = 0; i < eigen_data.rows(); ++i) {
728 for (
int j = 0; j < eigen_data.cols(); ++j) {
729 flat_data[idx++] =
static_cast<double>(eigen_data(i, j));
743 template <
typename EigenMatrix>
746 static thread_local std::vector<std::vector<double>>
columns;
749 std::vector<std::span<double>> spans;
750 spans.reserve(matrix.cols());
752 for (
int col = 0; col < matrix.cols(); ++col) {
753 columns[col].resize(matrix.rows());
754 for (
int row = 0; row < matrix.rows(); ++row) {
755 columns[col][row] =
static_cast<double>(matrix(row, col));
781 template <
typename EigenMatrix>
784 std::vector<Kakshya::DataVariant>
columns(matrix.cols());
786 for (
int col = 0; col < matrix.cols(); ++col) {
787 auto row_indices = std::views::iota(0, matrix.rows());
788 auto col_data = row_indices
789 | std::views::transform([&](
int row) {
return static_cast<double>(matrix(row, col)); });
790 columns[col] = { std::vector<double>(col_data.begin(), col_data.end()) };
801 template <
typename T>
811 for (
const auto& col :
columns) {
812 if (col.size() !=
rows) {
813 error<std::invalid_argument>(Journal::Component::Yantra, Journal::Context::Runtime, std::source_location::current(),
"All columns must have same size");
817 Eigen::MatrixXd matrix(
rows, cols);
818 for (
int col = 0; col < cols; ++col) {
819 for (
int row = 0; row <
rows; ++row) {
820 matrix(row, col) =
static_cast<double>(
columns[col][row]);
829 template <
typename T>
836 int rows = spans[0].size();
837 int cols = spans.size();
839 for (
const auto& span : spans) {
840 if (span.size() !=
rows) {
841 error<std::invalid_argument>(Journal::Component::Yantra, Journal::Context::Runtime, std::source_location::current(),
"All spans must have same size");
845 Eigen::MatrixXd matrix(
rows, cols);
846 for (
int col = 0; col < cols; ++col) {
847 for (
int row = 0; row <
rows; ++row) {
848 matrix(row, col) =
static_cast<double>(spans[col][row]);
861 static Eigen::MatrixXd recreate_eigen_matrix(
862 const std::vector<std::vector<double>>&
columns,
872 static Eigen::MatrixXd recreate_eigen_matrix(
873 const std::vector<std::span<const double>>& spans,
879 static Kakshya::DataVariant reconstruct_data_variant_from_double(
const std::vector<double>& double_data,
Core::GlobalInputConfig input
std::vector< std::byte > values
vk::PhysicalDeviceType type
bool clear(size_t index, std::string_view field_name)
Mark a field absent without removing its stored bytes.
bool set(size_t index, std::string_view field_name, T value)
Write an arithmetic field of an existing element.
Owns a sequence of values that share a CompositeLayout.
static Eigen::MatrixXd create_eigen_matrix(const std::vector< std::span< const T > > &spans)
Create Eigen matrix from spans.
static std::vector< std::span< double > > extract_from_eigen_matrix(const EigenMatrix &matrix)
Infer data structure from ComputeData type.
static Kakshya::ComplexConversionStrategy get_complex_conversion_strategy()
Get current complex conversion strategy.
static const Kakshya::CompositeArray & extract_composite_data(const Datum< T > &datum)
Borrow Composite data carried by a Datum.
static auto setup_operation_buffer(T &input, std::vector< std::vector< double > > &working_buffer)
Setup operation buffer from Datum or ComputeData type.
static Eigen::MatrixXd create_eigen_matrix(const std::vector< std::vector< T > > &columns)
Infer data structure from ComputeData type.
static std::vector< Kakshya::DataVariant > convert_eigen_matrix_to_variant(const EigenMatrix &matrix)
Extract data from Eigen vector to double span.
static std::optional< CompositeFieldDoubleData > extract_projected_composite_double(const T &compute_data, std::string_view field_name)
Extract one compatible numeric field for double-based operations.
static std::pair< std::reference_wrapper< const Kakshya::CompositeArray >, DataStructureInfo > extract_structured_composite(const T &compute_data)
Borrow Composite records together with their row axis and field layout.
static std::vector< Kakshya::DataSpanVariant > extract_native_data(const std::shared_ptr< Kakshya::SignalSourceContainer > &container, bool use_processed=false)
Extract native-typed channel spans from a SignalSourceContainer.
static std::vector< Kakshya::DataVariant > to_data_variant(const T &compute_data, const std::shared_ptr< Kakshya::SignalSourceContainer > &container)
Convert region-like ComputeData to DataVariant format.
static std::optional< Kakshya::CompositeArray > reconstruct_projected_composite(const T &compute_data, const CompositeFieldDoubleData &projected)
Copy Composite records and replace one projected numeric field.
static T reconstruct_from_double(const std::vector< std::vector< double > > &double_data, const DataStructureInfo &structure_info)
Reconstruct Datum type from double vector and structure info.
static std::tuple< std::vector< Kakshya::DataSpanVariant >, DataStructureInfo > extract_structured_native(T &compute_data)
Extract native-typed channel spans and structure metadata from a Datum or direct ComputeData,...
static std::vector< std::span< double > > extract_numeric_data(const T &compute_data, const std::shared_ptr< Kakshya::SignalSourceContainer > &container)
extract numeric data from region-like types
static Kakshya::DataSpanVariant extract_native_data(const Kakshya::DataVariant &variant)
Extract a single DataVariant as a type-erased span without conversion.
static std::vector< Kakshya::DataSpanVariant > extract_native_data(const std::vector< Kakshya::DataVariant > &variants)
Extract a vector of DataVariants as type-erased spans without conversion.
static const Kakshya::CompositeArray & extract_composite_data(const Kakshya::CompositeArray &data) noexcept
Borrow an owning Composite array without converting its fields.
static void set_complex_conversion_strategy(Kakshya::ComplexConversionStrategy strategy)
Set global complex conversion strategy.
static std::vector< std::span< double > > extract_numeric_data(const T &compute_data, bool needs_processig=false)
extract numeric data from multi-variant types
static DataStructureInfo get_structure_info(const T &compute_data)
Populate DataStructureInfo from a Datum without extracting spans.
static std::optional< Kakshya::CompositeProjection > project_composite_field(const T &compute_data, std::string_view field_name)
Project one exact-type numeric Composite field to compatible NDData.
static const Kakshya::CompositeArray & extract_composite_data(const std::shared_ptr< Kakshya::CompositeContainer > &container)
Borrow the array owned by a Composite container.
static std::vector< Kakshya::DataVariant > to_data_variant(const T &compute_data)
Convert ComputeData to DataVariant format.
static std::span< double > extract_numeric_data(const T &compute_data)
extract numeric data from single-variant types
static Kakshya::DataVariant create_data_variant_from_eigen(const EigenType &eigen_data)
Create DataVariant from Eigen matrix/vector.
static auto extract_native_data(const EigenMatrix &matrix) -> std::vector< std::span< const typename EigenMatrix::Scalar > >
Extract native-typed column spans from any Eigen matrix.
static std::tuple< std::vector< std::span< double > >, DataStructureInfo > extract_structured_double(T &compute_data)
Extract structured double data from Datum container or direct ComputeData with automatic container ha...
static T reconstruct_from_double(const std::vector< std::vector< double > > &double_data, const DataStructureInfo &structure_info)
Reconstruct ComputeData type from double vector and structure info.
Structure and extraction helpers for Yantra operation data.
Concept to constrain types to valid DataVariant elements.
Composite data that retains its field layout and presence information.
Any Eigen matrix type, regardless of scalar type.
Types that yield multiple data channels on extraction.
Types that represent spatial or temporal markers requiring a container to resolve data.
Types that need an associated SignalSourceContainer to extract data.
Single data source: one DataVariant, a column Eigen vector of any scalar type, or any type constructi...
typename detail::span_const_from_vector_variant< DataVariant >::type DataSpanVariant
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.
@ UNKNOWN
Unknown or undefined modality.
@ TENSOR_ND
N-dimensional tensor.
ComplexConversionStrategy
Strategy for converting complex numbers to real values.
constexpr bool is_composite_operation_data_v
Organizes related signal regions into a categorized collection.
Represents a point or span in N-dimensional space.
DataStructureInfo source_structure
std::vector< double > values
std::vector< uint8_t > presence
std::vector< Kakshya::DataDimension > dimensions
Kakshya::DataModality modality
Owning double projection of one Composite field with its presence mask.
std::optional< Kakshya::CompositeLayout > composite_layout
DataStructureInfo(Kakshya::DataModality mod, std::vector< Kakshya::DataDimension > dims, std::type_index type)
std::type_index original_type
Kakshya::DataModality modality
DataStructureInfo()=default
std::vector< Kakshya::DataDimension > dimensions
Dimensions, modality, source type, and optional Composite field schema.
T data
The actual computation data.
Input/Output container for computation pipeline data flow with structure preservation.
Helper to detect if a type is an Datum.