DynExp
Highly flexible laboratory automation for dynamically changing experiments.
LockinAmplifierControl.cpp
Go to the documentation of this file.
1 // This file is part of DynExp.
2 
3 #include "stdafx.h"
4 #include "moc_LockinAmplifierControl.cpp"
6 
7 namespace DynExpModule
8 {
9  LockinAmplifierControlWidget::LockinAmplifierControlWidget(LockinAmplifierControl& Owner, QModuleWidget* parent) : QModuleWidget(Owner, parent)
10  {
11  ui.setupUi(this);
12  }
13 
15  {
16  if (!GetUIInitialized())
17  {
18  ui.SBRange->setSuffix(" m" + QString::fromStdString(ModuleData->SensitivityUnitString));
19  ui.LEOscillatorFreq->setFocus();
20 
21  UIInitialized = true;
22  }
23  }
24 
26  {
27  Init();
28  }
29 
31  {
33  CurrentPhase = 0;
34  CurrentTimeConstant = 1e-3;
39  CurrentSamplingRate = 1000;
40  CurrentEnable = false;
41  CurrentOverload = false;
47  }
48 
49  const char* LockinAmplifierControl::ProgressBarRedStylesheet = "QProgressBar::chunk { background-color: rgb(255, 0, 0); }";
50  const char* LockinAmplifierControl::ProgressBarGreenStylesheet = "QProgressBar::chunk { background-color: rgb(0, 170, 0); }";
51 
53  {
54  try
55  {
56  auto ModuleData = DynExp::dynamic_ModuleData_cast<LockinAmplifierControl>(Instance.ModuleDataGetter());
57  auto InstrData = DynExp::dynamic_InstrumentData_cast<DynExpInstr::LockinAmplifier>(ModuleData->GetLockinAmplifier()->GetInstrumentData());
58 
59  ModuleData->CurrentSensitivity = InstrData->GetSensitivity();
60  ModuleData->CurrentPhase = InstrData->GetPhase();
61  ModuleData->CurrentTimeConstant = InstrData->GetTimeConstant();
62  ModuleData->CurrentFilterOrder = InstrData->GetFilterOrder();
63  ModuleData->CurrentTriggerMode = InstrData->GetTriggerMode();
64  ModuleData->CurrentTriggerEdge = InstrData->GetTriggerEdge();
65  ModuleData->CurrentSignal = InstrData->GetSignalType();
66  ModuleData->CurrentSamplingRate = InstrData->GetSamplingRate();
67  ModuleData->CurrentEnable = InstrData->IsEnabled();
68  ModuleData->CurrentOverload = InstrData->IsOverloaded();
69  std::tie(ModuleData->CurrentNegInputLoad, ModuleData->CurrentPosInputLoad) = InstrData->GetInputLoad();
70  ModuleData->CurrentOscillatorFrequency = InstrData->GetOscillatorFrequency();
71  ModuleData->CurrentAcquisitionProgress = InstrData->GetAcquisitionProgress();
72 
74  } // ModuleData and instruments' data unlocked here.
75  catch (const Util::TimeoutException& e)
76  {
77  if (NumFailedUpdateAttempts++ >= 3)
78  Instance.GetOwner().SetWarning(e);
79  }
80 
82  }
83 
85  {
87  }
88 
89  std::unique_ptr<DynExp::QModuleWidget> LockinAmplifierControl::MakeUIWidget()
90  {
91  auto Widget = std::make_unique<LockinAmplifierControlWidget>(*this);
92 
93  // Connect Qt signals to module events
94  Connect(Widget->GetUI().SBRange, QOverload<double>::of(&QDoubleSpinBox::valueChanged), this, &LockinAmplifierControl::OnSensitivityChanged);
95  Connect(Widget->GetUI().BAutoRange, &QPushButton::clicked, this, &LockinAmplifierControl::OnAutoRangeClicked);
96  Connect(Widget->GetUI().SBPhase, QOverload<double>::of(&QDoubleSpinBox::valueChanged), this, &LockinAmplifierControl::OnPhaseChanged);
97  Connect(Widget->GetUI().BAutoPhase, &QPushButton::clicked, this, &LockinAmplifierControl::OnAutoPhaseClicked);
98  Connect(Widget->GetUI().SBTimeConstant, QOverload<double>::of(&QDoubleSpinBox::valueChanged), this, &LockinAmplifierControl::OnTimeConstantChanged);
99  Connect(Widget->GetUI().SBFilterOrder, QOverload<int>::of(&QSpinBox::valueChanged), this, &LockinAmplifierControl::OnFilterOrderChanged);
100  Connect(Widget->GetUI().CBTriggerMode, QOverload<int>::of(&QComboBox::currentIndexChanged), this, &LockinAmplifierControl::OnTriggerModeChanged);
101  Connect(Widget->GetUI().CBTriggerEdge, QOverload<int>::of(&QComboBox::currentIndexChanged), this, &LockinAmplifierControl::OnTriggerEdgeChanged);
102  Connect(Widget->GetUI().BForceTrigger, &QPushButton::clicked, this, &LockinAmplifierControl::OnForceTriggerClicked);
103  Connect(Widget->GetUI().CBQuantity, QOverload<int>::of(&QComboBox::currentIndexChanged), this, &LockinAmplifierControl::OnSignalTypeChanged);
104  Connect(Widget->GetUI().SBSamplingRate, QOverload<double>::of(&QDoubleSpinBox::valueChanged), this, &LockinAmplifierControl::OnSamplingRateChanged);
105  Connect(Widget->GetUI().CBEnable, &QCheckBox::stateChanged, this, &LockinAmplifierControl::OnEnableClicked);
106  Connect(Widget->GetUI().BPersist, &QPushButton::clicked, this, &LockinAmplifierControl::OnPersistParamsClicked);
107 
108  return Widget;
109  }
110 
111  void LockinAmplifierControl::UpdateUIChild(const ModuleBase::ModuleDataGetterType& ModuleDataGetter)
112  {
113  auto Widget = GetWidget<LockinAmplifierControlWidget>();
114  auto ModuleData = DynExp::dynamic_ModuleData_cast<LockinAmplifierControl>(ModuleDataGetter());
115 
116  Widget->InitializeUI(ModuleData);
117 
118  if (!Widget->GetUI().SBRange->hasFocus())
119  {
120  const QSignalBlocker Blocker(Widget->GetUI().SBRange);
121  Widget->GetUI().SBRange->setValue(ModuleData->CurrentSensitivity * 1e3);
122  }
123 
124  if (ModuleData->CurrentNegInputLoad >= 0)
125  {
126  Widget->GetUI().PBInputNegLoad->setVisible(true);
127  Widget->GetUI().PBInputNegLoad->setValue(ModuleData->CurrentNegInputLoad * 100);
128  Widget->GetUI().PBInputNegLoad->setStyleSheet(ModuleData->CurrentNegInputLoad >= 0.95 ? ProgressBarRedStylesheet : ProgressBarGreenStylesheet);
129 
130  }
131  else
132  Widget->GetUI().PBInputNegLoad->setVisible(false);
133 
134  if (ModuleData->CurrentPosInputLoad >= 0)
135  {
136  Widget->GetUI().PBInputPosLoad->setVisible(true);
137  Widget->GetUI().PBInputPosLoad->setValue(ModuleData->CurrentPosInputLoad * 100);
138  Widget->GetUI().PBInputPosLoad->setStyleSheet(ModuleData->CurrentPosInputLoad >= 0.95 ? ProgressBarRedStylesheet : ProgressBarGreenStylesheet);
139 
140  }
141  else
142  Widget->GetUI().PBInputPosLoad->setVisible(false);
143 
144  Widget->GetUI().LInputOverload->setText(ModuleData->CurrentOverload ? "Overload" : "");
145 
146  Widget->GetUI().LOscillatorFreq->setVisible(ModuleData->CurrentOscillatorFrequency > 0);
147  Widget->GetUI().LEOscillatorFreq->setVisible(ModuleData->CurrentOscillatorFrequency > 0);
148  if (ModuleData->CurrentOscillatorFrequency > 0)
149  Widget->GetUI().LEOscillatorFreq->setText(QString::fromStdString(Util::ToStr(ModuleData->CurrentOscillatorFrequency, 2) + " Hz"));
150 
151  if (!Widget->GetUI().SBPhase->hasFocus())
152  {
153  const QSignalBlocker Blocker(Widget->GetUI().SBPhase);
154  Widget->GetUI().SBPhase->setValue(ModuleData->CurrentPhase / std::numbers::pi * 180.0);
155  }
156 
157  if (!Widget->GetUI().SBTimeConstant->hasFocus())
158  {
159  const QSignalBlocker Blocker(Widget->GetUI().SBTimeConstant);
160  Widget->GetUI().SBTimeConstant->setValue(ModuleData->CurrentTimeConstant * 1e6);
161  }
162 
163  if (!Widget->GetUI().SBFilterOrder->hasFocus())
164  {
165  const QSignalBlocker Blocker(Widget->GetUI().SBFilterOrder);
166  Widget->GetUI().SBFilterOrder->setValue(ModuleData->CurrentFilterOrder);
167  }
168 
169  if (!Widget->GetUI().CBTriggerMode->hasFocus())
170  {
171  const QSignalBlocker Blocker(Widget->GetUI().CBTriggerMode);
172  Widget->GetUI().CBTriggerMode->setCurrentIndex(ModuleData->CurrentTriggerMode - 1);
173  }
174 
175  if (!Widget->GetUI().CBTriggerEdge->hasFocus())
176  {
177  const QSignalBlocker Blocker(Widget->GetUI().CBTriggerEdge);
178  Widget->GetUI().CBTriggerEdge->setCurrentIndex(ModuleData->CurrentTriggerEdge - 1);
179  }
180 
181  if (!Widget->GetUI().CBQuantity->hasFocus())
182  {
183  const QSignalBlocker Blocker(Widget->GetUI().CBQuantity);
184  Widget->GetUI().CBQuantity->setCurrentIndex(ModuleData->CurrentSignal);
185  }
186 
187  if (!Widget->GetUI().SBSamplingRate->hasFocus())
188  {
189  const QSignalBlocker Blocker(Widget->GetUI().SBSamplingRate);
190  Widget->GetUI().SBSamplingRate->setValue(ModuleData->CurrentSamplingRate);
191  }
192 
193  if (!Widget->GetUI().CBEnable->hasFocus())
194  {
195  const QSignalBlocker Blocker(Widget->GetUI().CBEnable);
196  Widget->GetUI().CBEnable->setChecked(ModuleData->CurrentEnable);
197  }
198 
199  Widget->GetUI().LProgress->setVisible(ModuleData->CurrentAcquisitionProgress >= 0);
200  Widget->GetUI().PProgress->setVisible(ModuleData->CurrentAcquisitionProgress >= 0);
201  if (ModuleData->CurrentAcquisitionProgress >= 0)
202  Widget->GetUI().PProgress->setValue(ModuleData->CurrentAcquisitionProgress * 100);
203  }
204 
206  {
207  auto ModuleParams = DynExp::dynamic_Params_cast<LockinAmplifierControl>(Instance->ParamsGetter());
208  auto ModuleData = DynExp::dynamic_ModuleData_cast<LockinAmplifierControl>(Instance->ModuleDataGetter());
209 
210  Instance->LockObject(ModuleParams->LockinAmplifier, ModuleData->GetLockinAmplifier());
211 
212  ModuleData->SensitivityUnitString = ModuleData->GetLockinAmplifier()->GetSensitivityUnitString();
213  }
214 
216  {
217  auto ModuleData = DynExp::dynamic_ModuleData_cast<LockinAmplifierControl>(Instance->ModuleDataGetter());
218 
219  Instance->UnlockObject(ModuleData->GetLockinAmplifier());
220  }
221 
223  {
224  auto ModuleData = DynExp::dynamic_ModuleData_cast<LockinAmplifierControl>(Instance->ModuleDataGetter());
225  ModuleData->GetLockinAmplifier()->SetSensitivity(Value / 1e3);
226  }
227 
229  {
230  auto ModuleData = DynExp::dynamic_ModuleData_cast<LockinAmplifierControl>(Instance->ModuleDataGetter());
231  ModuleData->GetLockinAmplifier()->AutoAdjustSensitivity();
232  }
233 
235  {
236  auto ModuleData = DynExp::dynamic_ModuleData_cast<LockinAmplifierControl>(Instance->ModuleDataGetter());
237  ModuleData->GetLockinAmplifier()->SetPhase(Value / 180.0 * std::numbers::pi);
238  }
239 
241  {
242  auto ModuleData = DynExp::dynamic_ModuleData_cast<LockinAmplifierControl>(Instance->ModuleDataGetter());
243  ModuleData->GetLockinAmplifier()->AutoAdjustPhase();
244  }
245 
247  {
248  auto ModuleData = DynExp::dynamic_ModuleData_cast<LockinAmplifierControl>(Instance->ModuleDataGetter());
249  ModuleData->GetLockinAmplifier()->SetTimeConstant(Value / 1e6);
250  }
251 
253  {
254  auto ModuleData = DynExp::dynamic_ModuleData_cast<LockinAmplifierControl>(Instance->ModuleDataGetter());
255  ModuleData->GetLockinAmplifier()->SetFilterOrder(Value);
256  }
257 
259  {
260  auto ModuleData = DynExp::dynamic_ModuleData_cast<LockinAmplifierControl>(Instance->ModuleDataGetter());
261  ModuleData->GetLockinAmplifier()->SetTriggerMode(static_cast<DynExpInstr::LockinAmplifierDefs::TriggerModeType>(Index + 1));
262  }
263 
265  {
266  auto ModuleData = DynExp::dynamic_ModuleData_cast<LockinAmplifierControl>(Instance->ModuleDataGetter());
267  ModuleData->GetLockinAmplifier()->SetTriggerEdge(static_cast<DynExpInstr::LockinAmplifierDefs::TriggerEdgeType>(Index + 1));
268  }
269 
271  {
272  auto ModuleData = DynExp::dynamic_ModuleData_cast<LockinAmplifierControl>(Instance->ModuleDataGetter());
273  ModuleData->GetLockinAmplifier()->ForceTrigger();
274  }
275 
277  {
278  auto ModuleData = DynExp::dynamic_ModuleData_cast<LockinAmplifierControl>(Instance->ModuleDataGetter());
279  ModuleData->GetLockinAmplifier()->SetSignalType(static_cast<DynExpInstr::LockinAmplifierDefs::SignalType>(Index));
280  }
281 
283  {
284  auto ModuleData = DynExp::dynamic_ModuleData_cast<LockinAmplifierControl>(Instance->ModuleDataGetter());
285  ModuleData->GetLockinAmplifier()->SetSamplingRate(Value);
286  }
287 
289  {
290  auto ModuleData = DynExp::dynamic_ModuleData_cast<LockinAmplifierControl>(Instance->ModuleDataGetter());
291  ModuleData->GetLockinAmplifier()->SetEnable(Value);
292  }
293 
295  {
296  auto ModuleData = DynExp::dynamic_ModuleData_cast<LockinAmplifierControl>(Instance->ModuleDataGetter());
297  ModuleData->GetLockinAmplifier()->PersistDataToParams();
298  }
299 }
Implementation of a module to control a lock-in amplifier.
void ResetImpl(dispatch_tag< QModuleDataBase >) override final
DynExpInstr::LockinAmplifierDefs::TriggerEdgeType CurrentTriggerEdge
DynExpInstr::LockinAmplifierDefs::TriggerModeType CurrentTriggerMode
DynExpInstr::LockinAmplifierDefs::SignalType CurrentSignal
void InitializeUI(Util::SynchronizedPointer< LockinAmplifierControlData > &ModuleData)
LockinAmplifierControlWidget(LockinAmplifierControl &Owner, QModuleWidget *parent=nullptr)
void OnSignalTypeChanged(DynExp::ModuleInstance *Instance, int Index) const
void OnAutoPhaseClicked(DynExp::ModuleInstance *Instance, bool) const
void OnTimeConstantChanged(DynExp::ModuleInstance *Instance, double Value) const
void OnPersistParamsClicked(DynExp::ModuleInstance *Instance, bool) const
void OnFilterOrderChanged(DynExp::ModuleInstance *Instance, int Value) const
void OnPhaseChanged(DynExp::ModuleInstance *Instance, double Value) const
void UpdateUIChild(const ModuleBase::ModuleDataGetterType &ModuleDataGetter) override final
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...
void OnTriggerModeChanged(DynExp::ModuleInstance *Instance, int Index) const
void ResetImpl(dispatch_tag< QModuleBase >) override final
void OnForceTriggerClicked(DynExp::ModuleInstance *Instance, bool) const
void OnAutoRangeClicked(DynExp::ModuleInstance *Instance, bool) 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 OnExit(DynExp::ModuleInstance *Instance) const override final
This event is triggered right before the module thread terminates (not due to an exception,...
void OnEnableClicked(DynExp::ModuleInstance *Instance, int Value) const
void OnTriggerEdgeChanged(DynExp::ModuleInstance *Instance, int Index) const
void OnSamplingRateChanged(DynExp::ModuleInstance *Instance, double Value) const
void OnSensitivityChanged(DynExp::ModuleInstance *Instance, double Value) const
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
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
TriggerEdgeType
Type to determine at which edge of a trigger signal to trigger. Not a strongly-typed enum to allow us...
@ Fall
Trigger on falling edge.
SignalType
Type specifying different signal coordinates a lock-in amplifier can record. Not a strongly-typed enu...
@ R
Radial component of the signal in polar coordinates.
TriggerModeType
Type to determine the trigger mode. Not a strongly-typed enum to allow using the enumeration in a Dyn...
@ ExternSingle
Run once after an external trigger signal has been detected.
DynExp's module namespace contains the implementation of DynExp modules which extend DynExp's core fu...
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
Accumulates include statements to provide a precompiled header.