Deviation hist.

This commit is contained in:
2026-04-21 16:03:46 +02:00
parent fdfe43b6b9
commit 8f44cf56d4
2 changed files with 56 additions and 1 deletions

View File

@@ -31,7 +31,7 @@ artifact_detection:
threshold_db: -60 # Detect unexpected frequencies above noise floor + this threshold (more negative = less sensitive) threshold_db: -60 # Detect unexpected frequencies above noise floor + this threshold (more negative = less sensitive)
amplitude_spikes: amplitude_spikes:
enabled: true enabled: true
threshold_factor: 7.0 # MAD-based outlier detection on envelope (detects clicks, pops, dropouts). Lower = more sensitive. threshold_factor: 10.0 # MAD-based outlier detection on envelope (detects clicks, pops, dropouts). Lower = more sensitive.
zero_crossing: zero_crossing:
enabled: false enabled: false
threshold_factor: 2.0 # Number of standard deviations for zero-crossing anomalies (detects distortion) threshold_factor: 2.0 # Number of standard deviations for zero-crossing anomalies (detects distortion)

View File

@@ -722,6 +722,60 @@ def plot_artifact_detection(channel_1: np.ndarray, channel_2: np.ndarray,
plt.close() plt.close()
def plot_deviation_histogram(artifacts_ch1: Dict, artifacts_ch2: Dict, output_dir: Path):
def get_deviations(artifacts_dict):
values = []
for a in artifacts_dict.get('artifacts', []):
if 'deviation_factor' in a:
values.append(a['deviation_factor'])
return values
dev_ch1 = get_deviations(artifacts_ch1)
dev_ch2 = get_deviations(artifacts_ch2)
all_devs = dev_ch1 + dev_ch2
if not all_devs:
return
bin_min = int(np.floor(min(all_devs)))
bin_max = int(np.ceil(max(all_devs))) + 1
bins = np.arange(bin_min, bin_max + 1)
counts_ch1, _ = np.histogram(dev_ch1, bins=bins)
counts_ch2, _ = np.histogram(dev_ch2, bins=bins)
bin_labels = [f"{bins[i]}-{bins[i+1]}" for i in range(len(bins) - 1)]
x = np.arange(len(bin_labels))
width = 0.4
fig, ax = plt.subplots(figsize=(max(10, len(bin_labels) * 0.7), 6))
bars1 = ax.bar(x - width / 2, counts_ch1, width, label='Ch1 Loopback', color='steelblue', alpha=0.85)
bars2 = ax.bar(x + width / 2, counts_ch2, width, label='Ch2 DUT/Radio', color='tomato', alpha=0.85)
ax.set_xlabel('Deviation Factor (σ)')
ax.set_ylabel('Count')
ax.set_title('Artifact Deviation Factor Distribution')
ax.set_xticks(x)
ax.set_xticklabels(bin_labels, rotation=45, ha='right')
ax.yaxis.get_major_locator().set_params(integer=True)
ax.legend()
ax.grid(True, axis='y', alpha=0.3)
for bar in bars1:
if bar.get_height() > 0:
ax.text(bar.get_x() + bar.get_width() / 2, bar.get_height() + 0.05,
str(int(bar.get_height())), ha='center', va='bottom', fontsize=8)
for bar in bars2:
if bar.get_height() > 0:
ax.text(bar.get_x() + bar.get_width() / 2, bar.get_height() + 0.05,
str(int(bar.get_height())), ha='center', va='bottom', fontsize=8)
plt.tight_layout()
plot_file = output_dir / 'artifact_deviation_histogram.png'
plt.savefig(plot_file, dpi=150, bbox_inches='tight')
plt.close()
def run_artifact_detection_test(config: Dict, save_plots: bool = False, output_dir: Path = None) -> Dict: def run_artifact_detection_test(config: Dict, save_plots: bool = False, output_dir: Path = None) -> Dict:
import time import time
@@ -765,6 +819,7 @@ def run_artifact_detection_test(config: Dict, save_plots: bool = False, output_d
if save_plots and output_dir: if save_plots and output_dir:
plot_artifact_detection(channel_1, channel_2, artifacts_ch1, artifacts_ch2, plot_artifact_detection(channel_1, channel_2, artifacts_ch1, artifacts_ch2,
frequency, sample_rate, output_dir) frequency, sample_rate, output_dir)
plot_deviation_histogram(artifacts_ch1, artifacts_ch2, output_dir)
anomalies_dir = output_dir / 'individual_anomalies' anomalies_dir = output_dir / 'individual_anomalies'
anomalies_dir.mkdir(exist_ok=True) anomalies_dir.mkdir(exist_ok=True)