mirror of
				https://github.com/f4exb/sdrangel.git
				synced 2025-11-04 05:30:32 -05:00 
			
		
		
		
	
		
			
				
	
	
		
			368 lines
		
	
	
		
			13 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			368 lines
		
	
	
		
			13 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
///////////////////////////////////////////////////////////////////////////////////
 | 
						|
// Copyright (C) 2022 F4EXB                                                      //
 | 
						|
// written by Edouard Griffiths                                                  //
 | 
						|
//                                                                               //
 | 
						|
// 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 <QFileDialog>
 | 
						|
#include <QFile>
 | 
						|
#include <QStandardPaths>
 | 
						|
 | 
						|
#include "util/db.h"
 | 
						|
#include "util/csv.h"
 | 
						|
#include "dsp/spectrummarkers.h"
 | 
						|
 | 
						|
#include "spectrumcalibrationpointsdialog.h"
 | 
						|
 | 
						|
#include "ui_spectrumcalibrationpointsdialog.h"
 | 
						|
 | 
						|
SpectrumCalibrationPointsDialog::SpectrumCalibrationPointsDialog(
 | 
						|
    QList<SpectrumCalibrationPoint>& calibrationPoints,
 | 
						|
    SpectrumSettings::CalibrationInterpolationMode& calibrationInterpMode,
 | 
						|
    const SpectrumHistogramMarker *markerZero,
 | 
						|
    QWidget* parent
 | 
						|
) :
 | 
						|
    QDialog(parent),
 | 
						|
    ui(new Ui::SpectrumCalibrationPointsDialog),
 | 
						|
    m_calibrationPoints(calibrationPoints),
 | 
						|
    m_calibrationInterpMode(calibrationInterpMode),
 | 
						|
    m_markerZero(markerZero),
 | 
						|
    m_calibrationPointIndex(0),
 | 
						|
    m_centerFrequency(0),
 | 
						|
    m_globalCorrection(0.0),
 | 
						|
    m_setElseCorrectGlobal(false)
 | 
						|
{
 | 
						|
    ui->setupUi(this);
 | 
						|
    ui->calibPointFrequency->setColorMapper(ColorMapper(ColorMapper::GrayGold));
 | 
						|
    ui->calibPointFrequency->setValueRange(false, 10, -9999999999L, 9999999999L);
 | 
						|
    ui->calibrationGlobalCorr->setColorMapper(ColorMapper(ColorMapper::GrayYellow));
 | 
						|
    ui->calibrationGlobalCorr->setValueRange(false, 5, -20000L, 4000L, 2);
 | 
						|
    ui->relativePower->setColorMapper(ColorMapper(ColorMapper::GrayYellow));
 | 
						|
    ui->relativePower->setValueRange(false, 5, -20000L, 4000L, 2);
 | 
						|
    ui->calibratedPower->setColorMapper(ColorMapper(ColorMapper::GrayYellow));
 | 
						|
    ui->calibratedPower->setValueRange(false, 5, -20000L, 4000L, 2);
 | 
						|
    ui->calibPoint->setMaximum(m_calibrationPoints.size() - 1);
 | 
						|
    ui->calibInterpMode->blockSignals(true);
 | 
						|
    ui->calibInterpMode->setCurrentIndex((int) m_calibrationInterpMode);
 | 
						|
    ui->calibInterpMode->blockSignals(false);
 | 
						|
    ui->calibrationGlobalCorr->setValue(m_globalCorrection * 100.0);
 | 
						|
    ui->corrOrSet->setText("Cor");
 | 
						|
    displayCalibrationPoint();
 | 
						|
}
 | 
						|
 | 
						|
SpectrumCalibrationPointsDialog::~SpectrumCalibrationPointsDialog()
 | 
						|
{}
 | 
						|
 | 
						|
