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 "ODMR.h"
5
7{
12
13 unsigned long long ODMRData::GetSweepNumberSteps() const noexcept
14 {
16 return 0;
17
18 return std::floor(std::abs(SweepSeriesStop - SweepSeriesStart) / SweepSeriesStep) + 1;
19 }
20
21 std::stringstream ODMRData::AssembleCSVHeader(double RFPower, double RFModulationDepth, double AuxAnalogOutValue, bool IsRFOffResonance)
22 {
23 std::stringstream CSVData;
24
25 CSVData << std::setprecision(6);
26 CSVData << "RFPower = " << RFPower << " " << GetRFGenerator()->GetValueUnitStr() << "\n";
27 CSVData << "RFCenterFreq = " << RFCenterFreq << " Hz\n";
28 CSVData << "RFFreqSpan = " << RFFreqSpan << " Hz\n";
29 CSVData << "RFFreqSpacing = " << RFFreqSpacing << " Hz\n";
30 CSVData << "RFDwellTime = " << RFDwellTime << " s\n";
31
32 CSVData << "RFModulation = ";
33 switch (RFModulation)
34 {
35 case RFModulationType::None: CSVData << "none\n"; break;
36 case RFModulationType::Sine: CSVData << "sine\n"; break;
37 case RFModulationType::Pulse: CSVData << "pulse\n"; break;
38 default: CSVData << "\n";
39 }
40 CSVData << "RFModulationFreq = " << RFModulationFreq << " Hz\n";
41 CSVData << "RFModulationDepth = " << RFModulationDepth << " Hz\n";
42
43 CSVData << "ODMRSamplingRate = " << ODMRSamplingRate << " samples/s\n";
44 CSVData << "CurrentSaveIndex = " << CurrentSaveIndex << "\n";
45
46 CSVData << "IsRFOffResonance = " << (IsRFOffResonance ? "yes" : "no") << "\n";
47 CSVData << "SensitivityEnabled = " << (SensitivityEnabled ? "yes" : "no") << "\n";
48 CSVData << "SensitivityOncePerSweep = " << (SensitivityOncePerSweep ? "yes" : "no") << "\n";
49 CSVData << "SensitivityOffResonanceEnabled = " << (SensitivityOffResonanceEnabled ? "yes" : "no") << "\n";
50 CSVData << "SensitivityResonanceFreq = " << SensitivityResonanceFreq << " Hz\n";
51 CSVData << "SensitivityOffResonanceFreq = " << SensitivityOffResonanceFreq << " Hz\n";
52 CSVData << "SensitivityResonanceSpan = " << SensitivityResonanceSpan << " Hz\n";
53 CSVData << "SensitivitySamplingRate = " << SensitivitySamplingRate << " samples/s\n";
54 CSVData << "SensitivityDuration = " << SensitivityDuration << " s\n";
55
56 CSVData << "SensitivityAnalysisEnabled = " << (SensitivityAnalysisEnabled ? "yes" : "no") << "\n";
57 CSVData << "GyromagneticRatio = " << GyromagneticRatio << " Hz/T\n";
58
59 CSVData << "SweepSeriesEnabled = " << (SweepSeriesEnabled ? "yes" : "no") << "\n";
60 CSVData << "SweepSeries = ";
61 switch (SweepSeries)
62 {
63 case SweepSeriesType::RFModulationDepth: CSVData << "RFModulationDepth\n"; break;
64 case SweepSeriesType::RFPower: CSVData << "RFPower\n"; break;
65 case SweepSeriesType::AnalogOut: CSVData << "AnalogOut\n"; break;
66 default: CSVData << "\n";
67 }
68 CSVData << "SweepSeriesStart = " << SweepSeriesStart << "\n";
69 CSVData << "SweepSeriesStop = " << SweepSeriesStop << "\n";
70 CSVData << "SweepSeriesStep = " << SweepSeriesStep << "\n";
71 CSVData << "SweepSeriesRetrace = " << (SweepSeriesRetrace ? "yes" : "no") << "\n";
72 CSVData << "SweepSeriesAdvanceLastValue = " << (SweepSeriesAdvanceLastValue ? "yes" : "no") << "\n";
73 CSVData << "CurrentSweepIndex = " << CurrentSweepIndex << "\n";
74 CSVData << "AuxAnalogOutValue = " << AuxAnalogOutValue << "\n";
75
77 {
78 auto& LockinInstr = dynamic_cast<const DynExpInstr::LockinAmplifier&>(*GetSignalDetector());
79 auto LockinData = DynExp::dynamic_InstrumentData_cast<DynExpInstr::LockinAmplifier>(GetSignalDetector()->GetInstrumentData());
80
81 auto Sensitivity = LockinData->GetSensitivity();
82 auto TimeConstant = LockinData->GetTimeConstant();
83 unsigned int FilterOrder = LockinData->GetFilterOrder();
84
85 CSVData << "LockinSensitivity = " << Sensitivity << " " << LockinInstr.GetSensitivityUnitString() << "\n";
86 CSVData << "LockinTimeConstant = " << TimeConstant << " s\n";
87 CSVData << "LockinFilterOrder = " << FilterOrder << "\n";
88 }
89
90 CSVData << "HEADER_END\n";
91
92 return CSVData;
93 }
94
151
152 ODMR::ODMR::ODMR(const std::thread::id OwnerThreadID, DynExp::ParamsBasePtrType&& Params)
153 : QModuleBase(OwnerThreadID, std::move(Params)),
154 StateMachine(InitializingState, ReadyState,
155 MeasurementSeriesStepState, MeasurementSeriesInitState,
156 ODMRTraceInitState, ODMRTraceWaitState, ODMRTraceFinishState,
157 SensitivityInitState, SensitivityWaitState, SensitivityFinishState)
158 {
159 }
160
161 std::chrono::milliseconds ODMR::ODMR::GetMainLoopDelay() const
162 {
163 auto CurrentState = StateMachine.GetCurrentState()->GetState();
164
165 // If doing some measurement, run much faster.
166 if (CurrentState == StateType::Ready)
167 return std::chrono::milliseconds(30);
168 else
169 return std::chrono::milliseconds(2);
170 }
171
173 {
174 try
175 {
176 auto ModuleData = DynExp::dynamic_ModuleData_cast<ODMR>(Instance.ModuleDataGetter());
177
179 {
180 auto LockinData = DynExp::dynamic_InstrumentData_cast<DynExpInstr::LockinAmplifier>(ModuleData->GetSignalDetector()->GetInstrumentData());
181
182 ModuleData->AcquisitionTime = LockinData->GetAcquisitionTime();
183 } // LockinData unlocked here.
184
185 StateMachine.Invoke(*this, Instance);
186
188 }
189 catch (const Util::TimeoutException& e)
190 {
191 if (NumFailedUpdateAttempts++ >= 3)
192 Instance.GetOwner().SetWarning(e);
193 }
194
196 }
197
208
209 std::unique_ptr<DynExp::QModuleWidget> ODMR::MakeUIWidget()
210 {
211 auto Widget = std::make_unique<ODMRWidget>(*this);
212
213 Connect(Widget->GetUI().SBRFPower, QOverload<double>::of(&QDoubleSpinBox::valueChanged), this, &ODMR::OnRFPowerChanged);
214 Connect(Widget->GetUI().CBRFAutoEnable, &QCheckBox::stateChanged, this, &ODMR::OnRFAutoEnableClicked);
215 Connect(Widget->GetUI().SBRFCenter, QOverload<double>::of(&QDoubleSpinBox::valueChanged), this, &ODMR::OnRFCenterFreqChanged);
216 Connect(Widget->GetUI().SBRFSpan, QOverload<double>::of(&QDoubleSpinBox::valueChanged), this, &ODMR::OnRFFreqSpanChanged);
217 Connect(Widget->GetUI().SBRFFreqSpacing, QOverload<double>::of(&QDoubleSpinBox::valueChanged), this, &ODMR::OnRFFreqSpacingChanged);
218 Connect(Widget->GetUI().SBRFDwellTime, QOverload<double>::of(&QDoubleSpinBox::valueChanged), this, &ODMR::OnRFDwellTimeChanged);
219
220 Connect(Widget->GetUI().RBRFModulationTypeNone, &QRadioButton::clicked, this, &ODMR::OnRFModNoneClicked);
221 Connect(Widget->GetUI().RBRFModulationTypeSine, &QRadioButton::clicked, this, &ODMR::OnRFModSineClicked);
222 Connect(Widget->GetUI().RBRFModulationTypePulse, &QRadioButton::clicked, this, &ODMR::OnRFModPulseClicked);
223 Connect(Widget->GetUI().SBRFModulationFreq, QOverload<double>::of(&QDoubleSpinBox::valueChanged), this, &ODMR::OnRFModFreqChanged);
224 Connect(Widget->GetUI().SBRFModulationDepth, QOverload<double>::of(&QDoubleSpinBox::valueChanged), this, &ODMR::OnRFModDepthChanged);
225
226 Connect(Widget->GetUI().SBDataAcquisitionODMRSamplingRate, QOverload<double>::of(&QDoubleSpinBox::valueChanged), this, &ODMR::OnODMRSamplingRateChanged);
227
228 Connect(Widget->GetUI().LESaveDataPath, &QLineEdit::textChanged, this, &ODMR::OnSavePathChanged);
229 Connect(Widget->GetUI().SBSaveDataCurrentIndex, QOverload<int>::of(&QSpinBox::valueChanged), this, &ODMR::OnSaveIndexChanged);
230 Connect(Widget->GetUI().CBSaveDataEnable, &QCheckBox::stateChanged, this, &ODMR::OnAutosaveClicked);
231
232 Connect(Widget->GetUI().CBSensitivityEnable, &QCheckBox::stateChanged, this, &ODMR::OnRecordSensitivityClicked);
233 Connect(Widget->GetUI().CBSensitivityOncePerSweep, &QCheckBox::stateChanged, this, &ODMR::OnRecordSensitivityOncePerSweepClicked);
234 Connect(Widget->GetUI().CBSensitivityOffResEnable, &QCheckBox::stateChanged, this, &ODMR::OnRecordSensitivityOffResonanceClicked);
235 Connect(Widget->GetUI().SBSensitivityFreq, QOverload<double>::of(&QDoubleSpinBox::valueChanged), this, &ODMR::OnSensitivityResonanceFreqChanged);
236 Connect(Widget->GetUI().SBSensitivityOffResFreq, QOverload<double>::of(&QDoubleSpinBox::valueChanged), this, &ODMR::OnSensitivityOffResonanceFreqChanged);
237 Connect(Widget->GetUI().SBSensitivitySpan, QOverload<double>::of(&QDoubleSpinBox::valueChanged), this, &ODMR::OnSensitivityResonanceSpanChanged);
238 Connect(Widget->GetUI().SBSensitivitySamplingRate, QOverload<double>::of(&QDoubleSpinBox::valueChanged), this, &ODMR::OnSensitivitySamplingRateChanged);
239 Connect(Widget->GetUI().SBSensitivityDuration, QOverload<double>::of(&QDoubleSpinBox::valueChanged), this, &ODMR::OnSensitivityDurationChanged);
240
241 Connect(Widget->GetUI().GBSensitivityAnalysis, &QGroupBox::toggled, this, &ODMR::OnEnableSensitivityAnalysisClicked);
242 Connect(Widget->GetUI().SBGyromagneticRatio, QOverload<double>::of(&QDoubleSpinBox::valueChanged), this, &ODMR::OnGyromagneticRatioChanged);
243
244 Connect(Widget->GetUI().CBParamSweepEnable, &QCheckBox::stateChanged, this, &ODMR::OnEnableSweepSeriesClicked);
245 Connect(Widget->GetUI().CBParamSweepType, QOverload<int>::of(&QComboBox::currentIndexChanged), this, &ODMR::OnSweepSeriesParamChanged);
246 Connect(Widget->GetUI().SBParamSweepStart, QOverload<double>::of(&QDoubleSpinBox::valueChanged), this, &ODMR::OnSweepSeriesStartChanged);
247 Connect(Widget->GetUI().SBParamSweepStop, QOverload<double>::of(&QDoubleSpinBox::valueChanged), this, &ODMR::OnSweepSeriesStopChanged);
248 Connect(Widget->GetUI().SBParamSweepStep, QOverload<double>::of(&QDoubleSpinBox::valueChanged), this, &ODMR::OnSweepSeriesStepChanged);
249 Connect(Widget->GetUI().CBParamSweepRetrace, &QCheckBox::stateChanged, this, &ODMR::OnSweepSeriesRetraceClicked);
250 Connect(Widget->GetUI().CBParamSweepAdvanceLastValue, &QCheckBox::stateChanged, this, &ODMR::OnSweepSeriesAdvanceLastValueClicked);
251
252 Connect(Widget->GetUI().BStart, &QPushButton::clicked, this, &ODMR::OnStartClicked);
253 Connect(Widget->GetUI().BStartSensitivity, &QPushButton::clicked, this, &ODMR::OnStartSensitivityClicked);
254 Connect(Widget->GetUI().BStop, &QPushButton::clicked, this, &ODMR::OnStopClicked);
255 Connect(Widget->GetUI().BRFOn, &QPushButton::clicked, this, &ODMR::OnRFOnClicked);
256 Connect(Widget->GetUI().BRFOff, &QPushButton::clicked, this, &ODMR::OnRFOffClicked);
257
258 return Widget;
259 }
260
261 void ODMR::UpdateUIChild(const ModuleBase::ModuleDataGetterType& ModuleDataGetter)
262 {
263 auto Widget = GetWidget<ODMRWidget>();
264 ODMRPlotType ODMRPlot;
265 SensitivityPlotType SensitivityPlot;
266
267 {
268 auto ModuleData = DynExp::dynamic_ModuleData_cast<ODMR>(ModuleDataGetter());
269
270 if (StateMachine.GetCurrentState()->GetState() == StateType::Initializing)
271 return;
272
273 Widget->InitializeUI(ModuleData);
274 Widget->SetUIState(StateMachine.GetCurrentState(), ModuleData);
275 Widget->UpdateUIData(ModuleData);
276
277 if (ModuleData->ODMRPlot.HasChanged)
278 {
279 ODMRPlot = ModuleData->ODMRPlot;
280 ModuleData->ODMRPlot.HasChanged = false;
281 }
282 if (ModuleData->SensitivityPlot.HasChanged)
283 {
284 SensitivityPlot = ModuleData->SensitivityPlot;
285 ModuleData->SensitivityPlot.HasChanged = false;
286 }
287 } // ModuleData unlocked here (heavy plot operations follow).
288
289 if (ODMRPlot.HasChanged)
290 {
291 Widget->UpdateODMRPlot(ODMRPlot);
292 ConnectChartWidgets(Widget->GetODMRDataSeries());
293 }
294 if (SensitivityPlot.HasChanged)
295 Widget->UpdateSensitivityPlot(SensitivityPlot);
296 }
297
299 {
300 NextRFPower = ModuleData->RFPower;
301 NextRFModulationDepth = ModuleData->RFModulationDepth;
302 NextAuxAnalogOutValue = (ModuleData->AuxAnalogOutMinValue <= 0 && ModuleData->AuxAnalogOutMaxValue >= 0) ? 0 : ModuleData->AuxAnalogOutMinValue;
303
304 if (!ModuleData->SweepSeriesEnabled || !ModuleData->GetSweepNumberSteps())
305 return;
306
307 decltype(ModuleData->CurrentSweepIndex) SweepIndex = ModuleData->CurrentSweepIndex;
308 if (ModuleData->SweepSeriesAdvanceLastValue && SweepIndex == 1)
309 SweepIndex = ModuleData->GetSweepNumberSteps() - 1;
310 else if (ModuleData->SweepSeriesAdvanceLastValue && SweepIndex > 1)
311 --SweepIndex;
312
313 switch (ModuleData->SweepSeries)
314 {
316 NextRFModulationDepth = (ModuleData->SweepSeriesStart + SweepIndex * std::abs(ModuleData->SweepSeriesStep)) * 1e3;
317 break;
319 NextRFPower = ModuleData->SweepSeriesStart + SweepIndex * std::abs(ModuleData->SweepSeriesStep);
320 break;
322 NextAuxAnalogOutValue = ModuleData->SweepSeriesStart + SweepIndex * std::abs(ModuleData->SweepSeriesStep);
323 break;
324 }
325 }
326
341
343 {
345 ModuleData->GetAuxAnalogOut()->SetSync(NextAuxAnalogOutValue);
346 }
347
349 {
350 // Trigger on rising edge, so set to 0 now.
351 ModuleData->GetTrigger()->SetSync(0);
352
353 // Wait to ensure that trigger signal does not come too fast
354 std::this_thread::sleep_for(std::chrono::milliseconds(200));
355
356 // Prepare acquisition.
357 ModuleData->GetSignalDetector()->Stop();
358 ModuleData->GetSignalDetector()->Clear();
359 ModuleData->GetSignalDetector()->Start();
360
361 // Wait until every involved instrument is ready.
362 DynExp::WaitForInstruments(*ModuleData->GetRFGenerator(), *ModuleData->GetSignalDetector(), *ModuleData->GetTrigger());
363
364 // Trigger RF sweep and data acquisition now.
365 ModuleData->GetTrigger()->SetSync(1);
366 }
367
368 void ODMR::ConnectChartWidgets(QLineSeries* ODMRLineSeries)
369 {
370 if (!ODMRLineSeries)
371 return;
372
373 Connect(ODMRLineSeries, &QXYSeries::hovered, this, &ODMR::OnODMRChartHovered);
374 Connect(ODMRLineSeries, &QXYSeries::clicked, this, &ODMR::OnODMRChartClicked);
375 }
376
378 {
379 auto ModuleParams = DynExp::dynamic_Params_cast<ODMR>(Instance->ParamsGetter());
380 auto ModuleData = DynExp::dynamic_ModuleData_cast<ODMR>(Instance->ModuleDataGetter());
381
382 Instance->LockObject(ModuleParams->RFGenerator, ModuleData->GetRFGenerator());
383 Instance->LockObject(ModuleParams->SignalDetector, ModuleData->GetSignalDetector());
384 Instance->LockObject(ModuleParams->TriggerOut, ModuleData->GetTrigger());
385
386 ModuleData->RFGeneratorMinFuncDesc = ModuleData->GetRFGenerator()->GetMinCaps();
387 ModuleData->RFGeneratorMaxFuncDesc = ModuleData->GetRFGenerator()->GetMaxCaps();
388 ModuleData->RFGeneratorDefaultFuncDesc = ModuleData->GetRFGenerator()->GetParamDefaults();
389
390 if (dynamic_cast<const DynExpInstr::LockinAmplifier*>(ModuleData->GetSignalDetector().get()))
392 else if (dynamic_cast<const DynExpInstr::AnalogIn*>(ModuleData->GetSignalDetector().get()))
394 ModuleData->GetSignalDetector()->Stop();
395
396 if (ModuleParams->AuxAnalogOut.ContainsID())
397 {
398 Instance->LockObject(ModuleParams->AuxAnalogOut, ModuleData->GetAuxAnalogOut());
400
401 ModuleData->AuxAnalogOutValueUnit = ModuleData->GetAuxAnalogOut()->GetValueUnit();
402 ModuleData->AuxAnalogOutMinValue = ModuleData->GetAuxAnalogOut()->GetUserMinValue();
403 ModuleData->AuxAnalogOutMaxValue = ModuleData->GetAuxAnalogOut()->GetUserMaxValue();
404 }
405 }
406
408 {
409 auto ModuleData = DynExp::dynamic_ModuleData_cast<ODMR>(Instance->ModuleDataGetter());
410
411 Instance->UnlockObject(ModuleData->GetRFGenerator());
412 Instance->UnlockObject(ModuleData->GetSignalDetector());
413 Instance->UnlockObject(ModuleData->GetTrigger());
414 Instance->UnlockObject(ModuleData->GetAuxAnalogOut());
415 }
416
417 void ODMR::OnRFPowerChanged(DynExp::ModuleInstance* Instance, double Value) const
418 {
419 auto ModuleData = DynExp::dynamic_ModuleData_cast<ODMR>(Instance->ModuleDataGetter());
420 ModuleData->RFPower = Value;
421 }
422
423 void ODMR::OnRFAutoEnableClicked(DynExp::ModuleInstance* Instance, int Checked) const
424 {
425 auto ModuleData = DynExp::dynamic_ModuleData_cast<ODMR>(Instance->ModuleDataGetter());
426 ModuleData->RFAutoEnabled = Checked;
427 }
428
429 void ODMR::OnRFCenterFreqChanged(DynExp::ModuleInstance* Instance, double Value) const
430 {
431 auto ModuleData = DynExp::dynamic_ModuleData_cast<ODMR>(Instance->ModuleDataGetter());
432 ModuleData->RFCenterFreq = Value * 1e6;
433 }
434
435 void ODMR::OnRFFreqSpanChanged(DynExp::ModuleInstance* Instance, double Value) const
436 {
437 auto ModuleData = DynExp::dynamic_ModuleData_cast<ODMR>(Instance->ModuleDataGetter());
438 ModuleData->RFFreqSpan = Value * 1e6;
439 }
440
441 void ODMR::OnRFFreqSpacingChanged(DynExp::ModuleInstance* Instance, double Value) const
442 {
443 auto ModuleData = DynExp::dynamic_ModuleData_cast<ODMR>(Instance->ModuleDataGetter());
444 ModuleData->RFFreqSpacing = Value * 1e3;
445 }
446
447 void ODMR::OnRFDwellTimeChanged(DynExp::ModuleInstance* Instance, double Value) const
448 {
449 auto ModuleData = DynExp::dynamic_ModuleData_cast<ODMR>(Instance->ModuleDataGetter());
450 ModuleData->RFDwellTime = Value * 1e-3;
451 }
452
453 void ODMR::OnRFModNoneClicked(DynExp::ModuleInstance* Instance, bool Checked) const
454 {
455 auto ModuleData = DynExp::dynamic_ModuleData_cast<ODMR>(Instance->ModuleDataGetter());
456
457 if (Checked)
459 }
460
461 void ODMR::OnRFModSineClicked(DynExp::ModuleInstance* Instance, bool Checked) const
462 {
463 auto ModuleData = DynExp::dynamic_ModuleData_cast<ODMR>(Instance->ModuleDataGetter());
464
465 if (Checked)
467 }
468
469 void ODMR::OnRFModPulseClicked(DynExp::ModuleInstance* Instance, bool Checked) const
470 {
471 auto ModuleData = DynExp::dynamic_ModuleData_cast<ODMR>(Instance->ModuleDataGetter());
472
473 if (Checked)
475 }
476
477 void ODMR::OnRFModFreqChanged(DynExp::ModuleInstance* Instance, double Value) const
478 {
479 auto ModuleData = DynExp::dynamic_ModuleData_cast<ODMR>(Instance->ModuleDataGetter());
480 ModuleData->RFModulationFreq = Value * 1e3;
481 }
482
483 void ODMR::OnRFModDepthChanged(DynExp::ModuleInstance* Instance, double Value) const
484 {
485 auto ModuleData = DynExp::dynamic_ModuleData_cast<ODMR>(Instance->ModuleDataGetter());
486 ModuleData->RFModulationDepth = Value * 1e3;
487 }
488
489 void ODMR::OnODMRSamplingRateChanged(DynExp::ModuleInstance* Instance, double Value) const
490 {
491 auto ModuleData = DynExp::dynamic_ModuleData_cast<ODMR>(Instance->ModuleDataGetter());
492 ModuleData->ODMRSamplingRate = Value;
493 }
494
495 void ODMR::OnSavePathChanged(DynExp::ModuleInstance* Instance, QString Path) const
496 {
497 auto ModuleData = DynExp::dynamic_ModuleData_cast<ODMR>(Instance->ModuleDataGetter());
498 ModuleData->SaveDataPath = Path.toStdString();
499 }
500
501 void ODMR::OnSaveIndexChanged(DynExp::ModuleInstance* Instance, int Index) const
502 {
503 auto ModuleData = DynExp::dynamic_ModuleData_cast<ODMR>(Instance->ModuleDataGetter());
504 ModuleData->CurrentSaveIndex = Index;
505 }
506
507 void ODMR::OnAutosaveClicked(DynExp::ModuleInstance* Instance, int Checked) const
508 {
509 auto ModuleData = DynExp::dynamic_ModuleData_cast<ODMR>(Instance->ModuleDataGetter());
510 ModuleData->AutosaveEnabled = Checked;
511 }
512
514 {
515 auto ModuleData = DynExp::dynamic_ModuleData_cast<ODMR>(Instance->ModuleDataGetter());
516 ModuleData->SensitivityEnabled = Checked;
517 }
518
520 {
521 auto ModuleData = DynExp::dynamic_ModuleData_cast<ODMR>(Instance->ModuleDataGetter());
522 ModuleData->SensitivityOncePerSweep = Checked;
523 }
524
526 {
527 auto ModuleData = DynExp::dynamic_ModuleData_cast<ODMR>(Instance->ModuleDataGetter());
528 ModuleData->SensitivityOffResonanceEnabled = Checked;
529 }
530
532 {
533 auto ModuleData = DynExp::dynamic_ModuleData_cast<ODMR>(Instance->ModuleDataGetter());
534 ModuleData->SensitivityResonanceFreq = Value * 1e6;
535 }
536
538 {
539 auto ModuleData = DynExp::dynamic_ModuleData_cast<ODMR>(Instance->ModuleDataGetter());
540 ModuleData->SensitivityOffResonanceFreq = Value * 1e6;
541 }
542
544 {
545 auto ModuleData = DynExp::dynamic_ModuleData_cast<ODMR>(Instance->ModuleDataGetter());
546 ModuleData->SensitivityResonanceSpan = Value * 1e6;
547 }
548
550 {
551 auto ModuleData = DynExp::dynamic_ModuleData_cast<ODMR>(Instance->ModuleDataGetter());
552 ModuleData->SensitivitySamplingRate = Value;
553 }
554
556 {
557 auto ModuleData = DynExp::dynamic_ModuleData_cast<ODMR>(Instance->ModuleDataGetter());
558 ModuleData->SensitivityDuration = Value;
559 }
560
562 {
563 auto ModuleData = DynExp::dynamic_ModuleData_cast<ODMR>(Instance->ModuleDataGetter());
564 ModuleData->SensitivityAnalysisEnabled = Checked;
565 }
566
568 {
569 auto ModuleData = DynExp::dynamic_ModuleData_cast<ODMR>(Instance->ModuleDataGetter());
570 ModuleData->GyromagneticRatio = Value * 1e6;
571 }
572
574 {
575 auto ModuleData = DynExp::dynamic_ModuleData_cast<ODMR>(Instance->ModuleDataGetter());
576 ModuleData->SweepSeriesEnabled = Checked;
577 }
578
580 {
581 auto ModuleData = DynExp::dynamic_ModuleData_cast<ODMR>(Instance->ModuleDataGetter());
582
583 switch (Index)
584 {
585 case 0: ModuleData->SweepSeries = ODMRData::SweepSeriesType::RFModulationDepth; break;
586 case 1: ModuleData->SweepSeries = ODMRData::SweepSeriesType::RFPower; break;
587 case 2:
590 break;
591 }
592 }
593
594 void ODMR::OnSweepSeriesStartChanged(DynExp::ModuleInstance* Instance, double Value) const
595 {
596 auto ModuleData = DynExp::dynamic_ModuleData_cast<ODMR>(Instance->ModuleDataGetter());
597 ModuleData->SweepSeriesStart = Value;
598 }
599
600 void ODMR::OnSweepSeriesStopChanged(DynExp::ModuleInstance* Instance, double Value) const
601 {
602 auto ModuleData = DynExp::dynamic_ModuleData_cast<ODMR>(Instance->ModuleDataGetter());
603 ModuleData->SweepSeriesStop = Value;
604 }
605
606 void ODMR::OnSweepSeriesStepChanged(DynExp::ModuleInstance* Instance, double Value) const
607 {
608 auto ModuleData = DynExp::dynamic_ModuleData_cast<ODMR>(Instance->ModuleDataGetter());
609 ModuleData->SweepSeriesStep = Value;
610 }
611
613 {
614 auto ModuleData = DynExp::dynamic_ModuleData_cast<ODMR>(Instance->ModuleDataGetter());
615 ModuleData->SweepSeriesRetrace = Checked;
616 }
617
619 {
620 auto ModuleData = DynExp::dynamic_ModuleData_cast<ODMR>(Instance->ModuleDataGetter());
621 ModuleData->SweepSeriesAdvanceLastValue = Checked;
622 }
623
625 {
626 if (!IsReadyState())
627 return;
628
630
631 auto ModuleData = DynExp::dynamic_ModuleData_cast<ODMR>(Instance->ModuleDataGetter());
633 }
634
636 {
637 if (!IsReadyState())
638 return;
639
641
642 auto ModuleData = DynExp::dynamic_ModuleData_cast<ODMR>(Instance->ModuleDataGetter());
644 }
645
646 void ODMR::OnStopClicked(DynExp::ModuleInstance* Instance, bool) const
647 {
648 auto ModuleData = DynExp::dynamic_ModuleData_cast<ODMR>(Instance->ModuleDataGetter());
649
650 if (ModuleData->RFAutoEnabled)
651 ModuleData->GetRFGenerator()->Stop();
652 ModuleData->GetSignalDetector()->Stop();
653
654 StateMachine.ResetContext();
655 StateMachine.SetCurrentState(StateType::Ready);
656 }
657
658 void ODMR::OnRFOnClicked(DynExp::ModuleInstance* Instance, bool) const
659 {
660 auto ModuleData = DynExp::dynamic_ModuleData_cast<ODMR>(Instance->ModuleDataGetter());
661 ModuleData->GetRFGenerator()->Start();
662 }
663
665 {
666 auto ModuleData = DynExp::dynamic_ModuleData_cast<ODMR>(Instance->ModuleDataGetter());
667 ModuleData->GetRFGenerator()->Stop();
668 }
669
670 void ODMR::OnODMRChartHovered(DynExp::ModuleInstance* Instance, QPointF Point, bool State) const
671 {
672 auto ModuleData = DynExp::dynamic_ModuleData_cast<ODMR>(Instance->ModuleDataGetter());
673 ModuleData->ODMRPlot.SelectedPoint = State ? Point : QPointF();
674 }
675
676 void ODMR::OnODMRChartClicked(DynExp::ModuleInstance* Instance, QPointF Point) const
677 {
678 if (Point.isNull())
679 return;
680
681 auto ModuleData = DynExp::dynamic_ModuleData_cast<ODMR>(Instance->ModuleDataGetter());
682 ModuleData->GetRFGenerator()->SetSineFunction({ Point.x() * 1e9 , ModuleData->RFPower, 0, 0});
683 }
684
689
694
696 {
697 auto ModuleData = DynExp::dynamic_ModuleData_cast<ODMR>(Instance.ModuleDataGetter());
698
699 ModuleData->CurrentSweepIndex = 0;
701
703 {
704 auto LockinAmplifier = ModuleData->GetLockinAmplifier();
706 LockinAmplifier->SetTriggerEdge(DynExpInstr::LockinAmplifierDefs::TriggerEdgeType::Rise);
707 LockinAmplifier->SetEnable(true);
708 }
709
711 }
712
714 {
715 auto ModuleData = DynExp::dynamic_ModuleData_cast<ODMR>(Instance.ModuleDataGetter());
716
717 if (!ModuleData->SweepSeriesEnabled || ++ModuleData->CurrentSweepIndex >= ModuleData->GetSweepNumberSteps())
718 {
719 ++ModuleData->CurrentSaveIndex;
720
721 if (ModuleData->SweepSeriesEnabled && ModuleData->SweepSeriesRetrace)
722 {
723 ModuleData->CurrentSweepIndex = 0;
725
727 InitRFGenerator(ModuleData->GetRFStartFreq(), false, ModuleData);
728 }
729 if (ModuleData->RFAutoEnabled)
730 ModuleData->GetRFGenerator()->Stop();
731
732 return StateType::Ready;
733 }
734
736
738 }
739
741 {
742 auto ModuleData = DynExp::dynamic_ModuleData_cast<ODMR>(Instance.ModuleDataGetter());
743
745 InitRFGenerator(ModuleData->GetRFStartFreq(), ModuleData->RFAutoEnabled, ModuleData);
746 ModuleData->GetRFGenerator()->SetSweep({
748 ModuleData->GetRFStartFreq(),
749 ModuleData->GetRFStopFreq(),
750 ModuleData->RFFreqSpacing,
751 ModuleData->RFDwellTime * 1000,
752 true
753 });
754 ModuleData->GetRFGenerator()->SetTrigger({
757 });
758
760 {
761 auto LockinAmplifier = ModuleData->GetLockinAmplifier();
762 LockinAmplifier->SetStreamSize(ModuleData->RFDwellTime * ModuleData->GetNumSamples() * ModuleData->ODMRSamplingRate);
763 LockinAmplifier->SetSamplingRate(ModuleData->ODMRSamplingRate);
764 }
765
767
769 }
770
772 {
773 auto ModuleData = DynExp::dynamic_ModuleData_cast<ODMR>(Instance.ModuleDataGetter());
774
775 return ModuleData->GetSignalDetector()->HasFinished() ? StateType::ODMRTraceFinish : StateType::ODMRTraceWait;
776 }
777
779 {
780 std::vector<std::tuple<double, double, double>> SaveSamples;
781 bool Save = false;
782 bool PerformSensitivityMeasurement = false;
783 double RFStartFreq{};
784 decltype(ODMRData::RFDwellTime) RFDwellTime{};
785 decltype(ODMRData::RFFreqSpacing) RFFreqSpacing{};
786 bool IsBasicSampleTimeUsed{};
787 double SamplingRate{ .0 };
789 decltype(ODMRPlotType::DataPoints) ODMRDataPoints;
790 decltype(ODMRPlotType::DataPointsMinValues) ODMRDataPointsMinValues = { std::numeric_limits<double>::max(), std::numeric_limits<double>::max() };
791 decltype(ODMRPlotType::DataPointsMaxValues) ODMRDataPointsMaxValues = { std::numeric_limits<double>::lowest(), std::numeric_limits<double>::lowest() };
792 decltype(ODMRData::SensitivityResonanceFreq) SensitivityResonanceFreq{};
793 decltype(ODMRData::SensitivityResonanceSpan) SensitivityResonanceSpan{};
794 decltype(ODMRPlotType::FitParams) ODMRFitParams{};
795 decltype(ODMRPlotType::FitPoints) ODMRFitPoints{};
796 std::vector<double> FitXData;
797 std::vector<double> FitYData;
798 std::string Filename;
799 std::string ValueUnitStr;
800 std::stringstream CSVData;
801
802 {
803 auto ModuleData = DynExp::dynamic_ModuleData_cast<ODMR>(Instance.ModuleDataGetter());
804
805 if (!ModuleData->GetSignalDetector()->CanRead())
807
808 Save = ModuleData->AutosaveEnabled;
809 PerformSensitivityMeasurement = ModuleData->SensitivityEnabled && (!ModuleData->SensitivityOncePerSweep || !ModuleData->CurrentSweepIndex);
810 RFStartFreq = ModuleData->GetRFStartFreq();
811 RFDwellTime = ModuleData->RFDwellTime;
812 RFFreqSpacing = ModuleData->RFFreqSpacing;
813 SensitivityResonanceFreq = ModuleData->SensitivityResonanceFreq;
814 SensitivityResonanceSpan = ModuleData->SensitivityResonanceSpan;
815
816 auto SignalDetectorData = DynExp::dynamic_InstrumentData_cast<DynExpInstr::DataStreamInstrument>(ModuleData->GetSignalDetector()->GetInstrumentData());
817 SignalDetectorData->GetSampleStream()->SeekBeg(std::ios_base::in);
818 ODMRSamples = SignalDetectorData->GetSampleStream()->ReadBasicSamples(SignalDetectorData->GetSampleStream()->GetStreamSizeRead());
819
820 IsBasicSampleTimeUsed = SignalDetectorData->GetSampleStream()->IsBasicSampleTimeUsed();
821 if (!IsBasicSampleTimeUsed && ModuleData->TestFeature(ODMRData::FeatureType::AnalogInDetection))
822 {
823 SamplingRate = ModuleData->GetAnalogIn()->GetNumericSampleStreamParams().SamplingRate;
824
825 if (SamplingRate == .0)
826 throw Util::InvalidDataException("The analog input channel's sampling rate must not be 0.");
827 }
828
829 } // ModuleData unlocked here (heavy calculation follows).
830
831 for (size_t i = 0; i < ODMRSamples.size(); ++i)
832 {
833 const auto& Sample = ODMRSamples[i];
834
835 auto Frequency = RFStartFreq + (IsBasicSampleTimeUsed ? Sample.Time : (static_cast<double>(i) / SamplingRate)) / RFDwellTime * RFFreqSpacing;
836 ODMRDataPoints.push_back({ Frequency / 1e9, Sample.Value });
837 ODMRDataPointsMinValues = { std::min(ODMRDataPointsMinValues.x(), Frequency / 1e9), std::min(ODMRDataPointsMinValues.y(), Sample.Value) };
838 ODMRDataPointsMaxValues = { std::max(ODMRDataPointsMaxValues.x(), Frequency / 1e9), std::max(ODMRDataPointsMaxValues.y(), Sample.Value) };
839 if (Save)
840 SaveSamples.emplace_back(std::make_tuple(Frequency, Sample.Time, Sample.Value));
841
842 if (PerformSensitivityMeasurement &&
843 Frequency >= SensitivityResonanceFreq - SensitivityResonanceSpan / 2 &&
844 Frequency <= SensitivityResonanceFreq + SensitivityResonanceSpan / 2)
845 {
846 FitXData.push_back(Frequency - SensitivityResonanceFreq);
847 FitYData.push_back(Sample.Value);
848 }
849 }
850
851 if (PerformSensitivityMeasurement)
852 {
853 double c0{0}, c1{0}, cov00{0}, cov01{0}, cov11{0}, chisq{0};
854 gsl_fit_linear(FitXData.data(), 1, FitYData.data(), 1, FitXData.size(), &c0, &c1, &cov00, &cov01, &cov11, &chisq);
855 ODMRFitParams = { c0, c1 };
856
857 for (const auto& f : FitXData)
858 ODMRFitPoints.push_back({ (f + SensitivityResonanceFreq) / 1e9, c0 + c1 * f });
859 }
860
861 {
862 auto ModuleData = DynExp::dynamic_ModuleData_cast<ODMR>(Instance.ModuleDataGetter());
863
864 ModuleData->ODMRPlot.DataPoints = std::move(ODMRDataPoints);
865 ModuleData->ODMRPlot.DataPointsMinValues = ODMRDataPointsMinValues;
866 ModuleData->ODMRPlot.DataPointsMaxValues = ODMRDataPointsMaxValues;
867 ModuleData->ODMRPlot.FitParams = ODMRFitParams;
868 ModuleData->ODMRPlot.FitPoints = ODMRFitPoints;
869 ModuleData->ODMRPlot.HasChanged = true;
870
871 Filename = Util::RemoveExtFromPath(ModuleData->SaveDataPath) + "_ODMR" + Util::ToStr(ModuleData->CurrentSaveIndex) + "_Sweep" + Util::ToStr(ModuleData->CurrentSweepIndex) + ".csv";
872 ValueUnitStr = ModuleData->GetSignalDetector()->GetValueUnitStr();
873
874 if (Save)
875 CSVData = ModuleData->AssembleCSVHeader(NextRFPower, NextRFModulationDepth, NextAuxAnalogOutValue, false);
876 } // ModuleData unlocked here.
877
878 if (Save)
879 {
880 CSVData << "f(Hz);t(s);Value(" << ValueUnitStr << ")\n";
881 for (const auto& Sample : SaveSamples)
882 CSVData << std::get<0>(Sample) << ";" << std::get<1>(Sample) << ";" << std::get<2>(Sample) << "\n";
883
884 Util::SaveToFile(QString::fromStdString(Filename), CSVData.str());
885 }
886
887 return PerformSensitivityMeasurement ? StateType::SensitivityInit : StateType::MeasurementSeriesStep;
888 }
889
890 StateType ODMR::SensitivityInitFunc(DynExp::ModuleInstance& Instance)
891 {
892 auto ModuleData = DynExp::dynamic_ModuleData_cast<ODMR>(Instance.ModuleDataGetter());
893
894 // No sensitivity calculation if detection is not performed with a lock-in amplifer since in this case it is not possible
895 // to measure the ODMR signal's derivative directly.
896 if (!ModuleData->TestFeature(ODMRData::FeatureType::LockinDetection))
897 {
898 StateMachine.ResetContext();
899 return StateType::MeasurementSeriesStep;
900 }
901
902 SetAuxAnalogOutValue(ModuleData);
903 ModuleData->GetRFGenerator()->SetSweep({}); // Disable sweep.
904 ModuleData->GetRFGenerator()->SetTrigger({}); // Disable trigger.
905 auto RFFreq = StateMachine.GetContext() == &SensitivityOffResonanceContext ? ModuleData->SensitivityOffResonanceFreq : ModuleData->SensitivityResonanceFreq;
906 InitRFGenerator(RFFreq, ModuleData->RFAutoEnabled, ModuleData);
907
908 auto LockinAmplifier = ModuleData->GetLockinAmplifier();
909 LockinAmplifier->SetStreamSize(ModuleData->SensitivityDuration * ModuleData->SensitivitySamplingRate);
910 LockinAmplifier->SetSamplingRate(ModuleData->SensitivitySamplingRate);
911
912 WaitUntilReadyAndTrigger(ModuleData);
913
914 return StateType::SensitivityWait;
915 }
916
917 StateType ODMR::SensitivityWaitFunc(DynExp::ModuleInstance& Instance)
918 {
919 auto ModuleData = DynExp::dynamic_ModuleData_cast<ODMR>(Instance.ModuleDataGetter());
920
921 return ModuleData->GetSignalDetector()->HasFinished() ? StateType::SensitivityFinish : StateType::SensitivityWait;
922 }
923
924 StateType ODMR::SensitivityFinishFunc(DynExp::ModuleInstance& Instance)
925 {
926 std::vector<std::tuple<double, double>> SaveSamples;
927 ODMRData::MeasurementModeType MeasurementMode = ODMRData::MeasurementModeType::All;
928 bool Save = false;
929 bool SensitivityOffResonanceEnabled = false;
930 bool SensitivityAnalysisEnabled = false;
931 decltype(ODMRPlotType::FitParams) ODMRFitParams{};
932 decltype(ODMRData::GyromagneticRatio) GyromagneticRatio{};
934 std::vector<std::complex<double>> SensitivityASD;
935 decltype(SensitivityPlotType::DataPoints) SensitivityDataPoints;
936 decltype(SensitivityPlotType::DataPointsMinValues) SensitivityDataPointsMinValues = { std::numeric_limits<double>::max(), std::numeric_limits<double>::max() };
937 decltype(SensitivityPlotType::DataPointsMaxValues) SensitivityDataPointsMaxValues = { std::numeric_limits<double>::lowest(), std::numeric_limits<double>::lowest() };
938 std::string Filename;
939 std::string FilenamePrefix;
940 std::string ValueUnitStr;
941 std::stringstream CSVData;
942
943 {
944 auto ModuleData = DynExp::dynamic_ModuleData_cast<ODMR>(Instance.ModuleDataGetter());
945
946 if (!ModuleData->GetSignalDetector()->CanRead())
947 return StateType::SensitivityFinish;
948
949 MeasurementMode = ModuleData->MeasurementMode;
950 Save = ModuleData->AutosaveEnabled;
951 SensitivityOffResonanceEnabled = ModuleData->SensitivityOffResonanceEnabled;
952 SensitivityAnalysisEnabled = ModuleData->SensitivityAnalysisEnabled;
953 ODMRFitParams = ModuleData->ODMRPlot.FitParams;
954 GyromagneticRatio = ModuleData->GyromagneticRatio;
955
956 auto SignalDetectorData = DynExp::dynamic_InstrumentData_cast<DynExpInstr::DataStreamInstrument>(ModuleData->GetSignalDetector()->GetInstrumentData());
957 SignalDetectorData->GetSampleStream()->SeekBeg(std::ios_base::in);
958 SensitivitySamples = SignalDetectorData->GetSampleStream()->ReadBasicSamples(SignalDetectorData->GetSampleStream()->GetStreamSizeRead());
959 } // ModuleData unlocked here (heavy calculation follows).
960
961 for (const auto& Sample : SensitivitySamples)
962 {
963 SaveSamples.emplace_back(std::make_tuple(Sample.Time, Sample.Value));
964
965 if (MeasurementMode == ODMRData::MeasurementModeType::All && StateMachine.GetContext() != &SensitivityOffResonanceContext)
966 SensitivityASD.emplace_back(Sample.Value / std::get<1>(ODMRFitParams) / GyromagneticRatio, 0);
967 }
968
969 if (SensitivityASD.size() > 2 && SensitivityAnalysisEnabled && StateMachine.GetContext() != &SensitivityOffResonanceContext)
970 {
971 const auto Length = static_cast<double>(SensitivityASD.size());
972
973 SensitivityASD = Util::FFT(SensitivityASD);
974 std::transform(SensitivityASD.cbegin(), SensitivityASD.cend(), SensitivityASD.begin(), [Length](auto x) { return std::abs(x / Length); });
975
976 // Make single-sided spectrum
977 SensitivityASD.erase(SensitivityASD.cbegin() + SensitivityASD.size() / 2 + 1, SensitivityASD.cend());
978 std::transform(SensitivityASD.cbegin() + 1, SensitivityASD.cend(), SensitivityASD.begin() + 1, [Length](auto x) { return 2.0 * x; });
979
980 // Assume SensitivitySamples sorted by Time. Assume samples equally spaced in time.
981 double TimeSamplingRate = 1 / (std::abs(SensitivitySamples.back().Time - SensitivitySamples.front().Time) / (SensitivitySamples.size() - 1));
982 std::vector<double> Frequencies(Length / 2 + 1, 0);
983 std::iota(Frequencies.begin(), Frequencies.end(), 0);
984 std::transform(Frequencies.cbegin(), Frequencies.cend(), Frequencies.begin(), [TimeSamplingRate, Length](auto x) { return TimeSamplingRate * x / Length; });
985
986 double FrequencySamplingRate = std::abs(Frequencies.back() - Frequencies.front()) / (Frequencies.size() - 1);
987 std::transform(SensitivityASD.cbegin(), SensitivityASD.cend(), SensitivityASD.begin(), [FrequencySamplingRate](auto x) { return x / std::sqrt(FrequencySamplingRate); });
988
989 if (SensitivityASD.size() == Frequencies.size())
990 for (size_t i = 1; i < SensitivityASD.size(); ++i) // Ignore 0 Hz frequency component
991 {
992 SensitivityDataPoints.push_back({ Frequencies[i], SensitivityASD[i].real() });
993 SensitivityDataPointsMinValues = { std::min(SensitivityDataPointsMinValues.x(), SensitivityDataPoints.back().x()),
994 std::min(SensitivityDataPointsMinValues.y(), SensitivityDataPoints.back().y()) };
995 SensitivityDataPointsMaxValues = { std::max(SensitivityDataPointsMaxValues.x(), SensitivityDataPoints.back().x()),
996 std::max(SensitivityDataPointsMaxValues.y(), SensitivityDataPoints.back().y()) };
997 }
998 }
999
1000 {
1001 auto ModuleData = DynExp::dynamic_ModuleData_cast<ODMR>(Instance.ModuleDataGetter());
1002
1003 if (StateMachine.GetContext() != &SensitivityOffResonanceContext)
1004 {
1005 ModuleData->SensitivityPlot.DataPoints = std::move(SensitivityDataPoints);
1006 ModuleData->SensitivityPlot.DataPointsMinValues = SensitivityDataPointsMinValues;
1007 ModuleData->SensitivityPlot.DataPointsMaxValues = SensitivityDataPointsMaxValues;
1008 ModuleData->SensitivityPlot.HasChanged = true;
1009
1010 FilenamePrefix = "Sensitivity";
1011 }
1012 else
1013 FilenamePrefix = "OffResSensitivity";
1014
1015 Filename = Util::RemoveExtFromPath(ModuleData->SaveDataPath) + "_" + FilenamePrefix + Util::ToStr(ModuleData->CurrentSaveIndex) + "_Sweep" + Util::ToStr(ModuleData->CurrentSweepIndex) + ".csv";
1016 ValueUnitStr = ModuleData->GetSignalDetector()->GetValueUnitStr();
1017
1018 if (Save)
1019 CSVData = ModuleData->AssembleCSVHeader(NextRFPower, NextRFModulationDepth, NextAuxAnalogOutValue, StateMachine.GetContext() == &SensitivityOffResonanceContext);
1020 } // ModuleData unlocked here.
1021
1022 if (Save)
1023 {
1024 CSVData << "t(s);Value(" << ValueUnitStr << ")\n";
1025 CSVData << std::setprecision(12);
1026 for (const auto& Sample : SaveSamples)
1027 CSVData << std::get<0>(Sample) << ";" << std::get<1>(Sample) << "\n";
1028
1029 Util::SaveToFile(QString::fromStdString(Filename), CSVData.str());
1030 }
1031
1032 if (SensitivityOffResonanceEnabled)
1033 {
1034 if (StateMachine.GetContext() == &SensitivityOffResonanceContext)
1035 StateMachine.ResetContext();
1036 else
1037 {
1038 StateMachine.SetContext(&SensitivityOffResonanceContext);
1039 return StateType::SensitivityInit;
1040 }
1041 }
1042
1043 return StateType::MeasurementSeriesStep;
1044 }
1045}
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:21
bool TestFeature(const std::array< FeatureType, N > &Flags) const
Definition ODMR.h:35
DynExpInstr::DataStreamInstrumentData::UnitType AuxAnalogOutValueUnit
Definition ODMR.h:96
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
double SensitivityOffResonanceFreq
Definition ODMR.h:75
unsigned long long GetSweepNumberSteps() const noexcept
Definition ODMR.cpp:13
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:8
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:209
size_t NumFailedUpdateAttempts
Definition ODMR.h:284
void InitRFGenerator(double Frequency, bool EnableRF, Util::SynchronizedPointer< ModuleDataType > &ModuleData) const
Definition ODMR.cpp:327
void OnSweepSeriesStopChanged(DynExp::ModuleInstance *Instance, double Value) const
Definition ODMR.cpp:600
void OnRFModDepthChanged(DynExp::ModuleInstance *Instance, double Value) const
Definition ODMR.cpp:483
void ConnectChartWidgets(QLineSeries *ODMRLineSeries)
Definition ODMR.cpp:368
void UpdateUIChild(const ModuleBase::ModuleDataGetterType &ModuleDataGetter) override final
Definition ODMR.cpp:261
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:407
Util::StateMachine< StateMachineStateType > StateMachine
Definition ODMR.h:278
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:172
void WaitUntilReadyAndTrigger(Util::SynchronizedPointer< ModuleDataType > &ModuleData) const
Definition ODMR.cpp:348
StateType MeasurementSeriesInitFunc(DynExp::ModuleInstance &Instance)
Definition ODMR.cpp:695
void OnStopClicked(DynExp::ModuleInstance *Instance, bool) const
Definition ODMR.cpp:646
void OnRFAutoEnableClicked(DynExp::ModuleInstance *Instance, int Checked) const
Definition ODMR.cpp:423
StateType ODMRTraceWaitFunc(DynExp::ModuleInstance &Instance)
Definition ODMR.cpp:771
void OnRFModNoneClicked(DynExp::ModuleInstance *Instance, bool Checked) const
Definition ODMR.cpp:453
void OnRFFreqSpanChanged(DynExp::ModuleInstance *Instance, double Value) const
Definition ODMR.cpp:435
void OnGyromagneticRatioChanged(DynExp::ModuleInstance *Instance, double Value) const
Definition ODMR.cpp:567
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:161
void OnRecordSensitivityOffResonanceClicked(DynExp::ModuleInstance *Instance, int Checked) const
Definition ODMR.cpp:525
bool IsReadyState() const noexcept
Definition ODMR.h:181
void OnODMRSamplingRateChanged(DynExp::ModuleInstance *Instance, double Value) const
Definition ODMR.cpp:489
void OnEnableSweepSeriesClicked(DynExp::ModuleInstance *Instance, int Checked) const
Definition ODMR.cpp:573
void ResetImpl(dispatch_tag< QModuleBase >) override final
Definition ODMR.cpp:198
void OnRFOnClicked(DynExp::ModuleInstance *Instance, bool) const
Definition ODMR.cpp:658
double NextAuxAnalogOutValue
Definition ODMR.h:282
void OnRFModPulseClicked(DynExp::ModuleInstance *Instance, bool Checked) const
Definition ODMR.cpp:469
StateType ReadyStateFunc(DynExp::ModuleInstance &Instance)
Definition ODMR.cpp:690
ODMR(const std::thread::id OwnerThreadID, DynExp::ParamsBasePtrType &&Params)
Definition ODMR.cpp:152
void OnSavePathChanged(DynExp::ModuleInstance *Instance, QString Path) const
Definition ODMR.cpp:495
void OnSweepSeriesStepChanged(DynExp::ModuleInstance *Instance, double Value) const
Definition ODMR.cpp:606
void OnSensitivityResonanceSpanChanged(DynExp::ModuleInstance *Instance, double Value) const
Definition ODMR.cpp:543
void OnRecordSensitivityClicked(DynExp::ModuleInstance *Instance, int Checked) const
Definition ODMR.cpp:513
void OnSensitivityOffResonanceFreqChanged(DynExp::ModuleInstance *Instance, double Value) const
Definition ODMR.cpp:537
StateType ODMRTraceInitFunc(DynExp::ModuleInstance &Instance)
Definition ODMR.cpp:740
StateType InitializingStateFunc(DynExp::ModuleInstance &Instance)
Definition ODMR.cpp:685
double NextRFModulationDepth
Definition ODMR.h:281
void OnSweepSeriesRetraceClicked(DynExp::ModuleInstance *Instance, int Checked) const
Definition ODMR.cpp:612
void SetAuxAnalogOutValue(Util::SynchronizedPointer< ModuleDataType > &ModuleData) const
Definition ODMR.cpp:342
void OnSaveIndexChanged(DynExp::ModuleInstance *Instance, int Index) const
Definition ODMR.cpp:501
void OnODMRChartHovered(DynExp::ModuleInstance *Instance, QPointF Point, bool State) const
Definition ODMR.cpp:670
StateType MeasurementSeriesStepFunc(DynExp::ModuleInstance &Instance)
Definition ODMR.cpp:713
void OnODMRChartClicked(DynExp::ModuleInstance *Instance, QPointF Point) const
Definition ODMR.cpp:676
void OnRFFreqSpacingChanged(DynExp::ModuleInstance *Instance, double Value) const
Definition ODMR.cpp:441
void OnRFModFreqChanged(DynExp::ModuleInstance *Instance, double Value) const
Definition ODMR.cpp:477
void OnAutosaveClicked(DynExp::ModuleInstance *Instance, int Checked) const
Definition ODMR.cpp:507
void OnRFDwellTimeChanged(DynExp::ModuleInstance *Instance, double Value) const
Definition ODMR.cpp:447
void OnStartClicked(DynExp::ModuleInstance *Instance, bool) const
Definition ODMR.cpp:624
void InitSweepValues(Util::SynchronizedPointer< ModuleDataType > &ModuleData)
Definition ODMR.cpp:298
void OnSensitivitySamplingRateChanged(DynExp::ModuleInstance *Instance, double Value) const
Definition ODMR.cpp:549
void OnSensitivityResonanceFreqChanged(DynExp::ModuleInstance *Instance, double Value) const
Definition ODMR.cpp:531
void OnRFModSineClicked(DynExp::ModuleInstance *Instance, bool Checked) const
Definition ODMR.cpp:461
void OnSweepSeriesAdvanceLastValueClicked(DynExp::ModuleInstance *Instance, int Checked) const
Definition ODMR.cpp:618
void OnStartSensitivityClicked(DynExp::ModuleInstance *Instance, bool) const
Definition ODMR.cpp:635
void OnRFOffClicked(DynExp::ModuleInstance *Instance, bool) const
Definition ODMR.cpp:664
void OnSweepSeriesParamChanged(DynExp::ModuleInstance *Instance, int Index) const
Definition ODMR.cpp:579
void OnEnableSensitivityAnalysisClicked(DynExp::ModuleInstance *Instance, bool Checked) const
Definition ODMR.cpp:561
void OnRFPowerChanged(DynExp::ModuleInstance *Instance, double Value) const
Definition ODMR.cpp:417
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:377
void OnRecordSensitivityOncePerSweepClicked(DynExp::ModuleInstance *Instance, int Checked) const
Definition ODMR.cpp:519
void OnSweepSeriesStartChanged(DynExp::ModuleInstance *Instance, double Value) const
Definition ODMR.cpp:594
StateType ODMRTraceFinishFunc(DynExp::ModuleInstance &Instance)
Definition ODMR.cpp:778
void OnRFCenterFreqChanged(DynExp::ModuleInstance *Instance, double Value) const
Definition ODMR.cpp:429
void OnSensitivityDurationChanged(DynExp::ModuleInstance *Instance, double Value) const
Definition ODMR.cpp:555
const std::unique_ptr< ModuleDataType > ModuleData
Module data belonging to this ModuleBase instance.
Definition Module.h:743
Refer to ParamsBase::dispatch_tag.
Definition Module.h:189
Defines data for a thread belonging to a ModuleBase instance. Refer to RunnableInstance.
Definition Module.h:793
const ModuleBase::ModuleDataGetterType ModuleDataGetter
Getter for module's data. Refer to ModuleBase::ModuleDataGetterType.
Definition Module.h:825
Refer to ParamsBase::dispatch_tag.
Definition Object.h:2018
QModuleWidget * Widget
User interface widget belonging to the module.
Definition Module.h:1491
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:1500
const Object::ParamsGetterType ParamsGetter
Invoke to obtain the parameters (derived from ParamsBase) of Owner.
Definition Object.h:3671
void UnlockObject(LinkedObjectWrapperContainer< ObjectT > &ObjectWrapperContainer)
Unlocks an Object instance stored in the LinkedObjectWrapperContainer ObjectWrapperContainer....
Definition Object.h:3570
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:3554
const auto & GetOwner() const noexcept
Returns Owner.
Definition Object.h:3524
Data to operate on is invalid for a specific purpose. This indicates a corrupted data structure or fu...
Definition Exception.h:163
Pointer to lock a class derived from ISynchronizedPointerLockable for synchronizing between threads....
Definition Util.h:170
Thrown when an operation timed out before it could be completed, especially used for locking shared d...
Definition Exception.h:261
@ Rise
Trigger on rising edge.
@ ExternSingle
Run once after an external trigger signal has been detected.
std::tuple< double, double > FitParams
Definition ODMRWidget.h:41
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:625
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:853
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:220
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.