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
107
109 : QModuleBase(OwnerThreadID, std::move(Params)),
110 StateMachine(ReadyState, WaitForSettingFrequencyState, WaitForCapturingState)
111 {
112 }
113
115 {
116 try
117 {
118 auto ModuleData = DynExp::dynamic_ModuleData_cast<LaserScanningSpectroscopy>(Instance.ModuleDataGetter());
119
120 ModuleData->LaserState = DynExp::dynamic_InstrumentData_cast<DynExpInstr::Laser>(ModuleData->GetLaser()->GetInstrumentData())->GetLaserState();
121
122 StateMachine.Invoke(*this, Instance);
123
125 }
126
127 catch (const Util::TimeoutException& e)
128 {
129 if (NumFailedUpdateAttempts++ >= 3)
130 Instance.GetOwner().SetWarning(e);
131 }
132
134 }
135
142
143 std::unique_ptr<DynExp::QModuleWidget> LaserScanningSpectroscopy::MakeUIWidget()
144 {
145 auto Widget = std::make_unique<LaserScanningSpectroscopyWidget>(*this);
146
147 Connect(Widget->GetUI()->action_Start, &QAction::triggered, this, &LaserScanningSpectroscopy::OnStartClicked);
148 Connect(Widget->GetUI()->action_Stop, &QAction::triggered, this, &LaserScanningSpectroscopy::OnStopClicked);
149 Connect(Widget->GetUI()->action_StepwiseScan, &QAction::toggled, this, &LaserScanningSpectroscopy::OnStartAtToggled);
150
151 Connect(Widget->GetUI()->SBLowerFrequencyLimit, QOverload<double>::of(&QDoubleSpinBox::valueChanged), this, &LaserScanningSpectroscopy::OnLowerFrequencyLimitChanged);
152 Connect(Widget->GetUI()->SBUpperFrequencyLimit, QOverload<double>::of(&QDoubleSpinBox::valueChanged), this, &LaserScanningSpectroscopy::OnUpperFrequencyLimitChanged);
153 Connect(Widget->GetUI()->SBFrequencyRange, QOverload<double>::of(&QDoubleSpinBox::valueChanged), this, &LaserScanningSpectroscopy::OnFrequencyRangeChanged);
154 Connect(Widget->GetUI()->SBCenterFrequency, QOverload<double>::of(&QDoubleSpinBox::valueChanged), this, &LaserScanningSpectroscopy::OnCenterFrequencyChanged);
155 Connect(Widget->GetUI()->SBStepSize, QOverload<double>::of(&QDoubleSpinBox::valueChanged), this, &LaserScanningSpectroscopy::OnStepSizeChanged);
156 Connect(Widget->GetUI()->SBNumberOfSteps, QOverload<int>::of(&QSpinBox::valueChanged), this, &LaserScanningSpectroscopy::OnNumberOfStepsChanged);
157 Connect(Widget->GetUI()->SBNumberOfRepetitions, QOverload<int>::of(&QSpinBox::valueChanged), this, &LaserScanningSpectroscopy::OnNumberOfRepetitionsChanged);
158 Connect(Widget->GetUI()->CBScanBackAndForth, &QCheckBox::toggled, this, &LaserScanningSpectroscopy::OnScanBackAndForthToggled);
159 Connect(Widget->GetUI()->RBStartAtMinimum, &QRadioButton::toggled, this, &LaserScanningSpectroscopy::OnStartAtToggled);
160 Connect(Widget->GetUI()->RBStartAtMaximum, &QRadioButton::toggled, this, &LaserScanningSpectroscopy::OnStartAtToggled);
161 Connect(Widget->GetUI()->LEPath, &QLineEdit::textChanged, this, static_cast<void(LaserScanningSpectroscopy::*)(DynExp::ModuleInstance*, const QString) const>(&LaserScanningSpectroscopy::OnPathChanged));
162
163 return Widget;
164 }
165
166 void LaserScanningSpectroscopy::UpdateUIChild(const ModuleBase::ModuleDataGetterType& ModuleDataGetter)
167 {
168 const bool Ready = IsReadyState();
169 const bool SettingFrequency = IsSettingFrequencyState();
170 const bool Capturing = IsCapturingState();
171
172 auto Widget = GetWidget<LaserScanningSpectroscopyWidget>();
173 auto ModuleData = DynExp::dynamic_ModuleData_cast<LaserScanningSpectroscopy>(ModuleDataGetter());
174
175 Widget->InitializeUI(ModuleData);
176
177 Widget->GetUI()->action_Start->setEnabled(Ready && ModuleData->LaserState != DynExpInstr::LaserData::LaserStateType::Startup);
178 Widget->GetUI()->action_Stop->setEnabled(!Ready);
179 Widget->GetUI()->action_StepwiseScan->setEnabled(Ready);
180
181 Widget->GetUI()->SBLowerFrequencyLimit->setEnabled(Ready);
182 Widget->GetUI()->SBUpperFrequencyLimit->setEnabled(Ready);
183 Widget->GetUI()->SBFrequencyRange->setEnabled(Ready);
184 Widget->GetUI()->SBCenterFrequency->setEnabled(Ready);
185 Widget->GetUI()->SBStepSize->setEnabled(Ready);
186 Widget->GetUI()->SBNumberOfSteps->setEnabled(Ready);
187 Widget->GetUI()->SBNumberOfRepetitions->setEnabled(Ready);
188 Widget->GetUI()->CBScanBackAndForth->setEnabled(Ready && ModuleData->IsStepwiseScan);
189 Widget->GetUI()->RBStartAtMinimum->setEnabled(Ready && ModuleData->IsStepwiseScan);
190 Widget->GetUI()->RBStartAtMaximum->setEnabled(Ready && ModuleData->IsStepwiseScan);
191
192 Widget->GetUI()->PBLaserScanningSpectroscopyProgress->setVisible(!Ready);
193 Widget->GetUI()->PBLaserScanningSpectroscopyProgress->setValue(static_cast<int>(100.0 *
194 ModuleData->LaserScanningSpectroscopyProgress / ModuleData->NumberOfRepetitions / (ModuleData->NumberOfSteps + 1)));
195
196 if (SettingFrequency)
197 Widget->GetUI()->LLaserScanningSpectroscopyState->setText(" Stabilizing");
198 else if (Capturing)
199 Widget->GetUI()->LLaserScanningSpectroscopyState->setText(" Capturing");
200 else
201 Widget->GetUI()->LLaserScanningSpectroscopyState->setText(" Ready");
202
203 if (ModuleData->FileSavePathChanged)
204 {
205 const QSignalBlocker LEPathBlocker(Widget->GetUI()->LEPath);
206 Widget->GetUI()->LEPath->setText(QString::fromStdString(ModuleData->FileSavePath.string()));
207
208 ModuleData->FileSavePathChanged = false;
209 }
210 }
211
213 {
214 return StateMachine.GetCurrentState()->GetState() == StateType::Ready;
215 }
216
218 {
219 return StateMachine.GetCurrentState()->GetState() == StateType::WaitForSettingFrequency;
220 }
221
223 {
224 return StateMachine.GetCurrentState()->GetState() == StateType::WaitForCapturing;
225 }
226
228 {
229 auto ModuleData = DynExp::dynamic_ModuleData_cast<LaserScanningSpectroscopy>(Instance->ModuleDataGetter());
230
231 double Frequency = 0.0;
232
233 if (!ModuleData->CurrentStepCount)
234 Frequency = ModuleData->ScanStartFrequency;
235 else if (ModuleData->CurrentStepCount <= ModuleData->NumberOfSteps)
236 {
237 if ((ModuleData->ScanStartFrequency == ModuleData->LowerFrequencyLimit && ModuleData->ScanBackAndForth && ModuleData->CurrentRepCount % 2 == 0) ||
238 (ModuleData->ScanStartFrequency == ModuleData->UpperFrequencyLimit && ModuleData->ScanBackAndForth && ModuleData->CurrentRepCount % 2 == 1) ||
239 (ModuleData->ScanStartFrequency == ModuleData->LowerFrequencyLimit && !ModuleData->ScanBackAndForth))
240 Frequency = ModuleData->LowerFrequencyLimit + ModuleData->CurrentStepCount * ModuleData->StepSize;
241 else
242 Frequency = ModuleData->UpperFrequencyLimit - ModuleData->CurrentStepCount * ModuleData->StepSize;
243 }
244 else
245 {
246 ModuleData->CurrentStepCount = 0;
247
248 if (!ModuleData->ScanBackAndForth)
249 Frequency = ModuleData->ScanStartFrequency;
250 else
251 Frequency = (ModuleData->CurrentRepCount % 2 == 0) ? ModuleData->ScanStartFrequency : ModuleData->ScanEndFrequency;
252 }
253
254 ModuleData->GetLaser()->SetFrequency(Frequency);
255 }
256
257 std::filesystem::path LaserScanningSpectroscopy::BuildFilename(Util::SynchronizedPointer<ModuleDataType>& ModuleData, std::string_view FilenameSuffix) const
258 {
259 auto SavePath = ModuleData->FileSavePath;
260 SavePath.replace_filename(SavePath.filename().stem().concat(FilenameSuffix));
261 std::filesystem::create_directories(SavePath.parent_path());
262
263 return SavePath;
264 }
265
267 {
268 auto ModuleParams = DynExp::dynamic_Params_cast<LaserScanningSpectroscopy>(Instance->ParamsGetter());
269 auto ModuleData = DynExp::dynamic_ModuleData_cast<LaserScanningSpectroscopy>(Instance->ModuleDataGetter());
270
271 if (ModuleParams->PLECommunicator.ContainsID())
272 {
273 Instance->LockObject(ModuleParams->PLECommunicator, ModuleData->GetPLECommunicator());
275 }
276 if (ModuleParams->WFCommunicator.ContainsID())
277 {
278 Instance->LockObject(ModuleParams->WFCommunicator, ModuleData->GetWFCommunicator());
279 StartEvent::Register(*this, &LaserScanningSpectroscopy::OnStart, ModuleData->GetWFCommunicator()->GetID());
280 StopEvent::Register(*this, &LaserScanningSpectroscopy::OnStop, ModuleData->GetWFCommunicator()->GetID());
282 ModuleData->GetWFCommunicator()->GetID());
283 }
284
285 Instance->LockObject(ModuleParams->Laser, ModuleData->GetLaser());
286 ModuleData->ModeHopFreeTuningRange = ModuleData->GetLaser()->GetModeHopFreeTuningRange();
287 }
288
290 {
291 auto ModuleData = DynExp::dynamic_ModuleData_cast<LaserScanningSpectroscopy>(Instance->ModuleDataGetter());
292
293 Instance->UnlockObject(ModuleData->GetPLECommunicator());
294 Instance->UnlockObject(ModuleData->GetWFCommunicator());
295 Instance->UnlockObject(ModuleData->GetLaser());
296
301 }
302
304 {
305 auto ModuleData = DynExp::dynamic_ModuleData_cast<LaserScanningSpectroscopy>(Instance->ModuleDataGetter());
306
307 ModuleData->GetPLECommunicator()->PostEvent(*this, StartEvent{});
308
309 ModuleData->CurrentStepCount = 0;
310 ModuleData->CurrentRepCount = 0;
311 ModuleData->LaserScanningSpectroscopyProgress = 0;
312
313 FrequencyStep(Instance);
314
315 auto ModuleParams = DynExp::dynamic_Params_cast<LaserScanningSpectroscopy>(Instance->ParamsGetter());
316 WaitingEndTimePoint = std::chrono::system_clock::now() + std::chrono::milliseconds(ModuleParams->CapturingTimeDifference);
317
319 }
320
322 {
323 OnStart(Instance);
324 }
325
327 {
328 auto ModuleData = DynExp::dynamic_ModuleData_cast<LaserScanningSpectroscopy>(Instance->ModuleDataGetter());
329
330 ModuleData->GetPLECommunicator()->PostEvent(*this, StopEvent{});
331 ModuleData->GetLaser()->DisableScan();
332
333 StateMachine.SetCurrentState(StateType::Ready);
334 }
335
337 {
338 OnStop(Instance);
339 }
340
342 {
343 auto ModuleData = DynExp::dynamic_ModuleData_cast<LaserScanningSpectroscopy>(Instance->ModuleDataGetter());
344 auto Widget = GetWidget<LaserScanningSpectroscopyWidget>();
345
346 double NewFrequencyRange = ModuleData->UpperFrequencyLimit - LowerFrequencyLimit * 1e9;
347 ModuleData->LowerFrequencyLimit = LowerFrequencyLimit * 1e9;
348
349 if (NewFrequencyRange < 0)
350 {
351 NewFrequencyRange = ModuleData->FrequencyRange;
352 ModuleData->UpperFrequencyLimit = LowerFrequencyLimit * 1e9 + NewFrequencyRange;
353 }
354 else if (NewFrequencyRange > ModuleData->ModeHopFreeTuningRange)
355 {
356 NewFrequencyRange = ModuleData->ModeHopFreeTuningRange;
357 ModuleData->UpperFrequencyLimit = LowerFrequencyLimit * 1e9 + NewFrequencyRange;
358 }
359
360 // Modify FrequencyRange, CenterFrequency and UpperFrequencyLimit to match new LowerFrequencyLimit.
361 ModuleData->CenterFrequency = LowerFrequencyLimit * 1e9 + NewFrequencyRange / 2;
362 ModuleData->FrequencyRange = NewFrequencyRange;
363 ModuleData->NumberOfSteps = NewFrequencyRange / ModuleData->StepSize;
364 ModuleData->GetLaser()->SetScanRange(NewFrequencyRange);
365
366 const QSignalBlocker SBUpperFrequencyLimitBlocker(Widget->GetUI()->SBUpperFrequencyLimit);
367 const QSignalBlocker SBFrequencyRangeBlocker(Widget->GetUI()->SBFrequencyRange);
368 const QSignalBlocker SBCenterFrequencyBlocker(Widget->GetUI()->SBCenterFrequency);
369 const QSignalBlocker SBNumberOfStepsBlocker(Widget->GetUI()->SBNumberOfSteps);
370 Widget->GetUI()->SBUpperFrequencyLimit->setValue(ModuleData->UpperFrequencyLimit / 1e9);
371 Widget->GetUI()->SBFrequencyRange->setValue(ModuleData->FrequencyRange / 1e9);
372 Widget->GetUI()->SBCenterFrequency->setValue(ModuleData->CenterFrequency / 1e9);
373 Widget->GetUI()->SBNumberOfSteps->setValue(ModuleData->NumberOfSteps);
374 }
375
377 {
378 auto ModuleData = DynExp::dynamic_ModuleData_cast<LaserScanningSpectroscopy>(Instance->ModuleDataGetter());
379 auto Widget = GetWidget<LaserScanningSpectroscopyWidget>();
380
381 double NewFrequencyRange = UpperFrequencyLimit * 1e9 - ModuleData->LowerFrequencyLimit;
382 ModuleData->UpperFrequencyLimit = UpperFrequencyLimit * 1e9;
383
384 if (NewFrequencyRange < 0)
385 {
386 NewFrequencyRange = ModuleData->FrequencyRange;
387 ModuleData->LowerFrequencyLimit = UpperFrequencyLimit * 1e9 - NewFrequencyRange;
388 }
389 else if (NewFrequencyRange > ModuleData->ModeHopFreeTuningRange)
390 {
391 NewFrequencyRange = ModuleData->ModeHopFreeTuningRange;
392 ModuleData->LowerFrequencyLimit = UpperFrequencyLimit * 1e9 - NewFrequencyRange;
393 }
394
395 // Modify FrequencyRange, CenterFrequency and LowerFrequencyLimit to match new UpperFrequencyLimit.
396 ModuleData->CenterFrequency = UpperFrequencyLimit * 1e9 - NewFrequencyRange / 2;
397 ModuleData->FrequencyRange = NewFrequencyRange;
398 ModuleData->NumberOfSteps = NewFrequencyRange / ModuleData->StepSize;
399 ModuleData->GetLaser()->SetScanRange(NewFrequencyRange);
400
401 const QSignalBlocker SBLowerFrequencyLimitBlocker(Widget->GetUI()->SBLowerFrequencyLimit);
402 const QSignalBlocker SBFrequencyRangeBlocker(Widget->GetUI()->SBFrequencyRange);
403 const QSignalBlocker SBCenterFrequencyBlocker(Widget->GetUI()->SBCenterFrequency);
404 const QSignalBlocker SBNumberOfStepsBlocker(Widget->GetUI()->SBNumberOfSteps);
405 Widget->GetUI()->SBLowerFrequencyLimit->setValue(ModuleData->LowerFrequencyLimit / 1e9);
406 Widget->GetUI()->SBFrequencyRange->setValue(NewFrequencyRange / 1e9);
407 Widget->GetUI()->SBCenterFrequency->setValue(ModuleData->CenterFrequency / 1e9);
408 Widget->GetUI()->SBNumberOfSteps->setValue(ModuleData->NumberOfSteps);
409 }
410
412 {
413 auto ModuleData = DynExp::dynamic_ModuleData_cast<LaserScanningSpectroscopy>(Instance->ModuleDataGetter());
414 auto Widget = GetWidget<LaserScanningSpectroscopyWidget>();
415
416 ModuleData->FrequencyRange = FrequencyRange * 1e9;
417 const double NewFrequencyRange = FrequencyRange * 1e9 <= ModuleData->ModeHopFreeTuningRange ? FrequencyRange * 1e9 : ModuleData->ModeHopFreeTuningRange;
418
419 // Modify CenterFrequency and UpperFrequencyLimit to match new FrequencyRange.
420 ModuleData->UpperFrequencyLimit = ModuleData->LowerFrequencyLimit + NewFrequencyRange;
421 ModuleData->CenterFrequency = ModuleData->LowerFrequencyLimit + NewFrequencyRange / 2;
422 ModuleData->FrequencyRange = NewFrequencyRange;
423 ModuleData->NumberOfSteps = NewFrequencyRange / ModuleData->StepSize;
424 ModuleData->GetLaser()->SetScanRange(NewFrequencyRange);
425
426 const QSignalBlocker SBUpperFrequencyLimitBlocker(Widget->GetUI()->SBUpperFrequencyLimit);
427 const QSignalBlocker SBFrequencyRangeBlocker(Widget->GetUI()->SBFrequencyRange);
428 const QSignalBlocker SBCenterFrequencyBlocker(Widget->GetUI()->SBCenterFrequency);
429 const QSignalBlocker SBNumberOfStepsBlocker(Widget->GetUI()->SBNumberOfSteps);
430 Widget->GetUI()->SBUpperFrequencyLimit->setValue(ModuleData->UpperFrequencyLimit / 1e9);
431 Widget->GetUI()->SBFrequencyRange->setValue(ModuleData->FrequencyRange / 1e9);
432 Widget->GetUI()->SBCenterFrequency->setValue(ModuleData->CenterFrequency / 1e9);
433 Widget->GetUI()->SBNumberOfSteps->setValue(ModuleData->NumberOfSteps);
434 }
435
437 {
438 auto Widget = GetWidget<LaserScanningSpectroscopyWidget>();
439 auto ModuleData = DynExp::dynamic_ModuleData_cast<LaserScanningSpectroscopy>(Instance->ModuleDataGetter());
440
441 ModuleData->CenterFrequency = CenterFrequency * 1e9;
442
443 // Modify LowerFrequencyLimit and UpperFrequencyLimit to match new CenterFrequency.
444 ModuleData->UpperFrequencyLimit = CenterFrequency * 1e9 + ModuleData->FrequencyRange / 2;
445 ModuleData->LowerFrequencyLimit = CenterFrequency * 1e9 - ModuleData->FrequencyRange / 2;
446
447 const QSignalBlocker SBLowerFrequencyLimitBlocker(Widget->GetUI()->SBLowerFrequencyLimit);
448 const QSignalBlocker SBUpperFrequencyLimitBlocker(Widget->GetUI()->SBUpperFrequencyLimit);
449 Widget->GetUI()->SBLowerFrequencyLimit->setValue(ModuleData->LowerFrequencyLimit / 1e9);
450 Widget->GetUI()->SBUpperFrequencyLimit->setValue(ModuleData->UpperFrequencyLimit / 1e9);
451 }
452
454 {
455 auto Widget = GetWidget<LaserScanningSpectroscopyWidget>();
456 auto ModuleData = DynExp::dynamic_ModuleData_cast<LaserScanningSpectroscopy>(Instance->ModuleDataGetter());
457
458 ModuleData->StepSize = StepSize * 1e6;
459
460 // Modify NumberOfSteps to match new StepSize.
461 ModuleData->NumberOfSteps = ModuleData->FrequencyRange / ModuleData->StepSize;
462
463 const QSignalBlocker SBNumberOfStepsBlocker(Widget->GetUI()->SBNumberOfSteps);
464 Widget->GetUI()->SBNumberOfSteps->setValue(ModuleData->NumberOfSteps);
465 }
466
468 {
469 auto Widget = GetWidget<LaserScanningSpectroscopyWidget>();
470 auto ModuleData = DynExp::dynamic_ModuleData_cast<LaserScanningSpectroscopy>(Instance->ModuleDataGetter());
471
472 ModuleData->NumberOfSteps = NumberOfSteps;
473
474 // Modify StepSize to match new NumberOfSteps.
475 ModuleData->StepSize = ModuleData->FrequencyRange / ModuleData->NumberOfSteps;
476
477 const QSignalBlocker SBStepSizeBlocker(Widget->GetUI()->SBStepSize);
478 Widget->GetUI()->SBStepSize->setValue(ModuleData->StepSize / 1e6);
479 }
480
482 {
483 auto ModuleData = DynExp::dynamic_ModuleData_cast<LaserScanningSpectroscopy>(Instance->ModuleDataGetter());
484 ModuleData->NumberOfRepetitions = NumberOfRepetitions;
485 }
486
488 {
489 auto ModuleData = DynExp::dynamic_ModuleData_cast<LaserScanningSpectroscopy>(Instance->ModuleDataGetter());
490 ModuleData->ScanBackAndForth = Checked;
491 }
492
494 {
495 auto Widget = GetWidget<LaserScanningSpectroscopyWidget>();
496 auto ModuleData = DynExp::dynamic_ModuleData_cast<LaserScanningSpectroscopy>(Instance->ModuleDataGetter());
497
498 ModuleData->IsStepwiseScan = Widget->GetUI()->action_StepwiseScan->isChecked();
499 if (ModuleData->IsStepwiseScan)
500 {
501 ModuleData->ScanStartFrequency = Widget->GetUI()->RBStartAtMinimum->isChecked() ? ModuleData->LowerFrequencyLimit : ModuleData->UpperFrequencyLimit;
502 ModuleData->ScanEndFrequency = Widget->GetUI()->RBStartAtMinimum->isChecked() ? ModuleData->UpperFrequencyLimit : ModuleData->LowerFrequencyLimit;
503 }
504 else
505 {
506 ModuleData->ScanStartFrequency = ModuleData->CenterFrequency;
507 ModuleData->ScanEndFrequency = 0.0;
508 }
509 }
510
511 void LaserScanningSpectroscopy::OnPathChanged(DynExp::ModuleInstance* Instance, const QString SaveFilename) const
512 {
513 OnPathChanged(Instance, SaveFilename.toStdString());
514 }
515
516 void LaserScanningSpectroscopy::OnPathChanged(DynExp::ModuleInstance* Instance, const std::string& SaveFilename) const
517 {
518 auto ModuleData = DynExp::dynamic_ModuleData_cast<LaserScanningSpectroscopy>(Instance->ModuleDataGetter());
519 ModuleData->FileSavePath = std::filesystem::path(SaveFilename);
520 ModuleData->FileSavePathChanged = true;
521 }
522
524 {
525 auto ModuleData = DynExp::dynamic_ModuleData_cast<LaserScanningSpectroscopy>(Instance->ModuleDataGetter());
526
527 if (ModuleData->CurrentStepCount > ModuleData->NumberOfSteps)
528 {
529 ModuleData->CurrentStepCount = 0;
530 ModuleData->CurrentRepCount++;
531
532 if (ModuleData->CurrentRepCount >= ModuleData->NumberOfRepetitions)
533 {
534 // Turn off continuous scan mode.
535 ModuleData->GetLaser()->DisableScan();
536
537 ModuleData->GetPLECommunicator()->PostEvent(*this, FinishedEvent{});
538 ModuleData->GetWFCommunicator()->PostEvent(*this, FinishedEvent{});
539
540 StateMachine.SetCurrentState(StateType::Ready);
541
542 return;
543 }
544 }
545
546 if (ModuleData->IsStepwiseScan)
547 FrequencyStep(Instance);
548
549 auto ModuleParams = DynExp::dynamic_Params_cast<LaserScanningSpectroscopy>(Instance->ParamsGetter());
550 WaitingEndTimePoint = std::chrono::system_clock::now() + std::chrono::milliseconds(ModuleParams->CapturingTimeDifference);
551
553 }
554
559
561 {
562 auto ModuleData = DynExp::dynamic_ModuleData_cast<LaserScanningSpectroscopy>(Instance.ModuleDataGetter());
563 auto LaserInstrData = DynExp::dynamic_InstrumentData_cast<DynExpInstr::Laser>(ModuleData->GetLaser()->GetInstrumentData());
564
565 auto Suffix = std::string("_CenterHz_") + Util::ToStr(ModuleData->CenterFrequency, 0)
566 + "_RangeHz_" + Util::ToStr(ModuleData->FrequencyRange, 0)
567 + "_Rep_" + Util::ToStr(ModuleData->CurrentRepCount)
568 + "_Step_" + Util::ToStr(ModuleData->CurrentStepCount);
569 auto Filename = BuildFilename(ModuleData, Suffix);
570
571 if (ModuleData->IsStepwiseScan || (!ModuleData->CurrentStepCount && !ModuleData->CurrentRepCount))
572 {
573 if (LaserInstrData->GetLaserState() == DynExpInstr::LaserData::LaserStateType::Ready ||
575 {
576 ModuleData->GetPLECommunicator()->PostEvent(*this, SetFilenameEvent{ Filename.string() });
577 ModuleData->GetPLECommunicator()->PostEvent(*this, TriggerEvent{});
578
579 ModuleData->CurrentStepCount++;
580 ModuleData->LaserScanningSpectroscopyProgress++;
581
583 }
584 else
586 }
587 else
588 {
589 if (!ModuleData->CurrentRepCount && ModuleData->CurrentStepCount == 1)
590 {
591 auto ModuleParams = DynExp::dynamic_Params_cast<LaserScanningSpectroscopy>(Instance.ParamsGetter());
592
593 ModuleData->GetLaser()->SetScanRange(ModuleData->FrequencyRange);
594 ModuleData->GetLaser()->SetScanRate(ModuleData->FrequencyRange / (2 * ModuleData->NumberOfSteps * ModuleParams->CapturingTimeDifference));
595
596 // Turn on continuous scan mode.
597 ModuleData->GetLaser()->ScanContinuously();
598 }
599
600 if (std::chrono::system_clock::now() < WaitingEndTimePoint)
602
603 ModuleData->LaserScanningSpectroscopyProgress++;
604 ModuleData->CurrentStepCount++;
605
606 ModuleData->GetPLECommunicator()->PostEvent(*this, SetFilenameEvent{ Filename.string() });
607 ModuleData->GetPLECommunicator()->PostEvent(*this, TriggerEvent{});
608
610 }
611 }
612
617}
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:1262
static void Deregister(const ModuleBase &Listener)
Deregisters/unsubscribes module Listener from the event, regardless of the inter-module communicator ...
Definition Module.h:1271
const std::unique_ptr< ModuleDataType > ModuleData
Module data belonging to this ModuleBase instance.
Definition Module.h:788
Refer to ParamsBase::dispatch_tag.
Definition Module.h:191
Defines data for a thread belonging to a ModuleBase instance. Refer to RunnableInstance.
Definition Module.h:840
const ModuleBase::ModuleDataGetterType ModuleDataGetter
Getter for module's data. Refer to ModuleBase::ModuleDataGetterType.
Definition Module.h:872
Refer to ParamsBase::dispatch_tag.
Definition Object.h:2018
QModuleWidget * Widget
User interface widget belonging to the module.
Definition Module.h:1807
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:1816
const Object::ParamsGetterType ParamsGetter
Invoke to obtain the parameters (derived from ParamsBase) of Owner.
Definition Object.h:3710
void UnlockObject(LinkedObjectWrapperContainer< ObjectT > &ObjectWrapperContainer)
Unlocks an Object instance stored in the LinkedObjectWrapperContainer ObjectWrapperContainer....
Definition Object.h:3609
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:3593
const auto & GetOwner() const noexcept
Returns Owner.
Definition Object.h:3556
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: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:688
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.