DynExp
Highly flexible laboratory automation for dynamically changing experiments.
Loading...
Searching...
No Matches
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
8namespace 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
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)
ODMRWidget(ODMR &Owner, QModuleWidget *parent=nullptr)
void UpdateUIData(Util::SynchronizedPointer< ODMRData > &ModuleData)
void InitializeUI(Util::SynchronizedPointer< ODMRData > &ModuleData)
void UpdateSensitivityPlot(const SensitivityPlotType &SensitivityPlot)
void UpdateODMRPlot(const ODMRPlotType &ODMRPlot)
QLogValueAxis * SensitivityYAxis
Definition ODMRWidget.h:104
void SetUIState(const StateMachineStateType *State, Util::SynchronizedPointer< ODMRData > &ModuleData)
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