2021-10-12 11:31:14 +01:00
///////////////////////////////////////////////////////////////////////////////////
// Copyright (C) 2016 Edouard Griffiths, F4EXB //
2024-02-16 16:31:12 +00:00
// Copyright (C) 2021-2024 Jon Beniston, M7RCE //
2021-10-12 11:31:14 +01:00
// //
// 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 <limits>
# include <numeric>
# include <algorithm>
# include <functional>
# include <ctype.h>
# include <QDockWidget>
# include <QMainWindow>
# include <QDebug>
# include <QMessageBox>
# include <QAction>
2024-06-10 14:01:57 +01:00
# include <QRegularExpression>
2021-10-12 11:31:14 +01:00
# include <QClipboard>
# include <QFileDialog>
# include <QImage>
# include <QTimer>
# include "radioastronomygui.h"
# include "device/deviceuiset.h"
# include "dsp/dspengine.h"
# include "dsp/dspcommands.h"
# include "ui_radioastronomygui.h"
# include "plugin/pluginapi.h"
# include "util/db.h"
# include "util/astronomy.h"
# include "util/interpolation.h"
# include "util/png.h"
# include "util/units.h"
# include "gui/basicchannelsettingsdialog.h"
# include "dsp/dspengine.h"
2022-09-26 12:46:52 +01:00
# include "gui/timedelegate.h"
# include "gui/decimaldelegate.h"
2022-12-20 10:31:15 +00:00
# include "gui/dialogpositioner.h"
2025-06-24 12:32:42 +01:00
# include "gui/crightclickenabler.h"
2021-10-12 11:31:14 +01:00
# include "channel/channelwebapiutils.h"
# include "maincore.h"
# include "feature/feature.h"
2023-08-26 14:40:13 +01:00
# include "webapi/webapiutils.h"
2021-10-12 11:31:14 +01:00
# include "radioastronomy.h"
# include "radioastronomysensordialog.h"
# include "radioastronomycalibrationdialog.h"
# include "SWGStarTrackerTarget.h"
# include "SWGStarTrackerDisplaySettings.h"
# include "SWGStarTrackerDisplayLoSSettings.h"
// Time value is in milliseconds - Displays hh:mm:ss or d hh:mm:ss
class TimeDeltaDelegate : public QStyledItemDelegate {
public :
2024-06-09 19:14:51 +02:00
TimeDeltaDelegate ( QObject * parent = nullptr ) :
QStyledItemDelegate ( parent ) { }
2021-10-12 11:31:14 +01:00
virtual QString displayText ( const QVariant & value , const QLocale & locale ) const override
{
( void ) locale ;
qint64 v = value . toLongLong ( ) ; // In milliseconds
bool neg = v < 0 ;
v = abs ( v ) ;
qint64 days = v / ( 1000 * 60 * 60 * 24 ) ;
v = v % ( 1000 * 60 * 60 * 24 ) ;
qint64 hours = v / ( 1000 * 60 * 60 ) ;
v = v % ( 1000 * 60 * 60 ) ;
qint64 minutes = v / ( 1000 * 60 ) ;
v = v % ( 1000 * 60 ) ;
qint64 seconds = v / ( 1000 ) ;
2021-10-12 12:10:12 +01:00
//qint64 msec = v % 1000;
2021-10-12 11:31:14 +01:00
if ( days > 0 ) {
return QString ( " %1%2 %3:%4:%5 " ) . arg ( neg ? " - " : " " ) . arg ( days ) . arg ( hours , 2 , 10 , QChar ( ' 0 ' ) ) . arg ( minutes , 2 , 10 , QChar ( ' 0 ' ) ) . arg ( seconds , 2 , 10 , QChar ( ' 0 ' ) ) ;
} else {
return QString ( " %1%2:%3:%4 " ) . arg ( neg ? " - " : " " ) . arg ( hours , 2 , 10 , QChar ( ' 0 ' ) ) . arg ( minutes , 2 , 10 , QChar ( ' 0 ' ) ) . arg ( seconds , 2 , 10 , QChar ( ' 0 ' ) ) ;
}
}
private :
QString m_format ;
} ;
// Delegate for table to display hours, minutes and seconds
class HMSDelegate : public QStyledItemDelegate {
public :
2024-06-09 19:14:51 +02:00
HMSDelegate ( QObject * parent = nullptr ) :
QStyledItemDelegate ( parent ) { }
2021-10-12 11:31:14 +01:00
virtual QString displayText ( const QVariant & value , const QLocale & locale ) const override
{
( void ) locale ;
return Units : : decimalHoursToHoursMinutesAndSeconds ( value . toDouble ( ) ) ;
}
} ;
// Delegate for table to display degrees, minutes and seconds
class DMSDelegate : public QStyledItemDelegate {
public :
2024-06-09 19:14:51 +02:00
DMSDelegate ( QObject * parent = nullptr ) :
QStyledItemDelegate ( parent ) { }
2021-10-12 11:31:14 +01:00
virtual QString displayText ( const QVariant & value , const QLocale & locale ) const override
{
( void ) locale ;
return Units : : decimalDegreesToDegreeMinutesAndSeconds ( value . toDouble ( ) ) ;
}
} ;
void RadioAstronomyGUI : : LABData : : read ( QFile * file , float l , float b )
{
m_l = l ;
m_b = b ;
m_vlsr . clear ( ) ;
m_temp . clear ( ) ;
QTextStream in ( file ) ;
while ( ! in . atEnd ( ) )
{
QString line = in . readLine ( ) . trimmed ( ) ;
if ( ! line . startsWith ( " % " ) & & ( line . size ( ) > 0 ) ) // Lines starting with % are comments
{
// 4 cols: v_lsr [km/s], T_B [K], freq. [Mhz], wavel. [cm]
2021-10-12 15:22:20 +01:00
line = line . simplified ( ) ;
QStringList cols = line . split ( " " ) ;
2021-10-12 11:31:14 +01:00
if ( cols . size ( ) = = 4 )
{
m_vlsr . append ( cols [ 0 ] . toFloat ( ) ) ;
m_temp . append ( cols [ 1 ] . toFloat ( ) ) ;
}
else
{
qDebug ( ) < < " RadioAstronomyGUI::parseLAB: Unexpected number of columns " ;
}
}
}
}
void RadioAstronomyGUI : : LABData : : toSeries ( QLineSeries * series )
{
series - > clear ( ) ;
series - > setName ( QString ( " LAB l=%1 b=%2 " ) . arg ( m_l ) . arg ( m_b ) ) ;
for ( int i = 0 ; i < m_vlsr . size ( ) ; i + + ) {
series - > append ( m_vlsr [ i ] , m_temp [ i ] ) ;
}
}
void RadioAstronomyGUI : : SensorMeasurements : : init ( const QString & name , bool visible )
{
m_series = new QLineSeries ( ) ;
m_series - > setName ( name ) ;
m_series - > setVisible ( visible ) ;
m_yAxis = new QValueAxis ( ) ;
m_yAxis - > setTitleText ( name ) ;
m_yAxis - > setVisible ( visible ) ;
m_min = std : : numeric_limits < double > : : max ( ) ;
m_max = - std : : numeric_limits < double > : : max ( ) ;
}
void RadioAstronomyGUI : : SensorMeasurements : : setName ( const QString & name )
{
if ( m_series ) {
m_series - > setName ( name ) ;
}
if ( m_yAxis ) {
m_yAxis - > setTitleText ( name ) ;
}
}
void RadioAstronomyGUI : : SensorMeasurements : : clicked ( bool checked )
{
if ( m_series ) {
m_series - > setVisible ( checked ) ;
}
if ( m_yAxis ) {
m_yAxis - > setVisible ( checked ) ;
}
}
void RadioAstronomyGUI : : SensorMeasurements : : append ( SensorMeasurement * measurement )
{
m_measurements . append ( measurement ) ;
addToSeries ( measurement ) ;
}
void RadioAstronomyGUI : : SensorMeasurements : : addToSeries ( SensorMeasurement * measurement )
{
m_series - > append ( measurement - > m_dateTime . toMSecsSinceEpoch ( ) , measurement - > m_value ) ;
m_max = std : : max ( m_max , measurement - > m_value ) ;
m_min = std : : min ( m_min , measurement - > m_value ) ;
if ( m_min = = m_max ) {
// Axis isn't drawn properly if min and max are the same
m_yAxis - > setRange ( m_min * 0.9 , m_max * 1.1 ) ;
} else {
m_yAxis - > setRange ( m_min , m_max ) ;
}
}
void RadioAstronomyGUI : : SensorMeasurements : : addAllToSeries ( )
{
for ( int i = 0 ; i < m_measurements . size ( ) ; i + + ) {
addToSeries ( m_measurements [ i ] ) ;
}
}
void RadioAstronomyGUI : : SensorMeasurements : : clear ( )
{
m_series - > clear ( ) ;
qDeleteAll ( m_measurements ) ;
m_measurements . clear ( ) ;
}
void RadioAstronomyGUI : : SensorMeasurements : : addToChart ( QChart * chart , QDateTimeAxis * xAxis )
{
chart - > addSeries ( m_series ) ;
m_series - > attachAxis ( xAxis ) ;
m_series - > attachAxis ( m_yAxis ) ;
}
void RadioAstronomyGUI : : SensorMeasurements : : setPen ( const QPen & pen )
{
m_series - > setPen ( pen ) ;
}
QValueAxis * RadioAstronomyGUI : : SensorMeasurements : : yAxis ( ) const
{
return m_yAxis ;
}
qreal RadioAstronomyGUI : : SensorMeasurements : : lastValue ( )
{
if ( m_measurements . size ( ) > 0 ) {
return m_measurements . last ( ) - > m_value ;
} else {
return 0.0 ;
}
}
void RadioAstronomyGUI : : resizePowerTable ( )
{
// Fill table with a row of dummy data that will size the columns nicely
// Trailing spaces are for sort arrow
int row = ui - > powerTable - > rowCount ( ) ;
ui - > powerTable - > setRowCount ( row + 1 ) ;
ui - > powerTable - > setItem ( row , POWER_COL_DATE , new QTableWidgetItem ( " 15/04/2016 " ) ) ;
ui - > powerTable - > setItem ( row , POWER_COL_TIME , new QTableWidgetItem ( " 10:17:00 " ) ) ;
ui - > powerTable - > setItem ( row , POWER_COL_POWER , new QTableWidgetItem ( " 1.235-e5 " ) ) ;
ui - > powerTable - > setItem ( row , POWER_COL_POWER_DB , new QTableWidgetItem ( " -100.0 " ) ) ;
ui - > powerTable - > setItem ( row , POWER_COL_POWER_DBM , new QTableWidgetItem ( " -100.0 " ) ) ;
ui - > powerTable - > setItem ( row , POWER_COL_TSYS , new QTableWidgetItem ( " 3000 " ) ) ;
ui - > powerTable - > setItem ( row , POWER_COL_TSYS0 , new QTableWidgetItem ( " 100 " ) ) ;
ui - > powerTable - > setItem ( row , POWER_COL_TSOURCE , new QTableWidgetItem ( " 300 " ) ) ;
ui - > powerTable - > setItem ( row , POWER_COL_TB , new QTableWidgetItem ( " 100000 " ) ) ;
ui - > powerTable - > setItem ( row , POWER_COL_TSKY , new QTableWidgetItem ( " 300 " ) ) ;
ui - > powerTable - > setItem ( row , POWER_COL_FLUX , new QTableWidgetItem ( " 100000.00 " ) ) ;
ui - > powerTable - > setItem ( row , POWER_COL_SIGMA_T , new QTableWidgetItem ( " 0.01 " ) ) ;
ui - > powerTable - > setItem ( row , POWER_COL_SIGMA_S , new QTableWidgetItem ( " 1000.0 " ) ) ;
ui - > powerTable - > setItem ( row , POWER_COL_OMEGA_A , new QTableWidgetItem ( " 0.000001 " ) ) ;
ui - > powerTable - > setItem ( row , POWER_COL_OMEGA_S , new QTableWidgetItem ( " 0.000001 " ) ) ;
ui - > powerTable - > setItem ( row , POWER_COL_RA , new QTableWidgetItem ( " 12h59m59.10s " ) ) ;
ui - > powerTable - > setItem ( row , POWER_COL_DEC , new QTableWidgetItem ( " -90d59 \' 59.00 \" " ) ) ;
ui - > powerTable - > setItem ( row , POWER_COL_GAL_LAT , new QTableWidgetItem ( " -90.0 " ) ) ;
ui - > powerTable - > setItem ( row , POWER_COL_GAL_LON , new QTableWidgetItem ( " 359.0 " ) ) ;
ui - > powerTable - > setItem ( row , POWER_COL_AZ , new QTableWidgetItem ( " 359.0 " ) ) ;
ui - > powerTable - > setItem ( row , POWER_COL_EL , new QTableWidgetItem ( " 90.0 " ) ) ;
ui - > powerTable - > setItem ( row , POWER_COL_VBCRS , new QTableWidgetItem ( " 10.0 " ) ) ;
ui - > powerTable - > setItem ( row , POWER_COL_VLSR , new QTableWidgetItem ( " 10.0 " ) ) ;
ui - > powerTable - > setItem ( row , POWER_COL_SOLAR_FLUX , new QTableWidgetItem ( " 60.0 " ) ) ;
ui - > powerTable - > setItem ( row , POWER_COL_AIR_TEMP , new QTableWidgetItem ( " 20.0 " ) ) ;
ui - > powerTable - > setItem ( row , POWER_COL_SENSOR_1 , new QTableWidgetItem ( " 1.0000000 " ) ) ;
ui - > powerTable - > setItem ( row , POWER_COL_SENSOR_2 , new QTableWidgetItem ( " 1.0000000 " ) ) ;
2023-03-29 19:20:05 +01:00
ui - > powerTable - > setItem ( row , POWER_COL_UTC , new QTableWidgetItem ( " 15/04/2016 10:17:00 " ) ) ;
2023-08-26 14:40:13 +01:00
ui - > powerTable - > setItem ( row , POWER_COL_ROT_AZ , new QTableWidgetItem ( " 359.0 " ) ) ;
ui - > powerTable - > setItem ( row , POWER_COL_ROT_EL , new QTableWidgetItem ( " -90.0 " ) ) ;
ui - > powerTable - > setItem ( row , POWER_COL_ROT_AZ_OFF , new QTableWidgetItem ( " -10.0 " ) ) ;
ui - > powerTable - > setItem ( row , POWER_COL_ROT_EL_OFF , new QTableWidgetItem ( " -10.0 " ) ) ;
2021-10-12 11:31:14 +01:00
ui - > powerTable - > resizeColumnsToContents ( ) ;
ui - > powerTable - > removeRow ( row ) ;
}
void RadioAstronomyGUI : : resizePowerMarkerTable ( )
{
// Fill table with a row of dummy data that will size the columns nicely
int row = ui - > powerMarkerTable - > rowCount ( ) ;
ui - > powerMarkerTable - > setRowCount ( row + 1 ) ;
ui - > powerMarkerTable - > setItem ( row , POWER_MARKER_COL_NAME , new QTableWidgetItem ( " Max " ) ) ;
ui - > powerMarkerTable - > setItem ( row , POWER_MARKER_COL_DATE , new QTableWidgetItem ( " 15/04/2016 " ) ) ;
ui - > powerMarkerTable - > setItem ( row , POWER_MARKER_COL_TIME , new QTableWidgetItem ( " 10:17:00 " ) ) ;
ui - > powerMarkerTable - > setItem ( row , POWER_MARKER_COL_VALUE , new QTableWidgetItem ( " 1000.0 " ) ) ;
ui - > powerMarkerTable - > setItem ( row , POWER_MARKER_COL_DELTA_X , new QTableWidgetItem ( " 1 23:59:59 " ) ) ;
ui - > powerMarkerTable - > setItem ( row , POWER_MARKER_COL_DELTA_Y , new QTableWidgetItem ( " 1000.0 " ) ) ;
ui - > powerMarkerTable - > setItem ( row , POWER_MARKER_COL_DELTA_TO , new QTableWidgetItem ( " Max " ) ) ;
ui - > powerMarkerTable - > resizeColumnsToContents ( ) ;
ui - > powerMarkerTable - > removeRow ( row ) ;
}
void RadioAstronomyGUI : : resizeSpectrumMarkerTable ( )
{
// Fill table with a row of dummy data that will size the columns nicely
int row = ui - > spectrumMarkerTable - > rowCount ( ) ;
ui - > spectrumMarkerTable - > setRowCount ( row + 1 ) ;
ui - > spectrumMarkerTable - > setItem ( row , SPECTRUM_MARKER_COL_NAME , new QTableWidgetItem ( " Max " ) ) ;
ui - > spectrumMarkerTable - > setItem ( row , SPECTRUM_MARKER_COL_FREQ , new QTableWidgetItem ( " 1420.405000 " ) ) ;
ui - > spectrumMarkerTable - > setItem ( row , SPECTRUM_MARKER_COL_VALUE , new QTableWidgetItem ( " 1000.0 " ) ) ;
ui - > spectrumMarkerTable - > setItem ( row , SPECTRUM_MARKER_COL_DELTA_X , new QTableWidgetItem ( " 1420.405000 " ) ) ;
ui - > spectrumMarkerTable - > setItem ( row , SPECTRUM_MARKER_COL_DELTA_Y , new QTableWidgetItem ( " 1000.0 " ) ) ;
ui - > spectrumMarkerTable - > setItem ( row , SPECTRUM_MARKER_COL_DELTA_TO , new QTableWidgetItem ( " M1 " ) ) ;
ui - > spectrumMarkerTable - > setItem ( row , SPECTRUM_MARKER_COL_VR , new QTableWidgetItem ( " -100.0 " ) ) ;
ui - > spectrumMarkerTable - > setItem ( row , SPECTRUM_MARKER_COL_R , new QTableWidgetItem ( " 10.0 " ) ) ;
ui - > spectrumMarkerTable - > setItem ( row , SPECTRUM_MARKER_COL_D , new QTableWidgetItem ( " 10.0/10.0 " ) ) ;
QTableWidgetItem * check = new QTableWidgetItem ( ) ;
check - > setFlags ( Qt : : ItemIsUserCheckable ) ;
ui - > spectrumMarkerTable - > setItem ( row , SPECTRUM_MARKER_COL_PLOT_MAX , check ) ;
ui - > spectrumMarkerTable - > setItem ( row , SPECTRUM_MARKER_COL_R_MIN , new QTableWidgetItem ( " 10.0 " ) ) ;
ui - > spectrumMarkerTable - > setItem ( row , SPECTRUM_MARKER_COL_V , new QTableWidgetItem ( " 250.0 " ) ) ;
ui - > spectrumMarkerTable - > resizeColumnsToContents ( ) ;
ui - > spectrumMarkerTable - > removeRow ( row ) ;
}
void RadioAstronomyGUI : : calcSpectrumMarkerDelta ( )
{
if ( m_spectrumM1Valid & & m_spectrumM2Valid )
{
qreal dx = m_spectrumM2X - m_spectrumM1X ;
qreal dy = m_spectrumM2Y - m_spectrumM1Y ;
ui - > spectrumMarkerTable - > item ( SPECTRUM_MARKER_ROW_M2 , SPECTRUM_MARKER_COL_DELTA_X ) - > setData ( Qt : : DisplayRole , dx ) ;
ui - > spectrumMarkerTable - > item ( SPECTRUM_MARKER_ROW_M2 , SPECTRUM_MARKER_COL_DELTA_Y ) - > setData ( Qt : : DisplayRole , dy ) ;
ui - > spectrumMarkerTable - > item ( SPECTRUM_MARKER_ROW_M2 , SPECTRUM_MARKER_COL_DELTA_TO ) - > setData ( Qt : : DisplayRole , " M1 " ) ;
}
}
void RadioAstronomyGUI : : calcPowerMarkerDelta ( )
{
if ( m_powerM1Valid & & m_powerM2Valid )
{
qreal dx = m_powerM2X - m_powerM1X ;
qreal dy = m_powerM2Y - m_powerM1Y ;
ui - > powerMarkerTable - > item ( POWER_MARKER_ROW_M2 , POWER_MARKER_COL_DELTA_X ) - > setData ( Qt : : DisplayRole , dx ) ;
ui - > powerMarkerTable - > item ( POWER_MARKER_ROW_M2 , POWER_MARKER_COL_DELTA_Y ) - > setData ( Qt : : DisplayRole , dy ) ;
ui - > powerMarkerTable - > item ( POWER_MARKER_ROW_M2 , POWER_MARKER_COL_DELTA_TO ) - > setData ( Qt : : DisplayRole , " M1 " ) ;
}
}
void RadioAstronomyGUI : : calcPowerPeakDelta ( )
{
qreal dx = m_powerMaxX - m_powerMinX ;
qreal dy = m_powerMaxY - m_powerMinY ;
ui - > powerMarkerTable - > item ( POWER_MARKER_ROW_PEAK_MIN , POWER_MARKER_COL_DELTA_X ) - > setData ( Qt : : DisplayRole , dx ) ;
ui - > powerMarkerTable - > item ( POWER_MARKER_ROW_PEAK_MIN , POWER_MARKER_COL_DELTA_Y ) - > setData ( Qt : : DisplayRole , dy ) ;
ui - > powerMarkerTable - > item ( POWER_MARKER_ROW_PEAK_MIN , POWER_MARKER_COL_DELTA_TO ) - > setData ( Qt : : DisplayRole , " Max " ) ;
}
void RadioAstronomyGUI : : addToPowerSeries ( FFTMeasurement * fft , bool skipCalcs )
{
if ( ( ( m_settings . m_powerYUnits = = RadioAstronomySettings : : PY_DBFS ) | | fft - > m_temp ) // Only dBFS valid if no temp was calculated
& & ! ( ( m_settings . m_powerYUnits = = RadioAstronomySettings : : PY_DBM ) & & ( fft - > m_tSys = = 0.0f ) ) // dBm value not valid if temp is 0
)
{
2024-09-03 18:38:32 +03:00
qreal power = 0.0 ;
2021-10-12 11:31:14 +01:00
switch ( m_settings . m_powerYData )
{
case RadioAstronomySettings : : PY_POWER :
switch ( m_settings . m_powerYUnits )
{
case RadioAstronomySettings : : PY_DBFS :
power = fft - > m_totalPowerdBFS ;
break ;
case RadioAstronomySettings : : PY_DBM :
power = fft - > m_totalPowerdBm ;
break ;
case RadioAstronomySettings : : PY_WATTS :
power = fft - > m_totalPowerWatts ;
break ;
2021-10-12 12:10:12 +01:00
default :
break ;
2021-10-12 11:31:14 +01:00
}
break ;
case RadioAstronomySettings : : PY_TSYS :
power = fft - > m_tSys ;
break ;
case RadioAstronomySettings : : PY_TSOURCE :
power = fft - > m_tSource ;
break ;
case RadioAstronomySettings : : PY_FLUX :
switch ( m_settings . m_powerYUnits )
{
case RadioAstronomySettings : : PY_SFU :
power = Units : : wattsPerMetrePerHertzToSolarFluxUnits ( fft - > m_flux ) ;
break ;
case RadioAstronomySettings : : PY_JANSKY :
power = Units : : wattsPerMetrePerHertzToJansky ( fft - > m_flux ) ;
break ;
2021-10-12 12:10:12 +01:00
default :
break ;
2021-10-12 11:31:14 +01:00
}
break ;
2021-10-12 12:10:12 +01:00
default :
break ;
2021-10-12 11:31:14 +01:00
}
QDateTime dateTime = fft - > m_dateTime ;
if ( m_powerSeries - > count ( ) = = 0 )
{
m_powerMin = power ;
m_powerMax = power ;
}
else
{
m_powerMin = std : : min ( power , m_powerMin ) ;
m_powerMax = std : : max ( power , m_powerMax ) ;
}
m_powerSeries - > append ( dateTime . toMSecsSinceEpoch ( ) , power ) ;
2022-09-26 12:46:52 +01:00
addToPowerFilter ( dateTime . toMSecsSinceEpoch ( ) , power ) ;
2021-10-12 11:31:14 +01:00
if ( ! skipCalcs )
{
if ( m_settings . m_powerAutoscale )
{
blockApplySettings ( true ) ;
2021-10-12 13:38:37 +01:00
powerAutoscaleY ( false ) ;
2021-10-12 11:31:14 +01:00
blockApplySettings ( false ) ;
}
}
2021-10-12 12:10:12 +01:00
if ( m_settings . m_powerYUnits = = RadioAstronomySettings : : PY_KELVIN ) {
2021-10-12 11:31:14 +01:00
m_powerTsys0Series - > append ( dateTime . toMSecsSinceEpoch ( ) , fft - > m_tSys0 ) ;
2021-10-12 12:10:12 +01:00
} else if ( m_settings . m_powerYUnits = = RadioAstronomySettings : : PY_DBM ) {
2021-10-12 11:31:14 +01:00
m_powerTsys0Series - > append ( dateTime . toMSecsSinceEpoch ( ) , Astronomy : : noisePowerdBm ( fft - > m_tSys0 , fft - > m_sampleRate ) ) ;
2021-10-12 12:10:12 +01:00
} else if ( m_settings . m_powerYUnits = = RadioAstronomySettings : : PY_WATTS ) {
2021-10-12 11:31:14 +01:00
m_powerTsys0Series - > append ( dateTime . toMSecsSinceEpoch ( ) , Astronomy : : m_boltzmann * fft - > m_tSys0 * fft - > m_sampleRate ) ;
}
if ( ! m_powerPeakValid )
{
m_powerPeakValid = true ;
m_powerMinY = power ;
m_powerMinX = dateTime . toMSecsSinceEpoch ( ) ;
m_powerMaxY = power ;
m_powerMaxX = dateTime . toMSecsSinceEpoch ( ) ;
m_powerPeakSeries - > clear ( ) ;
m_powerPeakSeries - > append ( m_powerMaxX , m_powerMaxY ) ;
m_powerPeakSeries - > append ( m_powerMaxX , m_powerMaxY ) ;
QDateTime dt = QDateTime : : fromMSecsSinceEpoch ( m_powerMaxX ) ;
if ( ! skipCalcs )
{
ui - > powerMarkerTable - > item ( POWER_MARKER_ROW_PEAK_MAX , POWER_MARKER_COL_DATE ) - > setData ( Qt : : DisplayRole , dt . date ( ) ) ;
ui - > powerMarkerTable - > item ( POWER_MARKER_ROW_PEAK_MAX , POWER_MARKER_COL_TIME ) - > setData ( Qt : : DisplayRole , dt . time ( ) ) ;
ui - > powerMarkerTable - > item ( POWER_MARKER_ROW_PEAK_MAX , POWER_MARKER_COL_VALUE ) - > setData ( Qt : : DisplayRole , m_powerMaxY ) ;
ui - > powerMarkerTable - > item ( POWER_MARKER_ROW_PEAK_MIN , POWER_MARKER_COL_DATE ) - > setData ( Qt : : DisplayRole , dt . date ( ) ) ;
ui - > powerMarkerTable - > item ( POWER_MARKER_ROW_PEAK_MIN , POWER_MARKER_COL_TIME ) - > setData ( Qt : : DisplayRole , dt . time ( ) ) ;
ui - > powerMarkerTable - > item ( POWER_MARKER_ROW_PEAK_MIN , POWER_MARKER_COL_VALUE ) - > setData ( Qt : : DisplayRole , m_powerMinY ) ;
ui - > powerMarkerTable - > item ( POWER_MARKER_ROW_PEAK_MIN , POWER_MARKER_COL_DELTA_X ) - > setData ( Qt : : DisplayRole , 0.0 ) ;
ui - > powerMarkerTable - > item ( POWER_MARKER_ROW_PEAK_MIN , POWER_MARKER_COL_DELTA_Y ) - > setData ( Qt : : DisplayRole , 0.0 ) ;
ui - > powerMarkerTable - > item ( POWER_MARKER_ROW_PEAK_MIN , POWER_MARKER_COL_DELTA_TO ) - > setData ( Qt : : DisplayRole , " Max " ) ;
}
}
if ( power > m_powerMaxY )
{
m_powerMaxY = power ;
m_powerMaxX = dateTime . toMSecsSinceEpoch ( ) ;
m_powerPeakSeries - > replace ( 0 , m_powerMaxX , m_powerMaxY ) ;
QDateTime dt = QDateTime : : fromMSecsSinceEpoch ( m_powerMaxX ) ;
ui - > powerMarkerTable - > item ( POWER_MARKER_ROW_PEAK_MAX , POWER_MARKER_COL_DATE ) - > setData ( Qt : : DisplayRole , dt . date ( ) ) ;
ui - > powerMarkerTable - > item ( POWER_MARKER_ROW_PEAK_MAX , POWER_MARKER_COL_TIME ) - > setData ( Qt : : DisplayRole , dt . time ( ) ) ;
ui - > powerMarkerTable - > item ( POWER_MARKER_ROW_PEAK_MAX , POWER_MARKER_COL_VALUE ) - > setData ( Qt : : DisplayRole , m_powerMaxY ) ;
calcPowerPeakDelta ( ) ;
}
else if ( power < m_powerMinY )
{
m_powerMinY = power ;
m_powerMinX = dateTime . toMSecsSinceEpoch ( ) ;
m_powerPeakSeries - > replace ( 1 , m_powerMinX , m_powerMinY ) ;
QDateTime dt = QDateTime : : fromMSecsSinceEpoch ( m_powerMinX ) ;
ui - > powerMarkerTable - > item ( POWER_MARKER_ROW_PEAK_MIN , POWER_MARKER_COL_DATE ) - > setData ( Qt : : DisplayRole , dt . date ( ) ) ;
ui - > powerMarkerTable - > item ( POWER_MARKER_ROW_PEAK_MIN , POWER_MARKER_COL_TIME ) - > setData ( Qt : : DisplayRole , dt . time ( ) ) ;
ui - > powerMarkerTable - > item ( POWER_MARKER_ROW_PEAK_MIN , POWER_MARKER_COL_VALUE ) - > setData ( Qt : : DisplayRole , m_powerMinY ) ;
calcPowerPeakDelta ( ) ;
}
// Update markers (E.g. if scale changes)
int c = m_powerSeries - > count ( ) ;
if ( c > = 2 )
{
QPointF p1 = m_powerSeries - > at ( c - 2 ) ;
QPointF p2 = m_powerSeries - > at ( c - 1 ) ;
if ( m_powerM1Valid & & ( m_powerM1X > = p1 . x ( ) ) & & ( m_powerM1X < p2 . x ( ) ) )
{
m_powerM1Y = Interpolation : : interpolate ( p1 . x ( ) , p1 . y ( ) , p2 . x ( ) , p2 . y ( ) , m_powerM1X ) ;
m_powerMarkerSeries - > insert ( 0 , QPointF ( dateTime . toMSecsSinceEpoch ( ) , m_powerM1Y ) ) ;
ui - > powerMarkerTable - > item ( POWER_MARKER_ROW_M1 , POWER_MARKER_COL_VALUE ) - > setData ( Qt : : DisplayRole , m_powerM1Y ) ;
calcPowerMarkerDelta ( ) ;
}
if ( m_powerM2Valid & & ( m_powerM2X > = p1 . x ( ) ) & & ( m_powerM2X < p2 . x ( ) ) )
{
m_powerM2Y = Interpolation : : interpolate ( p1 . x ( ) , p1 . y ( ) , p2 . x ( ) , p2 . y ( ) , m_powerM2X ) ;
m_powerMarkerSeries - > append ( dateTime . toMSecsSinceEpoch ( ) , m_powerM2Y ) ;
ui - > powerMarkerTable - > item ( POWER_MARKER_ROW_M2 , POWER_MARKER_COL_VALUE ) - > setData ( Qt : : DisplayRole , m_powerM2Y ) ;
calcPowerMarkerDelta ( ) ;
}
}
if ( ! skipCalcs )
{
// Set X axis format to include date if measurements span over different days
// Seems there's a QT bug here, if we call m_powerXAxis->setFormat, the chart isn't
// redrawn properly, so we have to redraw the whole thing
QDateTime minDateTime = m_powerXAxis - > min ( ) ;
QDateTime maxDateTime = m_powerXAxis - > max ( ) ;
bool sameDay = minDateTime . date ( ) = = maxDateTime . date ( ) ;
if ( ! sameDay & & m_powerXAxisSameDay )
{
m_powerXAxisSameDay = true ;
QTimer : : singleShot ( 100 , this , SLOT ( plotPowerChart ( ) ) ) ;
}
}
if ( ! skipCalcs & & ui - > powerShowAvg - > isChecked ( ) ) {
calcAverages ( ) ;
}
}
if ( m_powerSeries - > count ( ) < = 1 ) // Don't check skipCalcs here, as that will be set for first data
{
ui - > powerStartTime - > setMinimumDateTime ( fft - > m_dateTime ) ;
ui - > powerEndTime - > setMinimumDateTime ( fft - > m_dateTime ) ;
if ( m_settings . m_powerAutoscale )
{
ui - > powerStartTime - > setDateTime ( fft - > m_dateTime ) ;
ui - > powerEndTime - > setDateTime ( fft - > m_dateTime ) ;
}
}
if ( ! skipCalcs )
{
ui - > powerStartTime - > setMaximumDateTime ( fft - > m_dateTime ) ;
ui - > powerEndTime - > setMaximumDateTime ( fft - > m_dateTime ) ;
if ( m_settings . m_powerAutoscale ) {
ui - > powerEndTime - > setDateTime ( fft - > m_dateTime ) ;
}
}
}
double RadioAstronomyGUI : : degreesToSteradian ( double deg ) const
{
// https://en.wikipedia.org/wiki/Steradian - Other properties
double s = sin ( Units : : degreesToRadians ( deg ) / 4.0 ) ;
return 4.0 * M_PI * s * s ;
}
double RadioAstronomyGUI : : hpbwToSteradians ( double hpbw ) const
{
// https://www.cv.nrao.edu/~sransom/web/Ch3.html#E118
double theta = Units : : degreesToRadians ( hpbw ) ;
return theta * theta * M_PI / ( 4.0 * M_LN2 ) ;
}
double RadioAstronomyGUI : : calcOmegaA ( ) const
{
return hpbwToSteradians ( m_beamWidth ) ;
}
double RadioAstronomyGUI : : calcOmegaS ( ) const
{
if ( m_settings . m_sourceType = = RadioAstronomySettings : : UNKNOWN )
{
return 0.0 ;
}
else if ( m_settings . m_sourceType = = RadioAstronomySettings : : EXTENDED )
{
return calcOmegaA ( ) ;
}
else
{
return m_settings . m_omegaSUnits = = RadioAstronomySettings : : STERRADIANS ? m_settings . m_omegaS : degreesToSteradian ( m_settings . m_omegaS ) ;
}
}
double RadioAstronomyGUI : : beamFillingFactor ( ) const
{
if ( m_settings . m_sourceType = = RadioAstronomySettings : : EXTENDED )
{
return 1.0 ;
}
else
{
// https://www.cv.nrao.edu/~sransom/web/Ch3.html#E55
return calcOmegaS ( ) / calcOmegaA ( ) ;
}
}
void RadioAstronomyGUI : : powerMeasurementReceived ( FFTMeasurement * fft , bool skipCalcs )
{
2022-10-10 11:26:41 +01:00
ui - > powerTable - > setSortingEnabled ( false ) ;
2021-10-12 11:31:14 +01:00
int row = ui - > powerTable - > rowCount ( ) ;
ui - > powerTable - > setRowCount ( row + 1 ) ;
QTableWidgetItem * dateItem = new QTableWidgetItem ( ) ;
QTableWidgetItem * timeItem = new QTableWidgetItem ( ) ;
QTableWidgetItem * powerItem = new QTableWidgetItem ( ) ;
QTableWidgetItem * powerDBItem = new QTableWidgetItem ( ) ;
QTableWidgetItem * powerdBmItem = new QTableWidgetItem ( ) ;
QTableWidgetItem * tSysItem = new QTableWidgetItem ( ) ;
QTableWidgetItem * tSys0Item = new QTableWidgetItem ( ) ;
QTableWidgetItem * tSourceItem = new QTableWidgetItem ( ) ;
QTableWidgetItem * tBItem = new QTableWidgetItem ( ) ;
QTableWidgetItem * tSkyItem = new QTableWidgetItem ( ) ;
QTableWidgetItem * fluxItem = new QTableWidgetItem ( ) ;
QTableWidgetItem * sigmaTItem = new QTableWidgetItem ( ) ;
QTableWidgetItem * sigmaSItem = new QTableWidgetItem ( ) ;
QTableWidgetItem * omegaAItem = new QTableWidgetItem ( ) ;
QTableWidgetItem * omegaSItem = new QTableWidgetItem ( ) ;
QTableWidgetItem * raItem = new QTableWidgetItem ( ) ;
QTableWidgetItem * decItem = new QTableWidgetItem ( ) ;
QTableWidgetItem * lonItem = new QTableWidgetItem ( ) ;
QTableWidgetItem * latItem = new QTableWidgetItem ( ) ;
QTableWidgetItem * azItem = new QTableWidgetItem ( ) ;
QTableWidgetItem * elItem = new QTableWidgetItem ( ) ;
QTableWidgetItem * vBCRSItem = new QTableWidgetItem ( ) ;
QTableWidgetItem * vLSRItem = new QTableWidgetItem ( ) ;
QTableWidgetItem * solarFluxItem = new QTableWidgetItem ( ) ;
QTableWidgetItem * airTempItem = new QTableWidgetItem ( ) ;
QTableWidgetItem * sensor1Item = new QTableWidgetItem ( ) ;
QTableWidgetItem * sensor2Item = new QTableWidgetItem ( ) ;
2023-03-29 19:20:05 +01:00
QTableWidgetItem * utcItem = new QTableWidgetItem ( ) ;
2023-08-26 14:40:13 +01:00
QTableWidgetItem * rotAzItem = new QTableWidgetItem ( ) ;
QTableWidgetItem * rotElItem = new QTableWidgetItem ( ) ;
QTableWidgetItem * rotAzOffItem = new QTableWidgetItem ( ) ;
QTableWidgetItem * rotElOffItem = new QTableWidgetItem ( ) ;
2021-10-12 11:31:14 +01:00
ui - > powerTable - > setItem ( row , POWER_COL_DATE , dateItem ) ;
ui - > powerTable - > setItem ( row , POWER_COL_TIME , timeItem ) ;
ui - > powerTable - > setItem ( row , POWER_COL_POWER , powerItem ) ;
ui - > powerTable - > setItem ( row , POWER_COL_POWER_DB , powerDBItem ) ;
ui - > powerTable - > setItem ( row , POWER_COL_POWER_DBM , powerdBmItem ) ;
ui - > powerTable - > setItem ( row , POWER_COL_TSYS , tSysItem ) ;
ui - > powerTable - > setItem ( row , POWER_COL_TSYS0 , tSys0Item ) ;
ui - > powerTable - > setItem ( row , POWER_COL_TSOURCE , tSourceItem ) ;
ui - > powerTable - > setItem ( row , POWER_COL_TB , tBItem ) ;
ui - > powerTable - > setItem ( row , POWER_COL_TSKY , tSkyItem ) ;
ui - > powerTable - > setItem ( row , POWER_COL_FLUX , fluxItem ) ;
ui - > powerTable - > setItem ( row , POWER_COL_SIGMA_T , sigmaTItem ) ;
ui - > powerTable - > setItem ( row , POWER_COL_SIGMA_S , sigmaSItem ) ;
ui - > powerTable - > setItem ( row , POWER_COL_OMEGA_A , omegaAItem ) ;
ui - > powerTable - > setItem ( row , POWER_COL_OMEGA_S , omegaSItem ) ;
ui - > powerTable - > setItem ( row , POWER_COL_RA , raItem ) ;
ui - > powerTable - > setItem ( row , POWER_COL_DEC , decItem ) ;
ui - > powerTable - > setItem ( row , POWER_COL_GAL_LON , lonItem ) ;
ui - > powerTable - > setItem ( row , POWER_COL_GAL_LAT , latItem ) ;
ui - > powerTable - > setItem ( row , POWER_COL_AZ , azItem ) ;
ui - > powerTable - > setItem ( row , POWER_COL_EL , elItem ) ;
ui - > powerTable - > setItem ( row , POWER_COL_VBCRS , vBCRSItem ) ;
ui - > powerTable - > setItem ( row , POWER_COL_VLSR , vLSRItem ) ;
ui - > powerTable - > setItem ( row , POWER_COL_SOLAR_FLUX , solarFluxItem ) ;
ui - > powerTable - > setItem ( row , POWER_COL_AIR_TEMP , airTempItem ) ;
ui - > powerTable - > setItem ( row , POWER_COL_SENSOR_1 , sensor1Item ) ;
ui - > powerTable - > setItem ( row , POWER_COL_SENSOR_2 , sensor2Item ) ;
2023-03-29 19:20:05 +01:00
ui - > powerTable - > setItem ( row , POWER_COL_UTC , utcItem ) ;
2023-08-26 14:40:13 +01:00
ui - > powerTable - > setItem ( row , POWER_COL_ROT_AZ , rotAzItem ) ;
ui - > powerTable - > setItem ( row , POWER_COL_ROT_EL , rotElItem ) ;
ui - > powerTable - > setItem ( row , POWER_COL_ROT_AZ_OFF , rotAzOffItem ) ;
ui - > powerTable - > setItem ( row , POWER_COL_ROT_EL_OFF , rotElOffItem ) ;
2021-10-12 11:31:14 +01:00
2022-10-10 11:26:41 +01:00
ui - > powerTable - > setSortingEnabled ( true ) ;
2021-10-12 11:31:14 +01:00
QDateTime dateTime = fft - > m_dateTime ;
dateItem - > setData ( Qt : : DisplayRole , dateTime . date ( ) ) ;
timeItem - > setData ( Qt : : DisplayRole , dateTime . time ( ) ) ;
2023-03-29 19:20:05 +01:00
utcItem - > setData ( Qt : : DisplayRole , dateTime . toUTC ( ) ) ;
2021-10-12 11:31:14 +01:00
powerItem - > setData ( Qt : : DisplayRole , fft - > m_totalPower ) ;
powerDBItem - > setData ( Qt : : DisplayRole , fft - > m_totalPowerdBFS ) ;
if ( fft - > m_tSys ! = 0.0f ) {
powerdBmItem - > setData ( Qt : : DisplayRole , fft - > m_totalPowerdBm ) ;
}
if ( fft - > m_temp ) {
updatePowerColumns ( row , fft ) ;
}
if ( fft - > m_coordsValid )
{
raItem - > setData ( Qt : : DisplayRole , fft - > m_ra ) ;
decItem - > setData ( Qt : : DisplayRole , fft - > m_dec ) ;
latItem - > setData ( Qt : : DisplayRole , fft - > m_b ) ;
lonItem - > setData ( Qt : : DisplayRole , fft - > m_l ) ;
azItem - > setData ( Qt : : DisplayRole , fft - > m_azimuth ) ;
elItem - > setData ( Qt : : DisplayRole , fft - > m_elevation ) ;
vBCRSItem - > setData ( Qt : : DisplayRole , fft - > m_vBCRS ) ;
vLSRItem - > setData ( Qt : : DisplayRole , fft - > m_vLSR ) ;
tSkyItem - > setData ( Qt : : DisplayRole , fft - > m_skyTemp ) ;
}
solarFluxItem - > setData ( Qt : : DisplayRole , fft - > m_solarFlux ) ;
airTempItem - > setData ( Qt : : DisplayRole , fft - > m_airTemp ) ;
sensor1Item - > setData ( Qt : : DisplayRole , fft - > m_sensor [ 0 ] ) ;
sensor2Item - > setData ( Qt : : DisplayRole , fft - > m_sensor [ 1 ] ) ;
2023-08-26 14:40:13 +01:00
if ( fft - > m_rotValid )
{
rotAzItem - > setData ( Qt : : DisplayRole , fft - > m_rotAz ) ;
rotElItem - > setData ( Qt : : DisplayRole , fft - > m_rotEl ) ;
rotAzOffItem - > setData ( Qt : : DisplayRole , fft - > m_rotAzOff ) ;
rotElOffItem - > setData ( Qt : : DisplayRole , fft - > m_rotElOff ) ;
}
2021-10-12 11:31:14 +01:00
addToPowerSeries ( fft , skipCalcs ) ;
}
void RadioAstronomyGUI : : powerAutoscale ( )
{
if ( m_settings . m_powerAutoscale )
{
on_powerAutoscaleX_clicked ( ) ;
on_powerAutoscaleY_clicked ( ) ;
}
}
// Scale X and Y axis according to min and max values
void RadioAstronomyGUI : : on_powerAutoscale_toggled ( bool checked )
{
m_settings . m_powerAutoscale = checked ;
ui - > powerAutoscaleX - > setEnabled ( ! m_settings . m_powerAutoscale ) ;
ui - > powerAutoscaleY - > setEnabled ( ! m_settings . m_powerAutoscale ) ;
ui - > powerReference - > setEnabled ( ! m_settings . m_powerAutoscale ) ;
ui - > powerRange - > setEnabled ( ! m_settings . m_powerAutoscale ) ;
ui - > powerStartTime - > setEnabled ( ! m_settings . m_powerAutoscale ) ;
ui - > powerEndTime - > setEnabled ( ! m_settings . m_powerAutoscale ) ;
powerAutoscale ( ) ;
2026-02-01 00:49:36 +01:00
applySettings ( QStringList ( " powerAutoscale " ) ) ;
2021-10-12 11:31:14 +01:00
}
2021-10-12 13:38:37 +01:00
void RadioAstronomyGUI : : powerAutoscaleY ( bool adjustAxis )
2021-10-12 11:31:14 +01:00
{
2021-10-12 13:38:37 +01:00
double min = m_powerMin ;
double max = m_powerMax ;
double range = max - min ;
// Round to 1 or 2 decimal places
if ( range > 1.0 )
{
min = std : : floor ( min * 10.0 ) / 10.0 ;
max = std : : ceil ( max * 10.0 ) / 10.0 ;
}
else
2021-10-12 11:31:14 +01:00
{
2021-10-12 13:38:37 +01:00
min = std : : floor ( min * 100.0 ) / 100.0 ;
max = std : : ceil ( max * 100.0 ) / 100.0 ;
}
range = max - min ;
max + = range * 0.2 ; // Add 20% space for markers
range = max - min ;
range = std : : max ( 0.1 , range ) ; // Don't be smaller than minimum value we can set in GUI
2021-10-12 11:31:14 +01:00
2021-10-12 13:38:37 +01:00
if ( adjustAxis ) {
2021-10-12 11:31:14 +01:00
m_powerYAxis - > setRange ( min , max ) ;
2021-10-12 13:38:37 +01:00
}
ui - > powerRange - > setValue ( range ) ; // Call before setting reference, so number of decimals are adjusted
ui - > powerReference - > setValue ( max ) ;
}
// Scale Y axis according to min and max values
void RadioAstronomyGUI : : on_powerAutoscaleY_clicked ( )
{
if ( m_powerYAxis ) {
powerAutoscaleY ( true ) ;
2021-10-12 11:31:14 +01:00
}
}
// Scale X axis according to min and max values in series
void RadioAstronomyGUI : : on_powerAutoscaleX_clicked ( )
{
if ( m_powerSeries & & ( m_powerSeries - > count ( ) > 0 ) )
{
QDateTime start = QDateTime : : fromMSecsSinceEpoch ( m_powerSeries - > at ( 0 ) . x ( ) ) ;
QDateTime end = QDateTime : : fromMSecsSinceEpoch ( m_powerSeries - > at ( m_powerSeries - > count ( ) - 1 ) . x ( ) ) ;
ui - > powerStartTime - > setDateTime ( start ) ;
ui - > powerEndTime - > setDateTime ( end ) ;
}
}
void RadioAstronomyGUI : : on_powerReference_valueChanged ( double value )
{
m_settings . m_powerReference = value ;
if ( m_powerYAxis ) {
m_powerYAxis - > setRange ( m_settings . m_powerReference - m_settings . m_powerRange , m_settings . m_powerReference ) ;
}
2026-02-01 00:49:36 +01:00
applySettings ( QStringList ( " powerReference " ) ) ;
2021-10-12 11:31:14 +01:00
}
void RadioAstronomyGUI : : on_powerRange_valueChanged ( double value )
{
m_settings . m_powerRange = value ;
if ( m_settings . m_powerRange < = 1.0 )
{
ui - > powerRange - > setSingleStep ( 0.1 ) ;
ui - > powerRange - > setDecimals ( 2 ) ;
ui - > powerReference - > setDecimals ( 2 ) ;
}
else
{
ui - > powerRange - > setSingleStep ( 1.0 ) ;
ui - > powerRange - > setDecimals ( 1 ) ;
ui - > powerReference - > setDecimals ( 1 ) ;
}
if ( m_powerYAxis ) {
m_powerYAxis - > setRange ( m_settings . m_powerReference - m_settings . m_powerRange , m_settings . m_powerReference ) ;
}
2026-02-01 00:49:36 +01:00
applySettings ( QStringList ( " powerRange " ) ) ;
2021-10-12 11:31:14 +01:00
}
void RadioAstronomyGUI : : on_powerStartTime_dateTimeChanged ( QDateTime value )
{
if ( m_powerXAxis ) {
m_powerXAxis - > setMin ( value ) ;
}
}
void RadioAstronomyGUI : : on_powerEndTime_dateTimeChanged ( QDateTime value )
{
if ( m_powerXAxis ) {
m_powerXAxis - > setMax ( value ) ;
}
}
// Columns in table reordered
void RadioAstronomyGUI : : powerTable_sectionMoved ( int logicalIndex , int oldVisualIndex , int newVisualIndex )
{
( void ) oldVisualIndex ;
m_settings . m_powerTableColumnIndexes [ logicalIndex ] = newVisualIndex ;
}
// Column in table resized (when hidden size is 0)
void RadioAstronomyGUI : : powerTable_sectionResized ( int logicalIndex , int oldSize , int newSize )
{
( void ) oldSize ;
m_settings . m_powerTableColumnSizes [ logicalIndex ] = newSize ;
}
// Right click in table header - show column select menu
void RadioAstronomyGUI : : powerTableColumnSelectMenu ( QPoint pos )
{
powerTableMenu - > popup ( ui - > powerTable - > horizontalHeader ( ) - > viewport ( ) - > mapToGlobal ( pos ) ) ;
}
// Hide/show column when menu selected
void RadioAstronomyGUI : : powerTableColumnSelectMenuChecked ( bool checked )
{
( void ) checked ;
QAction * action = qobject_cast < QAction * > ( sender ( ) ) ;
if ( action ! = nullptr )
{
int idx = action - > data ( ) . toInt ( nullptr ) ;
ui - > powerTable - > setColumnHidden ( idx , ! action - > isChecked ( ) ) ;
}
}
// Create column select menu item
QAction * RadioAstronomyGUI : : createCheckableItem ( QString & text , int idx , bool checked , const char * slot )
{
QAction * action = new QAction ( text , this ) ;
action - > setCheckable ( true ) ;
action - > setChecked ( checked ) ;
action - > setData ( QVariant ( idx ) ) ;
connect ( action , SIGNAL ( triggered ( ) ) , this , slot ) ;
return action ;
}
RadioAstronomyGUI * RadioAstronomyGUI : : create ( PluginAPI * pluginAPI , DeviceUISet * deviceUISet , BasebandSampleSink * rxChannel )
{
RadioAstronomyGUI * gui = new RadioAstronomyGUI ( pluginAPI , deviceUISet , rxChannel ) ;
return gui ;
}
void RadioAstronomyGUI : : destroy ( )
{
delete this ;
}
void RadioAstronomyGUI : : resetToDefaults ( )
{
m_settings . resetToDefaults ( ) ;
displaySettings ( ) ;
2026-02-01 00:49:36 +01:00
applySettings ( QStringList ( ) , true ) ;
2021-10-12 11:31:14 +01:00
}
QByteArray RadioAstronomyGUI : : serialize ( ) const
{
return m_settings . serialize ( ) ;
}
bool RadioAstronomyGUI : : deserialize ( const QByteArray & data )
{
if ( m_settings . deserialize ( data ) ) {
displaySettings ( ) ;
2026-02-01 00:49:36 +01:00
applySettings ( QStringList ( ) , true ) ;
2021-10-12 11:31:14 +01:00
return true ;
} else {
resetToDefaults ( ) ;
return false ;
}
}
2024-02-16 16:31:12 +00:00
void RadioAstronomyGUI : : updateAvailableFeatures ( const AvailableChannelOrFeatureList & availableFeatures , const QStringList & renameFrom , const QStringList & renameTo )
2021-10-12 11:31:14 +01:00
{
2024-07-10 22:59:13 +02:00
// Update starTracker setting if it has been renamed
2024-02-16 16:31:12 +00:00
if ( renameFrom . contains ( m_settings . m_starTracker ) )
{
m_settings . m_starTracker = renameTo [ renameFrom . indexOf ( m_settings . m_starTracker ) ] ;
2026-02-01 00:49:36 +01:00
applySettings ( QStringList ( " starTracker " ) ) ;
2024-02-16 16:31:12 +00:00
}
2021-10-12 11:31:14 +01:00
ui - > starTracker - > blockSignals ( true ) ;
ui - > starTracker - > clear ( ) ;
2024-02-16 16:31:12 +00:00
for ( const auto & feature : availableFeatures ) {
ui - > starTracker - > addItem ( feature . getLongId ( ) ) ;
2021-10-12 11:31:14 +01:00
}
2024-02-16 16:31:12 +00:00
int idx = ui - > starTracker - > findText ( m_settings . m_starTracker ) ;
if ( idx > = 0 ) {
ui - > starTracker - > setCurrentIndex ( idx ) ;
} else {
ui - > starTracker - > setCurrentIndex ( 0 ) ;
2021-10-12 11:31:14 +01:00
}
2022-03-27 08:01:02 +02:00
ui - > starTracker - > blockSignals ( false ) ;
2024-02-16 16:31:12 +00:00
QString newText = ui - > starTracker - > currentText ( ) ;
if ( m_settings . m_starTracker ! = newText )
2021-10-12 11:31:14 +01:00
{
m_settings . m_starTracker = newText ;
2026-02-01 00:49:36 +01:00
applySettings ( QStringList ( " starTracker " ) ) ;
2021-10-12 11:31:14 +01:00
}
}
bool RadioAstronomyGUI : : handleMessage ( const Message & message )
{
if ( DSPSignalNotification : : match ( message ) )
{
DSPSignalNotification & notif = ( DSPSignalNotification & ) message ;
m_basebandSampleRate = notif . getSampleRate ( ) ;
m_centerFrequency = notif . getCenterFrequency ( ) ;
2022-04-13 11:08:21 +02:00
ui - > deltaFrequency - > setValueRange ( false , 7 , - m_basebandSampleRate / 2 , m_basebandSampleRate / 2 ) ;
ui - > deltaFrequencyLabel - > setToolTip ( tr ( " Range %1 %L2 Hz " ) . arg ( QChar ( 0xB1 ) ) . arg ( m_basebandSampleRate / 2 ) ) ;
updateAbsoluteCenterFrequency ( ) ;
2021-10-12 11:31:14 +01:00
if ( m_settings . m_tempGalLink ) {
calcGalacticBackgroundTemp ( ) ;
}
2022-04-13 11:08:21 +02:00
2021-10-12 11:31:14 +01:00
updateTSys0 ( ) ;
2022-04-13 11:08:21 +02:00
2021-10-12 11:31:14 +01:00
return true ;
}
2022-03-27 08:01:02 +02:00
else if ( RadioAstronomy : : MsgReportAvailableFeatures : : match ( message ) )
2021-10-12 11:31:14 +01:00
{
2022-03-27 08:01:02 +02:00
qDebug ( " RadioAstronomyGUI::handleMessage: MsgReportAvailableFeatures " ) ;
RadioAstronomy : : MsgReportAvailableFeatures & report = ( RadioAstronomy : : MsgReportAvailableFeatures & ) message ;
2024-02-16 16:31:12 +00:00
updateAvailableFeatures ( report . getFeatures ( ) , report . getRenameFrom ( ) , report . getRenameTo ( ) ) ;
2021-10-12 11:31:14 +01:00
return true ;
}
else if ( MainCore : : MsgStarTrackerTarget : : match ( message ) )
{
MainCore : : MsgStarTrackerTarget & msg = ( MainCore : : MsgStarTrackerTarget & ) message ;
SWGSDRangel : : SWGStarTrackerTarget * target = msg . getSWGStarTrackerTarget ( ) ;
m_coordsValid = true ;
m_ra = target - > getRa ( ) ;
m_dec = target - > getDec ( ) ;
m_azimuth = target - > getAzimuth ( ) ;
m_elevation = target - > getElevation ( ) ;
m_l = target - > getL ( ) ;
m_b = target - > getB ( ) ;
m_vBCRS = target - > getEarthRotationVelocity ( ) + target - > getEarthOrbitVelocityBcrs ( ) ;
m_vLSR = target - > getSunVelocityLsr ( ) + m_vBCRS ;
m_solarFlux = target - > getSolarFlux ( ) ;
double airTemp = target - > getAirTemperature ( ) ;
m_skyTemp = target - > getSkyTemperature ( ) ;
m_beamWidth = target - > getHpbw ( ) ;
if ( m_settings . m_elevationLink ) {
ui - > elevation - > setValue ( m_elevation ) ;
}
if ( m_settings . m_tempAirLink ) {
ui - > tempAir - > setValue ( airTemp ) ;
}
SensorMeasurement * sm = new SensorMeasurement ( QDateTime : : currentDateTime ( ) , airTemp ) ;
m_airTemps . append ( sm ) ;
updateTSys0 ( ) ;
updateOmegaA ( ) ;
return true ;
}
else if ( RadioAstronomy : : MsgConfigureRadioAstronomy : : match ( message ) )
{
const RadioAstronomy : : MsgConfigureRadioAstronomy & cfg = ( RadioAstronomy : : MsgConfigureRadioAstronomy & ) message ;
m_settings = cfg . getSettings ( ) ;
blockApplySettings ( true ) ;
2021-12-02 23:54:39 +01:00
m_channelMarker . updateSettings ( static_cast < const ChannelMarker * > ( m_settings . m_channelMarker ) ) ;
2021-10-12 11:31:14 +01:00
displaySettings ( ) ;
blockApplySettings ( false ) ;
return true ;
}
else if ( RadioAstronomy : : MsgMeasurementProgress : : match ( message ) )
{
RadioAstronomy : : MsgMeasurementProgress & progress = ( RadioAstronomy : : MsgMeasurementProgress & ) message ;
ui - > measurementProgress - > setValue ( progress . getPercentComplete ( ) ) ;
return true ;
}
else if ( RadioAstronomy : : MsgSweepStatus : : match ( message ) )
{
RadioAstronomy : : MsgSweepStatus & status = ( RadioAstronomy : : MsgSweepStatus & ) message ;
ui - > sweepStatus - > setText ( status . getStatus ( ) ) ;
return true ;
}
else if ( RadioAstronomy : : MsgSweepComplete : : match ( message ) )
{
ui - > startStop - > blockSignals ( true ) ;
ui - > startStop - > setChecked ( false ) ;
ui - > startStop - > blockSignals ( false ) ;
ui - > startStop - > setStyleSheet ( " QToolButton { background-color : blue; } " ) ;
return true ;
}
else if ( RadioAstronomy : : MsgCalComplete : : match ( message ) )
{
RadioAstronomy : : MsgCalComplete & measurement = ( RadioAstronomy : : MsgCalComplete & ) message ;
calCompletetReceived ( measurement ) ;
return true ;
}
else if ( RadioAstronomy : : MsgFFTMeasurement : : match ( message ) )
{
RadioAstronomy : : MsgFFTMeasurement & measurement = ( RadioAstronomy : : MsgFFTMeasurement & ) message ;
fftMeasurementReceived ( measurement ) ;
if ( m_settings . m_runMode = = RadioAstronomySettings : : SINGLE )
{
ui - > startStop - > blockSignals ( true ) ;
ui - > startStop - > setChecked ( false ) ;
ui - > startStop - > blockSignals ( false ) ;
ui - > startStop - > setStyleSheet ( " QToolButton { background-color : blue; } " ) ;
}
return true ;
}
else if ( RadioAstronomy : : MsgSensorMeasurement : : match ( message ) )
{
RadioAstronomy : : MsgSensorMeasurement & measurement = ( RadioAstronomy : : MsgSensorMeasurement & ) message ;
sensorMeasurementReceived ( measurement ) ;
return true ;
}
2022-03-28 20:12:25 +02:00
else if ( RadioAstronomy : : MsgReportAvailableRotators : : match ( message ) )
{
RadioAstronomy : : MsgReportAvailableRotators & report = ( RadioAstronomy : : MsgReportAvailableRotators & ) message ;
2024-02-16 16:31:12 +00:00
updateRotatorList ( report . getFeatures ( ) , report . getRenameFrom ( ) , report . getRenameTo ( ) ) ;
2022-03-28 20:12:25 +02:00
return true ;
}
2021-10-12 11:31:14 +01:00
return false ;
}
void RadioAstronomyGUI : : handleInputMessages ( )
{
Message * message ;
while ( ( message = getInputMessageQueue ( ) - > pop ( ) ) ! = 0 )
{
if ( handleMessage ( * message ) )
{
delete message ;
}
}
}
void RadioAstronomyGUI : : channelMarkerChangedByCursor ( )
{
ui - > deltaFrequency - > setValue ( m_channelMarker . getCenterFrequency ( ) ) ;
m_settings . m_inputFrequencyOffset = m_channelMarker . getCenterFrequency ( ) ;
2026-02-01 00:49:36 +01:00
applySettings ( QStringList ( " inputFrequencyOffset " ) ) ;
2021-10-12 11:31:14 +01:00
}
void RadioAstronomyGUI : : channelMarkerHighlightedByCursor ( )
{
2022-04-26 00:42:26 +02:00
setHighlighted ( m_channelMarker . getHighlighted ( ) ) ;
2021-10-12 11:31:14 +01:00
}
// Calculate Tsys0 - i.e. receiver noise temperature when there's no source signal, just unwanted noise
void RadioAstronomyGUI : : updateTSys0 ( )
{
double tSys0 = calcTSys0 ( ) ;
ui - > tSys0 - > setText ( QString ( " %1 " ) . arg ( round ( tSys0 ) ) ) ;
double sigmaT = calcSigmaT ( tSys0 ) ;
double sigmaS = calcSigmaS ( tSys0 ) ;
ui - > sigmaTSys0 - > setText ( QString ( " %1 " ) . arg ( sigmaT , 0 , ' f ' , 1 ) ) ;
ui - > sigmaSSys0 - > setText ( QString ( " %1 " ) . arg ( sigmaS , 0 , ' f ' , 1 ) ) ;
}
// Estimate of system noise temperature due to all sources of unwanted noise, from user settings
double RadioAstronomyGUI : : calcTSys0 ( ) const
{
return m_settings . m_tempRX + m_settings . m_tempCMB + m_settings . m_tempGal + m_settings . m_tempSP + m_settings . m_tempAtm ;
}
// Calculate measurement time
double RadioAstronomyGUI : : calcTau ( ) const
{
return m_settings . m_integration / ( m_settings . m_sampleRate / ( double ) m_settings . m_fftSize ) ;
}
double RadioAstronomyGUI : : calcTau ( const FFTMeasurement * fft ) const
{
return fft - > m_integration / ( fft - > m_sampleRate / ( double ) fft - > m_fftSize ) ;
}
// Calculate variation in Tsys due to random noise fluctuations, including receiver gain variations
// Minimum temp we can reliably detect will be ~5x this
// Uses practical total-power radiometer equation: https://www.cv.nrao.edu/~sransom/web/Ch3.html#E158
double RadioAstronomyGUI : : calcSigmaT ( double tSys ) const
{
double tau = calcTau ( ) ;
return tSys * sqrt ( 1.0 / ( m_settings . m_rfBandwidth * tau ) + m_settings . m_gainVariation * m_settings . m_gainVariation ) ;
}
double RadioAstronomyGUI : : calcSigmaT ( const FFTMeasurement * fft ) const
{
double tau = calcTau ( fft ) ;
return fft - > m_tSys * sqrt ( 1.0 / ( fft - > m_rfBandwidth * tau ) + m_settings . m_gainVariation * m_settings . m_gainVariation ) ;
}
// Calculate variations in flux due to random noise fluctuations, including receiver gain variations
// Minimum flux we can reliably detect will be ~5x this
double RadioAstronomyGUI : : calcSigmaS ( double tSys ) const
{
double omegaA = hpbwToSteradians ( m_beamWidth ) ;
double lambda = Astronomy : : m_speedOfLight / ( double ) m_centerFrequency ;
double flux = 2.0 * Astronomy : : m_boltzmann * tSys * omegaA / ( lambda * lambda ) ; // Should we use Aeff here instead?
double tau = calcTau ( ) ;
double sigma = flux * sqrt ( 1.0 / ( m_settings . m_rfBandwidth * tau ) + m_settings . m_gainVariation * m_settings . m_gainVariation ) ;
return Units : : wattsPerMetrePerHertzToJansky ( sigma ) ;
}
double RadioAstronomyGUI : : calcSigmaS ( const FFTMeasurement * fft ) const
{
double omegaA = fft - > m_omegaA ;
double lambda = Astronomy : : m_speedOfLight / ( double ) fft - > m_centerFrequency ;
double flux = 2.0 * Astronomy : : m_boltzmann * fft - > m_tSys * omegaA / ( lambda * lambda ) ; // Should we use Aeff here instead?
double tau = calcTau ( fft ) ;
double sigma = flux * sqrt ( 1.0 / ( fft - > m_rfBandwidth * tau ) + m_settings . m_gainVariation * m_settings . m_gainVariation ) ;
return Units : : wattsPerMetrePerHertzToJansky ( sigma ) ;
}
// Calculate and display how long a single measurement will take
void RadioAstronomyGUI : : updateIntegrationTime ( )
{
double secs = calcTau ( ) ;
if ( secs > = 60 ) {
ui - > integrationTime - > setText ( QString ( " %1m " ) . arg ( secs / 60 , 0 , ' f ' , 1 ) ) ;
} else {
ui - > integrationTime - > setText ( QString ( " %1s " ) . arg ( secs , 0 , ' f ' , 1 ) ) ;
}
updateTSys0 ( ) ;
}
// Limit bandwidth to be less than sample rate
void RadioAstronomyGUI : : updateBWLimits ( )
{
qint64 sr = ( qint64 ) m_settings . m_sampleRate ;
int digits = ceil ( log10 ( sr + 1 ) ) ;
2023-03-29 19:20:05 +01:00
ui - > rfBW - > setValueRange ( true , digits , 100 , sr ) ;
2021-10-12 11:31:14 +01:00
}
void RadioAstronomyGUI : : on_deltaFrequency_changed ( qint64 value )
{
m_channelMarker . setCenterFrequency ( value ) ;
m_settings . m_inputFrequencyOffset = m_channelMarker . getCenterFrequency ( ) ;
2022-04-13 11:08:21 +02:00
updateAbsoluteCenterFrequency ( ) ;
2026-02-01 00:49:36 +01:00
applySettings ( QStringList ( " inputFrequencyOffset " ) ) ;
2021-10-12 11:31:14 +01:00
}
void RadioAstronomyGUI : : on_sampleRate_changed ( qint64 value )
{
float sr = value ;
m_settings . m_sampleRate = sr ;
updateBWLimits ( ) ;
updateIntegrationTime ( ) ;
2026-02-01 00:49:36 +01:00
applySettings ( QStringList ( " sampleRate " ) ) ;
2021-10-12 11:31:14 +01:00
}
void RadioAstronomyGUI : : on_rfBW_changed ( qint64 value )
{
float bw = value ;
m_channelMarker . setBandwidth ( bw ) ;
m_settings . m_rfBandwidth = bw ;
2026-02-01 00:49:36 +01:00
applySettings ( QStringList ( " rfBandwidth " ) ) ;
2021-10-12 11:31:14 +01:00
}
void RadioAstronomyGUI : : on_integration_changed ( qint64 value )
{
m_settings . m_integration = value ;
updateIntegrationTime ( ) ;
2026-02-01 00:49:36 +01:00
applySettings ( QStringList ( " integration " ) ) ;
2021-10-12 11:31:14 +01:00
}
void RadioAstronomyGUI : : on_recalibrate_toggled ( bool checked )
{
m_settings . m_recalibrate = checked ;
2026-02-01 00:49:36 +01:00
applySettings ( QStringList ( " recalibrate " ) ) ;
2021-10-12 11:31:14 +01:00
if ( checked ) {
recalibrate ( ) ;
}
}
void RadioAstronomyGUI : : on_showCalSettings_clicked ( )
{
RadioAstronomyCalibrationDialog dialog ( & m_settings ) ;
if ( dialog . exec ( ) = = QDialog : : Accepted ) {
2026-02-01 00:49:36 +01:00
applySettings ( QStringList ( { " gpioEnabled " , " gpioPin " , " gpioSense " , " startCalCommand " , " stopCalCommand " , " calCommandDelay " } ) ) ;
2021-10-12 11:31:14 +01:00
}
}
// Start hot calibration
void RadioAstronomyGUI : : on_startCalHot_clicked ( )
{
if ( ui - > startStop - > isChecked ( ) ) {
ui - > startStop - > click ( ) ;
}
m_radioAstronomy - > getInputMessageQueue ( ) - > push ( RadioAstronomy : : MsgStartCal : : create ( true ) ) ;
ui - > startCalHot - > setStyleSheet ( " QToolButton { background-color : green; } " ) ;
}
// Start cold calibration
void RadioAstronomyGUI : : on_startCalCold_clicked ( )
{
if ( ui - > startStop - > isChecked ( ) ) {
ui - > startStop - > click ( ) ;
}
m_radioAstronomy - > getInputMessageQueue ( ) - > push ( RadioAstronomy : : MsgStartCal : : create ( false ) ) ;
ui - > startCalCold - > setStyleSheet ( " QToolButton { background-color : green; } " ) ;
}
// Clear all measurements (but not calibration data)
void RadioAstronomyGUI : : clearData ( )
{
ui - > powerTable - > setRowCount ( 0 ) ;
m_powerSeries - > clear ( ) ;
m_powerPeakSeries - > clear ( ) ;
m_powerMarkerSeries - > clear ( ) ;
m_powerTsys0Series - > clear ( ) ;
2022-09-26 12:46:52 +01:00
m_powerFilteredSeries - > clear ( ) ;
2021-10-12 11:31:14 +01:00
m_airTemps . clear ( ) ;
for ( int i = 0 ; i < RADIOASTRONOMY_SENSORS ; i + + ) {
m_sensors [ i ] . clear ( ) ;
}
for ( int row = 0 ; row < POWER_MARKER_ROWS ; row + + )
{
for ( int col = POWER_MARKER_COL_DATE ; col < = POWER_MARKER_COL_DELTA_TO ; col + + )
{
ui - > powerMarkerTable - > item ( row , col ) - > setText ( " " ) ;
}
}
m_powerM1Valid = false ;
m_powerM2Valid = false ;
qDeleteAll ( m_fftMeasurements ) ;
m_fftMeasurements . clear ( ) ;
m_fftSeries - > clear ( ) ;
m_fftPeakSeries - > clear ( ) ;
m_fftMarkerSeries - > clear ( ) ;
for ( int row = 0 ; row < SPECTRUM_MARKER_ROWS ; row + + )
{
for ( int col = SPECTRUM_MARKER_COL_FREQ ; col < = SPECTRUM_MARKER_COL_D ; col + + )
{
ui - > spectrumMarkerTable - > item ( row , col ) - > setText ( " " ) ;
}
}
m_spectrumM1Valid = false ;
m_spectrumM2Valid = false ;
clearLoSMarker ( " Max " ) ;
clearLoSMarker ( " M1 " ) ;
clearLoSMarker ( " M2 " ) ;
ui - > spectrumIndex - > setRange ( 0 , 0 ) ;
ui - > spectrumDateTime - > setDateTime ( QDateTime : : currentDateTime ( ) ) ;
ui - > powerMean - > setText ( " " ) ;
ui - > powerRMS - > setText ( " " ) ;
ui - > powerSD - > setText ( " " ) ;
plotPowerVsTimeChart ( ) ; // To ensure min/max/peaks are reset
create2DImage ( ) ;
plotPowerChart ( ) ;
ui - > measurementProgress - > setValue ( 0 ) ;
ui - > sweepStatus - > setText ( " " ) ;
}
// Clear calibration data
void RadioAstronomyGUI : : clearCalData ( )
{
delete m_calHot ;
delete m_calCold ;
delete m_calG ;
m_calHot = nullptr ;
m_calCold = nullptr ;
m_calG = nullptr ;
m_calHotSeries - > clear ( ) ;
m_calColdSeries - > clear ( ) ;
ui - > calAvgDiff - > setText ( " " ) ;
}
// deleteRowsComplete should be called after all rows are deleted
// Returns if the row being deleted is the currently displayed FFT
bool RadioAstronomyGUI : : deleteRow ( int row )
{
ui - > powerTable - > removeRow ( row ) ;
delete m_fftMeasurements [ row ] ;
m_fftMeasurements . removeAt ( row ) ;
return row = = ui - > spectrumIndex - > value ( ) ;
}
// Updates GUI after rows have been deleted
void RadioAstronomyGUI : : deleteRowsComplete ( bool deletedCurrent , int next )
{
if ( m_fftMeasurements . size ( ) = = 0 )
{
clearData ( ) ;
}
else
{
if ( deletedCurrent ) {
ui - > spectrumIndex - > setValue ( next ) ;
}
plotPowerChart ( ) ;
powerAutoscale ( ) ;
}
}
// Calculate average difference in hot and cold cal data - so we can easily validate results
void RadioAstronomyGUI : : calcCalAvgDiff ( )
{
if ( ( m_calHot & & m_calCold ) & & ( m_calHot - > m_fftSize = = m_calCold - > m_fftSize ) )
{
Real sum = 0.0f ;
for ( int i = 0 ; i < m_calHot - > m_fftSize ; i + + ) {
sum + = CalcDb : : dbPower ( m_calHot - > m_fftData [ i ] ) - CalcDb : : dbPower ( m_calCold - > m_fftData [ i ] ) ;
}
Real avg = sum / m_calHot - > m_fftSize ;
ui - > calAvgDiff - > setText ( QString : : number ( avg , ' f ' , 1 ) ) ;
}
else
{
ui - > calAvgDiff - > setText ( " " ) ;
}
}
void RadioAstronomyGUI : : calcCalibrationScaleFactors ( )
{
if ( m_calHot )
{
delete [ ] m_calG ;
m_calG = new double [ m_calHot - > m_fftSize ] ;
// Calculate scaling factors from FFT mag to temperature
// FIXME: This assumes cal hot is fixed reference temp - E.g. 50Ohm term
for ( int i = 0 ; i < m_calHot - > m_fftSize ; i + + ) {
m_calG [ i ] = ( m_settings . m_tCalHot + m_settings . m_tempRX ) / m_calHot - > m_fftData [ i ] ;
}
}
}
void RadioAstronomyGUI : : calibrate ( )
{
if ( m_calHotSeries )
{
calcCalibrationScaleFactors ( ) ;
calcCalTrx ( ) ;
calcCalTsp ( ) ;
if ( m_settings . m_recalibrate )
{
// Apply new calibration to existing measurements
recalibrate ( ) ;
}
}
}
// Apply calibration to all existing measurements
void RadioAstronomyGUI : : recalibrate ( )
{
for ( int i = 0 ; i < m_fftMeasurements . size ( ) ; i + + )
{
FFTMeasurement * fft = m_fftMeasurements [ i ] ;
// Recalibrate
calcFFTTemperatures ( fft ) ;
calcFFTTotalTemperature ( fft ) ;
// Update table
if ( fft - > m_tSys ! = 0.0f ) {
ui - > powerTable - > item ( i , POWER_COL_POWER_DBM ) - > setData ( Qt : : DisplayRole , fft - > m_totalPowerdBm ) ;
}
if ( fft - > m_temp ) {
updatePowerColumns ( i , fft ) ;
}
}
// Update charts
plotFFTMeasurement ( ) ;
plotPowerChart ( ) ;
}
// Calculate Trx using Y-factor method
void RadioAstronomyGUI : : calcCalTrx ( )
{
if ( ( m_calHot & & m_calCold ) & & ( m_calHot - > m_fftSize = = m_calCold - > m_fftSize ) )
{
// y=Ph/Pc
double sumH = 0.0 ;
double sumC = 0.0 ;
for ( int i = 0 ; i < m_calHot - > m_fftSize ; i + + )
{
sumH + = m_calHot - > m_fftData [ i ] ;
sumC + = m_calCold - > m_fftData [ i ] ;
}
double y = sumH / sumC ;
// Use y to calculate Trx, which should be the same for both calibration points
double Trx = ( m_settings . m_tCalHot - ( m_settings . m_tCalCold * y ) ) / ( y - 1.0 ) ;
ui - > calYFactor - > setText ( QString : : number ( y , ' f ' , 2 ) ) ;
ui - > calTrx - > setText ( QString : : number ( Trx , ' f ' , 1 ) ) ;
}
else
{
ui - > calYFactor - > setText ( " " ) ;
ui - > calTrx - > setText ( " " ) ;
}
}
2024-07-10 22:59:13 +02:00
// Estimate spillover temperature (This is typically very Az/El dependent as ground noise will vary)
2021-10-12 11:31:14 +01:00
void RadioAstronomyGUI : : calcCalTsp ( )
{
if ( ! ui - > calTrx - > text ( ) . isEmpty ( ) & & ! ui - > calTsky - > text ( ) . isEmpty ( ) & & ! ui - > calYFactor - > text ( ) . isEmpty ( ) )
{
double Trx = ui - > calTrx - > text ( ) . toDouble ( ) ;
double Tsky = ui - > calTsky - > text ( ) . toDouble ( ) ;
double y = ui - > calYFactor - > text ( ) . toDouble ( ) ;
double atmosphericAbsorbtion = std : : exp ( - m_settings . m_zenithOpacity / cos ( Units : : degreesToRadians ( 90.0f - m_settings . m_elevation ) ) ) ;
double Tsp = ( m_settings . m_tCalHot + Trx ) / y - ( Tsky * atmosphericAbsorbtion ) - m_settings . m_tempAtm - Trx ;
ui - > calTsp - > setText ( QString : : number ( Tsp , ' f ' , 1 ) ) ;
}
else
{
ui - > calTsp - > setText ( " " ) ;
}
}
void RadioAstronomyGUI : : on_clearData_clicked ( )
{
clearData ( ) ;
}
void RadioAstronomyGUI : : on_clearCal_clicked ( )
{
clearCalData ( ) ;
}
2025-06-24 12:32:42 +01:00
void RadioAstronomyGUI : : savePowerData ( const QString & filename )
{
QFile file ( filename ) ;
if ( ! file . open ( QIODevice : : WriteOnly | QIODevice : : Text ) ) {
QMessageBox : : critical ( this , " Radio Astronomy " , QString ( " Failed to open file %1 " ) . arg ( filename ) ) ;
return ;
}
QTextStream out ( & file ) ;
// Create a CSV file from the values in the table
for ( int i = 0 ; i < ui - > powerTable - > horizontalHeader ( ) - > count ( ) ; i + + )
{
QString text = ui - > powerTable - > horizontalHeaderItem ( i ) - > text ( ) ;
out < < text < < " , " ;
}
out < < " \n " ;
for ( int i = 0 ; i < ui - > powerTable - > rowCount ( ) ; i + + )
{
for ( int j = 0 ; j < ui - > powerTable - > horizontalHeader ( ) - > count ( ) ; j + + )
{
out < < ui - > powerTable - > item ( i , j ) - > data ( Qt : : DisplayRole ) . toString ( ) < < " , " ;
}
out < < " \n " ;
}
}
2021-10-12 11:31:14 +01:00
// Save power data in table to a CSV file
2025-06-24 12:32:42 +01:00
void RadioAstronomyGUI : : on_savePowerData_clicked ( bool checked )
2021-10-12 11:31:14 +01:00
{
2026-01-06 14:02:19 +00:00
( void ) checked ;
2025-06-24 12:32:42 +01:00
ui - > savePowerData - > setChecked ( ! m_settings . m_powerAutoSaveCSVFilename . isEmpty ( ) ) ;
2021-10-12 11:31:14 +01:00
// Get filename to save to
QFileDialog fileDialog ( nullptr , " Select file to save data to " , " " , " *.csv " ) ;
2025-09-07 10:57:29 +01:00
fileDialog . setDefaultSuffix ( " csv " ) ;
2021-10-12 11:31:14 +01:00
fileDialog . setAcceptMode ( QFileDialog : : AcceptSave ) ;
if ( fileDialog . exec ( ) )
{
QStringList fileNames = fileDialog . selectedFiles ( ) ;
2025-06-24 12:32:42 +01:00
if ( fileNames . size ( ) > 0 ) {
savePowerData ( fileNames [ 0 ] ) ;
}
}
}
2021-10-12 11:31:14 +01:00
2025-06-24 12:32:42 +01:00
void RadioAstronomyGUI : : on_savePowerData_rightClicked ( const QPoint & point )
{
( void ) point ;
if ( ! ui - > savePowerData - > isChecked ( ) )
{
// Get filename to save to
QFileDialog fileDialog ( nullptr , " Select file to auto save data to " , " " , " *.csv " ) ;
2025-09-07 10:57:29 +01:00
fileDialog . setDefaultSuffix ( " csv " ) ;
2025-06-24 12:32:42 +01:00
fileDialog . setAcceptMode ( QFileDialog : : AcceptSave ) ;
if ( fileDialog . exec ( ) )
{
QStringList fileNames = fileDialog . selectedFiles ( ) ;
if ( fileNames . size ( ) > 0 )
2021-10-12 11:31:14 +01:00
{
2025-06-24 12:32:42 +01:00
m_settings . m_powerAutoSaveCSVFilename = fileNames [ 0 ] ;
ui - > savePowerData - > setChecked ( true ) ;
ui - > savePowerData - > setToolTip ( QString ( " Left click to save data to a .csv file. \n Right click to disable auto save. \n Auto saving to %1 " ) . arg ( m_settings . m_powerAutoSaveCSVFilename ) ) ;
2026-02-01 00:49:36 +01:00
applySettings ( QStringList ( " powerAutoSaveCSVFilename " ) ) ;
2025-06-24 12:32:42 +01:00
savePowerData ( m_settings . m_powerAutoSaveCSVFilename ) ;
2021-10-12 11:31:14 +01:00
}
}
}
2025-06-24 12:32:42 +01:00
else
{
ui - > savePowerData - > setChecked ( false ) ;
ui - > savePowerData - > setToolTip ( " Left click to save data to a .csv file. \n Right click to auto-save data to a .csv file " ) ;
m_settings . m_powerAutoSaveCSVFilename = " " ;
2026-02-01 00:49:36 +01:00
applySettings ( QStringList ( " powerAutoSaveCSVFilename " ) ) ;
2025-06-24 12:32:42 +01:00
}
2021-10-12 11:31:14 +01:00
}
// Create a hash mapping from column name to array index
QHash < QString , int > RadioAstronomyGUI : : csvHeadersToHash ( QStringList cols )
{
QHash < QString , int > hash ;
for ( int i = 0 ; i < cols . size ( ) ; i + + ) {
hash . insert ( cols [ i ] , i ) ;
}
return hash ;
}
// Get data from column with given name, if available
QString RadioAstronomyGUI : : csvData ( QHash < QString , int > hash , QStringList cols , QString col )
{
QString s ;
if ( hash . contains ( col ) )
{
int idx = hash [ col ] ;
if ( idx < cols . size ( ) ) {
s = cols [ idx ] ;
}
}
return s ;
}
bool RadioAstronomyGUI : : hasNeededFFTData ( QHash < QString , int > hash )
{
return hash . contains ( " FFT Size " ) & & hash . contains ( " Data " ) ;
}
// Write FFTMeasurement to a stream
void RadioAstronomyGUI : : saveFFT ( QTextStream & out , const FFTMeasurement * fft )
{
2026-04-08 13:07:32 +01:00
out < < fft - > m_dateTime . toString ( Qt : : ISODateWithMs ) ;
2021-10-12 11:31:14 +01:00
out < < " , " ;
out < < fft - > m_centerFrequency ;
out < < " , " ;
out < < fft - > m_sampleRate ;
out < < " , " ;
out < < fft - > m_integration ;
out < < " , " ;
out < < fft - > m_rfBandwidth ;
out < < " , " ;
out < < fft - > m_omegaA ;
out < < " , " ;
out < < fft - > m_omegaS ;
out < < " , " ;
out < < fft - > m_totalPower ;
out < < " , " ;
out < < fft - > m_totalPowerdBFS ;
out < < " , " ;
out < < fft - > m_totalPowerdBm ;
out < < " , " ;
out < < fft - > m_totalPowerWatts ;
out < < " , " ;
out < < fft - > m_tSys ;
out < < " , " ;
out < < fft - > m_tSys0 ;
out < < " , " ;
out < < fft - > m_tSource ;
out < < " , " ;
out < < fft - > m_flux ;
out < < " , " ;
out < < fft - > m_sigmaT ;
out < < " , " ;
out < < fft - > m_sigmaS ;
out < < " , " ;
out < < fft - > m_tempMin ;
out < < " , " ;
out < < fft - > m_baseline ;
out < < " , " ;
out < < fft - > m_ra ;
out < < " , " ;
out < < fft - > m_dec ;
out < < " , " ;
out < < fft - > m_azimuth ;
out < < " , " ;
out < < fft - > m_elevation ;
out < < " , " ;
out < < fft - > m_l ;
out < < " , " ;
out < < fft - > m_b ;
out < < " , " ;
out < < fft - > m_vBCRS ;
out < < " , " ;
out < < fft - > m_vLSR ;
out < < " , " ;
out < < fft - > m_solarFlux ;
out < < " , " ;
out < < fft - > m_airTemp ;
out < < " , " ;
out < < fft - > m_skyTemp ;
out < < " , " ;
out < < fft - > m_sensor [ 0 ] ;
out < < " , " ;
out < < fft - > m_sensor [ 1 ] ;
out < < " , " ;
out < < fft - > m_fftSize ;
out < < " , " ;
for ( int j = 0 ; j < fft - > m_fftSize ; j + + )
{
out < < fft - > m_fftData [ j ] ;
out < < " , " ;
}
if ( fft - > m_snr )
{
for ( int j = 0 ; j < fft - > m_fftSize ; j + + )
{
out < < fft - > m_snr [ j ] ;
out < < " , " ;
}
}
if ( fft - > m_temp )
{
for ( int j = 0 ; j < fft - > m_fftSize ; j + + )
{
out < < fft - > m_temp [ j ] ;
out < < " , " ;
}
}
out < < " \n " ;
}
// Create a FFTMeasurement from data read from CSV file
RadioAstronomyGUI : : FFTMeasurement * RadioAstronomyGUI : : loadFFT ( QHash < QString , int > hash , QStringList cols )
{
int fftSize = csvData ( hash , cols , " FFT Size " ) . toInt ( ) ;
int fftDataIdx = hash [ " Data " ] ;
if ( ( fftSize > 0 ) & & ( cols . size ( ) > = fftDataIdx + fftSize ) )
{
FFTMeasurement * fft = new FFTMeasurement ( ) ;
fft - > m_dateTime = QDateTime : : fromString ( csvData ( hash , cols , " Date Time " ) ) ;
fft - > m_centerFrequency = csvData ( hash , cols , " Centre Freq " ) . toLongLong ( ) ;
fft - > m_sampleRate = csvData ( hash , cols , " Sample Rate " ) . toInt ( ) ;
fft - > m_integration = csvData ( hash , cols , " Integration " ) . toInt ( ) ;
fft - > m_rfBandwidth = csvData ( hash , cols , " Bandwidth " ) . toInt ( ) ;
fft - > m_omegaA = csvData ( hash , cols , " OmegaA " ) . toFloat ( ) ;
fft - > m_omegaS = csvData ( hash , cols , " OmegaS " ) . toFloat ( ) ;
fft - > m_fftSize = fftSize ;
fft - > m_fftData = new Real [ fftSize ] ;
fft - > m_db = new Real [ fftSize ] ;
for ( int i = 0 ; i < fftSize ; i + + )
{
fft - > m_fftData [ i ] = cols [ fftDataIdx + i ] . toFloat ( ) ;
fft - > m_db [ i ] = ( Real ) CalcDb : : dbPower ( fft - > m_fftData [ i ] ) ;
}
if ( cols . size ( ) > = fftDataIdx + 2 * fftSize )
{
fft - > m_snr = new Real [ fftSize ] ;
for ( int i = 0 ; i < fftSize ; i + + ) {
fft - > m_snr [ i ] = cols [ fftDataIdx + fftSize + i ] . toFloat ( ) ;
}
if ( cols . size ( ) > = fftDataIdx + 3 * fftSize )
{
fft - > m_temp = new Real [ fftSize ] ;
for ( int i = 0 ; i < fftSize ; i + + ) {
fft - > m_temp [ i ] = cols [ fftDataIdx + 2 * fftSize + i ] . toFloat ( ) ;
}
}
}
fft - > m_totalPower = csvData ( hash , cols , " Power (FFT) " ) . toFloat ( ) ;
fft - > m_totalPowerdBFS = csvData ( hash , cols , " Power (dBFS) " ) . toFloat ( ) ;
fft - > m_totalPowerdBm = csvData ( hash , cols , " Power (dBm) " ) . toFloat ( ) ;
fft - > m_totalPowerWatts = csvData ( hash , cols , " Power (Watts) " ) . toFloat ( ) ;
fft - > m_tSys = csvData ( hash , cols , " Tsys " ) . toFloat ( ) ;
fft - > m_tSys0 = csvData ( hash , cols , " Tsys0 " ) . toFloat ( ) ;
fft - > m_tSource = csvData ( hash , cols , " Tsource " ) . toFloat ( ) ;
fft - > m_flux = csvData ( hash , cols , " Sv " ) . toFloat ( ) ;
fft - > m_sigmaT = csvData ( hash , cols , " SigmaTsys " ) . toFloat ( ) ;
fft - > m_sigmaS = csvData ( hash , cols , " SigmaSsys " ) . toFloat ( ) ;
fft - > m_tempMin = csvData ( hash , cols , " Min Temp " ) . toFloat ( ) ;
fft - > m_baseline = ( RadioAstronomySettings : : SpectrumBaseline ) csvData ( hash , cols , " Baseline " ) . toInt ( ) ;
fft - > m_ra = csvData ( hash , cols , " RA " ) . toFloat ( ) ;
fft - > m_dec = csvData ( hash , cols , " Dec " ) . toFloat ( ) ;
fft - > m_azimuth = csvData ( hash , cols , " Azimuth " ) . toFloat ( ) ;
fft - > m_elevation = csvData ( hash , cols , " Elevation " ) . toFloat ( ) ;
fft - > m_l = csvData ( hash , cols , " l " ) . toFloat ( ) ;
fft - > m_b = csvData ( hash , cols , " b " ) . toFloat ( ) ;
if ( ( fft - > m_ra ! = 0.0 ) | | ( fft - > m_dec ! = 0.0 ) | | ( fft - > m_azimuth ! = 0.0 ) | | ( fft - > m_elevation ! = 0.0 ) | | ( fft - > m_l ! = 0.0 ) | | ( fft - > m_b ! = 0.0 ) ) {
fft - > m_coordsValid = true ;
}
fft - > m_vBCRS = csvData ( hash , cols , " vBCRS " ) . toFloat ( ) ;
fft - > m_vLSR = csvData ( hash , cols , " vLSR " ) . toFloat ( ) ;
fft - > m_solarFlux = csvData ( hash , cols , " Solar Flux " ) . toFloat ( ) ;
fft - > m_airTemp = csvData ( hash , cols , " Air Temp " ) . toFloat ( ) ;
fft - > m_skyTemp = csvData ( hash , cols , " Sky Temp " ) . toFloat ( ) ;
fft - > m_sensor [ 0 ] = csvData ( hash , cols , " Sensor 1 " ) . toFloat ( ) ;
fft - > m_sensor [ 1 ] = csvData ( hash , cols , " Sensor 2 " ) . toFloat ( ) ;
if ( fft - > m_rfBandwidth = = 0 )
{
fft - > m_rfBandwidth = 0.9 * fft - > m_sampleRate ; // Older files don't have this column and we need a value for min
calcFFTTotalPower ( fft ) ;
/*calcFFTMinTemperature(fft);
calcFFTTotalTemperature(fft);*/
}
return fft ;
}
else
{
return nullptr ;
}
}
2025-06-24 12:32:42 +01:00
void RadioAstronomyGUI : : saveSpectrumData ( const QString & filename )
2021-10-12 11:31:14 +01:00
{
2025-06-24 12:32:42 +01:00
QFile file ( filename ) ;
if ( ! file . open ( QIODevice : : WriteOnly | QIODevice : : Text ) ) {
QMessageBox : : critical ( this , " Radio Astronomy " , QString ( " Failed to open file %1 " ) . arg ( filename ) ) ;
return ;
}
QTextStream out ( & file ) ;
if ( ui - > spectrumChartSelect - > currentIndex ( ) = = 0 )
{
// Create a CSV file for all the spectrum data
out < < " Date Time,Centre Freq,Sample Rate,Integration,Bandwidth,OmegaA,OmegaS,Power (FFT),Power (dBFS),Power (dBm),Power (Watts),Tsys,Tsys0,Tsource,Sv,SigmaTsys,SigmaSsys,Min Temp,Baseline,RA,Dec,Azimuth,Elevation,l,b,vBCRS,vLSR,Solar Flux,Air Temp,Sky Temp,Sensor 1,Sensor 2,FFT Size,Data \n " ;
for ( int i = 0 ; i < m_fftMeasurements . size ( ) ; i + + ) {
saveFFT ( out , m_fftMeasurements [ i ] ) ;
}
}
else
{
// Create a CSV file for calibration data
out < < " Cal,Cal Temp,Date Time,Centre Freq,Sample Rate,Integration,Bandwidth,OmegaA,OmegaS,Power (FFT),Power (dBFS),Power (dBm),Power (Watts),Tsys,Tsys0,Tsource,Sv,SigmaTsys,SigmaSsys,Min Temp,Baseline,RA,Dec,Azimuth,Elevation,l,b,vBCRS,vLSR,Solar Flux,Air Temp,Sky Temp,Sensor 1,Sensor 2,FFT Size,Data \n " ;
if ( m_calHot )
{
out < < " Hot, " ;
out < < m_settings . m_tCalHot ;
out < < " , " ;
saveFFT ( out , m_calHot ) ;
}
if ( m_calCold )
{
out < < " Cold, " ;
out < < m_settings . m_tCalCold ;
out < < " , " ;
saveFFT ( out , m_calCold ) ;
}
}
}
void RadioAstronomyGUI : : on_saveSpectrumData_clicked ( bool checked )
{
2026-01-06 14:02:19 +00:00
( void ) checked ;
2025-06-24 12:32:42 +01:00
ui - > saveSpectrumData - > setChecked ( ! m_settings . m_spectrumAutoSaveCSVFilename . isEmpty ( ) ) ;
2021-10-12 11:31:14 +01:00
// Get filename to save to
QFileDialog fileDialog ( nullptr , " Select file to save data to " , " " , " *.csv " ) ;
2025-09-07 10:57:29 +01:00
fileDialog . setDefaultSuffix ( " csv " ) ;
2021-10-12 11:31:14 +01:00
fileDialog . setAcceptMode ( QFileDialog : : AcceptSave ) ;
if ( fileDialog . exec ( ) )
{
QStringList fileNames = fileDialog . selectedFiles ( ) ;
2025-06-24 12:32:42 +01:00
if ( fileNames . size ( ) > 0 ) {
saveSpectrumData ( fileNames [ 0 ] ) ;
}
}
}
2021-10-12 11:31:14 +01:00
2025-06-24 12:32:42 +01:00
void RadioAstronomyGUI : : on_saveSpectrumData_rightClicked ( const QPoint & point )
{
( void ) point ;
if ( ! ui - > saveSpectrumData - > isChecked ( ) )
{
// Get filename to save to
QFileDialog fileDialog ( nullptr , " Select file to auto save data to " , " " , " *.csv " ) ;
2025-09-07 10:57:29 +01:00
fileDialog . setDefaultSuffix ( " csv " ) ;
2025-06-24 12:32:42 +01:00
fileDialog . setAcceptMode ( QFileDialog : : AcceptSave ) ;
if ( fileDialog . exec ( ) )
{
QStringList fileNames = fileDialog . selectedFiles ( ) ;
if ( fileNames . size ( ) > 0 )
2021-10-12 11:31:14 +01:00
{
2025-06-24 12:32:42 +01:00
m_settings . m_spectrumAutoSaveCSVFilename = fileNames [ 0 ] ;
ui - > saveSpectrumData - > setChecked ( true ) ;
ui - > saveSpectrumData - > setToolTip ( QString ( " Left click to save data to a .csv file. \n Right click to disable auto save. \n Auto saving to %1 " ) . arg ( m_settings . m_spectrumAutoSaveCSVFilename ) ) ;
2026-02-01 00:49:36 +01:00
applySettings ( QStringList ( " spectrumAutoSaveCSVFilename " ) ) ;
2025-06-24 12:32:42 +01:00
saveSpectrumData ( m_settings . m_spectrumAutoSaveCSVFilename ) ;
2021-10-12 11:31:14 +01:00
}
}
}
2025-06-24 12:32:42 +01:00
else
{
ui - > saveSpectrumData - > setChecked ( false ) ;
ui - > saveSpectrumData - > setToolTip ( " Left click to save data to a .csv file. \n Right click to auto-save data to a .csv file " ) ;
m_settings . m_spectrumAutoSaveCSVFilename = " " ;
2026-02-01 00:49:36 +01:00
applySettings ( QStringList ( " spectrumAutoSaveCSVFilename " ) ) ;
2025-06-24 12:32:42 +01:00
}
2021-10-12 11:31:14 +01:00
}
void RadioAstronomyGUI : : on_loadSpectrumData_clicked ( )
{
// Get filename to load from
QFileDialog fileDialog ( nullptr , " Select file to load data from " , " " , " *.csv " ) ;
2025-09-07 10:57:29 +01:00
fileDialog . setDefaultSuffix ( " csv " ) ;
2021-10-12 11:31:14 +01:00
fileDialog . setAcceptMode ( QFileDialog : : AcceptOpen ) ;
if ( fileDialog . exec ( ) )
{
QStringList fileNames = fileDialog . selectedFiles ( ) ;
if ( fileNames . size ( ) > 0 )
{
QFile file ( fileNames [ 0 ] ) ;
if ( ! file . open ( QIODevice : : ReadOnly | QIODevice : : Text ) ) {
QMessageBox : : critical ( this , " Radio Astronomy " , QString ( " Failed to open file %1 " ) . arg ( fileNames [ 0 ] ) ) ;
return ;
}
// Get column names
QTextStream in ( & file ) ;
QString header = in . readLine ( ) ;
QStringList colNames = header . split ( " , " ) ;
QHash < QString , int > hash = csvHeadersToHash ( colNames ) ;
if ( ui - > spectrumChartSelect - > currentIndex ( ) = = 0 )
{
// Load data from CSV file
if ( hasNeededFFTData ( hash ) )
{
// Remove old data - we could support multiple series for comparison
clearData ( ) ;
// Read in FFT data from file
ui - > spectrumIndex - > blockSignals ( true ) ; // Prevent every spectrum from being displayed
while ( ! in . atEnd ( ) )
{
QString row = in . readLine ( ) ;
QStringList cols = row . split ( " , " ) ;
FFTMeasurement * fft = loadFFT ( hash , cols ) ;
if ( fft ) {
addFFT ( fft , true ) ;
}
}
ui - > spectrumIndex - > blockSignals ( false ) ;
// Add data from FFT to sensor measurements
for ( int i = 0 ; i < m_fftMeasurements . size ( ) ; i + + )
{
SensorMeasurement * sm ;
sm = new SensorMeasurement ( m_fftMeasurements [ i ] - > m_dateTime , m_fftMeasurements [ i ] - > m_airTemp ) ;
m_airTemps . append ( sm ) ;
for ( int j = 0 ; j < RADIOASTRONOMY_SENSORS ; j + + )
{
sm = new SensorMeasurement ( m_fftMeasurements [ i ] - > m_dateTime , m_fftMeasurements [ i ] - > m_sensor [ j ] ) ;
m_sensors [ j ] . append ( sm ) ;
}
}
// If we're loading data from scratch, autoscale both axis
if ( ( ui - > spectrumCenterFreq - > value ( ) = = 0.0 ) | | m_settings . m_spectrumAutoscale )
{
on_spectrumAutoscaleY_clicked ( ) ;
on_spectrumAutoscaleX_clicked ( ) ;
}
// Ensure both charts are redrawn fully, as we've disabled some updates/calcs during load
on_spectrumIndex_valueChanged ( m_fftMeasurements . size ( ) - 1 ) ; // Don't call setValue, as it already has this value
plotPowerChart ( ) ;
// As signals were blocked above, power axis may not match up with GUI. Manually update
// Just calling autoscale will not work, as the GUI values may not change
on_powerStartTime_dateTimeChanged ( ui - > powerStartTime - > dateTime ( ) ) ;
on_powerEndTime_dateTimeChanged ( ui - > powerEndTime - > dateTime ( ) ) ;
on_powerRange_valueChanged ( m_settings . m_powerRange ) ;
on_powerReference_valueChanged ( m_settings . m_powerReference ) ;
}
}
else
{
// Load calibration data from CSV file
if ( hasNeededFFTData ( hash ) & & hash . contains ( " Cal " ) )
{
while ( ! in . atEnd ( ) )
{
QString row = in . readLine ( ) ;
QStringList cols = row . split ( " , " ) ;
QString calName = csvData ( hash , cols , " Cal " ) ;
FFTMeasurement * * calp = nullptr ;
FFTMeasurement * cal = nullptr ;
if ( calName = = " Hot " ) {
calp = & m_calHot ;
} else if ( calName = = " Cold " ) {
calp = & m_calCold ;
} else {
qDebug ( ) < < " RadioAstronomyGUI::on_loadSpectrumData_clicked: Skipping unknown calibration " < < calName ;
}
if ( calp )
{
cal = loadFFT ( hash , cols ) ;
if ( cal )
{
delete * calp ;
* calp = cal ;
qDebug ( ) < < " RadioAstronomyGUI::on_loadSpectrumData_clicked: Loaded calibration " < < calName ;
if ( calName = = " Cold " ) {
ui - > calTsky - > setText ( QString : : number ( cal - > m_skyTemp , ' f ' , 1 ) ) ;
}
QString calTempString = csvData ( hash , cols , " Cal Temp " ) ;
bool ok ;
double calTemp = calTempString . toDouble ( & ok ) ;
if ( ok )
{
if ( calName = = " Cold " )
{
ui - > tCalColdSelect - > setCurrentIndex ( 0 ) ;
ui - > tCalCold - > setValue ( calTemp ) ;
}
else
{
ui - > tCalHotSelect - > setCurrentIndex ( 0 ) ;
ui - > tCalHot - > setValue ( calTemp ) ;
}
}
}
}
}
calcCalAvgDiff ( ) ;
calibrate ( ) ;
plotCalMeasurements ( ) ;
}
else
{
QMessageBox : : critical ( this , " Radio Astronomy " , QString ( " Missing required columns in file %1 " ) . arg ( fileNames [ 0 ] ) ) ;
return ;
}
}
}
}
}
void RadioAstronomyGUI : : on_powerTable_cellDoubleClicked ( int row , int column )
{
2024-02-16 16:31:12 +00:00
if ( ( column > = POWER_COL_RA ) & & ( column < = POWER_COL_EL ) )
2021-10-12 11:31:14 +01:00
{
// Display target in Star Tracker
2022-03-27 08:01:02 +02:00
QList < ObjectPipe * > starTrackerPipes ;
2024-02-16 16:31:12 +00:00
MainCore : : instance ( ) - > getMessagePipes ( ) . getMessagePipes ( m_radioAstronomy , " startracker.display " , starTrackerPipes ) ;
2021-10-12 11:31:14 +01:00
2022-03-27 08:01:02 +02:00
for ( const auto & pipe : starTrackerPipes )
{
MessageQueue * messageQueue = qobject_cast < MessageQueue * > ( pipe - > m_element ) ;
SWGSDRangel : : SWGStarTrackerDisplaySettings * swgSettings = new SWGSDRangel : : SWGStarTrackerDisplaySettings ( ) ;
QDateTime dt ( ui - > powerTable - > item ( row , POWER_COL_DATE ) - > data ( Qt : : DisplayRole ) . toDate ( ) ,
ui - > powerTable - > item ( row , POWER_COL_TIME ) - > data ( Qt : : DisplayRole ) . toTime ( ) ) ;
swgSettings - > setDateTime ( new QString ( dt . toString ( Qt : : ISODateWithMs ) ) ) ;
swgSettings - > setAzimuth ( ui - > powerTable - > item ( row , POWER_COL_AZ ) - > data ( Qt : : DisplayRole ) . toFloat ( ) ) ;
swgSettings - > setElevation ( ui - > powerTable - > item ( row , POWER_COL_EL ) - > data ( Qt : : DisplayRole ) . toFloat ( ) ) ;
messageQueue - > push ( MainCore : : MsgStarTrackerDisplaySettings : : create ( m_radioAstronomy , swgSettings ) ) ;
2021-10-12 11:31:14 +01:00
}
}
else
{
// Display in Spectrometer
ui - > spectrumIndex - > setValue ( row ) ;
}
}
void RadioAstronomyGUI : : onWidgetRolled ( QWidget * widget , bool rollDown )
{
( void ) widget ;
( void ) rollDown ;
2022-01-09 05:27:12 +01:00
2022-11-11 12:24:27 +00:00
getRollupContents ( ) - > saveState ( m_rollupState ) ;
2026-02-01 00:49:36 +01:00
applySettings ( QStringList ( ) ) ;
2021-10-12 11:31:14 +01:00
}
void RadioAstronomyGUI : : onMenuDialogCalled ( const QPoint & p )
{
2024-08-25 23:36:46 +02:00
if ( m_contextMenuType = = ContextMenuType : : ContextMenuChannelSettings )
2021-10-12 11:31:14 +01:00
{
BasicChannelSettingsDialog dialog ( & m_channelMarker , this ) ;
dialog . setUseReverseAPI ( m_settings . m_useReverseAPI ) ;
dialog . setReverseAPIAddress ( m_settings . m_reverseAPIAddress ) ;
dialog . setReverseAPIPort ( m_settings . m_reverseAPIPort ) ;
dialog . setReverseAPIDeviceIndex ( m_settings . m_reverseAPIDeviceIndex ) ;
dialog . setReverseAPIChannelIndex ( m_settings . m_reverseAPIChannelIndex ) ;
2022-04-18 01:42:03 +02:00
dialog . setDefaultTitle ( m_displayedName ) ;
if ( m_deviceUISet - > m_deviceMIMOEngine )
{
dialog . setNumberOfStreams ( m_radioAstronomy - > getNumberOfDeviceStreams ( ) ) ;
dialog . setStreamIndex ( m_settings . m_streamIndex ) ;
}
2021-10-12 11:31:14 +01:00
dialog . move ( p ) ;
2022-12-20 10:31:15 +00:00
new DialogPositioner ( & dialog , false ) ;
2021-10-12 11:31:14 +01:00
dialog . exec ( ) ;
m_settings . m_rgbColor = m_channelMarker . getColor ( ) . rgb ( ) ;
m_settings . m_title = m_channelMarker . getTitle ( ) ;
m_settings . m_useReverseAPI = dialog . useReverseAPI ( ) ;
m_settings . m_reverseAPIAddress = dialog . getReverseAPIAddress ( ) ;
m_settings . m_reverseAPIPort = dialog . getReverseAPIPort ( ) ;
m_settings . m_reverseAPIDeviceIndex = dialog . getReverseAPIDeviceIndex ( ) ;
m_settings . m_reverseAPIChannelIndex = dialog . getReverseAPIChannelIndex ( ) ;
setWindowTitle ( m_settings . m_title ) ;
2022-04-12 16:20:45 +02:00
setTitle ( m_channelMarker . getTitle ( ) ) ;
2021-10-12 11:31:14 +01:00
setTitleColor ( m_settings . m_rgbColor ) ;
2022-04-18 01:42:03 +02:00
if ( m_deviceUISet - > m_deviceMIMOEngine )
{
m_settings . m_streamIndex = dialog . getSelectedStreamIndex ( ) ;
m_channelMarker . clearStreamIndexes ( ) ;
m_channelMarker . addStreamIndex ( m_settings . m_streamIndex ) ;
updateIndexLabel ( ) ;
}
2021-10-12 11:31:14 +01:00
2026-02-01 00:49:36 +01:00
applySettings ( QStringList ( { " title " , " rgbColor " , " useReverseAPI " , " reverseAPIAddress " ,
" reverseAPIPort " , " reverseAPIDeviceIndex " , " reverseAPIChannelIndex " ,
" streamIndex " } ) ) ;
2021-10-12 11:31:14 +01:00
}
resetContextMenuType ( ) ;
}
RadioAstronomyGUI : : RadioAstronomyGUI ( PluginAPI * pluginAPI , DeviceUISet * deviceUISet , BasebandSampleSink * rxChannel , QWidget * parent ) :
ChannelGUI ( parent ) ,
ui ( new Ui : : RadioAstronomyGUI ) ,
m_pluginAPI ( pluginAPI ) ,
m_deviceUISet ( deviceUISet ) ,
m_channelMarker ( this ) ,
m_doApplySettings ( true ) ,
m_basebandSampleRate ( 0 ) ,
m_centerFrequency ( 0 ) ,
m_tickCount ( 0 ) ,
m_powerChart ( nullptr ) ,
m_powerSeries ( nullptr ) ,
m_powerXAxis ( nullptr ) ,
m_powerYAxis ( nullptr ) ,
m_powerPeakSeries ( nullptr ) ,
m_powerMarkerSeries ( nullptr ) ,
m_powerTsys0Series ( nullptr ) ,
m_powerGaussianSeries ( nullptr ) ,
2022-09-26 12:46:52 +01:00
m_powerFilteredSeries ( nullptr ) ,
2021-10-12 12:10:12 +01:00
m_powerPeakValid ( false ) ,
2021-10-12 11:31:14 +01:00
m_2DChart ( nullptr ) ,
m_2DXAxis ( nullptr ) ,
m_2DYAxis ( nullptr ) ,
m_2DMapIntensity ( nullptr ) ,
m_sweepIndex ( 0 ) ,
m_calChart ( nullptr ) ,
m_calXAxis ( nullptr ) ,
m_calYAxis ( nullptr ) ,
m_calHotSeries ( nullptr ) ,
m_calColdSeries ( nullptr ) ,
m_calHot ( nullptr ) ,
m_calCold ( nullptr ) ,
m_calG ( nullptr ) ,
m_fftChart ( nullptr ) ,
m_fftSeries ( nullptr ) ,
m_fftHlineSeries ( nullptr ) ,
m_fftPeakSeries ( nullptr ) ,
m_fftMarkerSeries ( nullptr ) ,
m_fftGaussianSeries ( nullptr ) ,
m_fftLABSeries ( nullptr ) ,
m_fftXAxis ( nullptr ) ,
m_fftYAxis ( nullptr ) ,
m_fftDopplerAxis ( nullptr ) ,
m_powerM1Valid ( false ) ,
m_powerM2Valid ( false ) ,
m_spectrumM1Valid ( false ) ,
m_spectrumM2Valid ( false ) ,
m_coordsValid ( false ) ,
m_ra ( 0.0f ) ,
m_dec ( 0.0f ) ,
m_azimuth ( 0.0f ) ,
m_elevation ( 0.0f ) ,
m_l ( 0.0f ) ,
m_b ( 0.0f ) ,
m_vBCRS ( 0.0f ) ,
m_vLSR ( 0.0f ) ,
m_solarFlux ( 0.0f ) ,
m_beamWidth ( 5.6f ) ,
m_lLAB ( 0.0f ) ,
m_bLAB ( 0.0f ) ,
2022-09-26 12:46:52 +01:00
m_downloadingLAB ( false ) ,
m_window ( nullptr ) ,
m_windowSorted ( nullptr ) ,
m_windowIdx ( 0 ) ,
m_windowCount ( 0 )
2021-10-12 11:31:14 +01:00
{
2022-03-27 08:01:02 +02:00
qDebug ( " RadioAstronomyGUI::RadioAstronomyGUI " ) ;
2021-10-12 11:31:14 +01:00
setAttribute ( Qt : : WA_DeleteOnClose , true ) ;
2022-04-24 12:28:56 +02:00
m_helpURL = " plugins/channelrx/radioastronomy/readme.md " ;
RollupContents * rollupContents = getRollupContents ( ) ;
ui - > setupUi ( rollupContents ) ;
setSizePolicy ( rollupContents - > sizePolicy ( ) ) ;
rollupContents - > arrangeRollups ( ) ;
connect ( rollupContents , SIGNAL ( widgetRolled ( QWidget * , bool ) ) , this , SLOT ( onWidgetRolled ( QWidget * , bool ) ) ) ;
2021-10-12 11:31:14 +01:00
connect ( this , SIGNAL ( customContextMenuRequested ( const QPoint & ) ) , this , SLOT ( onMenuDialogCalled ( const QPoint & ) ) ) ;
m_radioAstronomy = reinterpret_cast < RadioAstronomy * > ( rxChannel ) ;
m_radioAstronomy - > setMessageQueueToGUI ( getInputMessageQueue ( ) ) ;
connect ( & MainCore : : instance ( ) - > getMasterTimer ( ) , SIGNAL ( timeout ( ) ) , this , SLOT ( tick ( ) ) ) ; // 50 ms
2025-06-24 12:32:42 +01:00
CRightClickEnabler * saveSpectrumDataClickEnabler = new CRightClickEnabler ( ui - > saveSpectrumData ) ;
connect ( saveSpectrumDataClickEnabler , SIGNAL ( rightClick ( const QPoint & ) ) , this , SLOT ( on_saveSpectrumData_rightClicked ( const QPoint & ) ) ) ;
CRightClickEnabler * savePowerDataClickEnabler = new CRightClickEnabler ( ui - > savePowerData ) ;
connect ( savePowerDataClickEnabler , SIGNAL ( rightClick ( const QPoint & ) ) , this , SLOT ( on_savePowerData_rightClicked ( const QPoint & ) ) ) ;
connect ( & m_autoSaveTimer , & QTimer : : timeout , this , & RadioAstronomyGUI : : autosave ) ;
m_autoSaveTimer . setInterval ( 5 * 60 * 1000 ) ;
m_autoSaveTimer . setSingleShot ( false ) ;
m_autoSaveTimer . start ( ) ;
2021-10-12 11:31:14 +01:00
m_networkManager = new QNetworkAccessManager ( ) ;
2022-03-23 22:32:23 +01:00
QObject : : connect (
m_networkManager ,
& QNetworkAccessManager : : finished ,
this ,
& RadioAstronomyGUI : : networkManagerFinished
) ;
2021-10-12 11:31:14 +01:00
connect ( & m_dlm , & HttpDownloadManager : : downloadComplete , this , & RadioAstronomyGUI : : downloadFinished ) ;
ui - > deltaFrequencyLabel - > setText ( QString ( " %1f " ) . arg ( QChar ( 0x94 , 0x03 ) ) ) ;
ui - > deltaFrequency - > setColorMapper ( ColorMapper ( ColorMapper : : GrayGold ) ) ;
ui - > deltaFrequency - > setValueRange ( false , 7 , - 9999999 , 9999999 ) ;
// Need to setValue before calling setValueRange, otherwise valueChanged is called
// overwriting the default settings (could also blockSignals)
// Also, set bandwidth before sampleRate
ui - > rfBW - > setColorMapper ( ColorMapper ( ColorMapper : : GrayGold ) ) ;
ui - > rfBW - > setValue ( m_settings . m_rfBandwidth ) ;
2023-03-29 19:20:05 +01:00
ui - > rfBW - > setValueRange ( true , 8 , 100 , 99999999 ) ;
2021-10-12 11:31:14 +01:00
ui - > sampleRate - > setColorMapper ( ColorMapper ( ColorMapper : : GrayGold ) ) ;
ui - > sampleRate - > setValue ( m_settings . m_sampleRate ) ;
2023-03-29 19:20:05 +01:00
ui - > sampleRate - > setValueRange ( true , 8 , 1000 , 99999999 ) ;
2021-10-12 11:31:14 +01:00
ui - > integration - > setColorMapper ( ColorMapper ( ColorMapper : : GrayGold ) ) ;
ui - > integration - > setValue ( m_settings . m_integration ) ;
ui - > integration - > setValueRange ( true , 7 , 1 , 99999999 ) ;
m_channelMarker . blockSignals ( true ) ;
m_channelMarker . setColor ( Qt : : yellow ) ;
m_channelMarker . setBandwidth ( m_settings . m_rfBandwidth ) ;
m_channelMarker . setCenterFrequency ( m_settings . m_inputFrequencyOffset ) ;
m_channelMarker . setTitle ( " Radio Astronomy " ) ;
m_channelMarker . blockSignals ( false ) ;
m_channelMarker . setVisible ( true ) ; // activate signal on the last setting only
setTitleColor ( m_channelMarker . getColor ( ) ) ;
m_settings . setChannelMarker ( & m_channelMarker ) ;
2022-01-09 05:27:12 +01:00
m_settings . setRollupState ( & m_rollupState ) ;
2021-10-12 11:31:14 +01:00
m_deviceUISet - > addChannelMarker ( & m_channelMarker ) ;
connect ( & m_channelMarker , SIGNAL ( changedByCursor ( ) ) , this , SLOT ( channelMarkerChangedByCursor ( ) ) ) ;
connect ( & m_channelMarker , SIGNAL ( highlightedByCursor ( ) ) , this , SLOT ( channelMarkerHighlightedByCursor ( ) ) ) ;
connect ( getInputMessageQueue ( ) , SIGNAL ( messageEnqueued ( ) ) , this , SLOT ( handleInputMessages ( ) ) ) ;
// Resize the table using dummy data
resizePowerTable ( ) ;
// Allow user to reorder columns
ui - > powerTable - > horizontalHeader ( ) - > setSectionsMovable ( true ) ;
// Allow user to sort table by clicking on headers
ui - > powerTable - > setSortingEnabled ( true ) ;
// Add context menu to allow hiding/showing of columns
powerTableMenu = new QMenu ( ui - > powerTable ) ;
for ( int i = 0 ; i < ui - > powerTable - > horizontalHeader ( ) - > count ( ) ; i + + )
{
QString text = ui - > powerTable - > horizontalHeaderItem ( i ) - > text ( ) ;
powerTableMenu - > addAction ( createCheckableItem ( text , i , true , SLOT ( powerTableColumnSelectMenuChecked ( ) ) ) ) ;
}
ui - > powerTable - > horizontalHeader ( ) - > setContextMenuPolicy ( Qt : : CustomContextMenu ) ;
connect ( ui - > powerTable - > horizontalHeader ( ) , SIGNAL ( customContextMenuRequested ( QPoint ) ) , SLOT ( powerTableColumnSelectMenu ( QPoint ) ) ) ;
// Get signals when columns change
connect ( ui - > powerTable - > horizontalHeader ( ) , SIGNAL ( sectionMoved ( int , int , int ) ) , SLOT ( powerTable_sectionMoved ( int , int , int ) ) ) ;
connect ( ui - > powerTable - > horizontalHeader ( ) , SIGNAL ( sectionResized ( int , int , int ) ) , SLOT ( powerTable_sectionResized ( int , int , int ) ) ) ;
ui - > powerTable - > setContextMenuPolicy ( Qt : : CustomContextMenu ) ;
connect ( ui - > powerTable , SIGNAL ( customContextMenuRequested ( QPoint ) ) , SLOT ( customContextMenuRequested ( QPoint ) ) ) ;
2024-06-08 23:46:22 +02:00
ui - > powerTable - > setItemDelegateForColumn ( POWER_COL_TIME , new TimeDelegate ( " hh:mm:ss " , ui - > powerTable ) ) ;
//ui->powerTable->setItemDelegateForColumn(POWER_COL_POWER, new DecimalDelegate(6, ui->powerTable));
ui - > powerTable - > setItemDelegateForColumn ( POWER_COL_POWER_DB , new DecimalDelegate ( 1 , ui - > powerTable ) ) ;
ui - > powerTable - > setItemDelegateForColumn ( POWER_COL_POWER_DBM , new DecimalDelegate ( 1 , ui - > powerTable ) ) ;
ui - > powerTable - > setItemDelegateForColumn ( POWER_COL_TSYS , new DecimalDelegate ( 0 , ui - > powerTable ) ) ;
ui - > powerTable - > setItemDelegateForColumn ( POWER_COL_TSYS0 , new DecimalDelegate ( 0 , ui - > powerTable ) ) ;
ui - > powerTable - > setItemDelegateForColumn ( POWER_COL_TSOURCE , new DecimalDelegate ( 0 , ui - > powerTable ) ) ;
ui - > powerTable - > setItemDelegateForColumn ( POWER_COL_TB , new DecimalDelegate ( 0 , ui - > powerTable ) ) ;
ui - > powerTable - > setItemDelegateForColumn ( POWER_COL_TSKY , new DecimalDelegate ( 0 , ui - > powerTable ) ) ;
ui - > powerTable - > setItemDelegateForColumn ( POWER_COL_FLUX , new DecimalDelegate ( 2 , ui - > powerTable ) ) ;
ui - > powerTable - > setItemDelegateForColumn ( POWER_COL_SIGMA_T , new DecimalDelegate ( 2 , ui - > powerTable ) ) ;
ui - > powerTable - > setItemDelegateForColumn ( POWER_COL_SIGMA_S , new DecimalDelegate ( 1 , ui - > powerTable ) ) ;
ui - > powerTable - > setItemDelegateForColumn ( POWER_COL_RA , new HMSDelegate ( ui - > powerTable ) ) ;
ui - > powerTable - > setItemDelegateForColumn ( POWER_COL_DEC , new DMSDelegate ( ui - > powerTable ) ) ;
ui - > powerTable - > setItemDelegateForColumn ( POWER_COL_GAL_LAT , new DecimalDelegate ( 0 , ui - > powerTable ) ) ;
ui - > powerTable - > setItemDelegateForColumn ( POWER_COL_GAL_LON , new DecimalDelegate ( 0 , ui - > powerTable ) ) ;
ui - > powerTable - > setItemDelegateForColumn ( POWER_COL_AZ , new DecimalDelegate ( 0 , ui - > powerTable ) ) ;
ui - > powerTable - > setItemDelegateForColumn ( POWER_COL_EL , new DecimalDelegate ( 0 , ui - > powerTable ) ) ;
ui - > powerTable - > setItemDelegateForColumn ( POWER_COL_VBCRS , new DecimalDelegate ( 1 , ui - > powerTable ) ) ;
ui - > powerTable - > setItemDelegateForColumn ( POWER_COL_VLSR , new DecimalDelegate ( 1 , ui - > powerTable ) ) ;
ui - > powerTable - > setItemDelegateForColumn ( POWER_COL_AIR_TEMP , new DecimalDelegate ( 1 , ui - > powerTable ) ) ;
ui - > powerTable - > setItemDelegateForColumn ( POWER_COL_ROT_AZ , new DecimalDelegate ( 0 , ui - > powerTable ) ) ;
ui - > powerTable - > setItemDelegateForColumn ( POWER_COL_ROT_EL , new DecimalDelegate ( 0 , ui - > powerTable ) ) ;
ui - > powerTable - > setItemDelegateForColumn ( POWER_COL_ROT_AZ_OFF , new DecimalDelegate ( 0 , ui - > powerTable ) ) ;
ui - > powerTable - > setItemDelegateForColumn ( POWER_COL_ROT_EL_OFF , new DecimalDelegate ( 0 , ui - > powerTable ) ) ;
2021-10-12 11:31:14 +01:00
resizeSpectrumMarkerTable ( ) ;
2024-06-08 23:46:22 +02:00
ui - > spectrumMarkerTable - > setItemDelegateForColumn ( SPECTRUM_MARKER_COL_FREQ , new DecimalDelegate ( 6 , ui - > spectrumMarkerTable ) ) ;
ui - > spectrumMarkerTable - > setItemDelegateForColumn ( SPECTRUM_MARKER_COL_VALUE , new DecimalDelegate ( 1 , ui - > spectrumMarkerTable ) ) ;
ui - > spectrumMarkerTable - > setItemDelegateForColumn ( SPECTRUM_MARKER_COL_DELTA_X , new DecimalDelegate ( 6 , ui - > spectrumMarkerTable ) ) ;
ui - > spectrumMarkerTable - > setItemDelegateForColumn ( SPECTRUM_MARKER_COL_DELTA_Y , new DecimalDelegate ( 1 , ui - > spectrumMarkerTable ) ) ;
ui - > spectrumMarkerTable - > setItemDelegateForColumn ( SPECTRUM_MARKER_COL_VR , new DecimalDelegate ( 2 , ui - > spectrumMarkerTable ) ) ;
ui - > spectrumMarkerTable - > setItemDelegateForColumn ( SPECTRUM_MARKER_COL_R , new DecimalDelegate ( 1 , ui - > spectrumMarkerTable ) ) ;
ui - > spectrumMarkerTable - > setItemDelegateForColumn ( SPECTRUM_MARKER_COL_D , new DecimalDelegate ( 1 , ui - > spectrumMarkerTable ) ) ;
ui - > spectrumMarkerTable - > setItemDelegateForColumn ( SPECTRUM_MARKER_COL_R_MIN , new DecimalDelegate ( 1 , ui - > spectrumMarkerTable ) ) ;
ui - > spectrumMarkerTable - > setItemDelegateForColumn ( SPECTRUM_MARKER_COL_V , new DecimalDelegate ( 1 , ui - > spectrumMarkerTable ) ) ;
2021-10-12 11:31:14 +01:00
// Create blank marker table
ui - > spectrumMarkerTable - > setRowCount ( SPECTRUM_MARKER_ROWS ) ; // 1 peak and two markers
for ( int row = 0 ; row < SPECTRUM_MARKER_ROWS ; row + + )
{
ui - > spectrumMarkerTable - > setItem ( row , SPECTRUM_MARKER_COL_NAME , new QTableWidgetItem ( ) ) ;
ui - > spectrumMarkerTable - > setItem ( row , SPECTRUM_MARKER_COL_FREQ , new QTableWidgetItem ( ) ) ;
ui - > spectrumMarkerTable - > setItem ( row , SPECTRUM_MARKER_COL_VALUE , new QTableWidgetItem ( ) ) ;
ui - > spectrumMarkerTable - > setItem ( row , SPECTRUM_MARKER_COL_DELTA_X , new QTableWidgetItem ( ) ) ;
ui - > spectrumMarkerTable - > setItem ( row , SPECTRUM_MARKER_COL_DELTA_Y , new QTableWidgetItem ( ) ) ;
ui - > spectrumMarkerTable - > setItem ( row , SPECTRUM_MARKER_COL_DELTA_TO , new QTableWidgetItem ( ) ) ;
ui - > spectrumMarkerTable - > setItem ( row , SPECTRUM_MARKER_COL_VR , new QTableWidgetItem ( ) ) ;
ui - > spectrumMarkerTable - > setItem ( row , SPECTRUM_MARKER_COL_R , new QTableWidgetItem ( ) ) ;
ui - > spectrumMarkerTable - > setItem ( row , SPECTRUM_MARKER_COL_D , new QTableWidgetItem ( ) ) ;
// It seems clearing Qt::ItemIsUserCheckable doesn't remove the checkbox, so once set, we always have it
QTableWidgetItem * item = new QTableWidgetItem ( ) ;
item - > setFlags ( item - > flags ( ) | Qt : : ItemIsUserCheckable ) ;
item - > setCheckState ( Qt : : Unchecked ) ;
ui - > spectrumMarkerTable - > setItem ( row , SPECTRUM_MARKER_COL_PLOT_MAX , item ) ;
ui - > spectrumMarkerTable - > setItem ( row , SPECTRUM_MARKER_COL_R_MIN , new QTableWidgetItem ( ) ) ;
ui - > spectrumMarkerTable - > setItem ( row , SPECTRUM_MARKER_COL_V , new QTableWidgetItem ( ) ) ;
}
ui - > spectrumMarkerTable - > item ( SPECTRUM_MARKER_ROW_PEAK , SPECTRUM_MARKER_COL_NAME ) - > setText ( " Max " ) ;
ui - > spectrumMarkerTable - > item ( SPECTRUM_MARKER_ROW_M1 , SPECTRUM_MARKER_COL_NAME ) - > setText ( " M1 " ) ;
ui - > spectrumMarkerTable - > item ( SPECTRUM_MARKER_ROW_M2 , SPECTRUM_MARKER_COL_NAME ) - > setText ( " M2 " ) ;
connect ( ui - > spectrumMarkerTable , & QTableWidget : : itemChanged , this , & RadioAstronomyGUI : : spectrumMarkerTableItemChanged ) ;
resizePowerMarkerTable ( ) ;
2024-06-08 23:46:22 +02:00
ui - > powerMarkerTable - > setItemDelegateForColumn ( POWER_MARKER_COL_TIME , new TimeDelegate ( " hh:mm:ss " , ui - > powerMarkerTable ) ) ;
ui - > powerMarkerTable - > setItemDelegateForColumn ( POWER_MARKER_COL_VALUE , new DecimalDelegate ( 1 , ui - > powerMarkerTable ) ) ;
ui - > powerMarkerTable - > setItemDelegateForColumn ( POWER_MARKER_COL_DELTA_X , new TimeDeltaDelegate ( ui - > powerMarkerTable ) ) ;
ui - > powerMarkerTable - > setItemDelegateForColumn ( POWER_MARKER_COL_DELTA_Y , new DecimalDelegate ( 1 , ui - > powerMarkerTable ) ) ;
2021-10-12 11:31:14 +01:00
// Create blank marker table
ui - > powerMarkerTable - > setRowCount ( POWER_MARKER_ROWS ) ; // 1 peak and two markers
for ( int row = 0 ; row < POWER_MARKER_ROWS ; row + + )
{
ui - > powerMarkerTable - > setItem ( row , POWER_MARKER_COL_NAME , new QTableWidgetItem ( ) ) ;
ui - > powerMarkerTable - > setItem ( row , POWER_MARKER_COL_DATE , new QTableWidgetItem ( ) ) ;
ui - > powerMarkerTable - > setItem ( row , POWER_MARKER_COL_TIME , new QTableWidgetItem ( ) ) ;
ui - > powerMarkerTable - > setItem ( row , POWER_MARKER_COL_VALUE , new QTableWidgetItem ( ) ) ;
ui - > powerMarkerTable - > setItem ( row , POWER_MARKER_COL_DELTA_X , new QTableWidgetItem ( ) ) ;
ui - > powerMarkerTable - > setItem ( row , POWER_MARKER_COL_DELTA_Y , new QTableWidgetItem ( ) ) ;
ui - > powerMarkerTable - > setItem ( row , POWER_MARKER_COL_DELTA_TO , new QTableWidgetItem ( ) ) ;
}
ui - > powerMarkerTable - > item ( POWER_MARKER_ROW_PEAK_MAX , POWER_MARKER_COL_NAME ) - > setText ( " Max " ) ;
ui - > powerMarkerTable - > item ( POWER_MARKER_ROW_PEAK_MIN , POWER_MARKER_COL_NAME ) - > setText ( " Min " ) ;
ui - > powerMarkerTable - > item ( POWER_MARKER_ROW_M1 , POWER_MARKER_COL_NAME ) - > setText ( " M1 " ) ;
ui - > powerMarkerTable - > item ( POWER_MARKER_ROW_M2 , POWER_MARKER_COL_NAME ) - > setText ( " M2 " ) ;
ui - > sweepStartDateTime - > setMinimumDateTime ( QDateTime : : currentDateTime ( ) ) ;
ui - > spectrumDateTime - > setDateTime ( QDateTime : : currentDateTime ( ) ) ;
ui - > startStop - > setStyleSheet ( " QToolButton { background-color : blue; } " ) ;
displaySettings ( ) ;
2022-04-12 16:20:45 +02:00
makeUIConnections ( ) ;
2026-02-01 00:49:36 +01:00
applySettings ( QStringList ( ) , true ) ; // Force apply all settings
2023-11-13 20:51:03 +00:00
m_resizer . enableChildMouseTracking ( ) ;
2021-10-12 11:31:14 +01:00
create2DImage ( ) ;
plotCalSpectrum ( ) ;
plotSpectrum ( ) ;
plotPowerChart ( ) ;
2023-03-30 16:50:01 +01:00
m_radioAstronomy - > getInputMessageQueue ( ) - > push ( RadioAstronomy : : MsgScanAvailableFeatures : : create ( ) ) ;
2021-10-12 11:31:14 +01:00
}
void RadioAstronomyGUI : : customContextMenuRequested ( QPoint pos )
{
QTableWidgetItem * item = ui - > powerTable - > itemAt ( pos ) ;
if ( item )
{
QMenu * tableContextMenu = new QMenu ( ui - > powerTable ) ;
connect ( tableContextMenu , & QMenu : : aboutToHide , tableContextMenu , & QMenu : : deleteLater ) ;
// Copy cell contents to clipboard
QAction * copyAction = new QAction ( " Copy cell " , tableContextMenu ) ;
const QString text = item - > text ( ) ;
connect ( copyAction , & QAction : : triggered , this , [ text ] ( ) - > void {
QClipboard * clipboard = QGuiApplication : : clipboard ( ) ;
clipboard - > setText ( text ) ;
} ) ;
tableContextMenu - > addAction ( copyAction ) ;
// Delete selected rows
QAction * delAction = new QAction ( " Delete rows " , tableContextMenu ) ;
connect ( delAction , & QAction : : triggered , this , [ this ] ( ) - > void {
QModelIndexList rowIndexes = ui - > powerTable - > selectionModel ( ) - > selectedRows ( ) ;
if ( rowIndexes . size ( ) > 0 )
{
// Delete in reverse row order
std : : vector < int > rows ;
foreach ( auto rowIndex , rowIndexes ) {
rows . push_back ( rowIndex . row ( ) ) ;
}
std : : sort ( rows . begin ( ) , rows . end ( ) , std : : greater < int > ( ) ) ;
bool deletedCurrent = false ;
int next ;
foreach ( auto row , rows ) {
next = row - 1 ;
if ( deleteRow ( row ) ) {
deletedCurrent = true ;
}
}
deleteRowsComplete ( deletedCurrent , next ) ;
}
} ) ;
tableContextMenu - > addAction ( delAction ) ;
// Update rows with new Tsys0 and baseline
QAction * updateTSysAction = new QAction ( QString ( " Update Tsys0 / baseline / %1 " ) . arg ( QChar ( 937 ) ) , tableContextMenu ) ;
connect ( updateTSysAction , & QAction : : triggered , this , [ this ] ( ) - > void {
QModelIndexList rowIndexes = ui - > powerTable - > selectionModel ( ) - > selectedRows ( ) ;
if ( rowIndexes . size ( ) > 0 )
{
foreach ( auto rowIndex , rowIndexes )
{
int row = rowIndex . row ( ) ;
m_fftMeasurements [ row ] - > m_tSys0 = calcTSys0 ( ) ;
m_fftMeasurements [ row ] - > m_baseline = m_settings . m_spectrumBaseline ;
m_fftMeasurements [ row ] - > m_omegaA = calcOmegaA ( ) ;
m_fftMeasurements [ row ] - > m_omegaS = calcOmegaS ( ) ;
calcFFTTotalTemperature ( m_fftMeasurements [ row ] ) ;
updatePowerColumns ( row , m_fftMeasurements [ row ] ) ;
}
plotFFTMeasurement ( ) ;
}
} ) ;
tableContextMenu - > addAction ( updateTSysAction ) ;
tableContextMenu - > popup ( ui - > powerTable - > viewport ( ) - > mapToGlobal ( pos ) ) ;
}
}
RadioAstronomyGUI : : ~ RadioAstronomyGUI ( )
{
2025-06-24 12:32:42 +01:00
m_autoSaveTimer . stop ( ) ;
2024-05-26 22:02:18 +02:00
delete m_networkManager ;
2021-10-12 11:31:14 +01:00
delete ui ;
delete m_calHot ;
delete m_calCold ;
qDeleteAll ( m_dataLAB ) ;
m_dataLAB . clear ( ) ;
delete [ ] m_2DMapIntensity ;
2022-09-26 12:46:52 +01:00
delete [ ] m_window ;
delete [ ] m_windowSorted ;
2021-10-12 11:31:14 +01:00
}
void RadioAstronomyGUI : : blockApplySettings ( bool block )
{
m_doApplySettings = ! block ;
}
2026-02-01 00:49:36 +01:00
void RadioAstronomyGUI : : applySettings ( const QStringList & settingsKeys , bool force )
2021-10-12 11:31:14 +01:00
{
if ( m_doApplySettings )
{
2026-02-01 00:49:36 +01:00
RadioAstronomy : : MsgConfigureRadioAstronomy * message = RadioAstronomy : : MsgConfigureRadioAstronomy : : create ( settingsKeys , m_settings , force ) ;
2021-10-12 11:31:14 +01:00
m_radioAstronomy - > getInputMessageQueue ( ) - > push ( message ) ;
}
}
int RadioAstronomyGUI : : fftSizeToIndex ( int size )
{
switch ( size )
{
case 16 :
return 0 ;
case 32 :
return 1 ;
case 64 :
return 2 ;
case 128 :
return 3 ;
case 256 :
return 4 ;
case 512 :
return 5 ;
case 1024 :
return 6 ;
case 2048 :
return 7 ;
case 4096 :
return 8 ;
}
return 0 ;
}
void RadioAstronomyGUI : : displaySettings ( )
{
m_channelMarker . blockSignals ( true ) ;
m_channelMarker . setBandwidth ( m_settings . m_rfBandwidth ) ;
m_channelMarker . setCenterFrequency ( m_settings . m_inputFrequencyOffset ) ;
m_channelMarker . setTitle ( m_settings . m_title ) ;
m_channelMarker . blockSignals ( false ) ;
m_channelMarker . setColor ( m_settings . m_rgbColor ) ; // activate signal on the last setting only
setTitleColor ( m_settings . m_rgbColor ) ;
setWindowTitle ( m_channelMarker . getTitle ( ) ) ;
2022-04-12 16:20:45 +02:00
setTitle ( m_channelMarker . getTitle ( ) ) ;
2021-10-12 11:31:14 +01:00
blockApplySettings ( true ) ;
ui - > deltaFrequency - > setValue ( m_channelMarker . getCenterFrequency ( ) ) ;
float rfBW = m_settings . m_rfBandwidth ; // Save value, as it may be corrupted when setting sampleRate
ui - > sampleRate - > setValue ( m_settings . m_sampleRate ) ;
ui - > rfBW - > setValue ( rfBW ) ;
updateBWLimits ( ) ;
ui - > integration - > setValue ( m_settings . m_integration ) ;
ui - > fftSize - > setCurrentIndex ( fftSizeToIndex ( m_settings . m_fftSize ) ) ;
ui - > fftWindow - > setCurrentIndex ( ( int ) m_settings . m_fftWindow ) ;
ui - > filterFreqs - > setText ( m_settings . m_filterFreqs ) ;
int idx = ui - > starTracker - > findText ( m_settings . m_starTracker ) ;
if ( idx ! = - 1 ) {
ui - > starTracker - > setCurrentIndex ( idx ) ;
}
idx = ui - > rotator - > findText ( m_settings . m_rotator ) ;
if ( idx ! = - 1 ) {
ui - > rotator - > setCurrentIndex ( idx ) ;
}
ui - > tempRXSelect - > setCurrentIndex ( 0 ) ;
ui - > tempRX - > setValue ( m_settings . m_tempRX ) ;
ui - > tempRXUnitsLabel - > setText ( " K " ) ;
ui - > tempCMB - > setValue ( m_settings . m_tempCMB ) ;
ui - > tempGal - > setValue ( m_settings . m_tempGal ) ;
ui - > tempGal - > setEnabled ( ! m_settings . m_tempGalLink ) ;
ui - > tempGalLink - > setChecked ( m_settings . m_tempGalLink ) ;
ui - > tempSP - > setValue ( m_settings . m_tempSP ) ;
ui - > tempAtm - > setValue ( m_settings . m_tempAtm ) ;
ui - > tempAtm - > setEnabled ( ! m_settings . m_tempAtmLink ) ;
ui - > tempAtmLink - > setChecked ( m_settings . m_tempAtmLink ) ;
ui - > tempAir - > setValue ( m_settings . m_tempAir ) ;
ui - > tempAir - > setEnabled ( ! m_settings . m_tempAirLink ) ;
ui - > tempAirLink - > setChecked ( m_settings . m_tempAirLink ) ;
ui - > zenithOpacity - > setValue ( m_settings . m_zenithOpacity ) ;
ui - > elevation - > setValue ( m_settings . m_elevation ) ;
ui - > elevation - > setEnabled ( ! m_settings . m_elevationLink ) ;
ui - > elevationLink - > setChecked ( m_settings . m_elevationLink ) ;
ui - > gainVariation - > setValue ( m_settings . m_gainVariation ) ;
ui - > sourceType - > setCurrentIndex ( ( int ) m_settings . m_sourceType ) ;
ui - > omegaS - > setValue ( m_settings . m_omegaS ) ;
ui - > omegaSUnits - > setCurrentIndex ( ( int ) m_settings . m_omegaSUnits ) ;
ui - > omegaAUnits - > setCurrentIndex ( ( int ) m_settings . m_omegaAUnits ) ;
ui - > recalibrate - > setChecked ( m_settings . m_recalibrate ) ;
ui - > tCalHot - > setValue ( m_settings . m_tCalHot ) ;
ui - > tCalCold - > setValue ( m_settings . m_tCalCold ) ;
ui - > spectrumAutoscale - > setChecked ( m_settings . m_spectrumAutoscale ) ;
ui - > spectrumReference - > setValue ( m_settings . m_spectrumReference ) ;
ui - > spectrumRange - > setValue ( m_settings . m_spectrumRange ) ;
FFTMeasurement * fft = currentFFT ( ) ;
if ( fft ) {
ui - > spectrumCenterFreq - > setValue ( fft - > m_centerFrequency / 1e6 + m_settings . m_spectrumCenterFreqOffset ) ;
} else {
ui - > spectrumCenterFreq - > setValue ( m_centerFrequency / 1e6 + m_settings . m_spectrumCenterFreqOffset ) ;
}
ui - > spectrumSpan - > setValue ( m_settings . m_spectrumSpan ) ;
ui - > spectrumYUnits - > setCurrentIndex ( ( int ) m_settings . m_spectrumYScale ) ;
ui - > spectrumBaseline - > setCurrentIndex ( ( int ) m_settings . m_spectrumBaseline ) ;
ui - > spectrumAutoscaleX - > setEnabled ( ! m_settings . m_spectrumAutoscale ) ;
ui - > spectrumAutoscaleY - > setEnabled ( ! m_settings . m_spectrumAutoscale ) ;
ui - > spectrumReference - > setEnabled ( ! m_settings . m_spectrumAutoscale ) ;
ui - > spectrumRange - > setEnabled ( ! m_settings . m_spectrumAutoscale ) ;
ui - > spectrumCenterFreq - > setEnabled ( ! m_settings . m_spectrumAutoscale ) ;
ui - > spectrumSpan - > setEnabled ( ! m_settings . m_spectrumAutoscale ) ;
ui - > powerAutoscale - > setChecked ( m_settings . m_powerAutoscale ) ;
ui - > powerReference - > setValue ( m_settings . m_powerReference ) ;
ui - > powerRange - > setValue ( m_settings . m_powerRange ) ;
ui - > powerShowPeak - > setChecked ( m_settings . m_powerPeaks ) ;
if ( m_powerPeakSeries )
{
m_powerPeakSeries - > setVisible ( m_settings . m_powerPeaks ) ;
m_powerChart - > legend ( ) - > markers ( m_powerPeakSeries ) [ 0 ] - > setVisible ( false ) ;
}
ui - > powerShowMarker - > setChecked ( m_settings . m_powerMarkers ) ;
if ( m_powerMarkerSeries )
{
m_powerMarkerSeries - > setVisible ( m_settings . m_powerMarkers ) ;
m_powerChart - > legend ( ) - > markers ( m_powerMarkerSeries ) [ 0 ] - > setVisible ( false ) ;
}
ui - > powerShowAvg - > setChecked ( m_settings . m_powerAvg ) ;
ui - > powerChartAvgWidgets - > setVisible ( m_settings . m_powerAvg ) ;
ui - > powerShowGaussian - > setChecked ( m_settings . m_powerShowGaussian ) ;
ui - > powerGaussianWidgets - > setVisible ( m_settings . m_powerShowGaussian ) ;
if ( m_powerGaussianSeries ) {
m_powerGaussianSeries - > setVisible ( m_settings . m_powerShowGaussian ) ;
}
ui - > powerShowLegend - > setChecked ( m_settings . m_powerLegend ) ;
if ( m_powerChart ) {
m_powerChart - > legend ( ) - > setVisible ( m_settings . m_powerLegend ) ;
}
ui - > powerChartSelect - > setCurrentIndex ( ( int ) m_settings . m_powerYData ) ;
ui - > powerYUnits - > setCurrentIndex ( powerYUnitsToIndex ( m_settings . m_powerYUnits ) ) ;
ui - > powerShowTsys0 - > setChecked ( m_settings . m_powerShowTsys0 ) ;
ui - > powerShowAirTemp - > setChecked ( m_settings . m_powerShowAirTemp ) ;
m_airTemps . clicked ( m_settings . m_powerShowAirTemp ) ;
ui - > powerShowSensor1 - > setChecked ( m_settings . m_sensorVisible [ 0 ] ) ;
m_sensors [ 0 ] . setName ( m_settings . m_sensorName [ 0 ] ) ;
m_sensors [ 0 ] . clicked ( m_settings . m_sensorVisible [ 0 ] ) ;
ui - > powerShowSensor2 - > setChecked ( m_settings . m_sensorVisible [ 1 ] ) ;
m_sensors [ 1 ] . setName ( m_settings . m_sensorName [ 1 ] ) ;
m_sensors [ 1 ] . clicked ( m_settings . m_sensorVisible [ 1 ] ) ;
2022-09-26 12:46:52 +01:00
ui - > powerShowFiltered - > setChecked ( m_settings . m_powerShowFiltered ) ;
if ( m_powerFilteredSeries ) {
m_powerFilteredSeries - > setVisible ( m_settings . m_powerShowFiltered ) ;
}
ui - > powerFilterWidgets - > setVisible ( m_settings . m_powerShowFiltered ) ;
ui - > powerFilter - > setCurrentIndex ( ( int ) m_settings . m_powerFilter ) ;
ui - > powerFilterN - > setValue ( m_settings . m_powerFilterN ) ;
ui - > powerShowMeasurement - > setChecked ( m_settings . m_powerShowMeasurement ) ;
if ( m_powerSeries ) {
m_powerSeries - > setVisible ( m_settings . m_powerShowMeasurement ) ;
}
2021-10-12 11:31:14 +01:00
ui - > power2DLinkSweep - > setChecked ( m_settings . m_power2DLinkSweep ) ;
ui - > power2DSweepType - > setCurrentIndex ( ( int ) m_settings . m_power2DSweepType ) ;
ui - > power2DWidth - > setValue ( m_settings . m_power2DWidth ) ;
ui - > power2DHeight - > setValue ( m_settings . m_power2DHeight ) ;
ui - > power2DXMin - > setValue ( m_settings . m_power2DXMin ) ;
ui - > power2DXMax - > setValue ( m_settings . m_power2DXMax ) ;
ui - > power2DYMin - > setValue ( m_settings . m_power2DYMin ) ;
ui - > power2DYMax - > setValue ( m_settings . m_power2DYMax ) ;
ui - > powerColourAutoscale - > setChecked ( m_settings . m_powerColourAutoscale ) ;
ui - > powerColourScaleMin - > setValue ( m_settings . m_powerColourScaleMin ) ;
ui - > powerColourScaleMin - > setEnabled ( ! m_settings . m_powerColourAutoscale ) ;
ui - > powerColourScaleMax - > setValue ( m_settings . m_powerColourScaleMax ) ;
ui - > powerColourScaleMax - > setEnabled ( ! m_settings . m_powerColourAutoscale ) ;
ui - > powerColourPalette - > setCurrentIndex ( ui - > powerColourPalette - > findText ( m_settings . m_powerColourPalette ) ) ;
ui - > spectrumReverseXAxis - > setChecked ( m_settings . m_spectrumReverseXAxis ) ;
ui - > spectrumPeak - > setChecked ( m_settings . m_spectrumPeaks ) ;
ui - > spectrumMarker - > setChecked ( m_settings . m_spectrumMarkers ) ;
ui - > spectrumTemp - > setChecked ( m_settings . m_spectrumTemp ) ;
if ( m_fftGaussianSeries ) {
m_fftGaussianSeries - > setVisible ( m_settings . m_spectrumTemp ) ;
}
ui - > spectrumShowRefLine - > setChecked ( m_settings . m_spectrumRefLine ) ;
if ( m_fftHlineSeries )
{
m_fftHlineSeries - > setVisible ( m_settings . m_spectrumRefLine ) ;
m_fftDopplerAxis - > setVisible ( m_settings . m_spectrumRefLine ) ;
}
ui - > spectrumShowLAB - > setChecked ( m_settings . m_spectrumLAB ) ;
if ( m_fftLABSeries ) {
m_fftLABSeries - > setVisible ( m_settings . m_spectrumLAB ) ;
}
ui - > spectrumShowDistance - > setChecked ( m_settings . m_spectrumDistance ) ;
updateDistanceColumns ( ) ;
ui - > spectrumShowLegend - > setChecked ( m_settings . m_spectrumLegend ) ;
if ( m_fftChart ) {
m_fftChart - > legend ( ) - > setVisible ( m_settings . m_spectrumLegend ) ;
}
if ( m_calChart ) {
m_calChart - > legend ( ) - > setVisible ( m_settings . m_spectrumLegend ) ;
}
2025-06-24 12:32:42 +01:00
ui - > savePowerData - > setChecked ( ! m_settings . m_powerAutoSaveCSVFilename . isEmpty ( ) ) ;
ui - > saveSpectrumData - > setChecked ( ! m_settings . m_spectrumAutoSaveCSVFilename . isEmpty ( ) ) ;
2021-10-12 11:31:14 +01:00
ui - > refFrame - > setCurrentIndex ( ( int ) m_settings . m_refFrame ) ;
ui - > spectrumLine - > setCurrentIndex ( ( int ) m_settings . m_line ) ;
ui - > sunDistanceToGC - > setValue ( m_settings . m_sunDistanceToGC ) ;
ui - > sunOrbitalVelocity - > setValue ( m_settings . m_sunOrbitalVelocity ) ;
displaySpectrumLineFrequency ( ) ;
updateSpectrumSelect ( ) ;
updatePowerSelect ( ) ;
// Updates visibility of widgets
updateSpectrumMarkerTableVisibility ( ) ;
updatePowerMarkerTableVisibility ( ) ;
updatePowerChartWidgetsVisibility ( ) ;
updateSpectrumChartWidgetsVisibility ( ) ;
updateIntegrationTime ( ) ;
ui - > runMode - > setCurrentIndex ( ( int ) m_settings . m_runMode ) ;
ui - > sweepStartAtTime - > setCurrentIndex ( m_settings . m_sweepStartAtTime ? 1 : 0 ) ;
ui - > sweepStartDateTime - > setDateTime ( m_settings . m_sweepStartDateTime ) ;
ui - > sweepStartDateTime - > setVisible ( m_settings . m_sweepStartAtTime ) ;
ui - > sweepType - > setCurrentIndex ( ( int ) m_settings . m_sweepType ) ;
ui - > sweep1Start - > setValue ( m_settings . m_sweep1Start ) ;
ui - > sweep1Stop - > setValue ( m_settings . m_sweep1Stop ) ;
ui - > sweep1Step - > setValue ( m_settings . m_sweep1Step ) ;
ui - > sweep1Delay - > setValue ( m_settings . m_sweep1Delay ) ;
ui - > sweep2Start - > setValue ( m_settings . m_sweep2Start ) ;
ui - > sweep2Stop - > setValue ( m_settings . m_sweep2Stop ) ;
ui - > sweep2Step - > setValue ( m_settings . m_sweep2Step ) ;
ui - > sweep2Delay - > setValue ( m_settings . m_sweep2Delay ) ;
displayRunModeSettings ( ) ;
2022-04-18 01:42:03 +02:00
updateIndexLabel ( ) ;
2021-10-12 11:31:14 +01:00
// Order and size columns
QHeaderView * header = ui - > powerTable - > horizontalHeader ( ) ;
for ( int i = 0 ; i < RADIOASTRONOMY_POWERTABLE_COLUMNS ; i + + )
{
bool hidden = m_settings . m_powerTableColumnSizes [ i ] = = 0 ;
header - > setSectionHidden ( i , hidden ) ;
powerTableMenu - > actions ( ) . at ( i ) - > setChecked ( ! hidden ) ;
if ( m_settings . m_powerTableColumnSizes [ i ] > 0 )
ui - > powerTable - > setColumnWidth ( i , m_settings . m_powerTableColumnSizes [ i ] ) ;
header - > moveSection ( header - > visualIndex ( i ) , m_settings . m_powerTableColumnIndexes [ i ] ) ;
}
2022-04-12 16:20:45 +02:00
getRollupContents ( ) - > restoreState ( m_rollupState ) ;
2022-04-13 11:08:21 +02:00
updateAbsoluteCenterFrequency ( ) ;
2021-10-12 11:31:14 +01:00
blockApplySettings ( false ) ;
2022-04-12 16:20:45 +02:00
getRollupContents ( ) - > arrangeRollups ( ) ;
2021-10-12 11:31:14 +01:00
}
2022-04-22 18:21:24 +01:00
void RadioAstronomyGUI : : leaveEvent ( QEvent * event )
2021-10-12 11:31:14 +01:00
{
m_channelMarker . setHighlighted ( false ) ;
2022-04-22 18:21:24 +01:00
ChannelGUI : : leaveEvent ( event ) ;
2021-10-12 11:31:14 +01:00
}
2022-11-17 14:36:12 +00:00
void RadioAstronomyGUI : : enterEvent ( EnterEventType * event )
2021-10-12 11:31:14 +01:00
{
m_channelMarker . setHighlighted ( true ) ;
2022-04-22 18:21:24 +01:00
ChannelGUI : : enterEvent ( event ) ;
2021-10-12 11:31:14 +01:00
}
void RadioAstronomyGUI : : tick ( )
{
double magsqAvg , magsqPeak ;
int nbMagsqSamples ;
m_radioAstronomy - > getMagSqLevels ( magsqAvg , magsqPeak , nbMagsqSamples ) ;
double powDbAvg = CalcDb : : dbPower ( magsqAvg ) ;
if ( m_tickCount % 4 = = 0 ) {
ui - > channelPower - > setText ( QString : : number ( powDbAvg , ' f ' , 1 ) ) ;
}
m_tickCount + + ;
}
2024-02-16 16:31:12 +00:00
void RadioAstronomyGUI : : updateRotatorList ( const AvailableChannelOrFeatureList & rotators , const QStringList & renameFrom , const QStringList & renameTo )
2021-10-12 11:31:14 +01:00
{
2024-07-10 22:59:13 +02:00
// Update rotator setting if it has been renamed
2024-02-16 16:31:12 +00:00
if ( renameFrom . contains ( m_settings . m_rotator ) )
{
m_settings . m_rotator = renameTo [ renameFrom . indexOf ( m_settings . m_rotator ) ] ;
2026-02-01 00:49:36 +01:00
applySettings ( QStringList ( " rotator " ) ) ;
2024-02-16 16:31:12 +00:00
}
2021-10-12 11:31:14 +01:00
// Update list of rotators
2022-03-28 20:12:25 +02:00
ui - > rotator - > blockSignals ( true ) ;
ui - > rotator - > clear ( ) ;
ui - > rotator - > addItem ( " None " ) ;
2024-02-16 16:31:12 +00:00
for ( const auto & rotator : rotators ) {
ui - > rotator - > addItem ( rotator . getLongId ( ) ) ;
2022-03-28 20:12:25 +02:00
}
// Rotator feature can be created after this plugin, so select it
// if the chosen rotator appears
int rotatorIndex = ui - > rotator - > findText ( m_settings . m_rotator ) ;
2023-05-23 22:29:06 +01:00
if ( rotatorIndex > = 0 )
{
2022-03-28 20:12:25 +02:00
ui - > rotator - > setCurrentIndex ( rotatorIndex ) ;
2023-05-23 22:29:06 +01:00
setColumnPrecisionFromRotator ( ) ;
}
else
{
2022-03-28 20:12:25 +02:00
ui - > rotator - > setCurrentIndex ( 0 ) ; // return to None
2021-10-12 11:31:14 +01:00
}
2022-03-28 20:12:25 +02:00
ui - > rotator - > blockSignals ( false ) ;
2021-10-12 11:31:14 +01:00
}
void RadioAstronomyGUI : : on_fftSize_currentIndexChanged ( int index )
{
m_settings . m_fftSize = 1 < < ( 4 + index ) ;
2026-02-01 00:49:36 +01:00
applySettings ( QStringList ( " fftSize " ) ) ;
2021-10-12 11:31:14 +01:00
updateIntegrationTime ( ) ;
}
void RadioAstronomyGUI : : on_fftWindow_currentIndexChanged ( int index )
{
m_settings . m_fftWindow = ( RadioAstronomySettings : : FFTWindow ) index ;
2026-02-01 00:49:36 +01:00
applySettings ( QStringList ( " fftWindow " ) ) ;
2021-10-12 11:31:14 +01:00
}
void RadioAstronomyGUI : : on_filterFreqs_editingFinished ( )
{
m_settings . m_filterFreqs = ui - > filterFreqs - > text ( ) ;
2026-02-01 00:49:36 +01:00
applySettings ( QStringList ( " filterFreqs " ) ) ;
2021-10-12 11:31:14 +01:00
}
void RadioAstronomyGUI : : on_gainVariation_valueChanged ( double value )
{
m_settings . m_gainVariation = value ;
2026-02-01 00:49:36 +01:00
applySettings ( QStringList ( " gainVariation " ) ) ;
2021-10-12 11:31:14 +01:00
updateTSys0 ( ) ;
}
// Can we allow user to enter text that is automatically looked up on SIMBAD?
void RadioAstronomyGUI : : on_sourceType_currentIndexChanged ( int index )
{
m_settings . m_sourceType = ( RadioAstronomySettings : : SourceType ) index ;
2026-02-01 00:49:36 +01:00
applySettings ( QStringList ( " sourceType " ) ) ;
2021-10-12 11:31:14 +01:00
if ( m_settings . m_sourceType = = RadioAstronomySettings : : SUN )
{
// Mean diameter of Sun in degrees from Earth
ui - > omegaS - > setValue ( 0.53 ) ;
ui - > omegaSUnits - > setCurrentIndex ( 0 ) ;
}
else if ( m_settings . m_sourceType = = RadioAstronomySettings : : CAS_A )
{
// Diameter of Cas A in degrees http://simbad.u-strasbg.fr/simbad/sim-id?Ident=Cassiopeia+A
ui - > omegaS - > setValue ( 0.08333 ) ;
ui - > omegaSUnits - > setCurrentIndex ( 0 ) ;
}
bool visible = index = = 1 | | index > = 3 ;
ui - > omegaS - > setVisible ( visible ) ;
ui - > omegaSUnits - > setVisible ( visible ) ;
}
void RadioAstronomyGUI : : on_omegaS_valueChanged ( double value )
{
m_settings . m_omegaS = value ;
if ( ( m_settings . m_sourceType = = RadioAstronomySettings : : SUN ) & & ( value ! = 0.53 ) ) {
ui - > sourceType - > setCurrentIndex ( ( int ) RadioAstronomySettings : : COMPACT ) ;
} else if ( ( m_settings . m_sourceType = = RadioAstronomySettings : : CAS_A ) & & ( value ! = 0.08333 ) ) {
ui - > sourceType - > setCurrentIndex ( ( int ) RadioAstronomySettings : : COMPACT ) ;
}
2026-02-01 00:49:36 +01:00
applySettings ( QStringList ( " omegaS " ) ) ;
2021-10-12 11:31:14 +01:00
}
void RadioAstronomyGUI : : updateOmegaA ( )
{
if ( m_settings . m_omegaAUnits = = RadioAstronomySettings : : DEGREES ) {
ui - > omegaA - > setText ( QString ( " %1 " ) . arg ( m_beamWidth , 0 , ' f ' , 1 ) ) ;
} else {
ui - > omegaA - > setText ( QString ( " %1 " ) . arg ( hpbwToSteradians ( m_beamWidth ) , 0 , ' f ' , 4 ) ) ;
}
}
void RadioAstronomyGUI : : on_omegaAUnits_currentIndexChanged ( int index )
{
m_settings . m_omegaAUnits = ( RadioAstronomySettings : : AngleUnits ) index ;
updateOmegaA ( ) ;
if ( m_settings . m_omegaAUnits = = RadioAstronomySettings : : DEGREES ) {
ui - > omegaALabel - > setText ( " HPBW " ) ;
} else {
ui - > omegaALabel - > setText ( QString ( " %1<sub>A</sub> " ) . arg ( QChar ( 937 ) ) ) ;
}
2026-02-01 00:49:36 +01:00
applySettings ( QStringList ( " omegaAUnits " ) ) ;
2021-10-12 11:31:14 +01:00
}
void RadioAstronomyGUI : : on_omegaSUnits_currentIndexChanged ( int index )
{
m_settings . m_omegaSUnits = ( RadioAstronomySettings : : AngleUnits ) index ;
if ( ( ( m_settings . m_sourceType = = RadioAstronomySettings : : SUN )
| | ( m_settings . m_sourceType = = RadioAstronomySettings : : CAS_A )
)
& & ( m_settings . m_omegaSUnits ! = RadioAstronomySettings : : DEGREES )
)
{
ui - > sourceType - > setCurrentIndex ( ( int ) RadioAstronomySettings : : COMPACT ) ;
}
2026-02-01 00:49:36 +01:00
applySettings ( QStringList ( " omegaSUnits " ) ) ;
2021-10-12 11:31:14 +01:00
}
void RadioAstronomyGUI : : on_starTracker_currentTextChanged ( const QString & text )
{
m_settings . m_starTracker = text ;
2026-02-01 00:49:36 +01:00
applySettings ( QStringList ( " starTracker " ) ) ;
2021-10-12 11:31:14 +01:00
}
void RadioAstronomyGUI : : on_rotator_currentTextChanged ( const QString & text )
{
m_settings . m_rotator = text ;
2026-02-01 00:49:36 +01:00
applySettings ( QStringList ( " rotator " ) ) ;
2023-05-23 22:29:06 +01:00
setColumnPrecisionFromRotator ( ) ;
}
void RadioAstronomyGUI : : setColumnPrecisionFromRotator ( )
{
// Match rotator precision
2023-12-05 12:32:53 +00:00
unsigned int featureSetIndex , featureIndex ;
2023-05-23 22:29:06 +01:00
2023-12-05 12:32:53 +00:00
if ( MainCore : : getFeatureIndexFromId ( m_settings . m_rotator , featureSetIndex , featureIndex ) )
{
2023-05-23 22:29:06 +01:00
int precision = 0 ;
if ( ChannelWebAPIUtils : : getFeatureSetting ( featureSetIndex , featureIndex , " precision " , precision ) )
{
int old = ( ( DecimalDelegate * ) ui - > powerTable - > itemDelegateForColumn ( POWER_COL_GAL_LAT ) ) - > getPrecision ( ) ;
( ( DecimalDelegate * ) ui - > powerTable - > itemDelegateForColumn ( POWER_COL_GAL_LAT ) ) - > setPrecision ( precision ) ;
( ( DecimalDelegate * ) ui - > powerTable - > itemDelegateForColumn ( POWER_COL_GAL_LON ) ) - > setPrecision ( precision ) ;
( ( DecimalDelegate * ) ui - > powerTable - > itemDelegateForColumn ( POWER_COL_AZ ) ) - > setPrecision ( precision ) ;
( ( DecimalDelegate * ) ui - > powerTable - > itemDelegateForColumn ( POWER_COL_EL ) ) - > setPrecision ( precision ) ;
2023-08-26 14:40:13 +01:00
( ( DecimalDelegate * ) ui - > powerTable - > itemDelegateForColumn ( POWER_COL_ROT_AZ ) ) - > setPrecision ( precision ) ;
( ( DecimalDelegate * ) ui - > powerTable - > itemDelegateForColumn ( POWER_COL_ROT_EL ) ) - > setPrecision ( precision ) ;
( ( DecimalDelegate * ) ui - > powerTable - > itemDelegateForColumn ( POWER_COL_ROT_AZ_OFF ) ) - > setPrecision ( precision ) ;
( ( DecimalDelegate * ) ui - > powerTable - > itemDelegateForColumn ( POWER_COL_ROT_EL_OFF ) ) - > setPrecision ( precision ) ;
2023-05-23 22:29:06 +01:00
if ( precision > old )
{
ui - > powerTable - > resizeColumnToContents ( POWER_COL_GAL_LAT ) ;
ui - > powerTable - > resizeColumnToContents ( POWER_COL_GAL_LON ) ;
ui - > powerTable - > resizeColumnToContents ( POWER_COL_AZ ) ;
ui - > powerTable - > resizeColumnToContents ( POWER_COL_EL ) ;
2023-08-26 14:40:13 +01:00
ui - > powerTable - > resizeColumnToContents ( POWER_COL_ROT_AZ ) ;
ui - > powerTable - > resizeColumnToContents ( POWER_COL_ROT_EL ) ;
ui - > powerTable - > resizeColumnToContents ( POWER_COL_ROT_AZ_OFF ) ;
ui - > powerTable - > resizeColumnToContents ( POWER_COL_ROT_EL_OFF ) ;
2023-05-23 22:29:06 +01:00
}
ui - > powerTable - > viewport ( ) - > update ( ) ;
}
}
2021-10-12 11:31:14 +01:00
}
void RadioAstronomyGUI : : on_showSensors_clicked ( )
{
RadioAstronomySensorDialog dialog ( & m_settings ) ;
if ( dialog . exec ( ) = = QDialog : : Accepted )
{
m_sensors [ 0 ] . setName ( m_settings . m_sensorName [ 0 ] ) ;
m_sensors [ 1 ] . setName ( m_settings . m_sensorName [ 1 ] ) ;
2026-02-01 00:49:36 +01:00
applySettings ( QStringList ( " sensorName " ) ) ;
2021-10-12 11:31:14 +01:00
}
}
void RadioAstronomyGUI : : sensorMeasurementReceived ( const RadioAstronomy : : MsgSensorMeasurement & measurement )
{
int sensor = measurement . getSensor ( ) ;
double value = measurement . getValue ( ) ;
QDateTime dateTime = measurement . getDateTime ( ) ;
SensorMeasurement * sm = new SensorMeasurement ( dateTime , value ) ;
m_sensors [ sensor ] . append ( sm ) ;
}
void RadioAstronomyGUI : : on_powerChartSelect_currentIndexChanged ( int index )
{
m_settings . m_powerYData = ( RadioAstronomySettings : : PowerYData ) index ;
ui - > powerYUnits - > clear ( ) ;
switch ( m_settings . m_powerYData )
{
case RadioAstronomySettings : : PY_POWER :
ui - > powerYUnits - > addItem ( " dBFS " ) ;
ui - > powerYUnits - > addItem ( " dBm " ) ;
ui - > powerYUnits - > addItem ( " Watts " ) ;
break ;
case RadioAstronomySettings : : PY_TSYS :
case RadioAstronomySettings : : PY_TSOURCE :
ui - > powerYUnits - > addItem ( " K " ) ;
break ;
case RadioAstronomySettings : : PY_FLUX :
ui - > powerYUnits - > addItem ( " SFU " ) ;
ui - > powerYUnits - > addItem ( " Jy " ) ;
break ;
case RadioAstronomySettings : : PY_2D_MAP :
ui - > powerYUnits - > addItem ( " dBFS " ) ;
ui - > powerYUnits - > addItem ( " dBm " ) ;
//ui->powerYUnits->addItem("Watts"); // No watts for now, as range spin boxes can't handle scientific notation
ui - > powerYUnits - > addItem ( " K " ) ;
break ;
2021-10-12 12:10:12 +01:00
default :
break ;
2021-10-12 11:31:14 +01:00
}
updatePowerMarkerTableVisibility ( ) ;
updatePowerChartWidgetsVisibility ( ) ;
plotPowerChart ( ) ;
2026-02-01 00:49:36 +01:00
applySettings ( QStringList ( " powerYData " ) ) ;
2021-10-12 11:31:14 +01:00
}
void RadioAstronomyGUI : : updatePowerChartWidgetsVisibility ( )
{
bool powerChart ;
if ( m_settings . m_powerYData ! = RadioAstronomySettings : : PY_2D_MAP ) {
powerChart = true ;
} else {
powerChart = false ;
}
ui - > powerShowLegend - > setVisible ( powerChart ) ;
ui - > powerShowSensor2 - > setVisible ( powerChart ) ;
ui - > powerShowSensor1 - > setVisible ( powerChart ) ;
ui - > powerShowAirTemp - > setVisible ( powerChart ) ;
ui - > powerShowTsys0 - > setVisible ( powerChart ) ;
ui - > powerShowAvg - > setVisible ( powerChart ) ;
ui - > powerShowGaussian - > setVisible ( powerChart ) ;
ui - > powerShowMarker - > setVisible ( powerChart ) ;
ui - > powerShowPeak - > setVisible ( powerChart ) ;
ui - > powerScaleWidgets - > setVisible ( powerChart ) ;
ui - > powerGaussianWidgets - > setVisible ( powerChart & & m_settings . m_powerShowGaussian ) ;
ui - > powerMarkerTableWidgets - > setVisible ( powerChart & & ( m_settings . m_powerPeaks | | m_settings . m_powerMarkers ) ) ;
ui - > power2DScaleWidgets - > setVisible ( ! powerChart ) ;
ui - > power2DColourScaleWidgets - > setVisible ( ! powerChart ) ;
2022-04-12 16:20:45 +02:00
getRollupContents ( ) - > arrangeRollups ( ) ;
2021-10-12 11:31:14 +01:00
}
int RadioAstronomyGUI : : powerYUnitsToIndex ( RadioAstronomySettings : : PowerYUnits units )
{
switch ( units )
{
case RadioAstronomySettings : : PY_DBFS :
return 0 ;
case RadioAstronomySettings : : PY_DBM :
return 1 ;
case RadioAstronomySettings : : PY_WATTS :
return 2 ;
case RadioAstronomySettings : : PY_KELVIN :
return 0 ;
case RadioAstronomySettings : : PY_SFU :
return 0 ;
case RadioAstronomySettings : : PY_JANSKY :
return 1 ;
}
return - 1 ;
}
void RadioAstronomyGUI : : on_powerYUnits_currentIndexChanged ( int index )
{
2021-10-12 12:10:12 +01:00
( void ) index ;
2021-10-12 11:31:14 +01:00
QString text = ui - > powerYUnits - > currentText ( ) ;
if ( text = = " dBFS " )
{
m_settings . m_powerYUnits = RadioAstronomySettings : : PY_DBFS ;
ui - > powerMarkerTable - > horizontalHeaderItem ( POWER_MARKER_COL_VALUE ) - > setText ( " Power (dBFS) " ) ;
ui - > powerColourScaleMin - > setDecimals ( 2 ) ;
ui - > powerColourScaleMax - > setDecimals ( 2 ) ;
}
else if ( text = = " dBm " )
{
m_settings . m_powerYUnits = RadioAstronomySettings : : PY_DBM ;
ui - > powerMarkerTable - > horizontalHeaderItem ( POWER_MARKER_COL_VALUE ) - > setText ( " Power (dBm) " ) ;
ui - > powerColourScaleMin - > setDecimals ( 2 ) ;
ui - > powerColourScaleMax - > setDecimals ( 2 ) ;
}
else if ( text = = " Watts " )
{
m_settings . m_powerYUnits = RadioAstronomySettings : : PY_WATTS ;
ui - > powerMarkerTable - > horizontalHeaderItem ( POWER_MARKER_COL_VALUE ) - > setText ( " Power (W) " ) ;
}
else if ( text = = " K " )
{
m_settings . m_powerYUnits = RadioAstronomySettings : : PY_KELVIN ;
ui - > powerMarkerTable - > horizontalHeaderItem ( POWER_MARKER_COL_VALUE ) - > setText ( " Temp (K) " ) ;
ui - > powerColourScaleMin - > setDecimals ( 0 ) ;
ui - > powerColourScaleMax - > setDecimals ( 0 ) ;
}
else if ( text = = " SFU " )
{
m_settings . m_powerYUnits = RadioAstronomySettings : : PY_SFU ;
ui - > powerMarkerTable - > horizontalHeaderItem ( POWER_MARKER_COL_VALUE ) - > setText ( " Flux (SFU) " ) ;
}
else if ( text = = " Jy " )
{
m_settings . m_powerYUnits = RadioAstronomySettings : : PY_JANSKY ;
ui - > powerMarkerTable - > horizontalHeaderItem ( POWER_MARKER_COL_VALUE ) - > setText ( " Flux (Jy) " ) ;
}
if ( text = = " dBFS " )
{
ui - > powerColourScaleMinUnits - > setText ( " dB " ) ;
ui - > powerColourScaleMaxUnits - > setText ( " dB " ) ;
}
else
{
ui - > powerColourScaleMinUnits - > setText ( text ) ;
ui - > powerColourScaleMaxUnits - > setText ( text ) ;
}
2026-02-01 00:49:36 +01:00
applySettings ( QStringList ( " powerYUnits " ) ) ;
2021-10-12 11:31:14 +01:00
plotPowerChart ( ) ;
}
void RadioAstronomyGUI : : on_spectrumChartSelect_currentIndexChanged ( int index )
{
updateSpectrumMarkerTableVisibility ( ) ; // If this follows updateSpectrumChartWidgetsVisibility, widgets are not redrawn properly.
updateSpectrumChartWidgetsVisibility ( ) ; // when switching from cal to spectrum if table is visible
if ( index = = 0 )
{
if ( m_fftChart ) {
ui - > spectrumChart - > setChart ( m_fftChart ) ;
}
}
else
{
if ( m_calChart ) {
ui - > spectrumChart - > setChart ( m_calChart ) ;
}
}
}
void RadioAstronomyGUI : : updateSpectrumChartWidgetsVisibility ( )
{
bool fft = ui - > spectrumChartSelect - > currentIndex ( ) = = 0 ;
ui - > spectrumYUnits - > setVisible ( fft ) ;
ui - > spectrumScaleWidgets - > setVisible ( fft ) ;
ui - > spectrumSelectWidgets - > setVisible ( fft ) ;
ui - > spectrumRefLineWidgets - > setVisible ( fft & & m_settings . m_spectrumRefLine ) ;
ui - > spectrumGaussianWidgets - > setVisible ( fft & & m_settings . m_spectrumTemp ) ;
ui - > calWidgets - > setVisible ( ! fft ) ;
ui - > recalibrate - > setVisible ( ! fft ) ;
ui - > startCalHot - > setVisible ( ! fft ) ;
ui - > startCalCold - > setVisible ( ! fft ) ;
ui - > clearCal - > setVisible ( ! fft ) ;
ui - > showCalSettings - > setVisible ( ! fft ) ;
ui - > spectrumShowRefLine - > setVisible ( fft ) ;
ui - > spectrumShowDistance - > setVisible ( fft ) ;
ui - > spectrumShowLAB - > setVisible ( fft ) ;
ui - > spectrumTemp - > setVisible ( fft ) ;
ui - > spectrumMarker - > setVisible ( fft ) ;
ui - > spectrumPeak - > setVisible ( fft ) ;
ui - > saveSpectrumChartImages - > setVisible ( fft ) ;
2022-04-12 16:20:45 +02:00
getRollupContents ( ) - > arrangeRollups ( ) ;
2021-10-12 11:31:14 +01:00
}
2024-07-10 22:59:13 +02:00
// Calculate mean, RMS and standard deviation
2021-10-12 11:31:14 +01:00
// Currently this is for all data - but could make it only for visible data
void RadioAstronomyGUI : : calcAverages ( )
{
qreal sum = 0.0 ;
qreal sumSq = 0.0 ;
QVector < QPointF > points = m_powerSeries - > pointsVector ( ) ;
for ( int i = 0 ; i < points . size ( ) ; i + + )
{
QPointF point = points . at ( i ) ;
qreal y = point . y ( ) ;
sum + = y ;
sumSq + = y * y ;
}
qreal mean = sum / points . size ( ) ;
qreal rms = std : : sqrt ( sumSq / points . size ( ) ) ;
qreal sumSqDiff = 0.0 ;
for ( int i = 0 ; i < points . size ( ) ; i + + )
{
QPointF point = points . at ( i ) ;
qreal y = point . y ( ) ;
qreal diff = y - mean ;
sumSqDiff + = diff * diff ;
}
qreal sigma = std : : sqrt ( sumSqDiff / points . size ( ) ) ;
ui - > powerMean - > setText ( QString : : number ( mean ) ) ;
ui - > powerRMS - > setText ( QString : : number ( rms ) ) ;
ui - > powerSD - > setText ( QString : : number ( sigma ) ) ;
}
QRgb RadioAstronomyGUI : : intensityToColor ( float intensity )
{
QRgb c1 , c2 ;
float scale ;
2021-10-12 12:10:12 +01:00
if ( std : : isnan ( intensity ) ) {
2021-10-12 11:31:14 +01:00
return qRgb ( 0 , 0 , 0 ) ;
}
// Get in range 0-1
intensity = ( intensity - m_settings . m_powerColourScaleMin ) / ( m_settings . m_powerColourScaleMax - m_settings . m_powerColourScaleMin ) ;
intensity = std : : min ( intensity , 1.0f ) ;
intensity = std : : max ( intensity , 0.0f ) ;
if ( m_settings . m_powerColourPalette [ 0 ] = = ' C ' )
{
// Colour heat map gradient
if ( intensity < = 0.25f )
{
c1 = qRgb ( 0 , 0 , 0x80 ) ; // Navy
c2 = qRgb ( 0 , 0 , 0xff ) ; // Blue
scale = intensity * 4.0f ;
}
else if ( intensity < = 0.5f )
{
c1 = qRgb ( 0 , 0 , 0xff ) ; // Blue
c2 = qRgb ( 0 , 0xff , 0 ) ; // Green
scale = ( intensity - 0.25f ) * 4.0f ;
}
else if ( intensity < = 0.75f )
{
c1 = qRgb ( 0 , 0xff , 0 ) ; // Green
c2 = qRgb ( 0xff , 0xff , 0 ) ; // Yellow
scale = ( intensity - 0.5f ) * 4.0f ;
}
else
{
c1 = qRgb ( 0xff , 0xff , 0 ) ; // Yellow
c2 = qRgb ( 0xff , 0 , 0 ) ; // Red
scale = ( intensity - 0.75f ) * 4.0f ;
}
int r , g , b ;
r = ( qRed ( c2 ) - qRed ( c1 ) ) * scale + qRed ( c1 ) ;
g = ( qGreen ( c2 ) - qGreen ( c1 ) ) * scale + qGreen ( c1 ) ;
b = ( qBlue ( c2 ) - qBlue ( c1 ) ) * scale + qBlue ( c1 ) ;
return qRgb ( r , g , b ) ;
}
else
{
// Greyscale
int g = 255 * intensity ;
return qRgb ( g , g , g ) ;
}
}
void RadioAstronomyGUI : : plot2DChart ( )
{
// Only plot if visible
if ( ui - > powerChartSelect - > currentIndex ( ) = = 4 )
{
QChart * oldChart = m_2DChart ;
m_2DChart = new QChart ( ) ;
m_2DChart - > layout ( ) - > setContentsMargins ( 0 , 0 , 0 , 0 ) ;
m_2DChart - > setMargins ( QMargins ( 1 , 1 , 1 , 1 ) ) ;
m_2DChart - > setTheme ( QChart : : ChartThemeDark ) ;
m_2DChart - > setTitle ( " " ) ;
m_2DXAxis = new QValueAxis ( ) ;
m_2DYAxis = new QValueAxis ( ) ;
m_2DXAxis - > setGridLineVisible ( false ) ;
m_2DYAxis - > setGridLineVisible ( false ) ;
set2DAxisTitles ( ) ;
m_2DXAxis - > setRange ( m_settings . m_power2DXMin , m_settings . m_power2DXMax ) ;
m_2DYAxis - > setRange ( m_settings . m_power2DYMin , m_settings . m_power2DYMax ) ;
m_2DChart - > addAxis ( m_2DXAxis , Qt : : AlignBottom ) ;
m_2DChart - > addAxis ( m_2DYAxis , Qt : : AlignLeft ) ;
m_2DMap . fill ( qRgb ( 0 , 0 , 0 ) ) ;
for ( int i = 0 ; i < m_fftMeasurements . size ( ) ; i + + ) {
update2DImage ( m_fftMeasurements [ i ] , i < m_fftMeasurements . size ( ) - 1 ) ;
}
2021-10-12 13:38:37 +01:00
if ( m_settings . m_powerColourAutoscale ) {
powerColourAutoscale ( ) ;
}
2021-10-12 11:31:14 +01:00
connect ( m_2DChart , SIGNAL ( plotAreaChanged ( QRectF ) ) , this , SLOT ( plotAreaChanged ( QRectF ) ) ) ;
ui - > powerChart - > setChart ( m_2DChart ) ;
delete oldChart ;
}
}
void RadioAstronomyGUI : : set2DAxisTitles ( )
{
if ( m_settings . m_power2DSweepType = = RadioAstronomySettings : : SWP_LB )
{
m_2DXAxis - > setTitleText ( QString ( " Galactic longitude (%1) " ) . arg ( QChar ( 0xb0 ) ) ) ;
m_2DYAxis - > setTitleText ( QString ( " Galactic latitude (%1) " ) . arg ( QChar ( 0xb0 ) ) ) ;
}
else
{
m_2DXAxis - > setTitleText ( QString ( " Azimuth (%1) " ) . arg ( QChar ( 0xb0 ) ) ) ;
m_2DYAxis - > setTitleText ( QString ( " Elevation (%1) " ) . arg ( QChar ( 0xb0 ) ) ) ;
}
}
void RadioAstronomyGUI : : update2DSettingsFromSweep ( )
{
if ( m_settings . m_runMode = = RadioAstronomySettings : : SWEEP )
{
ui - > power2DSweepType - > setCurrentIndex ( ( int ) m_settings . m_sweepType ) ;
// Calculate width and height of image - 1 pixel per sweep measurement
float sweep1Start , sweep1Stop ;
sweep1Start = m_settings . m_sweep1Start ;
sweep1Stop = m_settings . m_sweep1Stop ;
// Handle azimuth/l sweep through 0. E.g. 340deg -> 20deg with +vs step, or 20deg -> 340deg with -ve step
if ( ( m_settings . m_sweep1Stop < m_settings . m_sweep1Start ) & & ( m_settings . m_sweep1Step > 0 ) ) {
sweep1Stop = m_settings . m_sweep1Stop + 360.0 ;
} else if ( ( m_settings . m_sweep1Stop > m_settings . m_sweep1Start ) & & ( m_settings . m_sweep1Step < 0 ) ) {
sweep1Start + = 360.0 ;
}
int width = abs ( ( sweep1Stop - sweep1Start ) / m_settings . m_sweep1Step ) + 1 ;
int height = abs ( ( m_settings . m_sweep2Stop - m_settings . m_sweep2Start ) / m_settings . m_sweep2Step ) + 1 ;
ui - > power2DWidth - > setValue ( width ) ;
ui - > power2DHeight - > setValue ( height ) ;
// Subtract/add half a step so that pixels are centred on coordinates
int start1 = m_settings . m_sweep1Start - m_settings . m_sweep1Step / 2 ;
int stop1 = m_settings . m_sweep1Stop + m_settings . m_sweep1Step / 2 ;
if ( start1 < stop1 )
{
ui - > power2DXMin - > setValue ( start1 ) ;
ui - > power2DXMax - > setValue ( stop1 ) ;
}
else
{
ui - > power2DXMin - > setValue ( stop1 ) ;
ui - > power2DXMax - > setValue ( start1 ) ;
}
int start2 = m_settings . m_sweep2Start - m_settings . m_sweep2Step / 2 ;
int stop2 = m_settings . m_sweep2Stop + m_settings . m_sweep2Step / 2 ;
if ( start2 < stop2 )
{
ui - > power2DYMin - > setValue ( start2 ) ;
ui - > power2DYMax - > setValue ( stop2 ) ;
}
else
{
ui - > power2DYMin - > setValue ( stop2 ) ;
ui - > power2DYMax - > setValue ( start2 ) ;
}
m_sweepIndex = 0 ;
}
}
void RadioAstronomyGUI : : create2DImage ( )
{
// Intensity array holds power/temperature values which are then colourised in to a QImage
delete m_2DMapIntensity ;
int size = m_settings . m_power2DWidth * m_settings . m_power2DHeight ;
if ( size > 0 )
{
m_2DMapIntensity = new float [ size ] ;
for ( int i = 0 ; i < size ; i + + ) {
m_2DMapIntensity [ i ] = NAN ;
}
m_2DMapMin = std : : numeric_limits < float > : : max ( ) ;
m_2DMapMax = - std : : numeric_limits < float > : : max ( ) ;
QImage map ( m_settings . m_power2DWidth , m_settings . m_power2DHeight , QImage : : Format_ARGB32 ) ;
map . fill ( qRgb ( 0 , 0 , 0 ) ) ;
m_2DMap = map ;
}
else
{
m_2DMapIntensity = nullptr ;
m_2DMap = QImage ( ) ;
}
}
void RadioAstronomyGUI : : update2DImage ( FFTMeasurement * fft , bool skipCalcs )
{
if ( m_2DMap . width ( ) > 0 )
{
int x , y ;
if ( m_settings . m_power2DSweepType = = RadioAstronomySettings : : SWP_OFFSET )
{
y = fft - > m_sweepIndex / m_2DMap . width ( ) ;
x = fft - > m_sweepIndex % m_2DMap . width ( ) ;
if ( m_settings . m_sweep2Step > = 0 ) {
y = m_2DMap . height ( ) - 1 - y ;
}
if ( m_settings . m_sweep1Step < 0 ) {
x = m_2DMap . width ( ) - 1 - x ;
}
}
else
{
if ( m_settings . m_power2DSweepType = = RadioAstronomySettings : : SWP_LB )
{
x = ( int ) round ( fft - > m_l ) ;
y = ( int ) round ( fft - > m_b ) ;
}
else
{
x = ( int ) round ( fft - > m_azimuth ) ;
y = ( int ) round ( fft - > m_elevation ) ;
}
// Map coordinates to pixels
float xRange = m_settings . m_power2DXMax - m_settings . m_power2DXMin ;
float yRange = m_settings . m_power2DYMax - m_settings . m_power2DYMin ;
x = ( x - m_settings . m_power2DXMin ) * m_settings . m_power2DWidth / xRange ;
y = ( y - m_settings . m_power2DYMin ) * m_settings . m_power2DHeight / yRange ;
if ( yRange > = 0 ) {
y = m_2DMap . height ( ) - 1 - y ;
}
if ( xRange < 0 ) {
x = m_2DMap . width ( ) - 1 - x ;
}
}
if ( ( x > = 0 ) & & ( x < m_2DMap . width ( ) ) & & ( y > = 0 ) & & ( y < m_2DMap . height ( ) ) )
{
float intensity ;
switch ( m_settings . m_powerYUnits )
{
case RadioAstronomySettings : : PY_DBFS :
intensity = fft - > m_totalPowerdBFS ;
break ;
case RadioAstronomySettings : : PY_DBM :
intensity = fft - > m_totalPowerdBm ;
break ;
case RadioAstronomySettings : : PY_WATTS :
intensity = fft - > m_totalPowerWatts ;
break ;
case RadioAstronomySettings : : PY_KELVIN :
intensity = fft - > m_tSys ;
break ;
2021-10-12 12:10:12 +01:00
default :
break ;
2021-10-12 11:31:14 +01:00
}
float newMin = std : : min ( m_2DMapMin , intensity ) ;
float newMax = std : : max ( m_2DMapMax , intensity ) ;
bool rescale = false ;
if ( ( newMin ! = m_2DMapMin ) | | ( newMax ! = m_2DMapMax ) ) {
rescale = m_settings . m_powerColourAutoscale ;
}
m_2DMapMin = newMin ;
m_2DMapMax = newMax ;
m_2DMapIntensity [ y * m_2DMap . width ( ) + x ] = intensity ;
m_2DMap . setPixel ( x , y , intensityToColor ( intensity ) ) ;
if ( rescale & & ! skipCalcs ) {
powerColourAutoscale ( ) ;
}
if ( m_2DChart & & ! skipCalcs ) {
plotAreaChanged ( m_2DChart - > plotArea ( ) ) ;
}
}
}
}
void RadioAstronomyGUI : : recolour2DImage ( )
{
for ( int y = 0 ; y < m_2DMap . height ( ) ; y + + )
{
for ( int x = 0 ; x < m_2DMap . width ( ) ; x + + ) {
m_2DMap . setPixel ( x , y , intensityToColor ( m_2DMapIntensity [ y * m_2DMap . width ( ) + x ] ) ) ;
}
}
if ( m_2DChart ) {
plotAreaChanged ( m_2DChart - > plotArea ( ) ) ;
}
}
void RadioAstronomyGUI : : plotAreaChanged ( const QRectF & plotArea )
{
if ( ui - > powerChartSelect - > currentIndex ( ) = = 4 )
{
int width = static_cast < int > ( plotArea . width ( ) ) ;
int height = static_cast < int > ( plotArea . height ( ) ) ;
int viewW = static_cast < int > ( ui - > powerChart - > width ( ) ) ;
int viewH = static_cast < int > ( ui - > powerChart - > height ( ) ) ;
// Scale the image to fit plot area
QImage image = m_2DMap . scaled ( QSize ( width , height ) , Qt : : IgnoreAspectRatio ) ;
QImage translated ( viewW , viewH , QImage : : Format_ARGB32 ) ;
translated . fill ( Qt : : black ) ;
QPainter painter ( & translated ) ;
painter . drawImage ( plotArea . topLeft ( ) , image ) ;
m_2DChart - > setPlotAreaBackgroundBrush ( translated ) ;
m_2DChart - > setPlotAreaBackgroundVisible ( true ) ;
}
}
// Find min and max coordinates from existing data
void RadioAstronomyGUI : : power2DAutoscale ( )
{
if ( m_fftMeasurements . size ( ) > 0 )
{
float minX = std : : numeric_limits < float > : : max ( ) ;
float maxX = - std : : numeric_limits < float > : : max ( ) ;
float minY = std : : numeric_limits < float > : : max ( ) ;
float maxY = - std : : numeric_limits < float > : : max ( ) ;
for ( int i = 0 ; i < m_fftMeasurements . size ( ) ; i + + )
{
FFTMeasurement * fft = m_fftMeasurements [ i ] ;
float x , y ;
if ( m_settings . m_power2DSweepType = = RadioAstronomySettings : : SWP_LB )
{
x = fft - > m_l ;
y = fft - > m_b ;
}
else
{
x = fft - > m_azimuth ;
y = fft - > m_elevation ;
}
minX = std : : min ( minX , x ) ;
maxX = std : : max ( maxX , x ) ;
minY = std : : min ( minY , y ) ;
maxY = std : : max ( maxY , y ) ;
}
// Adjust so pixels are centered
float xAdjust = ( maxX - minX ) / m_2DMap . width ( ) / 2 ;
float yAdjust = ( maxY - minY ) / m_2DMap . height ( ) / 2 ;
ui - > power2DXMin - > setValue ( minX - xAdjust ) ;
ui - > power2DXMax - > setValue ( maxX + xAdjust ) ;
ui - > power2DYMin - > setValue ( minY - yAdjust ) ;
ui - > power2DYMax - > setValue ( maxY + xAdjust ) ;
}
}
void RadioAstronomyGUI : : on_power2DAutoscale_clicked ( )
{
power2DAutoscale ( ) ;
plot2DChart ( ) ;
}
void RadioAstronomyGUI : : on_power2DLinkSweep_toggled ( bool checked )
{
m_settings . m_power2DLinkSweep = checked ;
2026-02-01 00:49:36 +01:00
applySettings ( QStringList ( " power2DLinkSweep " ) ) ;
2021-10-12 11:31:14 +01:00
}
void RadioAstronomyGUI : : on_power2DSweepType_currentIndexChanged ( int index )
{
m_settings . m_power2DSweepType = ( RadioAstronomySettings : : SweepType ) index ;
2026-02-01 00:49:36 +01:00
applySettings ( QStringList ( " power2DSweepType " ) ) ;
2021-10-12 11:31:14 +01:00
plot2DChart ( ) ;
}
void RadioAstronomyGUI : : on_power2DWidth_valueChanged ( int value )
{
m_settings . m_power2DWidth = value ;
2026-02-01 00:49:36 +01:00
applySettings ( QStringList ( " power2DWidth " ) ) ;
2021-10-12 11:31:14 +01:00
create2DImage ( ) ;
plot2DChart ( ) ;
}
void RadioAstronomyGUI : : on_power2DHeight_valueChanged ( int value )
{
m_settings . m_power2DHeight = value ;
2026-02-01 00:49:36 +01:00
applySettings ( QStringList ( " power2DHeight " ) ) ;
2021-10-12 11:31:14 +01:00
create2DImage ( ) ;
plot2DChart ( ) ;
}
void RadioAstronomyGUI : : on_power2DXMin_valueChanged ( double value )
{
m_settings . m_power2DXMin = value ;
2026-02-01 00:49:36 +01:00
applySettings ( QStringList ( " power2DXMin " ) ) ;
2021-10-12 11:31:14 +01:00
if ( m_2DXAxis )
{
m_2DXAxis - > setMin ( m_settings . m_power2DXMin ) ;
plot2DChart ( ) ;
}
}
void RadioAstronomyGUI : : on_power2DXMax_valueChanged ( double value )
{
m_settings . m_power2DXMax = value ;
2026-02-01 00:49:36 +01:00
applySettings ( QStringList ( " power2DXMax " ) ) ;
2021-10-12 11:31:14 +01:00
if ( m_2DXAxis )
{
m_2DXAxis - > setMax ( m_settings . m_power2DXMax ) ;
plot2DChart ( ) ;
}
}
void RadioAstronomyGUI : : on_power2DYMin_valueChanged ( double value )
{
m_settings . m_power2DYMin = value ;
2026-02-01 00:49:36 +01:00
applySettings ( QStringList ( " power2DYMin " ) ) ;
2021-10-12 11:31:14 +01:00
if ( m_2DYAxis )
{
m_2DYAxis - > setMin ( m_settings . m_power2DYMin ) ;
plot2DChart ( ) ;
}
}
void RadioAstronomyGUI : : on_power2DYMax_valueChanged ( double value )
{
m_settings . m_power2DYMax = value ;
2026-02-01 00:49:36 +01:00
applySettings ( QStringList ( " power2DYMax " ) ) ;
2021-10-12 11:31:14 +01:00
if ( m_2DYAxis )
{
m_2DYAxis - > setMax ( m_settings . m_power2DYMax ) ;
plot2DChart ( ) ;
}
}
void RadioAstronomyGUI : : powerColourAutoscale ( )
{
int width = m_2DMap . width ( ) ;
int height = m_2DMap . height ( ) ;
float newMin = std : : numeric_limits < float > : : max ( ) ;
float newMax = - std : : numeric_limits < float > : : max ( ) ;
for ( int i = 0 ; i < width * height ; i + + )
{
2021-10-12 12:10:12 +01:00
if ( ! std : : isnan ( m_2DMapIntensity [ i ] ) )
2021-10-12 11:31:14 +01:00
{
newMin = std : : min ( newMin , m_2DMapIntensity [ i ] ) ;
newMax = std : : max ( newMax , m_2DMapIntensity [ i ] ) ;
}
}
if ( ( newMin ! = ui - > powerColourScaleMin - > value ( ) ) | | ( newMax ! = ui - > powerColourScaleMax - > value ( ) ) )
{
ui - > powerColourScaleMin - > setValue ( std : : floor ( newMin * 10.0 ) / 10.0 ) ;
ui - > powerColourScaleMax - > setValue ( std : : ceil ( newMax * 10.0 ) / 10.0 ) ;
}
}
void RadioAstronomyGUI : : on_powerColourAutoscale_toggled ( bool checked )
{
m_settings . m_powerColourAutoscale = checked ;
2026-02-01 00:49:36 +01:00
applySettings ( QStringList ( " powerColourAutoscale " ) ) ;
2021-10-12 11:31:14 +01:00
if ( m_settings . m_powerColourAutoscale ) {
powerColourAutoscale ( ) ;
}
ui - > powerColourScaleMin - > setEnabled ( ! m_settings . m_powerColourAutoscale ) ;
ui - > powerColourScaleMax - > setEnabled ( ! m_settings . m_powerColourAutoscale ) ;
}
void RadioAstronomyGUI : : updatePowerColourScaleStep ( )
{
float diff = abs ( m_settings . m_powerColourScaleMax - m_settings . m_powerColourScaleMin ) ;
double step = ( diff < = 1.0f ) ? 0.1 : 1.0f ;
ui - > powerColourScaleMin - > setSingleStep ( step ) ;
ui - > powerColourScaleMax - > setSingleStep ( step ) ;
}
void RadioAstronomyGUI : : on_powerColourScaleMin_valueChanged ( double value )
{
m_settings . m_powerColourScaleMin = value ;
updatePowerColourScaleStep ( ) ;
2026-02-01 00:49:36 +01:00
applySettings ( QStringList ( " powerColourScaleMin " ) ) ;
2021-10-12 11:31:14 +01:00
recolour2DImage ( ) ;
}
void RadioAstronomyGUI : : on_powerColourScaleMax_valueChanged ( double value )
{
m_settings . m_powerColourScaleMax = value ;
updatePowerColourScaleStep ( ) ;
2026-02-01 00:49:36 +01:00
applySettings ( QStringList ( " powerColourScaleMax " ) ) ;
2021-10-12 11:31:14 +01:00
recolour2DImage ( ) ;
}
void RadioAstronomyGUI : : on_powerColourPalette_currentIndexChanged ( int index )
{
( void ) index ;
m_settings . m_powerColourPalette = ui - > powerColourPalette - > currentText ( ) ;
2026-02-01 00:49:36 +01:00
applySettings ( QStringList ( " powerColourPalette " ) ) ;
2021-10-12 11:31:14 +01:00
recolour2DImage ( ) ;
}
void RadioAstronomyGUI : : plotPowerChart ( )
{
if ( ui - > powerChartSelect - > currentIndex ( ) = = 4 ) {
plot2DChart ( ) ;
} else {
plotPowerVsTimeChart ( ) ;
}
}
void RadioAstronomyGUI : : plotPowerVsTimeChart ( )
{
QChart * oldChart = m_powerChart ;
m_powerChart = new QChart ( ) ;
m_powerChart - > layout ( ) - > setContentsMargins ( 0 , 0 , 0 , 0 ) ;
m_powerChart - > setMargins ( QMargins ( 1 , 1 , 1 , 1 ) ) ;
m_powerChart - > setTheme ( QChart : : ChartThemeDark ) ;
m_powerChart - > legend ( ) - > setAlignment ( Qt : : AlignRight ) ;
m_powerChart - > legend ( ) - > setVisible ( m_settings . m_powerLegend ) ;
// Create measurement data series
m_powerSeries = new QLineSeries ( ) ;
2022-09-26 12:46:52 +01:00
m_powerSeries - > setVisible ( m_settings . m_powerShowMeasurement ) ;
2021-10-12 11:31:14 +01:00
connect ( m_powerSeries , & QXYSeries : : clicked , this , & RadioAstronomyGUI : : powerSeries_clicked ) ;
// Plot peak info
m_powerPeakSeries = new QScatterSeries ( ) ;
m_powerPeakSeries - > setName ( " Peak " ) ;
m_powerPeakSeries - > setPointLabelsVisible ( true ) ;
m_powerPeakSeries - > setPointLabelsFormat ( " @yPoint " ) ; // Qt can't display dates, so omit @xPoint
m_powerPeakSeries - > setMarkerSize ( 5 ) ;
m_powerPeakSeries - > setVisible ( m_settings . m_powerPeaks ) ;
// Markers
m_powerMarkerSeries = new QScatterSeries ( ) ;
m_powerMarkerSeries - > setName ( " Marker " ) ;
m_powerMarkerSeries - > setPointLabelsVisible ( true ) ;
m_powerMarkerSeries - > setPointLabelsFormat ( " @yPoint " ) ;
m_powerMarkerSeries - > setMarkerSize ( 5 ) ;
m_powerMarkerSeries - > setVisible ( m_settings . m_powerMarkers ) ;
// Noise
m_powerTsys0Series = new QLineSeries ( ) ;
m_powerTsys0Series - > setName ( " Tsys0 " ) ;
m_powerTsys0Series - > setVisible ( m_settings . m_powerShowTsys0 ) ;
// Air temperature
m_airTemps . init ( " Air temp " , m_settings . m_powerShowAirTemp ) ;
// Gaussian
m_powerGaussianSeries = new QLineSeries ( ) ;
m_powerGaussianSeries - > setName ( " Gaussian fit " ) ;
m_powerGaussianSeries - > setVisible ( m_settings . m_powerShowGaussian ) ;
2022-09-26 12:46:52 +01:00
// Filtered measurement
m_powerFilteredSeries = new QLineSeries ( ) ;
m_powerFilteredSeries - > setName ( " Filtered " ) ;
m_powerFilteredSeries - > setVisible ( m_settings . m_powerShowFiltered ) ;
plotPowerFiltered ( ) ;
2021-10-12 11:31:14 +01:00
// Sensors
for ( int i = 0 ; i < RADIOASTRONOMY_SENSORS ; i + + ) {
m_sensors [ i ] . init ( m_settings . m_sensorName [ i ] , m_settings . m_sensorVisible [ i ] ) ;
}
// Reset min/max and peaks
m_powerMin = std : : numeric_limits < double > : : max ( ) ;
m_powerMax = - std : : numeric_limits < double > : : max ( ) ;
m_powerPeakValid = false ;
// Create X axis
m_powerXAxis = new QDateTimeAxis ( ) ;
int rows = ui - > powerTable - > rowCount ( ) ;
QString dateTimeFormat = " hh:mm:ss " ;
m_powerXAxisSameDay = true ;
if ( rows > 1 )
{
QDate start = ui - > powerTable - > item ( 0 , POWER_COL_DATE ) - > data ( Qt : : DisplayRole ) . toDate ( ) ;
QDate end = ui - > powerTable - > item ( rows - 1 , POWER_COL_DATE ) - > data ( Qt : : DisplayRole ) . toDate ( ) ;
if ( start ! = end )
{
dateTimeFormat = QString ( " %1 hh:mm " ) . arg ( QLocale : : system ( ) . dateFormat ( QLocale : : ShortFormat ) ) ;
m_powerXAxisSameDay = false ;
}
}
m_powerXAxis - > setFormat ( dateTimeFormat ) ;
m_powerXAxis - > setRange ( ui - > powerStartTime - > dateTime ( ) , ui - > powerEndTime - > dateTime ( ) ) ;
ui - > powerStartTime - > setDisplayFormat ( dateTimeFormat ) ;
ui - > powerEndTime - > setDisplayFormat ( dateTimeFormat ) ;
// Create Y axis
m_powerYAxis = new QValueAxis ( ) ;
m_powerXAxis - > setTitleText ( " Time " ) ;
calcPowerChartTickCount ( size ( ) . width ( ) ) ;
switch ( m_settings . m_powerYData )
{
case RadioAstronomySettings : : PY_POWER :
m_powerSeries - > setName ( " Measurement " ) ;
switch ( m_settings . m_powerYUnits )
{
case RadioAstronomySettings : : PY_DBFS :
m_powerYAxis - > setTitleText ( " Power (dBFS) " ) ;
break ;
case RadioAstronomySettings : : PY_DBM :
m_powerYAxis - > setTitleText ( " Power (dBm) " ) ;
break ;
case RadioAstronomySettings : : PY_WATTS :
m_powerYAxis - > setTitleText ( " Power (Watts) " ) ;
break ;
2021-10-12 12:10:12 +01:00
default :
break ;
2021-10-12 11:31:14 +01:00
}
break ;
case RadioAstronomySettings : : PY_TSYS :
m_powerSeries - > setName ( " Tsys " ) ;
m_powerYAxis - > setTitleText ( " Tsys (K) " ) ;
break ;
case RadioAstronomySettings : : PY_TSOURCE :
m_powerSeries - > setName ( " Tsource " ) ;
m_powerYAxis - > setTitleText ( " Tsource (K) " ) ;
break ;
case RadioAstronomySettings : : PY_FLUX :
m_powerSeries - > setName ( " Flux density " ) ;
switch ( m_settings . m_powerYUnits )
{
case RadioAstronomySettings : : PY_SFU :
m_powerYAxis - > setTitleText ( " Flux density (SFU) " ) ;
break ;
case RadioAstronomySettings : : PY_JANSKY :
m_powerYAxis - > setTitleText ( " Flux density (Jy) " ) ;
break ;
2021-10-12 12:10:12 +01:00
default :
break ;
2021-10-12 11:31:14 +01:00
}
break ;
2021-10-12 12:17:57 +01:00
default :
break ;
2021-10-12 11:31:14 +01:00
}
m_powerChart - > addAxis ( m_powerXAxis , Qt : : AlignBottom ) ;
m_powerChart - > addAxis ( m_powerYAxis , Qt : : AlignLeft ) ;
m_powerChart - > addAxis ( m_airTemps . yAxis ( ) , Qt : : AlignRight ) ;
for ( int i = 0 ; i < RADIOASTRONOMY_SENSORS ; i + + ) {
m_powerChart - > addAxis ( m_sensors [ i ] . yAxis ( ) , Qt : : AlignRight ) ;
}
// Add data to series and calculate peaks
for ( int i = 0 ; i < m_fftMeasurements . size ( ) ; i + + ) {
addToPowerSeries ( m_fftMeasurements [ i ] , i < ( m_fftMeasurements . size ( ) - 1 ) ) ;
}
m_airTemps . addAllToSeries ( ) ;
for ( int i = 0 ; i < RADIOASTRONOMY_SENSORS ; i + + ) {
m_sensors [ i ] . addAllToSeries ( ) ;
}
m_powerChart - > addSeries ( m_powerSeries ) ;
m_powerSeries - > attachAxis ( m_powerXAxis ) ;
m_powerSeries - > attachAxis ( m_powerYAxis ) ;
m_powerChart - > addSeries ( m_powerTsys0Series ) ;
m_powerTsys0Series - > attachAxis ( m_powerXAxis ) ;
m_powerTsys0Series - > attachAxis ( m_powerYAxis ) ;
m_powerChart - > addSeries ( m_powerGaussianSeries ) ;
m_powerGaussianSeries - > attachAxis ( m_powerXAxis ) ;
m_powerGaussianSeries - > attachAxis ( m_powerYAxis ) ;
m_airTemps . addToChart ( m_powerChart , m_powerXAxis ) ;
for ( int i = 0 ; i < RADIOASTRONOMY_SENSORS ; i + + ) {
m_sensors [ i ] . addToChart ( m_powerChart , m_powerXAxis ) ;
}
2022-09-26 12:46:52 +01:00
m_powerChart - > addSeries ( m_powerFilteredSeries ) ;
m_powerFilteredSeries - > attachAxis ( m_powerXAxis ) ;
m_powerFilteredSeries - > attachAxis ( m_powerYAxis ) ;
2021-10-12 11:31:14 +01:00
m_powerChart - > addSeries ( m_powerPeakSeries ) ;
m_powerPeakSeries - > attachAxis ( m_powerXAxis ) ;
m_powerPeakSeries - > attachAxis ( m_powerYAxis ) ;
m_powerChart - > addSeries ( m_powerMarkerSeries ) ;
m_powerMarkerSeries - > attachAxis ( m_powerXAxis ) ;
m_powerMarkerSeries - > attachAxis ( m_powerYAxis ) ;
// Dark theme only has 5 colours for series, so use an extra unique colour (purple)
QPen pen ( QColor ( qRgb ( 146 , 65 , 146 ) ) , 2 , Qt : : SolidLine ) ;
m_sensors [ 1 ] . setPen ( pen ) ;
// Don't have peaks and markers in legend
m_powerChart - > legend ( ) - > markers ( m_powerPeakSeries ) [ 0 ] - > setVisible ( false ) ;
m_powerChart - > legend ( ) - > markers ( m_powerMarkerSeries ) [ 0 ] - > setVisible ( false ) ;
ui - > powerChart - > setChart ( m_powerChart ) ;
delete oldChart ;
}
void RadioAstronomyGUI : : calCompletetReceived ( const RadioAstronomy : : MsgCalComplete & measurement )
{
bool hot = measurement . getHot ( ) ;
int size = measurement . getSize ( ) ;
Real * data = measurement . getCal ( ) ;
FFTMeasurement * fft = new FFTMeasurement ( ) ;
if ( hot )
{
delete m_calHot ;
m_calHot = fft ;
ui - > startCalHot - > setStyleSheet ( " QToolButton { background: none; } " ) ;
}
else
{
delete m_calCold ;
m_calCold = fft ;
ui - > startCalCold - > setStyleSheet ( " QToolButton { background: none; } " ) ;
}
fft - > m_fftData = data ;
fft - > m_fftSize = size ;
fft - > m_dateTime = measurement . getDateTime ( ) ;
fft - > m_centerFrequency = m_centerFrequency ;
fft - > m_sampleRate = m_settings . m_sampleRate ;
fft - > m_integration = m_settings . m_integration ;
fft - > m_rfBandwidth = m_settings . m_rfBandwidth ;
fft - > m_omegaA = calcOmegaA ( ) ;
fft - > m_omegaS = calcOmegaS ( ) ;
fft - > m_coordsValid = m_coordsValid ;
fft - > m_ra = m_ra ;
fft - > m_dec = m_dec ;
fft - > m_azimuth = m_azimuth ;
fft - > m_elevation = m_elevation ;
fft - > m_l = m_l ;
fft - > m_b = m_b ;
fft - > m_vBCRS = m_vBCRS ;
fft - > m_vLSR = m_vLSR ;
fft - > m_solarFlux = m_solarFlux ;
fft - > m_airTemp = m_airTemps . lastValue ( ) ;
fft - > m_skyTemp = m_skyTemp ;
for ( int i = 0 ; i < RADIOASTRONOMY_SENSORS ; i + + ) {
fft - > m_sensor [ i ] = m_sensors [ i ] . lastValue ( ) ;
}
fft - > m_tSys0 = calcTSys0 ( ) ;
fft - > m_baseline = m_settings . m_spectrumBaseline ;
2023-08-26 14:40:13 +01:00
getRotatorData ( fft ) ;
2021-10-12 11:31:14 +01:00
if ( ! hot ) {
ui - > calTsky - > setText ( QString : : number ( m_skyTemp , ' f ' , 1 ) ) ;
}
calcFFTTotalPower ( fft ) ;
calcCalAvgDiff ( ) ;
calibrate ( ) ;
calcFFTTemperatures ( fft ) ;
calcFFTTotalTemperature ( fft ) ;
plotCalMeasurements ( ) ;
}
void RadioAstronomyGUI : : plotCalMeasurements ( )
{
m_calHotSeries - > clear ( ) ;
m_calColdSeries - > clear ( ) ;
if ( m_calHot | | m_calCold )
{
float minVal = std : : numeric_limits < float > : : max ( ) ;
float maxVal = - std : : numeric_limits < float > : : max ( ) ;
double size ;
double sampleRate ;
double centerFrequency ;
if ( m_calCold & & m_calHot )
{
size = ( double ) std : : min ( m_calCold - > m_fftSize , m_calHot - > m_fftSize ) ;
sampleRate = ( double ) m_calCold - > m_sampleRate ;
centerFrequency = ( double ) m_calCold - > m_centerFrequency ;
}
else if ( m_calCold )
{
size = ( double ) m_calCold - > m_fftSize ;
sampleRate = ( double ) m_calCold - > m_sampleRate ;
centerFrequency = ( double ) m_calCold - > m_centerFrequency ;
}
else
{
size = ( double ) m_calHot - > m_fftSize ;
sampleRate = ( double ) m_calHot - > m_sampleRate ;
centerFrequency = ( double ) m_calHot - > m_centerFrequency ;
}
double binRes = sampleRate / size ;
double startFreq = centerFrequency - sampleRate / 2.0 ;
double freq = startFreq ;
for ( int i = 0 ; i < size ; i + + )
{
float value ;
bool hotValid = m_calHot & & ( i < m_calHot - > m_fftSize ) ;
bool coldValid = m_calCold & & ( i < m_calCold - > m_fftSize ) ;
if ( hotValid )
{
value = CalcDb : : dbPower ( m_calHot - > m_fftData [ i ] ) ;
m_calHotSeries - > append ( freq / 1e6 , value ) ;
minVal = std : : min ( minVal , value ) ;
maxVal = std : : max ( maxVal , value ) ;
}
if ( coldValid )
{
value = CalcDb : : dbPower ( m_calCold - > m_fftData [ i ] ) ;
m_calColdSeries - > append ( freq / 1e6 , value ) ;
minVal = std : : min ( minVal , value ) ;
maxVal = std : : max ( maxVal , value ) ;
}
freq + = binRes ;
}
m_calYAxis - > setRange ( minVal , maxVal ) ;
double startFreqMHz = centerFrequency / 1e6 - sampleRate / 1e6 / 2.0 ;
double endFreqMHz = centerFrequency / 1e6 + sampleRate / 1e6 / 2.0 ;
m_calXAxis - > setRange ( startFreqMHz , endFreqMHz ) ;
m_calXAxis - > setReverse ( m_settings . m_spectrumReverseXAxis ) ;
}
}
void RadioAstronomyGUI : : plotCalSpectrum ( )
{
QChart * oldChart = m_calChart ;
m_calChart = new QChart ( ) ;
m_calChart - > layout ( ) - > setContentsMargins ( 0 , 0 , 0 , 0 ) ;
m_calChart - > setMargins ( QMargins ( 1 , 1 , 1 , 1 ) ) ;
m_calChart - > setTheme ( QChart : : ChartThemeDark ) ;
m_calChart - > legend ( ) - > setAlignment ( Qt : : AlignRight ) ;
m_calChart - > legend ( ) - > setVisible ( m_settings . m_spectrumLegend ) ;
m_calHotSeries = new QLineSeries ( ) ;
m_calHotSeries - > setName ( " Hot " ) ;
m_calColdSeries = new QLineSeries ( ) ;
m_calColdSeries - > setName ( " Cold " ) ;
m_calXAxis = new QValueAxis ( ) ;
m_calYAxis = new QValueAxis ( ) ;
m_calChart - > addAxis ( m_calXAxis , Qt : : AlignBottom ) ;
m_calChart - > addAxis ( m_calYAxis , Qt : : AlignLeft ) ;
m_calXAxis - > setTitleText ( " Frequency (MHz) " ) ;
calcSpectrumChartTickCount ( m_calXAxis , size ( ) . width ( ) ) ;
m_calYAxis - > setTitleText ( " Power (dBFS) " ) ;
m_calChart - > addSeries ( m_calHotSeries ) ;
m_calHotSeries - > attachAxis ( m_calXAxis ) ;
m_calHotSeries - > attachAxis ( m_calYAxis ) ;
m_calChart - > addSeries ( m_calColdSeries ) ;
m_calColdSeries - > attachAxis ( m_calXAxis ) ;
m_calColdSeries - > attachAxis ( m_calYAxis ) ;
plotCalMeasurements ( ) ;
ui - > spectrumChart - > setChart ( m_calChart ) ;
delete oldChart ;
}
void RadioAstronomyGUI : : on_spectrumReference_valueChanged ( double value )
{
m_settings . m_spectrumReference = value ;
spectrumUpdateYRange ( ) ;
if ( ! m_settings . m_spectrumAutoscale ) {
2026-02-01 00:49:36 +01:00
applySettings ( QStringList ( " spectrumReference " ) ) ;
2021-10-12 11:31:14 +01:00
}
}
void RadioAstronomyGUI : : on_spectrumRange_valueChanged ( double value )
{
m_settings . m_spectrumRange = value ;
if ( m_settings . m_spectrumRange < = 1.0 )
{
ui - > spectrumRange - > setSingleStep ( 0.1 ) ;
ui - > spectrumRange - > setDecimals ( 2 ) ;
ui - > spectrumReference - > setDecimals ( 2 ) ;
}
else
{
ui - > spectrumRange - > setSingleStep ( 1.0 ) ;
ui - > spectrumRange - > setDecimals ( 1 ) ;
ui - > spectrumReference - > setDecimals ( 1 ) ;
}
spectrumUpdateYRange ( ) ;
if ( ! m_settings . m_spectrumAutoscale ) {
2026-02-01 00:49:36 +01:00
applySettings ( QStringList ( " spectrumRange " ) ) ;
2021-10-12 11:31:14 +01:00
}
}
void RadioAstronomyGUI : : on_spectrumSpan_valueChanged ( double value )
{
m_settings . m_spectrumSpan = value ;
spectrumUpdateXRange ( ) ;
2026-02-01 00:49:36 +01:00
applySettings ( QStringList ( " spectrumSpan " ) ) ;
2021-10-12 11:31:14 +01:00
}
void RadioAstronomyGUI : : on_spectrumCenterFreq_valueChanged ( double value )
{
double offset ;
FFTMeasurement * fft = currentFFT ( ) ;
if ( fft ) {
offset = value - fft - > m_centerFrequency / 1e6 ;
} else {
offset = value - m_centerFrequency / 1e6 ;
}
m_settings . m_spectrumCenterFreqOffset = offset ;
spectrumUpdateXRange ( ) ;
2026-02-01 00:49:36 +01:00
applySettings ( QStringList ( " spectrumCenterFreqOffset " ) ) ;
2021-10-12 11:31:14 +01:00
}
void RadioAstronomyGUI : : spectrumUpdateXRange ( FFTMeasurement * fft )
{
if ( ! fft ) {
fft = currentFFT ( ) ;
}
if ( m_fftXAxis & & fft )
{
double startFreqMHz = fft - > m_centerFrequency / 1e6 - m_settings . m_spectrumSpan / 2.0 ;
double endFreqMHz = fft - > m_centerFrequency / 1e6 + m_settings . m_spectrumSpan / 2.0 ;
m_fftXAxis - > setRange ( startFreqMHz + m_settings . m_spectrumCenterFreqOffset , endFreqMHz + m_settings . m_spectrumCenterFreqOffset ) ;
double lineFreqMHz = ui - > spectrumLineFrequency - > value ( ) ;
double lineFreq = lineFreqMHz * 1e6 ;
double startFreq = fft - > m_centerFrequency + m_settings . m_spectrumSpan * 1e6 / 2.0 + m_settings . m_spectrumCenterFreqOffset * 1e6 ;
double endFreq = fft - > m_centerFrequency - m_settings . m_spectrumSpan * 1e6 / 2.0 + m_settings . m_spectrumCenterFreqOffset * 1e6 ;
m_fftDopplerAxis - > setRange ( dopplerToVelocity ( lineFreq , startFreq , fft ) ,
dopplerToVelocity ( lineFreq , endFreq , fft ) ) ;
}
}
void RadioAstronomyGUI : : spectrumUpdateYRange ( FFTMeasurement * fft )
{
if ( ! fft ) {
fft = currentFFT ( ) ;
}
if ( m_fftYAxis & & fft ) {
m_fftYAxis - > setRange ( m_settings . m_spectrumReference - m_settings . m_spectrumRange , m_settings . m_spectrumReference ) ;
}
}
void RadioAstronomyGUI : : spectrumAutoscale ( )
{
if ( m_settings . m_spectrumAutoscale )
{
on_spectrumAutoscaleX_clicked ( ) ;
on_spectrumAutoscaleY_clicked ( ) ;
}
}
// Scale Y axis according to min and max values
void RadioAstronomyGUI : : on_spectrumAutoscale_toggled ( bool checked )
{
m_settings . m_spectrumAutoscale = checked ;
ui - > spectrumAutoscaleX - > setEnabled ( ! m_settings . m_spectrumAutoscale ) ;
ui - > spectrumAutoscaleY - > setEnabled ( ! m_settings . m_spectrumAutoscale ) ;
ui - > spectrumReference - > setEnabled ( ! m_settings . m_spectrumAutoscale ) ;
ui - > spectrumRange - > setEnabled ( ! m_settings . m_spectrumAutoscale ) ;
ui - > spectrumCenterFreq - > setEnabled ( ! m_settings . m_spectrumAutoscale ) ;
ui - > spectrumSpan - > setEnabled ( ! m_settings . m_spectrumAutoscale ) ;
spectrumAutoscale ( ) ;
2026-02-01 00:49:36 +01:00
applySettings ( QStringList ( " spectrumAutoscale " ) ) ;
2021-10-12 11:31:14 +01:00
}
// Get minimum and maximum values in a series
// Assumes minVal and maxVal are initialised
static bool seriesMinAndMax ( QLineSeries * series , qreal & minVal , qreal & maxVal )
{
QVector < QPointF > points = series - > pointsVector ( ) ;
for ( int i = 0 ; i < points . size ( ) ; i + + )
{
qreal power = points [ i ] . y ( ) ;
minVal = std : : min ( minVal , power ) ;
maxVal = std : : max ( maxVal , power ) ;
}
return points . size ( ) > 0 ;
}
// Scale Y axis according to min and max values
void RadioAstronomyGUI : : on_spectrumAutoscaleY_clicked ( )
{
double minVal = std : : numeric_limits < double > : : max ( ) ;
double maxVal = - std : : numeric_limits < double > : : max ( ) ;
bool v0 = false , v1 = false ;
if ( m_fftSeries ) {
v0 = seriesMinAndMax ( m_fftSeries , minVal , maxVal ) ;
}
if ( m_fftLABSeries & & m_settings . m_spectrumLAB ) {
v1 = seriesMinAndMax ( m_fftLABSeries , minVal , maxVal ) ;
}
if ( v0 | | v1 )
{
double range = ( maxVal - minVal ) * 1.2 ; // 20% wider than signal range, for space for markers
range = std : : max ( 0.1 , range ) ; // Don't be smaller than minimum value we can set in GUI
ui - > spectrumRange - > setValue ( range ) ; // Call before setting reference, so number of decimals are adjusted
ui - > spectrumReference - > setValue ( maxVal + range * 0.15 ) ;
}
}
// Scale X axis according to min and max values
void RadioAstronomyGUI : : on_spectrumAutoscaleX_clicked ( )
{
FFTMeasurement * fft = currentFFT ( ) ;
if ( fft )
{
ui - > spectrumSpan - > setValue ( fft - > m_sampleRate / 1e6 ) ;
ui - > spectrumCenterFreq - > setValue ( fft - > m_centerFrequency / 1e6 ) ;
}
else
{
ui - > spectrumSpan - > setValue ( m_basebandSampleRate / 1e6 ) ;
ui - > spectrumCenterFreq - > setValue ( m_centerFrequency / 1e6 ) ;
}
}
RadioAstronomyGUI : : FFTMeasurement * RadioAstronomyGUI : : currentFFT ( )
{
int index = ui - > spectrumIndex - > value ( ) ;
if ( ( index > = 0 ) & & ( index < m_fftMeasurements . size ( ) ) ) {
return m_fftMeasurements [ index ] ;
} else {
return nullptr ;
}
}
void RadioAstronomyGUI : : on_spectrumYUnits_currentIndexChanged ( int index )
{
2021-10-12 12:17:57 +01:00
( void ) index ;
2021-10-12 11:31:14 +01:00
QString text = ui - > spectrumYUnits - > currentText ( ) ;
if ( text = = " dBFS " )
{
m_settings . m_spectrumYScale = RadioAstronomySettings : : SY_DBFS ;
ui - > spectrumMarkerTable - > horizontalHeaderItem ( SPECTRUM_MARKER_COL_VALUE ) - > setText ( " Power (dBFS) " ) ;
}
else if ( text = = " SNR " )
{
m_settings . m_spectrumYScale = RadioAstronomySettings : : SY_SNR ;
ui - > spectrumMarkerTable - > horizontalHeaderItem ( SPECTRUM_MARKER_COL_VALUE ) - > setText ( " SNR " ) ;
}
else if ( text = = " dBm " )
{
m_settings . m_spectrumYScale = RadioAstronomySettings : : SY_DBM ;
ui - > spectrumMarkerTable - > horizontalHeaderItem ( SPECTRUM_MARKER_COL_VALUE ) - > setText ( " Power (dBm) " ) ;
}
else if ( text = = " Tsys K " )
{
m_settings . m_spectrumYScale = RadioAstronomySettings : : SY_TSYS ;
ui - > spectrumMarkerTable - > horizontalHeaderItem ( SPECTRUM_MARKER_COL_VALUE ) - > setText ( " Tsys (K) " ) ;
}
else
{
m_settings . m_spectrumYScale = RadioAstronomySettings : : SY_TSOURCE ;
ui - > spectrumMarkerTable - > horizontalHeaderItem ( SPECTRUM_MARKER_COL_VALUE ) - > setText ( " Tsource (K) " ) ;
}
plotFFTMeasurement ( ) ;
2026-02-01 00:49:36 +01:00
applySettings ( QStringList ( " spectrumYScale " ) ) ;
2021-10-12 11:31:14 +01:00
}
void RadioAstronomyGUI : : on_spectrumBaseline_currentIndexChanged ( int index )
{
m_settings . m_spectrumBaseline = ( RadioAstronomySettings : : SpectrumBaseline ) index ;
plotFFTMeasurement ( ) ;
if ( ( m_settings . m_powerYData = = RadioAstronomySettings : : PY_TSOURCE ) | | ( m_settings . m_powerYData = = RadioAstronomySettings : : PY_FLUX ) ) {
plotPowerChart ( ) ;
}
2026-02-01 00:49:36 +01:00
applySettings ( QStringList ( " spectrumBaseline " ) ) ;
2021-10-12 11:31:14 +01:00
}
// Convert frequency shift to velocity in km/s (+ve approaching)
static double lineDopplerVelocity ( double centre , double f )
{
return Astronomy : : dopplerToVelocity ( f , centre ) / 1000.0f ;
}
2024-07-10 22:59:13 +02:00
// Convert frequency shift to velocity (+ve receding - which seems to be the astronomical convention)
2021-10-12 11:31:14 +01:00
double RadioAstronomyGUI : : dopplerToVelocity ( double centre , double f , FFTMeasurement * fft )
{
double v = lineDopplerVelocity ( centre , f ) ;
// Adjust in to selected reference frame
switch ( m_settings . m_refFrame )
{
case RadioAstronomySettings : : BCRS :
v - = fft - > m_vBCRS ;
break ;
case RadioAstronomySettings : : LSR :
v - = fft - > m_vLSR ;
break ;
2021-10-12 12:10:12 +01:00
default :
break ;
2021-10-12 11:31:14 +01:00
}
2024-07-10 22:59:13 +02:00
// Make +ve receding
2021-10-12 11:31:14 +01:00
return - v ;
}
// Replot current FFT
void RadioAstronomyGUI : : plotFFTMeasurement ( )
{
plotFFTMeasurement ( ui - > spectrumIndex - > value ( ) ) ;
}
// Plot FFT with specified index
void RadioAstronomyGUI : : plotFFTMeasurement ( int index )
{
if ( index < m_fftMeasurements . size ( ) )
{
FFTMeasurement * fft = m_fftMeasurements [ index ] ;
m_fftSeries - > clear ( ) ;
m_fftHlineSeries - > clear ( ) ;
m_fftGaussianSeries - > clear ( ) ;
m_fftLABSeries - > clear ( ) ;
m_fftPeakSeries - > clear ( ) ;
double binRes = fft - > m_sampleRate / ( double ) fft - > m_fftSize ;
double startFreq = fft - > m_centerFrequency - fft - > m_sampleRate / 2.0 ;
// Plot reference spectral line and Doppler axis
plotRefLine ( fft ) ;
// Plot Gaussian for temp estimation
plotTempGaussian ( startFreq , binRes , fft - > m_fftSize ) ;
// Plot LAB reference data
if ( fft - > m_coordsValid & & m_settings . m_spectrumLAB
& & ( ( m_settings . m_spectrumYScale = = RadioAstronomySettings : : SY_TSYS )
| | ( m_settings . m_spectrumYScale = = RadioAstronomySettings : : SY_TSOURCE )
)
)
{
plotLAB ( fft - > m_l , fft - > m_b , m_beamWidth ) ;
}
if ( ( ( m_settings . m_spectrumYScale = = RadioAstronomySettings : : SY_SNR ) & & ! fft - > m_snr )
| | ( ( m_settings . m_spectrumYScale = = RadioAstronomySettings : : SY_DBM ) & & ! fft - > m_temp )
| | ( ( m_settings . m_spectrumYScale = = RadioAstronomySettings : : SY_TSYS ) & & ! fft - > m_temp )
| | ( ( m_settings . m_spectrumYScale = = RadioAstronomySettings : : SY_TSOURCE ) & & ! fft - > m_temp )
)
{
m_fftChart - > setTitle ( " No cal data: Run calibration or set units to dBFS. " ) ;
}
else
{
m_fftChart - > setTitle ( " " ) ;
if ( fft - > m_coordsValid )
{
m_fftChart - > setTitle ( QString ( " RA: %1 Dec: %2 l: %3%7 b: %4%7 Az: %5%7 El: %6%7 " )
. arg ( Units : : decimalHoursToHoursMinutesAndSeconds ( fft - > m_ra ) )
. arg ( Units : : decimalDegreesToDegreeMinutesAndSeconds ( fft - > m_dec ) )
. arg ( QString : : number ( fft - > m_l , ' f ' , 1 ) )
. arg ( QString : : number ( fft - > m_b , ' f ' , 1 ) )
. arg ( QString : : number ( fft - > m_azimuth , ' f ' , 0 ) )
. arg ( QString : : number ( fft - > m_elevation , ' f ' , 0 ) )
. arg ( QChar ( 0xb0 ) ) ) ;
}
int peakIdx = 0 ;
double peakValue = - std : : numeric_limits < double > : : max ( ) ;
double freq = startFreq ; // Main spectrum seems to use bin midpoint - this uses lowest frequency, so we're tone at centre freq appears in centre of plot
// Plot power/temp
for ( int i = 0 ; i < fft - > m_fftSize ; i + + )
{
qreal value ;
switch ( m_settings . m_spectrumYScale )
{
case RadioAstronomySettings : : SY_DBFS :
value = fft - > m_db [ i ] ;
break ;
case RadioAstronomySettings : : SY_SNR :
value = fft - > m_snr [ i ] ;
break ;
case RadioAstronomySettings : : SY_DBM :
value = Astronomy : : noisePowerdBm ( fft - > m_temp [ i ] , fft - > m_sampleRate / ( double ) fft - > m_fftSize ) ;
break ;
case RadioAstronomySettings : : SY_TSYS :
value = fft - > m_temp [ i ] ;
break ;
case RadioAstronomySettings : : SY_TSOURCE :
switch ( m_settings . m_spectrumBaseline )
{
case RadioAstronomySettings : : SBL_TSYS0 :
value = fft - > m_temp [ i ] - fft - > m_tSys0 ;
break ;
case RadioAstronomySettings : : SBL_TMIN :
value = fft - > m_temp [ i ] - fft - > m_tempMin ;
break ;
case RadioAstronomySettings : : SBL_CAL_COLD :
if ( m_calCold ) {
value = m_calG [ i ] * ( fft - > m_fftData [ i ] - m_calCold - > m_fftData [ i ] ) ;
} else {
value = 0.0 ;
}
break ;
}
break ;
}
if ( value > peakValue )
{
peakValue = value ;
peakIdx = i ;
}
m_fftSeries - > append ( freq / 1e6 , value ) ;
freq + = binRes ;
}
double startFreqMHz = fft - > m_centerFrequency / 1e6 - m_settings . m_spectrumSpan / 2.0 ;
spectrumUpdateXRange ( fft ) ;
spectrumUpdateYRange ( fft ) ;
m_fftXAxis - > setReverse ( m_settings . m_spectrumReverseXAxis ) ;
switch ( m_settings . m_spectrumYScale )
{
case RadioAstronomySettings : : SY_DBFS :
m_fftYAxis - > setTitleText ( " Power (dBFS) " ) ;
break ;
case RadioAstronomySettings : : SY_SNR :
m_fftYAxis - > setTitleText ( " SNR " ) ;
break ;
case RadioAstronomySettings : : SY_DBM :
m_fftYAxis - > setTitleText ( " Power (dBm) " ) ;
break ;
case RadioAstronomySettings : : SY_TSYS :
m_fftYAxis - > setTitleText ( " Tsys (K) " ) ;
break ;
case RadioAstronomySettings : : SY_TSOURCE :
m_fftYAxis - > setTitleText ( " Tsource (K) " ) ;
break ;
}
// Plot peaks
if ( m_settings . m_spectrumPeaks )
{
double peakFreqMHz = ( startFreq + peakIdx * binRes ) / 1e6 ;
double peakFreq = peakFreqMHz * 1e6 ;
m_fftPeakSeries - > append ( peakFreqMHz , peakValue ) ;
ui - > spectrumMarkerTable - > item ( SPECTRUM_MARKER_ROW_PEAK , SPECTRUM_MARKER_COL_FREQ ) - > setData ( Qt : : DisplayRole , peakFreqMHz ) ;
ui - > spectrumMarkerTable - > item ( SPECTRUM_MARKER_ROW_PEAK , SPECTRUM_MARKER_COL_VALUE ) - > setData ( Qt : : DisplayRole , peakValue ) ;
calcVrAndDistanceToPeak ( peakFreq , fft , SPECTRUM_MARKER_ROW_PEAK ) ;
}
// Update markers to track current data
if ( m_spectrumM1Valid )
{
m_fftMarkerSeries - > clear ( ) ;
int idx ;
idx = ( m_spectrumM1X - startFreqMHz ) / ( binRes / 1e6 ) ;
if ( ( idx > = 0 ) & & ( idx < m_fftSeries - > count ( ) ) )
{
m_spectrumM1Y = m_fftSeries - > at ( idx ) . y ( ) ;
ui - > spectrumMarkerTable - > item ( SPECTRUM_MARKER_ROW_M1 , SPECTRUM_MARKER_COL_VALUE ) - > setData ( Qt : : DisplayRole , m_spectrumM1Y ) ;
m_fftMarkerSeries - > append ( m_spectrumM1X , m_spectrumM1Y ) ;
calcVrAndDistanceToPeak ( m_spectrumM1X * 1e6 , fft , SPECTRUM_MARKER_ROW_M1 ) ;
}
if ( m_spectrumM2Valid )
{
idx = ( m_spectrumM2X - startFreqMHz ) / ( binRes / 1e6 ) ;
if ( idx < m_fftSeries - > count ( ) )
{
m_spectrumM2Y = m_fftSeries - > at ( idx ) . y ( ) ;
ui - > spectrumMarkerTable - > item ( SPECTRUM_MARKER_ROW_M2 , SPECTRUM_MARKER_COL_VALUE ) - > setData ( Qt : : DisplayRole , m_spectrumM2Y ) ;
m_fftMarkerSeries - > append ( m_spectrumM2X , m_spectrumM2Y ) ;
calcVrAndDistanceToPeak ( m_spectrumM2X * 1e6 , fft , SPECTRUM_MARKER_ROW_M2 ) ;
calcSpectrumMarkerDelta ( ) ;
}
}
}
spectrumAutoscale ( ) ;
}
}
}
bool RadioAstronomyGUI : : losMarkerEnabled ( const QString & name )
{
if ( m_settings . m_spectrumDistance & & m_settings . m_spectrumRefLine )
{
if ( name = = " Max " ) {
return m_settings . m_spectrumPeaks ;
} else if ( name = = " M1 " ) {
return m_settings . m_spectrumMarkers ;
} else {
return m_settings . m_spectrumMarkers ;
}
}
return false ;
}
void RadioAstronomyGUI : : showLoSMarker ( const QString & name )
{
if ( losMarkerEnabled ( name ) )
{
if ( name = = " Max " ) {
showLoSMarker ( SPECTRUM_MARKER_ROW_PEAK ) ;
} else if ( name = = " M1 " ) {
showLoSMarker ( SPECTRUM_MARKER_ROW_M1 ) ;
} else {
showLoSMarker ( SPECTRUM_MARKER_ROW_M2 ) ;
}
}
}
void RadioAstronomyGUI : : showLoSMarker ( int row )
{
bool ok ;
float d = ui - > spectrumMarkerTable - > item ( row , SPECTRUM_MARKER_COL_D ) - > data ( Qt : : DisplayRole ) . toFloat ( & ok ) ;
if ( ok )
{
FFTMeasurement * fft = currentFFT ( ) ;
if ( fft )
{
QString name = ui - > spectrumMarkerTable - > item ( row , SPECTRUM_MARKER_COL_NAME ) - > text ( ) ;
updateLoSMarker ( name , fft - > m_l , fft - > m_b , d ) ;
}
}
}
void RadioAstronomyGUI : : updateLoSMarker ( const QString & name , float l , float b , float d )
{
// Send to Star Tracker
2022-03-27 08:01:02 +02:00
QList < ObjectPipe * > starTrackerPipes ;
2024-02-16 16:31:12 +00:00
MainCore : : instance ( ) - > getMessagePipes ( ) . getMessagePipes ( m_radioAstronomy , " startracker.display " , starTrackerPipes ) ;
2021-10-12 11:31:14 +01:00
2022-03-27 08:01:02 +02:00
for ( const auto & pipe : starTrackerPipes )
{
MessageQueue * messageQueue = qobject_cast < MessageQueue * > ( pipe - > m_element ) ;
SWGSDRangel : : SWGStarTrackerDisplayLoSSettings * swgSettings = new SWGSDRangel : : SWGStarTrackerDisplayLoSSettings ( ) ;
swgSettings - > setName ( new QString ( name ) ) ;
swgSettings - > setL ( l ) ;
swgSettings - > setB ( b ) ;
swgSettings - > setD ( d ) ;
messageQueue - > push ( MainCore : : MsgStarTrackerDisplayLoSSettings : : create ( m_radioAstronomy , swgSettings ) ) ;
2021-10-12 11:31:14 +01:00
}
}
void RadioAstronomyGUI : : clearLoSMarker ( const QString & name )
{
// Set d to 0 to clear
updateLoSMarker ( name , 0.0f , 0.0f , 0.0f ) ;
}
void RadioAstronomyGUI : : calcVrAndDistanceToPeak ( double freq , FFTMeasurement * fft , int row )
{
double lineFreq = ui - > spectrumLineFrequency - > value ( ) * 1e6 ;
// Calculate radial velocity (along line-of-sight) from Doppler shift
double vR = dopplerToVelocity ( lineFreq , freq , fft ) ;
ui - > spectrumMarkerTable - > item ( row , SPECTRUM_MARKER_COL_VR ) - > setData ( Qt : : DisplayRole , vR ) ;
// Tangent point method only valid for Galactic quadrants I (0-90) and IV (270-360)
if ( ( fft - > m_l < 90.0 ) | | ( fft - > m_l > 270.0 ) )
{
// Calculate minimum distance to Galactic centre along line of sight (tangential radius)
double rMin = m_settings . m_sunDistanceToGC * sin ( Units : : degreesToRadians ( fft - > m_l ) ) ;
ui - > spectrumMarkerTable - > item ( row , SPECTRUM_MARKER_COL_R_MIN ) - > setData ( Qt : : DisplayRole , rMin ) ;
// Calculate orbital velocity at tangent/minimum point
// This is the velocity to plot for the rotation curve
double w0 = m_settings . m_sunOrbitalVelocity / m_settings . m_sunDistanceToGC ;
double vOrb = vR + rMin * w0 ;
ui - > spectrumMarkerTable - > item ( row , SPECTRUM_MARKER_COL_V ) - > setData ( Qt : : DisplayRole , vOrb ) ;
}
else
{
ui - > spectrumMarkerTable - > item ( row , SPECTRUM_MARKER_COL_R_MIN ) - > setText ( " " ) ;
ui - > spectrumMarkerTable - > item ( row , SPECTRUM_MARKER_COL_V ) - > setText ( " " ) ;
}
// Calculate distance of HI cloud (as indicated by a peak) to Sun and Galactic center
double r , d1 , d2 ;
int solutions = calcDistanceToPeak ( vR , fft - > m_l , fft - > m_b , r , d1 , d2 ) ;
if ( solutions = = 0 )
{
ui - > spectrumMarkerTable - > item ( row , SPECTRUM_MARKER_COL_R ) - > setText ( " " ) ;
ui - > spectrumMarkerTable - > item ( row , SPECTRUM_MARKER_COL_D ) - > setText ( " " ) ;
}
else if ( solutions = = 1 )
{
ui - > spectrumMarkerTable - > item ( row , SPECTRUM_MARKER_COL_R ) - > setData ( Qt : : DisplayRole , r ) ;
ui - > spectrumMarkerTable - > item ( row , SPECTRUM_MARKER_COL_D ) - > setData ( Qt : : DisplayRole , d1 ) ;
}
else
{
ui - > spectrumMarkerTable - > item ( row , SPECTRUM_MARKER_COL_R ) - > setData ( Qt : : DisplayRole , r ) ;
ui - > spectrumMarkerTable - > item ( row , SPECTRUM_MARKER_COL_D ) - > setText ( QString ( " %1/%2 " ) . arg ( QString : : number ( d1 , ' f ' , 1 ) ) . arg ( QString : : number ( d2 , ' f ' , 1 ) ) ) ;
}
// Send to Star Tracker
QString name = ui - > spectrumMarkerTable - > item ( row , SPECTRUM_MARKER_COL_NAME ) - > text ( ) ;
if ( losMarkerEnabled ( name ) )
{
2021-10-12 12:10:12 +01:00
if ( ( solutions = = 0 ) | | std : : isnan ( d1 ) )
2021-10-12 11:31:14 +01:00
{
updateLoSMarker ( name , fft - > m_l , fft - > m_b , 0.0f ) ;
}
else if ( solutions = = 1 )
{
updateLoSMarker ( name , fft - > m_l , fft - > m_b , d1 ) ;
}
else
{
bool plotMax = ui - > spectrumMarkerTable - > item ( row , SPECTRUM_MARKER_COL_PLOT_MAX ) - > checkState ( ) = = Qt : : Checked ;
if ( ( plotMax & & ( d1 > d2 ) ) | | ( ! plotMax & & ( d1 < d2 ) ) ) {
updateLoSMarker ( name , fft - > m_l , fft - > m_b , d1 ) ;
} else {
updateLoSMarker ( name , fft - > m_l , fft - > m_b , d2 ) ;
}
}
}
}
int RadioAstronomyGUI : : calcDistanceToPeak ( double vr , float l , float b , double & r , double & d1 , double & d2 )
{
// Radio Astronomy 4th edition - Burke - p343
double r0 = m_settings . m_sunDistanceToGC ; // Distance of Sun to Galactic centre in kpc
double v0 = m_settings . m_sunOrbitalVelocity ; // Orbital velocity of the Sun around Galactic centre in km/s
double w0 = v0 / r0 ; // Angular velocity of the Sun
double gl = Units : : degreesToRadians ( l ) ;
double gb = Units : : degreesToRadians ( b ) ;
double w = vr / ( r0 * sin ( gl ) * cos ( gb ) ) + w0 ;
r = v0 / w ; // Assume constant v, regardless of distance from GC - Dark matter magic - Not valid <1kpc from GC
if ( r < 0 ) {
return 0 ;
}
// https://en.wikipedia.org/wiki/Solution_of_triangles#Two_sides_and_non-included_angle_given_(SSA)
double beta = gl ;
double d = sin ( beta ) * r0 / r ;
if ( d > 1.0 ) {
// No solutions
return 0 ;
}
if ( ( r < = r0 ) & & ( beta > = M_PI / 2.0 ) ) {
return 0 ;
}
double gamma = asin ( d ) ;
double alpha1 = M_PI - beta - gamma ;
d1 = r * sin ( alpha1 ) / sin ( beta ) ; // Distance from Sun to peak
if ( r < r0 )
{
double alpha2 = M_PI - beta - ( M_PI - gamma ) ;
d2 = r * sin ( alpha2 ) / sin ( beta ) ; // Distance from Sun to peak
return 2 ;
}
else
{
return 1 ;
}
}
void RadioAstronomyGUI : : spectrumMarkerTableItemChanged ( QTableWidgetItem * item )
{
if ( item - > column ( ) = = SPECTRUM_MARKER_COL_PLOT_MAX ) {
// Plot max checkbox clicked
calcDistances ( ) ;
}
}
void RadioAstronomyGUI : : calcDistances ( )
{
double freq ;
bool ok ;
FFTMeasurement * fft = currentFFT ( ) ;
if ( fft )
{
freq = ui - > spectrumMarkerTable - > item ( SPECTRUM_MARKER_ROW_PEAK , SPECTRUM_MARKER_COL_FREQ ) - > data ( Qt : : DisplayRole ) . toDouble ( & ok ) ;
if ( ok ) {
calcVrAndDistanceToPeak ( freq * 1e6 , fft , SPECTRUM_MARKER_ROW_PEAK ) ;
}
freq = ui - > spectrumMarkerTable - > item ( SPECTRUM_MARKER_ROW_M1 , SPECTRUM_MARKER_COL_FREQ ) - > data ( Qt : : DisplayRole ) . toDouble ( & ok ) ;
if ( ok ) {
calcVrAndDistanceToPeak ( freq * 1e6 , fft , SPECTRUM_MARKER_ROW_M1 ) ;
}
freq = ui - > spectrumMarkerTable - > item ( SPECTRUM_MARKER_ROW_M2 , SPECTRUM_MARKER_COL_FREQ ) - > data ( Qt : : DisplayRole ) . toDouble ( & ok ) ;
if ( ok ) {
calcVrAndDistanceToPeak ( freq * 1e6 , fft , SPECTRUM_MARKER_ROW_M2 ) ;
}
}
}
void RadioAstronomyGUI : : plotRefLine ( FFTMeasurement * fft )
{
double lineFreqMHz = ui - > spectrumLineFrequency - > value ( ) ;
double lineFreq = lineFreqMHz * 1e6 ;
QString refFrame [ ] = { " Topocentric " , " Barycentric " , " LSR " } ;
2023-07-23 16:44:42 +02:00
m_fftDopplerAxis - > setTitleText ( QString ( " %1 radial velocity (km/s - +ve receding) " ) . arg ( refFrame [ m_settings . m_refFrame ] ) ) ;
2021-10-12 11:31:14 +01:00
m_fftHlineSeries - > setName ( QString ( " %1 line " ) . arg ( ui - > spectrumLine - > currentText ( ) ) ) ;
m_fftHlineSeries - > append ( 0.0f , - 200.0f ) ; // For dB
m_fftHlineSeries - > append ( 0.0f , 10000.0f ) ; // For temp can be >1e6?
double startFreq = fft - > m_centerFrequency + m_settings . m_spectrumSpan * 1e6 / 2.0 + m_settings . m_spectrumCenterFreqOffset * 1e6 ;
double endFreq = fft - > m_centerFrequency - m_settings . m_spectrumSpan * 1e6 / 2.0 + m_settings . m_spectrumCenterFreqOffset * 1e6 ;
m_fftDopplerAxis - > setRange ( dopplerToVelocity ( lineFreq , startFreq , fft ) ,
dopplerToVelocity ( lineFreq , endFreq , fft ) ) ;
m_fftDopplerAxis - > setReverse ( ! m_settings . m_spectrumReverseXAxis ) ;
m_fftDopplerAxis - > setVisible ( m_settings . m_spectrumRefLine ) ;
}
void RadioAstronomyGUI : : plotTempGaussian ( double startFreq , double freqStep , int steps )
{
m_fftGaussianSeries - > clear ( ) ;
double f0 = ui - > spectrumGaussianFreq - > value ( ) * 1e6 ;
double a = ui - > spectrumGaussianAmp - > value ( ) ;
double floor = ui - > spectrumGaussianFloor - > value ( ) ;
double fwhm = ui - > spectrumGaussianFWHM - > value ( ) ;
double fwhm_sq = fwhm * fwhm ;
double freq = startFreq ;
for ( int i = 0 ; i < steps ; i + + )
{
double fd = freq - f0 ;
double g = a * std : : exp ( - 4.0 * M_LN2 * fd * fd / fwhm_sq ) + floor ;
m_fftGaussianSeries - > append ( freq / 1e6 , g ) ;
freq + = freqStep ;
}
}
void RadioAstronomyGUI : : calcFFTPower ( FFTMeasurement * fft )
{
// Convert linear to dB
for ( int i = 0 ; i < fft - > m_fftSize ; i + + ) {
fft - > m_db [ i ] = CalcDb : : dbPower ( fft - > m_fftData [ i ] ) ;
}
}
void RadioAstronomyGUI : : calcFFTTotalPower ( FFTMeasurement * fft )
{
double total = 0.0 ;
for ( int i = 0 ; i < fft - > m_fftSize ; i + + ) {
total + = fft - > m_fftData [ i ] ;
}
fft - > m_totalPower = total ;
fft - > m_totalPowerdBFS = CalcDb : : dbPower ( total ) ;
}
void RadioAstronomyGUI : : calcFFTTemperatures ( FFTMeasurement * fft )
{
if ( m_calCold & & ! fft - > m_snr ) {
fft - > m_snr = new Real [ fft - > m_fftSize ] ;
}
if ( m_calG & & ! fft - > m_temp ) {
fft - > m_temp = new Real [ fft - > m_fftSize ] ;
}
for ( int i = 0 ; i < fft - > m_fftSize ; i + + )
{
if ( fft - > m_snr & & m_calCold )
{
// Calculate SNR (relative to cold cal)
fft - > m_snr [ i ] = fft - > m_fftData [ i ] / m_calCold - > m_fftData [ i ] ;
}
if ( m_calG )
{
// Calculate temperature using scaling from hot cal
fft - > m_temp [ i ] = m_calG [ i ] * fft - > m_fftData [ i ] ;
// Calculate temperature using linear interpolation from hot/cold cal
//fft->m_temp[i] = m_calG[i] * (fft->m_fftData[i] - m_calCold->m_fftData[i]) + m_settings.m_tCalCold;
//fft->m_temp[i] = std::max(fft->m_temp[i], 0.0f); // Can't have negative temperatures
}
}
calcFFTMinTemperature ( fft ) ;
}
void RadioAstronomyGUI : : calcFFTMinTemperature ( FFTMeasurement * fft )
{
fft - > m_tempMin = 0 ;
if ( fft - > m_temp )
{
// Select minimum from within band. 95% of that to account for a little bit of inband rolloff
float tempMin = std : : numeric_limits < float > : : max ( ) ;
double pc = 0.95 * fft - > m_rfBandwidth / ( double ) fft - > m_sampleRate ;
int count = ( int ) ( pc * fft - > m_fftSize ) ;
int start = ( fft - > m_fftSize - count ) / 2 ;
for ( int i = 0 ; i < count ; i + + )
{
int idx = i + start ;
tempMin = std : : min ( tempMin , fft - > m_temp [ idx ] ) ;
}
if ( tempMin ! = std : : numeric_limits < float > : : max ( ) ) {
fft - > m_tempMin = tempMin ;
}
}
}
// Estimate Tsource by subtracting selected baseline
double RadioAstronomyGUI : : calcTSource ( FFTMeasurement * fft ) const
{
switch ( fft - > m_baseline )
{
case RadioAstronomySettings : : SBL_TSYS0 :
return fft - > m_tSys - fft - > m_tSys0 ;
case RadioAstronomySettings : : SBL_TMIN :
return fft - > m_tSys - fft - > m_tempMin ;
case RadioAstronomySettings : : SBL_CAL_COLD :
if ( m_calCold ) {
return fft - > m_tSys - m_calCold - > m_tSys ;
}
break ;
}
return fft - > m_tSys ;
}
// Calculate spectral flux density of source
double RadioAstronomyGUI : : calcFlux ( double Ta , const FFTMeasurement * fft ) const
{
// Factor of 2 here assumes single polarization
// See equation 5.13 and 5.20 in Radio Astronomy 4th edition - Burke
double lambda = Astronomy : : m_speedOfLight / ( double ) fft - > m_centerFrequency ;
return 2.0 * Astronomy : : m_boltzmann * Ta * fft - > m_omegaA / ( lambda * lambda ) ;
}
void RadioAstronomyGUI : : calcFFTTotalTemperature ( FFTMeasurement * fft )
{
if ( fft - > m_temp )
{
double tempSum = 0.0 ;
for ( int i = 0 ; i < fft - > m_fftSize ; i + + ) {
tempSum + = fft - > m_temp [ i ] ;
}
// Convert from temperature to power in Watts and dBm
Real bw = fft - > m_sampleRate / ( Real ) fft - > m_fftSize ;
fft - > m_totalPowerWatts = Astronomy : : m_boltzmann * tempSum * bw ;
fft - > m_totalPowerdBm = Astronomy : : noisePowerdBm ( tempSum , bw ) ;
fft - > m_tSys = tempSum / fft - > m_fftSize ;
2024-07-10 22:59:13 +02:00
// Estimate source temperature
2021-10-12 11:31:14 +01:00
fft - > m_tSource = calcTSource ( fft ) ;
// Calculate error due to thermal noise and gain variation
fft - > m_sigmaT = calcSigmaT ( fft ) ;
fft - > m_sigmaS = calcSigmaS ( fft ) ;
// Calculate spectral flux density of source
fft - > m_flux = calcFlux ( fft - > m_tSource , fft ) ;
}
}
void RadioAstronomyGUI : : updatePowerColumns ( int row , FFTMeasurement * fft )
{
ui - > powerTable - > item ( row , POWER_COL_TSYS ) - > setData ( Qt : : DisplayRole , fft - > m_tSys ) ;
ui - > powerTable - > item ( row , POWER_COL_TSYS0 ) - > setData ( Qt : : DisplayRole , fft - > m_tSys0 ) ;
ui - > powerTable - > item ( row , POWER_COL_TSOURCE ) - > setData ( Qt : : DisplayRole , fft - > m_tSource ) ;
if ( m_settings . m_sourceType ! = RadioAstronomySettings : : UNKNOWN ) {
ui - > powerTable - > item ( row , POWER_COL_TB ) - > setData ( Qt : : DisplayRole , fft - > m_tSource / beamFillingFactor ( ) ) ;
} else {
ui - > powerTable - > item ( row , POWER_COL_TB ) - > setText ( " " ) ;
}
ui - > powerTable - > item ( row , POWER_COL_FLUX ) - > setData ( Qt : : DisplayRole , Units : : wattsPerMetrePerHertzToJansky ( fft - > m_flux ) ) ;
ui - > powerTable - > item ( row , POWER_COL_SIGMA_T ) - > setData ( Qt : : DisplayRole , fft - > m_sigmaT ) ;
ui - > powerTable - > item ( row , POWER_COL_SIGMA_S ) - > setData ( Qt : : DisplayRole , fft - > m_sigmaS ) ;
ui - > powerTable - > item ( row , POWER_COL_OMEGA_A ) - > setData ( Qt : : DisplayRole , fft - > m_omegaA ) ;
ui - > powerTable - > item ( row , POWER_COL_OMEGA_S ) - > setData ( Qt : : DisplayRole , fft - > m_omegaS ) ;
}
void RadioAstronomyGUI : : addFFT ( FFTMeasurement * fft , bool skipCalcs )
{
m_fftMeasurements . append ( fft ) ;
powerMeasurementReceived ( fft , skipCalcs ) ; // Call before ui->spectrumIndex->setValue, so table row is valid
update2DImage ( fft , skipCalcs ) ;
ui - > spectrumIndex - > setRange ( 0 , m_fftMeasurements . size ( ) - 1 ) ;
if ( ( ui - > spectrumIndex - > value ( ) = = m_fftMeasurements . size ( ) - 2 ) | | ( m_fftMeasurements . size ( ) = = 1 ) ) {
ui - > spectrumIndex - > setValue ( m_fftMeasurements . size ( ) - 1 ) ;
}
if ( m_fftMeasurements . size ( ) = = 1 )
{
// Force drawing for first measurement
on_spectrumIndex_valueChanged ( 0 ) ;
}
}
2023-08-26 14:40:13 +01:00
void RadioAstronomyGUI : : getRotatorData ( FFTMeasurement * fft )
{
2023-12-05 12:32:53 +00:00
unsigned int rotatorFeatureSetIndex , rotatorFeatureIndex ;
2023-08-26 14:40:13 +01:00
2023-12-05 12:32:53 +00:00
if ( MainCore : : getFeatureIndexFromId ( m_settings . m_rotator , rotatorFeatureSetIndex , rotatorFeatureIndex ) )
{
2023-08-26 14:40:13 +01:00
SWGSDRangel : : SWGFeatureReport featureReport ;
double value ;
qDebug ( ) < < m_settings . m_rotator < < rotatorFeatureSetIndex < < rotatorFeatureIndex ;
if ( ChannelWebAPIUtils : : getFeatureReport ( rotatorFeatureSetIndex , rotatorFeatureIndex , featureReport ) )
{
QJsonObject * jsonObj = featureReport . asJsonObject ( ) ;
qDebug ( ) < < * jsonObj ;
if ( WebAPIUtils : : getSubObjectDouble ( * jsonObj , " currentAzimuth " , value ) ) {
fft - > m_rotAz = value ;
} else {
qDebug ( ) < < " RadioAstronomyGUI::getRotatorData: getSubObjectDouble currentAzimuth failed " ;
}
if ( WebAPIUtils : : getSubObjectDouble ( * jsonObj , " currentElevation " , value ) ) {
fft - > m_rotEl = value ;
} else {
qDebug ( ) < < " RadioAstronomyGUI::getRotatorData: getSubObjectDouble currentElevation failed " ;
}
}
else
{
qDebug ( ) < < " RadioAstronomyGUI::getRotatorData: getFeatureReport failed " ;
}
SWGSDRangel : : SWGFeatureSettings featureSettingsResponse ;
Feature * feature ;
if ( ChannelWebAPIUtils : : getFeatureSettings ( rotatorFeatureSetIndex , rotatorFeatureIndex , featureSettingsResponse , feature ) )
{
QJsonObject * jsonObj = featureSettingsResponse . asJsonObject ( ) ;
qDebug ( ) < < * jsonObj ;
if ( WebAPIUtils : : getSubObjectDouble ( * jsonObj , " azimuthOffset " , value ) ) {
fft - > m_rotAzOff = value ;
} else {
qDebug ( ) < < " RadioAstronomyGUI::getRotatorData: getSubObjectDouble azimuthOffset failed " ;
}
if ( WebAPIUtils : : getSubObjectDouble ( * jsonObj , " elevationOffset " , value ) ) {
fft - > m_rotElOff = value ;
} else {
qDebug ( ) < < " RadioAstronomyGUI::getRotatorData: getSubObjectDouble elevationOffset " ;
}
}
else
{
qDebug ( ) < < " RadioAstronomyGUI::getRotatorData: getFeatureSettings failed " ;
}
fft - > m_rotValid = true ;
}
else
qDebug ( ) < < " Couldn't parse rotator feature " < < m_settings . m_rotator ;
}
2021-10-12 11:31:14 +01:00
void RadioAstronomyGUI : : fftMeasurementReceived ( const RadioAstronomy : : MsgFFTMeasurement & measurement )
{
FFTMeasurement * fft = new FFTMeasurement ( ) ;
fft - > m_fftData = measurement . getFFT ( ) ;
fft - > m_fftSize = measurement . getSize ( ) ;
fft - > m_dateTime = measurement . getDateTime ( ) ;
fft - > m_centerFrequency = m_centerFrequency ;
fft - > m_sampleRate = m_settings . m_sampleRate ;
fft - > m_integration = m_settings . m_integration ;
fft - > m_rfBandwidth = m_settings . m_rfBandwidth ;
fft - > m_omegaA = calcOmegaA ( ) ;
fft - > m_omegaS = calcOmegaS ( ) ;
fft - > m_coordsValid = m_coordsValid ;
fft - > m_ra = m_ra ;
fft - > m_dec = m_dec ;
fft - > m_azimuth = m_azimuth ;
fft - > m_elevation = m_elevation ;
fft - > m_l = m_l ;
fft - > m_b = m_b ;
fft - > m_vBCRS = m_vBCRS ;
fft - > m_vLSR = m_vLSR ;
fft - > m_solarFlux = m_solarFlux ;
fft - > m_airTemp = m_airTemps . lastValue ( ) ;
fft - > m_skyTemp = m_skyTemp ;
for ( int i = 0 ; i < RADIOASTRONOMY_SENSORS ; i + + ) {
fft - > m_sensor [ i ] = m_sensors [ i ] . lastValue ( ) ;
}
fft - > m_db = new Real [ fft - > m_fftSize ] ;
fft - > m_sweepIndex = m_sweepIndex + + ;
fft - > m_tSys0 = calcTSys0 ( ) ;
fft - > m_baseline = m_settings . m_spectrumBaseline ;
2023-08-26 14:40:13 +01:00
getRotatorData ( fft ) ;
2021-10-12 11:31:14 +01:00
calcFFTPower ( fft ) ;
calcFFTTotalPower ( fft ) ;
calcFFTTemperatures ( fft ) ;
calcFFTTotalTemperature ( fft ) ;
addFFT ( fft ) ;
}
void RadioAstronomyGUI : : on_spectrumIndex_valueChanged ( int value )
{
if ( value < m_fftMeasurements . size ( ) )
{
plotFFTMeasurement ( value ) ;
// Highlight in table
ui - > powerTable - > selectRow ( value ) ;
ui - > powerTable - > scrollTo ( ui - > powerTable - > model ( ) - > index ( value , 0 ) ) ;
ui - > spectrumDateTime - > setDateTime ( m_fftMeasurements [ value ] - > m_dateTime ) ;
2022-03-27 08:01:02 +02:00
2021-10-12 11:31:14 +01:00
// Display target in Star Tracker
2022-03-27 08:01:02 +02:00
QList < ObjectPipe * > starTrackerPipes ;
2024-02-16 16:31:12 +00:00
MainCore : : instance ( ) - > getMessagePipes ( ) . getMessagePipes ( m_radioAstronomy , " startracker.display " , starTrackerPipes ) ;
2021-10-12 11:31:14 +01:00
2022-03-27 08:01:02 +02:00
for ( const auto & pipe : starTrackerPipes )
{
MessageQueue * messageQueue = qobject_cast < MessageQueue * > ( pipe - > m_element ) ;
SWGSDRangel : : SWGStarTrackerDisplaySettings * swgSettings = new SWGSDRangel : : SWGStarTrackerDisplaySettings ( ) ;
swgSettings - > setDateTime ( new QString ( m_fftMeasurements [ value ] - > m_dateTime . toString ( Qt : : ISODateWithMs ) ) ) ;
swgSettings - > setAzimuth ( m_fftMeasurements [ value ] - > m_azimuth ) ;
swgSettings - > setElevation ( m_fftMeasurements [ value ] - > m_elevation ) ;
messageQueue - > push ( MainCore : : MsgStarTrackerDisplaySettings : : create ( m_radioAstronomy , swgSettings ) ) ;
2021-10-12 11:31:14 +01:00
}
}
}
void RadioAstronomyGUI : : plotSpectrum ( )
{
QChart * oldChart = m_fftChart ;
m_fftChart = new QChart ( ) ;
m_fftChart - > layout ( ) - > setContentsMargins ( 0 , 0 , 0 , 0 ) ;
m_fftChart - > setMargins ( QMargins ( 1 , 1 , 1 , 1 ) ) ;
m_fftChart - > setTheme ( QChart : : ChartThemeDark ) ;
m_fftChart - > legend ( ) - > setAlignment ( Qt : : AlignRight ) ;
m_fftChart - > legend ( ) - > setVisible ( m_settings . m_spectrumLegend ) ;
m_fftSeries = new QLineSeries ( ) ;
m_fftSeries - > setName ( " Measurement " ) ;
connect ( m_fftSeries , & QXYSeries : : clicked , this , & RadioAstronomyGUI : : spectrumSeries_clicked ) ;
// Plot vertical reference spectral line
m_fftHlineSeries = new QLineSeries ( ) ;
m_fftHlineSeries - > setName ( QString ( " %1 line " ) . arg ( ui - > spectrumLine - > currentText ( ) ) ) ;
m_fftHlineSeries - > setVisible ( m_settings . m_spectrumRefLine ) ;
// Plot peak info
m_fftPeakSeries = new QScatterSeries ( ) ;
m_fftPeakSeries - > setPointLabelsVisible ( true ) ;
m_fftPeakSeries - > setMarkerSize ( 5 ) ;
m_fftPeakSeries - > setName ( " Max " ) ;
// Markers
m_fftMarkerSeries = new QScatterSeries ( ) ;
m_fftMarkerSeries - > setPointLabelsVisible ( true ) ;
m_fftMarkerSeries - > setMarkerSize ( 5 ) ;
m_fftMarkerSeries - > setName ( " Markers " ) ;
// Gaussian
m_fftGaussianSeries = new QLineSeries ( ) ;
m_fftGaussianSeries - > setName ( " Gaussian fit " ) ;
m_fftGaussianSeries - > setVisible ( m_settings . m_spectrumTemp ) ;
m_fftLABSeries = new QLineSeries ( ) ;
m_fftLABSeries - > setName ( " LAB reference " ) ;
m_fftLABSeries - > setVisible ( m_settings . m_spectrumLAB ) ;
m_fftXAxis = new QValueAxis ( ) ;
m_fftYAxis = new QValueAxis ( ) ;
m_fftDopplerAxis = new QValueAxis ( ) ;
m_fftChart - > addAxis ( m_fftXAxis , Qt : : AlignBottom ) ;
m_fftChart - > addAxis ( m_fftYAxis , Qt : : AlignLeft ) ;
m_fftChart - > addAxis ( m_fftDopplerAxis , Qt : : AlignTop ) ;
m_fftXAxis - > setTitleText ( " Frequency (MHz) " ) ;
calcSpectrumChartTickCount ( m_fftXAxis , size ( ) . width ( ) ) ;
calcSpectrumChartTickCount ( m_fftDopplerAxis , size ( ) . width ( ) ) ;
m_fftYAxis - > setTitleText ( " Power " ) ;
m_fftChart - > addSeries ( m_fftSeries ) ;
m_fftSeries - > attachAxis ( m_fftXAxis ) ;
m_fftSeries - > attachAxis ( m_fftYAxis ) ;
m_fftChart - > addSeries ( m_fftHlineSeries ) ;
//m_fftHlineSeries->attachAxis(m_fftXAxis);
m_fftHlineSeries - > attachAxis ( m_fftDopplerAxis ) ;
m_fftHlineSeries - > attachAxis ( m_fftYAxis ) ;
m_fftChart - > addSeries ( m_fftGaussianSeries ) ;
m_fftGaussianSeries - > attachAxis ( m_fftXAxis ) ;
m_fftGaussianSeries - > attachAxis ( m_fftYAxis ) ;
m_fftChart - > addSeries ( m_fftLABSeries ) ;
//m_fftLABSeries->attachAxis(m_fftXAxis);
m_fftLABSeries - > attachAxis ( m_fftDopplerAxis ) ;
m_fftLABSeries - > attachAxis ( m_fftYAxis ) ;
m_fftChart - > addSeries ( m_fftPeakSeries ) ;
m_fftPeakSeries - > attachAxis ( m_fftXAxis ) ;
m_fftPeakSeries - > attachAxis ( m_fftYAxis ) ;
m_fftChart - > addSeries ( m_fftMarkerSeries ) ;
m_fftMarkerSeries - > attachAxis ( m_fftXAxis ) ;
m_fftMarkerSeries - > attachAxis ( m_fftYAxis ) ;
// Don't have peaks and markers in legend
m_fftChart - > legend ( ) - > markers ( m_fftPeakSeries ) [ 0 ] - > setVisible ( false ) ;
m_fftChart - > legend ( ) - > markers ( m_fftMarkerSeries ) [ 0 ] - > setVisible ( false ) ;
ui - > spectrumChart - > setChart ( m_fftChart ) ;
delete oldChart ;
}
// Calculate galactic background temperature based on center frequency
void RadioAstronomyGUI : : calcGalacticBackgroundTemp ( )
{
// https://arxiv.org/ftp/arxiv/papers/1912/1912.12699.pdf - page 6
// 17.1, 25.2 and 54.8 K for the 10th, 50th and 90th percentile of the all-sky distribution
// See also ITU-R P.372-7 section 6
// If this is used for cold calibration, we don't want to use the higher value
double temp = 25.2 * std : : pow ( m_centerFrequency / 408000000.0 , - 2.75 ) ;
ui - > tempGal - > setValue ( temp ) ;
}
// Calculate athmospheric noise temperature based on air temperature, zenith opacity and elevation
void RadioAstronomyGUI : : calcAtmosphericTemp ( )
{
float el = m_settings . m_elevation ;
if ( m_settings . m_elevation < 1.0f ) {
el = 1.0f ; // Avoid divide by 0 and limit max value to match ITU-R P.372-7 figure 5
}
double temp = Units : : celsiusToKelvin ( m_settings . m_tempAir ) * ( 1.0 - std : : exp ( - m_settings . m_zenithOpacity / cos ( Units : : degreesToRadians ( 90.0f - el ) ) ) ) ;
ui - > tempAtm - > setValue ( temp ) ;
}
void RadioAstronomyGUI : : on_tempRXSelect_currentIndexChanged ( int value )
{
if ( value = = 0 )
{
// T_RX
ui - > tempRX - > setValue ( m_settings . m_tempRX ) ;
ui - > tempRXUnitsLabel - > setText ( " K " ) ;
}
else
{
// NF
ui - > tempRX - > setValue ( Units : : noiseTempToNoiseFigureTo ( m_settings . m_tempRX ) ) ;
ui - > tempRXUnitsLabel - > setText ( " dB " ) ;
}
}
void RadioAstronomyGUI : : on_tempRX_valueChanged ( double value )
{
if ( ui - > tempRXSelect - > currentIndex ( ) = = 0 ) {
m_settings . m_tempRX = value ;
} else {
m_settings . m_tempRX = Units : : noiseFigureToNoiseTemp ( value ) ;
}
updateTSys0 ( ) ;
2026-02-01 00:49:36 +01:00
applySettings ( QStringList ( " tempRX " ) ) ;
2021-10-12 11:31:14 +01:00
}
void RadioAstronomyGUI : : on_tempCMB_valueChanged ( double value )
{
m_settings . m_tempCMB = value ;
updateTSys0 ( ) ;
2026-02-01 00:49:36 +01:00
applySettings ( QStringList ( " tempCMB " ) ) ;
2021-10-12 11:31:14 +01:00
}
void RadioAstronomyGUI : : on_tempGal_valueChanged ( double value )
{
m_settings . m_tempGal = value ;
updateTSys0 ( ) ;
2026-02-01 00:49:36 +01:00
applySettings ( QStringList ( " tempGal " ) ) ;
2021-10-12 11:31:14 +01:00
}
void RadioAstronomyGUI : : on_tempSP_valueChanged ( double value )
{
m_settings . m_tempSP = value ;
updateTSys0 ( ) ;
2026-02-01 00:49:36 +01:00
applySettings ( QStringList ( " tempSP " ) ) ;
2021-10-12 11:31:14 +01:00
}
void RadioAstronomyGUI : : on_tempAtm_valueChanged ( double value )
{
m_settings . m_tempAtm = value ;
updateTSys0 ( ) ;
2026-02-01 00:49:36 +01:00
applySettings ( QStringList ( " tempAtm " ) ) ;
2021-10-12 11:31:14 +01:00
}
void RadioAstronomyGUI : : on_tempAir_valueChanged ( double value )
{
m_settings . m_tempAir = value ;
if ( m_settings . m_tempAtmLink ) {
calcAtmosphericTemp ( ) ;
}
2026-02-01 00:49:36 +01:00
applySettings ( QStringList ( " tempAir " ) ) ;
2021-10-12 11:31:14 +01:00
}
void RadioAstronomyGUI : : on_zenithOpacity_valueChanged ( double value )
{
m_settings . m_zenithOpacity = value ;
if ( m_settings . m_tempAtmLink ) {
calcAtmosphericTemp ( ) ;
}
2026-02-01 00:49:36 +01:00
applySettings ( QStringList ( " zenithOpacity " ) ) ;
2021-10-12 11:31:14 +01:00
}
void RadioAstronomyGUI : : on_elevation_valueChanged ( double value )
{
m_settings . m_elevation = value ;
if ( m_settings . m_tempAtmLink ) {
calcAtmosphericTemp ( ) ;
}
2026-02-01 00:49:36 +01:00
applySettings ( QStringList ( " elevation " ) ) ;
2021-10-12 11:31:14 +01:00
}
void RadioAstronomyGUI : : on_elevationLink_toggled ( bool checked )
{
m_settings . m_elevationLink = checked ;
ui - > elevation - > setValue ( m_elevation ) ;
ui - > elevation - > setEnabled ( ! m_settings . m_elevationLink ) ;
2026-02-01 00:49:36 +01:00
applySettings ( QStringList ( " elevationLink " ) ) ;
2021-10-12 11:31:14 +01:00
}
void RadioAstronomyGUI : : on_tempAtmLink_toggled ( bool checked )
{
m_settings . m_tempAtmLink = checked ;
ui - > tempAtm - > setEnabled ( ! m_settings . m_tempAtmLink ) ;
if ( checked ) {
calcAtmosphericTemp ( ) ;
}
2026-02-01 00:49:36 +01:00
applySettings ( QStringList ( " tempAtmLink " ) ) ;
2021-10-12 11:31:14 +01:00
}
void RadioAstronomyGUI : : on_tempAirLink_toggled ( bool checked )
{
m_settings . m_tempAirLink = checked ;
ui - > tempAir - > setEnabled ( ! m_settings . m_tempAirLink ) ;
if ( checked )
{
ui - > tempAir - > setValue ( m_airTemps . lastValue ( ) ) ;
calcAtmosphericTemp ( ) ;
}
2026-02-01 00:49:36 +01:00
applySettings ( QStringList ( " tempAirLink " ) ) ;
2021-10-12 11:31:14 +01:00
}
void RadioAstronomyGUI : : on_tempGalLink_toggled ( bool checked )
{
m_settings . m_tempGalLink = checked ;
if ( checked ) {
calcGalacticBackgroundTemp ( ) ;
}
ui - > tempGal - > setEnabled ( ! m_settings . m_tempGalLink ) ;
2026-02-01 00:49:36 +01:00
applySettings ( QStringList ( " tempGalLink " ) ) ;
2021-10-12 11:31:14 +01:00
}
void RadioAstronomyGUI : : on_tCalHotSelect_currentIndexChanged ( int value )
{
if ( value = = 0 )
{
// Thot
ui - > tCalHot - > setValue ( m_settings . m_tCalHot ) ;
ui - > tCalHotUnitsLabel - > setText ( " K " ) ;
}
else
{
// Phot
double power = Astronomy : : noisePowerdBm ( m_settings . m_tCalHot , m_settings . m_sampleRate ) ;
ui - > tCalHot - > setValue ( power ) ;
ui - > tCalHotUnitsLabel - > setText ( " dBm " ) ;
}
}
void RadioAstronomyGUI : : on_tCalHot_valueChanged ( double value )
{
double temp ;
if ( ui - > tCalHotSelect - > currentIndex ( ) = = 0 ) {
temp = value ;
} else {
temp = Astronomy : : noiseTemp ( value , m_settings . m_sampleRate ) ;
}
m_settings . m_tCalHot = ( float ) temp ;
calibrate ( ) ;
2026-02-01 00:49:36 +01:00
applySettings ( QStringList ( " tCalHot " ) ) ;
2021-10-12 11:31:14 +01:00
}
void RadioAstronomyGUI : : on_tCalColdSelect_currentIndexChanged ( int value )
{
if ( value = = 0 )
{
// Tcold
ui - > tCalCold - > setValue ( m_settings . m_tCalCold ) ;
ui - > tCalColdUnitsLabel - > setText ( " K " ) ;
}
else
{
// Pcold
double power = Astronomy : : noisePowerdBm ( m_settings . m_tCalCold , m_settings . m_sampleRate ) ;
ui - > tCalCold - > setValue ( power ) ;
ui - > tCalColdUnitsLabel - > setText ( " dBm " ) ;
}
}
void RadioAstronomyGUI : : on_tCalCold_valueChanged ( double value )
{
double temp ;
if ( ui - > tCalColdSelect - > currentIndex ( ) = = 0 ) {
temp = value ;
} else {
temp = Astronomy : : noiseTemp ( value , m_settings . m_sampleRate ) ;
}
m_settings . m_tCalCold = ( float ) temp ;
calibrate ( ) ;
2026-02-01 00:49:36 +01:00
applySettings ( QStringList ( " tCalCold " ) ) ;
2021-10-12 11:31:14 +01:00
}
void RadioAstronomyGUI : : on_spectrumLine_currentIndexChanged ( int value )
{
m_settings . m_line = ( RadioAstronomySettings : : Line ) value ;
displaySpectrumLineFrequency ( ) ;
plotFFTMeasurement ( ) ;
2026-02-01 00:49:36 +01:00
applySettings ( QStringList ( " line " ) ) ;
2021-10-12 11:31:14 +01:00
}
void RadioAstronomyGUI : : displaySpectrumLineFrequency ( )
{
switch ( m_settings . m_line )
{
case RadioAstronomySettings : : HI :
ui - > spectrumLineFrequency - > setValue ( Astronomy : : m_hydrogenLineFrequency / 1e6 ) ;
ui - > spectrumLineFrequency - > setEnabled ( false ) ;
break ;
case RadioAstronomySettings : : OH :
ui - > spectrumLineFrequency - > setValue ( Astronomy : : m_hydroxylLineFrequency / 1e6 ) ;
ui - > spectrumLineFrequency - > setEnabled ( false ) ;
break ;
case RadioAstronomySettings : : DI :
ui - > spectrumLineFrequency - > setValue ( Astronomy : : m_deuteriumLineFrequency / 1e6 ) ;
ui - > spectrumLineFrequency - > setEnabled ( false ) ;
break ;
case RadioAstronomySettings : : CUSTOM_LINE :
ui - > spectrumLineFrequency - > setValue ( m_settings . m_lineCustomFrequency / 1e6 ) ;
ui - > spectrumLineFrequency - > setEnabled ( true ) ;
break ;
}
}
void RadioAstronomyGUI : : on_spectrumLineFrequency_valueChanged ( double value )
{
m_settings . m_lineCustomFrequency = value * 1e6 ;
plotFFTMeasurement ( ) ;
2026-02-01 00:49:36 +01:00
applySettings ( QStringList ( " lineCustomFrequency " ) ) ;
2021-10-12 11:31:14 +01:00
}
void RadioAstronomyGUI : : on_refFrame_currentIndexChanged ( int value )
{
m_settings . m_refFrame = ( RadioAstronomySettings : : RefFrame ) value ;
plotFFTMeasurement ( ) ;
2026-02-01 00:49:36 +01:00
applySettings ( QStringList ( " refFrame " ) ) ;
2021-10-12 11:31:14 +01:00
}
void RadioAstronomyGUI : : on_sunDistanceToGC_valueChanged ( double value )
{
m_settings . m_sunDistanceToGC = value ;
2026-02-01 00:49:36 +01:00
applySettings ( QStringList ( " sunDistanceToGC " ) ) ;
2021-10-12 11:31:14 +01:00
calcDistances ( ) ;
}
void RadioAstronomyGUI : : on_sunOrbitalVelocity_valueChanged ( double value )
{
m_settings . m_sunOrbitalVelocity = value ;
2026-02-01 00:49:36 +01:00
applySettings ( QStringList ( " sunOrbitalVelocity " ) ) ;
2021-10-12 11:31:14 +01:00
calcDistances ( ) ;
}
void RadioAstronomyGUI : : on_savePowerChartImage_clicked ( )
{
2023-05-03 18:16:37 +01:00
QFileDialog fileDialog ( nullptr , " Select file to save image to " , " " , " *.png *.jpg *.jpeg *.bmp *.ppm *.xbm *.xpm " ) ;
2021-10-12 11:31:14 +01:00
fileDialog . setAcceptMode ( QFileDialog : : AcceptSave ) ;
if ( fileDialog . exec ( ) )
{
QStringList fileNames = fileDialog . selectedFiles ( ) ;
if ( fileNames . size ( ) > 0 )
{
QImage image ( ui - > powerChart - > size ( ) , QImage : : Format_ARGB32 ) ;
image . fill ( Qt : : transparent ) ;
QPainter painter ( & image ) ;
ui - > powerChart - > render ( & painter ) ;
if ( ! image . save ( fileNames [ 0 ] ) ) {
QMessageBox : : critical ( this , " Radio Astronomy " , QString ( " Failed to save image to %1 " ) . arg ( fileNames [ 0 ] ) ) ;
}
}
}
}
void RadioAstronomyGUI : : on_saveSpectrumChartImage_clicked ( )
{
2023-05-03 18:16:37 +01:00
QFileDialog fileDialog ( nullptr , " Select file to save image to " , " " , " *.png *.jpg *.jpeg *.bmp *.ppm *.xbm *.xpm " ) ;
2021-10-12 11:31:14 +01:00
fileDialog . setAcceptMode ( QFileDialog : : AcceptSave ) ;
if ( fileDialog . exec ( ) )
{
QStringList fileNames = fileDialog . selectedFiles ( ) ;
if ( fileNames . size ( ) > 0 )
{
QImage image ( ui - > spectrumChart - > size ( ) , QImage : : Format_ARGB32 ) ;
image . fill ( Qt : : transparent ) ;
QPainter painter ( & image ) ;
ui - > spectrumChart - > render ( & painter ) ;
if ( ! image . save ( fileNames [ 0 ] ) ) {
QMessageBox : : critical ( this , " Radio Astronomy " , QString ( " Failed to save image to %1 " ) . arg ( fileNames [ 0 ] ) ) ;
}
}
}
}
void RadioAstronomyGUI : : on_saveSpectrumChartImages_clicked ( )
{
if ( m_fftMeasurements . size ( ) > 1 )
{
// Get filename of animation file
QFileDialog fileDialog ( nullptr , " Select file to save animation to " , " " , " *.png " ) ;
fileDialog . setAcceptMode ( QFileDialog : : AcceptSave ) ;
if ( fileDialog . exec ( ) )
{
QStringList fileNames = fileDialog . selectedFiles ( ) ;
if ( fileNames . size ( ) > 0 )
{
// Create animation file
APNG apng ( m_fftMeasurements . size ( ) ) ;
// Plot each FFT to a temp .png file (in memory) then append to animation file
for ( int i = 0 ; i < m_fftMeasurements . size ( ) ; i + + )
{
plotFFTMeasurement ( i ) ;
2022-09-26 12:46:52 +01:00
QApplication : : processEvents ( ) ; // To get chart title to be updated
2021-10-12 11:31:14 +01:00
QImage image ( ui - > spectrumChart - > size ( ) , QImage : : Format_ARGB32 ) ;
image . fill ( Qt : : transparent ) ;
QPainter painter ( & image ) ;
ui - > spectrumChart - > render ( & painter ) ;
apng . addImage ( image ) ;
}
if ( ! apng . save ( fileNames [ 0 ] ) ) {
QMessageBox : : critical ( this , " Radio Astronomy " , QString ( " Failed to write to file %1 " ) . arg ( fileNames [ 0 ] ) ) ;
}
}
}
}
}
void RadioAstronomyGUI : : on_spectrumReverseXAxis_toggled ( bool checked )
{
m_settings . m_spectrumReverseXAxis = checked ;
2026-02-01 00:49:36 +01:00
applySettings ( QStringList ( " spectrumReverseXAxis " ) ) ;
2021-10-12 11:31:14 +01:00
if ( ui - > spectrumChartSelect - > currentIndex ( ) = = 0 ) {
plotFFTMeasurement ( ) ;
} else {
m_calXAxis - > setReverse ( m_settings . m_spectrumReverseXAxis ) ;
}
}
void RadioAstronomyGUI : : on_powerShowPeak_toggled ( bool checked )
{
m_settings . m_powerPeaks = checked ;
updatePowerMarkerTableVisibility ( ) ;
2026-02-01 00:49:36 +01:00
applySettings ( QStringList ( " powerPeaks " ) ) ;
2021-10-12 11:31:14 +01:00
if ( m_powerPeakSeries )
{
m_powerPeakSeries - > setVisible ( checked ) ;
if ( checked ) {
m_powerChart - > legend ( ) - > markers ( m_powerPeakSeries ) [ 0 ] - > setVisible ( false ) ;
}
}
2022-04-12 16:20:45 +02:00
getRollupContents ( ) - > arrangeRollups ( ) ;
2021-10-12 11:31:14 +01:00
}
void RadioAstronomyGUI : : on_spectrumPeak_toggled ( bool checked )
{
m_settings . m_spectrumPeaks = checked ;
updateSpectrumMarkerTableVisibility ( ) ;
plotFFTMeasurement ( ) ;
2026-02-01 00:49:36 +01:00
applySettings ( QStringList ( " spectrumPeaks " ) ) ;
2021-10-12 11:31:14 +01:00
if ( m_fftChart )
{
if ( checked ) {
m_fftChart - > legend ( ) - > markers ( m_fftPeakSeries ) [ 0 ] - > setVisible ( false ) ;
showLoSMarker ( " Max " ) ;
} else {
clearLoSMarker ( " Max " ) ;
}
}
2022-04-12 16:20:45 +02:00
getRollupContents ( ) - > arrangeRollups ( ) ;
2021-10-12 11:31:14 +01:00
}
void RadioAstronomyGUI : : on_powerShowMarker_toggled ( bool checked )
{
m_settings . m_powerMarkers = checked ;
updatePowerMarkerTableVisibility ( ) ;
2026-02-01 00:49:36 +01:00
applySettings ( QStringList ( " powerMarkers " ) ) ;
2021-10-12 11:31:14 +01:00
if ( m_powerMarkerSeries )
{
m_powerMarkerSeries - > setVisible ( checked ) ;
if ( checked ) {
m_powerChart - > legend ( ) - > markers ( m_powerMarkerSeries ) [ 0 ] - > setVisible ( false ) ;
}
}
updatePowerSelect ( ) ;
2022-04-12 16:20:45 +02:00
getRollupContents ( ) - > arrangeRollups ( ) ;
2021-10-12 11:31:14 +01:00
}
void RadioAstronomyGUI : : on_powerShowAvg_toggled ( bool checked )
{
m_settings . m_powerAvg = checked ;
2026-02-01 00:49:36 +01:00
applySettings ( QStringList ( " powerAvg " ) ) ;
2021-10-12 11:31:14 +01:00
ui - > powerChartAvgWidgets - > setVisible ( checked ) ;
2022-04-12 16:20:45 +02:00
getRollupContents ( ) - > arrangeRollups ( ) ;
2021-10-12 11:31:14 +01:00
if ( checked ) {
calcAverages ( ) ;
}
}
void RadioAstronomyGUI : : on_powerShowLegend_toggled ( bool checked )
{
m_settings . m_powerLegend = checked ;
2026-02-01 00:49:36 +01:00
applySettings ( QStringList ( " powerLegend " ) ) ;
2021-10-12 11:31:14 +01:00
if ( m_powerChart )
{
if ( checked ) {
m_powerChart - > legend ( ) - > show ( ) ;
} else {
m_powerChart - > legend ( ) - > hide ( ) ;
}
}
}
void RadioAstronomyGUI : : on_powerShowTsys0_toggled ( bool checked )
{
m_settings . m_powerShowTsys0 = checked ;
2026-02-01 00:49:36 +01:00
applySettings ( QStringList ( " powerShowTsys0 " ) ) ;
2021-10-12 11:31:14 +01:00
if ( m_powerTsys0Series ) {
m_powerTsys0Series - > setVisible ( checked ) ;
}
}
void RadioAstronomyGUI : : on_powerShowAirTemp_toggled ( bool checked )
{
m_settings . m_powerShowAirTemp = checked ;
2026-02-01 00:49:36 +01:00
applySettings ( QStringList ( " powerShowAirTemp " ) ) ;
2021-10-12 11:31:14 +01:00
m_airTemps . clicked ( checked ) ;
}
void RadioAstronomyGUI : : on_powerShowSensor1_toggled ( bool checked )
{
m_settings . m_sensorVisible [ 0 ] = checked ;
2026-02-01 00:49:36 +01:00
applySettings ( QStringList ( " sensorVisible " ) ) ;
2021-10-12 11:31:14 +01:00
m_sensors [ 0 ] . clicked ( checked ) ;
}
void RadioAstronomyGUI : : on_powerShowSensor2_toggled ( bool checked )
{
m_settings . m_sensorVisible [ 1 ] = checked ;
2026-02-01 00:49:36 +01:00
applySettings ( QStringList ( " sensorVisible " ) ) ;
2021-10-12 11:31:14 +01:00
m_sensors [ 1 ] . clicked ( checked ) ;
}
void RadioAstronomyGUI : : updatePowerMarkerTableVisibility ( )
{
ui - > powerMarkerTableWidgets - > setVisible ( m_settings . m_powerPeaks | | m_settings . m_powerMarkers ) ;
if ( m_settings . m_powerPeaks )
{
ui - > powerMarkerTable - > showRow ( POWER_MARKER_ROW_PEAK_MAX ) ;
ui - > powerMarkerTable - > showRow ( POWER_MARKER_ROW_PEAK_MIN ) ;
}
else
{
ui - > powerMarkerTable - > hideRow ( POWER_MARKER_ROW_PEAK_MAX ) ;
ui - > powerMarkerTable - > hideRow ( POWER_MARKER_ROW_PEAK_MIN ) ;
}
if ( m_settings . m_powerMarkers )
{
ui - > powerMarkerTable - > showRow ( POWER_MARKER_ROW_M1 ) ;
ui - > powerMarkerTable - > showRow ( POWER_MARKER_ROW_M2 ) ;
}
else
{
ui - > powerMarkerTable - > hideRow ( POWER_MARKER_ROW_M1 ) ;
ui - > powerMarkerTable - > hideRow ( POWER_MARKER_ROW_M2 ) ;
}
ui - > powerMarkerTableWidgets - > updateGeometry ( ) ; // Without this, widgets aren't resized properly
}
void RadioAstronomyGUI : : updateSpectrumMarkerTableVisibility ( )
{
bool fft = ui - > spectrumChartSelect - > currentIndex ( ) = = 0 ;
ui - > spectrumMarkerTableWidgets - > setVisible ( fft & & ( m_settings . m_spectrumPeaks | | m_settings . m_spectrumMarkers ) ) ;
if ( m_settings . m_spectrumPeaks )
{
ui - > spectrumMarkerTable - > showRow ( SPECTRUM_MARKER_ROW_PEAK ) ;
}
else
{
ui - > spectrumMarkerTable - > hideRow ( SPECTRUM_MARKER_ROW_PEAK ) ;
}
if ( m_settings . m_spectrumMarkers )
{
ui - > spectrumMarkerTable - > showRow ( SPECTRUM_MARKER_ROW_M1 ) ;
ui - > spectrumMarkerTable - > showRow ( SPECTRUM_MARKER_ROW_M2 ) ;
}
else
{
ui - > spectrumMarkerTable - > hideRow ( SPECTRUM_MARKER_ROW_M1 ) ;
ui - > spectrumMarkerTable - > hideRow ( SPECTRUM_MARKER_ROW_M2 ) ;
}
ui - > spectrumMarkerTableWidgets - > updateGeometry ( ) ; // Without this, widgets aren't resized properly
}
void RadioAstronomyGUI : : on_spectrumMarker_toggled ( bool checked )
{
m_settings . m_spectrumMarkers = checked ;
2026-02-01 00:49:36 +01:00
applySettings ( QStringList ( " spectrumMarkers " ) ) ;
2021-10-12 11:31:14 +01:00
updateSpectrumMarkerTableVisibility ( ) ;
m_fftMarkerSeries - > setVisible ( checked ) ;
if ( checked )
{
m_fftChart - > legend ( ) - > markers ( m_fftMarkerSeries ) [ 0 ] - > setVisible ( false ) ;
showLoSMarker ( " M1 " ) ;
showLoSMarker ( " M2 " ) ;
}
else
{
clearLoSMarker ( " M1 " ) ;
clearLoSMarker ( " M2 " ) ;
}
updateSpectrumSelect ( ) ;
2022-04-12 16:20:45 +02:00
getRollupContents ( ) - > arrangeRollups ( ) ;
2021-10-12 11:31:14 +01:00
}
void RadioAstronomyGUI : : on_spectrumTemp_toggled ( bool checked )
{
m_settings . m_spectrumTemp = checked ;
2026-02-01 00:49:36 +01:00
applySettings ( QStringList ( " spectrumTemp " ) ) ;
2021-10-12 11:31:14 +01:00
ui - > spectrumGaussianWidgets - > setVisible ( checked ) ;
m_fftGaussianSeries - > setVisible ( checked ) ;
updateSpectrumSelect ( ) ;
2022-04-12 16:20:45 +02:00
getRollupContents ( ) - > arrangeRollups ( ) ;
2021-10-12 11:31:14 +01:00
}
void RadioAstronomyGUI : : on_spectrumShowLegend_toggled ( bool checked )
{
m_settings . m_spectrumLegend = checked ;
2026-02-01 00:49:36 +01:00
applySettings ( QStringList ( " spectrumLegend " ) ) ;
2021-10-12 11:31:14 +01:00
if ( m_fftChart )
{
m_fftChart - > legend ( ) - > setVisible ( checked ) ;
m_calChart - > legend ( ) - > setVisible ( checked ) ;
}
}
void RadioAstronomyGUI : : on_spectrumShowRefLine_toggled ( bool checked )
{
m_settings . m_spectrumRefLine = checked ;
2026-02-01 00:49:36 +01:00
applySettings ( QStringList ( " spectrumRefLine " ) ) ;
2021-10-12 11:31:14 +01:00
ui - > spectrumRefLineWidgets - > setVisible ( checked ) ;
if ( m_fftHlineSeries )
{
m_fftHlineSeries - > setVisible ( m_settings . m_spectrumRefLine ) ;
m_fftDopplerAxis - > setVisible ( m_settings . m_spectrumRefLine ) ;
}
updateDistanceColumns ( ) ;
2022-04-12 16:20:45 +02:00
getRollupContents ( ) - > arrangeRollups ( ) ;
2021-10-12 11:31:14 +01:00
}
void RadioAstronomyGUI : : on_spectrumShowLAB_toggled ( bool checked )
{
m_settings . m_spectrumLAB = checked ;
2026-02-01 00:49:36 +01:00
applySettings ( QStringList ( " spectrumLAB " ) ) ;
2021-10-12 11:31:14 +01:00
m_fftLABSeries - > setVisible ( m_settings . m_spectrumLAB ) ;
if ( m_settings . m_spectrumLAB ) {
2024-07-10 22:59:13 +02:00
plotLAB ( ) ; // Replot in case data needs to be downloaded
2021-10-12 11:31:14 +01:00
}
spectrumAutoscale ( ) ;
}
void RadioAstronomyGUI : : updateDistanceColumns ( )
{
if ( m_settings . m_spectrumDistance & & m_settings . m_spectrumRefLine )
{
ui - > spectrumMarkerTable - > showColumn ( SPECTRUM_MARKER_COL_R ) ;
ui - > spectrumMarkerTable - > showColumn ( SPECTRUM_MARKER_COL_D ) ;
2022-09-26 12:46:52 +01:00
ui - > spectrumMarkerTable - > showColumn ( SPECTRUM_MARKER_COL_PLOT_MAX ) ;
ui - > spectrumMarkerTable - > showColumn ( SPECTRUM_MARKER_COL_R_MIN ) ;
ui - > spectrumMarkerTable - > showColumn ( SPECTRUM_MARKER_COL_V ) ;
2021-10-12 11:31:14 +01:00
showLoSMarker ( " Max " ) ;
showLoSMarker ( " M1 " ) ;
showLoSMarker ( " M2 " ) ;
ui - > sunDistanceToGCLine - > setVisible ( true ) ;
ui - > sunDistanceToGCLabel - > setVisible ( true ) ;
ui - > sunDistanceToGC - > setVisible ( true ) ;
ui - > sunDistanceToGCUnits - > setVisible ( true ) ;
ui - > sunOrbitalVelocityLine - > setVisible ( true ) ;
ui - > sunOrbitalVelocityLabel - > setVisible ( true ) ;
ui - > sunOrbitalVelocity - > setVisible ( true ) ;
ui - > sunOrbitalVelocityUnits - > setVisible ( true ) ;
}
else
{
ui - > spectrumMarkerTable - > hideColumn ( SPECTRUM_MARKER_COL_R ) ;
ui - > spectrumMarkerTable - > hideColumn ( SPECTRUM_MARKER_COL_D ) ;
2022-09-26 12:46:52 +01:00
ui - > spectrumMarkerTable - > hideColumn ( SPECTRUM_MARKER_COL_PLOT_MAX ) ;
ui - > spectrumMarkerTable - > hideColumn ( SPECTRUM_MARKER_COL_R_MIN ) ;
ui - > spectrumMarkerTable - > hideColumn ( SPECTRUM_MARKER_COL_V ) ;
2021-10-12 11:31:14 +01:00
clearLoSMarker ( " Max " ) ;
clearLoSMarker ( " M1 " ) ;
clearLoSMarker ( " M2 " ) ;
ui - > sunDistanceToGCLine - > setVisible ( false ) ;
ui - > sunDistanceToGCLabel - > setVisible ( false ) ;
ui - > sunDistanceToGC - > setVisible ( false ) ;
ui - > sunDistanceToGCUnits - > setVisible ( false ) ;
ui - > sunOrbitalVelocityLine - > setVisible ( false ) ;
ui - > sunOrbitalVelocityLabel - > setVisible ( false ) ;
ui - > sunOrbitalVelocity - > setVisible ( false ) ;
ui - > sunOrbitalVelocityUnits - > setVisible ( false ) ;
}
}
void RadioAstronomyGUI : : on_spectrumShowDistance_toggled ( bool checked )
{
m_settings . m_spectrumDistance = checked ;
2026-02-01 00:49:36 +01:00
applySettings ( QStringList ( " spectrumDistance " ) ) ;
2021-10-12 11:31:14 +01:00
if ( m_settings . m_spectrumDistance & & ! m_settings . m_spectrumRefLine ) {
ui - > spectrumShowRefLine - > setChecked ( true ) ;
}
updateDistanceColumns ( ) ;
}
// point isn't necessarily a point in the series - may be interpolated
void RadioAstronomyGUI : : powerSeries_clicked ( const QPointF & point )
{
QString selection = ui - > powerSelect - > currentText ( ) ;
if ( selection . startsWith ( " M " ) )
{
if ( selection = = " M1 " )
{
// Place marker 1
m_powerM1X = point . x ( ) ;
m_powerM1Y = point . y ( ) ;
if ( m_powerM1Valid ) {
m_powerMarkerSeries - > replace ( 0 , m_powerM1X , m_powerM1Y ) ;
} else {
m_powerMarkerSeries - > insert ( 0 , QPointF ( m_powerM1X , m_powerM1Y ) ) ;
}
m_powerM1Valid = true ;
QDateTime dt = QDateTime : : fromMSecsSinceEpoch ( m_powerM1X ) ;
ui - > powerMarkerTable - > item ( POWER_MARKER_ROW_M1 , POWER_MARKER_COL_DATE ) - > setData ( Qt : : DisplayRole , dt . date ( ) ) ;
ui - > powerMarkerTable - > item ( POWER_MARKER_ROW_M1 , POWER_MARKER_COL_TIME ) - > setData ( Qt : : DisplayRole , dt . time ( ) ) ;
ui - > powerMarkerTable - > item ( POWER_MARKER_ROW_M1 , POWER_MARKER_COL_VALUE ) - > setData ( Qt : : DisplayRole , m_powerM1Y ) ;
calcPowerMarkerDelta ( ) ;
}
else if ( selection = = " M2 " )
{
// Place marker 2
m_powerM2X = point . x ( ) ;
m_powerM2Y = point . y ( ) ;
if ( m_powerM2Valid ) {
m_powerMarkerSeries - > replace ( 1 , m_powerM2X , m_powerM2Y ) ;
} else {
m_powerMarkerSeries - > insert ( 1 , QPointF ( m_powerM2X , m_powerM2Y ) ) ;
}
m_powerM2Valid = true ;
QDateTime dt = QDateTime : : fromMSecsSinceEpoch ( m_powerM2X ) ;
ui - > powerMarkerTable - > item ( POWER_MARKER_ROW_M2 , POWER_MARKER_COL_DATE ) - > setData ( Qt : : DisplayRole , dt . date ( ) ) ;
ui - > powerMarkerTable - > item ( POWER_MARKER_ROW_M2 , POWER_MARKER_COL_TIME ) - > setData ( Qt : : DisplayRole , dt . time ( ) ) ;
ui - > powerMarkerTable - > item ( POWER_MARKER_ROW_M2 , POWER_MARKER_COL_VALUE ) - > setData ( Qt : : DisplayRole , m_powerM2Y ) ;
calcPowerMarkerDelta ( ) ;
}
}
else if ( selection = = " Gaussian " )
{
// Fit a Gaussian assuming point clicked is the peak
ui - > powerGaussianCenter - > setDateTime ( QDateTime : : fromMSecsSinceEpoch ( point . x ( ) ) ) ;
// Calculate noise floor - take average of lowest 10%
qreal floor = calcSeriesFloor ( m_powerSeries ) ;
ui - > powerGaussianFloor - > setValue ( floor ) ;
// Set amplitude to achieve selected point
ui - > powerGaussianAmp - > setValue ( point . y ( ) - floor ) ;
}
else
{
if ( m_fftMeasurements . size ( ) > 1 )
{
// Select row closest to clicked data
QDateTime dt = QDateTime : : fromMSecsSinceEpoch ( point . x ( ) ) ;
int i = 0 ;
while ( ( i < m_fftMeasurements . size ( ) ) & & ( dt > m_fftMeasurements [ i ] - > m_dateTime ) ) {
i + + ;
}
if ( i < m_fftMeasurements . size ( ) ) {
ui - > spectrumIndex - > setValue ( i ) ;
}
}
}
}
qreal RadioAstronomyGUI : : calcSeriesFloor ( QXYSeries * series , int percent )
{
QList < qreal > minValues ;
double count = series - > count ( ) * percent / 100.0 ;
for ( int i = 0 ; i < series - > count ( ) ; i + + )
{
qreal y = series - > at ( i ) . y ( ) ;
if ( minValues . size ( ) < count )
{
minValues . append ( y ) ;
std : : sort ( minValues . begin ( ) , minValues . end ( ) ) ;
}
else if ( y < minValues . last ( ) )
{
minValues . append ( y ) ;
std : : sort ( minValues . begin ( ) , minValues . end ( ) ) ;
}
}
qreal sum = std : : accumulate ( minValues . begin ( ) , minValues . end ( ) , 0.0 ) ;
return sum / minValues . size ( ) ;
}
void RadioAstronomyGUI : : updateSpectrumSelect ( )
{
ui - > spectrumSelect - > clear ( ) ;
if ( m_settings . m_spectrumMarkers )
{
ui - > spectrumSelect - > addItem ( " M1 " ) ;
ui - > spectrumSelect - > addItem ( " M2 " ) ;
}
if ( m_settings . m_spectrumTemp )
{
ui - > spectrumSelect - > addItem ( " Gaussian " ) ;
}
bool visible = ui - > spectrumSelect - > count ( ) ! = 0 ;
ui - > spectrumSelectLabel - > setVisible ( visible ) ;
ui - > spectrumSelect - > setVisible ( visible ) ;
}
void RadioAstronomyGUI : : updatePowerSelect ( )
{
ui - > powerSelect - > clear ( ) ;
if ( m_settings . m_powerMarkers | | m_settings . m_powerShowGaussian ) {
ui - > powerSelect - > addItem ( " Row " ) ;
}
if ( m_settings . m_powerMarkers )
{
ui - > powerSelect - > addItem ( " M1 " ) ;
ui - > powerSelect - > addItem ( " M2 " ) ;
}
if ( m_settings . m_powerShowGaussian ) {
ui - > powerSelect - > addItem ( " Gaussian " ) ;
}
bool visible = ui - > powerSelect - > count ( ) ! = 0 ;
ui - > powerSelectLabel - > setVisible ( visible ) ;
ui - > powerSelect - > setVisible ( visible ) ;
}
void RadioAstronomyGUI : : spectrumSeries_clicked ( const QPointF & point )
{
QString selection = ui - > spectrumSelect - > currentText ( ) ;
if ( selection . startsWith ( " M " ) )
{
FFTMeasurement * fft = currentFFT ( ) ;
if ( selection = = " M1 " )
{
m_spectrumM1X = point . x ( ) ;
m_spectrumM1Y = point . y ( ) ;
m_spectrumM1Valid = true ;
ui - > spectrumMarkerTable - > item ( SPECTRUM_MARKER_ROW_M1 , SPECTRUM_MARKER_COL_FREQ ) - > setData ( Qt : : DisplayRole , m_spectrumM1X ) ;
ui - > spectrumMarkerTable - > item ( SPECTRUM_MARKER_ROW_M1 , SPECTRUM_MARKER_COL_VALUE ) - > setData ( Qt : : DisplayRole , m_spectrumM1Y ) ;
calcVrAndDistanceToPeak ( m_spectrumM1X * 1e6 , fft , SPECTRUM_MARKER_ROW_M1 ) ;
}
else if ( selection = = " M2 " )
{
m_spectrumM2X = point . x ( ) ;
m_spectrumM2Y = point . y ( ) ;
m_spectrumM2Valid = true ;
ui - > spectrumMarkerTable - > item ( SPECTRUM_MARKER_ROW_M2 , SPECTRUM_MARKER_COL_FREQ ) - > setData ( Qt : : DisplayRole , m_spectrumM2X ) ;
ui - > spectrumMarkerTable - > item ( SPECTRUM_MARKER_ROW_M2 , SPECTRUM_MARKER_COL_VALUE ) - > setData ( Qt : : DisplayRole , m_spectrumM2Y ) ;
calcVrAndDistanceToPeak ( m_spectrumM2X * 1e6 , fft , SPECTRUM_MARKER_ROW_M2 ) ;
}
calcSpectrumMarkerDelta ( ) ;
m_fftMarkerSeries - > clear ( ) ;
if ( m_spectrumM1Valid ) {
m_fftMarkerSeries - > append ( m_spectrumM1X , m_spectrumM1Y ) ;
}
if ( m_spectrumM2Valid ) {
m_fftMarkerSeries - > append ( m_spectrumM2X , m_spectrumM2Y ) ;
}
}
else if ( selection = = " Gaussian " )
{
ui - > spectrumGaussianFreq - > setValue ( point . x ( ) ) ;
// Calculate noise floor - take average of lowest 10%
qreal floor = calcSeriesFloor ( m_fftSeries ) ;
ui - > spectrumGaussianFloor - > setValue ( floor ) ;
// Set amplitude to achieve selected point
ui - > spectrumGaussianAmp - > setValue ( point . y ( ) - floor ) ;
plotFFTMeasurement ( ) ;
}
}
void RadioAstronomyGUI : : on_spectrumGaussianFreq_valueChanged ( double value )
{
( void ) value ;
calcFWHM ( ) ;
plotFFTMeasurement ( ) ;
}
void RadioAstronomyGUI : : on_spectrumGaussianAmp_valueChanged ( double value )
{
( void ) value ;
plotFFTMeasurement ( ) ;
calcColumnDensity ( ) ;
}
void RadioAstronomyGUI : : on_spectrumGaussianFloor_valueChanged ( double value )
{
( void ) value ;
plotFFTMeasurement ( ) ;
}
void RadioAstronomyGUI : : on_spectrumGaussianFWHM_valueChanged ( double fFWHM )
{
double c = Astronomy : : m_speedOfLight ;
double k = Astronomy : : m_boltzmann ;
double m = Astronomy : : m_hydrogenMass ;
double f0 = ui - > spectrumGaussianFreq - > value ( ) * 1e6 ;
double vTurb = ui - > spectrumGaussianTurb - > value ( ) * 1e3 ; // RSM turbulent velocties - Convert to m/s
const double bf = 2.0 * sqrt ( M_LN2 ) ; // Convert from Doppler parameter to FWHM
double fr = fFWHM * c / ( bf * f0 ) ;
double frs = fr * fr ;
double T = m * ( frs - vTurb * vTurb ) / ( 2.0 * k ) ;
ui - > spectrumTemperature - > blockSignals ( true ) ;
ui - > spectrumTemperature - > setValue ( T ) ;
ui - > spectrumTemperature - > blockSignals ( false ) ;
plotFFTMeasurement ( ) ;
calcColumnDensity ( ) ;
}
void RadioAstronomyGUI : : on_spectrumGaussianTurb_valueChanged ( double value )
{
( void ) value ;
calcFWHM ( ) ;
plotFFTMeasurement ( ) ;
}
void RadioAstronomyGUI : : on_spectrumTemperature_valueChanged ( double value )
{
( void ) value ;
calcFWHM ( ) ;
plotFFTMeasurement ( ) ;
}
void RadioAstronomyGUI : : calcFWHM ( )
{
double c = Astronomy : : m_speedOfLight ;
double k = Astronomy : : m_boltzmann ;
double m = Astronomy : : m_hydrogenMass ;
double f0 = ui - > spectrumGaussianFreq - > value ( ) * 1e6 ;
double vTurb = ui - > spectrumGaussianTurb - > value ( ) * 1e3 ; // RSM turbulent velocties - Convert to m/s
double T = ui - > spectrumTemperature - > value ( ) ;
const double bf = 2.0 * sqrt ( M_LN2 ) ; // Convert from Doppler parameter to FWHM
double fFWHM = bf * f0 / c * sqrt ( ( 2 * k * T ) / m + vTurb * vTurb ) ;
ui - > spectrumGaussianFWHM - > blockSignals ( true ) ;
ui - > spectrumGaussianFWHM - > setValue ( fFWHM ) ;
ui - > spectrumGaussianFWHM - > blockSignals ( false ) ;
calcColumnDensity ( ) ;
}
// Assumes optically thin
void RadioAstronomyGUI : : calcColumnDensity ( )
{
double f0 = ui - > spectrumLineFrequency - > value ( ) * 1e6 ;
double f = f0 + ui - > spectrumGaussianFWHM - > value ( ) / 2.0 ;
double v = lineDopplerVelocity ( f0 , f ) * 2.0 ;
double a = ui - > spectrumGaussianAmp - > value ( ) ;
double integratedIntensity = v * a ;
double columnDensity = 1.81e18 * integratedIntensity ;
ui - > columnDensity - > setText ( QString : : number ( columnDensity , ' g ' , 2 ) ) ;
}
void RadioAstronomyGUI : : on_powerShowGaussian_clicked ( bool checked )
{
m_settings . m_powerShowGaussian = checked ;
2026-02-01 00:49:36 +01:00
applySettings ( QStringList ( " powerShowGaussian " ) ) ;
2021-10-12 11:31:14 +01:00
ui - > powerGaussianWidgets - > setVisible ( checked ) ;
m_powerGaussianSeries - > setVisible ( checked ) ;
updatePowerSelect ( ) ;
2022-04-12 16:20:45 +02:00
getRollupContents ( ) - > arrangeRollups ( ) ;
2022-09-26 12:46:52 +01:00
update ( ) ;
2021-10-12 11:31:14 +01:00
}
void RadioAstronomyGUI : : plotPowerGaussian ( )
{
m_powerGaussianSeries - > clear ( ) ;
double dt0 = ui - > powerGaussianCenter - > dateTime ( ) . toMSecsSinceEpoch ( ) ;
double a = ui - > powerGaussianAmp - > value ( ) ;
double floor = ui - > powerGaussianFloor - > value ( ) ;
double fwhm = ui - > powerGaussianFWHM - > value ( ) * 1000 ; // Convert from s to ms
double fwhm_sq = fwhm * fwhm ;
qint64 dt = m_powerXAxis - > min ( ) . toMSecsSinceEpoch ( ) ;
qint64 end = m_powerXAxis - > max ( ) . toMSecsSinceEpoch ( ) ;
int steps = 256 ;
qint64 step = ( end - dt ) / steps ;
for ( int i = 0 ; i < steps ; i + + )
{
double fd = dt - dt0 ;
double g = a * std : : exp ( - 4.0 * M_LN2 * fd * fd / fwhm_sq ) + floor ;
m_powerGaussianSeries - > append ( dt , g ) ;
dt + = step ;
}
}
// Calculate antenna HPBW from Sun's FWHM time
void RadioAstronomyGUI : : calcHPBWFromFWHM ( )
{
double fwhmSeconds = ui - > powerGaussianFWHM - > value ( ) ;
double sunDegPerSecond = 360.0 / ( 24.0 * 60.0 * 60.0 ) ;
double hpbwDeg = fwhmSeconds * sunDegPerSecond ;
ui - > powerGaussianHPBW - > setValue ( hpbwDeg ) ;
}
// Calculate Sun's FWHM time for anntena HPBW
void RadioAstronomyGUI : : calcFHWMFromHPBW ( )
{
double hpwmDeg = ui - > powerGaussianHPBW - > value ( ) ;
double sunDegPerSecond = 360.0 / ( 24.0 * 60.0 * 60.0 ) ;
double fwhmSeconds = hpwmDeg / sunDegPerSecond ;
ui - > powerGaussianFWHM - > setValue ( fwhmSeconds ) ;
}
void RadioAstronomyGUI : : on_powerGaussianCenter_dateTimeChanged ( QDateTime dateTime )
{
( void ) dateTime ;
plotPowerGaussian ( ) ;
}
void RadioAstronomyGUI : : on_powerGaussianAmp_valueChanged ( double value )
{
( void ) value ;
plotPowerGaussian ( ) ;
}
void RadioAstronomyGUI : : on_powerGaussianFloor_valueChanged ( double value )
{
( void ) value ;
plotPowerGaussian ( ) ;
}
void RadioAstronomyGUI : : on_powerGaussianFWHM_valueChanged ( double value )
{
( void ) value ;
plotPowerGaussian ( ) ;
ui - > powerGaussianHPBW - > blockSignals ( true ) ;
calcHPBWFromFWHM ( ) ;
ui - > powerGaussianHPBW - > blockSignals ( false ) ;
}
void RadioAstronomyGUI : : on_powerGaussianHPBW_valueChanged ( double value )
{
( void ) value ;
calcFHWMFromHPBW ( ) ;
ui - > powerGaussianFWHM - > blockSignals ( true ) ;
plotPowerGaussian ( ) ;
ui - > powerGaussianFWHM - > blockSignals ( false ) ;
}
2022-09-26 12:46:52 +01:00
void RadioAstronomyGUI : : addToPowerFilter ( qreal x , qreal y )
{
// Add data to circular buffer
m_window [ m_windowIdx ] = y ;
m_windowIdx = ( m_windowIdx + 1 ) % m_settings . m_powerFilterN ;
if ( m_windowCount < m_settings . m_powerFilterN ) {
m_windowCount + + ;
}
// Filter
if ( m_settings . m_powerFilter = = RadioAstronomySettings : : FILT_MOVING_AVERAGE )
{
// Moving average
qreal sum = 0.0 ;
for ( int i = 0 ; i < m_windowCount ; i + + ) {
sum + = m_window [ i ] ;
}
qreal mean = sum / m_windowCount ;
y = mean ;
}
else
{
// Median
std : : partial_sort_copy ( m_window , m_window + m_windowCount , m_windowSorted , m_windowSorted + m_windowCount ) ;
qreal median ;
if ( ( m_windowCount & 1 ) = = 1 ) {
median = m_windowSorted [ m_windowCount / 2 ] ;
} else {
median = ( m_windowSorted [ m_windowCount / 2 - 1 ] + m_windowSorted [ m_windowCount / 2 ] ) / 2.0 ;
}
y = median ;
}
// Add to series for chart
m_powerFilteredSeries - > append ( x , y ) ;
}
void RadioAstronomyGUI : : plotPowerFiltered ( )
{
delete [ ] m_window ;
delete [ ] m_windowSorted ;
m_window = new qreal [ m_settings . m_powerFilterN ] ;
m_windowSorted = new qreal [ m_settings . m_powerFilterN ] ;
m_windowIdx = 0 ;
m_windowCount = 0 ;
m_powerFilteredSeries - > clear ( ) ;
QVector < QPointF > powerSeries = m_powerSeries - > pointsVector ( ) ;
for ( int i = 0 ; i < powerSeries . size ( ) ; i + + )
{
QPointF point = powerSeries . at ( i ) ;
addToPowerFilter ( point . x ( ) , point . y ( ) ) ;
}
}
void RadioAstronomyGUI : : on_powerShowFiltered_clicked ( bool checked )
{
m_settings . m_powerShowFiltered = checked ;
2026-02-01 00:49:36 +01:00
applySettings ( QStringList ( " powerShowFiltered " ) ) ;
2022-09-26 12:46:52 +01:00
ui - > powerFilterWidgets - > setVisible ( checked ) ;
m_powerFilteredSeries - > setVisible ( checked ) ;
getRollupContents ( ) - > arrangeRollups ( ) ;
update ( ) ;
}
void RadioAstronomyGUI : : on_powerFilter_currentIndexChanged ( int index )
{
m_settings . m_powerFilter = ( RadioAstronomySettings : : PowerFilter ) index ;
2026-02-01 00:49:36 +01:00
applySettings ( QStringList ( " powerFilter " ) ) ;
2022-09-26 12:46:52 +01:00
plotPowerFiltered ( ) ;
}
void RadioAstronomyGUI : : on_powerFilterN_valueChanged ( int value )
{
m_settings . m_powerFilterN = value ;
2026-02-01 00:49:36 +01:00
applySettings ( QStringList ( " powerFilterN " ) ) ;
2022-09-26 12:46:52 +01:00
plotPowerFiltered ( ) ;
}
void RadioAstronomyGUI : : on_powerShowMeasurement_clicked ( bool checked )
{
m_settings . m_powerShowMeasurement = checked ;
2026-02-01 00:49:36 +01:00
applySettings ( QStringList ( " powerShowMeasurement " ) ) ;
2022-09-26 12:46:52 +01:00
m_powerSeries - > setVisible ( checked ) ;
}
2021-10-12 11:31:14 +01:00
RadioAstronomyGUI : : LABData * RadioAstronomyGUI : : parseLAB ( QFile * file , float l , float b )
{
LABData * data = new LABData ( ) ;
data - > read ( file , l , b ) ;
m_dataLAB . append ( data ) ;
return data ;
}
void RadioAstronomyGUI : : plotLAB ( )
{
int index = ui - > spectrumIndex - > value ( ) ;
if ( index < m_fftMeasurements . size ( ) )
{
FFTMeasurement * fft = m_fftMeasurements [ index ] ;
plotLAB ( fft - > m_l , fft - > m_b , m_beamWidth ) ;
}
}
void RadioAstronomyGUI : : plotLAB ( float l , float b , float beamWidth )
{
// Assume a beamwidth >1deg
l = round ( l ) ;
b = round ( b ) ;
// Check if we already have the data in memory
LABData * data = nullptr ;
for ( int i = 0 ; i < m_dataLAB . size ( ) ; i + + )
{
if ( ( m_dataLAB [ i ] - > m_l = = l ) & & ( m_dataLAB [ i ] - > m_b = = b ) )
{
data = m_dataLAB [ i ] ;
break ;
}
}
if ( ! data )
{
// Try to open previously downloaded data
2022-09-26 12:46:52 +01:00
QString filenameLAB = HttpDownloadManager : : downloadDir ( ) + " / " + QString ( " lab_l_%1_b_%2.txt " ) . arg ( l ) . arg ( b ) ;
QFile file ( filenameLAB ) ;
2021-10-12 11:31:14 +01:00
if ( file . open ( QIODevice : : ReadOnly ) )
{
2022-09-26 12:46:52 +01:00
qDebug ( ) < < " RadioAstronomyGUI::plotLAB: Using cached file: " < < filenameLAB ;
2021-10-12 11:31:14 +01:00
data = parseLAB ( & file , l , b ) ;
}
else
{
// Only download one file at a time, so we don't overload the server
if ( ! m_downloadingLAB )
{
m_downloadingLAB = true ;
m_lLAB = l ;
m_bLAB = b ;
2022-09-26 12:46:52 +01:00
m_filenameLAB = filenameLAB ;
2021-10-12 11:31:14 +01:00
// Request data be generated via web server
QNetworkRequest request ( QUrl ( " https://www.astro.uni-bonn.de/hisurvey/euhou/LABprofile/index.php " ) ) ;
request . setRawHeader ( " Content-Type " , " application/x-www-form-urlencoded " ) ;
QUrlQuery params ;
params . addQueryItem ( " coordinates " , " lb " ) ;
params . addQueryItem ( " ral " , QString : : number ( l ) ) ;
params . addQueryItem ( " decb " , QString : : number ( b ) ) ;
params . addQueryItem ( " beam " , QString : : number ( beamWidth ) ) ;
params . addQueryItem ( " vmin " , " -100.0 " ) ;
params . addQueryItem ( " vmax " , " 100.0 " ) ;
params . addQueryItem ( " search " , " Search data " ) ;
m_networkManager - > post ( request , params . query ( QUrl : : FullyEncoded ) . toUtf8 ( ) ) ;
}
}
}
if ( data )
{
data - > toSeries ( m_fftLABSeries ) ;
spectrumAutoscale ( ) ;
}
}
void RadioAstronomyGUI : : networkManagerFinished ( QNetworkReply * reply )
{
QNetworkReply : : NetworkError replyError = reply - > error ( ) ;
if ( replyError )
{
qWarning ( ) < < " RadioAstronomyGUI::networkManagerFinished: "
< < " error( " < < ( int ) replyError
< < " ): " < < replyError
< < " : " < < reply - > errorString ( ) ;
m_downloadingLAB = false ;
}
else
{
QString answer = reply - > readAll ( ) ;
2024-06-10 14:01:57 +01:00
QRegularExpression re ( " a href= \\ \" download.php([^ \" ]*) \ " " ) ;
QRegularExpressionMatch match = re . match ( answer ) ;
if ( match . hasMatch ( ) )
2021-10-12 11:31:14 +01:00
{
2024-06-10 14:01:57 +01:00
QString filename = match . capturedTexts ( ) [ 1 ] ;
2021-10-12 11:31:14 +01:00
qDebug ( ) < < " RadioAstronomyGUI: Downloading LAB reference data: " < < filename ;
m_dlm . download ( QUrl ( " https://www.astro.uni-bonn.de/hisurvey/euhou/LABprofile/download.php " + filename ) , m_filenameLAB ) ;
}
else
{
qDebug ( ) < < " RadioAstronomyGUI::networkManagerFinished - No filename found: " < < answer ;
m_downloadingLAB = false ;
}
}
reply - > deleteLater ( ) ;
}
void RadioAstronomyGUI : : downloadFinished ( const QString & filename , bool success )
{
if ( success )
{
QFile file ( filename ) ;
if ( file . open ( QIODevice : : ReadOnly ) )
{
LABData * data = parseLAB ( & file , m_lLAB , m_bLAB ) ;
2022-09-26 12:46:52 +01:00
file . close ( ) ;
2021-10-12 11:31:14 +01:00
// Check if the data we've downloaded is for the current FFT being displayed
int index = ui - > spectrumIndex - > value ( ) ;
if ( index < m_fftMeasurements . size ( ) )
{
FFTMeasurement * fft = m_fftMeasurements [ index ] ;
if ( m_lLAB = = fft - > m_l & & m_bLAB = = fft - > m_b )
{
data - > toSeries ( m_fftLABSeries ) ;
spectrumAutoscale ( ) ;
2022-09-26 12:46:52 +01:00
m_downloadingLAB = false ;
2021-10-12 11:31:14 +01:00
}
else
{
2024-07-10 22:59:13 +02:00
// Try plotting for current FFT (as we only allow one download at a time, so may have been skipped)
2021-10-12 11:31:14 +01:00
m_downloadingLAB = false ;
plotLAB ( fft - > m_l , fft - > m_b , m_beamWidth ) ;
2022-09-26 12:46:52 +01:00
// Don't clear m_downloadingLAB after this point
2021-10-12 11:31:14 +01:00
}
}
} else {
qDebug ( ) < < " RadioAstronomyGUI::downloadFinished: Failed to open downloaded file: " < < filename ;
2022-09-26 12:46:52 +01:00
m_downloadingLAB = false ;
2021-10-12 11:31:14 +01:00
}
}
2022-09-26 12:46:52 +01:00
else
{
qDebug ( ) < < " RadioAstronomyGUI::downloadFinished: Failed to download: " < < filename ;
m_downloadingLAB = false ;
}
2021-10-12 11:31:14 +01:00
}
void RadioAstronomyGUI : : displayRunModeSettings ( )
{
bool sweep = m_settings . m_runMode = = RadioAstronomySettings : : SWEEP ;
ui - > sweep1CoordLabel - > setVisible ( sweep ) ;
ui - > sweepType - > setVisible ( sweep ) ;
ui - > sweep1StartLabel - > setVisible ( sweep ) ;
ui - > sweep1Start - > setVisible ( sweep ) ;
ui - > sweep1StopLabel - > setVisible ( sweep ) ;
ui - > sweep1Stop - > setVisible ( sweep ) ;
ui - > sweep1StepLabel - > setVisible ( sweep ) ;
ui - > sweep1Step - > setVisible ( sweep ) ;
ui - > sweep1DelayLabel - > setVisible ( sweep ) ;
ui - > sweep1Delay - > setVisible ( sweep ) ;
ui - > sweep2CoordLabel - > setVisible ( sweep ) ;
ui - > sweep2StartLabel - > setVisible ( sweep ) ;
ui - > sweep2Start - > setVisible ( sweep ) ;
ui - > sweep2StopLabel - > setVisible ( sweep ) ;
ui - > sweep2Stop - > setVisible ( sweep ) ;
ui - > sweep2StepLabel - > setVisible ( sweep ) ;
ui - > sweep2Step - > setVisible ( sweep ) ;
ui - > sweep2DelayLabel - > setVisible ( sweep ) ;
ui - > sweep2Delay - > setVisible ( sweep ) ;
ui - > sweepStatus - > setVisible ( sweep ) ;
ui - > runLayout - > activate ( ) ; // Needed otherwise height of rollup doesn't seem to be reduced
ui - > statusLayout - > activate ( ) ; // going from sweep to single/continuous
2022-04-12 16:20:45 +02:00
getRollupContents ( ) - > arrangeRollups ( ) ;
2021-10-12 11:31:14 +01:00
}
void RadioAstronomyGUI : : on_runMode_currentIndexChanged ( int index )
{
m_settings . m_runMode = ( RadioAstronomySettings : : RunMode ) index ;
2026-02-01 00:49:36 +01:00
applySettings ( QStringList ( " runMode " ) ) ;
2021-10-12 11:31:14 +01:00
displayRunModeSettings ( ) ;
}
void RadioAstronomyGUI : : on_sweepType_currentIndexChanged ( int index )
{
m_settings . m_sweepType = ( RadioAstronomySettings : : SweepType ) index ;
if ( ( index = = 0 ) | | ( index = = 2 ) )
{
ui - > sweep1CoordLabel - > setText ( " Az " ) ;
ui - > sweep2CoordLabel - > setText ( " El " ) ;
}
else if ( index = = 1 )
{
ui - > sweep1CoordLabel - > setText ( " l " ) ;
ui - > sweep2CoordLabel - > setText ( " b " ) ;
}
}
void RadioAstronomyGUI : : on_sweep1Start_valueChanged ( double value )
{
2021-10-12 12:10:12 +01:00
m_settings . m_sweep1Start = value ;
2026-02-01 00:49:36 +01:00
applySettings ( QStringList ( " sweep1Start " ) ) ;
2021-10-12 11:31:14 +01:00
}
void RadioAstronomyGUI : : on_sweep1Stop_valueChanged ( double value )
{
2021-10-12 12:10:12 +01:00
m_settings . m_sweep1Stop = value ;
2026-02-01 00:49:36 +01:00
applySettings ( QStringList ( " sweep1Stop " ) ) ;
2021-10-12 11:31:14 +01:00
}
void RadioAstronomyGUI : : on_sweep1Step_valueChanged ( double value )
{
2021-10-12 12:10:12 +01:00
m_settings . m_sweep1Step = value ;
2026-02-01 00:49:36 +01:00
applySettings ( QStringList ( " sweep1Step " ) ) ;
2021-10-12 11:31:14 +01:00
}
void RadioAstronomyGUI : : on_sweep1Delay_valueChanged ( double value )
{
2021-10-12 12:10:12 +01:00
m_settings . m_sweep1Delay = value ;
2026-02-01 00:49:36 +01:00
applySettings ( QStringList ( " sweep1Delay " ) ) ;
2021-10-12 11:31:14 +01:00
}
void RadioAstronomyGUI : : on_sweep2Start_valueChanged ( double value )
{
2021-10-12 12:10:12 +01:00
m_settings . m_sweep2Start = value ;
2026-02-01 00:49:36 +01:00
applySettings ( QStringList ( " sweep2Start " ) ) ;
2021-10-12 11:31:14 +01:00
}
void RadioAstronomyGUI : : on_sweep2Stop_valueChanged ( double value )
{
2021-10-12 12:10:12 +01:00
m_settings . m_sweep2Stop = value ;
2026-02-01 00:49:36 +01:00
applySettings ( QStringList ( " sweep2Stop " ) ) ;
2021-10-12 11:31:14 +01:00
}
void RadioAstronomyGUI : : on_sweep2Step_valueChanged ( double value )
{
2021-10-12 12:10:12 +01:00
m_settings . m_sweep2Step = value ;
2026-02-01 00:49:36 +01:00
applySettings ( QStringList ( " sweep2Step " ) ) ;
2021-10-12 11:31:14 +01:00
}
void RadioAstronomyGUI : : on_sweep2Delay_valueChanged ( double value )
{
2021-10-12 12:10:12 +01:00
m_settings . m_sweep2Delay = value ;
2026-02-01 00:49:36 +01:00
applySettings ( QStringList ( " sweep2Delay " ) ) ;
2021-10-12 11:31:14 +01:00
}
void RadioAstronomyGUI : : on_sweepStartAtTime_currentIndexChanged ( int index )
{
m_settings . m_sweepStartAtTime = ui - > sweepStartAtTime - > currentIndex ( ) = = 1 ;
ui - > sweepStartDateTime - > setVisible ( index = = 1 ) ;
2022-04-12 16:20:45 +02:00
getRollupContents ( ) - > arrangeRollups ( ) ;
2026-02-01 00:49:36 +01:00
applySettings ( QStringList ( " sweepStartAtTime " ) ) ;
2021-10-12 11:31:14 +01:00
}
void RadioAstronomyGUI : : on_sweepStartDateTime_dateTimeChanged ( const QDateTime & dateTime )
{
m_settings . m_sweepStartDateTime = dateTime ;
2026-02-01 00:49:36 +01:00
applySettings ( QStringList ( " sweepStartDateTime " ) ) ;
2021-10-12 11:31:14 +01:00
}
void RadioAstronomyGUI : : on_startStop_clicked ( bool checked )
{
if ( checked )
{
ui - > startStop - > setStyleSheet ( " QToolButton { background-color : green; } " ) ;
2026-02-01 00:49:36 +01:00
applySettings ( QStringList ( " startStop " ) ) ;
2021-10-12 11:31:14 +01:00
if ( m_settings . m_power2DLinkSweep )
{
update2DSettingsFromSweep ( ) ;
create2DImage ( ) ;
}
m_radioAstronomy - > getInputMessageQueue ( ) - > push ( RadioAstronomy : : MsgStartSweep : : create ( ) ) ;
}
else
{
m_radioAstronomy - > getInputMessageQueue ( ) - > push ( RadioAstronomy : : MsgStopSweep : : create ( ) ) ;
if ( m_settings . m_runMode ! = RadioAstronomySettings : : SWEEP ) {
ui - > startStop - > setStyleSheet ( " QToolButton { background-color : blue; } " ) ;
}
2026-02-01 00:49:36 +01:00
applySettings ( QStringList ( " startStop " ) ) ;
2021-10-12 11:31:14 +01:00
}
}
void RadioAstronomyGUI : : calcPowerChartTickCount ( int width )
{
// These values should probably be dependent on the font used
if ( m_powerXAxis ) {
if ( m_powerXAxisSameDay ) {
m_powerXAxis - > setTickCount ( width > 700 ? 10 : 5 ) ;
} else {
m_powerXAxis - > setTickCount ( width > 1200 ? 10 : 5 ) ;
}
}
}
void RadioAstronomyGUI : : calcSpectrumChartTickCount ( QValueAxis * axis , int width )
{
if ( axis ) {
axis - > setTickCount ( width > 700 ? 10 : 5 ) ;
}
}
2025-06-24 12:32:42 +01:00
void RadioAstronomyGUI : : autosave ( )
{
if ( ! m_settings . m_powerAutoSaveCSVFilename . isEmpty ( ) )
{
qDebug ( ) < < " RadioAstronomyGUI: Autosaving power data to " < < m_settings . m_powerAutoSaveCSVFilename ;
savePowerData ( m_settings . m_powerAutoSaveCSVFilename ) ;
}
if ( ! m_settings . m_spectrumAutoSaveCSVFilename . isEmpty ( ) )
{
qDebug ( ) < < " RadioAstronomyGUI: Autosaving spectrum data to " < < m_settings . m_spectrumAutoSaveCSVFilename ;
saveSpectrumData ( m_settings . m_spectrumAutoSaveCSVFilename ) ;
}
}
2021-10-12 11:31:14 +01:00
void RadioAstronomyGUI : : resizeEvent ( QResizeEvent * size )
{
int width = size - > size ( ) . width ( ) ;
calcPowerChartTickCount ( width ) ;
calcSpectrumChartTickCount ( m_fftXAxis , width ) ;
calcSpectrumChartTickCount ( m_fftDopplerAxis , width ) ;
calcSpectrumChartTickCount ( m_calXAxis , width ) ;
ChannelGUI : : resizeEvent ( size ) ;
}
2022-04-12 16:20:45 +02:00
void RadioAstronomyGUI : : makeUIConnections ( )
{
QObject : : connect ( ui - > deltaFrequency , & ValueDialZ : : changed , this , & RadioAstronomyGUI : : on_deltaFrequency_changed ) ;
QObject : : connect ( ui - > sampleRate , & ValueDialZ : : changed , this , & RadioAstronomyGUI : : on_sampleRate_changed ) ;
QObject : : connect ( ui - > rfBW , & ValueDialZ : : changed , this , & RadioAstronomyGUI : : on_rfBW_changed ) ;
QObject : : connect ( ui - > integration , & ValueDialZ : : changed , this , & RadioAstronomyGUI : : on_integration_changed ) ;
QObject : : connect ( ui - > fftSize , QOverload < int > : : of ( & QComboBox : : currentIndexChanged ) , this , & RadioAstronomyGUI : : on_fftSize_currentIndexChanged ) ;
QObject : : connect ( ui - > fftWindow , QOverload < int > : : of ( & QComboBox : : currentIndexChanged ) , this , & RadioAstronomyGUI : : on_fftWindow_currentIndexChanged ) ;
QObject : : connect ( ui - > filterFreqs , & QLineEdit : : editingFinished , this , & RadioAstronomyGUI : : on_filterFreqs_editingFinished ) ;
QObject : : connect ( ui - > starTracker , & QComboBox : : currentTextChanged , this , & RadioAstronomyGUI : : on_starTracker_currentTextChanged ) ;
QObject : : connect ( ui - > rotator , & QComboBox : : currentTextChanged , this , & RadioAstronomyGUI : : on_rotator_currentTextChanged ) ;
QObject : : connect ( ui - > showSensors , & QToolButton : : clicked , this , & RadioAstronomyGUI : : on_showSensors_clicked ) ;
QObject : : connect ( ui - > tempRXSelect , QOverload < int > : : of ( & QComboBox : : currentIndexChanged ) , this , & RadioAstronomyGUI : : on_tempRXSelect_currentIndexChanged ) ;
QObject : : connect ( ui - > tempRX , QOverload < double > : : of ( & QDoubleSpinBox : : valueChanged ) , this , & RadioAstronomyGUI : : on_tempRX_valueChanged ) ;
QObject : : connect ( ui - > tempCMB , QOverload < double > : : of ( & QDoubleSpinBox : : valueChanged ) , this , & RadioAstronomyGUI : : on_tempCMB_valueChanged ) ;
QObject : : connect ( ui - > tempGal , QOverload < double > : : of ( & QDoubleSpinBox : : valueChanged ) , this , & RadioAstronomyGUI : : on_tempGal_valueChanged ) ;
QObject : : connect ( ui - > tempSP , QOverload < double > : : of ( & QDoubleSpinBox : : valueChanged ) , this , & RadioAstronomyGUI : : on_tempSP_valueChanged ) ;
QObject : : connect ( ui - > tempAtm , QOverload < double > : : of ( & QDoubleSpinBox : : valueChanged ) , this , & RadioAstronomyGUI : : on_tempAtm_valueChanged ) ;
QObject : : connect ( ui - > tempAir , QOverload < double > : : of ( & QDoubleSpinBox : : valueChanged ) , this , & RadioAstronomyGUI : : on_tempAir_valueChanged ) ;
QObject : : connect ( ui - > zenithOpacity , QOverload < double > : : of ( & QDoubleSpinBox : : valueChanged ) , this , & RadioAstronomyGUI : : on_zenithOpacity_valueChanged ) ;
QObject : : connect ( ui - > elevation , QOverload < double > : : of ( & QDoubleSpinBox : : valueChanged ) , this , & RadioAstronomyGUI : : on_elevation_valueChanged ) ;
QObject : : connect ( ui - > tempAtmLink , & ButtonSwitch : : toggled , this , & RadioAstronomyGUI : : on_tempAtmLink_toggled ) ;
QObject : : connect ( ui - > tempAirLink , & ButtonSwitch : : toggled , this , & RadioAstronomyGUI : : on_tempAirLink_toggled ) ;
QObject : : connect ( ui - > tempGalLink , & ButtonSwitch : : toggled , this , & RadioAstronomyGUI : : on_tempGalLink_toggled ) ;
QObject : : connect ( ui - > elevationLink , & ButtonSwitch : : toggled , this , & RadioAstronomyGUI : : on_elevationLink_toggled ) ;
QObject : : connect ( ui - > gainVariation , QOverload < double > : : of ( & QDoubleSpinBox : : valueChanged ) , this , & RadioAstronomyGUI : : on_gainVariation_valueChanged ) ;
QObject : : connect ( ui - > omegaAUnits , QOverload < int > : : of ( & QComboBox : : currentIndexChanged ) , this , & RadioAstronomyGUI : : on_omegaAUnits_currentIndexChanged ) ;
QObject : : connect ( ui - > sourceType , QOverload < int > : : of ( & QComboBox : : currentIndexChanged ) , this , & RadioAstronomyGUI : : on_sourceType_currentIndexChanged ) ;
QObject : : connect ( ui - > omegaS , QOverload < double > : : of ( & QDoubleSpinBox : : valueChanged ) , this , & RadioAstronomyGUI : : on_omegaS_valueChanged ) ;
QObject : : connect ( ui - > omegaSUnits , QOverload < int > : : of ( & QComboBox : : currentIndexChanged ) , this , & RadioAstronomyGUI : : on_omegaSUnits_currentIndexChanged ) ;
QObject : : connect ( ui - > spectrumChartSelect , QOverload < int > : : of ( & QComboBox : : currentIndexChanged ) , this , & RadioAstronomyGUI : : on_spectrumChartSelect_currentIndexChanged ) ;
QObject : : connect ( ui - > showCalSettings , & QToolButton : : clicked , this , & RadioAstronomyGUI : : on_showCalSettings_clicked ) ;
QObject : : connect ( ui - > startCalHot , & QToolButton : : clicked , this , & RadioAstronomyGUI : : on_startCalHot_clicked ) ;
QObject : : connect ( ui - > startCalCold , & QToolButton : : clicked , this , & RadioAstronomyGUI : : on_startCalCold_clicked ) ;
QObject : : connect ( ui - > recalibrate , & ButtonSwitch : : toggled , this , & RadioAstronomyGUI : : on_recalibrate_toggled ) ;
QObject : : connect ( ui - > spectrumShowLegend , & ButtonSwitch : : toggled , this , & RadioAstronomyGUI : : on_spectrumShowLegend_toggled ) ;
QObject : : connect ( ui - > spectrumShowRefLine , & ButtonSwitch : : toggled , this , & RadioAstronomyGUI : : on_spectrumShowRefLine_toggled ) ;
QObject : : connect ( ui - > spectrumTemp , & ButtonSwitch : : toggled , this , & RadioAstronomyGUI : : on_spectrumTemp_toggled ) ;
QObject : : connect ( ui - > spectrumMarker , & ButtonSwitch : : toggled , this , & RadioAstronomyGUI : : on_spectrumMarker_toggled ) ;
QObject : : connect ( ui - > spectrumPeak , & ButtonSwitch : : toggled , this , & RadioAstronomyGUI : : on_spectrumPeak_toggled ) ;
QObject : : connect ( ui - > spectrumReverseXAxis , & ButtonSwitch : : toggled , this , & RadioAstronomyGUI : : on_spectrumReverseXAxis_toggled ) ;
2025-06-24 12:32:42 +01:00
QObject : : connect ( ui - > savePowerData , & ButtonSwitch : : clicked , this , & RadioAstronomyGUI : : on_savePowerData_clicked ) ;
2022-04-12 16:20:45 +02:00
QObject : : connect ( ui - > savePowerChartImage , & QToolButton : : clicked , this , & RadioAstronomyGUI : : on_savePowerChartImage_clicked ) ;
2025-06-24 12:32:42 +01:00
QObject : : connect ( ui - > saveSpectrumData , & ButtonSwitch : : clicked , this , & RadioAstronomyGUI : : on_saveSpectrumData_clicked ) ;
2022-04-12 16:20:45 +02:00
QObject : : connect ( ui - > loadSpectrumData , & QToolButton : : clicked , this , & RadioAstronomyGUI : : on_loadSpectrumData_clicked ) ;
QObject : : connect ( ui - > saveSpectrumChartImage , & QToolButton : : clicked , this , & RadioAstronomyGUI : : on_saveSpectrumChartImage_clicked ) ;
QObject : : connect ( ui - > saveSpectrumChartImages , & QToolButton : : clicked , this , & RadioAstronomyGUI : : on_saveSpectrumChartImages_clicked ) ;
QObject : : connect ( ui - > clearData , & QToolButton : : clicked , this , & RadioAstronomyGUI : : on_clearData_clicked ) ;
QObject : : connect ( ui - > clearCal , & QToolButton : : clicked , this , & RadioAstronomyGUI : : on_clearCal_clicked ) ;
QObject : : connect ( ui - > spectrumAutoscale , & QToolButton : : toggled , this , & RadioAstronomyGUI : : on_spectrumAutoscale_toggled ) ;
QObject : : connect ( ui - > spectrumAutoscaleX , & QToolButton : : clicked , this , & RadioAstronomyGUI : : on_spectrumAutoscaleX_clicked ) ;
QObject : : connect ( ui - > spectrumAutoscaleY , & QToolButton : : clicked , this , & RadioAstronomyGUI : : on_spectrumAutoscaleY_clicked ) ;
QObject : : connect ( ui - > spectrumReference , QOverload < double > : : of ( & QDoubleSpinBox : : valueChanged ) , this , & RadioAstronomyGUI : : on_spectrumReference_valueChanged ) ;
QObject : : connect ( ui - > spectrumRange , QOverload < double > : : of ( & QDoubleSpinBox : : valueChanged ) , this , & RadioAstronomyGUI : : on_spectrumRange_valueChanged ) ;
QObject : : connect ( ui - > spectrumCenterFreq , QOverload < double > : : of ( & QDoubleSpinBox : : valueChanged ) , this , & RadioAstronomyGUI : : on_spectrumCenterFreq_valueChanged ) ;
QObject : : connect ( ui - > spectrumSpan , QOverload < double > : : of ( & QDoubleSpinBox : : valueChanged ) , this , & RadioAstronomyGUI : : on_spectrumSpan_valueChanged ) ;
QObject : : connect ( ui - > spectrumYUnits , QOverload < int > : : of ( & QComboBox : : currentIndexChanged ) , this , & RadioAstronomyGUI : : on_spectrumYUnits_currentIndexChanged ) ;
QObject : : connect ( ui - > spectrumBaseline , QOverload < int > : : of ( & QComboBox : : currentIndexChanged ) , this , & RadioAstronomyGUI : : on_spectrumBaseline_currentIndexChanged ) ;
QObject : : connect ( ui - > spectrumIndex , & QSlider : : valueChanged , this , & RadioAstronomyGUI : : on_spectrumIndex_valueChanged ) ;
QObject : : connect ( ui - > spectrumLine , QOverload < int > : : of ( & QComboBox : : currentIndexChanged ) , this , & RadioAstronomyGUI : : on_spectrumLine_currentIndexChanged ) ;
QObject : : connect ( ui - > spectrumLineFrequency , QOverload < double > : : of ( & QDoubleSpinBox : : valueChanged ) , this , & RadioAstronomyGUI : : on_spectrumLineFrequency_valueChanged ) ;
QObject : : connect ( ui - > refFrame , QOverload < int > : : of ( & QComboBox : : currentIndexChanged ) , this , & RadioAstronomyGUI : : on_refFrame_currentIndexChanged ) ;
QObject : : connect ( ui - > sunDistanceToGC , QOverload < double > : : of ( & QDoubleSpinBox : : valueChanged ) , this , & RadioAstronomyGUI : : on_sunDistanceToGC_valueChanged ) ;
QObject : : connect ( ui - > sunOrbitalVelocity , QOverload < double > : : of ( & QDoubleSpinBox : : valueChanged ) , this , & RadioAstronomyGUI : : on_sunOrbitalVelocity_valueChanged ) ;
QObject : : connect ( ui - > spectrumGaussianFreq , QOverload < double > : : of ( & QDoubleSpinBox : : valueChanged ) , this , & RadioAstronomyGUI : : on_spectrumGaussianFreq_valueChanged ) ;
QObject : : connect ( ui - > spectrumGaussianAmp , QOverload < double > : : of ( & QDoubleSpinBox : : valueChanged ) , this , & RadioAstronomyGUI : : on_spectrumGaussianAmp_valueChanged ) ;
QObject : : connect ( ui - > spectrumGaussianFloor , QOverload < double > : : of ( & QDoubleSpinBox : : valueChanged ) , this , & RadioAstronomyGUI : : on_spectrumGaussianFloor_valueChanged ) ;
QObject : : connect ( ui - > spectrumGaussianFWHM , QOverload < double > : : of ( & QDoubleSpinBox : : valueChanged ) , this , & RadioAstronomyGUI : : on_spectrumGaussianFWHM_valueChanged ) ;
QObject : : connect ( ui - > spectrumGaussianTurb , QOverload < double > : : of ( & QDoubleSpinBox : : valueChanged ) , this , & RadioAstronomyGUI : : on_spectrumGaussianTurb_valueChanged ) ;
QObject : : connect ( ui - > spectrumTemperature , QOverload < double > : : of ( & QDoubleSpinBox : : valueChanged ) , this , & RadioAstronomyGUI : : on_spectrumTemperature_valueChanged ) ;
QObject : : connect ( ui - > spectrumShowLAB , & ButtonSwitch : : toggled , this , & RadioAstronomyGUI : : on_spectrumShowLAB_toggled ) ;
QObject : : connect ( ui - > spectrumShowDistance , & ButtonSwitch : : toggled , this , & RadioAstronomyGUI : : on_spectrumShowDistance_toggled ) ;
QObject : : connect ( ui - > tCalHotSelect , QOverload < int > : : of ( & QComboBox : : currentIndexChanged ) , this , & RadioAstronomyGUI : : on_tCalHotSelect_currentIndexChanged ) ;
QObject : : connect ( ui - > tCalHot , QOverload < double > : : of ( & QDoubleSpinBox : : valueChanged ) , this , & RadioAstronomyGUI : : on_tCalHot_valueChanged ) ;
QObject : : connect ( ui - > tCalColdSelect , QOverload < int > : : of ( & QComboBox : : currentIndexChanged ) , this , & RadioAstronomyGUI : : on_tCalColdSelect_currentIndexChanged ) ;
QObject : : connect ( ui - > tCalCold , QOverload < double > : : of ( & QDoubleSpinBox : : valueChanged ) , this , & RadioAstronomyGUI : : on_tCalCold_valueChanged ) ;
QObject : : connect ( ui - > powerChartSelect , QOverload < int > : : of ( & QComboBox : : currentIndexChanged ) , this , & RadioAstronomyGUI : : on_powerChartSelect_currentIndexChanged ) ;
QObject : : connect ( ui - > powerYUnits , QOverload < int > : : of ( & QComboBox : : currentIndexChanged ) , this , & RadioAstronomyGUI : : on_powerYUnits_currentIndexChanged ) ;
QObject : : connect ( ui - > powerShowMarker , & ButtonSwitch : : toggled , this , & RadioAstronomyGUI : : on_powerShowMarker_toggled ) ;
QObject : : connect ( ui - > powerShowAirTemp , & ButtonSwitch : : toggled , this , & RadioAstronomyGUI : : on_powerShowAirTemp_toggled ) ;
QObject : : connect ( ui - > powerShowPeak , & ButtonSwitch : : toggled , this , & RadioAstronomyGUI : : on_powerShowPeak_toggled ) ;
QObject : : connect ( ui - > powerShowAvg , & ButtonSwitch : : toggled , this , & RadioAstronomyGUI : : on_powerShowAvg_toggled ) ;
QObject : : connect ( ui - > powerShowLegend , & ButtonSwitch : : toggled , this , & RadioAstronomyGUI : : on_powerShowLegend_toggled ) ;
QObject : : connect ( ui - > powerAutoscale , & QToolButton : : toggled , this , & RadioAstronomyGUI : : on_powerAutoscale_toggled ) ;
QObject : : connect ( ui - > powerAutoscaleY , & QToolButton : : clicked , this , & RadioAstronomyGUI : : on_powerAutoscaleY_clicked ) ;
QObject : : connect ( ui - > powerAutoscaleX , & QToolButton : : clicked , this , & RadioAstronomyGUI : : on_powerAutoscaleX_clicked ) ;
QObject : : connect ( ui - > powerReference , QOverload < double > : : of ( & QDoubleSpinBox : : valueChanged ) , this , & RadioAstronomyGUI : : on_powerReference_valueChanged ) ;
QObject : : connect ( ui - > powerRange , QOverload < double > : : of ( & QDoubleSpinBox : : valueChanged ) , this , & RadioAstronomyGUI : : on_powerRange_valueChanged ) ;
QObject : : connect ( ui - > powerStartTime , & WrappingDateTimeEdit : : dateTimeChanged , this , & RadioAstronomyGUI : : on_powerStartTime_dateTimeChanged ) ;
QObject : : connect ( ui - > powerEndTime , & WrappingDateTimeEdit : : dateTimeChanged , this , & RadioAstronomyGUI : : on_powerEndTime_dateTimeChanged ) ;
QObject : : connect ( ui - > powerShowGaussian , & ButtonSwitch : : clicked , this , & RadioAstronomyGUI : : on_powerShowGaussian_clicked ) ;
QObject : : connect ( ui - > powerGaussianCenter , & WrappingDateTimeEdit : : dateTimeChanged , this , & RadioAstronomyGUI : : on_powerGaussianCenter_dateTimeChanged ) ;
QObject : : connect ( ui - > powerGaussianAmp , QOverload < double > : : of ( & QDoubleSpinBox : : valueChanged ) , this , & RadioAstronomyGUI : : on_powerGaussianAmp_valueChanged ) ;
QObject : : connect ( ui - > powerGaussianFloor , QOverload < double > : : of ( & QDoubleSpinBox : : valueChanged ) , this , & RadioAstronomyGUI : : on_powerGaussianFloor_valueChanged ) ;
QObject : : connect ( ui - > powerGaussianFWHM , QOverload < double > : : of ( & QDoubleSpinBox : : valueChanged ) , this , & RadioAstronomyGUI : : on_powerGaussianFWHM_valueChanged ) ;
QObject : : connect ( ui - > powerGaussianHPBW , QOverload < double > : : of ( & QDoubleSpinBox : : valueChanged ) , this , & RadioAstronomyGUI : : on_powerGaussianHPBW_valueChanged ) ;
QObject : : connect ( ui - > runMode , QOverload < int > : : of ( & QComboBox : : currentIndexChanged ) , this , & RadioAstronomyGUI : : on_runMode_currentIndexChanged ) ;
QObject : : connect ( ui - > sweepType , QOverload < int > : : of ( & QComboBox : : currentIndexChanged ) , this , & RadioAstronomyGUI : : on_sweepType_currentIndexChanged ) ;
2023-03-30 16:50:01 +01:00
QObject : : connect ( ui - > sweep1Start , QOverload < double > : : of ( & QDoubleSpinBox : : valueChanged ) , this , & RadioAstronomyGUI : : on_sweep1Start_valueChanged ) ;
QObject : : connect ( ui - > sweep1Stop , QOverload < double > : : of ( & QDoubleSpinBox : : valueChanged ) , this , & RadioAstronomyGUI : : on_sweep1Stop_valueChanged ) ;
QObject : : connect ( ui - > sweep1Step , QOverload < double > : : of ( & QDoubleSpinBox : : valueChanged ) , this , & RadioAstronomyGUI : : on_sweep1Step_valueChanged ) ;
QObject : : connect ( ui - > sweep1Delay , QOverload < double > : : of ( & QDoubleSpinBox : : valueChanged ) , this , & RadioAstronomyGUI : : on_sweep1Delay_valueChanged ) ;
QObject : : connect ( ui - > sweep2Start , QOverload < double > : : of ( & QDoubleSpinBox : : valueChanged ) , this , & RadioAstronomyGUI : : on_sweep2Start_valueChanged ) ;
QObject : : connect ( ui - > sweep2Stop , QOverload < double > : : of ( & QDoubleSpinBox : : valueChanged ) , this , & RadioAstronomyGUI : : on_sweep2Stop_valueChanged ) ;
QObject : : connect ( ui - > sweep2Step , QOverload < double > : : of ( & QDoubleSpinBox : : valueChanged ) , this , & RadioAstronomyGUI : : on_sweep2Step_valueChanged ) ;
QObject : : connect ( ui - > sweep2Delay , QOverload < double > : : of ( & QDoubleSpinBox : : valueChanged ) , this , & RadioAstronomyGUI : : on_sweep2Delay_valueChanged ) ;
2022-04-12 16:20:45 +02:00
QObject : : connect ( ui - > sweepStartAtTime , QOverload < int > : : of ( & QComboBox : : currentIndexChanged ) , this , & RadioAstronomyGUI : : on_sweepStartAtTime_currentIndexChanged ) ;
QObject : : connect ( ui - > sweepStartDateTime , & QDateTimeEdit : : dateTimeChanged , this , & RadioAstronomyGUI : : on_sweepStartDateTime_dateTimeChanged ) ;
2023-03-30 16:50:01 +01:00
QObject : : connect ( ui - > startStop , & ButtonSwitch : : clicked , this , & RadioAstronomyGUI : : on_startStop_clicked ) ;
QObject : : connect ( ui - > power2DAutoscale , & QToolButton : : clicked , this , & RadioAstronomyGUI : : on_power2DAutoscale_clicked ) ;
QObject : : connect ( ui - > power2DLinkSweep , & ButtonSwitch : : clicked , this , & RadioAstronomyGUI : : on_power2DLinkSweep_toggled ) ;
QObject : : connect ( ui - > power2DSweepType , QOverload < int > : : of ( & QComboBox : : currentIndexChanged ) , this , & RadioAstronomyGUI : : on_power2DSweepType_currentIndexChanged ) ;
QObject : : connect ( ui - > power2DWidth , QOverload < int > : : of ( & QSpinBox : : valueChanged ) , this , & RadioAstronomyGUI : : on_power2DWidth_valueChanged ) ;
QObject : : connect ( ui - > power2DHeight , QOverload < int > : : of ( & QSpinBox : : valueChanged ) , this , & RadioAstronomyGUI : : on_power2DHeight_valueChanged ) ;
QObject : : connect ( ui - > power2DXMin , QOverload < double > : : of ( & QDoubleSpinBox : : valueChanged ) , this , & RadioAstronomyGUI : : on_power2DXMin_valueChanged ) ;
QObject : : connect ( ui - > power2DXMax , QOverload < double > : : of ( & QDoubleSpinBox : : valueChanged ) , this , & RadioAstronomyGUI : : on_power2DXMax_valueChanged ) ;
QObject : : connect ( ui - > power2DYMin , QOverload < double > : : of ( & QDoubleSpinBox : : valueChanged ) , this , & RadioAstronomyGUI : : on_power2DYMin_valueChanged ) ;
QObject : : connect ( ui - > power2DYMax , QOverload < double > : : of ( & QDoubleSpinBox : : valueChanged ) , this , & RadioAstronomyGUI : : on_power2DYMax_valueChanged ) ;
QObject : : connect ( ui - > powerShowSensor1 , & ButtonSwitch : : toggled , this , & RadioAstronomyGUI : : on_powerShowSensor1_toggled ) ;
QObject : : connect ( ui - > powerShowSensor2 , & ButtonSwitch : : toggled , this , & RadioAstronomyGUI : : on_powerShowSensor1_toggled ) ;
QObject : : connect ( ui - > powerShowFiltered , & ButtonSwitch : : clicked , this , & RadioAstronomyGUI : : on_powerShowFiltered_clicked ) ;
QObject : : connect ( ui - > powerFilter , QOverload < int > : : of ( & QComboBox : : currentIndexChanged ) , this , & RadioAstronomyGUI : : on_powerFilter_currentIndexChanged ) ;
QObject : : connect ( ui - > powerFilterN , QOverload < int > : : of ( & QSpinBox : : valueChanged ) , this , & RadioAstronomyGUI : : on_powerFilterN_valueChanged ) ;
QObject : : connect ( ui - > powerShowMeasurement , & ButtonSwitch : : clicked , this , & RadioAstronomyGUI : : on_powerShowMeasurement_clicked ) ;
2022-04-12 16:20:45 +02:00
QObject : : connect ( ui - > powerColourAutoscale , & QToolButton : : toggled , this , & RadioAstronomyGUI : : on_powerColourAutoscale_toggled ) ;
QObject : : connect ( ui - > powerColourScaleMin , QOverload < double > : : of ( & QDoubleSpinBox : : valueChanged ) , this , & RadioAstronomyGUI : : on_powerColourScaleMin_valueChanged ) ;
QObject : : connect ( ui - > powerColourScaleMax , QOverload < double > : : of ( & QDoubleSpinBox : : valueChanged ) , this , & RadioAstronomyGUI : : on_powerColourScaleMax_valueChanged ) ;
QObject : : connect ( ui - > powerColourPalette , QOverload < int > : : of ( & QComboBox : : currentIndexChanged ) , this , & RadioAstronomyGUI : : on_powerColourPalette_currentIndexChanged ) ;
QObject : : connect ( ui - > powerTable , & QTableWidget : : cellDoubleClicked , this , & RadioAstronomyGUI : : on_powerTable_cellDoubleClicked ) ;
}
2022-04-13 11:08:21 +02:00
void RadioAstronomyGUI : : updateAbsoluteCenterFrequency ( )
{
2023-03-29 19:20:05 +01:00
setStatusFrequency ( m_centerFrequency + m_settings . m_inputFrequencyOffset ) ;
2022-04-13 11:08:21 +02:00
}