MayaFlux 0.4.0
Digital-First Multimedia Processing Framework
Loading...
Searching...
No Matches
EnergyAnalyzer.hpp
Go to the documentation of this file.
1#pragma once
2
5
7#include <Eigen/Dense>
8
10
12
13/**
14 * @file EnergyAnalyzer.hpp
15 * @brief Span-based energy analysis for digital signals in Maya Flux
16 *
17 * Defines the EnergyAnalyzer using the new UniversalAnalyzer framework with
18 * zero-copy span processing and automatic structure handling via OperationHelper.
19 * This analyzer extracts energy-related features from digital signals with multiple
20 * computation methods and flexible output configurations.
21 *
22 * Key Features:
23 * - **Zero-copy processing:** Uses spans for maximum efficiency
24 * - **Template-flexible I/O:** Instance defines input/output types at construction
25 * - **Multiple energy methods:** RMS, peak, spectral, zero-crossing, harmonic, power, dynamic range
26 * - **Parallel processing:** Utilizes std::execution for performance
27 * - **Energy classification:** Maps values to qualitative levels (silent, quiet, etc.)
28 * - **Window-based analysis:** Configurable window size and hop size
29 * - **Automatic data handling:** OperationHelper manages all extraction/conversion
30 */
31
32namespace MayaFlux::Yantra {
33
34/**
35 * @enum EnergyMethod
36 * @brief Supported energy computation methods
37 */
38enum class EnergyMethod : uint8_t {
39 RMS, ///< Root Mean Square energy
40 PEAK, ///< Peak amplitude
41 SPECTRAL, ///< Spectral energy (FFT-based)
42 ZERO_CROSSING, ///< Zero-crossing rate
43 HARMONIC, ///< Harmonic energy (low-frequency content)
44 POWER, ///< Power (sum of squares)
45 DYNAMIC_RANGE ///< Dynamic range (dB)
46};
47
48/**
49 * @enum EnergyLevel
50 * @brief Qualitative classification of energy values
51 */
52enum class EnergyLevel : uint8_t {
53 SILENT,
54 QUIET,
56 LOUD,
57 PEAK
58};
59
60struct MAYAFLUX_API ChannelEnergy {
61 std::vector<double> energy_values;
62 double mean_energy {};
63 double max_energy {};
64 double min_energy {};
65 double variance {};
66
67 std::vector<EnergyLevel> classifications;
68 std::array<int, 5> level_counts {}; // [SILENT, QUIET, MODERATE, LOUD, PEAK]
69 std::vector<std::pair<size_t, size_t>> window_positions;
70
71 // Positions of detected energy events (e.g., peaks, zero crossings, flux)
72 std::vector<size_t> event_positions;
73};
74
75/**
76 * @struct EnergyAnalysis
77 * @brief Analysis result structure for energy analysis
78 */
79struct MAYAFLUX_API EnergyAnalysis {
80 std::vector<ChannelEnergy> channels;
81
82 EnergyMethod method_used {};
83 uint32_t window_size {};
84 uint32_t hop_size {};
85};
86
87/**
88 * @class EnergyAnalyzer
89 * @brief High-performance energy analyzer with zero-copy processing
90 *
91 * The EnergyAnalyzer provides comprehensive energy analysis capabilities for
92 * digital signals using span-based processing for maximum efficiency.
93 * All data extraction and conversion is handled automatically by OperationHelper.
94 *
95 * Example usage:
96 * ```cpp
97 * // DataVariant -> VectorXd analyzer
98 * auto energy_analyzer = std::make_shared<EnergyAnalyzer<Kakshya::DataVariant, Eigen::VectorXd>>();
99 *
100 * // User-facing analysis
101 * auto analysis = energy_analyzer->analyze_data(audio_data);
102 * auto energy_result = safe_any_cast<EnergyAnalysis>(analysis);
103 *
104 * // Pipeline usage
105 * auto pipeline_output = energy_analyzer->apply_operation(IO{audio_data});
106 * ```
107 */
108template <ComputeData InputType = std::vector<Kakshya::DataVariant>, ComputeData OutputType = Eigen::VectorXd>
109class MAYAFLUX_API EnergyAnalyzer : public UniversalAnalyzer<InputType, OutputType> {
110public:
114
115 /**
116 * @brief Construct EnergyAnalyzer with configurable window parameters
117 * @param window_size Size of analysis window in samples (default: 512)
118 * @param hop_size Step size between windows in samples (default: 256)
119 */
120 explicit EnergyAnalyzer(uint32_t window_size = 256, uint32_t hop_size = 128)
121 : m_window_size(window_size)
122 , m_hop_size(hop_size)
123 {
124 validate_window_parameters();
125 }
126
127 /**
128 * @brief Type-safe energy analysis method
129 * @param data Input data
130 * @return EnergyAnalysis directly
131 */
133 {
134 auto result = this->analyze_data(data);
135 return safe_any_cast_or_throw<EnergyAnalysis>(result);
136 }
137
138 EnergyAnalysis analyze_energy(const InputType& data)
139 {
140 return this->analyze_energy(input_type { data });
141 }
142
143 /**
144 * @brief Get last energy analysis result (type-safe)
145 * @return EnergyAnalysis from last operation
146 */
148 {
149 return safe_any_cast_or_throw<EnergyAnalysis>(this->get_current_analysis());
150 }
151
152 /**
153 * @brief Get analysis type category
154 * @return AnalysisType::FEATURE (energy is a feature extraction operation)
155 */
156 [[nodiscard]] AnalysisType get_analysis_type() const override
157 {
158 return AnalysisType::FEATURE;
159 }
160
161 /**
162 * @brief Get available analysis methods
163 * @return Vector of supported energy method names
164 */
165 [[nodiscard]] std::vector<std::string> get_available_methods() const override
166 {
167 return Reflect::get_enum_names_lowercase<EnergyMethod>();
168 }
169
170 /**
171 * @brief Check if a specific method is supported
172 * @param method Method name to check
173 * @return True if method is supported
174 */
175 [[nodiscard]] bool supports_method(const std::string& method) const override
176 {
177 return std::find_if(get_available_methods().begin(), get_available_methods().end(),
178 [&method](const std::string& m) {
179 return std::equal(method.begin(), method.end(), m.begin(), m.end(),
180 [](char a, char b) { return std::tolower(a) == std::tolower(b); });
181 })
182 != get_available_methods().end();
183 }
184
185 /**
186 * @brief Set energy computation method
187 */
188 void set_energy_method(EnergyMethod method) { m_method = method; }
189
190 /**
191 * @brief Get current energy computation method
192 */
193 [[nodiscard]] EnergyMethod get_energy_method() const { return m_method; }
194
195 /**
196 * @brief Set window parameters for analysis
197 * @param window_size Window size in samples
198 * @param hop_size Hop size in samples
199 */
200 void set_window_parameters(uint32_t window_size, uint32_t hop_size)
201 {
202 m_window_size = window_size;
203 m_hop_size = hop_size;
204 validate_window_parameters();
205 }
206
207 /**
208 * @brief Set energy level classification thresholds
209 * @param silent Threshold for silent level
210 * @param quiet Threshold for quiet level
211 * @param moderate Threshold for moderate level
212 * @param loud Threshold for loud level
213 */
214 void set_energy_thresholds(double silent, double quiet, double moderate, double loud)
215 {
216 if (silent >= quiet || quiet >= moderate || moderate >= loud) {
217 error<std::invalid_argument>(Journal::Component::Yantra, Journal::Context::ComputeMatrix, std::source_location::current(), "Energy thresholds must be in ascending order");
218 }
219 m_silent_threshold = silent;
220 m_quiet_threshold = quiet;
221 m_moderate_threshold = moderate;
222 m_loud_threshold = loud;
223 }
224
225 /**
226 * @brief Enable or disable energy level classification
227 * @param enabled True to enable classification
228 */
229 void enable_classification(bool enabled) { m_classification_enabled = enabled; }
230
231 /**
232 * @brief Classify energy value into qualitative level
233 * @param energy Energy value to classify
234 * @return EnergyLevel classification
235 */
236 [[nodiscard]] EnergyLevel classify_energy_level(double energy) const
237 {
238 if (energy <= m_silent_threshold)
239 return EnergyLevel::SILENT;
240 if (energy <= m_quiet_threshold)
241 return EnergyLevel::QUIET;
242 if (energy <= m_moderate_threshold)
243 return EnergyLevel::MODERATE;
244 if (energy <= m_loud_threshold)
245 return EnergyLevel::LOUD;
246 return EnergyLevel::PEAK;
247 }
248
249 /**
250 * @brief Get count of windows in a specific energy level for a channel
251 * @param channel ChannelEnergy result
252 * @param level EnergyLevel to query
253 * @return Count of windows in that level
254 */
255 [[nodiscard]]
257 {
258 return channel.level_counts[static_cast<size_t>(level)];
259 }
260
261 /**
262 * @brief Convert energy method enum to string
263 * @param method EnergyMethod value
264 * @return String representation
265 */
266 static std::string method_to_string(EnergyMethod method)
267 {
268 return Reflect::enum_to_lowercase_string(method);
269 }
270
271 /**
272 * @brief Convert string to energy method enum
273 * @param str String representation
274 * @return EnergyMethod value
275 */
276 static EnergyMethod string_to_method(const std::string& str)
277 {
278 if (str == "default")
279 return EnergyMethod::RMS;
280 return Reflect::string_to_enum_or_throw_case_insensitive<EnergyMethod>(str, "EnergyMethod");
281 }
282
283 /**
284 * @brief Convert energy level enum to string
285 * @param level EnergyLevel value
286 * @return String representation
287 */
288 static std::string energy_level_to_string(EnergyLevel level)
289 {
290 return Reflect::enum_to_lowercase_string(level);
291 }
292
293protected:
294 /**
295 * @brief Get analyzer name
296 * @return "EnergyAnalyzer"
297 */
298 [[nodiscard]] std::string get_analyzer_name() const override
299 {
300 return "EnergyAnalyzer";
301 }
302
303 /**
304 * @brief Core analysis implementation - creates analysis result AND pipeline output
305 * @param input Input data wrapped in Datum container
306 * @return Pipeline output (data flow for chaining operations)
307 */
309 {
310 try {
311 auto [data_span, structure_info] = OperationHelper::extract_structured_double(
312 const_cast<input_type&>(input));
313
314 std::vector<std::span<const double>> channel_spans;
315 for (auto& span : data_span)
316 channel_spans.emplace_back(span.data(), span.size());
317
318 for (const auto& channel_span : channel_spans) {
319 if (channel_span.size() < m_window_size) {
320 error<std::runtime_error>(Journal::Component::Yantra, Journal::Context::ComputeMatrix, std::source_location::current(), "One or more channels in input data are smaller than window size ({} samples)", m_window_size);
321 }
322 }
323
324 std::vector<std::vector<double>> energy_values;
325 energy_values.reserve(channel_spans.size());
326 for (const auto& channel_span : channel_spans) {
327 energy_values.push_back(compute_energy_values(channel_span, m_method));
328 }
329
330 EnergyAnalysis analysis_result = create_analysis_result(
331 energy_values, channel_spans, structure_info);
332
333 this->store_current_analysis(analysis_result);
334
335 return create_pipeline_output(input, analysis_result, structure_info);
336 } catch (const std::exception& e) {
337 MF_ERROR(Journal::Component::Yantra, Journal::Context::ComputeMatrix, "Energy analysis failed: {}", e.what());
338 output_type error_result;
339 error_result.metadata = input.metadata;
340 error_result.metadata["error"] = std::string("Analysis failed: ") + e.what();
341 return error_result;
342 }
343 }
344
345 /**
346 * @brief Handle analysis-specific parameters
347 */
348 void set_analysis_parameter(const std::string& name, std::any value) override
349 {
350 if (name == "method") {
351 if (auto str_result = safe_any_cast<std::string>(value)) {
352 m_method = string_to_method(*str_result.value);
353 return;
354 }
355
356 if (auto enum_result = safe_any_cast<EnergyMethod>(value)) {
357 m_method = *enum_result.value;
358 return;
359 }
360
361 error<std::invalid_argument>(Journal::Component::Yantra, Journal::Context::ComputeMatrix,
362 std::source_location::current(),
363 "Invalid method parameter - expected string or EnergyMethod enum");
364 } else if (name == "window_size") {
365 if (auto result = safe_any_cast<uint32_t>(value)) {
366 m_window_size = *result.value;
367 validate_window_parameters();
368 return;
369 }
370 } else if (name == "hop_size") {
371 if (auto result = safe_any_cast<uint32_t>(value)) {
372 m_hop_size = *result.value;
373 validate_window_parameters();
374 return;
375 }
376 } else if (name == "classification_enabled") {
377 if (auto result = safe_any_cast<bool>(value)) {
378 m_classification_enabled = *result.value;
379 return;
380 }
381 }
382
383 base_type::set_analysis_parameter(name, std::move(value));
384 }
385
386 /**
387 * @brief Get analysis-specific parameter
388 */
389 [[nodiscard]] std::any get_analysis_parameter(const std::string& name) const override
390 {
391 if (name == "method")
392 return std::any(method_to_string(m_method));
393 if (name == "window_size")
394 return std::any(m_window_size);
395 if (name == "hop_size")
396 return std::any(m_hop_size);
397 if (name == "classification_enabled")
398 return std::any(m_classification_enabled);
399
400 return base_type::get_analysis_parameter(name);
401 }
402
403private:
404 uint32_t m_window_size { 512 };
405 uint32_t m_hop_size { 256 };
406 EnergyMethod m_method { EnergyMethod::RMS };
407 bool m_classification_enabled { false };
408
409 double m_silent_threshold { 0.01 };
410 double m_quiet_threshold = { 0.1 };
411 double m_moderate_threshold { 0.5 };
412 double m_loud_threshold { 0.8 };
413
415 {
416 if (m_window_size == 0) {
417 error<std::invalid_argument>(Journal::Component::Yantra, Journal::Context::ComputeMatrix, std::source_location::current(), "Window size must be greater than 0");
418 }
419 if (m_hop_size == 0) {
420 error<std::invalid_argument>(Journal::Component::Yantra, Journal::Context::ComputeMatrix, std::source_location::current(), "Hop size must be greater than 0");
421 }
422 if (m_hop_size > m_window_size) {
423 error<std::invalid_argument>(Journal::Component::Yantra, Journal::Context::ComputeMatrix, std::source_location::current(), "Hop size should not exceed window size");
424 }
425 }
426
427 /**
428 * @brief Create comprehensive analysis result from energy computation
429 */
431 const std::vector<std::vector<double>>& energy_values,
432 std::vector<std::span<const double>> original_data,
433 const DataStructureInfo& /*structure_info*/) const
434 {
435 EnergyAnalysis result;
436 result.method_used = m_method;
437 result.window_size = m_window_size;
438 result.hop_size = m_hop_size;
439
440 if (energy_values.empty()) {
441 return result;
442 }
443
444 result.channels.resize(energy_values.size());
445
446 for (size_t ch = 0; ch < energy_values.size(); ch++) {
447
448 auto& channel_result = result.channels[ch];
449 const auto& ch_energy = energy_values[ch];
450
451 channel_result.energy_values = ch_energy;
452
453 if (!ch_energy.empty()) {
454 auto [min_it, max_it] = std::ranges::minmax_element(ch_energy);
455 channel_result.min_energy = *min_it;
456 channel_result.max_energy = *max_it;
457
458 const double sum = std::accumulate(ch_energy.begin(), ch_energy.end(), 0.0);
459 channel_result.mean_energy = sum / static_cast<double>(ch_energy.size());
460
461 const double mean = channel_result.mean_energy;
462 const double var_sum = std::transform_reduce(
463 ch_energy.begin(), ch_energy.end(), 0.0, std::plus {},
464 [mean](double val) { return (val - mean) * (val - mean); });
465 channel_result.variance = var_sum / static_cast<double>(ch_energy.size());
466 }
467
468 const size_t data_size = (ch < original_data.size()) ? original_data[ch].size() : 0;
469 channel_result.window_positions.reserve(ch_energy.size());
470
471 for (size_t i = 0; i < ch_energy.size(); ++i) {
472 const size_t start = i * m_hop_size;
473 const size_t end = std::min(start + m_window_size, data_size);
474 channel_result.window_positions.emplace_back(start, end);
475 }
476
477 if (ch < original_data.size()) {
478 switch (m_method) {
479 case EnergyMethod::ZERO_CROSSING:
480 channel_result.event_positions = Kinesis::Discrete::zero_crossing_positions(
481 original_data[ch], 0.0);
482 break;
483
484 case EnergyMethod::PEAK: {
485 double peak_threshold = m_classification_enabled ? m_quiet_threshold : 0.01;
486 channel_result.event_positions = Kinesis::Discrete::peak_positions(
487 original_data[ch], peak_threshold, m_hop_size / 4);
488 break;
489 }
490
491 case EnergyMethod::RMS:
492 case EnergyMethod::POWER:
493 case EnergyMethod::SPECTRAL:
494 case EnergyMethod::HARMONIC:
495 case EnergyMethod::DYNAMIC_RANGE:
496 default:
497 // event_positions remains empty
498 break;
499 }
500 }
501
502 if (m_classification_enabled) {
503 channel_result.classifications.reserve(ch_energy.size());
504 channel_result.level_counts.fill(0);
505
506 for (double energy : ch_energy) {
507 EnergyLevel level = classify_energy_level(energy);
508 channel_result.classifications.push_back(level);
509 channel_result.level_counts[static_cast<size_t>(level)]++;
510 }
511 }
512 }
513
514 return result;
515 }
516
517 /**
518 * @brief Create pipeline output from input and energy values
519 */
521 {
522 std::vector<std::vector<double>> channel_energies;
523 channel_energies.reserve(analysis_result.channels.size());
524
525 for (const auto& ch : analysis_result.channels) {
526 channel_energies.push_back(ch.energy_values);
527 }
528
529 output_type output = this->convert_result(channel_energies, info);
530
531 output.metadata = input.metadata;
532
533 output.metadata["source_analyzer"] = "EnergyAnalyzer";
534 output.metadata["energy_method"] = method_to_string(analysis_result.method_used);
535 output.metadata["window_size"] = analysis_result.window_size;
536 output.metadata["hop_size"] = analysis_result.hop_size;
537 output.metadata["num_channels"] = analysis_result.channels.size();
538
539 if (!analysis_result.channels.empty()) {
540 std::vector<double> channel_means, channel_maxs, channel_mins, channel_variances;
541 std::vector<size_t> channel_window_counts;
542
543 for (const auto& ch : analysis_result.channels) {
544 channel_means.push_back(ch.mean_energy);
545 channel_maxs.push_back(ch.max_energy);
546 channel_mins.push_back(ch.min_energy);
547 channel_variances.push_back(ch.variance);
548 channel_window_counts.push_back(ch.energy_values.size());
549 }
550
551 output.metadata["mean_energy_per_channel"] = channel_means;
552 output.metadata["max_energy_per_channel"] = channel_maxs;
553 output.metadata["min_energy_per_channel"] = channel_mins;
554 output.metadata["variance_per_channel"] = channel_variances;
555 output.metadata["window_count_per_channel"] = channel_window_counts;
556 }
557
558 return output;
559 }
560
561 /**
562 * @brief Compute energy values using span (zero-copy processing)
563 */
564 [[nodiscard]] std::vector<double> compute_energy_values(std::span<const double> data, EnergyMethod method) const
565 {
566 namespace D = MayaFlux::Kinesis::Discrete;
567 const size_t num_windows = calculate_num_windows(data.size());
568
569 switch (method) {
570 case EnergyMethod::PEAK:
571 return D::peak(data, num_windows, m_hop_size, m_window_size);
572 case EnergyMethod::ZERO_CROSSING:
573 return D::zero_crossing_rate(data, num_windows, m_hop_size, m_window_size);
574 case EnergyMethod::POWER:
575 return D::power(data, num_windows, m_hop_size, m_window_size);
576 case EnergyMethod::DYNAMIC_RANGE:
577 return D::dynamic_range(data, num_windows, m_hop_size, m_window_size);
578 case EnergyMethod::SPECTRAL:
579 return D::spectral_energy(data, num_windows, m_hop_size, m_window_size);
580 case EnergyMethod::HARMONIC:
581 return D::low_frequency_energy(data, num_windows, m_hop_size, m_window_size);
582 case EnergyMethod::RMS:
583 default:
584 return D::rms(data, num_windows, m_hop_size, m_window_size);
585 }
586 }
587
588 /**
589 * @brief Calculate number of windows for given data size
590 */
591 [[nodiscard]] size_t calculate_num_windows(size_t data_size) const
592 {
593 if (data_size < m_window_size)
594 return 0;
595 return (data_size - m_window_size) / m_hop_size + 1;
596 }
597};
598
599/// Standard energy analyzer: DataVariant -> MatrixXd
601
602/// Container energy analyzer: SignalContainer -> MatrixXd
604
605/// Region energy analyzer: Region -> MatrixXd
607
608/// Raw energy analyzer: produces double vectors
609template <ComputeData InputType = std::vector<Kakshya::DataVariant>>
611
612/// Variant energy analyzer: produces DataVariant output
613template <ComputeData InputType = std::vector<Kakshya::DataVariant>>
615
616/**
617 * @brief Extract a named scalar from an EnergyAnalysis result.
618 *
619 * Maps qualifier strings to scalar fields of the first channel in @p analysis.
620 * All scalar-valued fields of ChannelEnergy are addressable.
621 *
622 * Supported qualifiers:
623 * - "mean_energy" mean energy across analysis windows
624 * - "max_energy" maximum window energy
625 * - "min_energy" minimum window energy
626 * - "variance" variance of window energy values
627 * - "dynamic_range" max_energy - min_energy
628 * - "event_count" number of detected energy events (peaks, zero crossings, etc.)
629 * - "window_count" number of analysis windows
630 *
631 * An empty qualifier resolves to "mean_energy".
632 * Unknown qualifiers fall back to mean_energy.
633 *
634 * @param analysis Result produced by EnergyAnalyzer.
635 * @param qualifier Name of the scalar to extract.
636 * @return Extracted double value, or 0.0 if channels is empty.
637 */
638[[nodiscard]] MAYAFLUX_API inline double extract_scalar_energy(
639 const EnergyAnalysis& analysis, const std::string& qualifier)
640{
641 if (analysis.channels.empty())
642 return 0.0;
643
644 const auto& ch = analysis.channels[0];
645 const std::string q = qualifier.empty() ? "mean_energy" : qualifier;
646
647 if (q == "mean_energy")
648 return ch.mean_energy;
649 if (q == "max_energy")
650 return ch.max_energy;
651 if (q == "min_energy")
652 return ch.min_energy;
653 if (q == "variance")
654 return ch.variance;
655 if (q == "dynamic_range")
656 return ch.max_energy - ch.min_energy;
657 if (q == "event_count")
658 return static_cast<double>(ch.event_positions.size());
659 if (q == "window_count")
660 return static_cast<double>(ch.energy_values.size());
661
662 return ch.mean_energy;
663}
664
665} // namespace MayaFlux::Yantra
Discrete sequence analysis primitives for MayaFlux::Kinesis.
#define MF_ERROR(comp, ctx,...)
size_t a
size_t b
double q
Range size
uint32_t channel
Modern, digital-first universal analyzer framework for Maya Flux.
EnergyMethod get_energy_method() const
Get current energy computation method.
size_t calculate_num_windows(size_t data_size) const
Calculate number of windows for given data size.
bool supports_method(const std::string &method) const override
Check if a specific method is supported.
output_type create_pipeline_output(const input_type &input, const EnergyAnalysis &analysis_result, DataStructureInfo &info)
Create pipeline output from input and energy values.
static EnergyMethod string_to_method(const std::string &str)
Convert string to energy method enum.
void enable_classification(bool enabled)
Enable or disable energy level classification.
AnalysisType get_analysis_type() const override
Get analysis type category.
EnergyAnalyzer(uint32_t window_size=256, uint32_t hop_size=128)
Construct EnergyAnalyzer with configurable window parameters.
EnergyAnalysis create_analysis_result(const std::vector< std::vector< double > > &energy_values, std::vector< std::span< const double > > original_data, const DataStructureInfo &) const
Create comprehensive analysis result from energy computation.
void set_energy_method(EnergyMethod method)
Set energy computation method.
std::any get_analysis_parameter(const std::string &name) const override
Get analysis-specific parameter.
int get_level_count(const ChannelEnergy &channel, EnergyLevel level)
Get count of windows in a specific energy level for a channel.
static std::string method_to_string(EnergyMethod method)
Convert energy method enum to string.
output_type analyze_implementation(const input_type &input) override
Core analysis implementation - creates analysis result AND pipeline output.
void set_energy_thresholds(double silent, double quiet, double moderate, double loud)
Set energy level classification thresholds.
std::vector< double > compute_energy_values(std::span< const double > data, EnergyMethod method) const
Compute energy values using span (zero-copy processing)
std::vector< std::string > get_available_methods() const override
Get available analysis methods.
EnergyAnalysis analyze_energy(const input_type &data)
Type-safe energy analysis method.
void set_window_parameters(uint32_t window_size, uint32_t hop_size)
Set window parameters for analysis.
static std::string energy_level_to_string(EnergyLevel level)
Convert energy level enum to string.
std::string get_analyzer_name() const override
Get analyzer name.
EnergyAnalysis analyze_energy(const InputType &data)
void set_analysis_parameter(const std::string &name, std::any value) override
Handle analysis-specific parameters.
EnergyLevel classify_energy_level(double energy) const
Classify energy value into qualitative level.
EnergyAnalysis get_energy_analysis() const
Get last energy analysis result (type-safe)
High-performance energy analyzer with zero-copy processing.
Template-flexible analyzer base with instance-defined I/O types.
AnalysisType
Categories of analysis operations for discovery and organization.
MAYAFLUX_API double extract_scalar_energy(const EnergyAnalysis &analysis, const std::string &qualifier)
Extract a named scalar from an EnergyAnalysis result.
EnergyMethod
Supported energy computation methods.
@ SPECTRAL
Spectral energy (FFT-based)
@ DYNAMIC_RANGE
Dynamic range (dB)
@ RMS
Root Mean Square energy.
@ ZERO_CROSSING
Zero-crossing rate.
@ HARMONIC
Harmonic energy (low-frequency content)
@ POWER
Power (sum of squares)
EnergyLevel
Qualitative classification of energy values.
double mean(const std::vector< double > &data)
Calculate mean of single-channel data.
Definition Yantra.cpp:55
std::vector< size_t > event_positions
std::vector< EnergyLevel > classifications
std::vector< std::pair< size_t, size_t > > window_positions
std::vector< double > energy_values
Metadata about data structure for reconstruction.
std::unordered_map< std::string, std::any > metadata
Associated metadata.
Definition DataIO.hpp:28
Input/Output container for computation pipeline data flow with structure preservation.
Definition DataIO.hpp:24
std::vector< ChannelEnergy > channels
Analysis result structure for energy analysis.