Deviation hist.
This commit is contained in:
@@ -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)
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|||||||
Reference in New Issue
Block a user