void SpectrumCalibrationPointsDialog::displayCalibrationPoint()
 | 
						|
{
 | 
						|
    ui->calibPointFrequency->blockSignals(true);
 | 
						|
    ui->calibPoint->blockSignals(true);
 | 
						|
    ui->relativePower->blockSignals(true);
 | 
						|
    ui->calibratedPower->blockSignals(true);
 | 
						|
 | 
						|
    if (m_calibrationPoints.size() == 0)
 | 
						|
    {
 | 
						|
        ui->calibPoint->setEnabled(false);
 | 
						|
        ui->calibPointDel->setEnabled(false);
 | 
						|
        ui->relativePower->setEnabled(false);
 | 
						|
        ui->calibratedPower->setEnabled(false);
 | 
						|
        ui->calibPointFrequency->setEnabled(false);
 | 
						|
        ui->importMarkerZero->setEnabled(false);
 | 
						|
        ui->centerFrequency->setEnabled(false);
 | 
						|
    }
 | 
						|
    else
 | 
						|
    {
 | 
						|
        ui->calibPoint->setEnabled(true);
 | 
						|
        ui->calibPointDel->setEnabled(true);
 | 
						|
        ui->relativePower->setEnabled(true);
 | 
						|
        ui->calibratedPower->setEnabled(true);
 | 
						|
        ui->calibPointFrequency->setEnabled(true);
 | 
						|
        ui->importMarkerZero->setEnabled(true);
 | 
						|
        ui->centerFrequency->setEnabled(true);
 | 
						|
        ui->calibPoint->setValue(m_calibrationPointIndex);
 | 
						|
        ui->calibPointText->setText(tr("%1").arg(m_calibrationPointIndex));
 | 
						|
        double powerDB = CalcDb::dbPower(m_calibrationPoints[m_calibrationPointIndex].m_powerRelativeReference, 1e-20);
 | 
						|
        ui->relativePower->setValue(round(powerDB*100.0)); // fixed point 2 decimals
 | 
						|
        powerDB = CalcDb::dbPower(m_calibrationPoints[m_calibrationPointIndex].m_powerCalibratedReference, 1e-20);
 | 
						|
        ui->calibratedPower->setValue(round(powerDB*100.0)); // fixed point 2 decimals
 | 
						|
        ui->calibPointFrequency->setValue(m_calibrationPoints[m_calibrationPointIndex].m_frequency);
 | 
						|
    }
 | 
						|
 | 
						|
    ui->calibPointFrequency->blockSignals(false);
 | 
						|
    ui->calibPoint->blockSignals(false);
 | 
						|
    ui->relativePower->blockSignals(false);
 | 
						|
    ui->calibratedPower->blockSignals(false);
 | 
						|
}
 | 
						|
 | 
						|
void SpectrumCalibrationPointsDialog::on_calibPoint_valueChanged(int value)
 | 
						|
{
 | 
						|
    if (m_calibrationPoints.size() == 0) {
 | 
						|
        return;
 | 
						|
    }
 | 
						|
 | 
						|
    m_calibrationPointIndex = value;
 | 
						|
    displayCalibrationPoint();
 | 
						|
}
 | 
						|
 | 
						|
void SpectrumCalibrationPointsDialog::on_calibPointAdd_clicked()
 | 
						|
{
 | 
						|
    m_calibrationPoints.append(SpectrumCalibrationPoint());
 | 
						|
    m_calibrationPoints.back().m_frequency = m_centerFrequency;
 | 
						|
    m_calibrationPointIndex = m_calibrationPoints.size() - 1;
 | 
						|
    ui->calibPoint->setMaximum(m_calibrationPoints.size() - 1);
 | 
						|
    ui->calibPoint->setMinimum(0);
 | 
						|
    displayCalibrationPoint();
 | 
						|
}
 | 
						|
 | 
						|
