Pārlūkot izejas kodu

feat: introduce explicit surveillance and refinement phase results

master
Jan Svabenik pirms 17 stundām
vecāks
revīzija
e33efb6c3d
6 mainītis faili ar 86 papildinājumiem un 7 dzēšanām
  1. +7
    -4
      cmd/sdrd/dsp_loop.go
  2. +8
    -0
      cmd/sdrd/phase_state.go
  3. +20
    -0
      cmd/sdrd/phase_state_test.go
  4. +18
    -3
      cmd/sdrd/pipeline_runtime.go
  5. +16
    -0
      internal/pipeline/phases.go
  6. +17
    -0
      internal/pipeline/phases_test.go

+ 7
- 4
cmd/sdrd/dsp_loop.go Parādīt failu

@@ -29,6 +29,7 @@ func runDSP(ctx context.Context, srcMgr *sourceManager, cfg config.Config, det *
defer logTicker.Stop()
enc := json.NewEncoder(eventFile)
dcBlocker := dsp.NewDCBlocker(0.995)
state := &phaseState{}
for {
select {
case <-ctx.Done():
@@ -55,12 +56,14 @@ func runDSP(ctx context.Context, srcMgr *sourceManager, cfg config.Config, det *
log.Printf("received IQ samples")
rt.gotSamples = true
}
finished := art.finished
thresholds := art.thresholds
noiseFloor := art.noiseFloor
state.surveillance = rt.buildSurveillanceResult(art)
finished := state.surveillance.Finished
thresholds := state.surveillance.Thresholds
noiseFloor := state.surveillance.NoiseFloor
var displaySignals []detector.Signal
if len(art.iq) > 0 {
displaySignals = rt.refineSignals(art, extractMgr, rec)
state.refinement = rt.refineSignals(art, extractMgr, rec)
displaySignals = state.refinement.Signals
if rec != nil && len(displaySignals) > 0 && len(art.allIQ) > 0 {
aqCfg := extractionConfig{firTaps: rt.cfg.Recorder.ExtractionTaps, bwMult: rt.cfg.Recorder.ExtractionBwMult}
streamSnips, streamRates := extractForStreaming(extractMgr, art.allIQ, rt.cfg.SampleRate, rt.cfg.CenterHz, displaySignals, rt.streamPhaseState, rt.streamOverlap, aqCfg)


+ 8
- 0
cmd/sdrd/phase_state.go Parādīt failu

@@ -0,0 +1,8 @@
package main

import "sdr-wideband-suite/internal/pipeline"

type phaseState struct {
surveillance pipeline.SurveillanceResult
refinement pipeline.RefinementResult
}

+ 20
- 0
cmd/sdrd/phase_state_test.go Parādīt failu

@@ -0,0 +1,20 @@
package main

import (
"testing"

"sdr-wideband-suite/internal/pipeline"
)

func TestPhaseStateCarriesPhaseResults(t *testing.T) {
ps := &phaseState{
surveillance: pipeline.SurveillanceResult{NoiseFloor: -90},
refinement: pipeline.RefinementResult{Decisions: []pipeline.SignalDecision{{ShouldRecord: true}}},
}
if ps.surveillance.NoiseFloor != -90 {
t.Fatalf("unexpected surveillance state: %+v", ps.surveillance)
}
if len(ps.refinement.Decisions) != 1 || !ps.refinement.Decisions[0].ShouldRecord {
t.Fatalf("unexpected refinement state: %+v", ps.refinement)
}
}

+ 18
- 3
cmd/sdrd/pipeline_runtime.go Parādīt failu

@@ -212,9 +212,22 @@ func (rt *dspRuntime) captureSpectrum(srcMgr *sourceManager, rec *recorder.Manag
}, nil
}

func (rt *dspRuntime) refineSignals(art *spectrumArtifacts, extractMgr *extractionManager, rec *recorder.Manager) []detector.Signal {
func (rt *dspRuntime) buildSurveillanceResult(art *spectrumArtifacts) pipeline.SurveillanceResult {
if art == nil {
return pipeline.SurveillanceResult{}
}
return pipeline.SurveillanceResult{
Candidates: pipeline.CandidatesFromSignals(art.detected, "surveillance-detector"),
Finished: art.finished,
Signals: art.detected,
NoiseFloor: art.noiseFloor,
Thresholds: art.thresholds,
}
}

func (rt *dspRuntime) refineSignals(art *spectrumArtifacts, extractMgr *extractionManager, rec *recorder.Manager) pipeline.RefinementResult {
if art == nil || len(art.iq) == 0 {
return nil
return pipeline.RefinementResult{}
}
policy := pipeline.PolicyFromConfig(rt.cfg)
candidates := pipeline.CandidatesFromSignals(art.detected, "surveillance-detector")
@@ -237,12 +250,14 @@ func (rt *dspRuntime) refineSignals(art *spectrumArtifacts, extractMgr *extracti
snips, snipRates := extractSignalIQBatch(extractMgr, art.iq, rt.cfg.SampleRate, rt.cfg.CenterHz, selectedSignals)
refined := pipeline.RefineCandidates(selectedCandidates, art.spectrum, rt.cfg.SampleRate, rt.cfg.FFTSize, snips, snipRates, classifier.ClassifierMode(rt.cfg.ClassifierMode))
signals := make([]detector.Signal, 0, len(refined))
decisions := make([]pipeline.SignalDecision, 0, len(refined))
for i, ref := range refined {
sig := ref.Signal
signals = append(signals, sig)
cls := sig.Class
snipRate := ref.SnippetRate
decision := pipeline.DecideSignalAction(policy, ref.Candidate, cls)
decisions = append(decisions, decision)
if decision.ShouldAutoDecode && rec != nil {
rt.cfg.Recorder.AutoDecode = true
}
@@ -265,7 +280,7 @@ func (rt *dspRuntime) refineSignals(art *spectrumArtifacts, extractMgr *extracti
}
}
rt.det.UpdateClasses(signals)
return signals
return pipeline.RefinementResult{Signals: signals, Decisions: decisions}
}

func (rt *dspRuntime) updateRDS(now time.Time, rec *recorder.Manager, sig *detector.Signal, cls *classifier.Classification) {


+ 16
- 0
internal/pipeline/phases.go Parādīt failu

@@ -0,0 +1,16 @@
package pipeline

import "sdr-wideband-suite/internal/detector"

type SurveillanceResult struct {
Candidates []Candidate `json:"candidates"`
Finished []detector.Event `json:"finished"`
Signals []detector.Signal `json:"signals"`
NoiseFloor float64 `json:"noise_floor"`
Thresholds []float64 `json:"thresholds,omitempty"`
}

type RefinementResult struct {
Signals []detector.Signal `json:"signals"`
Decisions []SignalDecision `json:"decisions,omitempty"`
}

+ 17
- 0
internal/pipeline/phases_test.go Parādīt failu

@@ -0,0 +1,17 @@
package pipeline

import (
"testing"

"sdr-wideband-suite/internal/detector"
)

func TestRefinementResultCarriesDecisions(t *testing.T) {
res := RefinementResult{
Signals: []detector.Signal{{ID: 1}},
Decisions: []SignalDecision{{ShouldRecord: true}},
}
if len(res.Signals) != 1 || len(res.Decisions) != 1 {
t.Fatalf("unexpected refinement result: %+v", res)
}
}

Notiek ielāde…
Atcelt
Saglabāt