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 "ui_ODMR.h"
7#include "ODMRWidget.h"
8
9namespace DynExpModule::ODMR
10{
12 : CurrentState(nullptr),
13 StateLabel(new QLabel(Owner)), SweepStateLabel(new QLabel(Owner)), AcquisitionTimeLabel(new QLabel(Owner))
14 {
15 }
16
18 {
19 StateLabel->setText(CurrentState ? (QString(" ") + CurrentState->GetDescription()) : "< Unknown >");
20 if (CurrentState && CurrentState->GetState() != StateType::Ready)
21 StateLabel->setStyleSheet(DynExpUI::StatusBarBusyStyleSheet);
22 else
23 StateLabel->setStyleSheet("");
24 }
25
27 : QModuleWidget(Owner, parent),
28 ui(std::make_unique<Ui::ODMR>()), StatusBar(this),
29 ODMRGraph(nullptr), SensitivityGraph(nullptr)
30 {
31 ui->setupUi(this);
32
33 // Status bar
34 ui->MainStatusBar->addWidget(StatusBar.StateLabel, 5);
35 ui->MainStatusBar->addWidget(StatusBar.SweepStateLabel, 2);
36 ui->MainStatusBar->addWidget(StatusBar.AcquisitionTimeLabel, 3);
37
38 // Graph to display a single ODMR trace
39 connect(ui->ODMRGraph, &QQuickWidget::statusChanged, [this](QQuickWidget::Status Status) {
40 if (Status == QQuickWidget::Status::Ready && ui->ODMRGraph->rootObject())
41 {
42 auto BackendVariant = ui->ODMRGraph->rootObject()->property("backend");
43 ODMRGraph = BackendVariant.isValid() ? BackendVariant.value<DynExpQuick::DynExpLineGraphBackend*>() : nullptr;
44
45 if (ODMRGraph)
46 {
47 ODMRGraph->InsertSeries("meas");
48 ODMRGraph->InsertSeries("fit");
49 }
50 }
51 });
52 ui->ODMRGraph->loadFromModule("Modules.DynExpQuick", "QDynExpLineGraph");
53
54 // Graph to display a single sensitivity measurement
55 connect(ui->SensitivityGraph, &QQuickWidget::statusChanged, [this](QQuickWidget::Status Status) {
56 if (Status == QQuickWidget::Status::Ready && ui->SensitivityGraph->rootObject())
57 {
58 auto BackendVariant = ui->SensitivityGraph->rootObject()->property("backend");
59 SensitivityGraph = BackendVariant.isValid() ? BackendVariant.value<DynExpQuick::DynExpLineGraphBackend*>() : nullptr;
60
61 if (SensitivityGraph)
62 SensitivityGraph->InsertSeries("noise");
63 }
64 });
65 ui->SensitivityGraph->loadFromModule("Modules.DynExpQuick", "QDynExpLineGraph");
66
67 connect(ui->CBParamSweepType, QOverload<int>::of(&QComboBox::currentIndexChanged), this, &ODMRWidget::OnSweepSeriesParamChanged);
68 }
69
70 void ODMRWidget::InitializeUI(Util::SynchronizedPointer<ODMRData>& ModuleData)
71 {
72 if (!GetUIInitialized())
73 {
74 ui->SBRFPower->setValue(ModuleData->RFPower);
75 ui->SBRFCenter->setValue(ModuleData->RFCenterFreq / 1e6);
76 ui->SBRFSpan->setValue(ModuleData->RFFreqSpan / 1e6);
77 ui->SBRFFreqSpacing->setValue(ModuleData->RFFreqSpacing / 1e3);
78 ui->SBRFDwellTime->setValue(ModuleData->RFDwellTime / 1e-3);
79 ui->RBRFModulationTypeNone->setChecked(true); // Emits signal to update module data accordingly.
80 ui->SBRFModulationFreq->setValue(ModuleData->RFModulationFreq / 1e3);
81 ui->SBRFModulationDepth->setValue(ModuleData->RFModulationDepth / 1e3);
82 ui->SBDataAcquisitionODMRSamplingRate->setValue(ModuleData->ODMRSamplingRate);
83 ui->LESaveDataPath->setText(QString::fromStdString(ModuleData->SaveDataPath));
84 ui->SBSaveDataCurrentIndex->setValue(ModuleData->CurrentSaveIndex);
85 ui->CBSaveDataEnable->setChecked(ModuleData->AutosaveEnabled);
86 ui->CBSensitivityEnable->setChecked(ModuleData->SensitivityEnabled);
87 ui->CBSensitivityOncePerSweep->setChecked(ModuleData->SensitivityOncePerSweep);
88 ui->CBSensitivityOffResEnable->setChecked(ModuleData->SensitivityOffResonanceEnabled);
89 ui->SBSensitivityFreq->setValue(ModuleData->SensitivityResonanceFreq / 1e6);
90 ui->SBSensitivityOffResFreq->setValue(ModuleData->SensitivityOffResonanceFreq / 1e6);
91 ui->SBSensitivitySpan->setValue(ModuleData->SensitivityResonanceSpan / 1e6);
92 ui->SBSensitivitySamplingRate->setValue(ModuleData->SensitivitySamplingRate);
93 ui->SBSensitivityDuration->setValue(ModuleData->SensitivityDuration);
94 ui->GBSensitivityAnalysis->setChecked(ModuleData->SensitivityAnalysisEnabled);
95 ui->SBGyromagneticRatio->setValue(ModuleData->GyromagneticRatio / 1e6);
96 ui->CBParamSweepEnable->setChecked(ModuleData->SweepSeriesEnabled);
97 if (ModuleData->TestFeature(ODMRData::FeatureType::AuxAnalogOut))
98 ui->CBParamSweepType->insertItem(ui->CBParamSweepType->count(), "Auxiliary analog out");
99 ui->CBParamSweepType->setCurrentIndex(0); // Emits signal to update module data accordingly, but see below.
100 ui->SBParamSweepStart->setValue(ModuleData->SweepSeriesStart);
101 ui->SBParamSweepStop->setValue(ModuleData->SweepSeriesStop);
102 ui->SBParamSweepStep->setValue(ModuleData->SweepSeriesStep);
103 ui->CBParamSweepRetrace->setChecked(ModuleData->SweepSeriesRetrace);
104 ui->CBParamSweepAdvanceLastValue->setChecked(ModuleData->SweepSeriesAdvanceLastValue);
105
106 ui->SBRFPower->setMinimum(ModuleData->RFGeneratorMinFuncDesc.Amplitude);
107 ui->SBRFPower->setMaximum(ModuleData->RFGeneratorMaxFuncDesc.Amplitude);
108 ui->SBRFPower->setValue(ModuleData->RFGeneratorDefaultFuncDesc.Amplitude);
109 ui->SBRFPower->setSuffix(QString(" ") + ModuleData->GetRFGenerator()->GetValueUnitStr());
110 ui->SBRFCenter->setMinimum(ModuleData->RFGeneratorMinFuncDesc.FrequencyInHz / 1e6);
111 ui->SBRFCenter->setMaximum(ModuleData->RFGeneratorMaxFuncDesc.FrequencyInHz / 1e6);
112 ui->SBRFCenter->setValue(ModuleData->RFGeneratorDefaultFuncDesc.FrequencyInHz / 1e6);
113 ui->SBSensitivityFreq->setMinimum(ModuleData->RFGeneratorMinFuncDesc.FrequencyInHz / 1e6);
114 ui->SBSensitivityFreq->setMaximum(ModuleData->RFGeneratorMaxFuncDesc.FrequencyInHz / 1e6);
115 ui->SBSensitivityFreq->setValue(ModuleData->RFGeneratorDefaultFuncDesc.FrequencyInHz / 1e6);
116
117 ui->SBDataAcquisitionODMRSamplingRate->setEnabled(ModuleData->TestFeature(ODMRData::FeatureType::LockinDetection));
118 ui->SBSensitivitySamplingRate->setEnabled(ModuleData->TestFeature(ODMRData::FeatureType::LockinDetection));
119 ui->SBSensitivityDuration->setEnabled(ModuleData->TestFeature(ODMRData::FeatureType::LockinDetection));
120
121 // This is not emitted if setCurrentIndex() does not change the index (because it already is the desired value).
122 // So, do it manually.
123 OnSweepSeriesParamChanged(ui->CBParamSweepType->currentIndex());
124
125 AuxAnalogOutValueUnit = ModuleData->AuxAnalogOutValueUnit;
126 AuxAnalogOutMinValue = ModuleData->AuxAnalogOutMinValue;
127 AuxAnalogOutMaxValue = ModuleData->AuxAnalogOutMaxValue;
128
129 UIInitialized = true;
130 }
131 }
132
133 void ODMRWidget::SetUIState(const StateMachineStateType* State, Util::SynchronizedPointer<ODMRData>& ModuleData)
134 {
135 bool IsReady = State->GetState() == StateType::Ready;
136 StatusBar.CurrentState = State;
137
138 StatusBar.AcquisitionTimeLabel->setText((IsReady || ModuleData->AcquisitionTime <= 0) ? "" : QString::fromStdString("Acquisition time: " + Util::ToStr(ModuleData->AcquisitionTime, 2) + " s"));
139 StatusBar.SweepStateLabel->setText(IsReady ? "" : (!ModuleData->GetSweepNumberSteps() ? "single run" :
140 (QString("Sweep ") + QString::number(ModuleData->CurrentSweepIndex + 1) + " / " + QString::number(ModuleData->GetSweepNumberSteps()))));
141
142 ui->GBRFSweep->setEnabled(IsReady);
143 ui->GBRFModulation->setEnabled(IsReady);
144 ui->GBDataAcquisition->setEnabled(IsReady);
145 ui->GBSaveData->setEnabled(IsReady);
146 ui->GBSensitivity->setEnabled(IsReady);
147 ui->GBSensitivityAnalysis->setEnabled(IsReady);
148 ui->GBParamSweep->setEnabled(IsReady);
149 ui->BStart->setEnabled(IsReady);
150 ui->BStartSensitivity->setEnabled(IsReady);
151 ui->BStop->setEnabled(!IsReady);
152 }
153
154 void ODMRWidget::UpdateUIData(Util::SynchronizedPointer<ODMRData>& ModuleData)
155 {
156 ui->LERFNumSamples->setText(QString::number(ModuleData->GetNumSamples()));
157 ui->LEODMRFitSlope->setText(QString::number(std::get<1>(ModuleData->ODMRPlot.FitParams) * 1e6) + " [y]/MHz");
158 ui->LEODMRFitOffset->setText(QString::number(std::get<0>(ModuleData->ODMRPlot.FitParams)) + " [y]");
159
160 if (!ui->SBSaveDataCurrentIndex->hasFocus())
161 ui->SBSaveDataCurrentIndex->setValue(ModuleData->CurrentSaveIndex);
162
163 StatusBar.Update();
164 }
165
166 void ODMRWidget::UpdateODMRPlot(ODMRPlotType& ODMRPlot)
167 {
168 if (ODMRPlot.HasChanged)
169 ODMRPlot.HasChanged = false;
170 else
171 {
172 ODMRPlot.PlotInfo.ResetHoveredSample();
173 ODMRPlot.PlotInfo.ReprocessSamples(ODMRPlot.DataPoints, 0);
174 ODMRPlot.PlotInfo.ReprocessSamples(ODMRPlot.FitPoints, 0);
175 }
176
177 ODMRGraph->UpdateSeries(0, ODMRPlot.DataPoints, ODMRPlot.PlotInfo);
178 ODMRGraph->UpdateSeries(1, ODMRPlot.FitPoints, ODMRPlot.PlotInfo);
179 ODMRGraph->UpdateData(ODMRPlot.PlotInfo);
180 }
181
182 void ODMRWidget::UpdateSensitivityPlot(SensitivityPlotType& SensitivityPlot)
183 {
184 if (SensitivityPlot.HasChanged)
185 SensitivityPlot.HasChanged = false;
186 else
187 {
188 SensitivityPlot.PlotInfo.ResetHoveredSample();
189 SensitivityPlot.PlotInfo.ReprocessSamples(SensitivityPlot.DataPoints, 0);
190 }
191
192 SensitivityGraph->UpdateSeries(0, SensitivityPlot.DataPoints, SensitivityPlot.PlotInfo);
193 SensitivityGraph->UpdateData(SensitivityPlot.PlotInfo);
194 }
195
196 void ODMRWidget::OnBrowseSavePathClicked()
197 {
198 auto Filename = Util::PromptSaveFilePathModule(this, "Select file for saving ODMR data",
199 ".csv", " Comma-separated values file (*.csv)");
200 if (Filename.isEmpty())
201 return;
202
203 // Emits signal to update module data accordingly.
204 ui->LESaveDataPath->setText(Filename);
205 }
206
207 void ODMRWidget::OnSweepSeriesParamChanged(int Index)
208 {
209 QDoubleSpinBox* Destiny = nullptr;
210
211 if (Index != 2) // != ODMRData::SweepSeriesType::AnalogOut
212 {
213 switch (Index)
214 {
215 case 0: // ODMRData::SweepSeriesType::RFModulationDepth
216 Destiny = ui->SBRFModulationDepth;
217 break;
218 case 1: // ODMRData::SweepSeriesType::RFPower
219 Destiny = ui->SBRFPower;
220 break;
221 }
222
223 if (Destiny)
224 {
225 ui->SBParamSweepStart->setMinimum(Destiny->minimum());
226 ui->SBParamSweepStart->setMaximum(Destiny->maximum());
227 ui->SBParamSweepStart->setSuffix(Destiny->suffix());
228 ui->SBParamSweepStop->setMinimum(Destiny->minimum());
229 ui->SBParamSweepStop->setMaximum(Destiny->maximum());
230 ui->SBParamSweepStop->setSuffix(Destiny->suffix());
231 ui->SBParamSweepStep->setMinimum(Destiny->minimum());
232 ui->SBParamSweepStep->setMaximum(Destiny->maximum());
233 ui->SBParamSweepStep->setSuffix(Destiny->suffix());
234 }
235 }
236 else
237 {
238 ui->SBParamSweepStart->setMinimum(AuxAnalogOutMinValue);
239 ui->SBParamSweepStart->setMaximum(AuxAnalogOutMaxValue);
240 ui->SBParamSweepStart->setSuffix(QString(" ") + DynExp::Units::UnitTypeToStr(AuxAnalogOutValueUnit));
241 ui->SBParamSweepStop->setMinimum(AuxAnalogOutMinValue);
242 ui->SBParamSweepStop->setMaximum(AuxAnalogOutMaxValue);
243 ui->SBParamSweepStop->setSuffix(ui->SBParamSweepStart->suffix());
244 ui->SBParamSweepStep->setMinimum(AuxAnalogOutMinValue);
245 ui->SBParamSweepStep->setMaximum(AuxAnalogOutMaxValue);
246 ui->SBParamSweepStep->setSuffix(ui->SBParamSweepStart->suffix());
247 }
248 }
249}
User interface belonging to the DynExpModule::ODMR::ODMR module.
Implementation of a module to perform optically detected magnetic resonance (ODMR) measurements.
DynExpQuick::DynExpLineGraphBackend * SensitivityGraph
Definition ODMRWidget.h:96
ODMRWidget(ODMR &Owner, QModuleWidget *parent=nullptr)
std::unique_ptr< Ui::ODMR > ui
Definition ODMRWidget.h:92
DynExpQuick::DynExpLineGraphBackend * ODMRGraph
Definition ODMRWidget.h:95
QModuleBase & Owner
Module owning this user interface window (reference, because it should never change nor be nullptr).
Definition Module.h:1486
QModuleWidget(QModuleBase &Owner, QWidget *Parent=nullptr)
Constructs a QModuleWidget instance.
Definition Module.cpp:451
State machine state as used by class StateMachine. A state mainly wraps a state function of the membe...
Definition Util.h:1363
constexpr StateEnumType GetState() const noexcept
Returns the state's unique identifier.
Definition Util.h:1379
Pointer to lock a class derived from ISynchronizedPointerLockable for synchronizing between threads....
Definition Util.h:171
Graph::LineGraphPlotInfo PlotInfo
Definition ODMRWidget.h:46
Graph::LineGraphPlotInfo PlotInfo
Definition ODMRWidget.h:54
constexpr auto StatusBarBusyStyleSheet
const char * UnitTypeToStr(UnitType Unit)
Returns a descriptive string of the given unit's type (e.g. 'dBm').
Definition Units.cpp:104
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:684
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.
void ReprocessSamples(const QList< QPointF > &Samples, const size_t SeriesIndex)
If data plotting is not enabled (running), the available and already plotted samples have to be repro...
void ResetHoveredSample()
Removes the stored hovered sample.