void SpectrumCalibrationPointsDialog::on_calibPointDel_clicked()
 | 
						|
{
 | 
						|
    if (m_calibrationPoints.size() == 0) {
 | 
						|
        return;
 | 
						|
    }
 | 
						|
 | 
						|
    m_calibrationPoints.removeAt(m_calibrationPointIndex);
 | 
						|
    m_calibrationPointIndex = m_calibrationPointIndex < m_calibrationPoints.size() ?
 | 
						|
        m_calibrationPointIndex : m_calibrationPointIndex - 1;
 | 
						|
    ui->calibPoint->setMaximum(m_calibrationPoints.size() - 1);
 | 
						|
    ui->calibPoint->setMinimum(0);
 | 
						|
    displayCalibrationPoint();
 | 
						|
}
 | 
						|
 | 
						|
void SpectrumCalibrationPointsDialog::on_relativePower_changed(qint64 value)
 | 
						|
{
 | 
						|
    if (m_calibrationPoints.size() == 0) {
 | 
						|
        return;
 | 
						|
    }
 | 
						|
 | 
						|
    float powerDB = value / 100.0f;
 | 
						|
    m_calibrationPoints[m_calibrationPointIndex].m_powerRelativeReference = CalcDb::powerFromdB(powerDB);
 | 
						|
    emit updateCalibrationPoints();
 | 
						|
}
 | 
						|
 | 
						|
void SpectrumCalibrationPointsDialog::on_calibratedPower_changed(qint64 value)
 | 
						|
{
 | 
						|
    if (m_calibrationPoints.size() == 0) {
 | 
						|
        return;
 | 
						|
    }
 | 
						|
 | 
						|
    float powerDB = value / 100.0f;
 | 
						|
    m_calibrationPoints[m_calibrationPointIndex].m_powerCalibratedReference = CalcDb::powerFromdB(powerDB);
 | 
						|
    emit updateCalibrationPoints();
 | 
						|
}
 | 
						|
 | 
						|
void SpectrumCalibrationPointsDialog::on_calibPointFrequency_changed(qint64 value)
 | 
						|
{
 | 
						|
    if (m_calibrationPoints.size() == 0) {
 | 
						|
        return;
 | 
						|
    }
 | 
						|
 | 
						|
    m_calibrationPoints[m_calibrationPointIndex].m_frequency = value;
 | 
						|
    emit updateCalibrationPoints();
 | 
						|
}
 | 
						|
 | 
						|
void SpectrumCalibrationPointsDialog::on_calibPointDuplicate_clicked()
 | 
						|
{
 | 
						|
    if (m_calibrationPoints.size() == 0) {
 | 
						|
        return;
 | 
						|
    }
 | 
						|
 | 
						|
    m_calibrationPoints.push_back(SpectrumCalibrationPoint(m_calibrationPoints[m_calibrationPointIndex]));
 | 
						|
    ui->calibPoint->setMaximum(m_calibrationPoints.size() - 1);
 | 
						|
    ui->calibPoint->setMinimum(0);
 | 
						|
    m_calibrationPointIndex = m_calibrationPoints.size() - 1;
 | 
						|
    displayCalibrationPoint();
 | 
						|
}
 | 
						|
 | 
						|
void SpectrumCalibrationPointsDialog::on_calibPointsSort_clicked()
 | 
						|
{
 | 
						|
    if (m_calibrationPoints.size() == 0) {
 | 
						|
        return;
 | 
						|
    }
 | 
						|
 | 
						|
    std::sort(m_calibrationPoints.begin(), m_calibrationPoints.end(), calibrationPointsLessThan);
 | 
						|
    m_calibrationPointIndex = 0;
 | 
						|
    displayCalibrationPoint();
 | 
						|
}
 | 
						|
 | 
						|
void SpectrumCalibrationPointsDialog::on_importMarkerZero_clicked()
 | 
						|
{
 | 
						|
    if ((m_calibrationPoints.size() == 0) || (m_markerZero == nullptr)) {
 | 
						|
        return;
 | 
						|
    }
 | 
						|
 | 
						|
    m_calibrationPoints[m_calibrationPointIndex].m_frequency = m_markerZero->m_frequency;
 | 
						|
    m_calibrationPoints[m_calibrationPointIndex].m_powerRelativeReference = CalcDb::powerFromdB(m_markerZero->m_powerMax);
 | 
						|
    displayCalibrationPoint();
 | 
						|
    emit updateCalibrationPoints();
 | 
						|
}
 | 
						|
 | 
						|
