24 std::vector<Kakshya::DataDimension> dims,
76 if constexpr (std::is_same_v<T, Kakshya::DataVariant>) {
77 auto const_span = Kakshya::convert_variant<double>(compute_data);
78 return std::span<double>(
const_cast<double*
>(const_span.data()), const_span.size());
80 if constexpr (std::is_base_of_v<Eigen::MatrixBase<T>, T>) {
97 static std::vector<std::span<double>>
extract_numeric_data(
const T& compute_data,
bool needs_processig =
false)
99 if constexpr (std::is_same_v<T, std::vector<Kakshya::DataVariant>>) {
103 if constexpr (std::is_same_v<T, std::shared_ptr<Kakshya::SignalSourceContainer>>) {
104 if (needs_processig) {
106 compute_data->process_default();
109 std::vector<Kakshya::DataVariant> variant = compute_data->get_processed_data();
112 std::vector<Kakshya::DataVariant> variant = compute_data->get_data();
116 if constexpr (std::is_base_of_v<Eigen::MatrixBase<T>, T>)
119 return std::vector<std::span<double>> {};
129 template <
typename T>
132 const T& compute_data,
133 const std::shared_ptr<Kakshya::SignalSourceContainer>& container)
136 throw std::invalid_argument(
"Null container provided for region extraction");
139 if constexpr (std::is_same_v<T, Kakshya::Region>) {
140 auto data = container->get_region_data(compute_data);
141 return Kakshya::convert_variants<double>(data);
143 }
else if constexpr (std::is_same_v<T, Kakshya::RegionGroup>) {
144 if (compute_data.regions.empty()) {
145 throw std::runtime_error(
"Empty RegionGroup cannot be extracted");
147 auto data = container->get_region_group_data(compute_data);
148 return Kakshya::convert_variants<double>(data);
150 }
else if constexpr (std::is_same_v<T, std::vector<Kakshya::RegionSegment>>) {
151 if (compute_data.empty()) {
152 throw std::runtime_error(
"RegionSegment contains no extractable data");
154 auto data = container->get_segments_data(compute_data);
155 return Kakshya::convert_variants<double>(data);
165 template <
typename T>
169 if constexpr (std::is_same_v<T, std::vector<Kakshya::DataVariant>>) {
173 if constexpr (std::is_same_v<T, std::shared_ptr<Kakshya::SignalSourceContainer>>) {
175 return compute_data->get_processed_data();
177 return compute_data->get_data();
180 if constexpr (std::is_base_of_v<Eigen::MatrixBase<T>, T>) {
192 template <
typename T>
195 const T& compute_data,
196 const std::shared_ptr<Kakshya::SignalSourceContainer>& container)
198 if constexpr (std::is_same_v<T, Kakshya::Region>) {
199 return container->get_region_data(compute_data);
200 }
else if constexpr (std::is_same_v<T, Kakshya::RegionGroup>) {
201 return container->get_region_group_data(compute_data);
202 }
else if constexpr (std::is_same_v<T, std::vector<Kakshya::RegionSegment>>) {
203 return container->get_segments_data(compute_data);
214 template <OperationReadyData T>
220 info.
original_type = std::type_index(
typeid(std::decay_t<
decltype(compute_data.data)>));
221 info.dimensions = compute_data.dimensions;
222 info.modality = compute_data.modality;
225 if (!compute_data.has_container()) {
226 throw std::runtime_error(
"Container is required for region-like data extraction but not provided");
228 std::vector<std::span<double>> double_data =
extract_numeric_data(compute_data.data, compute_data.container.value());
229 return std::make_tuple(double_data, info);
231 std::vector<std::span<double>> double_data =
extract_numeric_data(compute_data.data, compute_data.needs_processig());
232 return std::make_tuple(double_data, info);
239 info.dimensions = dimensions;
240 info.modality = modality;
242 return std::make_tuple(double_data, info);
253 template <ComputeData T>
258 if constexpr (std::is_same_v<T, std::vector<std::vector<double>>>) {
260 }
else if constexpr (std::is_same_v<T, Eigen::MatrixXd>) {
262 }
else if constexpr (std::is_same_v<T, std::vector<Kakshya::DataVariant>>) {
263 std::vector<Kakshya::DataVariant> variants;
264 variants.reserve(double_data.size());
265 for (
const auto& vec : double_data) {
266 variants.emplace_back(vec);
269 }
else if constexpr (std::is_same_v<T, Kakshya::DataVariant>) {
270 auto data = Kakshya::interleave_channels<double>(double_data);
273 throw std::runtime_error(
"Reconstruction not implemented for target type");
284 template <
typename T>
289 using UnderlyingType = std::decay_t<decltype(std::declval<T>().data)>;
292 io_data.dimensions = structure_info.
dimensions;
293 io_data.modality = structure_info.
modality;
295 io_data.data = reconstruct_from_double<UnderlyingType>(double_data, structure_info);
307 template <OperationReadyData T>
312 if (working_buffer.size() != data_spans.size()) {
313 working_buffer.resize(data_spans.size());
316 std::vector<std::span<double>> working_spans(working_buffer.size());
318 for (
size_t i = 0; i < data_spans.size(); i++) {
319 working_buffer[i].resize(data_spans[i].size());
320 std::ranges::copy(data_spans[i], working_buffer[i].begin());
321 working_spans[i] = std::span<double>(working_buffer[i].data(), working_buffer[i].size());
324 return std::make_tuple(working_spans, structure_info);
333 template <
typename EigenType>
336 std::vector<double> flat_data;
338 if constexpr (EigenType::IsVectorAtCompileTime) {
339 flat_data.resize(eigen_data.size());
340 for (
int i = 0; i < eigen_data.size(); ++i) {
341 flat_data[i] =
static_cast<double>(eigen_data(i));
344 flat_data.resize(eigen_data.size());
346 for (
int i = 0; i < eigen_data.rows(); ++i) {
347 for (
int j = 0; j < eigen_data.cols(); ++j) {
348 flat_data[idx++] =
static_cast<double>(eigen_data(i, j));
362 template <
typename EigenMatrix>
365 static thread_local std::vector<std::vector<double>> columns;
367 columns.resize(matrix.cols());
368 std::vector<std::span<double>> spans;
369 spans.reserve(matrix.cols());
371 for (
int col = 0; col < matrix.cols(); ++col) {
372 columns[col].resize(matrix.rows());
373 for (
int row = 0; row < matrix.rows(); ++row) {
374 columns[col][row] =
static_cast<double>(matrix(row, col));
376 spans.emplace_back(columns[col].data(), columns[col].size());
400 template <
typename EigenMatrix>
403 std::vector<Kakshya::DataVariant> columns(matrix.cols());
405 for (
int col = 0; col < matrix.cols(); ++col) {
406 auto row_indices = std::views::iota(0, matrix.rows());
407 auto col_data = row_indices
408 | std::views::transform([&](
int row) {
return static_cast<double>(matrix(row, col)); });
409 columns[col] = { std::vector<double>(col_data.begin(), col_data.end()) };
420 template <
typename T>
423 if (columns.empty()) {
427 int rows = columns[0].size();
428 int cols = columns.size();
430 for (
const auto& col : columns) {
431 if (col.size() != rows) {
432 throw std::invalid_argument(
"All columns must have same size");
436 Eigen::MatrixXd matrix(rows, cols);
437 for (
int col = 0; col < cols; ++col) {
438 for (
int row = 0; row < rows; ++row) {
439 matrix(row, col) =
static_cast<double>(columns[col][row]);
448 template <
typename T>
455 int rows = spans[0].size();
456 int cols = spans.size();
458 for (
const auto& span : spans) {
459 if (span.size() != rows) {
460 throw std::invalid_argument(
"All spans must have same size");
464 Eigen::MatrixXd matrix(rows, cols);
465 for (
int col = 0; col < cols; ++col) {
466 for (
int row = 0; row < rows; ++row) {
467 matrix(row, col) =
static_cast<double>(spans[col][row]);
481 const std::vector<std::vector<double>>& columns,
492 const std::vector<std::span<const double>>& spans,
static Utils::ComplexConversionStrategy s_complex_strategy
static Eigen::MatrixXd create_eigen_matrix(const std::vector< std::span< const T > > &spans)
Create Eigen matrix from spans.
static Kakshya::DataVariant reconstruct_data_variant_from_double(const std::vector< double > &double_data, const DataStructureInfo &structure_info)
Reconstruct DataVariant from double data and structure info.
static Utils::ComplexConversionStrategy get_complex_conversion_strategy()
Get current complex conversion strategy.
static std::vector< std::span< double > > extract_from_eigen_matrix(const EigenMatrix &matrix)
Infer data structure from ComputeData type.
static ::value T reconstruct_from_double(const std::vector< std::vector< double > > &double_data, const DataStructureInfo &structure_info)
Reconstruct IO 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::vector< Kakshya::DataVariant > convert_eigen_matrix_to_variant(const EigenMatrix &matrix)
Extract data from Eigen vector to double span.
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 std::tuple< std::vector< std::span< double > >, DataStructureInfo > extract_structured_double(T &compute_data)
Extract structured double data from IO container or direct ComputeData with automatic container handl...
static void set_complex_conversion_strategy(Utils::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 auto setup_operation_buffer(T &input, std::vector< std::vector< double > > &working_buffer)
Setup operation buffer from IO or ComputeData type.
static Eigen::MatrixXd recreate_eigen_matrix(const std::vector< std::vector< double > > &columns, const DataStructureInfo &structure_info)
Infer data structure from 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 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.
Concept for Eigen matrix types with double scalar.
A SingleVariant is either a single DataVariant, an Eigen vector type, or any type constructible from ...
@ PROCESSED
Container has completed processing and results are available.
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.
std::span< double > convert_variant_to_double(DataVariant &data, Utils::ComplexConversionStrategy strategy=Utils::ComplexConversionStrategy::MAGNITUDE)
Convert variant to double span.
ComplexConversionStrategy
Strategy for converting complex numbers to real values.
@ MAGNITUDE
|z| = sqrt(real² + imag²)
static std::pair< std::vector< Kakshya::DataDimension >, Kakshya::DataModality > infer_structure(const T &data, const std::shared_ptr< Kakshya::SignalSourceContainer > &container=nullptr)
Infer dimensions and modality from any ComputeData type.
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 IO.