21 std::vector<Kakshya::DataDimension> dims,
73 if constexpr (std::is_same_v<T, Kakshya::DataVariant>) {
74 auto const_span = Kakshya::convert_variant<double>(compute_data);
75 return std::span<double>(
const_cast<double*
>(const_span.data()), const_span.size());
77 if constexpr (is_eigen_matrix_v<T>) {
79 return Kakshya::convert_variant<double>(variant, s_complex_strategy);
83 return Kakshya::convert_variant_to_double(variant, s_complex_strategy);
94 static std::vector<std::span<double>>
extract_numeric_data(
const T& compute_data,
bool needs_processig =
false)
96 if constexpr (std::is_same_v<T, std::vector<Kakshya::DataVariant>>) {
97 return Kakshya::convert_variants<double>(compute_data, s_complex_strategy);
100 if constexpr (std::is_same_v<T, std::shared_ptr<Kakshya::SignalSourceContainer>>) {
101 if (needs_processig) {
102 if (compute_data->get_processing_state() != Kakshya::ProcessingState::PROCESSED) {
103 compute_data->process_default();
104 compute_data->update_processing_state(Kakshya::ProcessingState::PROCESSED);
106 std::vector<Kakshya::DataVariant> variant = compute_data->get_processed_data();
107 return Kakshya::convert_variants<double>(variant, s_complex_strategy);
109 std::vector<Kakshya::DataVariant> variant = compute_data->get_data();
110 return Kakshya::convert_variants<double>(variant, s_complex_strategy);
113 if constexpr (is_eigen_matrix_v<T>)
114 return extract_from_eigen_matrix(compute_data);
116 return std::vector<std::span<double>> {};
126 template <
typename T>
129 const T& compute_data,
130 const std::shared_ptr<Kakshya::SignalSourceContainer>& container)
133 error<std::invalid_argument>(Journal::Component::Yantra, Journal::Context::ContainerProcessing, std::source_location::current(),
"Null container provided for region extraction");
136 if constexpr (std::is_same_v<T, Kakshya::Region>) {
137 auto data = container->get_region_data(compute_data);
138 return Kakshya::convert_variants<double>(data);
140 }
else if constexpr (std::is_same_v<T, Kakshya::RegionGroup>) {
141 if (compute_data.regions.empty()) {
142 error<std::runtime_error>(Journal::Component::Yantra, Journal::Context::ContainerProcessing, std::source_location::current(),
"Empty RegionGroup cannot be extracted");
144 auto data = container->get_region_group_data(compute_data);
145 return Kakshya::convert_variants<double>(data);
147 }
else if constexpr (std::is_same_v<T, std::vector<Kakshya::RegionSegment>>) {
148 if (compute_data.empty()) {
149 error<std::runtime_error>(Journal::Component::Yantra, Journal::Context::ContainerProcessing, std::source_location::current(),
"Empty RegionSegment vector cannot be extracted");
151 auto data = container->get_segments_data(compute_data);
152 return Kakshya::convert_variants<double>(data);
186 return std::span<
const typename std::decay_t<
decltype(vec)>::value_type>(
187 vec.data(), vec.size());
202 const std::vector<Kakshya::DataVariant>& variants)
204 std::vector<Kakshya::DataSpanVariant> result;
205 result.reserve(variants.size());
206 for (
const auto& v : variants)
207 result.push_back(extract_native_data(v));
223 const std::shared_ptr<Kakshya::SignalSourceContainer>& container,
224 bool use_processed =
false)
226 if (!container || !container->has_data())
229 const auto& variants = use_processed
230 ? container->get_processed_data()
231 : container->get_data();
233 return extract_native_data(variants);
246 template <
typename EigenMatrix>
247 requires is_eigen_matrix_v<EigenMatrix>
249 -> std::vector<std::span<const typename EigenMatrix::Scalar>>
251 using Scalar =
typename EigenMatrix::Scalar;
252 std::vector<std::span<const Scalar>> result;
253 result.reserve(
static_cast<size_t>(matrix.cols()));
255 for (
int col = 0; col < matrix.cols(); ++col) {
256 result.emplace_back(matrix.col(col).data(),
static_cast<size_t>(matrix.rows()));
267 template <
typename T>
271 if constexpr (std::is_same_v<T, std::vector<Kakshya::DataVariant>>) {
275 if constexpr (std::is_same_v<T, std::shared_ptr<Kakshya::SignalSourceContainer>>) {
276 if (compute_data->get_processing_state() == Kakshya::ProcessingState::PROCESSED) {
277 return compute_data->get_processed_data();
279 return compute_data->get_data();
282 if constexpr (is_eigen_matrix_v<T>) {
283 return convert_eigen_matrix_to_variant(compute_data);
294 template <
typename T>
297 const T& compute_data,
298 const std::shared_ptr<Kakshya::SignalSourceContainer>& container)
300 if constexpr (std::is_same_v<T, Kakshya::Region>) {
301 return container->get_region_data(compute_data);
302 }
else if constexpr (std::is_same_v<T, Kakshya::RegionGroup>) {
303 return container->get_region_group_data(compute_data);
304 }
else if constexpr (std::is_same_v<T, std::vector<Kakshya::RegionSegment>>) {
305 return container->get_segments_data(compute_data);
315 template <OperationReadyData T>
320 info.
original_type = std::type_index(
typeid(std::decay_t<
decltype(compute_data.data)>));
321 info.dimensions = compute_data.dimensions;
322 info.modality = compute_data.modality;
327 auto [dims, mod] = infer_structure(compute_data);
328 info.dimensions = std::move(dims);
341 template <OperationReadyData T>
347 info.
original_type = std::type_index(
typeid(std::decay_t<
decltype(compute_data.data)>));
348 info.dimensions = compute_data.dimensions;
349 info.modality = compute_data.modality;
352 if (!compute_data.has_container()) {
353 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");
355 std::vector<std::span<double>> double_data = extract_numeric_data(compute_data.data, compute_data.container.value());
356 return std::make_tuple(double_data, info);
358 std::vector<std::span<double>> double_data = extract_numeric_data(compute_data.data, compute_data.needs_processig());
359 return std::make_tuple(double_data, info);
364 std::vector<std::span<double>> double_data = extract_numeric_data(compute_data);
365 auto [dimensions, modality] = infer_structure(compute_data);
366 info.dimensions = dimensions;
367 info.modality = modality;
369 return std::make_tuple(double_data, info);
399 template <OperationReadyData T>
405 info.
original_type = std::type_index(
typeid(std::decay_t<
decltype(compute_data.data)>));
406 info.dimensions = compute_data.dimensions;
407 info.modality = compute_data.modality;
410 if (!compute_data.has_container()) {
411 error<std::runtime_error>(
412 Journal::Component::Yantra,
413 Journal::Context::ContainerProcessing,
414 std::source_location::current(),
415 "Container is required for region-like data extraction but not provided");
418 const auto region_variants = [&]() -> std::vector<Kakshya::DataVariant> {
419 if constexpr (std::is_same_v<std::decay_t<
decltype(compute_data.data)>,
Kakshya::Region>) {
420 return compute_data.container.value()->get_region_data(compute_data.data);
421 }
else if constexpr (std::is_same_v<std::decay_t<
decltype(compute_data.data)>,
Kakshya::RegionGroup>) {
422 return compute_data.container.value()->get_region_group_data(compute_data.data);
424 return compute_data.container.value()->get_segments_data(compute_data.data);
427 return { extract_native_data(region_variants), info };
429 auto spans = extract_native_data(compute_data.data);
430 return { std::move(spans), info };
435 auto spans = extract_native_data(compute_data);
436 auto [dimensions, modality] = infer_structure(compute_data);
437 info.dimensions = dimensions;
438 info.modality = modality;
439 return { std::move(spans), info };
450 template <ComputeData T>
455 if constexpr (std::is_same_v<T, std::vector<std::vector<double>>>) {
457 }
else if constexpr (std::is_same_v<T, Eigen::MatrixXd>) {
458 return recreate_eigen_matrix(double_data, structure_info);
459 }
else if constexpr (std::is_same_v<T, std::vector<Kakshya::DataVariant>>) {
460 std::vector<Kakshya::DataVariant> variants;
461 variants.reserve(double_data.size());
462 for (
const auto& vec : double_data) {
463 variants.emplace_back(vec);
466 }
else if constexpr (std::is_same_v<T, Kakshya::DataVariant>) {
467 auto data = Kakshya::interleave_channels<double>(double_data);
468 return reconstruct_data_variant_from_double(data, structure_info);
470 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());
482 template <
typename T>
487 using UnderlyingType = std::decay_t<decltype(std::declval<T>().data)>;
490 io_data.dimensions = structure_info.
dimensions;
491 io_data.modality = structure_info.
modality;
493 io_data.data = reconstruct_from_double<UnderlyingType>(double_data, structure_info);
505 template <OperationReadyData T>
508 auto [data_spans, structure_info] = extract_structured_double(
input);
510 if (working_buffer.size() != data_spans.size()) {
511 working_buffer.resize(data_spans.size());
514 std::vector<std::span<double>> working_spans(working_buffer.size());
516 for (
size_t i = 0; i < data_spans.size(); i++) {
517 working_buffer[i].resize(data_spans[i].size());
518 std::ranges::copy(data_spans[i], working_buffer[i].begin());
519 working_spans[i] = std::span<double>(working_buffer[i].data(), working_buffer[i].size());
522 return std::make_tuple(working_spans, structure_info);
531 template <
typename EigenType>
534 std::vector<double> flat_data;
536 if constexpr (EigenType::IsVectorAtCompileTime) {
537 flat_data.resize(eigen_data.size());
538 for (
int i = 0; i < eigen_data.size(); ++i) {
539 flat_data[i] =
static_cast<double>(eigen_data(i));
542 flat_data.resize(eigen_data.size());
544 for (
int i = 0; i < eigen_data.rows(); ++i) {
545 for (
int j = 0; j < eigen_data.cols(); ++j) {
546 flat_data[idx++] =
static_cast<double>(eigen_data(i, j));
560 template <
typename EigenMatrix>
563 static thread_local std::vector<std::vector<double>> columns;
565 columns.resize(matrix.cols());
566 std::vector<std::span<double>> spans;
567 spans.reserve(matrix.cols());
569 for (
int col = 0; col < matrix.cols(); ++col) {
570 columns[col].resize(matrix.rows());
571 for (
int row = 0; row < matrix.rows(); ++row) {
572 columns[col][row] =
static_cast<double>(matrix(row, col));
574 spans.emplace_back(columns[col].data(), columns[col].size());
598 template <
typename EigenMatrix>
601 std::vector<Kakshya::DataVariant> columns(matrix.cols());
603 for (
int col = 0; col < matrix.cols(); ++col) {
604 auto row_indices = std::views::iota(0, matrix.rows());
605 auto col_data = row_indices
606 | std::views::transform([&](
int row) {
return static_cast<double>(matrix(row, col)); });
607 columns[col] = { std::vector<double>(col_data.begin(), col_data.end()) };
618 template <
typename T>
621 if (columns.empty()) {
625 int rows = columns[0].size();
626 int cols = columns.size();
628 for (
const auto& col : columns) {
629 if (col.size() != rows) {
630 error<std::invalid_argument>(Journal::Component::Yantra, Journal::Context::Runtime, std::source_location::current(),
"All columns must have same size");
634 Eigen::MatrixXd matrix(rows, cols);
635 for (
int col = 0; col < cols; ++col) {
636 for (
int row = 0; row < rows; ++row) {
637 matrix(row, col) =
static_cast<double>(columns[col][row]);
646 template <
typename T>
653 int rows = spans[0].size();
654 int cols = spans.size();
656 for (
const auto& span : spans) {
657 if (span.size() != rows) {
658 error<std::invalid_argument>(Journal::Component::Yantra, Journal::Context::Runtime, std::source_location::current(),
"All spans must have same size");
662 Eigen::MatrixXd matrix(rows, cols);
663 for (
int col = 0; col < cols; ++col) {
664 for (
int row = 0; row < rows; ++row) {
665 matrix(row, col) =
static_cast<double>(spans[col][row]);
678 static Eigen::MatrixXd recreate_eigen_matrix(
679 const std::vector<std::vector<double>>& columns,
689 static Eigen::MatrixXd recreate_eigen_matrix(
690 const std::vector<std::span<const double>>& spans,
696 static Kakshya::DataVariant reconstruct_data_variant_from_double(
const std::vector<double>& double_data,
Core::GlobalInputConfig input
static Eigen::MatrixXd create_eigen_matrix(const std::vector< std::span< const T > > &spans)
Create Eigen matrix from spans.
static DataStructureInfo get_structure_info(T &compute_data)
Populate DataStructureInfo from a Datum without extracting 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 ::value 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 Eigen::MatrixXd create_eigen_matrix(const std::vector< std::vector< T > > &columns)
Infer data structure from ComputeData type.
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< Kakshya::DataVariant > convert_eigen_matrix_to_variant(const EigenMatrix &matrix)
Extract data from Eigen vector to double span.
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::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 void set_complex_conversion_strategy(Kakshya::ComplexConversionStrategy strategy)
Set global complex conversion strategy.
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 std::vector< std::span< double > > extract_numeric_data(const T &compute_data, bool needs_processig=false)
extract numeric data from multi-variant types
static auto setup_operation_buffer(T &input, std::vector< std::vector< double > > &working_buffer)
Setup operation buffer from Datum or ComputeData type.
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 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.
Universal data conversion helper for all Yantra operations.
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.
ComplexConversionStrategy
Strategy for converting complex numbers to real values.
Organizes related signal regions into a categorized collection.
Represents a point or span in N-dimensional space.
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
Metadata about data structure for reconstruction.
Helper to detect if a type is an Datum.