void SpectrumCalibrationPointsDialog::on_centerFrequency_clicked()
 | 
						|
{
 | 
						|
    if (m_calibrationPoints.size() == 0) {
 | 
						|
        return;
 | 
						|
    }
 | 
						|
 | 
						|
    m_calibrationPoints[m_calibrationPointIndex].m_frequency = m_centerFrequency;
 | 
						|
    displayCalibrationPoint();
 | 
						|
    emit updateCalibrationPoints();
 | 
						|
}
 | 
						|
 | 
						|
void SpectrumCalibrationPointsDialog::on_calibInterpMode_currentIndexChanged(int index)
 | 
						|
{
 | 
						|
    m_calibrationInterpMode = (SpectrumSettings::CalibrationInterpolationMode) index;
 | 
						|
    emit updateCalibrationPoints();
 | 
						|
}
 | 
						|
 | 
						|
void SpectrumCalibrationPointsDialog::on_calibrationGlobalCorr_changed(qint64 value)
 | 
						|
{
 | 
						|
    m_globalCorrection = value / 100.0;
 | 
						|
}
 | 
						|
 | 
						|
void SpectrumCalibrationPointsDialog::on_corrOrSet_toggled(bool checked)
 | 
						|
{
 | 
						|
    if (checked) {
 | 
						|
        ui->corrOrSet->setText("Set");
 | 
						|
    } else {
 | 
						|
        ui->corrOrSet->setText("Cor");
 | 
						|
    }
 | 
						|
 | 
						|
    m_setElseCorrectGlobal = checked;
 | 
						|
}
 | 
						|
 | 
						|
