MayaFlux 0.3.0
Digital-First Multimedia Processing Framework
Loading...
Searching...
No Matches
RegionUtils.hpp
Go to the documentation of this file.
1#pragma once
2
3#include "CoordUtils.hpp"
4
7
9
10namespace MayaFlux::Kakshya {
11
12/** @brief Remove the channel dimension from a Region.
13 * @param region The original Region.
14 * @param dimensions Dimension descriptors to identify the channel dimension.
15 * @return New Region without the channel dimension.
16 *
17 * This function identifies the channel dimension based on the provided dimension descriptors
18 * and removes it from the region's start and end coordinates.
19 *
20 * This is useful for operations that need to ignore the channel dimension, such as spatial-only processing
21 * or planar data handling.
22 */
23Region remove_channel_dimension(const Region& region, const std::vector<DataDimension>& dimensions);
24
25/**
26@brief Get all non-channel dimensions from a list of dimensions.
27 * @param dimensions Vector of DataDimension descriptors.
28 * @return Vector of DataDimensions excluding the channel dimension.
29 *
30 * This function filters out the dimension marked as 'channel' from the provided list of dimensions.
31 * It is useful for operations that need to focus on spatial or temporal dimensions only.
32 */
33std::vector<DataDimension> get_non_channel_dimensions(const std::vector<DataDimension>& dimensions);
34
35/** @brief Flatten a vector of channel data into a single vector.
36 * @tparam T Data type.
37 * @param channel_data Vector of vectors, each representing a channel's data.
38 * @return Single flattened vector containing all channel data in sequence.
39 *
40 * This function concatenates the data from multiple channels into a single continuous vector.
41 * It is useful for operations that require planar data to be processed as a single array.
42 */
43template <typename T>
44std::vector<T> flatten_channels(const std::vector<std::vector<T>>& channel_data)
45{
46 std::vector<T> result;
47 size_t total_size = 0;
48 for (const auto& channel : channel_data) {
49 total_size += channel.size();
50 }
51 result.reserve(total_size);
52
53 for (const auto& channel : channel_data) {
54 result.insert(result.end(), channel.begin(), channel.end());
55 }
56 return result;
57}
58
59/**
60 * @brief Extract a region of data from a flat data span using a Region and dimension info.
61 * @tparam T Data type.
62 * @param source_data Source data span.
63 * @param region Region to extract.
64 * @param dimensions Dimension descriptors.
65 * @return Vector containing the extracted region data.
66 * @throws std::out_of_range if region is out of bounds.
67 */
68template <typename T>
69std::vector<T> extract_region_data(const std::span<const T>& source_data, const Region& region, const std::vector<DataDimension>& dimensions)
70{
71 for (size_t i = 0; i < region.start_coordinates.size(); ++i) {
72 if (region.end_coordinates[i] > 0 && (region.end_coordinates[i] >= dimensions[i].size)) {
73 error<std::out_of_range>(
75 std::source_location::current(),
76 "Requested region is out of bounds for dimension {}",
77 std::to_string(i));
78 }
79 }
80
81 uint64_t region_size = region.get_volume();
82 std::vector<T> result;
83 result.reserve(region_size);
84
85 std::vector<uint64_t> current = region.start_coordinates;
86 while (true) {
87 uint64_t linear_index = coordinates_to_linear(current, dimensions);
88 result.push_back(source_data[linear_index]);
89
90 bool done = true;
91 for (int dim = (int)current.size() - 1; dim >= 0; --dim) {
92 if (current[dim] < region.end_coordinates[dim]) {
93 current[dim]++;
94 done = false;
95 break;
96 }
97 current[dim] = region.start_coordinates[dim];
98 }
99 if (done)
100 break;
101 }
102 return result;
103}
104
105/**
106 * @brief Extract region data from planar storage (separate per channel/variant)
107 * @tparam T Data type
108 * @param source_variants Vector of data spans (one per channel/variant)
109 * @param region Region to extract
110 * @param dimensions Dimension descriptors
111 * @param flatten If true, return single flattened vector; if false, return per-channel vectors
112 * @return Vector of vectors (per-channel) or single flattened vector
113 */
114template <typename T>
115std::vector<std::vector<T>> extract_region_data(
116 const std::vector<std::span<const T>>& source_data,
117 const Region& region,
118 const std::vector<DataDimension>& dimensions,
119 bool flatten = false)
120{
121 std::vector<std::vector<T>> results;
122
123 for (size_t idx = 0; idx < source_data.size(); ++idx) {
124
125 Region channel_region = remove_channel_dimension(region, dimensions);
126
127 auto channel_data = extract_region_data(
128 source_data[idx],
129 channel_region,
130 get_non_channel_dimensions(dimensions));
131
132 results.push_back(std::move(channel_data));
133 }
134
135 if (flatten) {
136 return { flatten_channels(results) };
137 }
138
139 return results;
140}
141
142/**
143 * @brief Extract data for multiple regions from multi-channel source data.
144 * @tparam T Data type.
145 * @param source_spans Vector of source data spans (one per channel).
146 * @param group Group of regions to extract.
147 * @param dimensions Dimension descriptors.
148 * @param organization Storage organization strategy.
149 * @return Vector of vectors, each containing extracted data for one region.
150 */
151template <typename T>
152std::vector<std::vector<T>> extract_group_data(
153 const std::vector<std::span<const T>>& source_spans,
154 const RegionGroup& group,
155 const std::vector<DataDimension>& dimensions,
156 OrganizationStrategy organization)
157{
158 std::vector<std::vector<T>> result;
159 result.reserve(group.regions.size());
160
161 for (const auto& region : group.regions) {
162 auto region_data = extract_region_data<T>(source_spans, region, dimensions, organization);
163
164 if (organization == OrganizationStrategy::INTERLEAVED) {
165 if (result.empty())
166 result.resize(1);
167
168 for (size_t i = 0; i < region_data[0].size(); i++) {
169 result[0].push_back(region_data[0][i]);
170 }
171 } else {
172 if (result.empty())
173 result.resize(region_data.size());
174
175 auto channel_pairs = std::views::zip(result, region_data);
176 auto total_sizes = channel_pairs | std::views::transform([](auto&& pair) {
177 return std::get<0>(pair).size() + std::get<1>(pair).size();
178 });
179
180 size_t i = 0;
181 for (auto size : total_sizes) {
182 result[i].reserve(size);
183 std::ranges::copy(region_data[i],
184 std::back_inserter(result[i]));
185 ++i;
186 }
187 }
188 }
189
190 return result;
191}
192
193/**
194 * @brief Extract data for multiple segments from multi-channel source data.
195 * @tparam T Data type.
196 * @param segments Vector of region segments to extract.
197 * @param source_spans Vector of source data spans (one per channel).
198 * @param dimensions Dimension descriptors.
199 * @param organization Storage organization strategy.
200 * @return Vector of vectors, each containing extracted data for one segment.
201 */
202template <typename T>
203std::vector<std::vector<T>> extract_segments_data(
204 const std::vector<RegionSegment>& segments,
205 const std::vector<std::span<const T>>& source_spans,
206 const std::vector<DataDimension>& dimensions,
207 OrganizationStrategy organization)
208{
209 if (source_spans.size() != 1) {
210 error<std::invalid_argument>(
212 std::source_location::current(),
213 "Source spans cannot be empty");
214 }
215
216 std::vector<std::vector<T>> result;
217
218 for (const auto& segment : segments) {
219 if (segment.is_cached && !segment.cache.data.empty()) {
220 for (const auto& variant : segment.cache.data) {
221 std::vector<T> converted;
222 auto span = extract_from_variant<T>(variant, converted);
223 std::vector<T> cached_data(span.begin(), span.end());
224
225 if (organization == OrganizationStrategy::INTERLEAVED) {
226 if (result.empty())
227 result.resize(1);
228 std::ranges::copy(cached_data, std::back_inserter(result[0]));
229 } else {
230 if (result.size() <= result.size())
231 result.resize(result.size() + 1);
232 result.back() = std::move(cached_data);
233 }
234 }
235 } else {
236 auto region_data = extract_region_data<T>(source_spans, segment.source_region, dimensions, organization);
237
238 if (organization == OrganizationStrategy::INTERLEAVED) {
239 if (result.empty())
240 result.resize(1);
241 std::ranges::copy(region_data[0], std::back_inserter(result[0]));
242 } else {
243 if (result.empty())
244 result.resize(region_data.size());
245 for (size_t i = 0; i < region_data.size(); ++i) {
246 std::ranges::copy(region_data[i], std::back_inserter(result[i]));
247 }
248 }
249 }
250 }
251
252 return result;
253}
254
255/**
256 * @brief Extract a region of data from a vector using a Region and dimension info.
257 * @tparam T Data type.
258 * @param data Source data vector.
259 * @param region Region to extract.
260 * @param dimensions Dimension descriptors.
261 * @return Vector containing the extracted region data.
262 */
263template <typename T>
264std::vector<T> extract_region(
265 const std::vector<T>& data,
266 const Region& region,
267 const std::vector<DataDimension>& dimensions)
268{
269 std::span<const T> data_span(data.data(), data.size());
270 return extract_region_data(data_span, region, dimensions);
271}
272
273/**
274 * @brief Extract a region of data from vector of vectors (planar data).
275 * @tparam T Data type.
276 * @param source_data Vector of vectors containing source data (one per channel).
277 * @param region Region to extract.
278 * @param dimensions Dimension descriptors.
279 * @return Vector of vectors (channels) containing extracted data.
280 */
281template <typename T>
282std::vector<std::vector<T>> extract_region(
283 const std::vector<std::vector<T>>& source_data,
284 const Region& region,
285 const std::vector<DataDimension>& dimensions)
286{
287 std::vector<std::span<const T>> source_spans;
288 source_spans.reserve(source_data.size());
289
290 for (const auto& channel : source_data) {
291 source_spans.emplace_back(channel.data(), channel.size());
292 }
293
294 return extract_region_data(source_spans, region, dimensions);
295}
296
297/**
298 * @brief Extract a region of data with organization strategy.
299 * @tparam T Data type.
300 * @param source_spans Vector of source data spans (one per channel).
301 * @param region Region to extract.
302 * @param dimensions Dimension descriptors.
303 * @param organization Storage organization strategy.
304 * @return Vector of vectors (channels) containing extracted data.
305 */
306template <typename T>
308 const std::vector<std::span<const T>>& source_spans,
309 const Region& region,
310 const std::vector<DataDimension>& dimensions,
311 OrganizationStrategy organization)
312{
313 if (organization == OrganizationStrategy::INTERLEAVED) {
314 return std::vector<std::vector<T>> {
315 extract_region_data(source_spans[0], region, dimensions)
316 };
317 }
318
319 return extract_region_data(source_spans, region, dimensions);
320}
321
322/**
323 * @brief Write or update a region of data in a flat data span (interleaved).
324 * @tparam T Data type.
325 * @param dest_data Destination data span (to be updated).
326 * @param source_data Source data span (to write from).
327 * @param region Region to update.
328 * @param dimensions Dimension descriptors.
329 */
330template <typename T>
332 std::span<T> dest_data,
333 std::span<const T> source_data,
334 const Region& region,
335 const std::vector<DataDimension>& dimensions)
336{
337 std::vector<uint64_t> current = region.start_coordinates;
338 size_t source_index = 0;
339 while (source_index < source_data.size()) {
340 uint64_t linear_index = coordinates_to_linear(current, dimensions);
341 dest_data[linear_index] = source_data[source_index++];
342 bool done = true;
343 /* for (size_t dim = 0; dim < current.size(); ++dim) {
344 if (current[dim] < region.end_coordinates[dim]) {
345 current[dim]++;
346 done = false;
347 break;
348 }
349 current[dim] = region.start_coordinates[dim];
350 } */
351 for (int dim = static_cast<int>(current.size()) - 1; dim >= 0; --dim) {
352 if (current[dim] < region.end_coordinates[dim]) {
353 current[dim]++;
354 done = false;
355 break;
356 }
357 current[dim] = region.start_coordinates[dim];
358 }
359
360 if (done)
361 break;
362 }
363}
364
365/**
366 * @brief Write or update a region of data in planar storage.
367 * @tparam T Data type.
368 * @param dest_spans Vector of destination data spans (one per channel).
369 * @param source_data Vector of source data spans (one per channel).
370 * @param region Region to update (includes channel dimension).
371 * @param dimensions Dimension descriptors (includes channel dimension).
372 */
373template <typename T>
375 std::vector<std::span<T>>& dest_spans,
376 const std::vector<std::span<const T>>& source_data,
377 const Region& region,
378 const std::vector<DataDimension>& dimensions)
379{
380 size_t channel_dim_idx = 0;
381 for (size_t i = 0; i < dimensions.size(); ++i) {
382 if (dimensions[i].role == DataDimension::Role::CHANNEL) {
383 channel_dim_idx = i;
384 break;
385 }
386 }
387
388 size_t start_channel = region.start_coordinates[channel_dim_idx];
389 size_t end_channel = region.end_coordinates[channel_dim_idx];
390
391 for (size_t ch = start_channel; ch <= end_channel && ch < dest_spans.size(); ++ch) {
392 size_t source_channel_idx = ch - start_channel;
393 if (source_channel_idx >= source_data.size())
394 continue;
395
396 Region channel_region = remove_channel_dimension(region, dimensions);
397 auto non_channel_dims = get_non_channel_dimensions(dimensions);
398
400 dest_spans[ch],
401 source_data[source_channel_idx],
402 channel_region,
403 non_channel_dims);
404 }
405}
406
407/**
408 * @brief Write or update a region of data with organization strategy.
409 * @tparam T Data type.
410 * @param dest_spans Vector of destination data spans (one per channel).
411 * @param source_data Vector of source data spans (one per channel).
412 * @param region Region to update.
413 * @param dimensions Dimension descriptors.
414 * @param organization Storage organization strategy.
415 */
416template <typename T>
418 std::vector<std::span<T>>& dest_spans,
419 const std::vector<std::span<const T>>& source_data,
420 const Region& region,
421 const std::vector<DataDimension>& dimensions,
422 OrganizationStrategy organization)
423{
424 if (organization == OrganizationStrategy::INTERLEAVED) {
425 set_or_update_region_data(dest_spans[0], source_data[0], region, dimensions);
426 } else {
427 set_or_update_region_data(dest_spans, source_data, region, dimensions);
428 }
429}
430
431/**
432 * @brief Calculate the total number of elements in a region.
433 * @param region Region to query.
434 * @return Product of spans across all dimensions.
435 */
436uint64_t calculate_region_size(const Region& region);
437
438/**
439 * @brief Get an attribute value from a Region by key.
440 * @tparam T Expected type.
441 * @param region Region to query.
442 * @param key Attribute key.
443 * @return Optional value if present and convertible.
444 */
445template <typename T>
446std::optional<T> get_region_attribute(const Region& region, const std::string& key)
447{
448 auto it = region.attributes.find(key);
449 if (it != region.attributes.end()) {
450 try {
451 return safe_any_cast<T>(it->second);
452 } catch (const std::bad_any_cast&) {
453 return std::nullopt;
454 }
455 }
456 return std::nullopt;
457}
458
459/**
460 * @brief Set an attribute value on a Region.
461 * @param region Region to modify.
462 * @param key Attribute key.
463 * @param value Value to set.
464 */
465void set_region_attribute(Region& region, const std::string& key, std::any value);
466
467/**
468 * @brief Find all regions in a RegionGroup with a given label.
469 * @param group RegionGroup to search.
470 * @param label Label to match.
471 * @return Vector of matching Regions.
472 */
473std::vector<Region> find_regions_with_label(const RegionGroup& group, const std::string& label);
474
475/**
476 * @brief Find all regions in a RegionGroup with a specific attribute value.
477 * @param group RegionGroup to search.
478 * @param key Attribute key.
479 * @param value Attribute value to match.
480 * @return Vector of matching Regions.
481 */
482std::vector<Region> find_regions_with_attribute(const RegionGroup& group, const std::string& key, const std::any& value);
483
484/**
485 * @brief Find all regions in a RegionGroup that contain the given coordinates.
486 * @param group RegionGroup to search.
487 * @param coordinates N-dimensional coordinates.
488 * @return Vector of matching Regions.
489 */
490std::vector<Region> find_regions_containing_coordinates(const RegionGroup& group, const std::vector<uint64_t>& coordinates);
491
492/**
493 * @brief Translate a Region by an offset vector.
494 * @param region Region to translate.
495 * @param offset Offset for each dimension (can be negative).
496 * @return New translated Region.
497 */
498Region translate_region(const Region& region, const std::vector<int64_t>& offset);
499
500/**
501 * @brief Scale a Region about its center by the given factors.
502 * @param region Region to scale.
503 * @param factors Scaling factors for each dimension.
504 * @return New scaled Region.
505 */
506Region scale_region(const Region& region, const std::vector<double>& factors);
507
508/**
509 * @brief Get the bounding region that contains all regions in a RegionGroup.
510 * @param group RegionGroup to query.
511 * @return Region representing the bounding box.
512 */
513Region get_bounding_region(const RegionGroup& group);
514
515/**
516 * @brief Sort a vector of Regions by a specific dimension.
517 * @param regions Vector of Regions to sort.
518 * @param dimension Dimension index to sort by.
519 */
520void sort_regions_by_dimension(std::vector<Region>& regions, size_t dimension);
521
522/**
523 * @brief Sort a vector of Regions by a specific attribute (numeric).
524 * @param regions Vector of Regions to sort.
525 * @param attr_name Attribute name to sort by.
526 */
527void sort_regions_by_attribute(std::vector<Region>& regions, const std::string& attr_name);
528
529/**
530 * @brief Add a named reference region to a reference list.
531 * @param refs Reference list (name, Region) pairs.
532 * @param name Name for the reference.
533 * @param region Region to add.
534 */
535void add_reference_region(std::vector<std::pair<std::string, Region>>& refs, const std::string& name, const Region& region);
536
537/**
538 * @brief Remove a named reference region from a reference list.
539 * @param refs Reference list (name, Region) pairs.
540 * @param name Name of the reference to remove.
541 */
542void remove_reference_region(std::vector<std::pair<std::string, Region>>& refs, const std::string& name);
543
544/**
545 * @brief Get a named reference region from a reference list.
546 * @param refs Reference list (name, Region) pairs.
547 * @param name Name of the reference to retrieve.
548 * @return Optional Region if found.
549 */
550std::optional<Region> get_reference_region(const std::vector<std::pair<std::string, Region>>& refs, const std::string& name);
551
552/**
553 * @brief Find all references in a reference list that overlap a given region.
554 * @param refs Reference list (name, Region) pairs.
555 * @param region Region to check for overlap.
556 * @return Vector of (name, Region) pairs that overlap.
557 */
558std::vector<std::pair<std::string, Region>> find_references_in_region(const std::vector<std::pair<std::string, Region>>& refs, const Region& region);
559
560/**
561 * @brief Add a RegionGroup to a group map.
562 * @param groups Map of group name to RegionGroup.
563 * @param group RegionGroup to add.
564 */
565void add_region_group(std::unordered_map<std::string, RegionGroup>& groups, const RegionGroup& group);
566
567/**
568 * @brief Get a RegionGroup by name from a group map.
569 * @param groups Map of group name to RegionGroup.
570 * @param name Name of the group to retrieve.
571 * @return Optional RegionGroup if found.
572 */
573std::optional<RegionGroup> get_region_group(const std::unordered_map<std::string, RegionGroup>& groups, const std::string& name);
574
575/**
576 * @brief Remove a RegionGroup by name from a group map.
577 * @param groups Map of group name to RegionGroup.
578 * @param name Name of the group to remove.
579 */
580void remove_region_group(std::unordered_map<std::string, RegionGroup>& groups, const std::string& name);
581
582/**
583 * @brief Calculate output region bounds from current position and shape.
584 * @param current_pos Current position coordinates.
585 * @param output_shape Desired output shape.
586 * @return Region representing the output bounds.
587 */
588Region calculate_output_region(const std::vector<uint64_t>& current_pos,
589 const std::vector<uint64_t>& output_shape);
590
591/**
592 *@brief Calculate output region for frame-based processing.
593 * @param current_frame Current frame index.
594 * @param frames_to_process Number of frames to process.
595 * @param container Container providing layout information.
596 * @return Region representing the output bounds for the specified frames.
597 */
598Region calculate_output_region(uint64_t current_frame,
599 uint64_t frames_to_process,
600 const std::shared_ptr<SignalSourceContainer>& container);
601
602/**
603 * @brief Check if region access will be contiguous in memory.
604 * @param region Region to check.
605 * @param container Container providing layout information.
606 * @return True if access is contiguous, false otherwise.
607 */
608bool is_region_access_contiguous(const Region& region,
609 const std::shared_ptr<SignalSourceContainer>& container);
610
611/**
612 * @brief Extract all regions from container's region groups.
613 * @param container Container to extract regions from.
614 * @return Vector of structured region information.
615 */
616std::vector<std::unordered_map<std::string, std::any>> extract_all_regions_info(const std::shared_ptr<SignalSourceContainer>& container);
617
618/**
619 * @brief Extract bounds information from region group.
620 * @param group Region group to analyze.
621 * @return Map containing group bounds metadata.
622 */
623std::unordered_map<std::string, std::any> extract_group_bounds_info(const RegionGroup& group);
624
625/**
626 * @brief Extract metadata from region segments.
627 * @param segments Vector of region segments.
628 * @return Vector of metadata maps, one per segment.
629 */
630std::vector<std::unordered_map<std::string, std::any>> extract_segments_metadata(const std::vector<RegionSegment>& segments);
631
632/**
633 * @brief Extract structured bounds information from region.
634 * @param region The region to analyze.
635 * @return Map containing bounds metadata.
636 */
637std::unordered_map<std::string, std::any> extract_region_bounds_info(const Region& region);
638
639/**
640 * @brief Find optimal region containing given position.
641 * @param position Coordinates to search for.
642 * @param regions Vector of regions to search within.
643 * @return Optional index of containing region.
644 */
645std::optional<size_t> find_region_for_position(const std::vector<uint64_t>& position,
646 const std::vector<Region>& regions);
647
648/**
649 * @brief Find the index of the region containing the given position.
650 * @param position N-dimensional coordinates.
651 * @param regions vector of OrganizedRegions
652 * @return Optional index of the containing region, or std::nullopt if not found.
653 */
654std::optional<size_t> find_region_for_position(const std::vector<uint64_t>& position, std::vector<OrganizedRegion> regions);
655
656/**
657 * @brief Test whether two N-dimensional regions overlap on every shared axis.
658 *
659 * Regions are treated as closed intervals. Only axes present in both
660 * regions are tested; regions with fewer than 2 coordinates on either side
661 * are never considered intersecting.
662 *
663 * @param r1 First region.
664 * @param r2 Second region.
665 * @return true if all shared axes of r1 and r2 overlap.
666 */
667[[nodiscard]] bool regions_intersect(const Region& r1, const Region& r2) noexcept;
668
669/**
670 * @brief Extract the data described by @p region from @p src using the
671 * container's dimension descriptors.
672 *
673 * Delegates to the existing role-aware @c extract_region_data machinery so
674 * that the region coordinates are interpreted correctly regardless of axis
675 * order or modality. The caller decides what the region bounds mean — this
676 * function imposes no shape assumption (rectangular, cubic, or otherwise).
677 *
678 * For interleaved image data (IMAGE_COLOR / ROW_MAJOR) the channel dimension
679 * is included in the walk if the region carries a coordinate for it;
680 * if the region has fewer coordinates than dimensions, trailing axes are
681 * included in full.
682 *
683 * @tparam T Element type of the source buffer (e.g. @c uint8_t).
684 * @param src Flat source buffer in the layout described by @p dims.
685 * @param region N-dimensional bounds; start/end coordinate count may be
686 * less than @c dims.size() — missing trailing axes default
687 * to full extent.
688 * @param dims Dimension descriptors from the container structure,
689 * ordered consistently with the flat buffer layout.
690 * @return Flat buffer containing the extracted elements in the same
691 * axis order as @p dims.
692 * @throws std::invalid_argument if @p dims is empty or @p src is smaller
693 * than the total element count implied by @p dims.
694 * @throws std::out_of_range if any coordinate in @p region exceeds the
695 * corresponding dimension size.
696 */
697template <typename T>
698[[nodiscard]] std::vector<T> extract_nd_region(
699 std::span<const T> src,
700 const Region& region,
701 const std::vector<DataDimension>& dims)
702{
703 if (dims.empty()) {
704 error<std::invalid_argument>(
706 std::source_location::current(),
707 "extract_nd_region: dims must not be empty");
708 }
709
710 uint64_t total = 1;
711 for (const auto& d : dims)
712 total *= d.size;
713
714 if (src.size() < total) {
715 error<std::invalid_argument>(
717 std::source_location::current(),
718 "extract_nd_region: src smaller than total element count implied by dims");
719 }
720
721 Region clamped = region;
722 clamped.start_coordinates.resize(dims.size(), 0);
723 clamped.end_coordinates.resize(dims.size());
724 for (size_t i = 0; i < dims.size(); ++i) {
725 if (i >= region.end_coordinates.size()) {
726 clamped.end_coordinates[i] = dims[i].size - 1;
727 } else {
728 clamped.end_coordinates[i] = std::min(region.end_coordinates[i], dims[i].size - 1);
729 }
730 }
731
732 return extract_region_data<T>(src, clamped, dims);
733}
734
735}
@ Runtime
General runtime operations (default fallback)
@ Kakshya
Containers[Signalsource, Stream, File], Regions, DataProcessors.
uint64_t coordinates_to_linear(const std::vector< uint64_t > &coords, const std::vector< DataDimension > &dimensions)
Convert N-dimensional coordinates to a linear index for interleaved data.
Definition CoordUtils.cpp:6
std::vector< T > extract_region(const std::vector< T > &data, const Region &region, const std::vector< DataDimension > &dimensions)
Extract a region of data from a vector using a Region and dimension info.
void set_region_attribute(Region &region, const std::string &key, std::any value)
Set an attribute value on a Region.
Region remove_channel_dimension(const Region &region, const std::vector< DataDimension > &dimensions)
Remove the channel dimension from a Region.
std::vector< std::vector< T > > extract_segments_data(const std::vector< RegionSegment > &segments, const std::vector< std::span< const T > > &source_spans, const std::vector< DataDimension > &dimensions, OrganizationStrategy organization)
Extract data for multiple segments from multi-channel source data.
void sort_regions_by_attribute(std::vector< Region > &regions, const std::string &attr_name)
Sort a vector of Regions by a specific attribute (numeric).
std::optional< T > get_region_attribute(const Region &region, const std::string &key)
Get an attribute value from a Region by key.
std::optional< RegionGroup > get_region_group(const std::unordered_map< std::string, RegionGroup > &groups, const std::string &name)
Get a RegionGroup by name from a group map.
std::vector< Region > find_regions_with_label(const RegionGroup &group, const std::string &label)
Find all regions in a RegionGroup with a given label.
bool is_region_access_contiguous(const Region &region, const std::shared_ptr< SignalSourceContainer > &container)
Check if region access will be contiguous in memory.
std::unordered_map< std::string, std::any > extract_region_bounds_info(const Region &region)
Extract structured bounds information from region.
std::vector< T > flatten_channels(const std::vector< std::vector< T > > &channel_data)
Flatten a vector of channel data into a single vector.
void add_reference_region(std::vector< std::pair< std::string, Region > > &refs, const std::string &name, const Region &region)
Add a named reference region to a reference list.
Region translate_region(const Region &region, const std::vector< int64_t > &offset)
Translate a Region by an offset vector.
void add_region_group(std::unordered_map< std::string, RegionGroup > &groups, const RegionGroup &group)
Add a RegionGroup to a group map.
Region scale_region(const Region &region, const std::vector< double > &factors)
Scale a Region about its center by the given factors.
bool regions_intersect(const Region &r1, const Region &r2) noexcept
Test whether two N-dimensional regions overlap on every shared axis.
std::vector< std::vector< T > > extract_group_data(const std::vector< std::span< const T > > &source_spans, const RegionGroup &group, const std::vector< DataDimension > &dimensions, OrganizationStrategy organization)
Extract data for multiple regions from multi-channel source data.
OrganizationStrategy
Data organization strategy for multi-channel/multi-frame data.
Definition NDData.hpp:46
@ INTERLEAVED
Single DataVariant with interleaved data (LRLRLR for stereo)
std::vector< std::unordered_map< std::string, std::any > > extract_segments_metadata(const std::vector< RegionSegment > &segments)
Extract metadata from region segments.
void remove_region_group(std::unordered_map< std::string, RegionGroup > &groups, const std::string &name)
Remove a RegionGroup by name from a group map.
std::unordered_map< std::string, std::any > extract_group_bounds_info(const RegionGroup &group)
Extract bounds information from region group.
std::vector< Region > find_regions_containing_coordinates(const RegionGroup &group, const std::vector< uint64_t > &coordinates)
Find all regions in a RegionGroup that contain the given coordinates.
void remove_reference_region(std::vector< std::pair< std::string, Region > > &refs, const std::string &name)
Remove a named reference region from a reference list.
std::vector< T > extract_region_data(const std::span< const T > &source_data, const Region &region, const std::vector< DataDimension > &dimensions)
Extract a region of data from a flat data span using a Region and dimension info.
std::vector< Region > find_regions_with_attribute(const RegionGroup &group, const std::string &key, const std::any &value)
Find all regions in a RegionGroup with a specific attribute value.
std::vector< std::unordered_map< std::string, std::any > > extract_all_regions_info(const std::shared_ptr< SignalSourceContainer > &container)
Extract all regions from container's region groups.
Region get_bounding_region(const RegionGroup &group)
Get the bounding region that contains all regions in a RegionGroup.
std::vector< std::pair< std::string, Region > > find_references_in_region(const std::vector< std::pair< std::string, Region > > &refs, const Region &region)
Find all references in a reference list that overlap a given region.
std::vector< T > extract_nd_region(std::span< const T > src, const Region &region, const std::vector< DataDimension > &dims)
Extract the data described by region from src using the container's dimension descriptors.
std::optional< size_t > find_region_for_position(const std::vector< uint64_t > &position, const std::vector< Region > &regions)
Find optimal region containing given position.
Region calculate_output_region(const std::vector< uint64_t > &current_pos, const std::vector< uint64_t > &output_shape)
Calculate output region bounds from current position and shape.
uint64_t calculate_region_size(const Region &region)
Calculate the total number of elements in a region.
std::optional< Region > get_reference_region(const std::vector< std::pair< std::string, Region > > &refs, const std::string &name)
Get a named reference region from a reference list.
void set_or_update_region_data(std::span< T > dest_data, std::span< const T > source_data, const Region &region, const std::vector< DataDimension > &dimensions)
Write or update a region of data in a flat data span (interleaved).
std::vector< DataDimension > get_non_channel_dimensions(const std::vector< DataDimension > &dimensions)
Get all non-channel dimensions from a list of dimensions.
void sort_regions_by_dimension(std::vector< Region > &regions, size_t dimension)
Sort a vector of Regions by a specific dimension.
@ CHANNEL
Parallel streams (audio channels, color channels)
std::vector< Region > regions
Collection of regions belonging to this group.
Organizes related signal regions into a categorized collection.
std::unordered_map< std::string, std::any > attributes
Flexible key-value store for region-specific attributes.
Definition Region.hpp:75
uint64_t get_volume() const
Get the total volume (number of elements) in the region.
Definition Region.hpp:295
std::vector< uint64_t > end_coordinates
Ending frame index (inclusive)
Definition Region.hpp:72
std::vector< uint64_t > start_coordinates
Starting frame index (inclusive)
Definition Region.hpp:69
Represents a point or span in N-dimensional space.
Definition Region.hpp:67