added white theme, some features to processing and saving

This commit is contained in:
Ayzen
2026-04-13 10:44:01 +03:00
parent 61685d7a4d
commit 5d2f95f959
20 changed files with 295 additions and 48 deletions
@@ -1,11 +1,94 @@
#include "data_preprocessor.hpp"
#include <algorithm>
#include <chrono>
#include <cmath>
#include <span>
#include <stdexcept>
#include <string_view>
#include <thread>
#include <vector>
namespace radar::preprocessing {
namespace {
constexpr double kPi = 3.14159265358979323846;
[[nodiscard]] auto should_apply_notch(const config::PreprocessNotchConfig& notch) -> bool {
return notch.enabled && !notch.bands_hz.empty();
}
[[nodiscard]] auto build_notch_mask(
std::span<const float> frequency_hz,
const config::PreprocessNotchConfig& notch
) -> std::vector<float> {
std::vector<float> mask(frequency_hz.size(), 1.0F);
if (!should_apply_notch(notch)) {
return mask;
}
const bool hard_taper = notch.taper_type == "hard";
const double taper_width_hz = std::max(0.0, static_cast<double>(notch.taper_width_hz));
for (const auto& band : notch.bands_hz) {
const double low_hz = static_cast<double>(band.low_hz);
const double high_hz = static_cast<double>(band.high_hz);
const double trans_low_hz = low_hz - taper_width_hz;
const double trans_high_hz = high_hz + taper_width_hz;
for (std::size_t index = 0U; index < frequency_hz.size(); ++index) {
const double frequency = static_cast<double>(frequency_hz[index]);
if (frequency >= low_hz && frequency <= high_hz) {
mask[index] = 0.0F;
continue;
}
if (hard_taper || taper_width_hz <= 0.0) {
if (frequency >= trans_low_hz && frequency <= trans_high_hz) {
mask[index] = 0.0F;
}
continue;
}
if (frequency >= trans_low_hz && frequency < low_hz) {
const double arg = kPi * (frequency - trans_low_hz) / taper_width_hz;
mask[index] *= static_cast<float>(0.5 * (1.0 - std::cos(arg)));
continue;
}
if (frequency > high_hz && frequency <= trans_high_hz) {
const double arg = kPi * (frequency - high_hz) / taper_width_hz;
mask[index] *= static_cast<float>(0.5 * (1.0 + std::cos(arg)));
}
}
}
return mask;
}
void apply_notch_mask(std::vector<ipc::Complex32>& samples, std::span<const float> mask) {
const std::size_t point_count = std::min(samples.size(), mask.size());
for (std::size_t index = 0U; index < point_count; ++index) {
samples[index].re *= mask[index];
samples[index].im *= mask[index];
}
}
[[nodiscard]] auto apply_notch_filter(
const ipc::SweepTraceBlock& trace,
const config::PreprocessNotchConfig& notch
) -> ipc::SweepTraceBlock {
if (!should_apply_notch(notch)) {
return trace;
}
ipc::SweepTraceBlock filtered = trace;
const auto mask = build_notch_mask(filtered.frequency_hz, notch);
apply_notch_mask(filtered.s21, mask);
apply_notch_mask(filtered.s11, mask);
return filtered;
}
} // namespace
DataPreprocessor::DataPreprocessor(
const config::RunConfig& config,
@@ -78,7 +161,7 @@ auto DataPreprocessor::preprocess_collection(const ipc::RawSweepCollection& raw_
// Pipeline order is fixed: calibration first, then reference subtraction.
const auto calibrated = calibration_master_.apply_to_trace(raw_trace);
const auto referenced = reference_master_.apply_to_trace(calibrated);
preprocessed.traces.push_back(referenced);
preprocessed.traces.push_back(apply_notch_filter(referenced, config_.preprocess.notch));
}
return preprocessed;