Spectrum markers peaks option

pull/1464/head
f4exb 2022-10-03 00:23:47 +02:00
rodzic 8a9662cf3f
commit 949a103b25
17 zmienionych plików z 241 dodań i 7 usunięć

Plik binarny nie jest wyświetlany.

Przed

Szerokość:  |  Wysokość:  |  Rozmiar: 18 KiB

Po

Szerokość:  |  Wysokość:  |  Rozmiar: 20 KiB

Plik binarny nie jest wyświetlany.

Plik binarny nie jest wyświetlany.

Przed

Szerokość:  |  Wysokość:  |  Rozmiar: 15 KiB

Po

Szerokość:  |  Wysokość:  |  Rozmiar: 17 KiB

Plik binarny nie jest wyświetlany.

Wyświetl plik

@ -192,6 +192,7 @@ set(sdrbase_SOURCES
util/morse.cpp
util/openaip.cpp
util/osndb.cpp
util/peakfinder.cpp
util/planespotters.cpp
util/png.cpp
util/prettyprint.cpp
@ -415,6 +416,7 @@ set(sdrbase_HEADERS
util/movingaverage.h
util/openaip.h
util/osndb.h
util/peakfinder.h
util/planespotters.h
util/png.h
util/prettyprint.h

Wyświetl plik

@ -78,6 +78,7 @@ void SpectrumSettings::resetToDefaults()
m_measurementHighlight = true;
m_measurementsPosition = PositionBelow;
m_measurementPrecision = 1;
m_findHistogramPeaks = false;
}
QByteArray SpectrumSettings::serialize() const
@ -128,6 +129,7 @@ QByteArray SpectrumSettings::serialize() const
s.writeS32(44, (int)m_measurementsPosition);
s.writeS32(45, m_measurementPrecision);
s.writeS32(46, m_measurementCenterFrequencyOffset);
s.writeBool(47, m_findHistogramPeaks);
s.writeS32(100, m_histogramMarkers.size());
for (int i = 0; i < m_histogramMarkers.size(); i++) {
@ -239,6 +241,7 @@ bool SpectrumSettings::deserialize(const QByteArray& data)
d.readS32(44, (int*)&m_measurementsPosition, (int)PositionBelow);
d.readS32(45, &m_measurementPrecision, 1);
d.readS32(46, &m_measurementCenterFrequencyOffset, 0);
d.readBool(47, &m_findHistogramPeaks, false);
int histogramMarkersSize;
d.readS32(100, &histogramMarkersSize, 0);

Wyświetl plik

@ -117,6 +117,7 @@ public:
QList<SpectrumHistogramMarker> m_histogramMarkers;
QList<SpectrumWaterfallMarker> m_waterfallMarkers;
QList<SpectrumAnnotationMarker> m_annoationMarkers;
bool m_findHistogramPeaks;
MarkersDisplay m_markersDisplay;
QList<SpectrumCalibrationPoint> m_calibrationPoints;
bool m_useCalibration;
@ -149,6 +150,7 @@ public:
QList<SpectrumHistogramMarker>& getHistogramMarkers() { return m_histogramMarkers; }
QList<SpectrumWaterfallMarker>& getWaterfallMarkers() { return m_waterfallMarkers; }
bool getHistogramFindPeaks() { return m_findHistogramPeaks; }
static int getAveragingMaxScale(AveragingMode averagingMode); //!< Max power of 10 multiplier to 2,5,10 base ex: 2 -> 2,5,10,20,50,100,200,500,1000
static int getAveragingValue(int averagingIndex, AveragingMode averagingMode);

Wyświetl plik

@ -0,0 +1,55 @@
///////////////////////////////////////////////////////////////////////////////////
// Copyright (C) 2022 F4EXB //
// written by Edouard Griffiths //
// //
// Find peaks in a series of real values //
// //
// This program is free software; you can redistribute it and/or modify //
// it under the terms of the GNU General Public License as published by //
// the Free Software Foundation as version 3 of the License, or //
// (at your option) any later version. //
// //
// This program is distributed in the hope that it will be useful, //
// but WITHOUT ANY WARRANTY; without even the implied warranty of //
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the //
// GNU General Public License V3 for more details. //
// //
// You should have received a copy of the GNU General Public License //
// along with this program. If not, see <http://www.gnu.org/licenses/>. //
///////////////////////////////////////////////////////////////////////////////////
#include "peakfinder.h"
PeakFinder::PeakFinder() :
m_prevValue(0.0),
m_index(0)
{}
PeakFinder::~PeakFinder()
{}
void PeakFinder::init(Real value)
{
m_prevValue = value;
m_peaks.clear();
m_index = 0;
}
void PeakFinder::push(Real value, bool last)
{
Real diff = value - m_prevValue;
if (diff < 0) {
m_peaks.push_back({m_prevValue, m_index});
} else if (last) {
m_peaks.push_back({value, m_index});
}
m_prevValue = value;
m_index++;
}
void PeakFinder::sortPeaks()
{
std::sort(m_peaks.rbegin(), m_peaks.rend()); // descending order of values
}

Wyświetl plik

@ -0,0 +1,48 @@
///////////////////////////////////////////////////////////////////////////////////
// Copyright (C) 2022 F4EXB //
// written by Edouard Griffiths //
// //
// Find peaks in a series of real values //
// //
// This program is free software; you can redistribute it and/or modify //
// it under the terms of the GNU General Public License as published by //
// the Free Software Foundation as version 3 of the License, or //
// (at your option) any later version. //
// //
// This program is distributed in the hope that it will be useful, //
// but WITHOUT ANY WARRANTY; without even the implied warranty of //
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the //
// GNU General Public License V3 for more details. //
// //
// You should have received a copy of the GNU General Public License //
// along with this program. If not, see <http://www.gnu.org/licenses/>. //
///////////////////////////////////////////////////////////////////////////////////
#ifndef SDRBASE_UTIL_PEAKFINDER_H_
#define SDRBASE_UTIL_PEAKFINDER_H_
#include <vector>
#include <utility>
#include "dsp/dsptypes.h"
#include "export.h"
class SDRBASE_API PeakFinder {
public:
PeakFinder();
~PeakFinder();
void init(Real value);
void push(Real value, bool last=false);
void sortPeaks();
const std::vector<std::pair<Real, int>>& getPeaks() { return m_peaks; }
private:
Real m_prevValue;
int m_index;
std::vector<std::pair<Real, int>> m_peaks; //!< index, value
};
#endif // SDRBASE_UTIL_PEAKFINDER_H_

Wyświetl plik

@ -95,6 +95,8 @@ public:
void updateMarkersDisplay() { m_spectrum->updateMarkersDisplay(); }
void updateCalibrationPoints() { m_spectrum->updateCalibrationPoints(); }
SpectrumSettings::MarkersDisplay& getMarkersDisplay() { return m_spectrum->getMarkersDisplay(); }
bool& getHistogramFindPeaks() { return m_spectrum->getHistogramFindPeaks(); }
void setHistogramFindPeaks(bool value) { m_spectrum->setHistogramFindPeaks(value); }
void setMarkersDisplay(SpectrumSettings::MarkersDisplay markersDisplay) { m_spectrum->setMarkersDisplay(markersDisplay); }
QList<SpectrumCalibrationPoint>& getCalibrationPoints() { return m_spectrum->getCalibrationPoints(); }
void setCalibrationPoints(const QList<SpectrumCalibrationPoint>& calibrationPoints) { m_spectrum->setCalibrationPoints(calibrationPoints); }

Wyświetl plik

@ -463,6 +463,7 @@ void GLSpectrumGUI::on_markers_clicked(bool checked)
m_glSpectrum->getWaterfallMarkers(),
m_glSpectrum->getAnnotationMarkers(),
m_glSpectrum->getMarkersDisplay(),
m_glSpectrum->getHistogramFindPeaks(),
m_calibrationShiftdB,
this
);

Wyświetl plik

@ -48,6 +48,7 @@ const float GLSpectrumView::m_annotationMarkerHeight = 20.0f;
GLSpectrumView::GLSpectrumView(QWidget* parent) :
QOpenGLWidget(parent),
m_markersDisplay(SpectrumSettings::MarkersDisplaySpectrum),
m_histogramFindPeaks(false),
m_cursorState(CSNormal),
m_cursorChannel(0),
m_spectrumVis(nullptr),
@ -1369,7 +1370,7 @@ void GLSpectrumView::paintGL()
}
// paint current spectrum line on top of histogram
if ((m_displayCurrent) && m_currentSpectrum)
if (m_displayCurrent && m_currentSpectrum)
{
Real bottom = -m_powerRange;
GLfloat *q3;
@ -1403,6 +1404,10 @@ void GLSpectrumView::paintGL()
}
{
if (m_histogramFindPeaks) {
m_peakFinder.init(m_currentSpectrum[0]);
}
// Draw line
q3 = m_q3FFT.m_array;
for (int i = 0; i < m_nbBins; i++)
@ -1418,6 +1423,9 @@ void GLSpectrumView::paintGL()
q3[2*i] = (Real) i;
q3[2*i+1] = v;
if (m_histogramFindPeaks && (i > 0)) {
m_peakFinder.push(m_currentSpectrum[i], i == m_nbBins - 1);
}
}
QVector4D color;
@ -1427,12 +1435,22 @@ void GLSpectrumView::paintGL()
color = QVector4D(1.0f, 1.0f, 0.25f, (float) m_displayTraceIntensity / 100.0f);
}
m_glShaderSimple.drawPolyline(m_glHistogramSpectrumMatrix, color, q3, m_nbBins);
if (m_histogramFindPeaks) {
m_peakFinder.sortPeaks();
}
}
}
if (m_markersDisplay & SpectrumSettings::MarkersDisplaySpectrum) {
if (m_displayCurrent && m_currentSpectrum && (m_markersDisplay & SpectrumSettings::MarkersDisplaySpectrum))
{
if (m_histogramFindPeaks) {
updateHistogramPeaks();
}
drawSpectrumMarkers();
}
if (m_markersDisplay & SpectrumSettings::MarkersDisplayAnnotations) {
drawAnnotationMarkers();
}
@ -1724,7 +1742,7 @@ void GLSpectrumView::paintGL()
}
m_mutex.unlock();
}
} // paintGL
// Hightlight power band for SFDR
void GLSpectrumView::drawPowerBandMarkers(float max, float min, const QVector4D &color)
@ -3289,7 +3307,7 @@ void GLSpectrumView::updateHistogramMarkers()
if (i > 0)
{
int64_t deltaFrequency = m_histogramMarkers.at(i).m_frequency - m_histogramMarkers.at(0).m_frequency;
m_histogramMarkers.back().m_deltaFrequencyStr = displayScaled(
m_histogramMarkers[i].m_deltaFrequencyStr = displayScaled(
deltaFrequency,
'f',
getPrecision(deltaFrequency/m_sampleRate),
@ -3297,7 +3315,7 @@ void GLSpectrumView::updateHistogramMarkers()
float power0 = m_linear ?
m_histogramMarkers.at(0).m_power * (m_useCalibration ? m_calibrationGain : 1.0f) :
CalcDb::dbPower(m_histogramMarkers.at(0).m_power) + (m_useCalibration ? m_calibrationShiftdB : 0.0f);
m_histogramMarkers.back().m_deltaPowerStr = displayPower(
m_histogramMarkers[i].m_deltaPowerStr = displayPower(
powerI - power0,
m_linear ? 'e' : 'f',
m_linear ? 3 : 1);
@ -3305,6 +3323,57 @@ void GLSpectrumView::updateHistogramMarkers()
}
}
void GLSpectrumView::updateHistogramPeaks()
{
int j = 0;
for (int i = 0; i < m_histogramMarkers.size(); i++)
{
if (j >= (int) m_peakFinder.getPeaks().size()) {
break;
}
int fftBin = m_peakFinder.getPeaks()[j].second;
Real power = m_peakFinder.getPeaks()[j].first;
// qDebug("GLSpectrumView::updateHistogramPeaks: %d %d %f", j, fftBin, power);
if ((m_histogramMarkers.at(i).m_markerType == SpectrumHistogramMarker::SpectrumMarkerTypePower) ||
((m_histogramMarkers.at(i).m_markerType == SpectrumHistogramMarker::SpectrumMarkerTypePowerMax) &&
(m_histogramMarkers.at(i).m_holdReset || (power > m_histogramMarkers.at(i).m_powerMax))))
{
float binSize = m_frequencyScale.getRange() / m_nbBins;
m_histogramMarkers[i].m_fftBin = fftBin;
m_histogramMarkers[i].m_frequency = m_frequencyScale.getRangeMin() + binSize*fftBin;
m_histogramMarkers[i].m_point.rx() = binSize*fftBin / m_frequencyScale.getRange();
if (i == 0)
{
m_histogramMarkers[i].m_frequencyStr = displayScaled(
m_histogramMarkers[i].m_frequency,
'f',
getPrecision((m_centerFrequency*1000)/m_sampleRate),
false
);
}
else
{
int64_t deltaFrequency = m_histogramMarkers.at(i).m_frequency - m_histogramMarkers.at(0).m_frequency;
m_histogramMarkers[i].m_deltaFrequencyStr = displayScaled(
deltaFrequency,
'f',
getPrecision(deltaFrequency/m_sampleRate),
true
);
}
}
else
{
continue;
}
j++;
}
}
void GLSpectrumView::updateWaterfallMarkers()
{
for (int i = 0; i < m_waterfallMarkers.size(); i++)

Wyświetl plik

@ -43,6 +43,7 @@
#include "util/incrementalarray.h"
#include "util/message.h"
#include "util/colormap.h"
#include "util/peakfinder.h"
class QOpenGLShaderProgram;
class MessageQueue;
@ -214,11 +215,14 @@ public:
QList<SpectrumAnnotationMarker>& getAnnotationMarkers() { return m_annotationMarkers; }
void setAnnotationMarkers(const QList<SpectrumAnnotationMarker>& annotationMarkers);
void updateHistogramMarkers();
void updateHistogramPeaks();
void updateWaterfallMarkers();
void updateAnnotationMarkers();
void updateMarkersDisplay();
void updateCalibrationPoints();
SpectrumSettings::MarkersDisplay& getMarkersDisplay() { return m_markersDisplay; }
SpectrumSettings::MarkersDisplay& getMarkersDisplay() { return m_markersDisplay; }
bool& getHistogramFindPeaks() { return m_histogramFindPeaks; }
void setHistogramFindPeaks(bool value) { m_histogramFindPeaks = value; }
void setMarkersDisplay(SpectrumSettings::MarkersDisplay markersDisplay);
QList<SpectrumCalibrationPoint>& getCalibrationPoints() { return m_calibrationPoints; }
void setCalibrationPoints(const QList<SpectrumCalibrationPoint>& calibrationPoints);
@ -258,6 +262,8 @@ private:
QList<SpectrumAnnotationMarker*> m_sortedAnnotationMarkers;
QList<SpectrumAnnotationMarker*> m_visibleAnnotationMarkers;
SpectrumSettings::MarkersDisplay m_markersDisplay;
bool m_histogramFindPeaks;
PeakFinder m_peakFinder;
QList<SpectrumCalibrationPoint> m_calibrationPoints;
CursorState m_cursorState;

Wyświetl plik

@ -72,6 +72,11 @@ This combo lets you select the type of marker:
Use this slider to adjust the power position of the marker. The units are in dB irrespective of the linear or log set of the spectrum display.
<h3>11. Peak detection</h3>
Activates or de-activates peak detection. With peak detection engaged markers with type "Cur" or "Max" will be automatically set to frequency (bin) of maximum power. The first marker in index order with "Cur" or "Max" will be set to the highest peak in magnitude then next marker to next peak in magnitude order etc,,, Markers of type "Cur" will track current peaks and markers of type "Max" will track peak maxima making it more suitable for transient signals.
<h2>Waterfall markers tab</h2>
![Spectrum Markers waterfall dialog](../../doc/img/Spectrum_Markers_dialog_wat.png)

Wyświetl plik

@ -32,6 +32,7 @@ SpectrumMarkersDialog::SpectrumMarkersDialog(
QList<SpectrumWaterfallMarker>& waterfallMarkers,
QList<SpectrumAnnotationMarker>& annotationMarkers,
SpectrumSettings::MarkersDisplay& markersDisplay,
bool& findPeaks,
float calibrationShiftdB,
QWidget* parent) :
QDialog(parent),
@ -40,6 +41,7 @@ SpectrumMarkersDialog::SpectrumMarkersDialog(
m_waterfallMarkers(waterfallMarkers),
m_annotationMarkers(annotationMarkers),
m_markersDisplay(markersDisplay),
m_findPeaks(findPeaks),
m_calibrationShiftdB(calibrationShiftdB),
m_histogramMarkerIndex(0),
m_waterfallMarkerIndex(0),
@ -63,6 +65,7 @@ SpectrumMarkersDialog::SpectrumMarkersDialog(
ui->fixedPower->setColorMapper(ColorMapper::GrayYellow);
ui->fixedPower->setValueRange(false, 4, -2000, 400, 1);
ui->showSelect->setCurrentIndex((int) m_markersDisplay);
ui->findPeaks->setChecked(m_findPeaks);
displayHistogramMarker();
displayWaterfallMarker();
displayAnnotationMarker();
@ -94,8 +97,12 @@ void SpectrumMarkersDialog::displayHistogramMarker()
}
else
{
bool disableFreq = m_findPeaks && (
(m_histogramMarkers[m_histogramMarkerIndex].m_markerType == SpectrumHistogramMarker::SpectrumMarkerTypePower) ||
(m_histogramMarkers[m_histogramMarkerIndex].m_markerType == SpectrumHistogramMarker::SpectrumMarkerTypePowerMax)
);
ui->marker->setEnabled(true);
ui->markerFrequency->setEnabled(true);
ui->markerFrequency->setEnabled(!disableFreq);
ui->powerMode->setEnabled(true);
ui->fixedPower->setEnabled(true);
ui->showMarker->setEnabled(true);
@ -403,6 +410,12 @@ void SpectrumMarkersDialog::on_powerHoldReset_clicked()
m_histogramMarkers[m_histogramMarkerIndex].m_holdReset = true;
}
void SpectrumMarkersDialog::on_findPeaks_toggled(bool checked)
{
m_findPeaks = checked;
displayHistogramMarker();
}
void SpectrumMarkersDialog::on_wMarkerFrequency_changed(qint64 value)
{
if (m_waterfallMarkers.size() == 0) {

Wyświetl plik

@ -39,6 +39,7 @@ public:
QList<SpectrumWaterfallMarker>& waterfallMarkers,
QList<SpectrumAnnotationMarker>& annotationMarkers,
SpectrumSettings::MarkersDisplay& markersDisplay,
bool& findPeaks,
float calibrationShiftdB,
QWidget* parent = nullptr
);
@ -55,6 +56,7 @@ private:
QList<SpectrumWaterfallMarker>& m_waterfallMarkers;
QList<SpectrumAnnotationMarker>& m_annotationMarkers;
SpectrumSettings::MarkersDisplay& m_markersDisplay;
bool &m_findPeaks;
float m_calibrationShiftdB;
int m_histogramMarkerIndex;
int m_waterfallMarkerIndex;
@ -82,6 +84,7 @@ private slots:
void on_markerDel_clicked();
void on_powerMode_currentIndexChanged(int index);
void on_powerHoldReset_clicked();
void on_findPeaks_toggled(bool checked);
void on_wMarkerFrequency_changed(qint64 value);
void on_timeCoarse_valueChanged(int value);

Wyświetl plik

@ -498,6 +498,26 @@ Max - Marker will move according to the maximum power at the marker frequency</s
</property>
</spacer>
</item>
<item>
<widget class="ButtonSwitch" name="findPeaks">
<property name="maximumSize">
<size>
<width>24</width>
<height>24</height>
</size>
</property>
<property name="toolTip">
<string>Put markers in find peaks mode</string>
</property>
<property name="text">
<string/>
</property>
<property name="icon">
<iconset resource="../resources/res.qrc">
<normaloff>:/dsb.png</normaloff>:/dsb.png</iconset>
</property>
</widget>
</item>
</layout>
</item>
</layout>
@ -1799,6 +1819,11 @@ All - Show all markers</string>
<extends>QLabel</extends>
<header>gui/clickablelabel.h</header>
</customwidget>
<customwidget>
<class>ButtonSwitch</class>
<extends>QToolButton</extends>
<header>gui/buttonswitch.h</header>
</customwidget>
</customwidgets>
<tabstops>
<tabstop>buttonBox</tabstop>