DynExp
Highly flexible laboratory automation for dynamically changing experiments.
Loading...
Searching...
No Matches
ODMR.cpp
Go to the documentation of this file.
1// This file is part of DynExp.
2
3#include "stdafx.h"
4#include "ui_ODMR.h"
5#include "ODMR.h"
6
8{
13
14 unsigned long long ODMRData::GetSweepNumberSteps() const noexcept
15 {
17 return 0;
18
19 return std::floor(std::abs(SweepSeriesStop - SweepSeriesStart) / SweepSeriesStep) + 1;
20 }
21
22 std::stringstream ODMRData::AssembleCSVHeader(double RFPower, double RFModulationDepth, double AuxAnalogOutValue, bool IsRFOffResonance)
23 {
24 std::stringstream CSVData;
25
26 CSVData << std::setprecision(6);
27 CSVData << "RFPower = " << RFPower << " " << GetRFGenerator()->GetValueUnitStr() << "\n";
28 CSVData << "RFCenterFreq = " << RFCenterFreq << " Hz\n";
29 CSVData << "RFFreqSpan = " << RFFreqSpan << " Hz\n";
30 CSVData << "RFFreqSpacing = " << RFFreqSpacing << " Hz\n";
31 CSVData << "RFDwellTime = " << RFDwellTime << " s\n";
32
33 CSVData << "RFModulation = ";
34 switch (RFModulation)
35 {
36 case RFModulationType::None: CSVData << "none\n"; break;
37 case RFModulationType::Sine: CSVData << "sine\n"; break;
38 case RFModulationType::Pulse: CSVData << "pulse\n"; break;
39 default: CSVData << "\n";
40 }
41 CSVData << "RFModulationFreq = " << RFModulationFreq << " Hz\n";
42 CSVData << "RFModulationDepth = " << RFModulationDepth << " Hz\n";
43
44 CSVData << "ODMRSamplingRate = " << ODMRSamplingRate << " samples/s\n";
45 CSVData << "CurrentSaveIndex = " << CurrentSaveIndex << "\n";
46
47 CSVData << "IsRFOffResonance = " << (IsRFOffResonance ? "yes" : "no") << "\n";
48 CSVData << "SensitivityEnabled = " << (SensitivityEnabled ? "yes" : "no") << "\n";
49 CSVData << "SensitivityOncePerSweep = " << (SensitivityOncePerSweep ? "yes" : "no") << "\n";
50 CSVData << "SensitivityOffResonanceEnabled = " << (SensitivityOffResonanceEnabled ? "yes" : "no") << "\n";
51 CSVData << "SensitivityResonanceFreq = " << SensitivityResonanceFreq << " Hz\n";
52 CSVData << "SensitivityOffResonanceFreq = " << SensitivityOffResonanceFreq << " Hz\n";
53 CSVData << "SensitivityResonanceSpan = " << SensitivityResonanceSpan << " Hz\n";
54 CSVData << "SensitivitySamplingRate = " << SensitivitySamplingRate << " samples/s\n";
55 CSVData << "SensitivityDuration = " << SensitivityDuration << " s\n";
56
57 CSVData << "SensitivityAnalysisEnabled = " << (SensitivityAnalysisEnabled ? "yes" : "no") << "\n";
58 CSVData << "GyromagneticRatio = " << GyromagneticRatio << " Hz/T\n";
59
60 CSVData << "SweepSeriesEnabled = " << (SweepSeriesEnabled ? "yes" : "no") << "\n";
61 CSVData << "SweepSeries = ";
62 switch (SweepSeries)
63 {
64 case SweepSeriesType::RFModulationDepth: CSVData << "RFModulationDepth\n"; break;
65 case SweepSeriesType::RFPower: CSVData << "RFPower\n"; break;
66 case SweepSeriesType::AnalogOut: CSVData << "AnalogOut\n"; break;
67 default: CSVData << "\n";
68 }
69 CSVData << "SweepSeriesStart = " << SweepSeriesStart << "\n";
70 CSVData << "SweepSeriesStop = " << SweepSeriesStop << "\n";
71 CSVData << "SweepSeriesStep = " << SweepSeriesStep << "\n";
72 CSVData << "SweepSeriesRetrace = " << (SweepSeriesRetrace ? "yes" : "no") << "\n";
73 CSVData << "SweepSeriesAdvanceLastValue = " << (SweepSeriesAdvanceLastValue ? "yes" : "no") << "\n";
74 CSVData << "CurrentSweepIndex = " << CurrentSweepIndex << "\n";
75 CSVData << "AuxAnalogOutValue = " << AuxAnalogOutValue << "\n";
76
78 {
79 auto& LockinInstr = dynamic_cast<const DynExpInstr::LockinAmplifier&>(*GetSignalDetector());
80 auto LockinData = DynExp::dynamic_InstrumentData_cast<DynExpInstr::LockinAmplifier>(GetSignalDetector()->GetInstrumentData());
81
82 auto Sensitivity = LockinData->GetSensitivity();
83 auto TimeConstant = LockinData->GetTimeConstant();
84 unsigned int FilterOrder = LockinData->GetFilterOrder();
85
86 CSVData << "LockinSensitivity = " << Sensitivity << " " << LockinInstr.GetSensitivityUnitString() << "\n";
87 CSVData << "LockinTimeConstant = " << TimeConstant << " s\n";
88 CSVData << "LockinFilterOrder = " << FilterOrder << "\n";
89 }
90
91 CSVData << "HEADER_END\n";
92
93 return CSVData;
94 }
95
97 {
98 RFPower = -10;
99 RFAutoEnabled = true;
100 RFCenterFreq = 2.87e9;
101 RFFreqSpan = 100e6;
102 RFFreqSpacing = 10e3;
103 RFDwellTime = 10e-3;
104
106 RFModulationFreq = 10e3;
107 RFModulationDepth = 1e6;
108
109 ODMRSamplingRate = .1e3;
110
112 SaveDataPath = "";
114 AutosaveEnabled = false;
115
116 SensitivityEnabled = false;
124
126 GyromagneticRatio = 28e9;
127
128 SweepSeriesEnabled = false;
130 SweepSeriesStart = 1e3;
131 SweepSeriesStop = 10e3;
132 SweepSeriesStep = .1e3;
133 SweepSeriesRetrace = true;
136
140
144
145 AcquisitionTime = 0.0;
146
150 ODMRPlot.PlotInfo.YLabel = "ODMR signal [V]";
156
157 Features = {};
158 }
159
160 ODMR::ODMR::ODMR(const std::thread::id OwnerThreadID, DynExp::ParamsBasePtrType&& Params)
161 : QModuleBase(OwnerThreadID, std::move(Params)),
162 StateMachine(InitializingState, ReadyState,
163 MeasurementSeriesStepState, MeasurementSeriesInitState,
164 ODMRTraceInitState, ODMRTraceWaitState, ODMRTraceFinishState,
165 SensitivityInitState, SensitivityWaitState, SensitivityFinishState)
166 {
167 }
168
169 std::chrono::milliseconds ODMR::ODMR::GetMainLoopDelay() const
170 {
171 auto CurrentState = StateMachine.GetCurrentState()->GetState();
172
173 // If doing some measurement, run much faster.
174 if (CurrentState == StateType::Ready)
175 return std::chrono::milliseconds(30);
176 else
177 return std::chrono::milliseconds(2);
178 }
179
181 {
182 try
183 {
184 auto ModuleData = DynExp::dynamic_ModuleData_cast<ODMR>(Instance.ModuleDataGetter());
185
187 {
188 auto LockinData = DynExp::dynamic_InstrumentData_cast<DynExpInstr::LockinAmplifier>(ModuleData->GetSignalDetector()->GetInstrumentData());
189
190 ModuleData->AcquisitionTime = LockinData->GetAcquisitionTime();
191 } // LockinData unlocked here.
192
193 StateMachine.Invoke(*this, Instance);
194
196 }
197 catch (const Util::TimeoutException& e)
198 {
199 if (NumFailedUpdateAttempts++ >= 3)
200 Instance.GetOwner().SetWarning(e);
201 }
202
204 }
205
216
217 std::unique_ptr<DynExp::QModuleWidget> ODMR::MakeUIWidget()
218 {
219 auto Widget = std::make_unique<ODMRWidget>(*this);
220
221 Connect(Widget->GetUI()->SBRFPower, QOverload<double>::of(&QDoubleSpinBox::valueChanged), this, &ODMR::OnRFPowerChanged);
222 Connect(Widget->GetUI()->CBRFAutoEnable, &QCheckBox::checkStateChanged, this, &ODMR::OnRFAutoEnableClicked);
223 Connect(Widget->GetUI()->SBRFCenter, QOverload<double>::of(&QDoubleSpinBox::valueChanged), this, &ODMR::OnRFCenterFreqChanged);
224 Connect(Widget->GetUI()->SBRFSpan, QOverload<double>::of(&QDoubleSpinBox::valueChanged), this, &ODMR::OnRFFreqSpanChanged);
225 Connect(Widget->GetUI()->SBRFFreqSpacing, QOverload<double>::of(&QDoubleSpinBox::valueChanged), this, &ODMR::OnRFFreqSpacingChanged);
226 Connect(Widget->GetUI()->SBRFDwellTime, QOverload<double>::of(&QDoubleSpinBox::valueChanged), this, &ODMR::OnRFDwellTimeChanged);
227
228 Connect(Widget->GetUI()->RBRFModulationTypeNone, &QRadioButton::clicked, this, &ODMR::OnRFModNoneClicked);
229 Connect(Widget->GetUI()->RBRFModulationTypeSine, &QRadioButton::clicked, this, &ODMR::OnRFModSineClicked);
230 Connect(Widget->GetUI()->RBRFModulationTypePulse, &QRadioButton::clicked, this, &ODMR::OnRFModPulseClicked);
231 Connect(Widget->GetUI()->SBRFModulationFreq, QOverload<double>::of(&QDoubleSpinBox::valueChanged), this, &ODMR::OnRFModFreqChanged);
232 Connect(Widget->GetUI()->SBRFModulationDepth, QOverload<double>::of(&QDoubleSpinBox::valueChanged), this, &ODMR::OnRFModDepthChanged);
233
234 Connect(Widget->GetUI()->SBDataAcquisitionODMRSamplingRate, QOverload<double>::of(&QDoubleSpinBox::valueChanged), this, &ODMR::OnODMRSamplingRateChanged);
235
236 Connect(Widget->GetUI()->LESaveDataPath, &QLineEdit::textChanged, this, &ODMR::OnSavePathChanged);
237 Connect(Widget->GetUI()->SBSaveDataCurrentIndex, QOverload<int>::of(&QSpinBox::valueChanged), this, &ODMR::OnSaveIndexChanged);
238 Connect(Widget->GetUI()->CBSaveDataEnable, &QCheckBox::checkStateChanged, this, &ODMR::OnAutosaveClicked);
239
240 Connect(Widget->GetUI()->CBSensitivityEnable, &QCheckBox::checkStateChanged, this, &ODMR::OnRecordSensitivityClicked);
241 Connect(Widget->GetUI()->CBSensitivityOncePerSweep, &QCheckBox::checkStateChanged, this, &ODMR::OnRecordSensitivityOncePerSweepClicked);
242 Connect(Widget->GetUI()->CBSensitivityOffResEnable, &QCheckBox::checkStateChanged, this, &ODMR::OnRecordSensitivityOffResonanceClicked);
243 Connect(Widget->GetUI()->SBSensitivityFreq, QOverload<double>::of(&QDoubleSpinBox::valueChanged), this, &ODMR::OnSensitivityResonanceFreqChanged);
244 Connect(Widget->GetUI()->SBSensitivityOffResFreq, QOverload<double>::of(&QDoubleSpinBox::valueChanged), this, &ODMR::OnSensitivityOffResonanceFreqChanged);
245 Connect(Widget->GetUI()->SBSensitivitySpan, QOverload<double>::of(&QDoubleSpinBox::valueChanged), this, &ODMR::OnSensitivityResonanceSpanChanged);
246 Connect(Widget->GetUI()->SBSensitivitySamplingRate, QOverload<double>::of(&QDoubleSpinBox::valueChanged), this, &ODMR::OnSensitivitySamplingRateChanged);
247 Connect(Widget->GetUI()->SBSensitivityDuration, QOverload<double>::of(&QDoubleSpinBox::valueChanged), this, &ODMR::OnSensitivityDurationChanged);
248
249 Connect(Widget->GetUI()->GBSensitivityAnalysis, &QGroupBox::toggled, this, &ODMR::OnEnableSensitivityAnalysisClicked);
250 Connect(Widget->GetUI()->SBGyromagneticRatio, QOverload<double>::of(&QDoubleSpinBox::valueChanged), this, &ODMR::OnGyromagneticRatioChanged);
251
252 Connect(Widget->GetUI()->CBParamSweepEnable, &QCheckBox::checkStateChanged, this, &ODMR::OnEnableSweepSeriesClicked);
253 Connect(Widget->GetUI()->CBParamSweepType, QOverload<int>::of(&QComboBox::currentIndexChanged), this, &ODMR::OnSweepSeriesParamChanged);
254 Connect(Widget->GetUI()->SBParamSweepStart, QOverload<double>::of(&QDoubleSpinBox::valueChanged), this, &ODMR::OnSweepSeriesStartChanged);
255 Connect(Widget->GetUI()->SBParamSweepStop, QOverload<double>::of(&QDoubleSpinBox::valueChanged), this, &ODMR::OnSweepSeriesStopChanged);
256 Connect(Widget->GetUI()->SBParamSweepStep, QOverload<double>::of(&QDoubleSpinBox::valueChanged), this, &ODMR::OnSweepSeriesStepChanged);
257 Connect(Widget->GetUI()->CBParamSweepRetrace, &QCheckBox::checkStateChanged, this, &ODMR::OnSweepSeriesRetraceClicked);
258 Connect(Widget->GetUI()->CBParamSweepAdvanceLastValue, &QCheckBox::checkStateChanged, this, &ODMR::OnSweepSeriesAdvanceLastValueClicked);
259
260 Connect(Widget->GetUI()->BStart, &QPushButton::clicked, this, &ODMR::OnStartClicked);
261 Connect(Widget->GetUI()->BStartSensitivity, &QPushButton::clicked, this, &ODMR::OnStartSensitivityClicked);
262 Connect(Widget->GetUI()->BStop, &QPushButton::clicked, this, &ODMR::OnStopClicked);
263 Connect(Widget->GetUI()->BRFOn, &QPushButton::clicked, this, &ODMR::OnRFOnClicked);
264 Connect(Widget->GetUI()->BRFOff, &QPushButton::clicked, this, &ODMR::OnRFOffClicked);
265
267
268 return Widget;
269 }
270
271 void ODMR::UpdateUIChild(const ModuleBase::ModuleDataGetterType& ModuleDataGetter)
272 {
273 auto Widget = GetWidget<ODMRWidget>();
274
275 {
276 auto ModuleData = DynExp::dynamic_ModuleData_cast<ODMR>(ModuleDataGetter());
277
278 if (StateMachine.GetCurrentState()->GetState() == StateType::Initializing)
279 return;
280
281 Widget->InitializeUI(ModuleData);
282 Widget->SetUIState(StateMachine.GetCurrentState(), ModuleData);
283 Widget->UpdateUIData(ModuleData);
284 Widget->UpdateODMRPlot(ModuleData->ODMRPlot);
285 Widget->UpdateSensitivityPlot(ModuleData->SensitivityPlot);
286 } // ModuleData unlocked here (heavy plot operations follow).
287 }
288
290 {
291 NextRFPower = ModuleData->RFPower;
292 NextRFModulationDepth = ModuleData->RFModulationDepth;
293 NextAuxAnalogOutValue = (ModuleData->AuxAnalogOutMinValue <= 0 && ModuleData->AuxAnalogOutMaxValue >= 0) ? 0 : ModuleData->AuxAnalogOutMinValue;
294
295 if (!ModuleData->SweepSeriesEnabled || !ModuleData->GetSweepNumberSteps())
296 return;
297
298 decltype(ModuleData->CurrentSweepIndex) SweepIndex = ModuleData->CurrentSweepIndex;
299 if (ModuleData->SweepSeriesAdvanceLastValue && SweepIndex == 1)
300 SweepIndex = ModuleData->GetSweepNumberSteps() - 1;
301 else if (ModuleData->SweepSeriesAdvanceLastValue && SweepIndex > 1)
302 --SweepIndex;
303
304 switch (ModuleData->SweepSeries)
305 {
307 NextRFModulationDepth = (ModuleData->SweepSeriesStart + SweepIndex * std::abs(ModuleData->SweepSeriesStep)) * 1e3;
308 break;
310 NextRFPower = ModuleData->SweepSeriesStart + SweepIndex * std::abs(ModuleData->SweepSeriesStep);
311 break;
313 NextAuxAnalogOutValue = ModuleData->SweepSeriesStart + SweepIndex * std::abs(ModuleData->SweepSeriesStep);
314 break;
315 }
316 }
317
332
334 {
336 ModuleData->GetAuxAnalogOut()->SetSync(NextAuxAnalogOutValue);
337 }
338
340 {
341 // Trigger on rising edge, so set to 0 now.
342 ModuleData->GetTrigger()->SetSync(0);
343
344 // Wait to ensure that trigger signal does not come too fast
345 std::this_thread::sleep_for(std::chrono::milliseconds(200));
346
347 // Prepare acquisition.
348 ModuleData->GetSignalDetector()->Stop();
349 ModuleData->GetSignalDetector()->Clear();
350 ModuleData->GetSignalDetector()->Start();
351
352 // Wait until every involved instrument is ready.
353 DynExp::WaitForInstruments(*ModuleData->GetRFGenerator(), *ModuleData->GetSignalDetector(), *ModuleData->GetTrigger());
354
355 // Trigger RF sweep and data acquisition now.
356 ModuleData->GetTrigger()->SetSync(1);
357 }
358
360 {
361 auto ModuleParams = DynExp::dynamic_Params_cast<ODMR>(Instance->ParamsGetter());
362 auto ModuleData = DynExp::dynamic_ModuleData_cast<ODMR>(Instance->ModuleDataGetter());
363
364 Instance->LockObject(ModuleParams->RFGenerator, ModuleData->GetRFGenerator());
365 Instance->LockObject(ModuleParams->SignalDetector, ModuleData->GetSignalDetector());
366 Instance->LockObject(ModuleParams->TriggerOut, ModuleData->GetTrigger());
367
368 ModuleData->RFGeneratorMinFuncDesc = ModuleData->GetRFGenerator()->GetMinCaps();
369 ModuleData->RFGeneratorMaxFuncDesc = ModuleData->GetRFGenerator()->GetMaxCaps();
370 ModuleData->RFGeneratorDefaultFuncDesc = ModuleData->GetRFGenerator()->GetParamDefaults();
371
372 if (dynamic_cast<const DynExpInstr::LockinAmplifier*>(ModuleData->GetSignalDetector().get()))
374 else if (dynamic_cast<const DynExpInstr::AnalogIn*>(ModuleData->GetSignalDetector().get()))
376 ModuleData->GetSignalDetector()->Stop();
377
378 if (ModuleParams->AuxAnalogOut.ContainsID())
379 {
380 Instance->LockObject(ModuleParams->AuxAnalogOut, ModuleData->GetAuxAnalogOut());
382
383 ModuleData->AuxAnalogOutValueUnit = ModuleData->GetAuxAnalogOut()->GetValueUnit();
384 ModuleData->AuxAnalogOutMinValue = ModuleData->GetAuxAnalogOut()->GetUserMinValue();
385 ModuleData->AuxAnalogOutMaxValue = ModuleData->GetAuxAnalogOut()->GetUserMaxValue();
386 }
387 }
388
390 {
391 auto ModuleData = DynExp::dynamic_ModuleData_cast<ODMR>(Instance->ModuleDataGetter());
392
393 Instance->UnlockObject(ModuleData->GetRFGenerator());
394 Instance->UnlockObject(ModuleData->GetSignalDetector());
395 Instance->UnlockObject(ModuleData->GetTrigger());
396 Instance->UnlockObject(ModuleData->GetAuxAnalogOut());
397 }
398
399 void ODMR::OnRFPowerChanged(DynExp::ModuleInstance* Instance, double Value) const
400 {
401 auto ModuleData = DynExp::dynamic_ModuleData_cast<ODMR>(Instance->ModuleDataGetter());
402 ModuleData->RFPower = Value;
403 }
404
405 void ODMR::OnRFAutoEnableClicked(DynExp::ModuleInstance* Instance, Qt::CheckState Checked) const
406 {
407 auto ModuleData = DynExp::dynamic_ModuleData_cast<ODMR>(Instance->ModuleDataGetter());
408 ModuleData->RFAutoEnabled = Checked == Qt::CheckState::Checked;
409 }
410
411 void ODMR::OnRFCenterFreqChanged(DynExp::ModuleInstance* Instance, double Value) const
412 {
413 auto ModuleData = DynExp::dynamic_ModuleData_cast<ODMR>(Instance->ModuleDataGetter());
414 ModuleData->RFCenterFreq = Value * 1e6;
415 }
416
417 void ODMR::OnRFFreqSpanChanged(DynExp::ModuleInstance* Instance, double Value) const
418 {
419 auto ModuleData = DynExp::dynamic_ModuleData_cast<ODMR>(Instance->ModuleDataGetter());
420 ModuleData->RFFreqSpan = Value * 1e6;
421 }
422
423 void ODMR::OnRFFreqSpacingChanged(DynExp::ModuleInstance* Instance, double Value) const
424 {
425 auto ModuleData = DynExp::dynamic_ModuleData_cast<ODMR>(Instance->ModuleDataGetter());
426 ModuleData->RFFreqSpacing = Value * 1e3;
427 }
428
429 void ODMR::OnRFDwellTimeChanged(DynExp::ModuleInstance* Instance, double Value) const
430 {
431 auto ModuleData = DynExp::dynamic_ModuleData_cast<ODMR>(Instance->ModuleDataGetter());
432 ModuleData->RFDwellTime = Value * 1e-3;
433 }
434
435 void ODMR::OnRFModNoneClicked(DynExp::ModuleInstance* Instance, bool Checked) const
436 {
437 auto ModuleData = DynExp::dynamic_ModuleData_cast<ODMR>(Instance->ModuleDataGetter());
438
439 if (Checked)
441 }
442
443 void ODMR::OnRFModSineClicked(DynExp::ModuleInstance* Instance, bool Checked) const
444 {
445 auto ModuleData = DynExp::dynamic_ModuleData_cast<ODMR>(Instance->ModuleDataGetter());
446
447 if (Checked)
449 }
450
451 void ODMR::OnRFModPulseClicked(DynExp::ModuleInstance* Instance, bool Checked) const
452 {
453 auto ModuleData = DynExp::dynamic_ModuleData_cast<ODMR>(Instance->ModuleDataGetter());
454
455 if (Checked)
457 }
458
459 void ODMR::OnRFModFreqChanged(DynExp::ModuleInstance* Instance, double Value) const
460 {
461 auto ModuleData = DynExp::dynamic_ModuleData_cast<ODMR>(Instance->ModuleDataGetter());
462 ModuleData->RFModulationFreq = Value * 1e3;
463 }
464
465 void ODMR::OnRFModDepthChanged(DynExp::ModuleInstance* Instance, double Value) const
466 {
467 auto ModuleData = DynExp::dynamic_ModuleData_cast<ODMR>(Instance->ModuleDataGetter());
468 ModuleData->RFModulationDepth = Value * 1e3;
469 }
470
471 void ODMR::OnODMRSamplingRateChanged(DynExp::ModuleInstance* Instance, double Value) const
472 {
473 auto ModuleData = DynExp::dynamic_ModuleData_cast<ODMR>(Instance->ModuleDataGetter());
474 ModuleData->ODMRSamplingRate = Value;
475 }
476
477 void ODMR::OnSavePathChanged(DynExp::ModuleInstance* Instance, QString Path) const
478 {
479 auto ModuleData = DynExp::dynamic_ModuleData_cast<ODMR>(Instance->ModuleDataGetter());
480 ModuleData->SaveDataPath = Path.toStdString();
481 }
482
483 void ODMR::OnSaveIndexChanged(DynExp::ModuleInstance* Instance, int Index) const
484 {
485 auto ModuleData = DynExp::dynamic_ModuleData_cast<ODMR>(Instance->ModuleDataGetter());
486 ModuleData->CurrentSaveIndex = Index;
487 }
488
489 void ODMR::OnAutosaveClicked(DynExp::ModuleInstance* Instance, Qt::CheckState Checked) const
490 {
491 auto ModuleData = DynExp::dynamic_ModuleData_cast<ODMR>(Instance->ModuleDataGetter());
492 ModuleData->AutosaveEnabled = Checked == Qt::CheckState::Checked;
493 }
494
495 void ODMR::OnRecordSensitivityClicked(DynExp::ModuleInstance* Instance, Qt::CheckState Checked) const
496 {
497 auto ModuleData = DynExp::dynamic_ModuleData_cast<ODMR>(Instance->ModuleDataGetter());
498 ModuleData->SensitivityEnabled = Checked == Qt::CheckState::Checked;
499 }
500
501 void ODMR::OnRecordSensitivityOncePerSweepClicked(DynExp::ModuleInstance* Instance, Qt::CheckState Checked) const
502 {
503 auto ModuleData = DynExp::dynamic_ModuleData_cast<ODMR>(Instance->ModuleDataGetter());
504 ModuleData->SensitivityOncePerSweep = Checked == Qt::CheckState::Checked;
505 }
506
507 void ODMR::OnRecordSensitivityOffResonanceClicked(DynExp::ModuleInstance* Instance, Qt::CheckState Checked) const
508 {
509 auto ModuleData = DynExp::dynamic_ModuleData_cast<ODMR>(Instance->ModuleDataGetter());
510 ModuleData->SensitivityOffResonanceEnabled = Checked == Qt::CheckState::Checked;
511 }
512
514 {
515 auto ModuleData = DynExp::dynamic_ModuleData_cast<ODMR>(Instance->ModuleDataGetter());
516 ModuleData->SensitivityResonanceFreq = Value * 1e6;
517 }
518
520 {
521 auto ModuleData = DynExp::dynamic_ModuleData_cast<ODMR>(Instance->ModuleDataGetter());
522 ModuleData->SensitivityOffResonanceFreq = Value * 1e6;
523 }
524
526 {
527 auto ModuleData = DynExp::dynamic_ModuleData_cast<ODMR>(Instance->ModuleDataGetter());
528 ModuleData->SensitivityResonanceSpan = Value * 1e6;
529 }
530
532 {
533 auto ModuleData = DynExp::dynamic_ModuleData_cast<ODMR>(Instance->ModuleDataGetter());
534 ModuleData->SensitivitySamplingRate = Value;
535 }
536
538 {
539 auto ModuleData = DynExp::dynamic_ModuleData_cast<ODMR>(Instance->ModuleDataGetter());
540 ModuleData->SensitivityDuration = Value;
541 }
542
544 {
545 auto ModuleData = DynExp::dynamic_ModuleData_cast<ODMR>(Instance->ModuleDataGetter());
546 ModuleData->SensitivityAnalysisEnabled = Checked;
547 }
548
550 {
551 auto ModuleData = DynExp::dynamic_ModuleData_cast<ODMR>(Instance->ModuleDataGetter());
552 ModuleData->GyromagneticRatio = Value * 1e6;
553 }
554
555 void ODMR::OnEnableSweepSeriesClicked(DynExp::ModuleInstance* Instance, Qt::CheckState Checked) const
556 {
557 auto ModuleData = DynExp::dynamic_ModuleData_cast<ODMR>(Instance->ModuleDataGetter());
558 ModuleData->SweepSeriesEnabled = Checked == Qt::CheckState::Checked;
559 }
560
562 {
563 auto ModuleData = DynExp::dynamic_ModuleData_cast<ODMR>(Instance->ModuleDataGetter());
564
565 switch (Index)
566 {
567 case 0: ModuleData->SweepSeries = ODMRData::SweepSeriesType::RFModulationDepth; break;
568 case 1: ModuleData->SweepSeries = ODMRData::SweepSeriesType::RFPower; break;
569 case 2:
572 break;
573 }
574 }
575
576 void ODMR::OnSweepSeriesStartChanged(DynExp::ModuleInstance* Instance, double Value) const
577 {
578 auto ModuleData = DynExp::dynamic_ModuleData_cast<ODMR>(Instance->ModuleDataGetter());
579 ModuleData->SweepSeriesStart = Value;
580 }
581
582 void ODMR::OnSweepSeriesStopChanged(DynExp::ModuleInstance* Instance, double Value) const
583 {
584 auto ModuleData = DynExp::dynamic_ModuleData_cast<ODMR>(Instance->ModuleDataGetter());
585 ModuleData->SweepSeriesStop = Value;
586 }
587
588 void ODMR::OnSweepSeriesStepChanged(DynExp::ModuleInstance* Instance, double Value) const
589 {
590 auto ModuleData = DynExp::dynamic_ModuleData_cast<ODMR>(Instance->ModuleDataGetter());
591 ModuleData->SweepSeriesStep = Value;
592 }
593
594 void ODMR::OnSweepSeriesRetraceClicked(DynExp::ModuleInstance* Instance, Qt::CheckState Checked) const
595 {
596 auto ModuleData = DynExp::dynamic_ModuleData_cast<ODMR>(Instance->ModuleDataGetter());
597 ModuleData->SweepSeriesRetrace = Checked == Qt::CheckState::Checked;
598 }
599
600 void ODMR::OnSweepSeriesAdvanceLastValueClicked(DynExp::ModuleInstance* Instance, Qt::CheckState Checked) const
601 {
602 auto ModuleData = DynExp::dynamic_ModuleData_cast<ODMR>(Instance->ModuleDataGetter());
603 ModuleData->SweepSeriesAdvanceLastValue = Checked == Qt::CheckState::Checked;
604 }
605
607 {
608 if (!IsReadyState())
609 return;
610
612
613 auto ModuleData = DynExp::dynamic_ModuleData_cast<ODMR>(Instance->ModuleDataGetter());
615 }
616
618 {
619 if (!IsReadyState())
620 return;
621
623
624 auto ModuleData = DynExp::dynamic_ModuleData_cast<ODMR>(Instance->ModuleDataGetter());
626 }
627
628 void ODMR::OnStopClicked(DynExp::ModuleInstance* Instance, bool) const
629 {
630 auto ModuleData = DynExp::dynamic_ModuleData_cast<ODMR>(Instance->ModuleDataGetter());
631
632 if (ModuleData->RFAutoEnabled)
633 ModuleData->GetRFGenerator()->Stop();
634 ModuleData->GetSignalDetector()->Stop();
635
636 StateMachine.ResetContext();
637 StateMachine.SetCurrentState(StateType::Ready);
638 }
639
640 void ODMR::OnRFOnClicked(DynExp::ModuleInstance* Instance, bool) const
641 {
642 auto ModuleData = DynExp::dynamic_ModuleData_cast<ODMR>(Instance->ModuleDataGetter());
643 ModuleData->GetRFGenerator()->Start();
644 }
645
647 {
648 auto ModuleData = DynExp::dynamic_ModuleData_cast<ODMR>(Instance->ModuleDataGetter());
649 ModuleData->GetRFGenerator()->Stop();
650 }
651
652 void ODMR::OnODMRGraphClicked(DynExp::ModuleInstance* Instance, QPointF Point) const
653 {
654 if (Point.isNull())
655 return;
656
657 auto ModuleData = DynExp::dynamic_ModuleData_cast<ODMR>(Instance->ModuleDataGetter());
658 ModuleData->GetRFGenerator()->SetSineFunction({ Point.x() * 1e9 , ModuleData->RFPower, 0, 0});
659 }
660
665
670
672 {
673 auto ModuleData = DynExp::dynamic_ModuleData_cast<ODMR>(Instance.ModuleDataGetter());
674
675 ModuleData->CurrentSweepIndex = 0;
677
679 {
680 auto LockinAmplifier = ModuleData->GetLockinAmplifier();
682 LockinAmplifier->SetTriggerEdge(DynExpInstr::LockinAmplifierDefs::TriggerEdgeType::Rise);
683 LockinAmplifier->SetEnable(true);
684 }
685
687 }
688
690 {
691 auto ModuleData = DynExp::dynamic_ModuleData_cast<ODMR>(Instance.ModuleDataGetter());
692
693 if (!ModuleData->SweepSeriesEnabled || ++ModuleData->CurrentSweepIndex >= ModuleData->GetSweepNumberSteps())
694 {
695 ++ModuleData->CurrentSaveIndex;
696
697 if (ModuleData->SweepSeriesEnabled && ModuleData->SweepSeriesRetrace)
698 {
699 ModuleData->CurrentSweepIndex = 0;
701
703 InitRFGenerator(ModuleData->GetRFStartFreq(), false, ModuleData);
704 }
705 if (ModuleData->RFAutoEnabled)
706 ModuleData->GetRFGenerator()->Stop();
707
708 return StateType::Ready;
709 }
710
712
714 }
715
717 {
718 auto ModuleData = DynExp::dynamic_ModuleData_cast<ODMR>(Instance.ModuleDataGetter());
719
721 InitRFGenerator(ModuleData->GetRFStartFreq(), ModuleData->RFAutoEnabled, ModuleData);
722 ModuleData->GetRFGenerator()->SetSweep({
724 ModuleData->GetRFStartFreq(),
725 ModuleData->GetRFStopFreq(),
726 ModuleData->RFFreqSpacing,
727 ModuleData->RFDwellTime * 1000,
728 true
729 });
730 ModuleData->GetRFGenerator()->SetTrigger({
733 });
734
736 {
737 auto LockinAmplifier = ModuleData->GetLockinAmplifier();
738 LockinAmplifier->SetStreamSize(ModuleData->RFDwellTime * ModuleData->GetNumSamples() * ModuleData->ODMRSamplingRate);
739 LockinAmplifier->SetSamplingRate(ModuleData->ODMRSamplingRate);
740 }
741
743
745 }
746
748 {
749 auto ModuleData = DynExp::dynamic_ModuleData_cast<ODMR>(Instance.ModuleDataGetter());
750
751 return ModuleData->GetSignalDetector()->HasFinished() ? StateType::ODMRTraceFinish : StateType::ODMRTraceWait;
752 }
753
755 {
756 std::vector<std::tuple<double, double, double>> SaveSamples;
757 bool Save = false;
758 bool PerformSensitivityMeasurement = false;
759 double RFStartFreq{};
760 decltype(ODMRData::RFDwellTime) RFDwellTime{};
761 decltype(ODMRData::RFFreqSpacing) RFFreqSpacing{};
762 bool IsBasicSampleTimeUsed{};
763 double SamplingRate{ .0 };
765 decltype(ODMRPlotType::DataPoints) ODMRDataPoints, ProcessedODMRDataPoints;
766 decltype(ODMRData::SensitivityResonanceFreq) SensitivityResonanceFreq{};
767 decltype(ODMRData::SensitivityResonanceSpan) SensitivityResonanceSpan{};
768 decltype(ODMRPlotType::FitParams) ODMRFitParams{};
769 decltype(ODMRPlotType::FitPoints) ODMRFitPoints, ProcessedODMRFitPoints;
770 decltype(ODMRPlotType::PlotInfo) ODMRPlotInfo;
771 std::vector<double> FitXData;
772 std::vector<double> FitYData;
773 std::string Filename;
774 std::string ValueUnitStr;
775 std::stringstream CSVData;
776
777 {
778 auto ModuleData = DynExp::dynamic_ModuleData_cast<ODMR>(Instance.ModuleDataGetter());
779
780 if (!ModuleData->GetSignalDetector()->CanRead())
782
783 Save = ModuleData->AutosaveEnabled;
784 PerformSensitivityMeasurement = ModuleData->SensitivityEnabled && (!ModuleData->SensitivityOncePerSweep || !ModuleData->CurrentSweepIndex);
785 RFStartFreq = ModuleData->GetRFStartFreq();
786 RFDwellTime = ModuleData->RFDwellTime;
787 RFFreqSpacing = ModuleData->RFFreqSpacing;
788 SensitivityResonanceFreq = ModuleData->SensitivityResonanceFreq;
789 SensitivityResonanceSpan = ModuleData->SensitivityResonanceSpan;
790 ODMRPlotInfo = ModuleData->ODMRPlot.PlotInfo;
791
792 auto SignalDetectorData = DynExp::dynamic_InstrumentData_cast<DynExpInstr::DataStreamInstrument>(ModuleData->GetSignalDetector()->GetInstrumentData());
793 SignalDetectorData->GetSampleStream()->SeekBeg(std::ios_base::in);
794 ODMRSamples = SignalDetectorData->GetSampleStream()->ReadBasicSamples(SignalDetectorData->GetSampleStream()->GetStreamSizeRead());
795
796 IsBasicSampleTimeUsed = SignalDetectorData->GetSampleStream()->IsBasicSampleTimeUsed();
797 if (!IsBasicSampleTimeUsed && ModuleData->TestFeature(ODMRData::FeatureType::AnalogInDetection))
798 {
799 SamplingRate = ModuleData->GetAnalogIn()->GetNumericSampleStreamParams().SamplingRate;
800
801 if (SamplingRate == .0)
802 throw Util::InvalidDataException("The analog input channel's sampling rate must not be 0.");
803 }
804
805 } // ModuleData unlocked here (heavy calculation follows).
806
807 for (size_t i = 0; i < ODMRSamples.size(); ++i)
808 {
809 const auto& Sample = ODMRSamples[i];
810
811 auto Frequency = RFStartFreq + (IsBasicSampleTimeUsed ? Sample.Time : (static_cast<double>(i) / SamplingRate)) / RFDwellTime * RFFreqSpacing;
812 ODMRDataPoints.push_back({ Frequency / 1e9, Sample.Value });
813 if (Save)
814 SaveSamples.emplace_back(std::make_tuple(Frequency, Sample.Time, Sample.Value));
815
816 if (PerformSensitivityMeasurement &&
817 Frequency >= SensitivityResonanceFreq - SensitivityResonanceSpan / 2 &&
818 Frequency <= SensitivityResonanceFreq + SensitivityResonanceSpan / 2)
819 {
820 FitXData.push_back(Frequency - SensitivityResonanceFreq);
821 FitYData.push_back(Sample.Value);
822 }
823 }
824
825 if (PerformSensitivityMeasurement)
826 {
827 double c0{0}, c1{0}, cov00{0}, cov01{0}, cov11{0}, chisq{0};
828 gsl_fit_linear(FitXData.data(), 1, FitYData.data(), 1, FitXData.size(), &c0, &c1, &cov00, &cov01, &cov11, &chisq);
829 ODMRFitParams = { c0, c1 };
830
831 for (const auto& f : FitXData)
832 ODMRFitPoints.push_back({ (f + SensitivityResonanceFreq) / 1e9, c0 + c1 * f });
833 }
834
835 ODMRPlotInfo.Reset();
836 ODMRPlotInfo.ProcessSamples(ODMRDataPoints, ProcessedODMRDataPoints, 0);
837 ODMRPlotInfo.ProcessSamples(ODMRFitPoints, ProcessedODMRFitPoints, 1);
838 ODMRPlotInfo.AdjustAxesLimits();
839
840 {
841 auto ModuleData = DynExp::dynamic_ModuleData_cast<ODMR>(Instance.ModuleDataGetter());
842
843 ModuleData->ODMRPlot.DataPoints = std::move(ProcessedODMRDataPoints);
844 ModuleData->ODMRPlot.FitPoints = std::move(ProcessedODMRFitPoints);
845 ModuleData->ODMRPlot.FitParams = ODMRFitParams;
846 ModuleData->ODMRPlot.HasChanged = true;
847 ModuleData->ODMRPlot.PlotInfo = ODMRPlotInfo;
848
849 Filename = Util::RemoveExtFromPath(ModuleData->SaveDataPath) + "_ODMR" + Util::ToStr(ModuleData->CurrentSaveIndex) + "_Sweep" + Util::ToStr(ModuleData->CurrentSweepIndex) + ".csv";
850 ValueUnitStr = ModuleData->GetSignalDetector()->GetValueUnitStr();
851
852 if (Save)
853 CSVData = ModuleData->AssembleCSVHeader(NextRFPower, NextRFModulationDepth, NextAuxAnalogOutValue, false);
854 } // ModuleData unlocked here.
855
856 if (Save)
857 {
858 CSVData << "f(Hz);t(s);Value(" << ValueUnitStr << ")\n";
859 for (const auto& Sample : SaveSamples)
860 CSVData << std::get<0>(Sample) << ";" << std::get<1>(Sample) << ";" << std::get<2>(Sample) << "\n";
861
862 Util::SaveToFile(QString::fromStdString(Filename), CSVData.str());
863 }
864
865 return PerformSensitivityMeasurement ? StateType::SensitivityInit : StateType::MeasurementSeriesStep;
866 }
867
868 StateType ODMR::SensitivityInitFunc(DynExp::ModuleInstance& Instance)
869 {
870 auto ModuleData = DynExp::dynamic_ModuleData_cast<ODMR>(Instance.ModuleDataGetter());
871
872 // No sensitivity calculation if detection is not performed with a lock-in amplifer since in this case it is not possible
873 // to measure the ODMR signal's derivative directly.
874 if (!ModuleData->TestFeature(ODMRData::FeatureType::LockinDetection))
875 {
876 StateMachine.ResetContext();
877 return StateType::MeasurementSeriesStep;
878 }
879
880 SetAuxAnalogOutValue(ModuleData);
881 ModuleData->GetRFGenerator()->SetSweep({}); // Disable sweep.
882 ModuleData->GetRFGenerator()->SetTrigger({}); // Disable trigger.
883 auto RFFreq = StateMachine.GetContext() == &SensitivityOffResonanceContext ? ModuleData->SensitivityOffResonanceFreq : ModuleData->SensitivityResonanceFreq;
884 InitRFGenerator(RFFreq, ModuleData->RFAutoEnabled, ModuleData);
885
886 auto LockinAmplifier = ModuleData->GetLockinAmplifier();
887 LockinAmplifier->SetStreamSize(ModuleData->SensitivityDuration * ModuleData->SensitivitySamplingRate);
888 LockinAmplifier->SetSamplingRate(ModuleData->SensitivitySamplingRate);
889
890 WaitUntilReadyAndTrigger(ModuleData);
891
892 return StateType::SensitivityWait;
893 }
894
895 StateType ODMR::SensitivityWaitFunc(DynExp::ModuleInstance& Instance)
896 {
897 auto ModuleData = DynExp::dynamic_ModuleData_cast<ODMR>(Instance.ModuleDataGetter());
898
899 return ModuleData->GetSignalDetector()->HasFinished() ? StateType::SensitivityFinish : StateType::SensitivityWait;
900 }
901
902 StateType ODMR::SensitivityFinishFunc(DynExp::ModuleInstance& Instance)
903 {
904 std::vector<std::tuple<double, double>> SaveSamples;
905 ODMRData::MeasurementModeType MeasurementMode = ODMRData::MeasurementModeType::All;
906 bool Save = false;
907 bool SensitivityOffResonanceEnabled = false;
908 bool SensitivityAnalysisEnabled = false;
909 decltype(ODMRPlotType::FitParams) ODMRFitParams{};
910 decltype(ODMRData::GyromagneticRatio) GyromagneticRatio{};
912 std::vector<std::complex<double>> SensitivityASD;
913 decltype(SensitivityPlotType::DataPoints) SensitivityDataPoints, ProcessedSensitivityDataPoints;
914 decltype(SensitivityPlotType::PlotInfo) SensitivityPlotInfo;
915 std::string Filename;
916 std::string FilenamePrefix;
917 std::string ValueUnitStr;
918 std::stringstream CSVData;
919
920 {
921 auto ModuleData = DynExp::dynamic_ModuleData_cast<ODMR>(Instance.ModuleDataGetter());
922
923 if (!ModuleData->GetSignalDetector()->CanRead())
924 return StateType::SensitivityFinish;
925
926 MeasurementMode = ModuleData->MeasurementMode;
927 Save = ModuleData->AutosaveEnabled;
928 SensitivityOffResonanceEnabled = ModuleData->SensitivityOffResonanceEnabled;
929 SensitivityAnalysisEnabled = ModuleData->SensitivityAnalysisEnabled;
930 ODMRFitParams = ModuleData->ODMRPlot.FitParams;
931 GyromagneticRatio = ModuleData->GyromagneticRatio;
932 SensitivityPlotInfo = ModuleData->SensitivityPlot.PlotInfo;
933
934 auto SignalDetectorData = DynExp::dynamic_InstrumentData_cast<DynExpInstr::DataStreamInstrument>(ModuleData->GetSignalDetector()->GetInstrumentData());
935 SignalDetectorData->GetSampleStream()->SeekBeg(std::ios_base::in);
936 SensitivitySamples = SignalDetectorData->GetSampleStream()->ReadBasicSamples(SignalDetectorData->GetSampleStream()->GetStreamSizeRead());
937 } // ModuleData unlocked here (heavy calculation follows).
938
939 for (const auto& Sample : SensitivitySamples)
940 {
941 SaveSamples.emplace_back(std::make_tuple(Sample.Time, Sample.Value));
942
943 if (MeasurementMode == ODMRData::MeasurementModeType::All && StateMachine.GetContext() != &SensitivityOffResonanceContext)
944 SensitivityASD.emplace_back(Sample.Value / std::get<1>(ODMRFitParams) / GyromagneticRatio, 0);
945 }
946
947 if (SensitivityASD.size() > 2 && SensitivityAnalysisEnabled && StateMachine.GetContext() != &SensitivityOffResonanceContext)
948 {
949 const auto Length = static_cast<double>(SensitivityASD.size());
950
951 SensitivityASD = Util::FFT(SensitivityASD);
952 std::transform(SensitivityASD.cbegin(), SensitivityASD.cend(), SensitivityASD.begin(), [Length](auto x) { return std::abs(x / Length); });
953
954 // Make single-sided spectrum
955 SensitivityASD.erase(SensitivityASD.cbegin() + SensitivityASD.size() / 2 + 1, SensitivityASD.cend());
956 std::transform(SensitivityASD.cbegin() + 1, SensitivityASD.cend(), SensitivityASD.begin() + 1, [Length](auto x) { return 2.0 * x; });
957
958 // Assume SensitivitySamples sorted by Time. Assume samples equally spaced in time.
959 double TimeSamplingRate = 1 / (std::abs(SensitivitySamples.back().Time - SensitivitySamples.front().Time) / (SensitivitySamples.size() - 1));
960 std::vector<double> Frequencies(Length / 2 + 1, 0);
961 std::iota(Frequencies.begin(), Frequencies.end(), 0);
962 std::transform(Frequencies.cbegin(), Frequencies.cend(), Frequencies.begin(), [TimeSamplingRate, Length](auto x) { return TimeSamplingRate * x / Length; });
963
964 double FrequencySamplingRate = std::abs(Frequencies.back() - Frequencies.front()) / (Frequencies.size() - 1);
965 std::transform(SensitivityASD.cbegin(), SensitivityASD.cend(), SensitivityASD.begin(), [FrequencySamplingRate](auto x) { return x / std::sqrt(FrequencySamplingRate); });
966
967 if (SensitivityASD.size() == Frequencies.size())
968 for (size_t i = 1; i < SensitivityASD.size(); ++i) // Ignore 0 Hz frequency component
969 SensitivityDataPoints.push_back({ Frequencies[i], SensitivityASD[i].real() });
970 }
971
972 SensitivityPlotInfo.Reset();
973 SensitivityPlotInfo.ProcessSamples(SensitivityDataPoints, ProcessedSensitivityDataPoints, 0);
974 SensitivityPlotInfo.AdjustAxesLimits();
975
976 {
977 auto ModuleData = DynExp::dynamic_ModuleData_cast<ODMR>(Instance.ModuleDataGetter());
978
979 if (StateMachine.GetContext() != &SensitivityOffResonanceContext)
980 {
981 ModuleData->SensitivityPlot.DataPoints = std::move(ProcessedSensitivityDataPoints);
982 ModuleData->SensitivityPlot.HasChanged = true;
983 ModuleData->SensitivityPlot.PlotInfo = SensitivityPlotInfo;
984
985 FilenamePrefix = "Sensitivity";
986 }
987 else
988 FilenamePrefix = "OffResSensitivity";
989
990 Filename = Util::RemoveExtFromPath(ModuleData->SaveDataPath) + "_" + FilenamePrefix + Util::ToStr(ModuleData->CurrentSaveIndex) + "_Sweep" + Util::ToStr(ModuleData->CurrentSweepIndex) + ".csv";
991 ValueUnitStr = ModuleData->GetSignalDetector()->GetValueUnitStr();
992
993 if (Save)
994 CSVData = ModuleData->AssembleCSVHeader(NextRFPower, NextRFModulationDepth, NextAuxAnalogOutValue, StateMachine.GetContext() == &SensitivityOffResonanceContext);
995 } // ModuleData unlocked here.
996
997 if (Save)
998 {
999 CSVData << "t(s);Value(" << ValueUnitStr << ")\n";
1000 CSVData << std::setprecision(12);
1001 for (const auto& Sample : SaveSamples)
1002 CSVData << std::get<0>(Sample) << ";" << std::get<1>(Sample) << "\n";
1003
1004 Util::SaveToFile(QString::fromStdString(Filename), CSVData.str());
1005 }
1006
1007 if (SensitivityOffResonanceEnabled)
1008 {
1009 if (StateMachine.GetContext() == &SensitivityOffResonanceContext)
1010 StateMachine.ResetContext();
1011 else
1012 {
1013 StateMachine.SetContext(&SensitivityOffResonanceContext);
1014 return StateType::SensitivityInit;
1015 }
1016 }
1017
1018 return StateType::MeasurementSeriesStep;
1019 }
1020}
Implementation of a module to perform optically detected magnetic resonance (ODMR) measurements.
Meta instrument for a single analog input port based on the data stream and generic input port meta i...
Definition AnalogIn.h:136
std::vector< BasicSample > BasicSampleListType
Type of a list containing data stream samples of type BasicSample.
Meta instrument for a lock-in amplifier based on the data stream meta instrument.
DynExpInstr::DataStreamInstrumentData::ValueType AuxAnalogOutMinValue
Definition ODMR.h:97
double SensitivityResonanceFreq
Definition ODMR.h:74
std::stringstream AssembleCSVHeader(double RFPower, double RFModulationDepth, double AuxAnalogOutValue, bool IsRFOffResonance)
Definition ODMR.cpp:22
bool TestFeature(const std::array< FeatureType, N > &Flags) const
Definition ODMR.h:35
SweepSeriesType SweepSeries
Definition ODMR.h:84
auto & GetRFGenerator() noexcept
Definition ODMR.h:40
std::string SaveDataPath
Definition ODMR.h:67
unsigned long long CurrentSweepIndex
Definition ODMR.h:90
SensitivityPlotType SensitivityPlot
Definition ODMR.h:103
DynExpInstr::FunctionGeneratorDefs::FunctionDescType RFGeneratorMaxFuncDesc
Definition ODMR.h:93
double SensitivityResonanceSpan
Definition ODMR.h:76
Util::FeatureTester< FeatureType > Features
Definition ODMR.h:116
DynExp::Units::UnitType AuxAnalogOutValueUnit
Definition ODMR.h:96
double SensitivityOffResonanceFreq
Definition ODMR.h:75
unsigned long long GetSweepNumberSteps() const noexcept
Definition ODMR.cpp:14
unsigned int CurrentSaveIndex
Definition ODMR.h:68
MeasurementModeType MeasurementMode
Definition ODMR.h:66
DynExpInstr::FunctionGeneratorDefs::FunctionDescType RFGeneratorDefaultFuncDesc
Definition ODMR.h:94
ODMRPlotType ODMRPlot
Definition ODMR.h:102
RFModulationType RFModulation
Definition ODMR.h:60
DynExpInstr::FunctionGeneratorDefs::FunctionDescType RFGeneratorMinFuncDesc
Definition ODMR.h:92
bool SensitivityOffResonanceEnabled
Definition ODMR.h:73
DynExpInstr::DataStreamInstrumentData::ValueType AuxAnalogOutMaxValue
Definition ODMR.h:98
auto & GetSignalDetector() noexcept
Definition ODMR.h:41
void ResetImpl(dispatch_tag< QModuleDataBase >) override final
Definition ODMR.cpp:9
std::unique_ptr< DynExp::QModuleWidget > MakeUIWidget() override final
Used by InitUI() as a factory function for the module's user interface widget. Create the widget here...
Definition ODMR.cpp:217
size_t NumFailedUpdateAttempts
Definition ODMR.h:282
void InitRFGenerator(double Frequency, bool EnableRF, Util::SynchronizedPointer< ModuleDataType > &ModuleData) const
Definition ODMR.cpp:318
void OnEnableSweepSeriesClicked(DynExp::ModuleInstance *Instance, Qt::CheckState Checked) const
Definition ODMR.cpp:555
void OnSweepSeriesStopChanged(DynExp::ModuleInstance *Instance, double Value) const
Definition ODMR.cpp:582
void OnRFModDepthChanged(DynExp::ModuleInstance *Instance, double Value) const
Definition ODMR.cpp:465
void UpdateUIChild(const ModuleBase::ModuleDataGetterType &ModuleDataGetter) override final
Definition ODMR.cpp:271
void OnExit(DynExp::ModuleInstance *Instance) const override final
This event is triggered right before the module thread terminates (not due to an exception,...
Definition ODMR.cpp:389
Util::StateMachine< StateMachineStateType > StateMachine
Definition ODMR.h:276
Util::DynExpErrorCodes::DynExpErrorCodes ModuleMainLoop(DynExp::ModuleInstance &Instance) override final
Module main loop. The function is executed periodically by the module thread. Also refer to GetMainLo...
Definition ODMR.cpp:180
void WaitUntilReadyAndTrigger(Util::SynchronizedPointer< ModuleDataType > &ModuleData) const
Definition ODMR.cpp:339
StateType MeasurementSeriesInitFunc(DynExp::ModuleInstance &Instance)
Definition ODMR.cpp:671
void OnSweepSeriesAdvanceLastValueClicked(DynExp::ModuleInstance *Instance, Qt::CheckState Checked) const
Definition ODMR.cpp:600
void OnStopClicked(DynExp::ModuleInstance *Instance, bool) const
Definition ODMR.cpp:628
void OnSweepSeriesRetraceClicked(DynExp::ModuleInstance *Instance, Qt::CheckState Checked) const
Definition ODMR.cpp:594
StateType ODMRTraceWaitFunc(DynExp::ModuleInstance &Instance)
Definition ODMR.cpp:747
void OnRFModNoneClicked(DynExp::ModuleInstance *Instance, bool Checked) const
Definition ODMR.cpp:435
void OnAutosaveClicked(DynExp::ModuleInstance *Instance, Qt::CheckState Checked) const
Definition ODMR.cpp:489
void OnRFFreqSpanChanged(DynExp::ModuleInstance *Instance, double Value) const
Definition ODMR.cpp:417
void OnGyromagneticRatioChanged(DynExp::ModuleInstance *Instance, double Value) const
Definition ODMR.cpp:549
std::chrono::milliseconds GetMainLoopDelay() const override final
Specifies in which time intervals the module's event queue runs to handle pending events.
Definition ODMR.cpp:169
bool IsReadyState() const noexcept
Definition ODMR.h:181
void OnODMRSamplingRateChanged(DynExp::ModuleInstance *Instance, double Value) const
Definition ODMR.cpp:471
void ResetImpl(dispatch_tag< QModuleBase >) override final
Definition ODMR.cpp:206
void OnRFOnClicked(DynExp::ModuleInstance *Instance, bool) const
Definition ODMR.cpp:640
double NextAuxAnalogOutValue
Definition ODMR.h:280
void OnRFModPulseClicked(DynExp::ModuleInstance *Instance, bool Checked) const
Definition ODMR.cpp:451
StateType ReadyStateFunc(DynExp::ModuleInstance &Instance)
Definition ODMR.cpp:666
void OnRecordSensitivityOffResonanceClicked(DynExp::ModuleInstance *Instance, Qt::CheckState Checked) const
Definition ODMR.cpp:507
ODMR(const std::thread::id OwnerThreadID, DynExp::ParamsBasePtrType &&Params)
Definition ODMR.cpp:160
void OnSavePathChanged(DynExp::ModuleInstance *Instance, QString Path) const
Definition ODMR.cpp:477
void OnSweepSeriesStepChanged(DynExp::ModuleInstance *Instance, double Value) const
Definition ODMR.cpp:588
void OnSensitivityResonanceSpanChanged(DynExp::ModuleInstance *Instance, double Value) const
Definition ODMR.cpp:525
void OnSensitivityOffResonanceFreqChanged(DynExp::ModuleInstance *Instance, double Value) const
Definition ODMR.cpp:519
StateType ODMRTraceInitFunc(DynExp::ModuleInstance &Instance)
Definition ODMR.cpp:716
StateType InitializingStateFunc(DynExp::ModuleInstance &Instance)
Definition ODMR.cpp:661
double NextRFModulationDepth
Definition ODMR.h:279
void SetAuxAnalogOutValue(Util::SynchronizedPointer< ModuleDataType > &ModuleData) const
Definition ODMR.cpp:333
void OnSaveIndexChanged(DynExp::ModuleInstance *Instance, int Index) const
Definition ODMR.cpp:483
StateType MeasurementSeriesStepFunc(DynExp::ModuleInstance &Instance)
Definition ODMR.cpp:689
void OnRFFreqSpacingChanged(DynExp::ModuleInstance *Instance, double Value) const
Definition ODMR.cpp:423
void OnRFModFreqChanged(DynExp::ModuleInstance *Instance, double Value) const
Definition ODMR.cpp:459
void OnODMRGraphClicked(DynExp::ModuleInstance *Instance, QPointF Point) const
Definition ODMR.cpp:652
void OnRFDwellTimeChanged(DynExp::ModuleInstance *Instance, double Value) const
Definition ODMR.cpp:429
void OnStartClicked(DynExp::ModuleInstance *Instance, bool) const
Definition ODMR.cpp:606
void InitSweepValues(Util::SynchronizedPointer< ModuleDataType > &ModuleData)
Definition ODMR.cpp:289
void OnSensitivitySamplingRateChanged(DynExp::ModuleInstance *Instance, double Value) const
Definition ODMR.cpp:531
void OnSensitivityResonanceFreqChanged(DynExp::ModuleInstance *Instance, double Value) const
Definition ODMR.cpp:513
void OnRFModSineClicked(DynExp::ModuleInstance *Instance, bool Checked) const
Definition ODMR.cpp:443
void OnStartSensitivityClicked(DynExp::ModuleInstance *Instance, bool) const
Definition ODMR.cpp:617
void OnRFAutoEnableClicked(DynExp::ModuleInstance *Instance, Qt::CheckState Checked) const
Definition ODMR.cpp:405
void OnRFOffClicked(DynExp::ModuleInstance *Instance, bool) const
Definition ODMR.cpp:646
void OnRecordSensitivityClicked(DynExp::ModuleInstance *Instance, Qt::CheckState Checked) const
Definition ODMR.cpp:495
void OnSweepSeriesParamChanged(DynExp::ModuleInstance *Instance, int Index) const
Definition ODMR.cpp:561
void OnEnableSensitivityAnalysisClicked(DynExp::ModuleInstance *Instance, bool Checked) const
Definition ODMR.cpp:543
void OnRecordSensitivityOncePerSweepClicked(DynExp::ModuleInstance *Instance, Qt::CheckState Checked) const
Definition ODMR.cpp:501
void OnRFPowerChanged(DynExp::ModuleInstance *Instance, double Value) const
Definition ODMR.cpp:399
void OnInit(DynExp::ModuleInstance *Instance) const override final
This event is triggered right before the module thread starts. Override it to lock instruments this m...
Definition ODMR.cpp:359
void OnSweepSeriesStartChanged(DynExp::ModuleInstance *Instance, double Value) const
Definition ODMR.cpp:576
StateType ODMRTraceFinishFunc(DynExp::ModuleInstance &Instance)
Definition ODMR.cpp:754
void OnRFCenterFreqChanged(DynExp::ModuleInstance *Instance, double Value) const
Definition ODMR.cpp:411
void OnSensitivityDurationChanged(DynExp::ModuleInstance *Instance, double Value) const
Definition ODMR.cpp:537
const std::unique_ptr< ModuleDataType > ModuleData
Module data belonging to this ModuleBase instance.
Definition Module.h:789
Refer to ParamsBase::dispatch_tag.
Definition Module.h:192
Defines data for a thread belonging to a ModuleBase instance. Refer to RunnableInstance.
Definition Module.h:841
const ModuleBase::ModuleDataGetterType ModuleDataGetter
Getter for module's data. Refer to ModuleBase::ModuleDataGetterType.
Definition Module.h:873
Refer to ParamsBase::dispatch_tag.
Definition Object.h:2026
QModuleWidget * Widget
User interface widget belonging to the module.
Definition Module.h:1816
void Connect(SenderType *Sender, SignalType Signal, ReceiverType *Receiver, EventType Event)
Uses Qt's connect mechanism to connect a QObject's signal to a DynExp module's event....
Definition Module.h:1825
const Object::ParamsGetterType ParamsGetter
Invoke to obtain the parameters (derived from ParamsBase) of Owner.
Definition Object.h:3718
void UnlockObject(LinkedObjectWrapperContainer< ObjectT > &ObjectWrapperContainer)
Unlocks an Object instance stored in the LinkedObjectWrapperContainer ObjectWrapperContainer....
Definition Object.h:3617
void LockObject(const ParamsBase::Param< ObjectLink< ObjectT > > &LinkParam, LinkedObjectWrapperContainer< ObjectT > &ObjectWrapperContainer, std::chrono::milliseconds Timeout=ObjectLinkBase::LockObjectTimeoutDefault)
Locks an Object instance referenced by a parameter LinkParam of type ParamsBase::Param< ObjectLink< O...
Definition Object.h:3601
const auto & GetOwner() const noexcept
Returns Owner.
Definition Object.h:3564
Data to operate on is invalid for a specific purpose. This indicates a corrupted data structure or fu...
Definition Exception.h:164
Pointer to lock a class derived from ISynchronizedPointerLockable for synchronizing between threads....
Definition Util.h:171
Thrown when an operation timed out before it could be completed, especially used for locking shared d...
Definition Exception.h:262
@ Rise
Trigger on rising edge.
@ ExternSingle
Run once after an external trigger signal has been detected.
std::tuple< double, double > FitParams
Definition ODMRWidget.h:44
Graph::LineGraphPlotInfo PlotInfo
Definition ODMRWidget.h:46
Graph::LineGraphPlotInfo PlotInfo
Definition ODMRWidget.h:54
@ TperSqrtHz
Magnetic field amplitude spectral density in T/sqrt(Hz)
@ Arbitrary
Arbitrary units (a.u.)
@ Freq_Hz
Frequency in Hz.
@ Freq_GHz
Frequency in GHz.
@ Volt
Voltage in Volt (V)
void WaitForInstruments(InstrTs &... Instruments)
Blocks until every instrument passed to the function as a reference parameter has arrived at a synchr...
std::unique_ptr< ParamsBase > ParamsBasePtrType
Alias for a pointer to the parameter system base class ParamsBase.
Definition Object.h:1807
DynExpErrorCodes
DynExp's error codes
Definition Exception.h:22
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
bool SaveToFile(const QString &Filename, std::string_view Text)
Saves a std::string_view to a file (using QFile). Creates a new file or truncates an existing file's ...
Definition QtUtil.cpp:236
auto RemoveExtFromPath(std::string Path)
Removes the filename's extension from a path.
Definition Util.h:909
std::vector< std::complex< double > > FFT(const std::vector< std::complex< double > > &Data, bool InverseTransform)
Computes the Fast Fourier Transform (FFT) a vector of complex values.
Definition Util.cpp:228
Accumulates include statements to provide a precompiled header.
@ Pulse
Pulse (binary) modulation switching the affected quantity between two values.
@ Frequency
Modulation affecting the waveform's frequency.
@ ExternSingle
Run once after an external trigger signal has been detected.
DynExp::Units::UnitType XUnit
Joint unit of the plot's x axis.
Definition GraphUtil.h:104
QString YLabel
If empty, the y label is constructed from YUnit. Otherwise, YLabel is used.
Definition GraphUtil.h:129
bool XIsLogarithmic
Determines whether x axis is logarithmic.
Definition GraphUtil.h:114
bool YIsLogarithmic
Determines whether y axis is logarithmic.
Definition GraphUtil.h:119
DynExp::Units::UnitType YUnit
Joint unit of the plot's y axis.
Definition GraphUtil.h:109