Parcourir la source

feat: add refinement windows for local analysis

master
Jan Svabenik il y a 9 heures
Parent
révision
b53bcfcdd9
4 fichiers modifiés avec 40 ajouts et 17 suppressions
  1. +10
    -1
      cmd/sdrd/pipeline_runtime.go
  2. +1
    -0
      internal/pipeline/phases.go
  3. +6
    -1
      internal/pipeline/refiner.go
  4. +23
    -15
      internal/pipeline/types.go

+ 10
- 1
cmd/sdrd/pipeline_runtime.go Voir le fichier

@@ -236,10 +236,19 @@ func (rt *dspRuntime) buildRefinementInput(surv pipeline.SurveillanceResult) pip
if len(scheduled) == 0 && len(plan.Selected) > 0 { if len(scheduled) == 0 && len(plan.Selected) > 0 {
scheduled = append([]pipeline.ScheduledCandidate(nil), plan.Selected...) scheduled = append([]pipeline.ScheduledCandidate(nil), plan.Selected...)
} }
windows := make([]pipeline.RefinementWindow, 0, len(scheduled))
for _, sc := range scheduled {
windows = append(windows, pipeline.RefinementWindow{
CenterHz: sc.Candidate.CenterHz,
SpanHz: sc.Candidate.BandwidthHz,
Source: "candidate",
})
}
input := pipeline.RefinementInput{ input := pipeline.RefinementInput{
Candidates: append([]pipeline.Candidate(nil), surv.Candidates...), Candidates: append([]pipeline.Candidate(nil), surv.Candidates...),
Scheduled: scheduled, Scheduled: scheduled,
Plan: plan, Plan: plan,
Windows: windows,
SampleRate: rt.cfg.SampleRate, SampleRate: rt.cfg.SampleRate,
FFTSize: rt.cfg.FFTSize, FFTSize: rt.cfg.FFTSize,
CenterHz: rt.cfg.CenterHz, CenterHz: rt.cfg.CenterHz,
@@ -284,7 +293,7 @@ func (rt *dspRuntime) refineSignals(art *spectrumArtifacts, input pipeline.Refin
centerHz = rt.cfg.CenterHz centerHz = rt.cfg.CenterHz
} }
snips, snipRates := extractSignalIQBatch(extractMgr, art.iq, sampleRate, centerHz, selectedSignals) snips, snipRates := extractSignalIQBatch(extractMgr, art.iq, sampleRate, centerHz, selectedSignals)
refined := pipeline.RefineCandidates(selectedCandidates, art.spectrum, sampleRate, fftSize, snips, snipRates, classifier.ClassifierMode(rt.cfg.ClassifierMode))
refined := pipeline.RefineCandidates(selectedCandidates, input.Windows, art.spectrum, sampleRate, fftSize, snips, snipRates, classifier.ClassifierMode(rt.cfg.ClassifierMode))
signals := make([]detector.Signal, 0, len(refined)) signals := make([]detector.Signal, 0, len(refined))
decisions := make([]pipeline.SignalDecision, 0, len(refined)) decisions := make([]pipeline.SignalDecision, 0, len(refined))
for i, ref := range refined { for i, ref := range refined {


+ 1
- 0
internal/pipeline/phases.go Voir le fichier

@@ -24,6 +24,7 @@ type RefinementInput struct {
Candidates []Candidate `json:"candidates,omitempty"` Candidates []Candidate `json:"candidates,omitempty"`
Scheduled []ScheduledCandidate `json:"scheduled,omitempty"` Scheduled []ScheduledCandidate `json:"scheduled,omitempty"`
Plan RefinementPlan `json:"plan,omitempty"` Plan RefinementPlan `json:"plan,omitempty"`
Windows []RefinementWindow `json:"windows,omitempty"`
SampleRate int `json:"sample_rate"` SampleRate int `json:"sample_rate"`
FFTSize int `json:"fft_size"` FFTSize int `json:"fft_size"`
CenterHz float64 `json:"center_hz"` CenterHz float64 `json:"center_hz"`


+ 6
- 1
internal/pipeline/refiner.go Voir le fichier

@@ -7,7 +7,7 @@ import (


// RefineCandidates upgrades coarse detector candidates into refined signals // RefineCandidates upgrades coarse detector candidates into refined signals
// by attaching local IQ-derived classification and PLL metadata. // by attaching local IQ-derived classification and PLL metadata.
func RefineCandidates(candidates []Candidate, spectrum []float64, sampleRate int, fftSize int, snippets [][]complex64, snippetRates []int, mode classifier.ClassifierMode) []Refinement {
func RefineCandidates(candidates []Candidate, windows []RefinementWindow, spectrum []float64, sampleRate int, fftSize int, snippets [][]complex64, snippetRates []int, mode classifier.ClassifierMode) []Refinement {
out := make([]Refinement, 0, len(candidates)) out := make([]Refinement, 0, len(candidates))
for i, c := range candidates { for i, c := range candidates {
sig := detector.Signal{ sig := detector.Signal{
@@ -44,8 +44,13 @@ func RefineCandidates(candidates []Candidate, spectrum []float64, sampleRate int
cls.ModType = classifier.ClassWFMStereo cls.ModType = classifier.ClassWFMStereo
} }
} }
var window RefinementWindow
if i < len(windows) {
window = windows[i]
}
out = append(out, Refinement{ out = append(out, Refinement{
Candidate: c, Candidate: c,
Window: window,
Signal: sig, Signal: sig,
SnippetRate: snipRate, SnippetRate: snipRate,
Class: cls, Class: cls,


+ 23
- 15
internal/pipeline/types.go Voir le fichier

@@ -8,25 +8,33 @@ import (
// Candidate is the coarse output of the surveillance detector. // Candidate is the coarse output of the surveillance detector.
// It intentionally stays lightweight and cheap to produce. // It intentionally stays lightweight and cheap to produce.
type Candidate struct { type Candidate struct {
ID int64 `json:"id"`
CenterHz float64 `json:"center_hz"`
BandwidthHz float64 `json:"bandwidth_hz"`
PeakDb float64 `json:"peak_db"`
SNRDb float64 `json:"snr_db"`
FirstBin int `json:"first_bin"`
LastBin int `json:"last_bin"`
NoiseDb float64 `json:"noise_db,omitempty"`
Source string `json:"source,omitempty"`
Hint string `json:"hint,omitempty"`
ID int64 `json:"id"`
CenterHz float64 `json:"center_hz"`
BandwidthHz float64 `json:"bandwidth_hz"`
PeakDb float64 `json:"peak_db"`
SNRDb float64 `json:"snr_db"`
FirstBin int `json:"first_bin"`
LastBin int `json:"last_bin"`
NoiseDb float64 `json:"noise_db,omitempty"`
Source string `json:"source,omitempty"`
Hint string `json:"hint,omitempty"`
}

// RefinementWindow describes the local analysis span that refinement should use.
type RefinementWindow struct {
CenterHz float64 `json:"center_hz"`
SpanHz float64 `json:"span_hz"`
Source string `json:"source,omitempty"`
} }


// Refinement contains higher-cost local analysis derived from a candidate. // Refinement contains higher-cost local analysis derived from a candidate.
type Refinement struct { type Refinement struct {
Candidate Candidate `json:"candidate"`
Signal detector.Signal `json:"signal"`
SnippetRate int `json:"snippet_rate"`
Class *classifier.Classification `json:"class,omitempty"`
Stage string `json:"stage,omitempty"`
Candidate Candidate `json:"candidate"`
Window RefinementWindow `json:"window"`
Signal detector.Signal `json:"signal"`
SnippetRate int `json:"snippet_rate"`
Class *classifier.Classification `json:"class,omitempty"`
Stage string `json:"stage,omitempty"`
} }


func CandidatesFromSignals(signals []detector.Signal, source string) []Candidate { func CandidatesFromSignals(signals []detector.Signal, source string) []Candidate {


Chargement…
Annuler
Enregistrer