DynExp
Highly flexible laboratory automation for dynamically changing experiments.
Loading...
Searching...
No Matches
LaserControl.cpp
Go to the documentation of this file.
1// This file is part of DynExp.
2
3#include "stdafx.h"
4#include "moc_LaserControl.cpp"
5#include "ui_LaserControl.h"
6#include "LaserControl.h"
7
8namespace DynExpModule
9{
11 : QModuleWidget(Owner, parent),
12 ui(std::make_unique<Ui::LaserControl>())
13 {
14 ui->setupUi(this);
15
16 // For shortcuts
17 this->addAction(ui->action_Enable);
18 }
19
21 {
22 const QSignalBlocker SBFrequencyBlocker(ui->SBFrequency);
23 ui->SBFrequency->setRange(ModuleData->HardwareMinFrequency * 1e-12, ModuleData->HardwareMaxFrequency * 1e-12);
24 ui->SBFrequency->setValue(ModuleData->HardwareMinFrequency * 1e-12);
25
26 const QSignalBlocker SBWavelengthBlocker(ui->SBWavelength);
27 ui->SBWavelength->setRange(Util::ConvertFrequencyWavelength(ModuleData->HardwareMaxFrequency) * 1e9, Util::ConvertFrequencyWavelength(ModuleData->HardwareMinFrequency) * 1e9);
28 ui->SBWavelength->setValue(Util::ConvertFrequencyWavelength(ModuleData->HardwareMaxFrequency) * 1e9);
29
30 const QSignalBlocker SBIntensityBlocker(ui->SBIntensity);
31 ui->SBIntensity->setRange(ModuleData->HardwareMinIntensity * 1e3, ModuleData->HardwareMaxIntensity * 1e3);
32 ui->SBIntensity->setValue(ModuleData->HardwareMinIntensity * 1e3);
33
34 const QSignalBlocker SBScanRangeBlocker(ui->SBScanRange);
35 ui->SBScanRange->setRange(ModuleData->HardwareMinScanRange * 1e-9, ModuleData->HardwareMaxScanRange * 1e-9);
36
37 const QSignalBlocker SBScanRateBlocker(ui->SBScanRate);
38 ui->SBScanRate->setRange(ModuleData->HardwareMinScanRate * 1e-9, ModuleData->HardwareMaxScanRate * 1e-9);
39
40 ui->GBFrequencyWavelength->setVisible(ModuleData->HardwareMinFrequency != ModuleData->HardwareMaxFrequency);
41 ui->GBIntensity->setVisible(ModuleData->HardwareMinIntensity != ModuleData->HardwareMaxIntensity);
42 ui->GBScanSettings->setVisible(ModuleData->HardwareMinScanRange != ModuleData->HardwareMaxScanRange);
43 ui->action_Scan->setEnabled(ModuleData->HardwareMinScanRange != ModuleData->HardwareMaxScanRange);
44 }
45
47 {
48 ui->action_Enable->setEnabled(ModuleData->LaserState == DynExpInstr::LaserData::LaserStateType::Ready ||
51 ui->action_Scan->setEnabled(ModuleData->LaserState == DynExpInstr::LaserData::LaserStateType::Ready ||
54
55 if (std::isnan(ModuleData->CurrentFrequency))
56 {
57 ui->LActualFrequency->setText("Output unstable");
58 ui->LActualWavelength->setText("Output unstable");
59 ui->LActualFrequency->setStyleSheet(DynExpUI::StatusBarWarningStyleSheet);
60 ui->LActualWavelength->setStyleSheet(DynExpUI::StatusBarWarningStyleSheet);
61 }
62 else
63 {
64 ui->LActualFrequency->setText(QString::number(ModuleData->CurrentFrequency * 1e-12, 'f', 6) + " THz");
65 ui->LActualWavelength->setText(QString::number(Util::ConvertFrequencyWavelength(ModuleData->CurrentFrequency) * 1e9, 'f', 6) + " nm");
66 ui->LActualFrequency->setStyleSheet("");
67 ui->LActualWavelength->setStyleSheet("");
68 }
69
70 if (ModuleData->CurrentIntensity < ModuleData->HardwareMinIntensity)
71 {
72 ui->LActualIntensity->setText(QString::number(ModuleData->CurrentIntensity * 1e3, 'f', 3) + " mW (Power low)");
73 ui->LActualIntensity->setStyleSheet(DynExpUI::StatusBarWarningStyleSheet);
74 }
75 else
76 {
77 ui->LActualIntensity->setText(QString::number(ModuleData->CurrentIntensity * 1e3, 'f', 3) + " mW");
78 ui->LActualIntensity->setStyleSheet("");
79 }
80
81 if (!ui->SBScanRange->hasFocus())
82 {
83 const QSignalBlocker Blocker(ui->SBScanRange);
84 ui->SBScanRange->setValue(ModuleData->CurrentScanRange * 1e-9);
85 }
86
87 if (!ui->SBScanRate->hasFocus())
88 {
89 const QSignalBlocker Blocker(ui->SBScanRate);
90 ui->SBScanRate->setValue(ModuleData->CurrentScanRate * 1e-9);
91 }
92
93 switch (ModuleData->LaserState)
94 {
96 ui->LState->setText(" Startup...");
97 ui->LState->setStyleSheet(DynExpUI::StatusBarReadyStyleSheetBright);
98 break;
100 ui->LState->setText(" Emitting in constant mode.");
101 ui->LState->setStyleSheet(DynExpUI::StatusBarBusyStyleSheet);
102 break;
104 ui->LState->setText(" Emitting in scanning mode.");
105 ui->LState->setStyleSheet(DynExpUI::StatusBarBusyStyleSheet);
106 break;
108 ui->LState->setText(" The Laser is in an error state.");
109 ui->LState->setStyleSheet(DynExpUI::StatusBarErrorStyleSheet);
110 break;
111 default:
112 ui->LState->setText(" Laser is ready for emission.");
113 ui->LState->setStyleSheet(DynExpUI::StatusBarReadyStyleSheetBright);
114 }
115 }
116
118 {
119 switch (FrequencyUnit)
120 {
122 return Value;
124 return Util::ConvertFrequencyWavelength(Value) * 1e9;
125 default:
126 throw Util::NotImplementedException("Cannot convert frequency in Hz to the unit required by the laser instrument.");
127 }
128 }
129
131 {
132 switch (FrequencyUnit)
133 {
135 return Value;
137 return Util::ConvertFrequencyWavelength(Value * 1e-9);
138 default:
139 throw Util::NotImplementedException("Cannot convert frequency in unit required by the laser instrument to Hz.");
140 }
141 }
142
144 {
145 switch (IntensityUnit)
146 {
148 return Value;
149 default:
150 throw Util::NotImplementedException("Cannot convert intensity in W to the unit required by the laser instrument.");
151 }
152 }
153
155 {
156 switch (IntensityUnit)
157 {
159 return Value;
160 default:
161 throw Util::NotImplementedException("Cannot convert intensity in unit required by the laser instrument to W.");
162 }
163 }
164
169
191
193 {
194 try
195 {
196 auto ModuleData = DynExp::dynamic_ModuleData_cast<LaserControl>(Instance.ModuleDataGetter());
197 auto InstrData = DynExp::dynamic_InstrumentData_cast<DynExpInstr::Laser>(ModuleData->GetLaser()->GetInstrumentData());
198
199 ModuleData->CurrentFrequency = ModuleData->FrequencyInLaserUnitToHz(InstrData->GetFrequencyValue());
200 ModuleData->CurrentIntensity = ModuleData->IntensityInLaserUnitToW(InstrData->GetIntensityValue());
201 ModuleData->CurrentScanRange = ModuleData->FrequencyInLaserUnitToHz(InstrData->GetScanRangeValue());
202 ModuleData->CurrentScanRate = ModuleData->FrequencyInLaserUnitToHz(InstrData->GetScanRateValue());
203 ModuleData->LaserState = InstrData->GetLaserState();
204
206 } // ModuleData and instruments' data unlocked here.
207 catch (const Util::TimeoutException& e)
208 {
209 if (NumFailedUpdateAttempts++ >= 3)
210 Instance.GetOwner().SetWarning(e);
211 }
212
214 }
215
220
221 std::unique_ptr<DynExp::QModuleWidget> LaserControl::MakeUIWidget()
222 {
223 auto Widget = std::make_unique<LaserControlWidget>(*this);
224
225 Connect(Widget->GetUI()->action_Enable, &QAction::toggled, this, &LaserControl::OnEnableToggled);
226 Connect(Widget->GetUI()->action_Scan, &QAction::toggled, this, &LaserControl::OnScanToggled);
227 Connect(Widget->GetUI()->SBFrequency, QOverload<double>::of(&QDoubleSpinBox::valueChanged), this, &LaserControl::OnFrequencyValueChanged);
228 Connect(Widget->GetUI()->SBWavelength, QOverload<double>::of(&QDoubleSpinBox::valueChanged), this, &LaserControl::OnWavelengthValueChanged);
229 Connect(Widget->GetUI()->SBIntensity, QOverload<double>::of(&QDoubleSpinBox::valueChanged), this, &LaserControl::OnIntensityValueChanged);
230 Connect(Widget->GetUI()->SBScanRange, QOverload<double>::of(&QDoubleSpinBox::valueChanged), this, &LaserControl::OnScanRangeValueChanged);
231 Connect(Widget->GetUI()->SBScanRate, QOverload<double>::of(&QDoubleSpinBox::valueChanged), this, &LaserControl::OnScanRateValueChanged);
232
233 return Widget;
234 }
235
236 void LaserControl::UpdateUIChild(const ModuleBase::ModuleDataGetterType& ModuleDataGetter)
237 {
238 auto Widget = GetWidget<LaserControlWidget>();
239 auto ModuleData = DynExp::dynamic_ModuleData_cast<LaserControl>(ModuleDataGetter());
240
241 if (!ModuleData->IsUIInitialized())
242 {
243 Widget->InitializeUI(ModuleData);
244 ModuleData->SetUIInitialized();
245 }
246
247 Widget->UpdateUI(ModuleData);
248 }
249
251 {
252 auto ModuleParams = DynExp::dynamic_Params_cast<LaserControl>(Instance->ParamsGetter());
253 auto ModuleData = DynExp::dynamic_ModuleData_cast<LaserControl>(Instance->ModuleDataGetter());
254
255 Instance->LockObject(ModuleParams->Laser, ModuleData->GetLaser());
256
257 ModuleData->FrequencyUnit = ModuleData->GetLaser()->GetFrequencyUnit();
258 ModuleData->IntensityUnit = ModuleData->GetLaser()->GetIntensityUnit();
259 ModuleData->HardwareMinFrequency = ModuleData->FrequencyInLaserUnitToHz(ModuleData->GetLaser()->GetMinFrequency());
260 ModuleData->HardwareMaxFrequency = ModuleData->FrequencyInLaserUnitToHz(ModuleData->GetLaser()->GetMaxFrequency());
261 ModuleData->HardwareMinIntensity = ModuleData->IntensityInLaserUnitToW(ModuleData->GetLaser()->GetMinIntensity());
262 ModuleData->HardwareMaxIntensity = ModuleData->IntensityInLaserUnitToW(ModuleData->GetLaser()->GetMaxIntensity());
263 ModuleData->HardwareMinScanRange = ModuleData->FrequencyInLaserUnitToHz(ModuleData->GetLaser()->GetMinScanRange());
264 ModuleData->HardwareMaxScanRange = ModuleData->FrequencyInLaserUnitToHz(ModuleData->GetLaser()->GetMaxScanRange());
265 ModuleData->HardwareMinScanRate = ModuleData->FrequencyInLaserUnitToHz(ModuleData->GetLaser()->GetMinScanRate());
266 ModuleData->HardwareMaxScanRate = ModuleData->FrequencyInLaserUnitToHz(ModuleData->GetLaser()->GetMaxScanRate());
267 ModuleData->HardwareModeHopFreeTuningRange = ModuleData->FrequencyInLaserUnitToHz(ModuleData->GetLaser()->GetModeHopFreeTuningRange());
268 }
269
271 {
272 auto ModuleData = DynExp::dynamic_ModuleData_cast<LaserControl>(Instance->ModuleDataGetter());
273
274 Instance->UnlockObject(ModuleData->GetLaser());
275 }
276
277 void LaserControl::OnEnableToggled(DynExp::ModuleInstance* Instance, bool Checked) const
278 {
279 auto ModuleData = DynExp::dynamic_ModuleData_cast<LaserControl>(Instance->ModuleDataGetter());
280
281 if (Checked)
282 ModuleData->GetLaser()->Enable();
283 else
284 ModuleData->GetLaser()->Disable();
285 }
286
287 void LaserControl::OnScanToggled(DynExp::ModuleInstance* Instance, bool Checked) const
288 {
289 auto ModuleData = DynExp::dynamic_ModuleData_cast<LaserControl>(Instance->ModuleDataGetter());
290
291 if (Checked)
292 ModuleData->GetLaser()->ScanContinuously();
293 else
294 ModuleData->GetLaser()->DisableScan();
295 }
296
298 {
299 auto ModuleData = DynExp::dynamic_ModuleData_cast<LaserControl>(Instance->ModuleDataGetter());
300
301 const double FrequencyInHz = Util::ConvertFrequencyWavelength(Value * 1e-9);
302 if (ModuleData->CurrentFrequency != FrequencyInHz)
303 ModuleData->GetLaser()->SetFrequency(ModuleData->FrequencyInHzToLaserUnit(FrequencyInHz));
304 }
305
307 {
308 auto ModuleData = DynExp::dynamic_ModuleData_cast<LaserControl>(Instance->ModuleDataGetter());
309
310 const double FrequencyInHz = Value * 1e12;
311 if (ModuleData->CurrentFrequency != FrequencyInHz)
312 ModuleData->GetLaser()->SetFrequency(ModuleData->FrequencyInHzToLaserUnit(FrequencyInHz));
313 }
314
316 {
317 auto ModuleData = DynExp::dynamic_ModuleData_cast<LaserControl>(Instance->ModuleDataGetter());
318
319 const double IntensityInW = Value * 1e-3;
320 if (ModuleData->CurrentIntensity != IntensityInW)
321 ModuleData->GetLaser()->SetIntensity(ModuleData->IntensityInWToLaserUnit(IntensityInW));
322 }
323
325 {
326 auto ModuleData = DynExp::dynamic_ModuleData_cast<LaserControl>(Instance->ModuleDataGetter());
327
328 const double FrequencyInHz = Value * 1e9;
329 if (ModuleData->CurrentScanRange != FrequencyInHz)
330 ModuleData->GetLaser()->SetScanRange(ModuleData->FrequencyInHzToLaserUnit(FrequencyInHz));
331 }
332
334 {
335 auto ModuleData = DynExp::dynamic_ModuleData_cast<LaserControl>(Instance->ModuleDataGetter());
336
337 const double FrequencyInHz = Value * 1e9;
338 if (ModuleData->CurrentScanRate != FrequencyInHz)
339 ModuleData->GetLaser()->SetScanRate(ModuleData->FrequencyInHzToLaserUnit(FrequencyInHz));
340 }
341}
Implementation of a module to control a laser source.
@ Startup
The laser is warming up.
@ Error
The laser is in an error state.
@ EmissionEnabledConstant
The laser is emitting in constant mode.
@ EmissionEnabledScanning
The laser is emitting in scan mode.
@ Ready
The laser is ready for emission.
double IntensityInLaserUnitToW(double Value) const
DynExpInstr::LaserData::IntensityUnitType IntensityUnit
void ResetImpl(dispatch_tag< QModuleDataBase >) override final
double FrequencyInLaserUnitToHz(double Value) const
double FrequencyInHzToLaserUnit(double Value) const
double IntensityInWToLaserUnit(double Value) const
DynExpInstr::LaserData::FrequencyUnitType FrequencyUnit
DynExpInstr::LaserData::LaserStateType LaserState
void InitializeUI(Util::SynchronizedPointer< LaserControlData > &ModuleData)
void UpdateUI(Util::SynchronizedPointer< LaserControlData > &ModuleData)
LaserControlWidget(LaserControl &Owner, QModuleWidget *parent=nullptr)
std::unique_ptr< Ui::LaserControl > ui
void OnScanToggled(DynExp::ModuleInstance *Instance, bool) const
void OnWavelengthValueChanged(DynExp::ModuleInstance *Instance, double Wavelength) const
void OnIntensityValueChanged(DynExp::ModuleInstance *Instance, double Intensity) const
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 OnInit(DynExp::ModuleInstance *Instance) const override final
This event is triggered right before the module thread starts. Override it to lock instruments this m...
void UpdateUIChild(const ModuleBase::ModuleDataGetterType &ModuleDataGetter) override final
void OnScanRangeValueChanged(DynExp::ModuleInstance *Instance, double ScanRange) const
void OnScanRateValueChanged(DynExp::ModuleInstance *Instance, double ScanRate) 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 ResetImpl(dispatch_tag< QModuleBase >) override final
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...
void OnFrequencyValueChanged(DynExp::ModuleInstance *Instance, double Frequency) const
void OnEnableToggled(DynExp::ModuleInstance *Instance, bool) const
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
Thrown when a requested feature is either under development and thus not implemented yet or when a sp...
Definition Exception.h:300
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
DynExp's module namespace contains the implementation of DynExp modules which extend DynExp's core fu...
constexpr auto StatusBarWarningStyleSheet
constexpr auto StatusBarReadyStyleSheetBright
constexpr auto StatusBarErrorStyleSheet
constexpr auto StatusBarBusyStyleSheet
DynExpErrorCodes
DynExp's error codes
Definition Exception.h:22
constexpr auto ConvertFrequencyWavelength(double Value) noexcept
Converts the frequency value of an electromagnetic wave in Hz to the corresponding wavelength in m an...
Definition Util.h:635
Accumulates include statements to provide a precompiled header.