481a55264be21d601c0354bff1c4489e2372c84f
[debian/gnuradio] / gr-qtgui / src / lib / spectrumdisplayform.cc
1 #include <cmath>
2 #include <QColorDialog>
3 #include <QMessageBox>
4 #include <spectrumdisplayform.h>
5
6 int SpectrumDisplayForm::_openGLWaterfall3DFlag = -1;
7
8 SpectrumDisplayForm::SpectrumDisplayForm(QWidget* parent) : QDialog(parent){
9   setupUi(this);
10   
11   _systemSpecifiedFlag = false;
12   _intValidator = new QIntValidator(this);
13   _intValidator->setBottom(0);
14   _frequencyDisplayPlot = new FrequencyDisplayPlot(Tab1PlotDisplayFrame);
15   _waterfallDisplayPlot = new WaterfallDisplayPlot(Tab2PlotDisplayFrame);
16   _waterfall3DDisplayPlot = new Waterfall3DDisplayPlot(Waterfall3DPlotDisplayFrame);
17   _timeDomainDisplayPlot = new TimeDomainDisplayPlot(TimeDomainDisplayFrame);
18   _numRealDataPoints = 1024;
19   _realFFTDataPoints = new double[_numRealDataPoints];
20   _averagedValues = new double[_numRealDataPoints];
21   _historyVector = new std::vector<double*>;
22   
23   AvgLineEdit->setValidator(_intValidator);
24   PowerLineEdit->setValidator(_intValidator);
25   MinHoldCheckBox_toggled( false );
26   MaxHoldCheckBox_toggled( false );
27   
28   WaterfallMaximumIntensityWheel->setRange(-200, 0);
29   WaterfallMaximumIntensityWheel->setTickCnt(50);
30   WaterfallMinimumIntensityWheel->setRange(-200, 0);
31   WaterfallMinimumIntensityWheel->setTickCnt(50);
32   WaterfallMinimumIntensityWheel->setValue(-200);
33   
34   Waterfall3DMaximumIntensityWheel->setRange(-200, 0);
35   Waterfall3DMaximumIntensityWheel->setTickCnt(50);
36   Waterfall3DMinimumIntensityWheel->setRange(-200, 0);
37   Waterfall3DMinimumIntensityWheel->setTickCnt(50);
38   Waterfall3DMinimumIntensityWheel->setValue(-200);
39   
40   _peakFrequency = 0;
41   _peakAmplitude = -HUGE_VAL;
42   
43   _noiseFloorAmplitude = -HUGE_VAL;
44   
45   connect(_waterfallDisplayPlot, SIGNAL(UpdatedLowerIntensityLevel(const double)), _frequencyDisplayPlot, SLOT(SetLowerIntensityLevel(const double)));
46   connect(_waterfallDisplayPlot, SIGNAL(UpdatedUpperIntensityLevel(const double)), _frequencyDisplayPlot, SLOT(SetUpperIntensityLevel(const double)));
47   
48   _frequencyDisplayPlot->SetLowerIntensityLevel(-200);
49   _frequencyDisplayPlot->SetUpperIntensityLevel(-200);
50   
51   // Load up the acceptable FFT sizes...
52   FFTSizeComboBox->clear();
53   for(long fftSize = SpectrumGUIClass::MIN_FFT_SIZE; fftSize <= SpectrumGUIClass::MAX_FFT_SIZE; fftSize *= 2){
54     FFTSizeComboBox->insertItem(FFTSizeComboBox->count(), QString("%1").arg(fftSize));
55   }
56   Reset();
57 }
58
59 SpectrumDisplayForm::~SpectrumDisplayForm(){
60   // Qt deletes children when parent is deleted
61
62   // Don't worry about deleting Display Plots - they are deleted when parents are deleted
63   /*   delete _intValidator; */
64
65   delete[] _realFFTDataPoints;
66   delete[] _averagedValues;
67
68   for(unsigned int count = 0; count < _historyVector->size(); count++){
69     delete[] _historyVector->operator[](count);
70   }
71
72   delete _historyVector;
73 }
74
75 void SpectrumDisplayForm::setSystem( SpectrumGUIClass * newSystem, const uint64_t numFFTDataPoints, const uint64_t numTimeDomainDataPoints )
76 {
77   ResizeBuffers(numFFTDataPoints, numTimeDomainDataPoints);
78   
79   if(newSystem != NULL){
80     _system = newSystem;
81     _systemSpecifiedFlag = true;
82   }
83   else{
84     _systemSpecifiedFlag = false;
85   }
86 }
87
88 void SpectrumDisplayForm::newFrequencyData( const SpectrumUpdateEvent* spectrumUpdateEvent)
89 {
90   const std::complex<float>* complexDataPoints = spectrumUpdateEvent->getFFTPoints();
91   const uint64_t numFFTDataPoints = spectrumUpdateEvent->getNumFFTDataPoints();
92   const double* realTimeDomainDataPoints = spectrumUpdateEvent->getRealTimeDomainPoints();
93   const double* imagTimeDomainDataPoints = spectrumUpdateEvent->getImagTimeDomainPoints();
94   const uint64_t numTimeDomainDataPoints = spectrumUpdateEvent->getNumTimeDomainDataPoints();
95   const double timePerFFT = spectrumUpdateEvent->getTimePerFFT();
96   const timespec dataTimestamp = spectrumUpdateEvent->getDataTimestamp();;
97   const bool repeatDataFlag = spectrumUpdateEvent->getRepeatDataFlag();
98   const bool lastOfMultipleUpdatesFlag = spectrumUpdateEvent->getLastOfMultipleUpdateFlag();
99   const timespec generatedTimestamp = spectrumUpdateEvent->getEventGeneratedTimestamp();
100
101   // REMEMBER: The dataTimestamp is NOT valid when the repeat data flag is true...
102   ResizeBuffers(numFFTDataPoints, numTimeDomainDataPoints);
103
104   // Calculate the Magnitude of the complex point
105   const std::complex<float>* complexDataPointsPtr = complexDataPoints;
106   double* realFFTDataPointsPtr = _realFFTDataPoints;
107   for(uint64_t point = 0; point < numFFTDataPoints; point++){
108     // Calculate dBm
109     // 50 ohm load assumption
110     // 10 * log10 (v^2 / (2 * 50.0 * .001)) = 10 * log10( v^2 * 10)
111     // 75 ohm load assumption
112     // 10 * log10 (v^2 / (2 * 75.0 * .001)) = 10 * log10( v^2 * 15)
113     
114     *realFFTDataPointsPtr = 10.0*log10((((*complexDataPointsPtr).real() * (*complexDataPointsPtr).real()) + ((*complexDataPointsPtr).imag()*(*complexDataPointsPtr).imag())) + 1e-20);
115
116     complexDataPointsPtr++;
117     realFFTDataPointsPtr++;
118   }
119  
120
121   // Don't update the averaging history if this is repeated data
122   if(!repeatDataFlag){
123     _AverageHistory(_realFFTDataPoints);
124
125     double sumMean;
126     const double fft_bin_size = (_stopFrequency-_startFrequency) / static_cast<double>(numFFTDataPoints);
127
128     // find the peak, sum (for mean), etc
129     _peakAmplitude = -HUGE_VAL;
130     sumMean = 0.0;
131     for(uint64_t number = 0; number < numFFTDataPoints; number++){
132       // find peak
133       if(_realFFTDataPoints[number] > _peakAmplitude){
134         _peakFrequency = (static_cast<float>(number) * fft_bin_size);  // Calculate the frequency relative to the local bw, adjust for _startFrequency later
135         _peakAmplitude = _realFFTDataPoints[number];
136         // _peakBin = number;
137       }
138       // sum (for mean)
139       sumMean += _realFFTDataPoints[number];
140     }
141
142     // calculate the spectral mean
143     // +20 because for the comparison below we only want to throw out bins
144     // that are significantly higher (and would, thus, affect the mean more)
145     const double meanAmplitude = (sumMean / numFFTDataPoints) + 20.0;
146
147     // now throw out any bins higher than the mean
148     sumMean = 0.0;
149     uint64_t newNumDataPoints = numFFTDataPoints;
150     for(uint64_t number = 0; number < numFFTDataPoints; number++){
151       if (_realFFTDataPoints[number] <= meanAmplitude)
152         sumMean += _realFFTDataPoints[number];
153       else
154         newNumDataPoints--;
155     }
156
157     if (newNumDataPoints == 0)             // in the odd case that all
158       _noiseFloorAmplitude = meanAmplitude; // amplitudes are equal!
159     else
160       _noiseFloorAmplitude = sumMean / newNumDataPoints;
161   }
162
163   if(lastOfMultipleUpdatesFlag){
164     _frequencyDisplayPlot->PlotNewData(_averagedValues, numFFTDataPoints, _noiseFloorAmplitude, _peakFrequency, _peakAmplitude);
165     _timeDomainDisplayPlot->PlotNewData(realTimeDomainDataPoints, imagTimeDomainDataPoints, numTimeDomainDataPoints);
166   }
167   // Don't update the repeated data for the waterfall
168   if(!repeatDataFlag){
169     _waterfallDisplayPlot->PlotNewData(_realFFTDataPoints, numFFTDataPoints, timePerFFT, dataTimestamp, spectrumUpdateEvent->getDroppedFFTFrames());
170     if( _openGLWaterfall3DFlag == 1 ){
171       _waterfall3DDisplayPlot->PlotNewData(_realFFTDataPoints, numFFTDataPoints, timePerFFT, dataTimestamp, spectrumUpdateEvent->getDroppedFFTFrames());
172     }
173   }
174   
175   // Tell the system the GUI has been updated
176   if(_systemSpecifiedFlag){
177     _system->SetLastGUIUpdateTime(generatedTimestamp);
178     _system->DecrementPendingGUIUpdateEvents();
179   }
180 }
181
182 void SpectrumDisplayForm::resizeEvent( QResizeEvent *e )
183 {
184   // Let the actual window resize its width, but not its height
185   QSize newSize(e->size().width(), e->oldSize().height());
186   QResizeEvent et(newSize, e->oldSize());
187   QWidget::resizeEvent(&et);
188
189   // Tell the Tab Window to Resize
190   SpectrumTypeTab->resize( e->size().width(), SpectrumTypeTab->height());
191
192   // Tell the TabXFreqDisplay to resize
193   Tab1PlotDisplayFrame->resize(e->size().width()-4, Tab1PlotDisplayFrame->height());
194   Tab2PlotDisplayFrame->resize(e->size().width()-4, Tab2PlotDisplayFrame->height());
195   Waterfall3DPlotDisplayFrame->resize(e->size().width()-4, Waterfall3DPlotDisplayFrame->height());
196   TimeDomainDisplayFrame->resize(e->size().width()-4, TimeDomainDisplayFrame->height());
197   _frequencyDisplayPlot->resize( Tab1PlotDisplayFrame->width()-4, Tab1PlotDisplayFrame->height());
198   _waterfallDisplayPlot->resize( Tab2PlotDisplayFrame->width()-4, Tab2PlotDisplayFrame->height());
199   _waterfall3DDisplayPlot->resize( Waterfall3DPlotDisplayFrame->width()-4, Waterfall3DPlotDisplayFrame->height());
200   _timeDomainDisplayPlot->resize( TimeDomainDisplayFrame->width()-4, TimeDomainDisplayFrame->height());
201
202   // Move the IntensityWheels and Labels
203   WaterfallMaximumIntensityLabel->move(width() - 5 - WaterfallMaximumIntensityLabel->width(), WaterfallMaximumIntensityLabel->y());
204   WaterfallMinimumIntensityLabel->move(width() - 5 - WaterfallMinimumIntensityLabel->width(), WaterfallMinimumIntensityLabel->y());
205   WaterfallMaximumIntensityWheel->resize(WaterfallMaximumIntensityLabel->x() - 5 - WaterfallMaximumIntensityWheel->x(), WaterfallMaximumIntensityWheel->height());
206   WaterfallMinimumIntensityWheel->resize(WaterfallMinimumIntensityLabel->x() - 5 - WaterfallMinimumIntensityWheel->x(), WaterfallMinimumIntensityWheel->height());
207
208   Waterfall3DMaximumIntensityLabel->move(width() - 5 - Waterfall3DMaximumIntensityLabel->width(), Waterfall3DMaximumIntensityLabel->y());
209   Waterfall3DMinimumIntensityLabel->move(width() - 5 - Waterfall3DMinimumIntensityLabel->width(), Waterfall3DMinimumIntensityLabel->y());
210   Waterfall3DMaximumIntensityWheel->resize(Waterfall3DMaximumIntensityLabel->x() - 5 - Waterfall3DMaximumIntensityWheel->x(), Waterfall3DMaximumIntensityWheel->height());
211   Waterfall3DMinimumIntensityWheel->resize(Waterfall3DMinimumIntensityLabel->x() - 5 - Waterfall3DMinimumIntensityWheel->x(), Waterfall3DMinimumIntensityWheel->height());
212
213
214   // Move the Power Lbl
215   PowerLabel->move(e->size().width()-(415-324) - PowerLabel->width(), PowerLabel->y());
216
217   // Move the Power Line Edit
218   PowerLineEdit->move(e->size().width()-(415-318) - PowerLineEdit->width(), PowerLineEdit->y());
219
220   // Move the Avg Lbl
221   AvgLabel->move(e->size().width()-(415-406) - AvgLabel->width(), AvgLabel->y());
222
223   // Move the Avg Line Edit
224   AvgLineEdit->move(e->size().width()-(415-400) - AvgLineEdit->width(), AvgLineEdit->y());
225   
226   // Move the FFT Size Combobox and label
227   FFTSizeComboBox->move(width() - 5 - FFTSizeComboBox->width(), FFTSizeComboBox->y());
228   FFTSizeLabel->move(width() - 10 - FFTSizeComboBox->width() - FFTSizeLabel->width(), FFTSizeLabel->y());
229 }
230
231
232 void SpectrumDisplayForm::customEvent( QEvent * e)
233 {
234   if(e->type() == QEvent::User+3){
235     if(_systemSpecifiedFlag){
236       WindowComboBox->setCurrentIndex(_system->GetWindowType());
237       FFTSizeComboBox->setCurrentIndex(_system->GetFFTSizeIndex());
238       //FFTSizeComboBox->setCurrentIndex(1);
239       PowerLineEdit_textChanged(PowerLineEdit->text());
240     }
241
242     waterfallMinimumIntensityChangedCB(WaterfallMinimumIntensityWheel->value());
243     waterfallMaximumIntensityChangedCB(WaterfallMaximumIntensityWheel->value());
244
245     waterfall3DMinimumIntensityChangedCB(Waterfall3DMinimumIntensityWheel->value());
246     waterfall3DMaximumIntensityChangedCB(Waterfall3DMaximumIntensityWheel->value());
247
248     // If the video card doesn't support OpenGL then don't display the 3D Waterfall
249     if(QGLFormat::hasOpenGL()){
250       // Check for Hardware Acceleration of the OpenGL
251       if(!_waterfall3DDisplayPlot->format().directRendering()){
252         // Only ask this once while the program is running...
253         if(_openGLWaterfall3DFlag == -1){
254           _openGLWaterfall3DFlag = 0;
255           if(QMessageBox::warning(this, "OpenGL Direct Rendering NOT Supported", "<center>The system's video card hardware or current drivers do not support direct hardware rendering of the OpenGL modules.</center><br><center>Software rendering is VERY processor intensive.</center><br><center>Do you want to use software rendering?</center>", QMessageBox::Yes, QMessageBox::No | QMessageBox::Default | QMessageBox::Escape) == QMessageBox::Yes){
256             _openGLWaterfall3DFlag = 1;
257           }
258         }
259       }
260       else{
261         _openGLWaterfall3DFlag = 1;
262       }
263     }
264
265     if(_openGLWaterfall3DFlag != 1){
266       SpectrumTypeTab->removeTab(SpectrumTypeTab->indexOf(Waterfall3DPage));
267     }
268
269     // Clear any previous display
270     Reset();
271
272     show();
273   }
274   else if(e->type() == 10005){
275     SpectrumUpdateEvent* spectrumUpdateEvent = (SpectrumUpdateEvent*)e;
276     newFrequencyData(spectrumUpdateEvent);
277   }
278   else if(e->type() == 10008){
279     setWindowTitle(((SpectrumWindowCaptionEvent*)e)->getLabel());
280   }
281   else if(e->type() == 10009){
282     Reset();
283     if(_systemSpecifiedFlag){
284       _system->ResetPendingGUIUpdateEvents();
285     }
286   }
287   else if(e->type() == 10010){
288     _startFrequency = ((SpectrumFrequencyRangeEvent*)e)->GetStartFrequency();
289     _stopFrequency = ((SpectrumFrequencyRangeEvent*)e)->GetStopFrequency();
290     _centerFrequency  = ((SpectrumFrequencyRangeEvent*)e)->GetCenterFrequency();
291
292     UseRFFrequenciesCB(UseRFFrequenciesCheckBox->isChecked());
293   }
294 }
295
296 void SpectrumDisplayForm::AvgLineEdit_textChanged( const QString &valueString )
297 {
298   if(!valueString.isEmpty()){
299     int value = valueString.toInt();
300     if(value > 500){
301       value = 500;
302       AvgLineEdit->setText("500");
303     }
304     SetAverageCount(value);
305   }
306 }
307
308
309 void SpectrumDisplayForm::MaxHoldCheckBox_toggled( bool newState )
310 {
311   MaxHoldResetBtn->setEnabled(newState);
312   _frequencyDisplayPlot->SetMaxFFTVisible(newState);
313   MaxHoldResetBtn_clicked();
314 }
315
316
317 void SpectrumDisplayForm::MinHoldCheckBox_toggled( bool newState )
318 {
319   MinHoldResetBtn->setEnabled(newState);
320   _frequencyDisplayPlot->SetMinFFTVisible(newState);
321   MinHoldResetBtn_clicked();
322 }
323
324
325 void SpectrumDisplayForm::MinHoldResetBtn_clicked()
326 {
327   _frequencyDisplayPlot->ClearMinData();
328   _frequencyDisplayPlot->replot();
329 }
330
331
332 void SpectrumDisplayForm::MaxHoldResetBtn_clicked()
333 {
334   _frequencyDisplayPlot->ClearMaxData();
335   _frequencyDisplayPlot->replot();
336 }
337
338
339 void SpectrumDisplayForm::PowerLineEdit_textChanged( const QString &valueString )
340 {
341   if(_systemSpecifiedFlag){
342     if(!valueString.isEmpty()){
343       double value = valueString.toDouble();
344       if(value < 1.0){
345         value = 1.0;
346         PowerLineEdit->setText("1");
347       }
348       _system->SetPowerValue(value);
349     }
350
351     if(_system->GetPowerValue() > 1){
352       UseRFFrequenciesCheckBox->setChecked(false);
353       UseRFFrequenciesCheckBox->setEnabled(false);
354       UseRFFrequenciesCB(false);
355     }
356     else{
357       UseRFFrequenciesCheckBox->setEnabled(true);
358     }
359   }
360 }
361
362 void SpectrumDisplayForm::SetFrequencyRange(const double newStartFrequency, const double newStopFrequency, const double newCenterFrequency){
363   _frequencyDisplayPlot->SetFrequencyRange(newStartFrequency, newStopFrequency, newCenterFrequency, UseRFFrequenciesCheckBox->isChecked());
364   _waterfallDisplayPlot->SetFrequencyRange(newStartFrequency, newStopFrequency, newCenterFrequency, UseRFFrequenciesCheckBox->isChecked());
365   _waterfall3DDisplayPlot->SetFrequencyRange(newStartFrequency, newStopFrequency, newCenterFrequency, UseRFFrequenciesCheckBox->isChecked());
366
367 }
368
369 int SpectrumDisplayForm::GetAverageCount(){
370   return _historyVector->size();
371 }
372
373 void SpectrumDisplayForm::SetAverageCount(const int newCount){
374   if(newCount > -1){
375     if(newCount != static_cast<int>(_historyVector->size())){
376       std::vector<double*>::iterator pos;
377       while(newCount < static_cast<int>(_historyVector->size())){
378         pos = _historyVector->begin();
379         delete[] (*pos);
380         _historyVector->erase(pos);
381       }
382
383       while(newCount > static_cast<int>(_historyVector->size())){
384         _historyVector->push_back(new double[_numRealDataPoints]);
385       }
386       AverageDataReset();
387     }
388   }
389 }
390
391 void SpectrumDisplayForm::_AverageHistory(const double* newBuffer){
392   if(_numRealDataPoints > 0){
393     if(_historyVector->size() > 0){
394       memcpy(_historyVector->operator[](_historyEntry), newBuffer, _numRealDataPoints*sizeof(double));
395
396       // Increment the next location to store data
397       _historyEntryCount++;
398       if(_historyEntryCount > static_cast<int>(_historyVector->size())){
399         _historyEntryCount = _historyVector->size();
400       }
401       _historyEntry = (++_historyEntry)%_historyVector->size();
402
403       // Total up and then average the values
404       double sum;
405       for(uint64_t location = 0; location < _numRealDataPoints; location++){
406         sum = 0;
407         for(int number = 0; number < _historyEntryCount; number++){
408           sum += _historyVector->operator[](number)[location];
409         }
410         _averagedValues[location] = sum/static_cast<double>(_historyEntryCount);
411       }
412     }
413     else{
414       memcpy(_averagedValues, newBuffer, _numRealDataPoints*sizeof(double));
415     }
416   }
417 }
418
419 void SpectrumDisplayForm::ResizeBuffers( const uint64_t numFFTDataPoints, const uint64_t /*numTimeDomainDataPoints*/ ){
420   // Convert from Complex to Real for certain Displays
421   if(_numRealDataPoints != numFFTDataPoints){
422     _numRealDataPoints = numFFTDataPoints;
423     delete[] _realFFTDataPoints;
424     delete[] _averagedValues;
425     
426     _realFFTDataPoints = new double[_numRealDataPoints];
427     _averagedValues = new double[_numRealDataPoints];
428     memset(_realFFTDataPoints, 0x0, _numRealDataPoints*sizeof(double));
429     
430     const int historySize = _historyVector->size();
431     SetAverageCount(0); // Clear the existing history
432     SetAverageCount(historySize);
433     
434     Reset();
435   }
436 }
437
438 void SpectrumDisplayForm::Reset(){
439   AverageDataReset();
440
441   _waterfallDisplayPlot->Reset();
442   _waterfall3DDisplayPlot->Reset();
443 }
444
445
446 void SpectrumDisplayForm::AverageDataReset(){
447   _historyEntry = 0;
448   _historyEntryCount = 0;
449
450   memset(_averagedValues, 0x0, _numRealDataPoints*sizeof(double));
451
452   MaxHoldResetBtn_clicked();
453   MinHoldResetBtn_clicked();
454 }
455
456
457 void SpectrumDisplayForm::closeEvent( QCloseEvent *e )
458 {
459   if(_systemSpecifiedFlag){
460     _system->SetWindowOpenFlag(false);
461   }
462
463   qApp->processEvents();
464
465   QWidget::closeEvent(e);
466 }
467
468
469 void SpectrumDisplayForm::WindowTypeChanged( int newItem )
470 {
471   if(_systemSpecifiedFlag){
472    _system->SetWindowType(newItem);
473   }
474 }
475
476
477 void SpectrumDisplayForm::UseRFFrequenciesCB( bool useRFFlag )
478 {
479   if(useRFFlag){
480     SetFrequencyRange(_startFrequency, _stopFrequency, _centerFrequency);
481   }
482   else{
483     SetFrequencyRange(_startFrequency, _stopFrequency, 0.0 );
484   }
485 }
486
487
488 void SpectrumDisplayForm::waterfallMaximumIntensityChangedCB( double newValue )
489 {
490   if(newValue > WaterfallMinimumIntensityWheel->value()){
491     WaterfallMaximumIntensityLabel->setText(QString("%1 dB").arg(newValue, 0, 'f', 0));
492   }
493   else{
494     WaterfallMaximumIntensityWheel->setValue(WaterfallMinimumIntensityWheel->value());
495   }
496   _waterfallDisplayPlot->SetIntensityRange(WaterfallMinimumIntensityWheel->value(), WaterfallMaximumIntensityWheel->value());
497 }
498
499
500 void SpectrumDisplayForm::waterfallMinimumIntensityChangedCB( double newValue )
501 {
502   if(newValue < WaterfallMaximumIntensityWheel->value()){
503     WaterfallMinimumIntensityLabel->setText(QString("%1 dB").arg(newValue, 0, 'f', 0));
504   }
505   else{
506     WaterfallMinimumIntensityWheel->setValue(WaterfallMaximumIntensityWheel->value());
507   }
508   _waterfallDisplayPlot->SetIntensityRange(WaterfallMinimumIntensityWheel->value(), WaterfallMaximumIntensityWheel->value());
509 }
510
511 void SpectrumDisplayForm::waterfall3DMaximumIntensityChangedCB( double newValue )
512 {
513   if(newValue > Waterfall3DMinimumIntensityWheel->value()){
514     Waterfall3DMaximumIntensityLabel->setText(QString("%1 dB").arg(newValue, 0, 'f', 0));
515   }
516   else{
517     Waterfall3DMaximumIntensityWheel->setValue(Waterfall3DMinimumIntensityWheel->value());
518   }
519   _waterfall3DDisplayPlot->SetIntensityRange(Waterfall3DMinimumIntensityWheel->value(), Waterfall3DMaximumIntensityWheel->value());
520 }
521
522
523 void SpectrumDisplayForm::waterfall3DMinimumIntensityChangedCB( double newValue )
524 {
525   if(newValue < Waterfall3DMaximumIntensityWheel->value()){
526     Waterfall3DMinimumIntensityLabel->setText(QString("%1 dB").arg(newValue, 0, 'f', 0));
527   }
528   else{
529     Waterfall3DMinimumIntensityWheel->setValue(Waterfall3DMaximumIntensityWheel->value());
530   }
531   _waterfall3DDisplayPlot->SetIntensityRange(Waterfall3DMinimumIntensityWheel->value(), Waterfall3DMaximumIntensityWheel->value());
532 }
533
534
535 void SpectrumDisplayForm::FFTComboBoxSelectedCB( const QString &fftSizeString )
536 {
537   if(_systemSpecifiedFlag){
538     _system->SetFFTSize(fftSizeString.toLong());
539   }
540 }
541
542
543 void SpectrumDisplayForm::WaterfallAutoScaleBtnCB()
544 {
545   double minimumIntensity = _noiseFloorAmplitude - 5;
546   if(minimumIntensity < WaterfallMinimumIntensityWheel->minValue()){
547     minimumIntensity = WaterfallMinimumIntensityWheel->minValue();
548   }
549   WaterfallMinimumIntensityWheel->setValue(minimumIntensity);
550   double maximumIntensity = _peakAmplitude + 10;
551   if(maximumIntensity > WaterfallMaximumIntensityWheel->maxValue()){
552     maximumIntensity = WaterfallMaximumIntensityWheel->maxValue();
553   }
554   WaterfallMaximumIntensityWheel->setValue(maximumIntensity);
555   waterfallMaximumIntensityChangedCB(maximumIntensity);
556 }
557
558 void SpectrumDisplayForm::Waterfall3DAutoScaleBtnCB()
559 {
560   double minimumIntensity = _noiseFloorAmplitude - 5;
561   if(minimumIntensity < Waterfall3DMinimumIntensityWheel->minValue()){
562     minimumIntensity = Waterfall3DMinimumIntensityWheel->minValue();
563   }
564   Waterfall3DMinimumIntensityWheel->setValue(minimumIntensity);
565   double maximumIntensity = _peakAmplitude + 10;
566   if(maximumIntensity > Waterfall3DMaximumIntensityWheel->maxValue()){
567     maximumIntensity = Waterfall3DMaximumIntensityWheel->maxValue();
568   }
569   Waterfall3DMaximumIntensityWheel->setValue(maximumIntensity);
570   waterfallMaximumIntensityChangedCB(maximumIntensity);
571 }
572
573 void SpectrumDisplayForm::WaterfallIntensityColorTypeChanged( int newType )
574 {
575   QColor lowIntensityColor;
576   QColor highIntensityColor;
577   if(newType == WaterfallDisplayPlot::INTENSITY_COLOR_MAP_TYPE_USER_DEFINED){
578     // Select the Low Intensity Color
579     lowIntensityColor = _waterfallDisplayPlot->GetUserDefinedLowIntensityColor();
580     if(!lowIntensityColor.isValid()){
581       lowIntensityColor = Qt::black;
582     }
583     QMessageBox::information(this, "Low Intensity Color Selection", "In the next window, select the low intensity color for the waterfall display",  QMessageBox::Ok);
584     lowIntensityColor = QColorDialog::getColor(lowIntensityColor, this);
585
586     // Select the High Intensity Color
587     highIntensityColor = _waterfallDisplayPlot->GetUserDefinedHighIntensityColor();
588     if(!highIntensityColor.isValid()){
589       highIntensityColor = Qt::white;
590     }
591     QMessageBox::information(this, "High Intensity Color Selection", "In the next window, select the high intensity color for the waterfall display",  QMessageBox::Ok);
592     highIntensityColor = QColorDialog::getColor(highIntensityColor, this);
593   }
594   _waterfallDisplayPlot->SetIntensityColorMapType(newType, lowIntensityColor, highIntensityColor);
595 }
596
597 void SpectrumDisplayForm::Waterfall3DIntensityColorTypeChanged( int newType )
598 {
599   QColor lowIntensityColor;
600   QColor highIntensityColor;
601   if(newType == Waterfall3DDisplayPlot::INTENSITY_COLOR_MAP_TYPE_USER_DEFINED){
602     // Select the Low Intensity Color
603     lowIntensityColor = _waterfallDisplayPlot->GetUserDefinedLowIntensityColor();
604     if(!lowIntensityColor.isValid()){
605       lowIntensityColor = Qt::black;
606     }
607     QMessageBox::information(this, "Low Intensity Color Selection", "In the next window, select the low intensity color for the waterfall display",  QMessageBox::Ok);
608     lowIntensityColor = QColorDialog::getColor(lowIntensityColor, this);
609
610     // Select the High Intensity Color
611     highIntensityColor = _waterfallDisplayPlot->GetUserDefinedHighIntensityColor();
612     if(!highIntensityColor.isValid()){
613       highIntensityColor = Qt::white;
614     }
615     QMessageBox::information(this, "High Intensity Color Selection", "In the next window, select the high intensity color for the waterfall display",  QMessageBox::Ok);
616     highIntensityColor = QColorDialog::getColor(highIntensityColor, this);
617   }
618   _waterfall3DDisplayPlot->SetIntensityColorMapType(newType, lowIntensityColor, highIntensityColor);
619 }