DynExp
Highly flexible laboratory automation for dynamically changing experiments.
ODMRWidget.cpp
Go to the documentation of this file.
1 // This file is part of DynExp.
2 
3 #include "stdafx.h"
4 #include "ODMR.h"
5 #include "moc_ODMRWidget.cpp"
6 #include "ODMRWidget.h"
7 
8 namespace DynExpModule::ODMR
9 {
11  : CurrentState(nullptr),
12  StateLabel(new QLabel(Owner)), SweepStateLabel(new QLabel(Owner)), AcquisitionTimeLabel(new QLabel(Owner))
13  {
14  }
15 
17  {
18  StateLabel->setText(CurrentState ? (QString(" ") + CurrentState->GetDescription()) : "< Unknown >");
19  if (CurrentState && CurrentState->GetState() != StateType::Ready)
20  StateLabel->setStyleSheet(DynExpUI::StatusBarBusyStyleSheet);
21  else
22  StateLabel->setStyleSheet("");
23  }
24 
26  : QModuleWidget(Owner, parent), StatusBar(this),
27  ODMRDataSeries(nullptr), ODMRFitSeries(nullptr), ODMRDataChart(nullptr), ODMRXAxis(new QValueAxis(this)), ODMRYAxis(new QValueAxis(this)),
28  SensitivityDataSeries(nullptr), SensitivityDataChart(nullptr), SensitivityXAxis(new QLogValueAxis(this)), SensitivityYAxis(new QLogValueAxis(this))
29  {
30  ui.setupUi(this);
31 
32  // Status bar
33  ui.MainStatusBar->addWidget(StatusBar.StateLabel, 5);
34  ui.MainStatusBar->addWidget(StatusBar.SweepStateLabel, 2);
35  ui.MainStatusBar->addWidget(StatusBar.AcquisitionTimeLabel, 3);
36 
37  // Graph to display a single ODMR trace
38  ODMRDataChart = new QChart();
39  ui.ODMRChartView->setChart(ODMRDataChart); // Takes ownership of ODMRDataChart.
40  ui.ODMRChartView->setRenderHint(QPainter::Antialiasing);
42  ODMRDataChart->legend()->setVisible(false);
43  ODMRXAxis->setTitleText("frequency in GHz");
44 
45  // Graph to display a single sensitivity measurement
46  SensitivityDataChart = new QChart();
47  ui.SensitivityChartView->setChart(SensitivityDataChart); // Takes ownership of SensitivityDataChart.
48  ui.SensitivityChartView->setRenderHint(QPainter::Antialiasing);
50  SensitivityDataChart->legend()->setVisible(false);
51  SensitivityXAxis->setBase(10);
52  SensitivityXAxis->setTitleText("frequency in Hz");
53  SensitivityYAxis->setBase(10);
54  SensitivityYAxis->setTitleText("sensitivity ASD in T/sqrt(Hz)");
55 
56  // Chart takes ownership of axes.
57  ODMRDataChart->addAxis(ODMRXAxis, Qt::AlignBottom);
58  ODMRDataChart->addAxis(ODMRYAxis, Qt::AlignLeft);
59  SensitivityDataChart->addAxis(SensitivityXAxis, Qt::AlignBottom);
60  SensitivityDataChart->addAxis(SensitivityYAxis, Qt::AlignLeft);
61 
62  connect(ui.CBParamSweepType, QOverload<int>::of(&QComboBox::currentIndexChanged), this, &ODMRWidget::OnSweepSeriesParamChanged);
63  }
64 
66  {
67  if (!GetUIInitialized())
68  {
69  ui.SBRFPower->setValue(ModuleData->RFPower);
70  ui.SBRFCenter->setValue(ModuleData->RFCenterFreq / 1e6);
71  ui.SBRFSpan->setValue(ModuleData->RFFreqSpan / 1e6);
72  ui.SBRFFreqSpacing->setValue(ModuleData->RFFreqSpacing / 1e3);
73  ui.SBRFDwellTime->setValue(ModuleData->RFDwellTime / 1e-3);
74  ui.RBRFModulationTypeNone->setChecked(true); // Emits signal to update module data accordingly.
75  ui.SBRFModulationFreq->setValue(ModuleData->RFModulationFreq / 1e3);
76  ui.SBRFModulationDepth->setValue(ModuleData->RFModulationDepth / 1e3);
77  ui.SBDataAcquisitionODMRSamplingRate->setValue(ModuleData->ODMRSamplingRate);
78  ui.LESaveDataPath->setText(QString::fromStdString(ModuleData->SaveDataPath));
79  ui.SBSaveDataCurrentIndex->setValue(ModuleData->CurrentSaveIndex);
80  ui.CBSaveDataEnable->setChecked(ModuleData->AutosaveEnabled);
81  ui.CBSensitivityEnable->setChecked(ModuleData->SensitivityEnabled);
82  ui.CBSensitivityOncePerSweep->setChecked(ModuleData->SensitivityOncePerSweep);
83  ui.CBSensitivityOffResEnable->setChecked(ModuleData->SensitivityOffResonanceEnabled);
84  ui.SBSensitivityFreq->setValue(ModuleData->SensitivityResonanceFreq / 1e6);
85  ui.SBSensitivityOffResFreq->setValue(ModuleData->SensitivityOffResonanceFreq / 1e6);
86  ui.SBSensitivitySpan->setValue(ModuleData->SensitivityResonanceSpan / 1e6);
87  ui.SBSensitivitySamplingRate->setValue(ModuleData->SensitivitySamplingRate);
88  ui.SBSensitivityDuration->setValue(ModuleData->SensitivityDuration);
89  ui.GBSensitivityAnalysis->setChecked(ModuleData->SensitivityAnalysisEnabled);
90  ui.SBGyromagneticRatio->setValue(ModuleData->GyromagneticRatio / 1e6);
91  ui.CBParamSweepEnable->setChecked(ModuleData->SweepSeriesEnabled);
92  if (ModuleData->TestFeature(ODMRData::FeatureType::AuxAnalogOut))
93  ui.CBParamSweepType->insertItem(ui.CBParamSweepType->count(), "Auxiliary analog out");
94  ui.CBParamSweepType->setCurrentIndex(0); // Emits signal to update module data accordingly, but see below.
95  ui.SBParamSweepStart->setValue(ModuleData->SweepSeriesStart);
96  ui.SBParamSweepStop->setValue(ModuleData->SweepSeriesStop);
97  ui.SBParamSweepStep->setValue(ModuleData->SweepSeriesStep);
98  ui.CBParamSweepRetrace->setChecked(ModuleData->SweepSeriesRetrace);
99  ui.CBParamSweepAdvanceLastValue->setChecked(ModuleData->SweepSeriesAdvanceLastValue);
100 
101  ui.SBRFPower->setMinimum(ModuleData->RFGeneratorMinFuncDesc.Amplitude);
102  ui.SBRFPower->setMaximum(ModuleData->RFGeneratorMaxFuncDesc.Amplitude);
103  ui.SBRFPower->setValue(ModuleData->RFGeneratorDefaultFuncDesc.Amplitude);
104  ui.SBRFPower->setSuffix(QString(" ") + ModuleData->GetRFGenerator()->GetValueUnitStr());
105  ui.SBRFCenter->setMinimum(ModuleData->RFGeneratorMinFuncDesc.FrequencyInHz / 1e6);
106  ui.SBRFCenter->setMaximum(ModuleData->RFGeneratorMaxFuncDesc.FrequencyInHz / 1e6);
107  ui.SBRFCenter->setValue(ModuleData->RFGeneratorDefaultFuncDesc.FrequencyInHz / 1e6);
108  ui.SBSensitivityFreq->setMinimum(ModuleData->RFGeneratorMinFuncDesc.FrequencyInHz / 1e6);
109  ui.SBSensitivityFreq->setMaximum(ModuleData->RFGeneratorMaxFuncDesc.FrequencyInHz / 1e6);
110  ui.SBSensitivityFreq->setValue(ModuleData->RFGeneratorDefaultFuncDesc.FrequencyInHz / 1e6);
111 
112  ui.SBDataAcquisitionODMRSamplingRate->setEnabled(ModuleData->TestFeature(ODMRData::FeatureType::LockinDetection));
113  ui.SBSensitivitySamplingRate->setEnabled(ModuleData->TestFeature(ODMRData::FeatureType::LockinDetection));
114  ui.SBSensitivityDuration->setEnabled(ModuleData->TestFeature(ODMRData::FeatureType::LockinDetection));
115 
116  ODMRYAxis->setTitleText(QString("ODMR signal in ") + ModuleData->GetSignalDetector()->GetValueUnitStr());
117 
118  // This is not emitted if setCurrentIndex() does not change the index (because it already is the desired value).
119  // So, do it manually.
120  OnSweepSeriesParamChanged(ui.CBParamSweepType->currentIndex());
121 
122  AuxAnalogOutValueUnit = ModuleData->AuxAnalogOutValueUnit;
123  AuxAnalogOutMinValue = ModuleData->AuxAnalogOutMinValue;
124  AuxAnalogOutMaxValue = ModuleData->AuxAnalogOutMaxValue;
125 
126  UIInitialized = true;
127  }
128  }
129 
131  {
132  bool IsReady = State->GetState() == StateType::Ready;
133  StatusBar.CurrentState = State;
134 
135  StatusBar.AcquisitionTimeLabel->setText((IsReady || ModuleData->AcquisitionTime <= 0) ? "" : QString::fromStdString("Acquisition time: " + Util::ToStr(ModuleData->AcquisitionTime, 2) + " s"));
136  StatusBar.SweepStateLabel->setText(IsReady ? "" : (!ModuleData->GetSweepNumberSteps() ? "single run" :
137  (QString("Sweep ") + QString::number(ModuleData->CurrentSweepIndex + 1) + " / " + QString::number(ModuleData->GetSweepNumberSteps()))));
138 
139  ui.GBRFSweep->setEnabled(IsReady);
140  ui.GBRFModulation->setEnabled(IsReady);
141  ui.GBDataAcquisition->setEnabled(IsReady);
142  ui.GBSaveData->setEnabled(IsReady);
143  ui.GBSensitivity->setEnabled(IsReady);
144  ui.GBSensitivityAnalysis->setEnabled(IsReady);
145  ui.GBParamSweep->setEnabled(IsReady);
146  ui.BStart->setEnabled(IsReady);
147  ui.BStartSensitivity->setEnabled(IsReady);
148  ui.BStop->setEnabled(!IsReady);
149  }
150 
152  {
153  ui.LERFNumSamples->setText(QString::number(ModuleData->GetNumSamples()));
154  ui.LODMRCurrentSelection->setText(ModuleData->ODMRPlot.SelectedPoint.isNull() ? QString() : (QString::number(ModuleData->ODMRPlot.SelectedPoint.x() * 1e3, 'f', 3) + " MHz"));
155  ui.LEODMRFitSlope->setText(QString::number(std::get<1>(ModuleData->ODMRPlot.FitParams) * 1e6) + " [y]/MHz");
156  ui.LEODMRFitOffset->setText(QString::number(std::get<0>(ModuleData->ODMRPlot.FitParams)) + " [y]");
157 
158  if (!ui.SBSaveDataCurrentIndex->hasFocus())
159  ui.SBSaveDataCurrentIndex->setValue(ModuleData->CurrentSaveIndex);
160 
161  StatusBar.Update();
162  }
163 
165  {
166  ODMRDataChart->removeAllSeries();
167  ODMRDataSeries = new QLineSeries(this);
168  ODMRDataSeries->append(ODMRPlot.DataPoints);
169  ODMRDataSeries->setPointsVisible(false);
170  ODMRFitSeries = new QLineSeries(this);
171  ODMRFitSeries->append(ODMRPlot.FitPoints);
172  ODMRFitSeries->setPointsVisible(false);
173 
174  ODMRXAxis->setRange(ODMRPlot.DataPointsMinValues.x(), ODMRPlot.DataPointsMaxValues.x());
175  ODMRYAxis->setRange(ODMRPlot.DataPointsMinValues.y(), ODMRPlot.DataPointsMaxValues.y());
176 
177  ODMRDataChart->addSeries(ODMRDataSeries);
178  ODMRDataChart->addSeries(ODMRFitSeries);
179  ODMRDataSeries->attachAxis(ODMRDataChart->axes()[0]);
180  ODMRDataSeries->attachAxis(ODMRDataChart->axes()[1]);
181  ODMRFitSeries->attachAxis(ODMRDataChart->axes()[0]);
182  ODMRFitSeries->attachAxis(ODMRDataChart->axes()[1]);
183  }
184 
186  {
187  SensitivityDataChart->removeAllSeries();
188  SensitivityDataSeries = new QLineSeries(this);
189  SensitivityDataSeries->append(SensitivityPlot.DataPoints);
190  SensitivityDataSeries->setPointsVisible(false);
191 
192  SensitivityYAxis->setRange(SensitivityPlot.DataPointsMinValues.y(), SensitivityPlot.DataPointsMaxValues.y());
193  SensitivityXAxis->setRange(SensitivityPlot.DataPointsMinValues.x(), SensitivityPlot.DataPointsMaxValues.x());
194 
196  SensitivityDataSeries->attachAxis(SensitivityDataChart->axes()[0]);
197  SensitivityDataSeries->attachAxis(SensitivityDataChart->axes()[1]);
198  }
199 
201  {
202  auto Filename = Util::PromptSaveFilePathModule(this, "Select file for saving ODMR data",
203  ".csv", " Comma-separated values file (*.csv)");
204  if (Filename.isEmpty())
205  return;
206 
207  // Emits signal to update module data accordingly.
208  ui.LESaveDataPath->setText(Filename);
209  }
210 
212  {
213  QDoubleSpinBox* Destiny = nullptr;
214 
215  if (Index != 2) // != ODMRData::SweepSeriesType::AnalogOut
216  {
217  switch (Index)
218  {
219  case 0: // ODMRData::SweepSeriesType::RFModulationDepth
220  Destiny = ui.SBRFModulationDepth;
221  break;
222  case 1: // ODMRData::SweepSeriesType::RFPower
223  Destiny = ui.SBRFPower;
224  break;
225  }
226 
227  if (Destiny)
228  {
229  ui.SBParamSweepStart->setMinimum(Destiny->minimum());
230  ui.SBParamSweepStart->setMaximum(Destiny->maximum());
231  ui.SBParamSweepStart->setSuffix(Destiny->suffix());
232  ui.SBParamSweepStop->setMinimum(Destiny->minimum());
233  ui.SBParamSweepStop->setMaximum(Destiny->maximum());
234  ui.SBParamSweepStop->setSuffix(Destiny->suffix());
235  ui.SBParamSweepStep->setMinimum(Destiny->minimum());
236  ui.SBParamSweepStep->setMaximum(Destiny->maximum());
237  ui.SBParamSweepStep->setSuffix(Destiny->suffix());
238  }
239  }
240  else
241  {
242  ui.SBParamSweepStart->setMinimum(AuxAnalogOutMinValue);
243  ui.SBParamSweepStart->setMaximum(AuxAnalogOutMaxValue);
244  ui.SBParamSweepStart->setSuffix(QString(" ") + DynExpInstr::DataStreamInstrumentData::UnitTypeToStr(AuxAnalogOutValueUnit));
245  ui.SBParamSweepStop->setMinimum(AuxAnalogOutMinValue);
246  ui.SBParamSweepStop->setMaximum(AuxAnalogOutMaxValue);
247  ui.SBParamSweepStop->setSuffix(ui.SBParamSweepStart->suffix());
248  ui.SBParamSweepStep->setMinimum(AuxAnalogOutMinValue);
249  ui.SBParamSweepStep->setMaximum(AuxAnalogOutMaxValue);
250  ui.SBParamSweepStep->setSuffix(ui.SBParamSweepStart->suffix());
251  }
252  }
253 }
User interface belonging to the DynExpModule::ODMR::ODMR module.
Implementation of a module to perform optically detected magnetic resonance (ODMR) measurements.
static const char * UnitTypeToStr(const UnitType &Unit)
Returns a descriptive string of a respective unit to be e.g. used in plots.
QLogValueAxis * SensitivityXAxis
Definition: ODMRWidget.h:103
void OnSweepSeriesParamChanged(int Index)
Definition: ODMRWidget.cpp:211
ODMRWidget(ODMR &Owner, QModuleWidget *parent=nullptr)
Definition: ODMRWidget.cpp:25
void UpdateUIData(Util::SynchronizedPointer< ODMRData > &ModuleData)
Definition: ODMRWidget.cpp:151
void InitializeUI(Util::SynchronizedPointer< ODMRData > &ModuleData)
Definition: ODMRWidget.cpp:65
void UpdateSensitivityPlot(const SensitivityPlotType &SensitivityPlot)
Definition: ODMRWidget.cpp:185
void UpdateODMRPlot(const ODMRPlotType &ODMRPlot)
Definition: ODMRWidget.cpp:164
QLogValueAxis * SensitivityYAxis
Definition: ODMRWidget.h:104
void SetUIState(const StateMachineStateType *State, Util::SynchronizedPointer< ODMRData > &ModuleData)
Definition: ODMRWidget.cpp:130
DynExpInstr::DataStreamInstrumentData::UnitType AuxAnalogOutValueUnit
Definition: ODMRWidget.h:106
DynExpInstr::DataStreamInstrumentData::ValueType AuxAnalogOutMinValue
Definition: ODMRWidget.h:107
DynExpInstr::DataStreamInstrumentData::ValueType AuxAnalogOutMaxValue
Definition: ODMRWidget.h:108
bool GetUIInitialized() const noexcept
Definition: ODMRWidget.h:88
QModuleBase & Owner
Module owning this user interface window (reference, because it should never change nor be nullptr).
Definition: Module.h:1162
QModuleWidget(QModuleBase &Owner, QWidget *Parent=nullptr)
Constructs a QModuleWidget instance.
Definition: Module.cpp:417
State machine state as used by class StateMachine. A state mainly wraps a state function of the membe...
Definition: Util.h:1305
constexpr StateEnumType GetState() const noexcept
Returns the state's unique identifier.
Definition: Util.h:1321
Pointer to lock a class derived from ISynchronizedPointerLockable for synchronizing between threads....
Definition: Util.h:170
constexpr auto DefaultQChartTheme
constexpr auto StatusBarBusyStyleSheet
std::string ToStr(const T &Value, int Precision=-1)
Converts a (numeric) value of type T to a std::string using operator<< of std::stringstream.
Definition: Util.h:625
QString PromptSaveFilePathModule(DynExp::QModuleWidget *Parent, const QString &Title, const QString &DefaultSuffix, const QString &NameFilter)
Works as PromptOpenFilePath() but asks the user to select a single file which does not need to exist....
Definition: QtUtil.cpp:143
Accumulates include statements to provide a precompiled header.
const StateMachineStateType * CurrentState
Definition: ODMRWidget.h:68