DynExp
Highly flexible laboratory automation for dynamically changing experiments.
Loading...
Searching...
No Matches
LaserScanningSpectroscopy.cpp
Go to the documentation of this file.
1// This file is part of DynExp.
2
3#include "stdafx.h"
4#include "moc_LaserScanningSpectroscopy.cpp"
5#include "ui_LaserScanningSpectroscopy.h"
7
9{
11 : QModuleWidget(Owner, parent),
12 ui(std::make_unique<Ui::LaserScanningSpectroscopy>())
13 {
14 ui->setupUi(this);
15
16 // For shortcuts
17 this->addAction(ui->action_Stop);
18 }
19
21 {
22 if (!GetUIInitialized())
23 {
24 const QSignalBlocker SBLowerFrequencyLimitBlocker(ui->SBLowerFrequencyLimit);
25 ui->SBLowerFrequencyLimit->setRange(ModuleData->GetLaser()->GetMinFrequency() * 1e-9, ModuleData->GetLaser()->GetMaxFrequency() * 1e-9);
26 ui->SBLowerFrequencyLimit->setValue(ModuleData->GetLaser()->GetMinFrequency() * 1e-9);
27
28 const QSignalBlocker SBUpperFrequencyLimitBlocker(ui->SBUpperFrequencyLimit);
29 ui->SBUpperFrequencyLimit->setRange(ModuleData->GetLaser()->GetMinFrequency() * 1e-9, ModuleData->GetLaser()->GetMaxFrequency() * 1e-9);
30 ui->SBUpperFrequencyLimit->setValue((ModuleData->GetLaser()->GetMinFrequency() + ModuleData->GetLaser()->GetModeHopFreeTuningRange()) * 1e-9);
31
32 const QSignalBlocker SBFrequencyRangeBlocker(ui->SBFrequencyRange);
33 ui->SBFrequencyRange->setRange(0.0, ModuleData->GetLaser()->GetModeHopFreeTuningRange() * 1e-9);
34 ui->SBFrequencyRange->setValue(ModuleData->GetLaser()->GetModeHopFreeTuningRange() * 1e-9);
35
36 const QSignalBlocker SBCenterFrequencyBlocker(ui->SBCenterFrequency);
37 ui->SBCenterFrequency->setRange(ModuleData->GetLaser()->GetMinFrequency() * 1e-9 + 0.5 * ModuleData->GetLaser()->GetModeHopFreeTuningRange() * 1e-9, ModuleData->GetLaser()->GetMaxFrequency() * 1e-9 - 0.5 * ModuleData->GetLaser()->GetModeHopFreeTuningRange() * 1e-9);
38 ui->SBCenterFrequency->setValue(ModuleData->GetLaser()->GetMinFrequency() * 1e-9 + 0.5 * ModuleData->GetLaser()->GetModeHopFreeTuningRange() * 1e-9);
39
40 const QSignalBlocker SBStepSizeBlocker(ui->SBStepSize);
41 ui->SBStepSize->setRange(1, 10000);
42 ui->SBStepSize->setValue(100);
43
44 const QSignalBlocker SBNumberOfStepsBlocker(ui->SBNumberOfSteps);
45 ui->SBNumberOfSteps->setRange(1, 10000);
46 ui->SBNumberOfSteps->setValue(ui->SBFrequencyRange->value() * 1e3 / ui->SBStepSize->value());
47
48 const QSignalBlocker SBNumberOfRepetitionsBlocker(ui->SBNumberOfRepetitions);
49 ui->SBNumberOfRepetitions->setRange(1, 10000);
50 ui->SBNumberOfRepetitions->setValue(1);
51
52 ModuleData->LowerFrequencyLimit = ui->SBLowerFrequencyLimit->value() * 1e9;
53 ModuleData->UpperFrequencyLimit = ui->SBUpperFrequencyLimit->value() * 1e9;
54 ModuleData->FrequencyRange = ui->SBFrequencyRange->value() * 1e9;
55 ModuleData->CenterFrequency = ui->SBCenterFrequency->value() * 1e9;
56 ModuleData->StepSize = ui->SBStepSize->value() * 1e6;
57 ModuleData->NumberOfSteps = ui->SBNumberOfSteps->value();
58 ModuleData->NumberOfRepetitions = ui->SBNumberOfRepetitions->value();
59 ModuleData->ScanBackAndForth = ui->CBScanBackAndForth->isChecked();
60
61 ModuleData->ScanStartFrequency = ui->RBStartAtMinimum->isChecked() ? ModuleData->LowerFrequencyLimit : ModuleData->UpperFrequencyLimit;
62 ModuleData->ScanEndFrequency = ui->RBStartAtMinimum->isChecked() ? ModuleData->UpperFrequencyLimit : ModuleData->LowerFrequencyLimit;
63
64 UIInitialized = true;
65 }
66 }
67
69 {
70 auto Filename = Util::PromptSaveFilePathModule(this, "Select directory and filename prefix for saving data", ".csv", "Comma-separated values file (*.csv)");
71 if (Filename.isEmpty())
72 return;
73
74 // Emits signal to update module data accordingly.
75 ui->LEPath->setText(Filename);
76 }
77
82
109
111 : QModuleBase(OwnerThreadID, std::move(Params)),
112 StateMachine(ReadyState, WaitForSettingFrequencyState, WaitForCapturingState)
113 {
114 }
115
117 {
118 try
119 {
120 auto ModuleData = DynExp::dynamic_ModuleData_cast<LaserScanningSpectroscopy>(Instance.ModuleDataGetter());
121
122 ModuleData->LaserState = DynExp::dynamic_InstrumentData_cast<DynExpInstr::Laser>(ModuleData->GetLaser()->GetInstrumentData())->GetLaserState();
123
124 StateMachine.Invoke(*this, Instance);
125
127 }
128
129 catch (const Util::TimeoutException& e)
130 {
131 if (NumFailedUpdateAttempts++ >= 3)
132 Instance.GetOwner().SetWarning(e);
133 }
134
136 }
137
144
145 std::unique_ptr<DynExp::QModuleWidget> LaserScanningSpectroscopy::MakeUIWidget()
146 {
147 auto Widget = std::make_unique<LaserScanningSpectroscopyWidget>(*this);
148
149 Connect(Widget->GetUI()->action_Start, &QAction::triggered, this, &LaserScanningSpectroscopy::OnStartClicked);
150 Connect(Widget->GetUI()->action_Stop, &QAction::triggered, this, &LaserScanningSpectroscopy::OnStopClicked);
151 Connect(Widget->GetUI()->action_StepwiseScan, &QAction::toggled, this, &LaserScanningSpectroscopy::OnStartAtToggled);
152
153 Connect(Widget->GetUI()->SBLowerFrequencyLimit, QOverload<double>::of(&QDoubleSpinBox::valueChanged), this, &LaserScanningSpectroscopy::OnLowerFrequencyLimitChanged);
154 Connect(Widget->GetUI()->SBUpperFrequencyLimit, QOverload<double>::of(&QDoubleSpinBox::valueChanged), this, &LaserScanningSpectroscopy::OnUpperFrequencyLimitChanged);
155 Connect(Widget->GetUI()->SBFrequencyRange, QOverload<double>::of(&QDoubleSpinBox::valueChanged), this, &LaserScanningSpectroscopy::OnFrequencyRangeChanged);
156 Connect(Widget->GetUI()->SBCenterFrequency, QOverload<double>::of(&QDoubleSpinBox::valueChanged), this, &LaserScanningSpectroscopy::OnCenterFrequencyChanged);
157 Connect(Widget->GetUI()->SBStepSize, QOverload<double>::of(&QDoubleSpinBox::valueChanged), this, &LaserScanningSpectroscopy::OnStepSizeChanged);
158 Connect(Widget->GetUI()->SBNumberOfSteps, QOverload<int>::of(&QSpinBox::valueChanged), this, &LaserScanningSpectroscopy::OnNumberOfStepsChanged);
159 Connect(Widget->GetUI()->SBNumberOfRepetitions, QOverload<int>::of(&QSpinBox::valueChanged), this, &LaserScanningSpectroscopy::OnNumberOfRepetitionsChanged);
160 Connect(Widget->GetUI()->CBScanBackAndForth, &QCheckBox::toggled, this, &LaserScanningSpectroscopy::OnScanBackAndForthToggled);
161 Connect(Widget->GetUI()->RBStartAtMinimum, &QRadioButton::toggled, this, &LaserScanningSpectroscopy::OnStartAtToggled);
162 Connect(Widget->GetUI()->RBStartAtMaximum, &QRadioButton::toggled, this, &LaserScanningSpectroscopy::OnStartAtToggled);
163 Connect(Widget->GetUI()->LEPath, &QLineEdit::textChanged, this, static_cast<void(LaserScanningSpectroscopy::*)(DynExp::ModuleInstance*, const QString) const>(&LaserScanningSpectroscopy::OnPathChanged));
164
165 return Widget;
166 }
167
168 void LaserScanningSpectroscopy::UpdateUIChild(const ModuleBase::ModuleDataGetterType& ModuleDataGetter)
169 {
170 auto Widget = GetWidget<LaserScanningSpectroscopyWidget>();
171 const bool Ready = IsReadyState();
172 const bool SettingFrequency = IsSettingFrequencyState();
173 const bool Capturing = IsCapturingState();
174 std::string UIMessage;
175
176 {
177 auto ModuleData = DynExp::dynamic_ModuleData_cast<LaserScanningSpectroscopy>(ModuleDataGetter());
178
179 Widget->InitializeUI(ModuleData);
180
181 Widget->GetUI()->action_Start->setEnabled(Ready);
182 Widget->GetUI()->action_Stop->setEnabled(!Ready);
183 Widget->GetUI()->action_StepwiseScan->setEnabled(Ready);
184
185 Widget->GetUI()->SBLowerFrequencyLimit->setEnabled(Ready);
186 Widget->GetUI()->SBUpperFrequencyLimit->setEnabled(Ready);
187 Widget->GetUI()->SBFrequencyRange->setEnabled(Ready);
188 Widget->GetUI()->SBCenterFrequency->setEnabled(Ready);
189 Widget->GetUI()->SBStepSize->setEnabled(Ready);
190 Widget->GetUI()->SBNumberOfSteps->setEnabled(Ready);
191 Widget->GetUI()->SBNumberOfRepetitions->setEnabled(Ready);
192 Widget->GetUI()->CBScanBackAndForth->setEnabled(Ready && ModuleData->IsStepwiseScan);
193 Widget->GetUI()->RBStartAtMinimum->setEnabled(Ready && ModuleData->IsStepwiseScan);
194 Widget->GetUI()->RBStartAtMaximum->setEnabled(Ready && ModuleData->IsStepwiseScan);
195
196 Widget->GetUI()->PBLaserScanningSpectroscopyProgress->setVisible(!Ready);
197 Widget->GetUI()->PBLaserScanningSpectroscopyProgress->setValue(static_cast<int>(100.0 *
198 ModuleData->LaserScanningSpectroscopyProgress / ModuleData->NumberOfRepetitions / (ModuleData->NumberOfSteps + 1)));
199
200 if (SettingFrequency)
201 Widget->GetUI()->LLaserScanningSpectroscopyState->setText(" Stabilizing");
202 else if (Capturing)
203 Widget->GetUI()->LLaserScanningSpectroscopyState->setText(" Capturing");
204 else
205 Widget->GetUI()->LLaserScanningSpectroscopyState->setText(" Ready");
206
207 ModuleData->ScanStartFrequency = Widget->GetUI()->RBStartAtMinimum->isChecked() ? ModuleData->LowerFrequencyLimit : ModuleData->UpperFrequencyLimit;
208 ModuleData->ScanEndFrequency = Widget->GetUI()->RBStartAtMinimum->isChecked() ? ModuleData->UpperFrequencyLimit : ModuleData->LowerFrequencyLimit;
209
210 if (ModuleData->FileSavePathChanged)
211 {
212 const QSignalBlocker LEPathBlocker(Widget->GetUI()->LEPath);
213 Widget->GetUI()->LEPath->setText(QString::fromStdString(ModuleData->FileSavePath.string()));
214
215 ModuleData->FileSavePathChanged = false;
216 }
217
218 if (!ModuleData->GetUIMessage().empty())
219 {
220 UIMessage = ModuleData->GetUIMessage();
221 ModuleData->ClearUIMessage();
222 }
223 } // ModuleData unlocked here.
224
225 if (!UIMessage.empty())
226 QMessageBox::warning(Widget, "Laser Control", UIMessage.data());
227 }
228
230 {
231 return StateMachine.GetCurrentState()->GetState() == StateType::Ready;
232 }
233
235 {
236 return StateMachine.GetCurrentState()->GetState() == StateType::WaitForSettingFrequency;
237 }
238
240 {
241 return StateMachine.GetCurrentState()->GetState() == StateType::WaitForCapturing;
242 }
243
245 {
246 auto ModuleData = DynExp::dynamic_ModuleData_cast<LaserScanningSpectroscopy>(Instance->ModuleDataGetter());
247
248 double Frequency = 0.0;
249
250 if (!ModuleData->CurrentStepCount && !ModuleData->CurrentRepCount)
251 Frequency = ModuleData->ScanStartFrequency;
252 else
253 {
254 if ((ModuleData->ScanStartFrequency == ModuleData->LowerFrequencyLimit && ModuleData->ScanBackAndForth && ModuleData->CurrentRepCount % 2 == 0) ||
255 (ModuleData->ScanStartFrequency == ModuleData->UpperFrequencyLimit && ModuleData->ScanBackAndForth && ModuleData->CurrentRepCount % 2 == 1) ||
256 (ModuleData->ScanStartFrequency == ModuleData->LowerFrequencyLimit && !ModuleData->ScanBackAndForth))
257 Frequency = ModuleData->LowerFrequencyLimit + ModuleData->CurrentStepCount * ModuleData->StepSize;
258 else
259 Frequency = ModuleData->UpperFrequencyLimit - ModuleData->CurrentStepCount * ModuleData->StepSize;
260 }
261
262 ModuleData->GetLaser()->SetFrequency(Frequency);
263 }
264
265 std::filesystem::path LaserScanningSpectroscopy::BuildFilename(Util::SynchronizedPointer<ModuleDataType>& ModuleData, std::string_view FilenameSuffix) const
266 {
267 auto SavePath = ModuleData->FileSavePath;
268 SavePath.replace_filename(SavePath.filename().stem().concat(FilenameSuffix));
269 std::filesystem::create_directories(SavePath.parent_path());
270
271 return SavePath;
272 }
273
275 {
276 auto ModuleParams = DynExp::dynamic_Params_cast<LaserScanningSpectroscopy>(Instance->ParamsGetter());
277 auto ModuleData = DynExp::dynamic_ModuleData_cast<LaserScanningSpectroscopy>(Instance->ModuleDataGetter());
278
279 if (ModuleParams->PLECommunicator.ContainsID())
280 {
281 Instance->LockObject(ModuleParams->PLECommunicator, ModuleData->GetPLECommunicator());
283 }
284 if (ModuleParams->WFCommunicator.ContainsID())
285 {
286 Instance->LockObject(ModuleParams->WFCommunicator, ModuleData->GetWFCommunicator());
287 StartEvent::Register(*this, &LaserScanningSpectroscopy::OnStart, ModuleData->GetWFCommunicator()->GetID());
288 StopEvent::Register(*this, &LaserScanningSpectroscopy::OnStop, ModuleData->GetWFCommunicator()->GetID());
290 ModuleData->GetWFCommunicator()->GetID());
291 }
292
293 Instance->LockObject(ModuleParams->Laser, ModuleData->GetLaser());
294 ModuleData->ModeHopFreeTuningRange = ModuleData->GetLaser()->GetModeHopFreeTuningRange();
295 }
296
298 {
299 auto ModuleData = DynExp::dynamic_ModuleData_cast<LaserScanningSpectroscopy>(Instance->ModuleDataGetter());
300
301 Instance->UnlockObject(ModuleData->GetPLECommunicator());
302 Instance->UnlockObject(ModuleData->GetWFCommunicator());
303 Instance->UnlockObject(ModuleData->GetLaser());
304
309 }
310
312 {
313 auto ModuleData = DynExp::dynamic_ModuleData_cast<LaserScanningSpectroscopy>(Instance->ModuleDataGetter());
314
315 ModuleData->GetPLECommunicator()->PostEvent(*this, StartEvent{});
316
317 ModuleData->CurrentStepCount = 0;
318 ModuleData->CurrentRepCount = 0;
319 ModuleData->LaserScanningSpectroscopyProgress = 0;
320
321 FrequencyStep(Instance);
322
323 auto ModuleParams = DynExp::dynamic_Params_cast<LaserScanningSpectroscopy>(Instance->ParamsGetter());
324 WaitingEndTimePoint = std::chrono::system_clock::now() + std::chrono::milliseconds(ModuleParams->CapturingTimeDifference);
325
327 }
328
330 {
331 OnStart(Instance);
332 }
333
335 {
336 auto ModuleData = DynExp::dynamic_ModuleData_cast<LaserScanningSpectroscopy>(Instance->ModuleDataGetter());
337
338 ModuleData->GetPLECommunicator()->PostEvent(*this, StopEvent{});
339 ModuleData->GetLaser()->DisableScan();
340
341 StateMachine.SetCurrentState(StateType::Ready);
342 }
343
345 {
346 OnStop(Instance);
347 }
348
350 {
351 auto ModuleData = DynExp::dynamic_ModuleData_cast<LaserScanningSpectroscopy>(Instance->ModuleDataGetter());
352 auto Widget = GetWidget<LaserScanningSpectroscopyWidget>();
353
354 double NewFrequencyRange = ModuleData->UpperFrequencyLimit - LowerFrequencyLimit * 1e9;
355 ModuleData->LowerFrequencyLimit = LowerFrequencyLimit * 1e9;
356
357 if (NewFrequencyRange < 0)
358 {
359 NewFrequencyRange = ModuleData->FrequencyRange;
360 ModuleData->UpperFrequencyLimit = LowerFrequencyLimit * 1e9 + NewFrequencyRange;
361 }
362 else if (NewFrequencyRange > ModuleData->ModeHopFreeTuningRange)
363 {
364 NewFrequencyRange = ModuleData->ModeHopFreeTuningRange;
365 ModuleData->UpperFrequencyLimit = LowerFrequencyLimit * 1e9 + NewFrequencyRange;
366 }
367
368 // Modify FrequencyRange, CenterFrequency and UpperFrequencyLimit to match new LowerFrequencyLimit.
369 ModuleData->CenterFrequency = LowerFrequencyLimit * 1e9 + NewFrequencyRange / 2;
370 ModuleData->FrequencyRange = NewFrequencyRange;
371 ModuleData->NumberOfSteps = NewFrequencyRange / ModuleData->StepSize;
372 ModuleData->GetLaser()->SetScanRange(NewFrequencyRange);
373
374 const QSignalBlocker SBUpperFrequencyLimitBlocker(Widget->GetUI()->SBUpperFrequencyLimit);
375 const QSignalBlocker SBFrequencyRangeBlocker(Widget->GetUI()->SBFrequencyRange);
376 const QSignalBlocker SBCenterFrequencyBlocker(Widget->GetUI()->SBCenterFrequency);
377 const QSignalBlocker SBNumberOfStepsBlocker(Widget->GetUI()->SBNumberOfSteps);
378 Widget->GetUI()->SBUpperFrequencyLimit->setValue(ModuleData->UpperFrequencyLimit / 1e9);
379 Widget->GetUI()->SBFrequencyRange->setValue(ModuleData->FrequencyRange / 1e9);
380 Widget->GetUI()->SBCenterFrequency->setValue(ModuleData->CenterFrequency / 1e9);
381 Widget->GetUI()->SBNumberOfSteps->setValue(ModuleData->NumberOfSteps);
382 }
383
385 {
386 auto ModuleData = DynExp::dynamic_ModuleData_cast<LaserScanningSpectroscopy>(Instance->ModuleDataGetter());
387 auto Widget = GetWidget<LaserScanningSpectroscopyWidget>();
388
389 double NewFrequencyRange = UpperFrequencyLimit * 1e9 - ModuleData->LowerFrequencyLimit;
390 ModuleData->UpperFrequencyLimit = UpperFrequencyLimit * 1e9;
391
392 if (NewFrequencyRange < 0)
393 {
394 NewFrequencyRange = ModuleData->FrequencyRange;
395 ModuleData->LowerFrequencyLimit = UpperFrequencyLimit * 1e9 - NewFrequencyRange;
396 }
397 else if (NewFrequencyRange > ModuleData->ModeHopFreeTuningRange)
398 {
399 NewFrequencyRange = ModuleData->ModeHopFreeTuningRange;
400 ModuleData->LowerFrequencyLimit = UpperFrequencyLimit * 1e9 - NewFrequencyRange;
401 }
402
403 // Modify FrequencyRange, CenterFrequency and LowerFrequencyLimit to match new UpperFrequencyLimit.
404 ModuleData->CenterFrequency = UpperFrequencyLimit * 1e9 - NewFrequencyRange / 2;
405 ModuleData->FrequencyRange = NewFrequencyRange;
406 ModuleData->NumberOfSteps = NewFrequencyRange / ModuleData->StepSize;
407 ModuleData->GetLaser()->SetScanRange(NewFrequencyRange);
408
409 const QSignalBlocker SBLowerFrequencyLimitBlocker(Widget->GetUI()->SBLowerFrequencyLimit);
410 const QSignalBlocker SBFrequencyRangeBlocker(Widget->GetUI()->SBFrequencyRange);
411 const QSignalBlocker SBCenterFrequencyBlocker(Widget->GetUI()->SBCenterFrequency);
412 const QSignalBlocker SBNumberOfStepsBlocker(Widget->GetUI()->SBNumberOfSteps);
413 Widget->GetUI()->SBLowerFrequencyLimit->setValue(ModuleData->LowerFrequencyLimit / 1e9);
414 Widget->GetUI()->SBFrequencyRange->setValue(NewFrequencyRange / 1e9);
415 Widget->GetUI()->SBCenterFrequency->setValue(ModuleData->CenterFrequency / 1e9);
416 Widget->GetUI()->SBNumberOfSteps->setValue(ModuleData->NumberOfSteps);
417 }
418
420 {
421 auto ModuleData = DynExp::dynamic_ModuleData_cast<LaserScanningSpectroscopy>(Instance->ModuleDataGetter());
422 auto Widget = GetWidget<LaserScanningSpectroscopyWidget>();
423
424 ModuleData->FrequencyRange = FrequencyRange * 1e9;
425 const double NewFrequencyRange = FrequencyRange * 1e9 <= ModuleData->ModeHopFreeTuningRange ? FrequencyRange * 1e9 : ModuleData->ModeHopFreeTuningRange;
426
427 // Modify CenterFrequency and UpperFrequencyLimit to match new FrequencyRange.
428 ModuleData->UpperFrequencyLimit = ModuleData->LowerFrequencyLimit + NewFrequencyRange;
429 ModuleData->CenterFrequency = ModuleData->LowerFrequencyLimit + NewFrequencyRange / 2;
430 ModuleData->FrequencyRange = NewFrequencyRange;
431 ModuleData->NumberOfSteps = NewFrequencyRange / ModuleData->StepSize;
432 ModuleData->GetLaser()->SetScanRange(NewFrequencyRange);
433
434 const QSignalBlocker SBUpperFrequencyLimitBlocker(Widget->GetUI()->SBUpperFrequencyLimit);
435 const QSignalBlocker SBFrequencyRangeBlocker(Widget->GetUI()->SBFrequencyRange);
436 const QSignalBlocker SBCenterFrequencyBlocker(Widget->GetUI()->SBCenterFrequency);
437 const QSignalBlocker SBNumberOfStepsBlocker(Widget->GetUI()->SBNumberOfSteps);
438 Widget->GetUI()->SBUpperFrequencyLimit->setValue(ModuleData->UpperFrequencyLimit / 1e9);
439 Widget->GetUI()->SBFrequencyRange->setValue(ModuleData->FrequencyRange / 1e9);
440 Widget->GetUI()->SBCenterFrequency->setValue(ModuleData->CenterFrequency / 1e9);
441 Widget->GetUI()->SBNumberOfSteps->setValue(ModuleData->NumberOfSteps);
442 }
443
445 {
446 auto Widget = GetWidget<LaserScanningSpectroscopyWidget>();
447 auto ModuleData = DynExp::dynamic_ModuleData_cast<LaserScanningSpectroscopy>(Instance->ModuleDataGetter());
448
449 ModuleData->CenterFrequency = CenterFrequency * 1e9;
450
451 // Modify LowerFrequencyLimit and UpperFrequencyLimit to match new CenterFrequency.
452 ModuleData->UpperFrequencyLimit = CenterFrequency * 1e9 + ModuleData->FrequencyRange / 2;
453 ModuleData->LowerFrequencyLimit = CenterFrequency * 1e9 - ModuleData->FrequencyRange / 2;
454
455 const QSignalBlocker SBLowerFrequencyLimitBlocker(Widget->GetUI()->SBLowerFrequencyLimit);
456 const QSignalBlocker SBUpperFrequencyLimitBlocker(Widget->GetUI()->SBUpperFrequencyLimit);
457 Widget->GetUI()->SBLowerFrequencyLimit->setValue(ModuleData->LowerFrequencyLimit / 1e9);
458 Widget->GetUI()->SBUpperFrequencyLimit->setValue(ModuleData->UpperFrequencyLimit / 1e9);
459 }
460
462 {
463 auto Widget = GetWidget<LaserScanningSpectroscopyWidget>();
464 auto ModuleData = DynExp::dynamic_ModuleData_cast<LaserScanningSpectroscopy>(Instance->ModuleDataGetter());
465
466 ModuleData->StepSize = StepSize * 1e6;
467
468 // Modify NumberOfSteps to match new StepSize.
469 ModuleData->NumberOfSteps = ModuleData->FrequencyRange / ModuleData->StepSize;
470
471 const QSignalBlocker SBNumberOfStepsBlocker(Widget->GetUI()->SBNumberOfSteps);
472 Widget->GetUI()->SBNumberOfSteps->setValue(ModuleData->NumberOfSteps);
473 }
474
476 {
477 auto Widget = GetWidget<LaserScanningSpectroscopyWidget>();
478 auto ModuleData = DynExp::dynamic_ModuleData_cast<LaserScanningSpectroscopy>(Instance->ModuleDataGetter());
479
480 ModuleData->NumberOfSteps = NumberOfSteps;
481
482 // Modify StepSize to match new NumberOfSteps.
483 ModuleData->StepSize = ModuleData->FrequencyRange / ModuleData->NumberOfSteps;
484
485 const QSignalBlocker SBStepSizeBlocker(Widget->GetUI()->SBStepSize);
486 Widget->GetUI()->SBStepSize->setValue(ModuleData->StepSize / 1e6);
487 }
488
490 {
491 auto ModuleData = DynExp::dynamic_ModuleData_cast<LaserScanningSpectroscopy>(Instance->ModuleDataGetter());
492 ModuleData->NumberOfRepetitions = NumberOfRepetitions;
493 }
494
496 {
497 auto ModuleData = DynExp::dynamic_ModuleData_cast<LaserScanningSpectroscopy>(Instance->ModuleDataGetter());
498 ModuleData->ScanBackAndForth = Checked;
499 }
500
502 {
503 auto Widget = GetWidget<LaserScanningSpectroscopyWidget>();
504 auto ModuleData = DynExp::dynamic_ModuleData_cast<LaserScanningSpectroscopy>(Instance->ModuleDataGetter());
505
506 ModuleData->IsStepwiseScan = Widget->GetUI()->action_StepwiseScan->isChecked();
507 if (ModuleData->IsStepwiseScan)
508 {
509 ModuleData->ScanStartFrequency = Widget->GetUI()->RBStartAtMinimum->isChecked() ? ModuleData->LowerFrequencyLimit : ModuleData->UpperFrequencyLimit;
510 ModuleData->ScanEndFrequency = Widget->GetUI()->RBStartAtMinimum->isChecked() ? ModuleData->UpperFrequencyLimit : ModuleData->LowerFrequencyLimit;
511 }
512 else
513 {
514 ModuleData->ScanStartFrequency = ModuleData->CenterFrequency;
515 ModuleData->ScanEndFrequency = 0.0;
516 }
517 }
518
519 void LaserScanningSpectroscopy::OnPathChanged(DynExp::ModuleInstance* Instance, const QString SaveFilename) const
520 {
521 OnPathChanged(Instance, SaveFilename.toStdString());
522 }
523
524 void LaserScanningSpectroscopy::OnPathChanged(DynExp::ModuleInstance* Instance, const std::string& SaveFilename) const
525 {
526 auto ModuleData = DynExp::dynamic_ModuleData_cast<LaserScanningSpectroscopy>(Instance->ModuleDataGetter());
527 ModuleData->FileSavePath = std::filesystem::path(SaveFilename);
528 ModuleData->FileSavePathChanged = true;
529 }
530
532 {
533 auto ModuleData = DynExp::dynamic_ModuleData_cast<LaserScanningSpectroscopy>(Instance->ModuleDataGetter());
534
535 if (ModuleData->CurrentStepCount > ModuleData->NumberOfSteps)
536 {
537 ModuleData->CurrentStepCount = 0;
538 ModuleData->CurrentRepCount++;
539
540 if (ModuleData->CurrentRepCount >= ModuleData->NumberOfRepetitions)
541 {
542 // Turn off continuous scan mode.
543 ModuleData->GetLaser()->DisableScan();
544
545 ModuleData->GetPLECommunicator()->PostEvent(*this, FinishedEvent{});
546 ModuleData->GetWFCommunicator()->PostEvent(*this, FinishedEvent{});
547
548 StateMachine.SetCurrentState(StateType::Ready);
549
550 return;
551 }
552 }
553
554 if (ModuleData->IsStepwiseScan)
555 FrequencyStep(Instance);
556
557 auto ModuleParams = DynExp::dynamic_Params_cast<LaserScanningSpectroscopy>(Instance->ParamsGetter());
558 WaitingEndTimePoint = std::chrono::system_clock::now() + std::chrono::milliseconds(ModuleParams->CapturingTimeDifference);
559
561 }
562
567
569 {
570 auto ModuleData = DynExp::dynamic_ModuleData_cast<LaserScanningSpectroscopy>(Instance.ModuleDataGetter());
571 auto LaserInstrData = DynExp::dynamic_InstrumentData_cast<DynExpInstr::Laser>(ModuleData->GetLaser()->GetInstrumentData());
572
573 if (ModuleData->IsStepwiseScan || (!ModuleData->CurrentStepCount && !ModuleData->CurrentRepCount))
574 {
575 if (LaserInstrData->GetLaserState() != DynExpInstr::LaserData::LaserStateType::Ready &&
578 }
579 else
580 {
581 if (!ModuleData->CurrentRepCount && ModuleData->CurrentStepCount == 1)
582 {
583 auto ModuleParams = DynExp::dynamic_Params_cast<LaserScanningSpectroscopy>(Instance.ParamsGetter());
584
585 ModuleData->GetLaser()->SetScanRange(ModuleData->FrequencyRange);
586 ModuleData->GetLaser()->SetScanRate(ModuleData->FrequencyRange / (2 * ModuleData->NumberOfSteps * ModuleParams->CapturingTimeDifference));
587
588 // Turn on continuous scan mode.
589 ModuleData->GetLaser()->ScanContinuously();
590 }
591
592 if (std::chrono::system_clock::now() < WaitingEndTimePoint)
594 }
595
596 auto Suffix = std::string("_CenterHz_") + Util::ToStr(ModuleData->CenterFrequency, 0)
597 + "_RangeHz_" + Util::ToStr(ModuleData->FrequencyRange, 0)
598 + "_CurrentFreqHz_" + Util::ToStr(LaserInstrData->GetFrequencyValue(), 0)
599 + "_Rep_" + Util::ToStr(ModuleData->CurrentRepCount)
600 + "_Step_" + Util::ToStr(ModuleData->CurrentStepCount);
601 auto Filename = BuildFilename(ModuleData, Suffix);
602
603 ModuleData->LaserScanningSpectroscopyProgress++;
604 ModuleData->CurrentStepCount++;
605
607 ModuleData->SetInvalidStartupStateMessage();
608
609 ModuleData->GetPLECommunicator()->PostEvent(*this, SetFilenameEvent{ Filename.string() });
610 ModuleData->GetPLECommunicator()->PostEvent(*this, TriggerEvent{});
611
613 }
614
619}
Implementation of a module to perform photoluminescence excitation spectroscopy.
@ Startup
The laser is warming up.
@ EmissionEnabledConstant
The laser is emitting in constant mode.
@ Ready
The laser is ready for emission.
This event signals that an action (like a measurement) started by a TriggerEvent has been completed.
LaserScanningSpectroscopyWidget(LaserScanningSpectroscopy &Owner, QModuleWidget *parent=nullptr)
void InitializeUI(Util::SynchronizedPointer< LaserScanningSpectroscopyData > &ModuleData)
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...
void OnStartAtToggled(DynExp::ModuleInstance *Instance, bool) const
void OnNumberOfRepetitionsChanged(DynExp::ModuleInstance *Instance, int NumberOfRepetitions) const
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...
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...
std::filesystem::path BuildFilename(Util::SynchronizedPointer< ModuleDataType > &ModuleData, std::string_view FilenameSuffix) const
void OnStepSizeChanged(DynExp::ModuleInstance *Instance, double StepSize) const
void OnExit(DynExp::ModuleInstance *Instance) const override final
This event is triggered right before the module thread terminates (not due to an exception,...
void OnLowerFrequencyLimitChanged(DynExp::ModuleInstance *Instance, double LowerFrequencyLimit) const
void OnPathChanged(DynExp::ModuleInstance *Instance, const std::string &SaveFilename) const
void OnNumberOfStepsChanged(DynExp::ModuleInstance *Instance, int NumberOfSteps) const
void OnUpperFrequencyLimitChanged(DynExp::ModuleInstance *Instance, double UpperFrequencyLimit) const
void UpdateUIChild(const ModuleBase::ModuleDataGetterType &ModuleDataGetter) override final
void OnScanBackAndForthToggled(DynExp::ModuleInstance *Instance, bool Checked) const
void OnFrequencyRangeChanged(DynExp::ModuleInstance *Instance, double FrequencyRange) const
void OnCenterFrequencyChanged(DynExp::ModuleInstance *Instance, double CenterFrequency) const
This event tells the receiver where to store e.g. acquired data.
This event is intended to make the receiver prepare an action (like a measurement) that is started wh...
This event is intended to make the receiver stop an action (like a measurement).
This event is intended to make the receiver start an action (like a measurement) after it received a ...
static void Register(const ModuleBase &Listener, CallableT EventFunc, ItemIDType CommunicatorID=ItemIDNotSet)
Registers/Subscribes module Listener to the event with the event function EventFunc....
Definition Module.h:1263
static void Deregister(const ModuleBase &Listener)
Deregisters/unsubscribes module Listener from the event, regardless of the inter-module communicator ...
Definition Module.h:1272
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
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
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
QString PromptSaveFilePathModule(DynExp::QModuleWidget *Parent, const QString &Title, const QString &DefaultSuffix, const QString &NameFilter)
Works as PromptOpenFilePath() but asks the user to select a single file which does not need to exist....
Definition QtUtil.cpp:143
Accumulates include statements to provide a precompiled header.