|
- package cfar
-
- import "sort"
-
- type orderedStat struct {
- guard int
- train int
- rank int
- scaleDb float64
- wrapAround bool
- }
-
- func newOS(cfg Config) CFAR {
- rank := cfg.Rank - 1
- total := 2 * cfg.TrainCells
- if rank < 0 {
- rank = 0
- }
- if rank >= total {
- rank = total - 1
- }
- return &orderedStat{
- guard: cfg.GuardCells,
- train: cfg.TrainCells,
- rank: rank,
- scaleDb: cfg.ScaleDb,
- wrapAround: cfg.WrapAround,
- }
- }
-
- func (o *orderedStat) Thresholds(spectrum []float64) []float64 {
- n := len(spectrum)
- if n == 0 {
- return nil
- }
- out := make([]float64, n)
- train := o.train
- guard := o.guard
-
- at := func(i int) float64 {
- if o.wrapAround {
- return spectrum[((i%n)+n)%n]
- }
- if i < 0 || i >= n {
- return spectrum[clampInt(i, 0, n-1)]
- }
- return spectrum[i]
- }
-
- win := make([]float64, 0, 2*train)
- for k := 1; k <= train; k++ {
- win = append(win, at(0-guard-k))
- win = append(win, at(0+guard+k))
- }
- sort.Float64s(win)
- out[0] = win[o.rank] + o.scaleDb
-
- for i := 1; i < n; i++ {
- removeFromSorted(&win, at(i-1-guard-train))
- removeFromSorted(&win, at(i-1+guard+1))
-
- insertSorted(&win, at(i-guard-1))
- insertSorted(&win, at(i+guard+train))
-
- out[i] = win[o.rank] + o.scaleDb
- }
- return out
- }
-
- func insertSorted(s *[]float64, v float64) {
- idx := sort.SearchFloat64s(*s, v)
- *s = append(*s, 0)
- copy((*s)[idx+1:], (*s)[idx:])
- (*s)[idx] = v
- }
-
- func removeFromSorted(s *[]float64, v float64) {
- idx := sort.SearchFloat64s(*s, v)
- if idx < len(*s) && (*s)[idx] == v {
- *s = append((*s)[:idx], (*s)[idx+1:]...)
- return
- }
- for i := idx - 1; i >= 0; i-- {
- if (*s)[i] == v {
- *s = append((*s)[:i], (*s)[i+1:]...)
- return
- }
- if (*s)[i] < v {
- break
- }
- }
- for i := idx + 1; i < len(*s); i++ {
- if (*s)[i] == v {
- *s = append((*s)[:i], (*s)[i+1:]...)
- return
- }
- if (*s)[i] > v {
- break
- }
- }
- }
|