void SpectrumCalibrationPointsDialog::on_globalRelativeCorrection_clicked()
 | 
						|
{
 | 
						|
    for (auto& calibrationPoint : m_calibrationPoints)
 | 
						|
    {
 | 
						|
        if (m_setElseCorrectGlobal) {
 | 
						|
            calibrationPoint.m_powerRelativeReference = CalcDb::powerFromdB(m_globalCorrection);
 | 
						|
        } else {
 | 
						|
            calibrationPoint.m_powerRelativeReference *= CalcDb::powerFromdB(m_globalCorrection);
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    displayCalibrationPoint();
 | 
						|
    emit updateCalibrationPoints();
 | 
						|
}
 | 
						|
 | 
						|
void SpectrumCalibrationPointsDialog::on_globalCalibratedCorrection_clicked()
 | 
						|
{
 | 
						|
    for (auto& calibrationPoint : m_calibrationPoints)
 | 
						|
    {
 | 
						|
        if (m_setElseCorrectGlobal) {
 | 
						|
            calibrationPoint.m_powerCalibratedReference = CalcDb::powerFromdB(m_globalCorrection);
 | 
						|
        } else {
 | 
						|
            calibrationPoint.m_powerCalibratedReference *= CalcDb::powerFromdB(m_globalCorrection);
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    displayCalibrationPoint();
 | 
						|
    emit updateCalibrationPoints();
 | 
						|
}
 | 
						|
 | 
						|
void SpectrumCalibrationPointsDialog::on_calibPointsExport_clicked()
 | 
						|
{
 | 
						|
    QFileDialog fileDialog(
 | 
						|
        nullptr,
 | 
						|
        "Select file to write calibration points to",
 | 
						|
        QStandardPaths::writableLocation(QStandardPaths::AppDataLocation),
 | 
						|
        "*.csv"
 | 
						|
    );
 | 
						|
    fileDialog.setAcceptMode(QFileDialog::AcceptSave);
 | 
						|
 | 
						|
    if (fileDialog.exec())
 | 
						|
    {
 | 
						|
        QStringList fileNames = fileDialog.selectedFiles();
 | 
						|
 | 
						|
        if (fileNames.size() > 0)
 | 
						|
        {
 | 
						|
            QFile file(fileNames[0]);
 | 
						|
 | 
						|
            if (file.open(QIODevice::WriteOnly | QIODevice::Text))
 | 
						|
            {
 | 
						|
                QTextStream stream;
 | 
						|
                stream.setDevice(&file);
 | 
						|
                stream << "Frequency,Relative,Calibrated\n";
 | 
						|
 | 
						|
                for (const auto &calibrationPint : m_calibrationPoints)
 | 
						|
                {
 | 
						|
 | 
						|
                    stream << calibrationPint.m_frequency << ","
 | 
						|
                        << CalcDb::dbPower(calibrationPint.m_powerRelativeReference, 1e-20) << ","
 | 
						|
                        << CalcDb::dbPower(calibrationPint.m_powerCalibratedReference, 1e-20) << "\n";
 | 
						|
                }
 | 
						|
 | 
						|
                stream.flush();
 | 
						|
                file.close();
 | 
						|
            }
 | 
						|
        }
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
void SpectrumCalibrationPointsDialog::on_calibPointsImport_clicked()
 | 
						|
{
 | 
						|
    QFileDialog fileDialog(
 | 
						|
        nullptr,
 | 
						|
        "Select .csv calibration points file to read",
 | 
						|
        QStandardPaths::writableLocation(QStandardPaths::AppDataLocation),
 | 
						|
        "*.csv"
 | 
						|
    );
 | 
						|
 | 
						|
    if (fileDialog.exec())
 | 
						|
    {
 | 
						|
        QStringList fileNames = fileDialog.selectedFiles();
 | 
						|
 | 
						|
        if (fileNames.size() > 0)
 | 
						|
        {
 | 
						|
            QFile file(fileNames[0]);
 | 
						|
 | 
						|
            if (file.open(QIODevice::ReadOnly | QIODevice::Text))
 | 
						|
            {
 | 
						|
 | 
						|
                QTextStream in(&file);
 | 
						|
                QString error;
 | 
						|
                QHash<QString, int> colIndexes = CSV::readHeader(
 | 
						|
                    in,
 | 
						|
                    {"Frequency", "Relative", "Calibrated"},
 | 
						|
                    error
 | 
						|
                );
 | 
						|
 | 
						|
                if (error.isEmpty())
 | 
						|
                {
 | 
						|
                    QStringList cols;
 | 
						|
                    int frequencyCol = colIndexes.value("Frequency");
 | 
						|
                    int referenceCol = colIndexes.value("Relative");
 | 
						|
                    int absoluteCol = colIndexes.value("Calibrated");
 | 
						|
 | 
						|
                    m_calibrationPoints.clear();
 | 
						|
 | 
						|
                    while (CSV::readRow(in, &cols))
 | 
						|
                    {
 | 
						|
                        m_calibrationPoints.push_back(SpectrumCalibrationPoint());
 | 
						|
                        m_calibrationPoints.back().m_frequency = cols[frequencyCol].toLongLong();
 | 
						|
                        m_calibrationPoints.back().m_powerRelativeReference = CalcDb::powerFromdB(cols[referenceCol].toFloat());
 | 
						|
                        m_calibrationPoints.back().m_powerCalibratedReference = CalcDb::powerFromdB(cols[absoluteCol].toFloat());
 | 
						|
                    }
 | 
						|
 | 
						|
                    m_calibrationPointIndex = 0;
 | 
						|
                    ui->calibPoint->setMaximum(m_calibrationPoints.size() - 1);
 | 
						|
                    ui->calibPoint->setMinimum(0);
 | 
						|
                    displayCalibrationPoint();
 | 
						|
                    emit updateCalibrationPoints();
 | 
						|
                }
 | 
						|
            }
 | 
						|
        }
 | 
						|
    }
 | 
						|
}
 |