18 m_chain = std::make_shared<DataProcessingChain>();
33 return *std::static_pointer_cast<PlotProcessor>(
m_processor);
43 m_data.emplace_back(std::vector<double>(
count, 0.0));
52 MF_INFO(C, X,
"PlotContainer: added series '{}' at index {} ({} samples, role={}, modality={})",
54 static_cast<int>(role),
62 if (index >=
m_data.size()) {
63 MF_ERROR(C, X,
"PlotContainer::write_series: index {} out of range", index);
67 auto* vec = std::get_if<std::vector<double>>(&
m_data[index]);
69 MF_ERROR(C, X,
"PlotContainer::write_series: series {} has unexpected variant type", index);
73 const uint64_t n = std::min<uint64_t>(samples.size(), vec->size());
75 std::copy_n(samples.begin(), n, vec->begin());
80 if (index >=
m_data.size()) {
81 MF_ERROR(C, X,
"PlotContainer::write_sample: series index {} out of range", index);
85 auto* vec = std::get_if<std::vector<double>>(&
m_data[index]);
86 if (!vec || sample_index >= vec->size()) {
87 MF_ERROR(C, X,
"PlotContainer::write_sample: sample index {} out of range in series {}", sample_index, index);
92 (*vec)[sample_index] =
value;
97 if (index >=
m_data.size()) {
98 MF_ERROR(C, X,
"PlotContainer::resize_series: index {} out of range", index);
102 auto* vec = std::get_if<std::vector<double>>(&
m_data[index]);
106 vec->resize(
count, 0.0);
110 pv->resize(
count, 0.0);
122 static const std::string empty;
130 if (index >=
m_data.size())
132 const auto* vec = std::get_if<std::vector<double>>(&
m_data[index]);
133 return vec ?
static_cast<uint64_t
>(vec->size()) : 0;
150 p.bind_node(series_index, std::move(node));
157 std::shared_ptr<Buffers::AudioBuffer> buffer)
160 p.bind_audio_buffer(series_index, std::move(buffer));
167 std::shared_ptr<Nodes::Network::NodeNetwork>
network)
170 p.bind_network(series_index, std::move(
network));
177 std::function<
void(std::vector<double>&)> fn)
180 p.bind_callable(series_index, std::move(fn));
189 p.set_raw(series_index, std::move(data));
198 std::static_pointer_cast<PlotProcessor>(
m_processor)->unbind(series_index);
213 for (
const auto& v :
m_data) {
214 const auto* vec = std::get_if<std::vector<double>>(&v);
216 total += vec->size();
223 return static_cast<uint64_t
>(
m_data.size());
232 if (series_idx >=
m_data.size())
235 std::optional<std::vector<DataVariant>> result;
237 const auto* src = std::get_if<std::vector<double>>(&
m_data[series_idx]);
238 if (!src || src->empty())
242 ? std::min(region.
end_coordinates[1],
static_cast<uint64_t
>(src->size() - 1))
243 :
static_cast<uint64_t
>(src->size() - 1);
246 std::vector<double> slice(src->begin() +
static_cast<ptrdiff_t
>(s),
247 src->begin() +
static_cast<ptrdiff_t
>(e + 1));
251 return result.value_or(std::vector<DataVariant> {});
260 if (series_idx >=
m_data.size())
263 const auto* src = std::get_if<std::vector<double>>(&data[0]);
264 if (!src || src->empty())
268 auto* dst = std::get_if<std::vector<double>>(&
m_data[series_idx]);
274 ? std::min(region.
end_coordinates[1],
static_cast<uint64_t
>(dst->size() - 1))
275 :
static_cast<uint64_t
>(dst->size() - 1);
279 const uint64_t n = std::min<uint64_t>(src->size(), e - s + 1);
280 std::copy_n(src->begin(), n, dst->begin() +
static_cast<ptrdiff_t
>(s));
285 std::vector<DataVariant> result;
286 for (
const auto& r : group.
regions) {
288 for (
auto& v : slice)
289 result.push_back(std::move(v));
301 if (coordinates.size() < 2)
303 return coordinates[1];
308 return { 0, linear };
323 const auto* vec = std::get_if<std::vector<double>>(&
m_data[0]);
324 return (vec && !vec->empty()) ? vec->data() :
nullptr;
334 if (index >=
m_data.size()) {
336 static std::vector<DataDimension> empty_dims;
344 std::vector<DataAccess> result;
345 result.reserve(
m_data.size());
346 for (
size_t i = 0; i <
m_data.size(); ++i) {
347 result.emplace_back(
m_data[i],
364 std::optional<RegionGroup> result;
369 return result.value_or(empty);
374 std::optional<std::unordered_map<std::string, RegionGroup>> result;
378 return result.value_or(std::unordered_map<std::string, RegionGroup> {});
409 std::function<
void(
const std::shared_ptr<SignalSourceContainer>&,
ProcessingState)> cb)
463 m_chain = std::make_shared<DataProcessingChain>();
469 if (frame_index >= m_data.size())
472 std::span<const double> result;
473 seqlock_read_void(m_series_locks[frame_index], 8, [&] {
474 const auto* vec = std::get_if<std::vector<double>>(&m_data[frame_index]);
475 if (!vec || vec->empty())
477 result = { vec->data(), vec->size() };
485 for (uint64_t i = start_frame; i < start_frame + num_frames && i <
m_data.size(); ++i) {
487 const auto* vec = std::get_if<std::vector<double>>(&
m_data[i]);
490 for (
double v : *vec) {
501 return { get_frame_typed(frame_index) };
507 uint64_t start_frame,
509 const std::type_info& type)
const
511 if (type !=
typeid(
double)) {
512 error<std::runtime_error>(
515 std::source_location::current(),
516 "PlotContainer only supports double");
523 const std::vector<uint64_t>& coords,
525 const std::type_info& type)
const
527 if (type !=
typeid(
double) || coords.size() < 2 || coords[0] >=
m_data.size())
530 const auto idx =
static_cast<size_t>(coords[0]);
533 const auto* vec = std::get_if<std::vector<double>>(&
m_data[idx]);
534 if (!vec || coords[1] >= vec->size())
536 *
static_cast<double*
>(out) = (*vec)[coords[1]];
541 const std::vector<uint64_t>& coords,
543 const std::type_info& type)
545 if (type !=
typeid(
double) || coords.size() < 2 || coords[0] >=
m_data.size())
548 const auto idx =
static_cast<size_t>(coords[0]);
551 auto* vec = std::get_if<std::vector<double>>(&
m_data[idx]);
552 if (!vec || coords[1] >= vec->size())
555 (*vec)[coords[1]] = *
static_cast<const double*
>(in);
#define MF_INFO(comp, ctx,...)
#define MF_ERROR(comp, ctx,...)
Core::GlobalNetworkConfig network
std::shared_ptr< Core::VKImage > output
Type-erased accessor for NDData with semantic view construction.
void bind(uint32_t series_index, std::shared_ptr< Nodes::Node > node)
Bind a series to a Node.
std::unordered_map< std::string, RegionGroup > get_all_region_groups() const override
Get all region groups in the container.
PlotProcessor & ensure_processor()
Return the PlotProcessor, creating and attaching it if absent.
void get_frames_impl(void *output, size_t count, uint64_t start_frame, uint64_t num_frames, const std::type_info &type) const override
Implementation-specific method to retrieve multiple frames.
std::vector< DataAccess > all_channel_data() override
Get all channel data as accessors.
void unbind(uint32_t series_index)
Remove the source binding for a series.
std::shared_ptr< DataProcessingChain > m_chain
std::vector< DataVariant > m_data
auto get_frame_typed(uint64_t frame_index) const -> std::span< const double >
void mark_ready_for_processing(bool ready) override
Mark the container as ready or not ready for processing.
void remove_region_group(const std::string &name) override
Remove a region group by name.
auto get_frame_span_impl(uint64_t frame_index) const -> DataSpanVariant override
Implementation-specific method to retrieve a frame span.
PlotContainer()
Construct an empty container.
std::function< void(const std::shared_ptr< SignalSourceContainer > &, ProcessingState)> m_state_cb
void get_frames_typed(std::span< double > output, uint64_t start_frame, uint64_t num_frames) const
std::atomic< ProcessingState > m_processing_state
RegionGroup get_region_group(const std::string &name) const override
Get a region group by name.
void write_series(uint32_t index, std::span< const double > samples)
Write the full sample buffer for a series.
Memory::Seqlock m_cb_lock
uint32_t add_series(std::string name, uint64_t count, DataDimension::Role role=DataDimension::Role::CUSTOM, DataModality modality=DataModality::TENSOR_ND)
Add a named series with a given capacity, zero-initialised.
std::unordered_map< std::string, RegionGroup > m_region_groups
std::vector< DataDimension > get_dimensions() const override
Get the dimensions describing the structure of the data.
bool has_data() const override
Check if the container currently holds any data.
void write_sample(uint32_t index, uint64_t sample_index, double value)
Write a single sample within a series.
std::vector< DataVariant > get_region_data(const Region ®ion) const override
Extract a sample range from a single series.
std::vector< DataVariant > m_processed_data
ContainerDataStructure m_structure
std::vector< DataVariant > get_region_group_data(const RegionGroup &group) const override
Get data for multiple regions efficiently.
const void * get_raw_data() const override
Get a raw pointer to the underlying data storage.
uint64_t coordinates_to_linear_index(const std::vector< uint64_t > &coordinates) const override
Convert coordinates to linear index based on current memory layout.
const std::string & series_name(uint32_t index) const
Return the name of a series.
void resize_series(uint32_t index, uint64_t count)
Resize a series.
uint64_t series_size(uint32_t index) const
Return the sample count of a series.
void process_default() override
Process the container's data using the default processor.
uint32_t series_count() const
Return the number of series.
std::shared_ptr< DataProcessingChain > get_processing_chain() override
Get the current processing chain for this container.
void create_default_processor() override
Create and configure a default processor for this container.
void set_value_impl(const std::vector< uint64_t > &coords, const void *in, const std::type_info &type) override
Type-erased single-element write.
DataAccess channel_data(size_t index) override
Get channel data with semantic interpretation.
void set_default_processor(const std::shared_ptr< DataProcessor > &processor) override
Set the default data processor for this container.
std::shared_ptr< DataProcessor > get_default_processor() const override
Get the current default data processor.
void get_value_impl(const std::vector< uint64_t > &coords, void *out, const std::type_info &type) const override
Type-erased single-element read.
Memory::SeqlockArray m_series_locks
void clear() override
Clear all data in the container.
Memory::Seqlock m_region_lock
uint64_t get_total_elements() const override
Get the total number of elements in the container.
void update_processing_state(ProcessingState state) override
Update the processing state of the container.
std::vector< uint64_t > linear_index_to_coordinates(uint64_t linear_index) const override
Convert linear index to coordinates based on current memory layout.
std::vector< DataVariant > get_segments_data(const std::vector< RegionSegment > &segments) const override
Get data for multiple region segments efficiently.
void add_region_group(const RegionGroup &group) override
Add a named group of regions to the container.
void unregister_state_change_callback() override
Unregister the state change callback, if any.
std::shared_ptr< DataProcessor > m_processor
void set_raw(uint32_t series_index, std::vector< double > data)
Push raw sample data into a series.
bool is_ready_for_processing() const override
Check if the container is ready for processing.
void register_state_change_callback(std::function< void(const std::shared_ptr< SignalSourceContainer > &, ProcessingState)> cb) override
Register a callback to be invoked on processing state changes.
ProcessingState get_processing_state() const override
Get the current processing state of the container.
DataDimension::Role series_role(uint32_t index) const
Return the role of a series.
void set_region_data(const Region ®ion, const std::vector< DataVariant > &data) override
Write a sample range back into a series.
uint64_t get_num_frames() const override
Get the number of frames in the primary (temporal) dimension.
DataProcessor that acquires per-series data from heterogeneous sources and writes into PlotContainer:...
void resize(size_t n)
Replace the slot array with n default-constructed Seqlock instances.
RAII guard that brackets a Seqlock write region.
@ ContainerProcessing
Container operations (Kakshya - file/stream/region processing)
@ Runtime
General runtime operations (default fallback)
@ Kakshya
Containers[Signalsource, Stream, File], Regions, DataProcessors.
ProcessingState
Represents the current processing lifecycle state of a container.
@ READY
Container has data loaded and is ready for processing.
@ IDLE
Container is inactive with no data or not ready for processing.
@ PROCESSING
Container is actively being processed.
@ PROCESSED
Container has completed processing and results are available.
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.
@ TENSOR_ND
N-dimensional tensor.
@ ROW_MAJOR
C/C++ style (last dimension varies fastest)
@ PLANAR
Separate DataVariant per logical unit (LLL...RRR for stereo)
std::string_view modality_to_string(DataModality modality)
Convert DataModality enum to string representation.
std::vector< DataDimension > dimensions
Container structure for consistent dimension ordering.
Role
Semantic role of the dimension.
@ CUSTOM
User-defined or application-specific.
std::vector< Region > regions
Collection of regions belonging to this group.
std::string name
Descriptive name of the group.
Organizes related signal regions into a categorized collection.
std::vector< uint64_t > end_coordinates
Ending frame index (inclusive)
std::vector< uint64_t > start_coordinates
Starting frame index (inclusive)
Represents a point or span in N-dimensional space.