DynExp
Highly flexible laboratory automation for dynamically changing experiments.
WidefieldMicroscope.cpp
Go to the documentation of this file.
1 // This file is part of DynExp.
2 
3 #include "stdafx.h"
4 #include "WidefieldMicroscope.h"
5 
7 {
9  {
10  x = 0;
11  y = 0;
12  z = 0;
13 
14  MeasuredX = 0;
15  MeasuredY = 0;
16  MeasuredZ = 0;
17 
18  UsingX = false;
19  UsingY = false;
20  UsingZ = false;
21 
22  RowIndex = -1;
23  ColumnIndex = -1;
24  }
25 
27  {
28  double dist = 0;
29 
30  if (UsingX && Other.UsingX)
31  dist += (x - Other.x) * (x - Other.x);
32  if (UsingY && Other.UsingY)
33  dist += (y - Other.y) * (y - Other.y);
34  if (UsingZ && Other.UsingZ)
35  dist += (z - Other.z) * (z - Other.z);
36 
37  return std::sqrt(dist);
38  }
39 
40  std::string WidefieldMicroscopeData::PositionPoint::ToStr(std::string_view Prefix) const
41  {
42  std::stringstream stream;
43  stream << std::setprecision(9);
44 
45  stream << Prefix << "Valid = " << (!IsEmpty() ? "yes" : "no") << "\n";
46  if (UsingX)
47  {
48  stream << Prefix << "X = " << x << " nm\n";
49  stream << Prefix << "MeasuredX = " << MeasuredX << " nm\n";
50  }
51  if (UsingY)
52  {
53  stream << Prefix << "Y = " << y << " nm\n";
54  stream << Prefix << "MeasuredY = " << MeasuredY << " nm\n";
55  }
56  if (UsingZ)
57  {
58  stream << Prefix << "Z = " << z << " nm\n";
59  stream << Prefix << "MeasuredZ = " << MeasuredZ << " nm\n";
60  }
61 
62  return stream.str();
63  }
64 
66  {
67  switch (State)
68  {
69  case LocalizedEmitterStateType::Characterizing: return "Characterizing...";
70  case LocalizedEmitterStateType::Finished: return "Finished";
71  case LocalizedEmitterStateType::Failed: return "Failed";
72  default: return "";
73  }
74  }
75 
77  {
78  switch (State)
79  {
81  case LocalizedEmitterStateType::Finished: return "green";
82  case LocalizedEmitterStateType::Failed: return "red";
83  default: return QApplication::palette().text().color();
84  }
85  }
86 
92  {
94  return {};
95 
96  auto Ratio = GetSampleStageX()->GetStepNanoMeterRatio();
97  auto X = DynExp::dynamic_InstrumentData_cast<DynExpInstr::PositionerStage>(GetSampleStageX()->GetInstrumentData())->GetCurrentPosition();
98  auto Y = DynExp::dynamic_InstrumentData_cast<DynExpInstr::PositionerStage>(GetSampleStageY()->GetInstrumentData())->GetCurrentPosition();
99 
100  return { static_cast<decltype(X)>(X * Ratio) , static_cast<decltype(Y)>(Y * Ratio) };
101  }
102 
103  std::stringstream WidefieldMicroscopeData::AssembleCSVHeader(bool IncludeConfocalScan, bool IncludeHBT, bool IncludeAutoMeasure) const
104  {
105  std::stringstream CSVData;
106  CSVData << std::setprecision(9);
107 
108  CSVData << "WidefieldPumpPower = " << WidefieldPumpPower << " V\n";
109  CSVData << "ConfocalPumpPower = " << ConfocalPumpPower << " V\n";
110  CSVData << "FocusCurrentVoltage = " << FocusCurrentVoltage << " V\n";
111  CSVData << "FocusZeroVoltage = " << FocusZeroVoltage << " V\n";
112  CSVData << "FocusConfocalOffsetVoltage = " << FocusConfocalOffsetVoltage << " V\n";
113 
114  CSVData << "LEDCameraExposureTime = " << LEDCameraExposureTime.count() << " ms\n";
115  CSVData << "WidefieldCameraExposureTime = " << WidefieldCameraExposureTime.count() << " ms\n";
116  CSVData << GetSamplePosition().ToStr("CurrentPosition");
117  CSVData << WidefieldPosition.ToStr("WidefieldPosition");
118 
119  CSVData << CurrentCellID;
120 
121  if (IncludeConfocalScan)
122  {
123  CSVData << SampleHomePosition.ToStr("SampleHomePosition");
124  CSVData << "ConfocalScanWidth = " << ConfocalScanWidth << "\n";
125  CSVData << "ConfocalScanHeight = " << ConfocalScanHeight << "\n";
126  CSVData << "ConfocalScanDistPerPixel = " << ConfocalScanDistPerPixel << "\n";
127  CSVData << "SPDExposureTime = " << SPDExposureTime.count() << " ms\n";
128  }
129 
130  CSVData << "ConfocalOptimizationInitXYStepSize = " << ConfocalOptimizationInitXYStepSize << "\n";
131  CSVData << "ConfocalOptimizationInitZStepSize = " << ConfocalOptimizationInitZStepSize << "\n";
132  CSVData << "ConfocalOptimizationTolerance = " << ConfocalOptimizationTolerance << "\n";
133 
134  if (IncludeHBT)
135  {
136  CSVData << "HBTBinWidth = " << HBTBinWidth.count() << " ps\n";
137  CSVData << "HBTBinCount = " << HBTBinCount << "\n";
138  CSVData << "HBTMaxIntegrationTime = " << HBTMaxIntegrationTime.count() << " us\n";
139  CSVData << HBTSamplePosition.ToStr("HBTSamplePosition");
140  CSVData << "HBTNumEventCounts = " << HBTNumEventCounts << "\n";
141  CSVData << "HBTTotalIntegrationTime = " << HBTTotalIntegrationTime.count() << " us\n";
142  }
143 
144  if (IncludeAutoMeasure)
145  {
146  CSVData << AutoMeasureCurrentCellPosition.ToStr("AutoMeasureCurrentCellPosition");
147  CSVData << "AutoMeasureNumberImageSets = " << AutoMeasureNumberImageSets << "\n";
148  CSVData << "AutoMeasureCurrentImageSet = " << AutoMeasureCurrentImageSet << "\n";
149  CSVData << "AutoMeasureInitialImageSetWaitTime = " << AutoMeasureInitialImageSetWaitTime.count() << " s\n";
150  CSVData << "AutoMeasureImagePositionScatterRadius = " << AutoMeasureImagePositionScatterRadius << "\n";
151  CSVData << "AutoMeasureLocalizationType = " << AutoMeasureLocalizationType << "\n";
152  CSVData << "AutoMeasureOptimizeEnabled = " << (AutoMeasureOptimizeEnabled ? "yes" : "no") << "\n";
153  CSVData << "AutoMeasureSpectrumEnabled = " << (AutoMeasureSpectrumEnabled ? "yes" : "no") << "\n";
154  CSVData << "AutoMeasureHBTEnabled = " << (AutoMeasureHBTEnabled ? "yes" : "no") << "\n";
155  CSVData << "AutoMeasureNumOptimizationAttempts = " << AutoMeasureNumOptimizationAttempts << "\n";
156  CSVData << "AutoMeasureCurrentOptimizationAttempt = " << AutoMeasureCurrentOptimizationAttempt << "\n";
157  CSVData << "AutoMeasureMaxOptimizationReruns = " << AutoMeasureMaxOptimizationReruns << "\n";
158  CSVData << "AutoMeasureCurrentOptimizationRerun = " << AutoMeasureCurrentOptimizationRerun << "\n";
159  CSVData << "AutoMeasureOptimizationMaxDistance = " << AutoMeasureOptimizationMaxDistance << "\n";
160  CSVData << "AutoMeasureCountRateThreshold = " << AutoMeasureCountRateThreshold << "\n";
161  CSVData << "AutoMeasureCellRangeFromX = " << AutoMeasureCellRangeFrom.x() << "\n";
162  CSVData << "AutoMeasureCellRangeFromY = " << AutoMeasureCellRangeFrom.y() << "\n";
163  CSVData << "AutoMeasureCellRangeToX = " << AutoMeasureCellRangeTo.x() << "\n";
164  CSVData << "AutoMeasureCellRangeToY = " << AutoMeasureCellRangeTo.y() << "\n";
165  CSVData << "AutoMeasureCellSkipX = " << AutoMeasureCellSkip.x() << "\n";
166  CSVData << "AutoMeasureCellSkipY = " << AutoMeasureCellSkip.y() << "\n";
168  CSVData << "AutoMeasureFirstEmitter = " << AutoMeasureFirstEmitter->first << "\n";
170  CSVData << "AutoMeasureCurrentEmitter = " << AutoMeasureCurrentEmitter->first << "\n";
171  }
172 
173  CSVData << "HEADER_END\n";
174 
175  return CSVData;
176  }
177 
178  void WidefieldMicroscopeData::WriteConfocalScanResults(std::stringstream& Stream) const
179  {
180  Stream << "X_measured(nm);Y_measured(nm);X_destiny(nm);Y_destiny(nm);C(Hz)\n";
181 
182  auto& ResultItems = GetConfocalScanResults();
183  for (const auto& ResultItem : ResultItems)
184  Stream << ResultItem.first.MeasuredX << ";" << ResultItem.first.MeasuredY << ";"
185  << ResultItem.first.x << ";" << ResultItem.first.y << ";"
186  << ResultItem.second << "\n";
187  }
188 
189  void WidefieldMicroscopeData::WriteHBTResults(std::stringstream& Stream) const
190  {
191  Stream << "t(ps);g2\n";
192 
193  for (const auto& ResultItem : GetHBTDataPoints())
194  Stream << ResultItem.x() << ";" << ResultItem.y() << "\n";
195  }
196 
198  {
199  LEDLightTurnedOn = State;
200  LEDSwitch->SetSync(State);
201  }
202 
204  {
205  PumpLightTurnedOn = State;
206  PumpSwitch->SetSync(State);
207  }
208 
210  {
211  if (Util::NumToT<int>(++CurrentCellID.X_id) > AutoMeasureCellRangeTo.x())
212  {
215  }
216 
218  }
219 
221  {
222  return std::count_if(LocalizedPositions.cbegin(), LocalizedPositions.cend(), [](const auto& Pos) {
223  return Pos.second.State == LocalizedEmitterStateType::Finished;
224  });
225  }
226 
228  {
229  return std::count_if(LocalizedPositions.cbegin(), LocalizedPositions.cend(), [](const auto& Pos) {
230  return Pos.second.State == LocalizedEmitterStateType::Failed;
231  });
232  }
233 
234  void WidefieldMicroscopeData::AppendLocalizedPosition(LocalizedPositionsMapType::value_type&& Position)
235  {
236  LocalizedPositions.insert(std::move(Position));
238  }
239 
241  {
242  LocalizedPositions = std::move(Positions);
244 
246  }
247 
249  {
250  LocalizedPositions.clear();
252 
254  }
255 
257  {
258  return CurrentCellID.Valid ?
260  }
261 
263  {
264  Init();
265  }
266 
268  {
269  return AutoMeasureCellRangeTo.x() - AutoMeasureCellRangeFrom.x() >= 0 &&
271  }
272 
274  {
276  }
277 
279  {
281  }
282 
284  {
286  }
287 
289  {
290  if (!CurrentCellID.Valid)
291  throw Util::InvalidDataException("The current cell ID is invalid.");
292 
293  return (Util::NumToT<int>(CurrentCellID.Y_id) - AutoMeasureCellRangeFrom.y()) * GetAutoMeasureCellLineLength() +
294  Util::NumToT<int>(CurrentCellID.X_id) - AutoMeasureCellRangeFrom.x();
295  }
296 
298  {
299  if (FirstEmitterID < 0)
300  return false;
301 
302  auto FirstEmitter = LocalizedPositions.find(FirstEmitterID);
303  if (FirstEmitter == LocalizedPositions.cend())
304  return false;
305 
306  AutoMeasureFirstEmitter = FirstEmitter;
307  AutoMeasureCurrentEmitter = FirstEmitter;
308 
309  return true;
310  }
311 
313  {
316  }
317 
319  {
320  Features = {};
321  ClearUIMessage();
322 
324  LEDLightTurnedOn = false;
325  PumpLightTurnedOn = false;
326  MinPumpPower = .0;
327  MaxPumpPower = .0;
328  WidefieldPumpPower = .0;
329  ConfocalPumpPower = .0;
330  MeasuredPumpPower = .0;
331  MinFocusVoltage = .0;
332  MaxFocusVoltage = .0;
333  FocusCurrentVoltage = .0;
334  FocusZeroVoltage = .0;
336  AutofocusFinished = false;
337 
340  LEDCameraExposureTime = std::chrono::milliseconds(30);
341  WidefieldCameraExposureTime = std::chrono::milliseconds(3500);
342  ConfocalSpotImagePosition = { 0, 0 };
344  CurrentImage = QImage();
345  CurrentImageChanged = false;
346  CurrentCellID = {};
347  LastCellID = {};
348  LocalizedPositions.clear();
351 
353  ConfocalScanWidth = 20;
354  ConfocalScanHeight = 20;
356  SPDExposureTime = std::chrono::milliseconds(100);
357  SPD1State.Reset();
358  SPD2State.Reset();
361 
365  LastCountRate = .0;
366 
368  HBTBinCount = 256;
369  HBTMaxIntegrationTime = std::chrono::microseconds(0);
371  HBTNumEventCounts = 0;
372  HBTTotalIntegrationTime = std::chrono::microseconds(0);
373  HBTDataPoints.clear();
376 
377  AutoMeasureRunning = false;
378  AutoMeasureSavePath.clear();
384  AutoMeasureLocalizationType = WidefieldMicroscopeWidget::LocalizationType::LocalizeEmittersFromImage;
387  AutoMeasureHBTEnabled = true;
394  AutoMeasureCellRangeFrom = { 0, 0 };
395  AutoMeasureCellRangeTo = { 10, 10 };
396  AutoMeasureCellSkip = { 100000, 100000 };
397 
399  }
400 
402  {
404 
405  if (lhs.UsingX && rhs.UsingX)
406  {
407  Point.x = lhs.x + rhs.x;
408  Point.MeasuredX = lhs.MeasuredX + rhs.MeasuredX;
409  Point.UsingX = true;
410  }
411  else if (lhs.UsingX && !rhs.UsingX)
412  {
413  Point.x = lhs.x;
414  Point.MeasuredX = lhs.MeasuredX;
415  Point.UsingX = true;
416  }
417  else if (!lhs.UsingX && rhs.UsingX)
418  {
419  Point.x = rhs.x;
420  Point.MeasuredX = rhs.MeasuredX;
421  Point.UsingX = true;
422  }
423 
424  if (lhs.UsingY && rhs.UsingY)
425  {
426  Point.y = lhs.y + rhs.y;
427  Point.MeasuredY = lhs.MeasuredY + rhs.MeasuredY;
428  Point.UsingY = true;
429  }
430  else if (lhs.UsingY && !rhs.UsingY)
431  {
432  Point.y = lhs.y;
433  Point.MeasuredY = lhs.MeasuredY;
434  Point.UsingY = true;
435  }
436  else if (!lhs.UsingY && rhs.UsingY)
437  {
438  Point.y = rhs.y;
439  Point.MeasuredY = rhs.MeasuredY;
440  Point.UsingY = true;
441  }
442 
443  if (lhs.UsingZ && rhs.UsingZ)
444  {
445  Point.z = lhs.z + rhs.z;
446  Point.MeasuredZ = lhs.MeasuredZ + rhs.MeasuredZ;
447  Point.UsingZ = true;
448  }
449  else if (lhs.UsingZ && !rhs.UsingZ)
450  {
451  Point.z = lhs.z;
452  Point.MeasuredZ = lhs.MeasuredZ;
453  Point.UsingZ = true;
454  }
455  else if (!lhs.UsingZ && rhs.UsingZ)
456  {
457  Point.z = rhs.z;
458  Point.MeasuredZ = rhs.MeasuredZ;
459  Point.UsingZ = true;
460  }
461 
462  return Point;
463  }
464 
466  {
468 
469  if (lhs.UsingX && rhs.UsingX)
470  {
471  Point.x = lhs.x - rhs.x;
472  Point.MeasuredX = lhs.MeasuredX - rhs.MeasuredX;
473  Point.UsingX = true;
474  }
475  else if (lhs.UsingX && !rhs.UsingX)
476  {
477  Point.x = lhs.x;
478  Point.MeasuredX = lhs.MeasuredX;
479  Point.UsingX = true;
480  }
481  else if (!lhs.UsingX && rhs.UsingX)
482  {
483  Point.x = -rhs.x;
484  Point.MeasuredX = -rhs.MeasuredX;
485  Point.UsingX = true;
486  }
487 
488  if (lhs.UsingY && rhs.UsingY)
489  {
490  Point.y = lhs.y - rhs.y;
491  Point.MeasuredY = lhs.MeasuredY - rhs.MeasuredY;
492  Point.UsingY = true;
493  }
494  else if (lhs.UsingY && !rhs.UsingY)
495  {
496  Point.y = lhs.y;
497  Point.MeasuredY = lhs.MeasuredY;
498  Point.UsingY = true;
499  }
500  else if (!lhs.UsingY && rhs.UsingY)
501  {
502  Point.y = -rhs.y;
503  Point.MeasuredY = -rhs.MeasuredY;
504  Point.UsingY = true;
505  }
506 
507  if (lhs.UsingZ && rhs.UsingZ)
508  {
509  Point.z = lhs.z - rhs.z;
510  Point.MeasuredZ = lhs.MeasuredZ - rhs.MeasuredZ;
511  Point.UsingZ = true;
512  }
513  else if (lhs.UsingZ && !rhs.UsingZ)
514  {
515  Point.z = lhs.z;
516  Point.MeasuredZ = lhs.MeasuredZ;
517  Point.UsingZ = true;
518  }
519  else if (!lhs.UsingZ && rhs.UsingZ)
520  {
521  Point.z = -rhs.z;
522  Point.MeasuredZ = -rhs.MeasuredZ;
523  Point.UsingZ = true;
524  }
525 
526  return Point;
527  }
528 
529  WidefieldMicroscope::WidefieldMicroscope(const std::thread::id OwnerThreadID, DynExp::ParamsBasePtrType&& Params)
530  : QModuleBase(OwnerThreadID, std::move(Params)),
531  StateMachine(InitializingState,
532  SetupTransitionBeginState, SetupTransitioningState, SetupTransitionEndState, SetupTransitionFinishedState,
533  ReadyState,
534  AutofocusBeginState, AutofocusWaitingState, AutofocusFinishedState,
535  LEDImageAcquisitionBeginState, WidefieldImageAcquisitionBeginState,
536  WaitingForLEDImageReadyToCaptureState, WaitingForLEDImageState, WaitingForLEDImageFinishedState,
537  WaitingForWidefieldImageReadyToCaptureState, WaitingForWidefieldImageState, WaitingForWidefieldImageFinishedState,
538  WaitingForWidefieldCellIDState, WidefieldCellWaitUntilCenteredState, WidefieldCellIDReadFinishedState,
539  WaitingForWidefieldLocalizationState, WidefieldLocalizationFinishedState,
540  FindingConfocalSpotBeginState, FindingConfocalSpotAfterTransitioningToConfocalModeState, FindingConfocalSpotAfterRecordingWidefieldImageState,
541  ConfocalScanStepState, ConfocalScanWaitUntilMovedState, ConfocalScanCaptureState, ConfocalScanWaitUntilCapturedState,
542  ConfocalOptimizationInitState, ConfocalOptimizationInitSubStepState, ConfocalOptimizationWaitState, ConfocalOptimizationStepState, ConfocalOptimizationFinishedState,
543  HBTAcquiringState, HBTFinishedState,
544  WaitingState, WaitingFinishedState,
545  SpectrumAcquisitionWaitingState, SpectrumAcquisitionFinishedState,
546  AutoMeasureLocalizationStepState, AutoMeasureLocalizationSaveLEDImageState, AutoMeasureLocalizationSaveWidefieldImageState,
547  AutoMeasureLocalizationMovingState, AutoMeasureLocalizationFinishedState,
548  AutoMeasureCharacterizationStepState, AutoMeasureCharacterizationGotoEmitterState, AutoMeasureCharacterizationOptimizationFinishedState,
549  AutoMeasureCharacterizationSpectrumBeginState, AutoMeasureCharacterizationSpectrumFinishedState,
550  AutoMeasureCharacterizationHBTBeginState, AutoMeasureCharacterizationHBTWaitForInitState, AutoMeasureCharacterizationHBTFinishedState,
551  AutoMeasureCharacterizationFinishedState,
552  AutoMeasureSampleStepState, AutoMeasureSampleReadCellIDState, AutoMeasureSampleReadCellIDFinishedState,
553  AutoMeasureSampleLocalizeState, AutoMeasureSampleFindEmittersState,
554  AutoMeasureSampleCharacterizeState, AutoMeasureSampleAdvanceCellState, AutoMeasureSampleFinishedState),
555  ConfocalScanPositionerStateX(std::make_shared<AtomicPositionerStateType>()),
556  ConfocalScanPositionerStateY(std::make_shared<AtomicPositionerStateType>()),
557  ConfocalScanPositionerStateZ(std::make_shared<AtomicPositionerStateType>()),
558  WidefieldCellIDState(std::make_shared<AtomicWidefieldImageProcessingStateType>()),
559  WidefieldLocalizationState(std::make_shared<AtomicWidefieldImageProcessingStateType>()),
560  GSLConfocalOptimizationState(gsl_multimin_fminimizer_alloc(GSLConfocalOptimizationMinimizer, GSLConfocalOptimizationNumDimensions)),
561  GSLConfocalOptimizationStepSize(gsl_vector_alloc(GSLConfocalOptimizationNumDimensions)),
562  GSLConfocalOptimizationInitialPoint(gsl_vector_alloc(GSLConfocalOptimizationNumDimensions))
563  {
565  throw Util::NotAvailableException("Could not initialize GSL multimin library components.", Util::ErrorType::Error);
566  }
567 
569  {
571  gsl_vector_free(GSLConfocalOptimizationInitialPoint);
573  gsl_vector_free(GSLConfocalOptimizationStepSize);
575  gsl_multimin_fminimizer_free(GSLConfocalOptimizationState);
576  }
577 
578  std::chrono::milliseconds WidefieldMicroscope::GetMainLoopDelay() const
579  {
580  auto CurrentState = StateMachine.GetCurrentState()->GetState();
581 
582  // If doing some measurement, run much faster.
583  if (CurrentState == StateType::Ready)
584  return std::chrono::milliseconds(30);
585  else
586  return std::chrono::milliseconds(2);
587  }
588 
589  void WidefieldMicroscope::OnSaveCurrentImage(DynExp::ModuleInstance* Instance, QString Filename) const
590  {
591  static constexpr const char* SaveErrorMsg = "Saving an image failed.";
592 
593  QImage Image;
594  {
595  auto ModuleData = DynExp::dynamic_ModuleData_cast<WidefieldMicroscope>(Instance->ModuleDataGetter());
596  Image = ModuleData->GetCurrentImage().copy();
597  } // ModuleData unlocked here for heavy save operation.
598 
599  if (!Image.save(Filename))
600  {
601  if (LogUIMessagesOnly)
603  else
604  {
605  auto ModuleData = DynExp::dynamic_ModuleData_cast<WidefieldMicroscope>(Instance->ModuleDataGetter());
606  ModuleData->SetUIMessage(SaveErrorMsg);
607  }
608  }
609  }
610 
611  void WidefieldMicroscope::OnGoToSamplePos(DynExp::ModuleInstance* Instance, QPointF SamplePos) const
612  {
613  auto ModuleData = DynExp::dynamic_ModuleData_cast<WidefieldMicroscope>(Instance->ModuleDataGetter());
614 
615  if (!IsReadyState() || !ModuleData->TestFeature(WidefieldMicroscopeData::FeatureType::Widefield) || SamplePos.isNull())
616  return;
617 
618  MoveSampleTo(
619  { Util::NumToT<WidefieldMicroscopeData::PositionType>(SamplePos.x()), Util::NumToT<WidefieldMicroscopeData::PositionType>(SamplePos.y()) },
620  ModuleData
621  );
622  }
623 
624  void WidefieldMicroscope::OnBringMarkerToConfocalSpot(DynExp::ModuleInstance* Instance, QPoint MarkerPos, QPointF SamplePos) const
625  {
626  auto ModuleParams = DynExp::dynamic_Params_cast<WidefieldMicroscope>(Instance->ParamsGetter());
627  auto ModuleData = DynExp::dynamic_ModuleData_cast<WidefieldMicroscope>(Instance->ModuleDataGetter());
628 
629  if (!IsReadyState() || !ModuleData->TestFeature(WidefieldMicroscopeData::FeatureType::Widefield) || SamplePos.isNull())
630  return;
631 
632  BringMarkerToConfocalSpot(ModuleParams, ModuleData, MarkerPos, SamplePos);
633  }
634 
636  {
637  auto ModuleData = DynExp::dynamic_ModuleData_cast<WidefieldMicroscope>(Instance->ModuleDataGetter());
638 
640  }
641 
643  {
644  try
645  {
646  auto ModuleData = DynExp::dynamic_ModuleData_cast<WidefieldMicroscope>(Instance.ModuleDataGetter());
647 
649  if (ModuleData->GetPumpPowerIndicator()->CanRead())
650  ModuleData->SetMeasuredPumpPower(ModuleData->GetPumpPowerIndicator()->Get());
651 
652  StateMachine.Invoke(*this, Instance);
653 
655  }
656  catch (const Util::TimeoutException& e)
657  {
658  if (NumFailedUpdateAttempts++ >= 3)
659  Instance.GetOwner().SetWarning(e);
660  }
661 
663  }
664 
666  {
667  StateMachine.SetCurrentState(StateType::Initializing);
668 
674 
675  ConfocalScanPositions.clear();
676 
679 
681  ImageCapturingPaused = false;
682 
684 
686  LogUIMessagesOnly = false;
687  }
688 
689  std::unique_ptr<DynExp::QModuleWidget> WidefieldMicroscope::MakeUIWidget()
690  {
691  auto Widget = std::make_unique<WidefieldMicroscopeWidget>(*this);
692 
693  Connect(Widget->GetUI().action_Terminate, &QAction::triggered, this, &WidefieldMicroscope::OnTerminate);
694  Connect(Widget->GetUI().action_Stop_current_action, &QAction::triggered, this, &WidefieldMicroscope::OnStopAction);
695  Connect(Widget->GetUI().action_Set_home_position, &QAction::triggered, this, &WidefieldMicroscope::OnSetHomePosition);
696  Connect(Widget->GetUI().action_Go_home_position, &QAction::triggered, this, &WidefieldMicroscope::OnGoToHomePosition);
697  Connect(Widget->GetUI().action_Toogle_LED_light_source, &QAction::triggered, this, &WidefieldMicroscope::OnToggleLEDLightSource);
698  Connect(Widget->GetUI().action_Toogle_pump_light_source, &QAction::triggered, this, &WidefieldMicroscope::OnTogglePumpLightSource);
699  Connect(Widget->GetWidefieldConfocalModeActionGroup(), &QActionGroup::triggered, this, &WidefieldMicroscope::OnSetupModeChanged);
700  Connect(Widget->GetUI().action_Autofocus, &QAction::triggered, this, &WidefieldMicroscope::OnAutofocus);
701  Connect(Widget->GetUI().action_Optimize_positions, &QAction::triggered, this, &WidefieldMicroscope::OnOptimizePositions);
702  Connect(Widget->GetUI().action_Toggle_HBT_mirror, &QAction::triggered, this, &WidefieldMicroscope::OnToggleHBTMirror);
703  Connect(Widget->GetUI().action_Reset_CellID, &QAction::triggered, this, &WidefieldMicroscope::OnResetCellID);
704  Connect(Widget->GetUI().SBGeneralWidefieldPower, QOverload<double>::of(&QDoubleSpinBox::valueChanged), this, &WidefieldMicroscope::OnGeneralWidefieldPowerChanged);
705  Connect(Widget->GetUI().SBGeneralConfocalPower, QOverload<double>::of(&QDoubleSpinBox::valueChanged), this, &WidefieldMicroscope::OnGeneralConfocalPowerChanged);
706  Connect(Widget->GetUI().SBGeneralFocusCurrentVoltage, QOverload<double>::of(&QDoubleSpinBox::valueChanged), this, &WidefieldMicroscope::OnGeneralFocusCurrentVoltageChanged);
707  Connect(Widget->GetUI().SBGeneralFocusZeroVoltage, QOverload<double>::of(&QDoubleSpinBox::valueChanged), this, &WidefieldMicroscope::OnGeneralFocusZeroVoltageChanged);
708  Connect(Widget->GetUI().SBGeneralFocusConfocalOffsetVoltage, QOverload<double>::of(&QDoubleSpinBox::valueChanged), this, &WidefieldMicroscope::OnGeneralFocusConfocalOffsetVoltageChanged);
709  Connect(Widget->GetUI().BGeneralFocusSetZeroVoltage, &QPushButton::clicked, this, &WidefieldMicroscope::OnGeneralSetZeroFocus);
710  Connect(Widget->GetUI().BGeneralFocusApplyZeroVoltage, &QPushButton::clicked, this, &WidefieldMicroscope::OnGeneralApplyZeroFocus);
711  Connect(Widget->GetUI().SBWidefieldLEDExposureTime, QOverload<int>::of(&QSpinBox::valueChanged), this, &WidefieldMicroscope::OnWidefieldLEDExposureTimeChanged);
712  Connect(Widget->GetUI().BWidefieldApplyLEDExposureTime, &QPushButton::clicked, this, &WidefieldMicroscope::OnWidefieldApplyLEDExposureTime);
713  Connect(Widget->GetUI().SBWidefieldPumpExposureTime, QOverload<int>::of(&QSpinBox::valueChanged), this, &WidefieldMicroscope::OnWidefieldPumpExposureTimeChanged);
714  Connect(Widget->GetUI().BWidefieldApplyPumpExposureTime, &QPushButton::clicked, this, &WidefieldMicroscope::OnWidefieldApplyPumpExposureTime);
715  Connect(Widget->GetUI().BWidefieldFindConfocalSpot, &QPushButton::clicked, this, &WidefieldMicroscope::OnWidefieldFindConfocalSpot);
716  Connect(Widget->GetUI().BWidefieldLEDCapture, &QPushButton::clicked, this, &WidefieldMicroscope::OnCaptureLEDImage);
717  Connect(Widget->GetUI().BWidefieldCapture, &QPushButton::clicked, this, &WidefieldMicroscope::OnCaptureWidefieldImage);
718  Connect(Widget->GetUI().BReadCellID, &QPushButton::clicked, this, &WidefieldMicroscope::OnWidefieldReadCellID);
719  Connect(Widget->GetUI().BAnalyzeImageDistortion, &QPushButton::clicked, this, &WidefieldMicroscope::OnWidefieldAnalyzeImageDistortion);
720  Connect(Widget->GetUI().BLocalizeEmitters, &QPushButton::clicked, this, &WidefieldMicroscope::OnWidefieldLocalizeEmitters);
722  Connect(Widget->GetUI().SBConfocalWidth, QOverload<int>::of(&QSpinBox::valueChanged), this, &WidefieldMicroscope::OnConfocalConfocalWidthChanged);
723  Connect(Widget->GetUI().SBConfocalHeight, QOverload<int>::of(&QSpinBox::valueChanged), this, &WidefieldMicroscope::OnConfocalConfocalHeightChanged);
724  Connect(Widget->GetUI().SBConfocalDistPerPixel, QOverload<int>::of(&QSpinBox::valueChanged), this, &WidefieldMicroscope::OnConfocalConfocalDistPerPixelChanged);
725  Connect(Widget->GetUI().SBConfocalSPDExposureTime, QOverload<int>::of(&QSpinBox::valueChanged), this, &WidefieldMicroscope::OnConfocalSPDExposureTimeChanged);
726  Connect(Widget->GetUI().SBConfocalOptimizationInitXYStepSize, QOverload<double>::of(&QDoubleSpinBox::valueChanged), this, &WidefieldMicroscope::OnConfocalOptimizationInitXYStepSizeChanged);
727  Connect(Widget->GetUI().SBConfocalOptimizationInitZStepSize, QOverload<double>::of(&QDoubleSpinBox::valueChanged), this, &WidefieldMicroscope::OnConfocalOptimizationInitZStepSizeChanged);
728  Connect(Widget->GetUI().SBConfocalOptimizationTolerance, QOverload<double>::of(&QDoubleSpinBox::valueChanged), this, &WidefieldMicroscope::OnConfocalOptimizationToleranceChanged);
729  Connect(Widget->GetUI().BConfocalScan, &QPushButton::clicked, this, &WidefieldMicroscope::OnPerformConfocalScan);
730  Connect(Widget->GetConfocalSurface3DSeries(), &QSurface3DSeries::selectedPointChanged, this, &WidefieldMicroscope::ConfocalSurfaceSelectedPointChanged);
731  Connect(Widget->GetUI().SBHBTBinWidth, QOverload<int>::of(&QSpinBox::valueChanged), this, &WidefieldMicroscope::OnHBTBinWidthChanged);
732  Connect(Widget->GetUI().SBHBTBinCount, QOverload<int>::of(&QSpinBox::valueChanged), this, &WidefieldMicroscope::OnHBTBinCountChanged);
733  Connect(Widget->GetUI().SBHBTAcquisitionTime, QOverload<double>::of(&QDoubleSpinBox::valueChanged), this, &WidefieldMicroscope::OnHHBTMaxIntegrationTimeChanged);
734  Connect(Widget->GetUI().BHBT, &QPushButton::clicked, this, &WidefieldMicroscope::OnMeasureHBT);
735  Connect(Widget->GetUI().LEAutoMeasureSavePath, &QLineEdit::textChanged, this, &WidefieldMicroscope::OnAutoMeasureSavePathChanged);
736  Connect(Widget->GetUI().SBAutoMeasureNumberImageSets, QOverload<int>::of(&QSpinBox::valueChanged), this, &WidefieldMicroscope::OnAutoMeasureNumberImageSetsChanged);
737  Connect(Widget->GetUI().SBAutoMeasureInitialImageSetWaitTime, QOverload<int>::of(&QSpinBox::valueChanged), this, &WidefieldMicroscope::OnAutoMeasureInitialImageSetWaitTimeChanged);
738  Connect(Widget->GetUI().SBAutoMeasureImagePositionScatterRadius, QOverload<int>::of(&QSpinBox::valueChanged), this, &WidefieldMicroscope::OnAutoMeasureImagePositionScatterRadius);
739  Connect(Widget->GetUI().CBAutoMeasureLocalize, &QComboBox::currentIndexChanged, this, &WidefieldMicroscope::OnAutoMeasureLocalizationTypeChanged);
740  Connect(Widget->GetUI().CBAutoMeasureOptimize, &QCheckBox::stateChanged, this, &WidefieldMicroscope::OnToggleAutoMeasureOptimizeEnabled);
741  Connect(Widget->GetUI().CBAutoMeasureEnableSpectrum, &QCheckBox::stateChanged, this, &WidefieldMicroscope::OnToggleAutoMeasureSpectrumEnabled);
742  Connect(Widget->GetUI().CBAutoMeasureEnableHBT, &QCheckBox::stateChanged, this, &WidefieldMicroscope::OnToggleAutoMeasureHBTEnabled);
743  Connect(Widget->GetUI().SBAutoMeasureOptimizationAttempts, QOverload<int>::of(&QSpinBox::valueChanged), this, &WidefieldMicroscope::OnAutoMeasureNumOptimizationAttemptsChanged);
744  Connect(Widget->GetUI().SBAutoMeasureOptimizationReruns, QOverload<int>::of(&QSpinBox::valueChanged), this, &WidefieldMicroscope::OnAutoMeasureMaxOptimizationRerunsChanged);
745  Connect(Widget->GetUI().SBAutoMeasureOptimizationMaxDistance, QOverload<int>::of(&QSpinBox::valueChanged), this, &WidefieldMicroscope::OnAutoMeasureOptimizationMaxDistanceChanged);
746  Connect(Widget->GetUI().SBAutoMeasureCountRateThreshold, QOverload<int>::of(&QSpinBox::valueChanged), this, &WidefieldMicroscope::OnAutoMeasureCountRateThresholdChanged);
747  Connect(Widget->GetUI().SBAutoMeasureCellRangeFromX, QOverload<int>::of(&QSpinBox::valueChanged), this, &WidefieldMicroscope::OnAutoMeasureCellRangeFromXChanged);
748  Connect(Widget->GetUI().SBAutoMeasureCellRangeFromY, QOverload<int>::of(&QSpinBox::valueChanged), this, &WidefieldMicroscope::OnAutoMeasureCellRangeFromYChanged);
749  Connect(Widget->GetUI().SBAutoMeasureCellRangeToX, QOverload<int>::of(&QSpinBox::valueChanged), this, &WidefieldMicroscope::OnAutoMeasureCellRangeToXChanged);
750  Connect(Widget->GetUI().SBAutoMeasureCellRangeToY, QOverload<int>::of(&QSpinBox::valueChanged), this, &WidefieldMicroscope::OnAutoMeasureCellRangeToYChanged);
751  Connect(Widget->GetUI().SBAutoMeasureCellSkipX, QOverload<int>::of(&QSpinBox::valueChanged), this, &WidefieldMicroscope::OnAutoMeasureCellSkipXChanged);
752  Connect(Widget->GetUI().SBAutoMeasureCellSkipY, QOverload<int>::of(&QSpinBox::valueChanged), this, &WidefieldMicroscope::OnAutoMeasureCellSkipYChanged);
753  Connect(Widget->GetUI().BAutoMeasureRunLocalization, &QPushButton::clicked, this, &WidefieldMicroscope::OnAutoMeasureRunLocalization);
754  Connect(Widget->GetUI().BAutoMeasureRunCharacterization, &QPushButton::clicked, this, &WidefieldMicroscope::OnAutoMeasureRunCharacterization);
755  Connect(Widget->GetUI().BAutoMeasureRunSampleCharacterization, &QPushButton::clicked, this, &WidefieldMicroscope::OnAutoMeasureRunSampleCharacterization);
756 
757  auto ModuleData = DynExp::dynamic_ModuleData_cast<WidefieldMicroscope>(GetModuleData());
758  ModuleData->SetSPDExposureTime(std::chrono::milliseconds(Widget->GetUI().SBConfocalSPDExposureTime->value()));
759 
760  return Widget;
761  }
762 
763  void WidefieldMicroscope::UpdateUIChild(const ModuleBase::ModuleDataGetterType& ModuleDataGetter)
764  {
765  auto Widget = GetWidget<WidefieldMicroscopeWidget>();
766  std::string UIMessage;
767 
768  {
769  auto ModuleData = DynExp::dynamic_ModuleData_cast<WidefieldMicroscope>(ModuleDataGetter());
770 
771  Widget->InitializeUI(ModuleData);
772  Widget->SetUIState(StateMachine.GetCurrentState(), StateMachine.GetContext(), ModuleData);
773  Widget->UpdateUIData(ModuleData);
774  Widget->UpdateWidefieldUIData(ModuleData);
775  Widget->UpdateConfocalUIData(ModuleData);
776  Widget->UpdateHBTUIData(ModuleData);
777  Widget->UpdateAutoMeasureUIData(ModuleData, IsCharacterizingSample());
778  Widget->UpdateScene();
779 
780  if (!ModuleData->GetUIMessage().empty())
781  {
782  UIMessage = ModuleData->GetUIMessage();
783  ModuleData->ClearUIMessage();
784  }
785  } // ModuleData unlocked here.
786 
787  if (!UIMessage.empty())
788  QMessageBox::warning(Widget, "Widefield Microscope", UIMessage.data());
789  }
790 
797  {
799  ModuleData->GetAcqCommunicator()->PostEvent(*this, SpectrumViewer::SetSilentModeEvent{ false });
800 
801  ModuleData->ResetAutoMeasureCurrentImageSet();
802  ModuleData->SetAutoMeasureRunning(false);
803 
804  LogUIMessagesOnly = false;
805 
806  StateMachine.ResetContext();
807 
808  // Must always return StateType::Ready.
809  return StateType::Ready;
810  }
811 
818  {
819  auto CurrentContext = StateMachine.GetContext();
820 
821  return CurrentContext == &AutoMeasureSampleContext ||
822  CurrentContext == &AutoMeasureSampleRecenterCellContext ||
823  CurrentContext == &AutoMeasureSampleLocalizationContext ||
824  CurrentContext == &AutoMeasureSampleCharacterizationContext ||
828  }
829 
830  // Point in nm
831  void WidefieldMicroscope::MoveSampleTo(const ModuleDataType::PositionPoint& Point, Util::SynchronizedPointer<ModuleDataType>& ModuleData) const
832  {
834  {
836  ModuleData->GetSampleStageX()->MoveAbsolute(Point.x / ModuleData->GetSampleStageX()->GetStepNanoMeterRatio(),
838  *PositionerState = PositionerStateType::Moving;
839  }
840  );
841  }
842 
844  {
846  ModuleData->GetSampleStageY()->MoveAbsolute(Point.y / ModuleData->GetSampleStageX()->GetStepNanoMeterRatio(),
848  *PositionerState = PositionerStateType::Moving;
849  }
850  );
851  }
852 
854  {
856  ModuleData->GetSampleStageZ()->MoveAbsolute(Point.z / ModuleData->GetSampleStageX()->GetStepNanoMeterRatio(),
858  *PositionerState = PositionerStateType::Moving;
859  }
860  );
861  }
862  }
863 
871  {
873  return false;
875  return true; // Movement has not started yet.
876 
877  auto SampleStageXData = DynExp::dynamic_InstrumentData_cast<DynExpInstr::PositionerStage>(ModuleData->GetSampleStageX()->GetInstrumentData());
878  auto SampleStageYData = DynExp::dynamic_InstrumentData_cast<DynExpInstr::PositionerStage>(ModuleData->GetSampleStageY()->GetInstrumentData());
879  bool IsMoving = !SampleStageXData->HasArrived() || !SampleStageYData->HasArrived();
880 
881  if (!IsMoving)
882  {
885  }
886 
887  return IsMoving;
888  }
889 
890  void WidefieldMicroscope::SetFocus(Util::SynchronizedPointer<ModuleDataType>& ModuleData, double Voltage, bool IgnoreOffset) const
891  {
893  return;
894 
895  ModuleData->GetSampleFocusPiezoZ()->SetSync(std::max(ModuleData->GetMinFocusVoltage(),
896  std::min(ModuleData->GetMaxFocusVoltage(), Voltage +
897  ((ModuleData->GetSetupMode() == WidefieldMicroscopeData::SetupModeType::Confocal && !IgnoreOffset) ? ModuleData->GetFocusConfocalOffsetVoltage() : .0))));
898  ModuleData->SetFocusCurrentVoltage(Voltage);
899  }
900 
902  QPoint MarkerPos, QPointF SamplePos) const
903  {
904  const auto DiffPosInPx = ModuleData->GetConfocalSpotImagePosition() - MarkerPos;
905  const WidefieldMicroscopeData::PositionPoint SamplePosPoint(Util::NumToT<WidefieldMicroscopeData::PositionType>(SamplePos.x()), Util::NumToT<WidefieldMicroscopeData::PositionType>(SamplePos.y()));
906 
907  return SamplePosPoint + PositionPointFromPixelDist(ModuleParams, ModuleData, DiffPosInPx.x(), DiffPosInPx.y());
908  }
909 
911  QPoint MarkerPos, QPointF SamplePos) const
912  {
913  MoveSampleTo(CalcMarkerToConfocalSpotDestiny(ModuleParams, ModuleData, MarkerPos, SamplePos), ModuleData);
914  }
915 
917  const int DistPerPixel, const WidefieldMicroscopeData::PositionPoint CenterPosition) const
918  {
919  ModuleDataType::QSurfaceDataRowsType QSurfaceDataRows;
920  ConfocalScanPositions.clear();
921 
922  for (int i = 1; i <= Height; ++i)
923  {
924  auto y = CenterPosition.y + (-static_cast<double>(Height) / 2 + i) * DistPerPixel;
925  auto Row = std::make_unique<QSurfaceDataRow>(Width);
926 
927  for (auto j = Width; j > 0; --j)
928  {
929  double x{};
930 
931  // Create a 'wiggly' line.
932  if (i % 2)
933  x = CenterPosition.x + (-static_cast<double>(Width) / 2 + j) * DistPerPixel;
934  else
935  x = CenterPosition.x + (static_cast<double>(Width) / 2 - j + 1) * DistPerPixel;
936 
937  auto ColIndex = i % 2 ? j - 1 : Width - j;
938  (*Row)[ColIndex].setPosition(QVector3D(std::round(x), 0, std::round(y)));
940  ConfocalScanPositions.back().RowIndex = Util::NumToT<int>(QSurfaceDataRows.size());
941  ConfocalScanPositions.back().ColumnIndex = ColIndex;
942  }
943 
944  QSurfaceDataRows.push_back(std::move(Row));
945  }
946 
947  return QSurfaceDataRows;
948  }
949 
951  {
953  return;
954 
956  ModuleData->GetPumpPower()->SetSync(ModuleData->GetWidefieldPumpPower());
957  else
958  ModuleData->GetPumpPower()->SetSync(ModuleData->GetConfocalPumpPower());
959  }
960 
962  {
963  ImageCapturingPaused = false;
965  ModuleData->GetAcqCommunicator()->PostEvent(*this, ImageViewer::PauseImageCapturingEvent{ true });
966 
967  ModuleData->GetWidefieldCamera()->StopCapturingSync();
968 
969  {
970  auto CameraData = DynExp::dynamic_InstrumentData_cast<DynExpInstr::Camera>(ModuleData->GetWidefieldCamera()->GetInstrumentData());
971  CameraData->ClearImage();
972  } // CameraData unlocked here.
973  }
974 
976  {
977  ModuleData->GetWidefieldCamera()->CaptureSingle();
978  }
979 
981  {
982  if (ModuleData->GetCurrentImage().isNull())
984  else
985  {
987  ModuleData->GetWidefieldLocalizer()->ReadCellID(ModuleData->GetCurrentImage(),
988  [CellIDState = WidefieldCellIDState](const DynExp::TaskBase&, DynExp::ExceptionContainer& Exception) {
989  try
990  {
991  Exception.Throw();
992  }
993  catch (const Util::ServiceFailedException& e)
994  {
996  Exception.ClearError();
997 
998  Util::EventLog().Log("Reading the cell ID from the current image, the error listed below occurred.", Util::ErrorType::Error);
999  Util::EventLog().Log(e.what());
1000 
1001  return;
1002  }
1003 
1005  }
1006  );
1007  }
1008 
1010  }
1011 
1012  StateType WidefieldMicroscope::InitiateLocalizationFromImage(Util::SynchronizedPointer<ModuleDataType>& ModuleData) const
1013  {
1014  if (ModuleData->GetCurrentImage().isNull())
1015  *WidefieldLocalizationState = WidefieldImageProcessingStateType::Failed;
1016  else
1017  {
1018  const auto CallbackFunc = [LocalizerState = WidefieldLocalizationState](const DynExp::TaskBase&, DynExp::ExceptionContainer& Exception) {
1019  try
1020  {
1021  Exception.Throw();
1022  }
1023  catch (const Util::ServiceFailedException& e)
1024  {
1025  *LocalizerState = WidefieldImageProcessingStateType::Failed;
1026  Exception.ClearError();
1027 
1028  Util::EventLog().Log("Localizing emitters in the widefield image, the error listed below occurred.", Util::ErrorType::Error);
1029  Util::EventLog().Log(e.what());
1030 
1031  return;
1032  }
1033 
1034  *LocalizerState = WidefieldImageProcessingStateType::Finished;
1035  };
1036 
1037  *WidefieldLocalizationState = WidefieldImageProcessingStateType::Waiting;
1038 
1039  if (ModuleData->GetAutoMeasureLocalizationType() == WidefieldMicroscopeWidget::LocalizationType::LocalizeEmittersFromImage)
1040  ModuleData->GetWidefieldLocalizer()->AnalyzeWidefield(ModuleData->GetCurrentImage(), CallbackFunc);
1041  else
1042  ModuleData->GetWidefieldLocalizer()->RecallPositions(ModuleData->GetCurrentImage(),
1043  ModuleData->GetCellID(), ModuleData->GetAutoMeasureSavePath().string(), CallbackFunc);
1044  }
1045 
1046  return StateType::WaitingForWidefieldLocalization;
1047  }
1048 
1049  void WidefieldMicroscope::PrepareAPDsForConfocalMode(Util::SynchronizedPointer<ModuleDataType>& ModuleData) const
1050  {
1051  ModuleData->GetSPD1()->SetStreamSize(1);
1052  ModuleData->GetSPD1()->SetExposureTime(ModuleData->GetSPDExposureTime());
1053  ModuleData->GetSPD1()->SetCoincidenceWindow(ModuleData->GetSPD1()->GetResolution());
1054 
1055  if (ModuleData->TestFeature(WidefieldMicroscopeData::FeatureType::HBT))
1056  {
1057  ModuleData->GetSPD2()->SetStreamSize(1);
1058  ModuleData->GetSPD2()->SetExposureTime(ModuleData->GetSPDExposureTime());
1059  ModuleData->GetSPD2()->SetCoincidenceWindow(ModuleData->GetSPD2()->GetResolution());
1060  }
1061  }
1062 
1063  void WidefieldMicroscope::InitializeConfocalOptimizer(Util::SynchronizedPointer<ModuleDataType>& ModuleData) const
1064  {
1065  ConfocalOptimizationNumStepsPerformed = 0;
1066 
1067  PrepareAPDsForConfocalMode(ModuleData);
1068  SetFocus(ModuleData, ModuleData->GetFocusZeroVoltage());
1069  auto SamplePosition = ModuleData->GetSamplePosition();
1070 
1071  gsl_vector_set(GSLConfocalOptimizationStepSize, 0,
1072  ModuleData->GetSampleStageX()->GetResolution() * ModuleData->GetConfocalOptimizationInitXYStepSize());
1073  gsl_vector_set(GSLConfocalOptimizationStepSize, 1,
1074  ModuleData->GetSampleStageY()->GetResolution() * ModuleData->GetConfocalOptimizationInitXYStepSize());
1075  gsl_vector_set(GSLConfocalOptimizationStepSize, 2,
1076  ModuleData->GetSampleFocusPiezoZ()->GetHardwareResolution() * ModuleData->GetConfocalOptimizationInitZStepSize());
1077  gsl_vector_set(GSLConfocalOptimizationInitialPoint, 0, SamplePosition.x);
1078  gsl_vector_set(GSLConfocalOptimizationInitialPoint, 1, SamplePosition.y);
1079  gsl_vector_set(GSLConfocalOptimizationInitialPoint, 2, ModuleData->GetFocusZeroVoltage());
1080  }
1081 
1082  void WidefieldMicroscope::SetHBTSwitch(Util::SynchronizedPointer<const ParamsType>& ModuleParams,
1083  Util::SynchronizedPointer<ModuleDataType>& ModuleData, bool IsHBTMode) const
1084  {
1085  ModuleData->GetWidefieldHBTSwitch()->Clear();
1086  ModuleData->GetWidefieldHBTSwitch()->SetRectFunction({ 1, 1, 0, 0,
1087  IsHBTMode ? ModuleParams->WidefieldHBTSwitchHighDutyCycle : ModuleParams->WidefieldHBTSwitchLowDutyCycle },
1088  false, true);
1089  }
1090 
1091  void WidefieldMicroscope::InitializeHBT(Util::SynchronizedPointer<ModuleDataType>& ModuleData) const
1092  {
1093  ModuleData->ClearHBTDataPoints();
1094  ModuleData->SetHBTSamplePosition(ModuleData->GetSamplePosition());
1095 
1096  auto TimeTagger = DynExp::dynamic_Object_cast<DynExpInstr::TimeTagger>(ModuleData->GetSPD1().get());
1097  TimeTagger->SetHBTActive(true);
1098  TimeTagger->ConfigureHBT(ModuleData->GetHBTBinWidth(), ModuleData->GetHBTBinCount());
1099  TimeTagger->ResetHBT();
1100  HBTIntegrationTimeBeforeReset = ModuleData->GetHBTTotalIntegrationTime();
1101  }
1102 
1103  void WidefieldMicroscope::StopHBT(Util::SynchronizedPointer<ModuleDataType>& ModuleData) const
1104  {
1105  if (ModuleData->TestFeature(WidefieldMicroscopeData::FeatureType::HBT))
1106  {
1107  auto SPD1 = DynExp::dynamic_Object_cast<DynExpInstr::TimeTagger>(ModuleData->GetSPD1().get());
1108  auto SPD1Data = DynExp::dynamic_InstrumentData_cast<DynExpInstr::TimeTagger>(SPD1->GetInstrumentData());
1109  auto SPD2Data = DynExp::dynamic_InstrumentData_cast<DynExpInstr::TimeTagger>(ModuleData->GetSPD2()->GetInstrumentData());
1110  SPD1->SetHBTActive(false);
1111  SPD1Data->ResetStreamMode();
1112  SPD2Data->ResetStreamMode();
1113  }
1114  }
1115 
1116  StateType WidefieldMicroscope::StartAutofocus(Util::SynchronizedPointer<ModuleDataType>& ModuleData) const
1117  {
1118  if (ModuleData->TestFeature(WidefieldMicroscopeData::FeatureType::WidefieldConfocalSwitch))
1119  {
1120  ModuleData->SetSetupMode(WidefieldMicroscopeData::SetupModeType::Widefield);
1121 
1122  if (!IsCharacterizingSample())
1123  StateMachine.SetContext(&AutofocusSetupTransitioningContext);
1124 
1125  return StateType::SetupTransitionBegin;
1126  }
1127  else
1128  return StateType::AutofocusBegin;
1129  }
1130 
1131  StateType WidefieldMicroscope::StartAutoMeasureLocalization(Util::SynchronizedPointer<ModuleDataType>& ModuleData) const
1132  {
1133  if (ModuleData->TestFeature(WidefieldMicroscopeData::FeatureType::InterModuleCommunicator))
1134  ModuleData->GetAcqCommunicator()->PostEvent(*this, SpectrumViewer::SetSilentModeEvent{ true });
1135 
1136  ModuleData->SetAutoMeasureCurrentCellPosition(ModuleData->GetSamplePosition());
1137  ModuleData->ResetAutoMeasureCurrentImageSet();
1138  WaitingEndTimePoint = std::chrono::system_clock::now() + ModuleData->GetAutoMeasureInitialImageSetWaitTime();
1139 
1140  LogUIMessagesOnly = true;
1141 
1142  StateMachine.SetContext(IsCharacterizingSample() ? &AutoMeasureSampleLocalizationContext : &AutoMeasureLocalizationContext);
1143  if (ModuleData->TestFeature(WidefieldMicroscopeData::FeatureType::WidefieldConfocalSwitch))
1144  {
1145  ModuleData->SetSetupMode(WidefieldMicroscopeData::SetupModeType::Widefield);
1146 
1147  return StateType::SetupTransitionBegin;
1148  }
1149  else
1150  return StateType::Waiting;
1151  }
1152 
1153  StateType WidefieldMicroscope::StartAutoMeasureCharacterization(Util::SynchronizedPointer<ModuleDataType>& ModuleData, Util::MarkerGraphicsView::MarkerType::IDType FirstEmitterID) const
1154  {
1155  if (FirstEmitterID < 0)
1156  ModuleData->ResetAutoMeasureCurrentEmitter();
1157  else
1158  {
1159  bool Success = ModuleData->SetAutoMeasureFirstEmitter(FirstEmitterID);
1160  if (!Success)
1161  return ResetState(ModuleData);
1162  }
1163 
1164  std::ranges::for_each(ModuleData->GetLocalizedPositions(), [](auto& Item) { Item.second.State = WidefieldMicroscopeData::LocalizedEmitterStateType::NotSet; });
1165  ModuleData->SetLocalizedPositionsStateChanged();
1166  ModuleData->SetAutoMeasureRunning(true);
1167  ModuleData->SetAutoMeasureCurrentCellPosition(ModuleData->GetSamplePosition());
1168 
1169  LogUIMessagesOnly = true;
1170 
1171  StateMachine.SetContext(IsCharacterizingSample() ? &AutoMeasureSampleCharacterizationContext : &AutoMeasureCharacterizationContext);
1172  if (ModuleData->TestFeature(WidefieldMicroscopeData::FeatureType::WidefieldConfocalSwitch))
1173  {
1174  ModuleData->SetSetupMode(WidefieldMicroscopeData::SetupModeType::Confocal);
1175 
1176  return StateType::SetupTransitionBegin;
1177  }
1178  else
1179  return StateType::AutoMeasureCharacterizationStep;
1180  }
1181 
1182  StateType WidefieldMicroscope::StartAutoMeasureSampleCharacterization(Util::SynchronizedPointer<ModuleDataType>& ModuleData) const
1183  {
1184  LogUIMessagesOnly = true;
1185 
1186  StateMachine.SetContext(&AutoMeasureSampleContext);
1187 
1188  return StateType::AutoMeasureSampleStep;
1189  }
1190 
1191  std::filesystem::path WidefieldMicroscope::BuildFilename(Util::SynchronizedPointer<ModuleDataType>& ModuleData, std::string_view FilenameSuffix) const
1192  {
1193  auto SavePath = ModuleData->GetAutoMeasureSavePath();
1194  SavePath.replace_filename(SavePath.filename().stem().concat(FilenameSuffix));
1195  std::filesystem::create_directories(SavePath.parent_path());
1196 
1197  return SavePath;
1198  }
1199 
1200  WidefieldMicroscope::ModuleDataType::PositionPoint WidefieldMicroscope::RandomPointInCircle(ModuleDataType::PositionType Radius) const
1201  {
1202  static std::random_device random_devce;
1203  static std::mt19937 random_generator(random_devce());
1204  static std::uniform_real_distribution<double> angle_random_distribution(0., 2. * std::numbers::pi);
1205  std::uniform_real_distribution<double> radius_random_distribution(0., Radius);
1206 
1207  const auto angle = angle_random_distribution(random_generator);
1208  const auto r = radius_random_distribution(random_generator);
1209  const auto x = Util::NumToT<ModuleDataType::PositionType>(r * std::cos(angle));
1210  const auto y = Util::NumToT<ModuleDataType::PositionType>(r * std::sin(angle));
1211 
1212  return { x, y };
1213  }
1214 
1215  void WidefieldMicroscope::ConfocalOptimizationInitPromises()
1216  {
1217  ConfocalOptimizationStatePromise = decltype(ConfocalOptimizationStatePromise)();
1218  ConfocalOptimizationStateFuture = ConfocalOptimizationStatePromise.get_future();
1219  ConfocalOptimizationFeedbackPromise = decltype(ConfocalOptimizationFeedbackPromise)();
1220  ConfocalOptimizationFeedbackFuture = ConfocalOptimizationFeedbackPromise.get_future();
1221 
1222  ConfocalOptimizationPromisesRenewed = true;
1223  }
1224 
1225  // Run gsl minimizer in its own thread since it calls a callback function to evaluate the result of the samples.
1226  // This can only be done in an async way interacting with the module thread since stages have to be moved etc.
1227  WidefieldMicroscope::ConfocalOptimizationThreadReturnType WidefieldMicroscope::ConfocalOptimizationThread(WidefieldMicroscope* Owner)
1228  {
1229  try
1230  {
1231  if (Owner->ConfocalOptimizationNumStepsPerformed == 0)
1232  {
1233  auto Status = gsl_multimin_fminimizer_set(Owner->GSLConfocalOptimizationState, &Owner->GSLConfocalOptimizationFuncDesc,
1235 
1236  return Status ? ConfocalOptimizationThreadReturnType::Failed : ConfocalOptimizationThreadReturnType::NextStep;
1237  }
1238  else
1239  {
1240  auto Status = gsl_multimin_fminimizer_iterate(Owner->GSLConfocalOptimizationState);
1241  if (Status)
1242  return ConfocalOptimizationThreadReturnType::Failed;
1243 
1244  auto Size = gsl_multimin_fminimizer_size(Owner->GSLConfocalOptimizationState);
1245 
1246  {
1247  auto ModuleData = DynExp::dynamic_ModuleData_cast<WidefieldMicroscope>(Owner->GetModuleData());
1248 
1249  Status = gsl_multimin_test_size(Size, ModuleData->GetConfocalOptimizationTolerance());
1250  } // ModuleData unlocked here.
1251 
1252  return Status == GSL_SUCCESS ? ConfocalOptimizationThreadReturnType::Finished :
1253  (Status == GSL_CONTINUE ? ConfocalOptimizationThreadReturnType::NextStep : ConfocalOptimizationThreadReturnType::Failed);
1254  }
1255  }
1256  catch (...)
1257  {
1258  return ConfocalOptimizationThreadReturnType::Failed;
1259  }
1260  }
1261 
1262  // This callback function can be evaluated by gsl minimizer multiple times per iteration!
1263  double WidefieldMicroscope::ConfocalOptimizationFuncForwarder(const gsl_vector* vector, void* params)
1264  {
1265  return static_cast<WidefieldMicroscope*>(params)->ConfocalOptimizationFunc(vector);
1266  }
1267 
1268  double WidefieldMicroscope::ConfocalOptimizationFunc(const gsl_vector* vector) noexcept
1269  {
1270  try
1271  {
1272  // ConfocalOptimizationPromisesRenewed must also be set to true if minimizer should abort...
1273  while (!ConfocalOptimizationPromisesRenewed)
1274  std::this_thread::yield();
1275 
1276  auto X = static_cast<decltype(ConfocalOptimizationStateType::X)>(gsl_vector_get(vector, 0));
1277  auto Y = static_cast<decltype(ConfocalOptimizationStateType::Y)>(gsl_vector_get(vector, 1));
1278  auto Z = static_cast<decltype(ConfocalOptimizationStateType::Z)>(gsl_vector_get(vector, 2));
1279 
1280  // ...in that case, prmoise might already contain a value. This will trigger a std::future_error
1281  // being caught (and swallowed) below.
1282  ConfocalOptimizationStatePromise.set_value({ X, Y, Z });
1283 
1284  if (!ConfocalOptimizationFeedbackFuture.valid())
1285  return GSL_NAN;
1286 
1287  // If ConfocalOptimizationFeedbackPromise is destroyed while waiting, std::future_error is thrown here.
1288  return ConfocalOptimizationFeedbackFuture.get();
1289  }
1290  catch (...)
1291  {
1292  return GSL_NAN;
1293  }
1294  }
1295 
1296  void WidefieldMicroscope::OnInit(DynExp::ModuleInstance* Instance) const
1297  {
1298  ImageViewer::ImageCapturingPausedEvent::Register(*this, &WidefieldMicroscope::OnImageCapturingPaused);
1299  ImageViewer::FinishedAutofocusEvent::Register(*this, &WidefieldMicroscope::OnFinishedAutofocus);
1300  SpectrumViewer::SpectrumFinishedRecordingEvent::Register(*this, &WidefieldMicroscope::OnSpectrumFinishedRecording);
1301 
1302  auto ModuleParams = DynExp::dynamic_Params_cast<WidefieldMicroscope>(Instance->ParamsGetter());
1303  auto ModuleData = DynExp::dynamic_ModuleData_cast<WidefieldMicroscope>(Instance->ModuleDataGetter());
1304 
1305  if (ModuleParams->AcqCommunicator.ContainsID())
1306  {
1307  Instance->LockObject(ModuleParams->AcqCommunicator, ModuleData->GetAcqCommunicator());
1308  ModuleData->SetFeature(WidefieldMicroscopeData::FeatureType::InterModuleCommunicator);
1309  }
1310 
1311  if (ModuleParams->WidefieldCamera.ContainsID())
1312  {
1313  Instance->LockObject(ModuleParams->WidefieldCamera, ModuleData->GetWidefieldCamera());
1314  ModuleData->SetFeature(WidefieldMicroscopeData::FeatureType::Widefield);
1315 
1316  {
1317  auto CameraData = DynExp::dynamic_InstrumentData_cast<DynExpInstr::Camera>(ModuleData->GetWidefieldCamera()->GetInstrumentData());
1318  ModuleData->SetMinCameraExposureTime(CameraData->GetMinExposureTime());
1319  ModuleData->SetMaxCameraExposureTime(CameraData->GetMaxExposureTime());
1320  } // CameraData unlocked here.
1321 
1322  if (ModuleParams->WidefieldLocalizer.ContainsID())
1323  {
1324  Instance->LockObject(ModuleParams->WidefieldLocalizer, ModuleData->GetWidefieldLocalizer());
1325  ModuleData->SetFeature(WidefieldMicroscopeData::FeatureType::WidefieldLocalization);
1326  }
1327  }
1328 
1329  if (ModuleParams->SampleStageX.ContainsID() && ModuleParams->SampleStageY.ContainsID())
1330  {
1331  Instance->LockObject(ModuleParams->SampleStageX, ModuleData->GetSampleStageX());
1332  Instance->LockObject(ModuleParams->SampleStageY, ModuleData->GetSampleStageY());
1333 
1334  ModuleData->SetFeature(WidefieldMicroscopeData::FeatureType::SampleXYPositioning);
1335 
1336  if (ModuleParams->SPD1.ContainsID())
1337  {
1338  Instance->LockObject(ModuleParams->SPD1, ModuleData->GetSPD1());
1339  ModuleData->SetFeature(WidefieldMicroscopeData::FeatureType::Confocal);
1340  }
1341  }
1342 
1343  if (ModuleParams->SampleStageZ.ContainsID())
1344  {
1345  Instance->LockObject(ModuleParams->SampleStageZ, ModuleData->GetSampleStageZ());
1346  ModuleData->SetFeature(WidefieldMicroscopeData::FeatureType::SampleZPositioning);
1347  }
1348 
1349  if (ModuleParams->FocusPiezoZ.ContainsID())
1350  {
1351  Instance->LockObject(ModuleParams->FocusPiezoZ, ModuleData->GetSampleFocusPiezoZ());
1352 
1353  if (ModuleData->TestFeature(WidefieldMicroscopeData::FeatureType::InterModuleCommunicator))
1354  ModuleData->SetFeature(WidefieldMicroscopeData::FeatureType::FocusAdjustment);
1355  if (ModuleData->TestFeature(WidefieldMicroscopeData::FeatureType::SampleXYPositioning))
1356  ModuleData->SetFeature(WidefieldMicroscopeData::FeatureType::ConfocalOptimization);
1357 
1358  ModuleData->SetMinFocusVoltage(ModuleData->GetSampleFocusPiezoZ()->GetUserMinValue());
1359  ModuleData->SetMaxFocusVoltage(ModuleData->GetSampleFocusPiezoZ()->GetUserMaxValue());
1360  }
1361 
1362  if (ModuleParams->SPD1.ContainsID() && ModuleParams->SPD2.ContainsID())
1363  {
1364  if (!ModuleData->TestFeature(WidefieldMicroscopeData::FeatureType::Confocal))
1365  Instance->LockObject(ModuleParams->SPD1, ModuleData->GetSPD1());
1366  Instance->LockObject(ModuleParams->SPD2, ModuleData->GetSPD2());
1367 
1368  ModuleData->SetFeature(WidefieldMicroscopeData::FeatureType::HBT);
1369  }
1370 
1371  if (ModuleParams->LEDSwitch.ContainsID())
1372  {
1373  Instance->LockObject(ModuleParams->LEDSwitch, ModuleData->GetLEDSwitch());
1374  ModuleData->SetFeature(WidefieldMicroscopeData::FeatureType::LEDLightToggle);
1375 
1376  ModuleData->SetLEDLightTurnedOn(false);
1377  }
1378 
1379  if (ModuleParams->PumpSwitch.ContainsID())
1380  {
1381  Instance->LockObject(ModuleParams->PumpSwitch, ModuleData->GetPumpSwitch());
1382  ModuleData->SetFeature(WidefieldMicroscopeData::FeatureType::PumpLightToggle);
1383 
1384  ModuleData->SetPumpLightTurnedOn(false);
1385  }
1386 
1387  if (ModuleParams->PumpPower.ContainsID())
1388  {
1389  Instance->LockObject(ModuleParams->PumpPower, ModuleData->GetPumpPower());
1390  ModuleData->SetFeature(WidefieldMicroscopeData::FeatureType::SetPumpPower);
1391 
1392  ModuleData->SetMinPumpPower(ModuleData->GetPumpPower()->GetUserMinValue());
1393  ModuleData->SetMaxPumpPower(ModuleData->GetPumpPower()->GetUserMaxValue());
1394  ModuleData->SetWidefieldPumpPower(ModuleParams->DefaultPowerWidefieldMode);
1395  ModuleData->SetConfocalPumpPower(ModuleParams->DefaultPowerConfocalMode);
1396  }
1397 
1398  if (ModuleParams->PumpPowerIndicator.ContainsID())
1399  {
1400  Instance->LockObject(ModuleParams->PumpPowerIndicator, ModuleData->GetPumpPowerIndicator());
1401  ModuleData->SetFeature(WidefieldMicroscopeData::FeatureType::MeasurePumpPower);
1402  }
1403 
1404  if (ModuleParams->WidefieldConfocalSwitch.ContainsID())
1405  {
1406  Instance->LockObject(ModuleParams->WidefieldConfocalSwitch, ModuleData->GetWidefieldConfocalSwitch());
1407  ModuleData->SetFeature(WidefieldMicroscopeData::FeatureType::WidefieldConfocalSwitch);
1408 
1409  if (ModuleParams->WidefieldConfocalIndicator.ContainsID())
1410  {
1411  Instance->LockObject(ModuleParams->WidefieldConfocalIndicator, ModuleData->GetWidefieldConfocalIndicator());
1412  ModuleData->SetFeature(WidefieldMicroscopeData::FeatureType::WidefieldConfocalIndicator);
1413 
1414  ModuleData->SetSetupMode(ModuleData->GetWidefieldConfocalIndicator()->GetSync() ? WidefieldMicroscopeData::SetupModeType::Confocal : WidefieldMicroscopeData::SetupModeType::Widefield);
1415  }
1416  else
1417  ModuleData->SetSetupMode(WidefieldMicroscopeData::SetupModeType::Widefield);
1418  }
1419 
1420  if (ModuleParams->WidefieldHBTSwitch.ContainsID())
1421  {
1422  Instance->LockObject(ModuleParams->WidefieldHBTSwitch, ModuleData->GetWidefieldHBTSwitch());
1423  ModuleData->SetFeature(WidefieldMicroscopeData::FeatureType::HBTSwitch);
1424 
1425  MakeAndEnqueueEvent(this, &WidefieldMicroscope::OnToggleHBTMirror, false);
1426  }
1427  }
1428 
1429  void WidefieldMicroscope::OnExit(DynExp::ModuleInstance* Instance) const
1430  {
1431  auto ModuleData = DynExp::dynamic_ModuleData_cast<WidefieldMicroscope>(Instance->ModuleDataGetter());
1432 
1433  OnStopAction(Instance, false);
1434 
1435  Instance->UnlockObject(ModuleData->GetAcqCommunicator());
1436  Instance->UnlockObject(ModuleData->GetSampleStageX());
1437  Instance->UnlockObject(ModuleData->GetSampleStageY());
1438  Instance->UnlockObject(ModuleData->GetSampleStageZ());
1439  Instance->UnlockObject(ModuleData->GetSampleFocusPiezoZ());
1440  Instance->UnlockObject(ModuleData->GetLEDSwitch());
1441  Instance->UnlockObject(ModuleData->GetPumpSwitch());
1442  Instance->UnlockObject(ModuleData->GetWidefieldConfocalSwitch());
1443  Instance->UnlockObject(ModuleData->GetWidefieldConfocalIndicator());
1444  Instance->UnlockObject(ModuleData->GetWidefieldHBTSwitch());
1445  Instance->UnlockObject(ModuleData->GetPumpPower());
1446  Instance->UnlockObject(ModuleData->GetPumpPowerIndicator());
1447  Instance->UnlockObject(ModuleData->GetWidefieldCamera());
1448  Instance->UnlockObject(ModuleData->GetWidefieldLocalizer());
1449  Instance->UnlockObject(ModuleData->GetSPD1());
1450  Instance->UnlockObject(ModuleData->GetSPD2());
1451 
1455  }
1456 
1457  void WidefieldMicroscope::OnTerminate(DynExp::ModuleInstance* Instance, bool) const
1458  {
1459  Instance->Exit();
1460  }
1461 
1462  void WidefieldMicroscope::OnStopAction(DynExp::ModuleInstance* Instance, bool) const
1463  {
1464  auto ModuleData = DynExp::dynamic_ModuleData_cast<WidefieldMicroscope>(Instance->ModuleDataGetter());
1465 
1466  // Firstly, stop moving parts.
1467  if (ModuleData->TestFeature(WidefieldMicroscopeData::FeatureType::Confocal))
1468  {
1469  ModuleData->GetSampleStageX()->StopMotion();
1470  ModuleData->GetSampleStageY()->StopMotion();
1471  }
1472 
1473  if (ModuleData->TestFeature(WidefieldMicroscopeData::FeatureType::Widefield))
1474  ModuleData->GetWidefieldCamera()->StopCapturing();
1475 
1476  StopHBT(ModuleData);
1477 
1478  if (ConfocalOptimizationThreadReturnFuture.valid())
1479  {
1480  // Unblock ConfocalOptimizationThread (see above). Set ConfocalOptimizationPromisesRenewed to true
1481  // last to avoid ConfocalOptimizationFunc access ConfocalOptimizationFeedbackFuture while
1482  // ConfocalOptimizationFeedbackPromise is destroyed.
1483  ConfocalOptimizationFeedbackPromise = decltype(ConfocalOptimizationFeedbackPromise)();
1484  ConfocalOptimizationPromisesRenewed = true;
1485 
1486  // ...and wait for ConfocalOptimizationThread to terminate. This is important not to use involved
1487  // WidefieldMicroscope member variables by multiple running gsl optimization threads if a new
1488  // optimization is started directly after.
1489  ConfocalOptimizationThreadReturnFuture.wait();
1490  }
1491 
1492  if (ModuleData->IsAutoMeasureRunning())
1493  {
1494  if (ModuleData->GetAutoMeasureCurrentEmitter() != ModuleData->GetLocalizedPositions().cend())
1495  {
1496  ModuleData->GetAutoMeasureCurrentEmitter()->second.State = WidefieldMicroscopeData::LocalizedEmitterStateType::NotSet;
1497  ModuleData->SetLocalizedPositionsStateChanged();
1498  }
1499 
1500  ModuleData->SetAutoMeasureRunning(false);
1501  }
1502 
1503  StateMachine.SetCurrentState(ResetState(ModuleData));
1504  }
1505 
1506  void WidefieldMicroscope::OnSetHomePosition(DynExp::ModuleInstance* Instance, bool) const
1507  {
1508  auto ModuleData = DynExp::dynamic_ModuleData_cast<WidefieldMicroscope>(Instance->ModuleDataGetter());
1509 
1510  if (!IsReadyState() || !ModuleData->TestFeature(WidefieldMicroscopeData::FeatureType::Confocal))
1511  return;
1512 
1513  ModuleData->SetSampleHomePosition(ModuleData->GetSamplePosition());
1514  }
1515 
1516  void WidefieldMicroscope::OnGoToHomePosition(DynExp::ModuleInstance* Instance, bool) const
1517  {
1518  auto ModuleData = DynExp::dynamic_ModuleData_cast<WidefieldMicroscope>(Instance->ModuleDataGetter());
1519 
1520  if (!IsReadyState() || !ModuleData->TestFeature(WidefieldMicroscopeData::FeatureType::Confocal))
1521  return;
1522 
1523  MoveSampleTo(ModuleData->GetSampleHomePosition(), ModuleData);
1524  }
1525 
1526  void WidefieldMicroscope::OnToggleLEDLightSource(DynExp::ModuleInstance* Instance, bool State) const
1527  {
1528  auto ModuleData = DynExp::dynamic_ModuleData_cast<WidefieldMicroscope>(Instance->ModuleDataGetter());
1529 
1530  if (!ModuleData->TestFeature(WidefieldMicroscopeData::FeatureType::LEDLightToggle))
1531  return;
1532 
1533  ModuleData->SetLEDLightTurnedOn(State);
1534  }
1535 
1536  void WidefieldMicroscope::OnTogglePumpLightSource(DynExp::ModuleInstance* Instance, bool State) const
1537  {
1538  auto ModuleData = DynExp::dynamic_ModuleData_cast<WidefieldMicroscope>(Instance->ModuleDataGetter());
1539 
1540  if (!ModuleData->TestFeature(WidefieldMicroscopeData::FeatureType::PumpLightToggle))
1541  return;
1542 
1543  ModuleData->SetPumpLightTurnedOn(State);
1544  }
1545 
1546  void WidefieldMicroscope::OnSetupModeChanged(DynExp::ModuleInstance* Instance, QAction* Action) const
1547  {
1548  auto ModuleData = DynExp::dynamic_ModuleData_cast<WidefieldMicroscope>(Instance->ModuleDataGetter());
1549 
1550  if (!IsReadyState() || !ModuleData->TestFeature(WidefieldMicroscopeData::FeatureType::WidefieldConfocalSwitch))
1551  return;
1552 
1553  if (Action == GetWidget<WidefieldMicroscopeWidget>()->GetUI().action_Widefield_mode)
1554  ModuleData->SetSetupMode(WidefieldMicroscopeData::SetupModeType::Widefield);
1555  else if (Action == GetWidget<WidefieldMicroscopeWidget>()->GetUI().action_Confocal_mode)
1556  ModuleData->SetSetupMode(WidefieldMicroscopeData::SetupModeType::Confocal);
1557  else
1558  return;
1559 
1560  StateMachine.SetCurrentState(StateType::SetupTransitionBegin);
1561  }
1562 
1563  void WidefieldMicroscope::OnAutofocus(DynExp::ModuleInstance* Instance, bool) const
1564  {
1565  auto ModuleData = DynExp::dynamic_ModuleData_cast<WidefieldMicroscope>(Instance->ModuleDataGetter());
1566 
1567  if (!IsReadyState() || !ModuleData->TestFeature(WidefieldMicroscopeData::FeatureType::FocusAdjustment))
1568  return;
1569 
1570  StateMachine.SetCurrentState(StartAutofocus(ModuleData));
1571  }
1572 
1573  void WidefieldMicroscope::OnOptimizePositions(DynExp::ModuleInstance* Instance, bool) const
1574  {
1575  auto ModuleData = DynExp::dynamic_ModuleData_cast<WidefieldMicroscope>(Instance->ModuleDataGetter());
1576 
1577  if (!IsReadyState() || !ModuleData->TestFeature(WidefieldMicroscopeData::FeatureType::ConfocalOptimization)
1578  || ModuleData->GetSetupMode() != WidefieldMicroscopeData::SetupModeType::Confocal)
1579  return;
1580 
1581  InitializeConfocalOptimizer(ModuleData);
1582 
1583  // To move the positioners and to record the count rate, state functions from confocal scanning are used.
1584  StateMachine.SetContext(&ConfocalOptimizationContext);
1585  StateMachine.SetCurrentState(StateType::ConfocalOptimizationInit);
1586  }
1587 
1588  void WidefieldMicroscope::OnToggleHBTMirror(DynExp::ModuleInstance* Instance, bool Checked) const
1589  {
1590  auto ModuleParams = DynExp::dynamic_Params_cast<WidefieldMicroscope>(Instance->ParamsGetter());
1591  auto ModuleData = DynExp::dynamic_ModuleData_cast<WidefieldMicroscope>(Instance->ModuleDataGetter());
1592 
1593  if (!IsReadyState() || !ModuleData->TestFeature(WidefieldMicroscopeData::FeatureType::HBTSwitch))
1594  return;
1595 
1596  SetHBTSwitch(ModuleParams, ModuleData, Checked);
1597  }
1598 
1599  void WidefieldMicroscope::OnResetCellID(DynExp::ModuleInstance* Instance, bool) const
1600  {
1601  if (!IsReadyState())
1602  return;
1603 
1604  auto ModuleData = DynExp::dynamic_ModuleData_cast<WidefieldMicroscope>(Instance->ModuleDataGetter());
1605  ModuleData->ResetCellID();
1606  }
1607 
1608  void WidefieldMicroscope::OnGeneralWidefieldPowerChanged(DynExp::ModuleInstance* Instance, double Value) const
1609  {
1610  auto ModuleData = DynExp::dynamic_ModuleData_cast<WidefieldMicroscope>(Instance->ModuleDataGetter());
1611  ModuleData->SetWidefieldPumpPower(Value);
1612 
1613  UpdatePumpPower(ModuleData);
1614  }
1615 
1616  void WidefieldMicroscope::OnGeneralConfocalPowerChanged(DynExp::ModuleInstance* Instance, double Value) const
1617  {
1618  auto ModuleData = DynExp::dynamic_ModuleData_cast<WidefieldMicroscope>(Instance->ModuleDataGetter());
1619  ModuleData->SetConfocalPumpPower(Value);
1620 
1621  UpdatePumpPower(ModuleData);
1622  }
1623 
1624  void WidefieldMicroscope::OnGeneralFocusCurrentVoltageChanged(DynExp::ModuleInstance* Instance, double Value) const
1625  {
1626  if (!IsReadyState())
1627  return;
1628 
1629  auto ModuleData = DynExp::dynamic_ModuleData_cast<WidefieldMicroscope>(Instance->ModuleDataGetter());
1630  SetFocus(ModuleData, Value);
1631  }
1632 
1633  void WidefieldMicroscope::OnGeneralFocusZeroVoltageChanged(DynExp::ModuleInstance* Instance, double Value) const
1634  {
1635  auto ModuleData = DynExp::dynamic_ModuleData_cast<WidefieldMicroscope>(Instance->ModuleDataGetter());
1636  ModuleData->SetFocusZeroVoltage(Value);
1637  }
1638 
1639  void WidefieldMicroscope::OnGeneralFocusConfocalOffsetVoltageChanged(DynExp::ModuleInstance* Instance, double Value) const
1640  {
1641  auto ModuleData = DynExp::dynamic_ModuleData_cast<WidefieldMicroscope>(Instance->ModuleDataGetter());
1642  ModuleData->SetFocusConfocalOffsetVoltage(Value);
1643 
1644  if (IsReadyState() && ModuleData->GetSetupMode() == WidefieldMicroscopeData::SetupModeType::Confocal)
1645  SetFocus(ModuleData, ModuleData->GetFocusCurrentVoltage());
1646  }
1647 
1648  void WidefieldMicroscope::OnGeneralSetZeroFocus(DynExp::ModuleInstance* Instance, bool) const
1649  {
1650  auto ModuleData = DynExp::dynamic_ModuleData_cast<WidefieldMicroscope>(Instance->ModuleDataGetter());
1651  ModuleData->SetFocusZeroVoltage(ModuleData->GetFocusCurrentVoltage());
1652  }
1653 
1654  void WidefieldMicroscope::OnGeneralApplyZeroFocus(DynExp::ModuleInstance* Instance, bool) const
1655  {
1656  if (!IsReadyState())
1657  return;
1658 
1659  auto ModuleData = DynExp::dynamic_ModuleData_cast<WidefieldMicroscope>(Instance->ModuleDataGetter());
1660  SetFocus(ModuleData, ModuleData->GetFocusZeroVoltage());
1661  }
1662 
1663  void WidefieldMicroscope::OnWidefieldLEDExposureTimeChanged(DynExp::ModuleInstance* Instance, int Value) const
1664  {
1665  auto ModuleData = DynExp::dynamic_ModuleData_cast<WidefieldMicroscope>(Instance->ModuleDataGetter());
1666  ModuleData->SetLEDCameraExposureTime(std::chrono::milliseconds(static_cast<std::chrono::milliseconds::rep>(Value)));
1667  }
1668 
1669  void WidefieldMicroscope::OnWidefieldApplyLEDExposureTime(DynExp::ModuleInstance* Instance, bool) const
1670  {
1671  auto ModuleData = DynExp::dynamic_ModuleData_cast<WidefieldMicroscope>(Instance->ModuleDataGetter());
1672 
1673  if (!IsReadyState() || !ModuleData->TestFeature(WidefieldMicroscopeData::FeatureType::Widefield))
1674  return;
1675 
1676  if (ModuleData->GetWidefieldCamera()->CanSetExposureTime())
1677  ModuleData->GetWidefieldCamera()->SetExposureTime(ModuleData->GetLEDCameraExposureTime());
1678  }
1679 
1680  void WidefieldMicroscope::OnWidefieldPumpExposureTimeChanged(DynExp::ModuleInstance* Instance, int Value) const
1681  {
1682  auto ModuleData = DynExp::dynamic_ModuleData_cast<WidefieldMicroscope>(Instance->ModuleDataGetter());
1683  ModuleData->SetWidefieldCameraExposureTime(std::chrono::milliseconds(static_cast<std::chrono::milliseconds::rep>(Value)));
1684  }
1685 
1686  void WidefieldMicroscope::OnWidefieldApplyPumpExposureTime(DynExp::ModuleInstance* Instance, bool) const
1687  {
1688  auto ModuleData = DynExp::dynamic_ModuleData_cast<WidefieldMicroscope>(Instance->ModuleDataGetter());
1689 
1690  if (!IsReadyState() || !ModuleData->TestFeature(WidefieldMicroscopeData::FeatureType::Widefield))
1691  return;
1692 
1693  if (ModuleData->GetWidefieldCamera()->CanSetExposureTime())
1694  ModuleData->GetWidefieldCamera()->SetExposureTime(ModuleData->GetWidefieldCameraExposureTime());
1695  }
1696 
1697  void WidefieldMicroscope::OnWidefieldFindConfocalSpot(DynExp::ModuleInstance* Instance, bool) const
1698  {
1699  auto ModuleData = DynExp::dynamic_ModuleData_cast<WidefieldMicroscope>(Instance->ModuleDataGetter());
1700 
1701  if (!IsReadyState() || !ModuleData->TestFeature(WidefieldMicroscopeData::FeatureType::Widefield)
1702  || !ModuleData->TestFeature(WidefieldMicroscopeData::FeatureType::WidefieldConfocalSwitch))
1703  return;
1704 
1705  StateMachine.SetCurrentState(StateType::FindingConfocalSpotBegin);
1706  }
1707 
1708  void WidefieldMicroscope::OnCaptureLEDImage(DynExp::ModuleInstance* Instance, bool) const
1709  {
1710  auto ModuleData = DynExp::dynamic_ModuleData_cast<WidefieldMicroscope>(Instance->ModuleDataGetter());
1711 
1712  if (!IsReadyState() || !ModuleData->TestFeature(WidefieldMicroscopeData::FeatureType::Widefield))
1713  return;
1714 
1715  if (ModuleData->TestFeature(WidefieldMicroscopeData::FeatureType::WidefieldConfocalSwitch))
1716  {
1717  ModuleData->SetSetupMode(WidefieldMicroscopeData::SetupModeType::Widefield);
1718 
1719  StateMachine.SetContext(&LEDImageAcquisitionSetupTransitioningContext);
1720  StateMachine.SetCurrentState(StateType::SetupTransitionBegin);
1721  }
1722  else
1723  StateMachine.SetCurrentState(StateType::LEDImageAcquisitionBegin);
1724  }
1725 
1726  void WidefieldMicroscope::OnCaptureWidefieldImage(DynExp::ModuleInstance* Instance, bool) const
1727  {
1728  auto ModuleData = DynExp::dynamic_ModuleData_cast<WidefieldMicroscope>(Instance->ModuleDataGetter());
1729 
1730  if (!IsReadyState() || !ModuleData->TestFeature(WidefieldMicroscopeData::FeatureType::Widefield))
1731  return;
1732 
1733  if (ModuleData->TestFeature(WidefieldMicroscopeData::FeatureType::WidefieldConfocalSwitch))
1734  {
1735  ModuleData->SetSetupMode(WidefieldMicroscopeData::SetupModeType::Widefield);
1736 
1737  StateMachine.SetContext(&WidefieldImageAcquisitionSetupTransitioningContext);
1738  StateMachine.SetCurrentState(StateType::SetupTransitionBegin);
1739  }
1740  else
1741  StateMachine.SetCurrentState(StateType::WidefieldImageAcquisitionBegin);
1742  }
1743 
1744  void WidefieldMicroscope::OnWidefieldReadCellID(DynExp::ModuleInstance* Instance, bool) const
1745  {
1746  auto ModuleData = DynExp::dynamic_ModuleData_cast<WidefieldMicroscope>(Instance->ModuleDataGetter());
1747 
1748  if (!IsReadyState() || !ModuleData->TestFeature(WidefieldMicroscopeData::FeatureType::WidefieldLocalization))
1749  return;
1750 
1751  StateMachine.SetCurrentState(InitiateReadCellIDFromImage(ModuleData));
1752  }
1753 
1754  void WidefieldMicroscope::OnWidefieldAnalyzeImageDistortion(DynExp::ModuleInstance* Instance, bool) const
1755  {
1756  auto ModuleData = DynExp::dynamic_ModuleData_cast<WidefieldMicroscope>(Instance->ModuleDataGetter());
1757 
1758  if (!IsReadyState() || !ModuleData->TestFeature(WidefieldMicroscopeData::FeatureType::WidefieldLocalization) || ModuleData->GetCurrentImage().isNull())
1759  return;
1760 
1761  ModuleData->GetWidefieldLocalizer()->AnalyzeDistortion(ModuleData->GetCurrentImage());
1762  }
1763 
1764  void WidefieldMicroscope::OnWidefieldLocalizeEmitters(DynExp::ModuleInstance* Instance, bool) const
1765  {
1766  auto ModuleData = DynExp::dynamic_ModuleData_cast<WidefieldMicroscope>(Instance->ModuleDataGetter());
1767 
1768  if (!IsReadyState() || !ModuleData->TestFeature(WidefieldMicroscopeData::FeatureType::WidefieldLocalization))
1769  return;
1770 
1771  StateMachine.SetCurrentState(InitiateLocalizationFromImage(ModuleData));
1772  }
1773 
1774  void WidefieldMicroscope::OnWidefieldImageClicked(DynExp::ModuleInstance* Instance, QPoint Position) const
1775  {
1776  auto ModuleData = DynExp::dynamic_ModuleData_cast<WidefieldMicroscope>(Instance->ModuleDataGetter());
1777 
1778  // The rest is tested in OnBringMarkerToConfocalSpot().
1779  if (ModuleData->GetWidefieldPosition().IsEmpty())
1780  return;
1781 
1782  OnBringMarkerToConfocalSpot(Instance, Position, { static_cast<qreal>(ModuleData->GetWidefieldPosition().x), static_cast<qreal>(ModuleData->GetWidefieldPosition().y) });
1783  }
1784 
1785  void WidefieldMicroscope::OnConfocalConfocalWidthChanged(DynExp::ModuleInstance* Instance, int Value) const
1786  {
1787  auto ModuleData = DynExp::dynamic_ModuleData_cast<WidefieldMicroscope>(Instance->ModuleDataGetter());
1788  ModuleData->SetConfocalScanWidth(Value);
1789  }
1790 
1791  void WidefieldMicroscope::OnConfocalConfocalHeightChanged(DynExp::ModuleInstance* Instance, int Value) const
1792  {
1793  auto ModuleData = DynExp::dynamic_ModuleData_cast<WidefieldMicroscope>(Instance->ModuleDataGetter());
1794  ModuleData->SetConfocalScanHeight(Value);
1795  }
1796 
1797  void WidefieldMicroscope::OnConfocalConfocalDistPerPixelChanged(DynExp::ModuleInstance* Instance, int Value) const
1798  {
1799  auto ModuleData = DynExp::dynamic_ModuleData_cast<WidefieldMicroscope>(Instance->ModuleDataGetter());
1800  ModuleData->SetConfocalScanDistPerPixel(Value);
1801  }
1802 
1803  void WidefieldMicroscope::OnConfocalSPDExposureTimeChanged(DynExp::ModuleInstance* Instance, int Value) const
1804  {
1805  auto ModuleData = DynExp::dynamic_ModuleData_cast<WidefieldMicroscope>(Instance->ModuleDataGetter());
1806  ModuleData->SetSPDExposureTime(std::chrono::milliseconds(Value));
1807  }
1808 
1809  void WidefieldMicroscope::OnConfocalOptimizationInitXYStepSizeChanged(DynExp::ModuleInstance* Instance, double Value) const
1810  {
1811  auto ModuleData = DynExp::dynamic_ModuleData_cast<WidefieldMicroscope>(Instance->ModuleDataGetter());
1812  ModuleData->SetConfocalOptimizationInitXYStepSize(Value);
1813  }
1814 
1815  void WidefieldMicroscope::OnConfocalOptimizationInitZStepSizeChanged(DynExp::ModuleInstance* Instance, double Value) const
1816  {
1817  auto ModuleData = DynExp::dynamic_ModuleData_cast<WidefieldMicroscope>(Instance->ModuleDataGetter());
1818  ModuleData->SetConfocalOptimizationInitZStepSize(Value);
1819  }
1820 
1821  void WidefieldMicroscope::OnConfocalOptimizationToleranceChanged(DynExp::ModuleInstance* Instance, double Value) const
1822  {
1823  auto ModuleData = DynExp::dynamic_ModuleData_cast<WidefieldMicroscope>(Instance->ModuleDataGetter());
1824  ModuleData->SetConfocalOptimizationTolerance(Value);
1825  }
1826 
1827  void WidefieldMicroscope::OnPerformConfocalScan(DynExp::ModuleInstance* Instance, bool) const
1828  {
1829  int Width{}, Height{}, DistPerPixel{};
1830  WidefieldMicroscopeData::PositionPoint CenterPosition{ 0, 0 };
1831 
1832  OnGoToHomePosition(Instance, false);
1833 
1834  {
1835  auto ModuleData = DynExp::dynamic_ModuleData_cast<WidefieldMicroscope>(Instance->ModuleDataGetter());
1836 
1837  if (!IsReadyState() || !ModuleData->TestFeature(WidefieldMicroscopeData::FeatureType::Confocal))
1838  return;
1839 
1840  CenterPosition = ModuleData->GetSamplePosition();
1841 
1842  Width = ModuleData->GetConfocalScanWidth();
1843  Height = ModuleData->GetConfocalScanHeight();
1844  DistPerPixel = ModuleData->GetConfocalScanDistPerPixel();
1845 
1846  PrepareAPDsForConfocalMode(ModuleData);
1847 
1848  ModuleData->ClearConfocalScanResults();
1849 
1850  } // ModuleData unlocked here.
1851 
1852  // ModuleData unlocked for this call, because it is potentially heavy.
1853  auto SurfaceDataRows = CalculateConfocalScanPositions(Width, Height, DistPerPixel, CenterPosition);
1854 
1855  auto ModuleData = DynExp::dynamic_ModuleData_cast<WidefieldMicroscope>(Instance->ModuleDataGetter());
1856  ModuleData->SetConfocalScanSurfacePlotRows(std::move(SurfaceDataRows));
1857 
1858  StateMachine.SetCurrentState(StateType::ConfocalScanStep);
1859  }
1860 
1861  void WidefieldMicroscope::ConfocalSurfaceSelectedPointChanged(DynExp::ModuleInstance* Instance, QPoint Position) const
1862  {
1863  auto ModuleData = DynExp::dynamic_ModuleData_cast<WidefieldMicroscope>(Instance->ModuleDataGetter());
1864 
1865  if (!IsReadyState() || !ModuleData->TestFeature(WidefieldMicroscopeData::FeatureType::Confocal))
1866  return;
1867 
1868  const auto& Results = ModuleData->GetConfocalScanResults();
1869  auto ResultItemIt = std::find_if(Results.cbegin(), Results.cend(), [&Position](const std::pair<WidefieldMicroscopeData::PositionPoint, double>& ResultItem) {
1870  return ResultItem.first.RowIndex == Position.x() && ResultItem.first.ColumnIndex == Position.y();
1871  });
1872 
1873  if (ResultItemIt != Results.cend())
1874  MoveSampleTo({ ResultItemIt->first.MeasuredX, ResultItemIt->first.MeasuredY }, ModuleData);
1875  }
1876 
1877  void WidefieldMicroscope::OnHBTBinWidthChanged(DynExp::ModuleInstance* Instance, int Value) const
1878  {
1879  auto ModuleData = DynExp::dynamic_ModuleData_cast<WidefieldMicroscope>(Instance->ModuleDataGetter());
1880  ModuleData->SetHBTBinWidth(Util::picoseconds(static_cast<Util::picoseconds::rep>(Value)));
1881  }
1882 
1883  void WidefieldMicroscope::OnHBTBinCountChanged(DynExp::ModuleInstance* Instance, int Value) const
1884  {
1885  auto ModuleData = DynExp::dynamic_ModuleData_cast<WidefieldMicroscope>(Instance->ModuleDataGetter());
1886  ModuleData->SetHBTBinCount(Value);
1887  }
1888 
1889  void WidefieldMicroscope::OnHHBTMaxIntegrationTimeChanged(DynExp::ModuleInstance* Instance, double Value) const
1890  {
1891  auto ModuleData = DynExp::dynamic_ModuleData_cast<WidefieldMicroscope>(Instance->ModuleDataGetter());
1892  ModuleData->SetHBTMaxIntegrationTime(std::chrono::microseconds(Util::NumToT<std::chrono::microseconds::rep>(Value * std::chrono::microseconds::period::den)));
1893  }
1894 
1895  void WidefieldMicroscope::OnMeasureHBT(DynExp::ModuleInstance* Instance, bool) const
1896  {
1897  auto ModuleData = DynExp::dynamic_ModuleData_cast<WidefieldMicroscope>(Instance->ModuleDataGetter());
1898 
1899  if (!IsReadyState() || !ModuleData->TestFeature(WidefieldMicroscopeData::FeatureType::HBT))
1900  return;
1901 
1902  InitializeHBT(ModuleData);
1903 
1904  StateMachine.SetCurrentState(StateType::HBTAcquiring);
1905  }
1906 
1907  void WidefieldMicroscope::OnImageCapturingPaused(DynExp::ModuleInstance* Instance) const
1908  {
1909  ImageCapturingPaused = true;
1910  }
1911 
1912  void WidefieldMicroscope::OnFinishedAutofocus(DynExp::ModuleInstance* Instance, bool Success, double Voltage) const
1913  {
1914  static constexpr const char* AutofocusFailedErrorMsg = "Autofocusing failed!";
1915 
1916  if (StateMachine.GetCurrentState()->GetState() != StateType::AutofocusWaiting)
1917  return;
1918 
1919  auto ModuleData = DynExp::dynamic_ModuleData_cast<WidefieldMicroscope>(Instance->ModuleDataGetter());
1920  ModuleData->SetAutofocusFinished();
1921 
1922  if (Success)
1923  {
1924  Voltage -= ModuleData->GetSetupMode() == WidefieldMicroscopeData::SetupModeType::Confocal ? ModuleData->GetFocusConfocalOffsetVoltage() : .0;
1925 
1926  SetFocus(ModuleData, Voltage);
1927  ModuleData->SetFocusZeroVoltage(Voltage);
1928  }
1929  else
1930  {
1931  if (LogUIMessagesOnly)
1932  Util::EventLogger().Log(AutofocusFailedErrorMsg, Util::ErrorType::Error);
1933  else
1934  {
1935  auto ModuleData = DynExp::dynamic_ModuleData_cast<WidefieldMicroscope>(Instance->ModuleDataGetter());
1936  ModuleData->SetUIMessage(AutofocusFailedErrorMsg);
1937  }
1938  }
1939 
1940  if (ModuleData->TestFeature(WidefieldMicroscopeData::FeatureType::LEDLightToggle))
1941  ModuleData->SetLEDLightTurnedOn(false);
1942  }
1943 
1944  void WidefieldMicroscope::OnSpectrumFinishedRecording(DynExp::ModuleInstance* Instance) const
1945  {
1946  StateMachine.SetCurrentState(StateType::SpectrumAcquisitionFinished);
1947  }
1948 
1949  void WidefieldMicroscope::OnAutoMeasureSavePathChanged(DynExp::ModuleInstance* Instance, QString Path) const
1950  {
1951  auto ModuleData = DynExp::dynamic_ModuleData_cast<WidefieldMicroscope>(Instance->ModuleDataGetter());
1952  ModuleData->SetAutoMeasureSavePath(Path.toStdString());
1953  }
1954 
1955  void WidefieldMicroscope::OnAutoMeasureNumberImageSetsChanged(DynExp::ModuleInstance* Instance, int Value) const
1956  {
1957  auto ModuleData = DynExp::dynamic_ModuleData_cast<WidefieldMicroscope>(Instance->ModuleDataGetter());
1958  ModuleData->SetAutoMeasureNumberImageSets(Value);
1959  }
1960 
1961  void WidefieldMicroscope::OnAutoMeasureInitialImageSetWaitTimeChanged(DynExp::ModuleInstance* Instance, int Value) const
1962  {
1963  auto ModuleData = DynExp::dynamic_ModuleData_cast<WidefieldMicroscope>(Instance->ModuleDataGetter());
1964  ModuleData->SetAutoMeasureInitialImageSetWaitTime(std::chrono::seconds(static_cast<std::chrono::seconds::rep>(Value)));
1965  }
1966 
1967  void WidefieldMicroscope::OnAutoMeasureImagePositionScatterRadius(DynExp::ModuleInstance* Instance, int Value) const
1968  {
1969  auto ModuleData = DynExp::dynamic_ModuleData_cast<WidefieldMicroscope>(Instance->ModuleDataGetter());
1970  ModuleData->SetAutoMeasureImagePositionScatterRadius(Value);
1971  }
1972 
1973  void WidefieldMicroscope::OnAutoMeasureLocalizationTypeChanged(DynExp::ModuleInstance* Instance, int Value) const
1974  {
1975  auto ModuleData = DynExp::dynamic_ModuleData_cast<WidefieldMicroscope>(Instance->ModuleDataGetter());
1976  ModuleData->SetAutoMeasureLocalizationType(static_cast<WidefieldMicroscopeWidget::LocalizationType>(Value));
1977  }
1978 
1979  void WidefieldMicroscope::OnToggleAutoMeasureOptimizeEnabled(DynExp::ModuleInstance* Instance, int State) const
1980  {
1981  auto ModuleData = DynExp::dynamic_ModuleData_cast<WidefieldMicroscope>(Instance->ModuleDataGetter());
1982  ModuleData->SetAutoMeasureOptimizeEnabled(State);
1983  }
1984 
1985  void WidefieldMicroscope::OnToggleAutoMeasureSpectrumEnabled(DynExp::ModuleInstance* Instance, int State) const
1986  {
1987  auto ModuleData = DynExp::dynamic_ModuleData_cast<WidefieldMicroscope>(Instance->ModuleDataGetter());
1988  ModuleData->SetAutoMeasureSpectrumEnabled(State);
1989  }
1990 
1991  void WidefieldMicroscope::OnToggleAutoMeasureHBTEnabled(DynExp::ModuleInstance* Instance, int State) const
1992  {
1993  auto ModuleData = DynExp::dynamic_ModuleData_cast<WidefieldMicroscope>(Instance->ModuleDataGetter());
1994  ModuleData->SetAutoMeasureHBTEnabled(State);
1995  }
1996 
1997  void WidefieldMicroscope::OnAutoMeasureNumOptimizationAttemptsChanged(DynExp::ModuleInstance* Instance, int Value) const
1998  {
1999  auto ModuleData = DynExp::dynamic_ModuleData_cast<WidefieldMicroscope>(Instance->ModuleDataGetter());
2000  ModuleData->SetAutoMeasureNumOptimizationAttempts(Value);
2001  }
2002 
2003  void WidefieldMicroscope::OnAutoMeasureMaxOptimizationRerunsChanged(DynExp::ModuleInstance* Instance, int Value) const
2004  {
2005  auto ModuleData = DynExp::dynamic_ModuleData_cast<WidefieldMicroscope>(Instance->ModuleDataGetter());
2006  ModuleData->SetAutoMeasureMaxOptimizationReruns(Value);
2007  }
2008 
2009  void WidefieldMicroscope::OnAutoMeasureOptimizationMaxDistanceChanged(DynExp::ModuleInstance* Instance, int Value) const
2010  {
2011  auto ModuleData = DynExp::dynamic_ModuleData_cast<WidefieldMicroscope>(Instance->ModuleDataGetter());
2012  ModuleData->SetAutoMeasureOptimizationMaxDistance(Value);
2013  }
2014 
2015  void WidefieldMicroscope::OnAutoMeasureCountRateThresholdChanged(DynExp::ModuleInstance* Instance, int Value) const
2016  {
2017  auto ModuleData = DynExp::dynamic_ModuleData_cast<WidefieldMicroscope>(Instance->ModuleDataGetter());
2018  ModuleData->SetAutoMeasureCountRateThreshold(Value);
2019  }
2020 
2021  void WidefieldMicroscope::OnAutoMeasureCellRangeFromXChanged(DynExp::ModuleInstance* Instance, int Value) const
2022  {
2023  auto ModuleData = DynExp::dynamic_ModuleData_cast<WidefieldMicroscope>(Instance->ModuleDataGetter());
2024  ModuleData->GetAutoMeasureCellRangeFrom().setX(Value);
2025  }
2026 
2027  void WidefieldMicroscope::OnAutoMeasureCellRangeFromYChanged(DynExp::ModuleInstance* Instance, int Value) const
2028  {
2029  auto ModuleData = DynExp::dynamic_ModuleData_cast<WidefieldMicroscope>(Instance->ModuleDataGetter());
2030  ModuleData->GetAutoMeasureCellRangeFrom().setY(Value);
2031  }
2032 
2033  void WidefieldMicroscope::OnAutoMeasureCellRangeToXChanged(DynExp::ModuleInstance* Instance, int Value) const
2034  {
2035  auto ModuleData = DynExp::dynamic_ModuleData_cast<WidefieldMicroscope>(Instance->ModuleDataGetter());
2036  ModuleData->GetAutoMeasureCellRangeTo().setX(Value);
2037  }
2038 
2039  void WidefieldMicroscope::OnAutoMeasureCellRangeToYChanged(DynExp::ModuleInstance* Instance, int Value) const
2040  {
2041  auto ModuleData = DynExp::dynamic_ModuleData_cast<WidefieldMicroscope>(Instance->ModuleDataGetter());
2042  ModuleData->GetAutoMeasureCellRangeTo().setY(Value);
2043  }
2044 
2045  void WidefieldMicroscope::OnAutoMeasureCellSkipXChanged(DynExp::ModuleInstance* Instance, int Value) const
2046  {
2047  auto ModuleData = DynExp::dynamic_ModuleData_cast<WidefieldMicroscope>(Instance->ModuleDataGetter());
2048  ModuleData->GetAutoMeasureCellSkip().setX(Value);
2049  }
2050 
2051  void WidefieldMicroscope::OnAutoMeasureCellSkipYChanged(DynExp::ModuleInstance* Instance, int Value) const
2052  {
2053  auto ModuleData = DynExp::dynamic_ModuleData_cast<WidefieldMicroscope>(Instance->ModuleDataGetter());
2054  ModuleData->GetAutoMeasureCellSkip().setY(Value);
2055  }
2056 
2057  void WidefieldMicroscope::OnAutoMeasureRunLocalization(DynExp::ModuleInstance* Instance, bool) const
2058  {
2059  auto ModuleData = DynExp::dynamic_ModuleData_cast<WidefieldMicroscope>(Instance->ModuleDataGetter());
2060 
2061  if (!IsReadyState() || !ModuleData->TestFeature(WidefieldMicroscopeData::FeatureType::Widefield))
2062  return;
2063 
2064  StateMachine.SetCurrentState(StartAutoMeasureLocalization(ModuleData));
2065  }
2066 
2067  void WidefieldMicroscope::OnAutoMeasureRunCharacterization(DynExp::ModuleInstance* Instance, bool) const
2068  {
2069  auto ModuleData = DynExp::dynamic_ModuleData_cast<WidefieldMicroscope>(Instance->ModuleDataGetter());
2070 
2071  if (!IsReadyState() || !ModuleData->TestFeature(WidefieldMicroscopeData::FeatureType::Confocal) ||
2072  ModuleData->GetLocalizedPositions().empty() || ModuleData->GetWidefieldPosition().IsEmpty())
2073  return;
2074 
2075  StateMachine.SetCurrentState(StartAutoMeasureCharacterization(ModuleData));
2076  }
2077 
2078  void WidefieldMicroscope::OnAutoMeasureRunSampleCharacterization(DynExp::ModuleInstance* Instance, bool) const
2079  {
2080  auto ModuleData = DynExp::dynamic_ModuleData_cast<WidefieldMicroscope>(Instance->ModuleDataGetter());
2081 
2082  if (!IsReadyState() || !ModuleData->TestFeature(WidefieldMicroscopeData::FeatureType::Widefield) ||
2083  !ModuleData->TestFeature(WidefieldMicroscopeData::FeatureType::Confocal) ||
2084  !ModuleData->TestFeature(WidefieldMicroscopeData::FeatureType::WidefieldLocalization))
2085  return;
2086 
2087  if (!ModuleData->IsCellRangeValid())
2088  {
2089  ModuleData->SetUIMessage("Please specify a valid cell range.");
2090 
2091  return;
2092  }
2093 
2094  // Required to especially reset WidefieldMicroscopeData::LastCellID, which is needed to determine
2095  // the direction of advancing from cell to cell.
2096  ModuleData->ResetCellID();
2097 
2098  StateMachine.SetCurrentState(StartAutoMeasureSampleCharacterization(ModuleData));
2099  }
2100 
2101  StateType WidefieldMicroscope::ReturnToReadyStateFunc(DynExp::ModuleInstance& Instance)
2102  {
2103  auto ModuleData = DynExp::dynamic_ModuleData_cast<WidefieldMicroscope>(Instance.ModuleDataGetter());
2104 
2105  // This state may be replaced by a state machine context.
2106  // Do not perform any complex task here, just transition back to the ready state.
2107  return ResetState(ModuleData);
2108  }
2109 
2110  StateType WidefieldMicroscope::InitializingStateFunc(DynExp::ModuleInstance& Instance)
2111  {
2112  auto ModuleData = DynExp::dynamic_ModuleData_cast<WidefieldMicroscope>(Instance.ModuleDataGetter());
2113 
2114  ResetState(ModuleData);
2115 
2116  if (ModuleData->TestFeature(WidefieldMicroscopeData::FeatureType::WidefieldConfocalSwitch))
2117  return StateType::SetupTransitionBegin;
2118 
2119  return StateType::Ready;
2120  }
2121 
2122  StateType WidefieldMicroscope::SetupTransitionBeginStateFunc(DynExp::ModuleInstance& Instance)
2123  {
2124  {
2125  auto ModuleParams = DynExp::dynamic_Params_cast<WidefieldMicroscope>(Instance.ParamsGetter());
2126  SetupTransitionFinishedTimePoint = std::chrono::system_clock::now() + std::chrono::milliseconds(ModuleParams->WidefieldConfocalTransitionTime);
2127  } // ModuleParams unlocked here.
2128 
2129  auto ModuleData = DynExp::dynamic_ModuleData_cast<WidefieldMicroscope>(Instance.ModuleDataGetter());
2130 
2131  if (ModuleData->GetSetupMode() == WidefieldMicroscopeData::SetupModeType::Unknown)
2132  {
2133  ModuleData->SetUIMessage("Transitioning failed due to unknown destiny setup mode!");
2134 
2135  return ResetState(ModuleData);
2136  }
2137 
2138  if (ModuleData->TestFeature(WidefieldMicroscopeData::FeatureType::PumpLightToggle))
2139  {
2140  TurnOnPumpSourceAfterTransitioning = ModuleData->GetPumpLightTurnedOn();
2141  ModuleData->SetPumpLightTurnedOn(false);
2142  }
2143  else
2144  TurnOnPumpSourceAfterTransitioning = false;
2145 
2146  if (ModuleData->GetSetupMode() == WidefieldMicroscopeData::SetupModeType::Widefield)
2147  ModuleData->GetWidefieldConfocalSwitch()->Set(false);
2148  else if (ModuleData->GetSetupMode() == WidefieldMicroscopeData::SetupModeType::Confocal)
2149  ModuleData->GetWidefieldConfocalSwitch()->Set(true);
2150 
2151  return StateType::SetupTransitioning;
2152  }
2153 
2154  StateType WidefieldMicroscope::SetupTransitioningStateFunc(DynExp::ModuleInstance& Instance)
2155  {
2156  return std::chrono::system_clock::now() >= SetupTransitionFinishedTimePoint ? StateType::SetupTransitionEnd : StateType::SetupTransitioning;
2157  }
2158 
2159  StateType WidefieldMicroscope::SetupTransitionEndStateFunc(DynExp::ModuleInstance& Instance)
2160  {
2161  auto ModuleData = DynExp::dynamic_ModuleData_cast<WidefieldMicroscope>(Instance.ModuleDataGetter());
2162 
2163  if (ModuleData->TestFeature(WidefieldMicroscopeData::FeatureType::WidefieldConfocalIndicator)
2164  && ModuleData->GetWidefieldConfocalIndicator()->GetSync() != (ModuleData->GetSetupMode() == WidefieldMicroscopeData::SetupModeType::Confocal))
2165  {
2166  ModuleData->SetUIMessage("Transitioning into " + std::string(ModuleData->GetSetupMode() == WidefieldMicroscopeData::SetupModeType::Confocal ? "confocal" : "widefield") + " mode failed!");
2167  ModuleData->SetSetupMode(ModuleData->GetSetupMode() == WidefieldMicroscopeData::SetupModeType::Confocal ? WidefieldMicroscopeData::SetupModeType::Widefield : WidefieldMicroscopeData::SetupModeType::Confocal);
2168 
2169  return ResetState(ModuleData);
2170  }
2171 
2172  // Update focus to account for a focus deviation in between confocal/widefield mode.
2173  SetFocus(ModuleData, ModuleData->GetFocusCurrentVoltage());
2174 
2175  UpdatePumpPower(ModuleData);
2176  if (TurnOnPumpSourceAfterTransitioning)
2177  ModuleData->SetPumpLightTurnedOn(true);
2178 
2179  return StateType::SetupTransitionFinished;
2180  }
2181 
2182  StateType WidefieldMicroscope::ReadyStateFunc(DynExp::ModuleInstance& Instance)
2183  {
2184  return StateType::Ready;
2185  }
2186 
2187  StateType WidefieldMicroscope::AutofocusBeginStateFunc(DynExp::ModuleInstance& Instance)
2188  {
2189  auto ModuleData = DynExp::dynamic_ModuleData_cast<WidefieldMicroscope>(Instance.ModuleDataGetter());
2190 
2191  // This is required here since AutoMeasureSampleStepStateFunc() uses the autofocusing states to switch to the
2192  // widefield mode - even if the FocusAdjustment feature is not set.
2193  if (!ModuleData->TestFeature(WidefieldMicroscopeData::FeatureType::FocusAdjustment))
2194  return StateType::AutofocusFinished;
2195 
2196  if (ModuleData->GetWidefieldCamera()->CanSetExposureTime())
2197  ModuleData->GetWidefieldCamera()->SetExposureTimeSync(ModuleData->GetLEDCameraExposureTime());
2198 
2199  if (ModuleData->TestFeature(WidefieldMicroscopeData::FeatureType::LEDLightToggle))
2200  ModuleData->SetLEDLightTurnedOn(true);
2201  if (ModuleData->TestFeature(WidefieldMicroscopeData::FeatureType::PumpLightToggle))
2202  ModuleData->SetPumpLightTurnedOn(false);
2203 
2204  ModuleData->ResetAutofocusFinished();
2205  ModuleData->GetAcqCommunicator()->PostEvent(*this, ImageViewer::AutofocusEvent{ true });
2206 
2207  return StateType::AutofocusWaiting;
2208  }
2209 
2210  StateType WidefieldMicroscope::AutofocusWaitingStateFunc(DynExp::ModuleInstance& Instance)
2211  {
2212  auto ModuleData = DynExp::dynamic_ModuleData_cast<WidefieldMicroscope>(Instance.ModuleDataGetter());
2213 
2214  // If directly continuing with capturing a LED image in the context of the automatic sample
2215  // characterization, wait for a small amount of time until the focus is set to the correct value.
2216  if (StateMachine.GetContext() == &AutoMeasureSampleContext)
2217  WaitingEndTimePoint = std::chrono::system_clock::now() + std::chrono::seconds(2);
2218 
2219  return ModuleData->IsAutofocusFinished() ? StateType::AutofocusFinished : StateType::AutofocusWaiting;
2220  }
2221 
2222  StateType WidefieldMicroscope::LEDImageAcquisitionBeginStateFunc(DynExp::ModuleInstance& Instance)
2223  {
2224  auto ModuleData = DynExp::dynamic_ModuleData_cast<WidefieldMicroscope>(Instance.ModuleDataGetter());
2225 
2226  if (ModuleData->GetWidefieldCamera()->CanSetExposureTime())
2227  ModuleData->GetWidefieldCamera()->SetExposureTimeSync(ModuleData->GetLEDCameraExposureTime());
2228 
2229  if (ModuleData->TestFeature(WidefieldMicroscopeData::FeatureType::LEDLightToggle))
2230  ModuleData->SetLEDLightTurnedOn(true);
2231  if (ModuleData->TestFeature(WidefieldMicroscopeData::FeatureType::PumpLightToggle))
2232  ModuleData->SetPumpLightTurnedOn(false);
2233 
2234  // Always pretend to be in widefield mode if capturing a LED image.
2235  SetFocus(ModuleData, ModuleData->GetFocusCurrentVoltage(), true);
2236 
2237  PrepareImageRecording(ModuleData);
2238 
2239  return StateType::WaitingForLEDImageReadyToCapture;
2240  }
2241 
2242  StateType WidefieldMicroscope::WidefieldImageAcquisitionBeginStateFunc(DynExp::ModuleInstance& Instance)
2243  {
2244  auto ModuleData = DynExp::dynamic_ModuleData_cast<WidefieldMicroscope>(Instance.ModuleDataGetter());
2245 
2246  if (ModuleData->GetWidefieldCamera()->CanSetExposureTime())
2247  ModuleData->GetWidefieldCamera()->SetExposureTimeSync(ModuleData->GetWidefieldCameraExposureTime());
2248 
2249  if (ModuleData->TestFeature(WidefieldMicroscopeData::FeatureType::LEDLightToggle))
2250  ModuleData->SetLEDLightTurnedOn(false);
2251  if (ModuleData->TestFeature(WidefieldMicroscopeData::FeatureType::PumpLightToggle))
2252  ModuleData->SetPumpLightTurnedOn(true);
2253 
2254  PrepareImageRecording(ModuleData);
2255 
2256  return StateType::WaitingForWidefieldImageReadyToCapture;
2257  }
2258 
2259  StateType WidefieldMicroscope::WaitingForImageReadyToCaptureStateFunc(DynExp::ModuleInstance& Instance)
2260  {
2261  auto ModuleData = DynExp::dynamic_ModuleData_cast<WidefieldMicroscope>(Instance.ModuleDataGetter());
2262 
2263  if (ModuleData->TestFeature(WidefieldMicroscopeData::FeatureType::InterModuleCommunicator) && !ImageCapturingPaused)
2264  return StateMachine.GetCurrentState()->GetState();
2265 
2266  RecordImage(ModuleData);
2267 
2268  return StateMachine.GetCurrentState()->GetState() == StateType::WaitingForLEDImageReadyToCapture ?
2269  StateType::WaitingForLEDImage : StateType::WaitingForWidefieldImage;
2270  }
2271 
2272  StateType WidefieldMicroscope::WaitingForImageStateFunc(DynExp::ModuleInstance& Instance)
2273  {
2274  auto ModuleData = DynExp::dynamic_ModuleData_cast<WidefieldMicroscope>(Instance.ModuleDataGetter());
2275  auto CameraData = DynExp::dynamic_InstrumentData_cast<DynExpInstr::Camera>(ModuleData->GetWidefieldCamera()->GetInstrumentData());
2276 
2277  if (CameraData->IsImageAvailbale())
2278  {
2279  if (ModuleData->TestFeature(WidefieldMicroscopeData::FeatureType::LEDLightToggle))
2280  ModuleData->SetLEDLightTurnedOn(false);
2281  if (ModuleData->TestFeature(WidefieldMicroscopeData::FeatureType::PumpLightToggle))
2282  ModuleData->SetPumpLightTurnedOn(false);
2283 
2284  // Reset focus (refer to WidefieldMicroscope::LEDImageAcquisitionBeginStateFunc()).
2285  SetFocus(ModuleData, ModuleData->GetFocusCurrentVoltage());
2286 
2287  ModuleData->SetCurrentImage(CameraData->GetImage());
2288 
2289  if (StateMachine.GetCurrentState()->GetState() == StateType::WaitingForWidefieldImage)
2290  ModuleData->SetWidefieldPosition(ModuleData->GetSamplePosition());
2291 
2292  if (ModuleData->TestFeature(WidefieldMicroscopeData::FeatureType::InterModuleCommunicator))
2293  ModuleData->GetAcqCommunicator()->PostEvent(*this, ImageViewer::ResumeImageCapturingEvent{});
2294 
2295  return StateMachine.GetCurrentState()->GetState() == StateType::WaitingForLEDImage ?
2296  StateType::WaitingForLEDImageFinished : StateType::WaitingForWidefieldImageFinished;
2297  }
2298 
2299  return StateMachine.GetCurrentState()->GetState();
2300  }
2301 
2302  StateType WidefieldMicroscope::WaitingForWidefieldCellIDStateFunc(DynExp::ModuleInstance& Instance)
2303  {
2304  static constexpr const char* ReadCellIDErrorMsg = "Reading cell ID from current image failed. See log for further information.";
2305 
2306  if (*WidefieldCellIDState == WidefieldImageProcessingStateType::Waiting)
2307  return StateType::WaitingForWidefieldCellID;
2308 
2309  auto ModuleParams = DynExp::dynamic_Params_cast<WidefieldMicroscope>(Instance.ParamsGetter());
2310  auto ModuleData = DynExp::dynamic_ModuleData_cast<WidefieldMicroscope>(Instance.ModuleDataGetter());
2311 
2312  if (*WidefieldCellIDState == WidefieldImageProcessingStateType::Finished)
2313  {
2314  auto WidefieldLocalizerData = DynExp::dynamic_InstrumentData_cast<DynExpInstr::WidefieldLocalization>(ModuleData->GetWidefieldLocalizer()->GetInstrumentData());
2315  ModuleData->SetCellID(WidefieldLocalizerData->GetCellID());
2316 
2317  if (WidefieldLocalizerData->GetCellID().HasCellShift())
2318  {
2319  MoveSampleTo(ModuleData->GetSamplePosition() +
2320  PositionPointFromPixelDist(ModuleParams, ModuleData, WidefieldLocalizerData->GetCellID().CellShift_px_x, WidefieldLocalizerData->GetCellID().CellShift_px_y),
2321  ModuleData);
2322 
2323  return StateType::WidefieldCellWaitUntilCentered;
2324  }
2325  }
2326  else
2327  {
2328  ModuleData->ResetCellID();
2329 
2330  if (LogUIMessagesOnly)
2331  Util::EventLogger().Log(ReadCellIDErrorMsg, Util::ErrorType::Error);
2332  else
2333  ModuleData->SetUIMessage(ReadCellIDErrorMsg);
2334  }
2335 
2336  return StateType::WidefieldCellIDReadFinished;
2337  }
2338 
2339  StateType WidefieldMicroscope::WidefieldCellWaitUntilCenteredStateFunc(DynExp::ModuleInstance& Instance)
2340  {
2341  auto ModuleData = DynExp::dynamic_ModuleData_cast<WidefieldMicroscope>(Instance.ModuleDataGetter());
2342  if (IsSampleMoving(ModuleData))
2343  return StateType::WidefieldCellWaitUntilCentered;
2344 
2345  if (IsCharacterizingSample())
2346  {
2347  StateMachine.SetContext(&AutoMeasureSampleRecenterCellContext);
2348 
2349  // Record new, now centered LED image.
2350  return StateType::LEDImageAcquisitionBegin;
2351  }
2352 
2353  return StateType::WidefieldCellIDReadFinished;
2354  }
2355 
2356  StateType WidefieldMicroscope::WaitingForWidefieldLocalizationStateFunc(DynExp::ModuleInstance& Instance)
2357  {
2358  static constexpr const char* LocalizationFailedErrorMsg = "Localization of emitters in widefield image failed. See log for further information.";
2359 
2360  if (*WidefieldLocalizationState == WidefieldImageProcessingStateType::Waiting)
2361  return StateType::WaitingForWidefieldLocalization;
2362 
2363  auto ModuleData = DynExp::dynamic_ModuleData_cast<WidefieldMicroscope>(Instance.ModuleDataGetter());
2364 
2365  if (*WidefieldLocalizationState == WidefieldImageProcessingStateType::Finished)
2366  {
2367  auto WidefieldLocalizerData = DynExp::dynamic_InstrumentData_cast<DynExpInstr::WidefieldLocalization>(ModuleData->GetWidefieldLocalizer()->GetInstrumentData());
2368  auto& LocalizedPositionsRaw = WidefieldLocalizerData->GetLocalizedPositions();
2369 
2371  for (const auto& Position : LocalizedPositionsRaw)
2372  LocalizedPositions[Util::NumToT<WidefieldMicroscopeData::LocalizedPositionsMapType::key_type>(Position.first)] = { Position.second };
2373 
2374  ModuleData->SetLocalizedPositions(std::move(LocalizedPositions));
2375  }
2376  else
2377  {
2378  ModuleData->ClearLocalizedPositions();
2379 
2380  if (LogUIMessagesOnly)
2381  Util::EventLogger().Log(LocalizationFailedErrorMsg, Util::ErrorType::Error);
2382  else
2383  ModuleData->SetUIMessage(LocalizationFailedErrorMsg);
2384  }
2385 
2386  return StateType::WidefieldLocalizationFinished;
2387  }
2388 
2389  StateType WidefieldMicroscope::FindingConfocalSpotBeginStateFunc(DynExp::ModuleInstance& Instance)
2390  {
2391  auto ModuleData = DynExp::dynamic_ModuleData_cast<WidefieldMicroscope>(Instance.ModuleDataGetter());
2392 
2393  // If other modules reading the camera's images are running, stop capturing, so that those modules do not take
2394  // away a single frame which is to be processed here.
2395  ModuleData->GetWidefieldCamera()->StopCapturing();
2396 
2397  if (ModuleData->GetWidefieldCamera()->CanSetExposureTime())
2398  ModuleData->GetWidefieldCamera()->SetExposureTimeSync(ModuleData->GetWidefieldCameraExposureTime());
2399 
2400  ModuleData->SetSetupMode(WidefieldMicroscopeData::SetupModeType::Confocal);
2401 
2402  StateMachine.SetContext(&FindingConfocalSpotBeginContext);
2403  return StateType::SetupTransitionBegin;
2404  }
2405 
2406  StateType WidefieldMicroscope::FindingConfocalSpotAfterTransitioningToConfocalModeStateFunc(DynExp::ModuleInstance& Instance)
2407  {
2408  auto ModuleData = DynExp::dynamic_ModuleData_cast<WidefieldMicroscope>(Instance.ModuleDataGetter());
2409 
2410  if (ModuleData->TestFeature(WidefieldMicroscopeData::FeatureType::LEDLightToggle))
2411  ModuleData->SetLEDLightTurnedOn(false);
2412  if (ModuleData->TestFeature(WidefieldMicroscopeData::FeatureType::PumpLightToggle))
2413  ModuleData->SetPumpLightTurnedOn(true);
2414 
2415  PrepareImageRecording(ModuleData);
2416 
2417  StateMachine.SetContext(&FindingConfocalSpotRecordingWidefieldImageContext);
2418  return StateType::WaitingForWidefieldImageReadyToCapture;
2419  }
2420 
2421  StateType WidefieldMicroscope::FindingConfocalSpotAfterRecordingWidefieldImageStateFunc(DynExp::ModuleInstance& Instance)
2422  {
2423  auto ModuleData = DynExp::dynamic_ModuleData_cast<WidefieldMicroscope>(Instance.ModuleDataGetter());
2424 
2425  if (ModuleData->TestFeature(WidefieldMicroscopeData::FeatureType::PumpLightToggle))
2426  ModuleData->SetPumpLightTurnedOn(false);
2427 
2428  auto IntensityImage = ModuleData->GetCurrentImage().convertToFormat(QImage::Format_Grayscale8);
2429  const unsigned char* DataPtr = IntensityImage.constBits();
2430 
2431  QPoint MaxCoord(0, 0);
2432  unsigned char MaxValue = 0;
2433  for (int y = 0; y < IntensityImage.width(); ++y)
2434  for (int x = 0; x < IntensityImage.height(); ++x)
2435  if (*DataPtr++ > MaxValue)
2436  {
2437  MaxCoord = { x, y };
2438  MaxValue = *(DataPtr - 1);
2439  }
2440 
2441  ModuleData->SetConfocalSpotImagePosition(MaxCoord);
2442  ModuleData->SetSetupMode(WidefieldMicroscopeData::SetupModeType::Widefield);
2443 
2444  return StateType::SetupTransitionBegin;
2445  }
2446 
2447  StateType WidefieldMicroscope::ConfocalScanStepStateFunc(DynExp::ModuleInstance& Instance)
2448  {
2449  if (ConfocalScanPositions.empty())
2450  return StateType::Ready;
2451 
2452  const auto& Position = ConfocalScanPositions.front();
2453 
2454  {
2455  auto ModuleData = DynExp::dynamic_ModuleData_cast<WidefieldMicroscope>(Instance.ModuleDataGetter());
2456  ModuleData->GetSampleStageX()->UpdateData();
2457  ModuleData->GetSampleStageY()->UpdateData();
2458  MoveSampleTo(Position, ModuleData);
2459  } // ModuleData unlocked here.
2460 
2461  return StateType::ConfocalScanWaitUntilMoved;
2462  }
2463 
2464  StateType WidefieldMicroscope::ConfocalScanWaitUntilMovedStateFunc(DynExp::ModuleInstance& Instance)
2465  {
2466  auto ModuleData = DynExp::dynamic_ModuleData_cast<WidefieldMicroscope>(Instance.ModuleDataGetter());
2467  if (IsSampleMoving(ModuleData))
2468  return StateType::ConfocalScanWaitUntilMoved;
2469 
2470  auto MeasuredPos = ModuleData->GetSamplePosition();
2471  ConfocalScanPositions.front().MeasuredX = MeasuredPos.x;
2472  ConfocalScanPositions.front().MeasuredY = MeasuredPos.y;
2473 
2474  return StateType::ConfocalScanCapture;
2475  }
2476 
2477  StateType WidefieldMicroscope::ConfocalScanCaptureStateFunc(DynExp::ModuleInstance& Instance)
2478  {
2479  auto ModuleData = DynExp::dynamic_ModuleData_cast<WidefieldMicroscope>(Instance.ModuleDataGetter());
2480 
2481  ModuleData->ResetSPD1State();
2482  ModuleData->ResetSPD2State();
2483 
2484  {
2485  auto SPD1Data = DynExp::dynamic_InstrumentData_cast<DynExpInstr::TimeTagger>(ModuleData->GetSPD1()->GetInstrumentData());
2486  ModuleData->SetSPD1SamplesWritten(SPD1Data->GetCastSampleStream<DynExpInstr::TimeTaggerData::SampleStreamType>()->GetNumSamplesWritten());
2487  } // SPD1Data unlocked here.
2488  ModuleData->GetSPD1()->ReadData();
2489 
2490  if (ModuleData->TestFeature(WidefieldMicroscopeData::FeatureType::HBT))
2491  {
2492  {
2493  auto SPD2Data = DynExp::dynamic_InstrumentData_cast<DynExpInstr::TimeTagger>(ModuleData->GetSPD2()->GetInstrumentData());
2494  ModuleData->SetSPD2SamplesWritten(SPD2Data->GetCastSampleStream<DynExpInstr::TimeTaggerData::SampleStreamType>()->GetNumSamplesWritten());
2495  } // SPD2Data unlocked here.
2496  ModuleData->GetSPD2()->ReadData();
2497  }
2498 
2499  return StateType::ConfocalScanWaitUntilCaptured;
2500  }
2501 
2502  // Skips first sample to be sure that the sample read has entirely been captured at the most recent sample stages' positions.
2503  StateType WidefieldMicroscope::ConfocalScanWaitUntilCapturedStateFunc(DynExp::ModuleInstance& Instance)
2504  {
2505  auto ModuleData = DynExp::dynamic_ModuleData_cast<WidefieldMicroscope>(Instance.ModuleDataGetter());
2506  bool UsingSPD2 = ModuleData->TestFeature(WidefieldMicroscopeData::FeatureType::HBT);
2507 
2508  {
2509  auto SPD1Data = DynExp::dynamic_InstrumentData_cast<DynExpInstr::TimeTagger>(ModuleData->GetSPD1()->GetInstrumentData());
2510  auto SPD1DataSampleStream = SPD1Data->GetCastSampleStream<DynExpInstr::TimeTaggerData::SampleStreamType>();
2511  if (SPD1DataSampleStream->GetNumSamplesWritten() >= ModuleData->GetSPD1SamplesWritten() + 2)
2512  ModuleData->SetSPD1Ready(SPD1DataSampleStream->ReadSample().Value);
2513  } // SPD1Data unlocked here.
2514  ModuleData->GetSPD1()->ReadData();
2515 
2516  if (UsingSPD2)
2517  {
2518  {
2519  auto SPD2Data = DynExp::dynamic_InstrumentData_cast<DynExpInstr::TimeTagger>(ModuleData->GetSPD2()->GetInstrumentData());
2520  auto SPD2DataSampleStream = SPD2Data->GetCastSampleStream<DynExpInstr::TimeTaggerData::SampleStreamType>();
2521  if (SPD2DataSampleStream->GetNumSamplesWritten() >= ModuleData->GetSPD2SamplesWritten() + 2)
2522  ModuleData->SetSPD2Ready(SPD2DataSampleStream->ReadSample().Value);
2523  } // SPD2Data unlocked here.
2524  ModuleData->GetSPD2()->ReadData();
2525  }
2526 
2527  if (ModuleData->GetSPD1Ready() && (!UsingSPD2 || ModuleData->GetSPD2Ready()))
2528  {
2529  auto ExposureTime = ModuleData->GetSPDExposureTime().count();
2530  double CountRate = (ModuleData->GetSPD1Value() + ModuleData->GetSPD2Value())
2531  / ExposureTime * WidefieldMicroscope::ModuleDataType::SPDTimeType::period::den;
2532 
2533  if (StateMachine.GetContext() != &ConfocalOptimizationContext &&
2534  StateMachine.GetContext() != &AutoMeasureCharacterizationContext &&
2535  StateMachine.GetContext() != &AutoMeasureCharacterizationOptimizationContext &&
2536  StateMachine.GetContext() != &AutoMeasureCharacterizationSpectrumContext &&
2537  StateMachine.GetContext() != &AutoMeasureCharacterizationHBTContext &&
2538  !IsCharacterizingSample())
2539  ModuleData->GetConfocalScanResults().emplace_back(ConfocalScanPositions.front(), CountRate);
2540  ModuleData->SetLastCountRate(CountRate);
2541 
2542  ConfocalScanPositions.pop_front();
2543 
2544  return StateType::ConfocalScanStep;
2545  }
2546 
2547  return StateType::ConfocalScanWaitUntilCaptured;
2548  }
2549 
2550  StateType WidefieldMicroscope::ConfocalOptimizationInitStateFunc(DynExp::ModuleInstance& Instance)
2551  {
2552  ConfocalOptimizationInitPromises();
2553 
2554  ConfocalOptimizationThreadReturnFuture = std::async(std::launch::async, &WidefieldMicroscope::ConfocalOptimizationThread, this);
2555 
2556  return StateType::ConfocalOptimizationWait;
2557  }
2558 
2559  StateType WidefieldMicroscope::ConfocalOptimizationInitSubStepStateFunc(DynExp::ModuleInstance& Instance)
2560  {
2561  ConfocalOptimizationInitPromises();
2562 
2563  return StateType::ConfocalOptimizationWait;
2564  }
2565 
2566  StateType WidefieldMicroscope::ConfocalOptimizationWaitStateFunc(DynExp::ModuleInstance& Instance)
2567  {
2568  // New sample available?
2569  if (ConfocalOptimizationStateFuture.wait_for(std::chrono::microseconds(0)) == std::future_status::ready)
2570  {
2571  const auto State = ConfocalOptimizationStateFuture.get();
2572 
2573  auto ModuleData = DynExp::dynamic_ModuleData_cast<WidefieldMicroscope>(Instance.ModuleDataGetter());
2574 
2575  SetFocus(ModuleData, State.Z);
2576  ConfocalScanPositions.clear();
2577  ConfocalScanPositions.emplace_back(State.X, State.Y);
2578 
2579  // StateType::DummyState is replaced by context.
2580  return StateType::DummyState;
2581  }
2582 
2583  // Optimizer iteration finished?
2584  if (ConfocalOptimizationThreadReturnFuture.wait_for(std::chrono::microseconds(0)) == std::future_status::ready)
2585  return StateType::ConfocalOptimizationStep;
2586  else
2587  return StateType::ConfocalOptimizationWait;
2588  }
2589 
2590  StateType WidefieldMicroscope::ConfocalOptimizationStepStateFunc(DynExp::ModuleInstance& Instance)
2591  {
2592  static constexpr const char* OptimizationMaxIterReachedErrorMsg = "Optimizing confocal count rate failed - maximal number of iterations reached!";
2593  static constexpr const char* OptimizationFailedErrorMsg = "Optimizing confocal count rate failed!";
2594 
2595  {
2596  auto ModuleData = DynExp::dynamic_ModuleData_cast<WidefieldMicroscope>(Instance.ModuleDataGetter());
2597 
2598  ConfocalOptimizationPromisesRenewed = false;
2599 
2600  // Negative value to find maximum instead of minimum.
2601  ConfocalOptimizationFeedbackPromise.set_value(-ModuleData->GetLastCountRate());
2602  } // ModuleData unlocked here.
2603 
2604  // Optimizer iteration finished? Next iteration...
2605  if (ConfocalOptimizationThreadReturnFuture.wait_for(std::chrono::microseconds(0)) == std::future_status::ready)
2606  {
2607  auto Result = ConfocalOptimizationThreadReturnFuture.get();
2608 
2609  if (++ConfocalOptimizationNumStepsPerformed > 100)
2610  {
2611  auto ModuleData = DynExp::dynamic_ModuleData_cast<WidefieldMicroscope>(Instance.ModuleDataGetter());
2612  if (LogUIMessagesOnly)
2613  Util::EventLogger().Log(OptimizationMaxIterReachedErrorMsg, Util::ErrorType::Error);
2614  else
2615  ModuleData->SetUIMessage(OptimizationMaxIterReachedErrorMsg);
2616  }
2617 
2618  if (Result == ConfocalOptimizationThreadReturnType::NextStep)
2619  return StateType::ConfocalOptimizationInit;
2620  if (Result == ConfocalOptimizationThreadReturnType::Failed)
2621  {
2622  auto ModuleData = DynExp::dynamic_ModuleData_cast<WidefieldMicroscope>(Instance.ModuleDataGetter());
2623  if (LogUIMessagesOnly)
2624  Util::EventLogger().Log(OptimizationFailedErrorMsg, Util::ErrorType::Error);
2625  else
2626  ModuleData->SetUIMessage(OptimizationFailedErrorMsg);
2627  }
2628 
2629  return StateType::ConfocalOptimizationFinished;
2630  }
2631 
2632  // Iteration not finished. Prepare for next sample within the same iteration.
2633  return StateType::ConfocalOptimizationInitSubStep;
2634  }
2635 
2636  StateType WidefieldMicroscope::HBTAcquiringStateFunc(DynExp::ModuleInstance& Instance)
2637  {
2638  auto ModuleData = DynExp::dynamic_ModuleData_cast<WidefieldMicroscope>(Instance.ModuleDataGetter());
2639  auto SPD1Data = DynExp::dynamic_InstrumentData_cast<DynExpInstr::TimeTagger>(ModuleData->GetSPD1()->GetInstrumentData());
2640 
2641  // If the number of already enqueued tasks is not checked and if the SPD's
2642  // read data task is slow, the queue might grow large.
2643  if (SPD1Data->GetNumEnqueuedTasks() < 10)
2644  ModuleData->GetSPD1()->ReadData();
2645 
2646  ModuleData->SetHBTTotalIntegrationTime(SPD1Data->GetHBTResults().IntegrationTime);
2647  ModuleData->SetHBTNumEventCounts(SPD1Data->GetHBTResults().EventCounts);
2648 
2649  double XMin(std::numeric_limits<double>::max()), XMax(std::numeric_limits<double>::lowest());
2650  double YMin(std::numeric_limits<double>::max()), YMax(std::numeric_limits<double>::lowest());
2651  ModuleData->GetHBTDataPoints().clear();
2652  for (const auto& ResultItem : SPD1Data->GetHBTResults().ResultVector)
2653  {
2654  auto X = ResultItem.Time * std::pico::den;
2655  auto Y = ResultItem.Value;
2656  ModuleData->GetHBTDataPoints().append(QPointF(X, Y));
2657 
2658  XMin = std::min(XMin, X);
2659  XMax = std::max(XMax, X);
2660  YMin = std::min(YMin, Y);
2661  YMax = std::max(YMax, Y);
2662  ModuleData->SetHBTDataPointsMaxValues({ XMax, YMax });
2663  ModuleData->SetHBTDataPointsMinValues({ XMin, YMin });
2664  }
2665 
2666  if (ModuleData->GetHBTMaxIntegrationTime() > std::chrono::microseconds(0) && ModuleData->GetHBTTotalIntegrationTime() >= ModuleData->GetHBTMaxIntegrationTime())
2667  {
2668  StopHBT(ModuleData);
2669 
2670  return StateType::HBTFinished;
2671  }
2672  else
2673  return StateType::HBTAcquiring;
2674  }
2675 
2676  StateType WidefieldMicroscope::WaitingStateFunc(DynExp::ModuleInstance& Instance)
2677  {
2678  return std::chrono::system_clock::now() >= WaitingEndTimePoint ? StateType::WaitingFinished : StateType::Waiting;
2679  }
2680 
2681  StateType WidefieldMicroscope::SpectrumAcquisitionWaitingStateFunc(DynExp::ModuleInstance& Instance)
2682  {
2683  // Nothing to do here. We await SpectrumFinishedRecordingEvent.
2684  return StateType::SpectrumAcquisitionWaiting;
2685  }
2686 
2687  StateType WidefieldMicroscope::AutoMeasureLocalizationStepStateFunc(DynExp::ModuleInstance& Instance)
2688  {
2689  auto ModuleData = DynExp::dynamic_ModuleData_cast<WidefieldMicroscope>(Instance.ModuleDataGetter());
2690 
2691  if (ModuleData->IncrementAutoMeasureCurrentImageSet() >= ModuleData->GetAutoMeasureNumberImageSets())
2692  return StateType::AutoMeasureLocalizationFinished;
2693 
2694  return StateType::LEDImageAcquisitionBegin;
2695  }
2696 
2697  StateType WidefieldMicroscope::AutoMeasureLocalizationSaveLEDImageStateFunc(DynExp::ModuleInstance& Instance)
2698  {
2699  int Index;
2700  std::filesystem::path Filename;
2701 
2702  {
2703  auto ModuleData = DynExp::dynamic_ModuleData_cast<WidefieldMicroscope>(Instance.ModuleDataGetter());
2704 
2705  Index = ModuleData->GetAutoMeasureCurrentImageSet();
2706  Filename = BuildFilename(ModuleData, "_LED_" + Util::ToStr(Index) + ".png");
2707  } // ModuleData unlocked here.
2708 
2709  OnSaveCurrentImage(&Instance, QString::fromUtf16(Filename.u16string().c_str()));
2710 
2711  return StateType::WidefieldImageAcquisitionBegin;
2712  }
2713 
2714  StateType WidefieldMicroscope::AutoMeasureLocalizationSaveWidefieldImageStateFunc(DynExp::ModuleInstance& Instance)
2715  {
2716  int Index, ImagePositionScatterRadius;
2717  std::filesystem::path Filename;
2718 
2719  {
2720  auto ModuleData = DynExp::dynamic_ModuleData_cast<WidefieldMicroscope>(Instance.ModuleDataGetter());
2721 
2722  Index = ModuleData->GetAutoMeasureCurrentImageSet();
2723  ImagePositionScatterRadius = ModuleData->GetAutoMeasureImagePositionScatterRadius();
2724  Filename = BuildFilename(ModuleData, "_WF_" + Util::ToStr(Index) + ".png");
2725  } // ModuleData unlocked here.
2726 
2727  OnSaveCurrentImage(&Instance, QString::fromUtf16(Filename.u16string().c_str()));
2728 
2729  // Move to next image capturing position.
2730  if (ImagePositionScatterRadius > 0)
2731  {
2732  auto ModuleData = DynExp::dynamic_ModuleData_cast<WidefieldMicroscope>(Instance.ModuleDataGetter());
2733 
2734  // Record first and last image sets at the cell's center position.
2735  // Subtract 2 since index of current image set starts at 0 and this function runs before
2736  // advancing to the next image set whose position is determined here.
2737  if (ModuleData->GetAutoMeasureNumberImageSets() > 2 &&
2738  ModuleData->GetAutoMeasureCurrentImageSet() != ModuleData->GetAutoMeasureNumberImageSets() - 2)
2739  MoveSampleTo(ModuleData->GetAutoMeasureCurrentCellPosition() + RandomPointInCircle(ImagePositionScatterRadius), ModuleData);
2740  else
2741  MoveSampleTo(ModuleData->GetAutoMeasureCurrentCellPosition(), ModuleData);
2742 
2743  return StateType::AutoMeasureLocalizationMoving;
2744  }
2745  else
2746  return StateType::AutoMeasureLocalizationStep;
2747  }
2748 
2749  StateType WidefieldMicroscope::AutoMeasureLocalizationMovingStateFunc(DynExp::ModuleInstance& Instance)
2750  {
2751  auto ModuleData = DynExp::dynamic_ModuleData_cast<WidefieldMicroscope>(Instance.ModuleDataGetter());
2752 
2753  if (IsSampleMoving(ModuleData))
2754  return StateType::AutoMeasureLocalizationMoving;
2755 
2756  return StateType::AutoMeasureLocalizationStep;
2757  }
2758 
2759  StateType WidefieldMicroscope::AutoMeasureCharacterizationStepStateFunc(DynExp::ModuleInstance& Instance)
2760  {
2761  auto ModuleParams = DynExp::dynamic_Params_cast<WidefieldMicroscope>(Instance.ParamsGetter());
2762  auto ModuleData = DynExp::dynamic_ModuleData_cast<WidefieldMicroscope>(Instance.ModuleDataGetter());
2763 
2764  // Save the emitter list after characterizing each emitter.
2765  std::stringstream CSVData;
2766  CSVData = ModuleData->AssembleCSVHeader(false, false, true);
2767  CSVData << "ID;X(px);Y(px);State\n";
2768 
2769  auto& Positions = ModuleData->GetLocalizedPositions();
2770  for (const auto& Position : Positions)
2771  CSVData << Position.first << ";" << Position.second.Position.x() << ";" << Position.second.Position.y() << ";"
2772  << WidefieldMicroscopeData::GetLocalizedEmitterStateString(Position.second.State) << "\n";
2773 
2774  if (!Util::SaveToFile(QString::fromUtf16(BuildFilename(ModuleData, "_Emitters.csv").u16string().c_str()), CSVData.str()))
2775  Util::EventLogger().Log("Saving the emitter list failed.", Util::ErrorType::Error);
2776 
2777  if (ModuleData->GetAutoMeasureCurrentEmitter() == ModuleData->GetLocalizedPositions().cend())
2778  {
2779  if (ModuleData->TestFeature(WidefieldMicroscopeData::FeatureType::PumpLightToggle))
2780  ModuleData->SetPumpLightTurnedOn(false);
2781 
2782  ModuleData->SetAutoMeasureRunning(false);
2783 
2784  return StateType::AutoMeasureCharacterizationFinished;
2785  }
2786 
2787  if (ModuleData->TestFeature(WidefieldMicroscopeData::FeatureType::LEDLightToggle))
2788  ModuleData->SetLEDLightTurnedOn(false);
2789  if (ModuleData->TestFeature(WidefieldMicroscopeData::FeatureType::PumpLightToggle))
2790  ModuleData->SetPumpLightTurnedOn(true);
2791 
2792  ModuleData->GetAutoMeasureCurrentEmitter()->second.State = WidefieldMicroscopeData::LocalizedEmitterStateType::Characterizing;
2793  ModuleData->SetLocalizedPositionsStateChanged();
2794  BringMarkerToConfocalSpot(ModuleParams, ModuleData, ModuleData->GetAutoMeasureCurrentEmitter()->second.Position,
2795  { static_cast<qreal>(ModuleData->GetWidefieldPosition().x), static_cast<qreal>(ModuleData->GetWidefieldPosition().y) });
2796 
2797  ModuleData->ResetAutoMeasureCurrentOptimizationAttempt();
2798 
2799  return StateType::AutoMeasureCharacterizationGotoEmitter;
2800  }
2801 
2802  StateType WidefieldMicroscope::AutoMeasureCharacterizationGotoEmitterStateFunc(DynExp::ModuleInstance& Instance)
2803  {
2804  auto ModuleParams = DynExp::dynamic_Params_cast<WidefieldMicroscope>(Instance.ParamsGetter());
2805  auto ModuleData = DynExp::dynamic_ModuleData_cast<WidefieldMicroscope>(Instance.ModuleDataGetter());
2806 
2807  if (IsSampleMoving(ModuleData))
2808  return StateType::AutoMeasureCharacterizationGotoEmitter;
2809 
2810  if (ModuleData->GetAutoMeasureOptimizeEnabled() && ModuleData->TestFeature(WidefieldMicroscopeData::FeatureType::ConfocalOptimization) &&
2811  ModuleData->GetSetupMode() == WidefieldMicroscopeData::SetupModeType::Confocal)
2812  {
2813  ModuleData->ResetAutoMeasureCurrentOptimizationRerun();
2814  InitializeConfocalOptimizer(ModuleData);
2815 
2816  if (ModuleData->TestFeature(WidefieldMicroscopeData::FeatureType::HBTSwitch))
2817  {
2818  SetHBTSwitch(ModuleParams, ModuleData, true);
2819 
2820  WaitingEndTimePoint = std::chrono::system_clock::now() + std::chrono::milliseconds(ModuleParams->WidefieldHBTTransitionTime);
2821 
2822  StateMachine.SetContext(IsCharacterizingSample() ? &AutoMeasureSampleCharacterizationOptimizationContext : &AutoMeasureCharacterizationOptimizationContext);
2823  return StateType::Waiting;
2824  }
2825  else
2826  return StateType::ConfocalOptimizationInit;
2827  }
2828  else
2829  return StateType::AutoMeasureCharacterizationOptimizationFinished;
2830  }
2831 
2832  StateType WidefieldMicroscope::AutoMeasureCharacterizationOptimizationFinishedStateFunc(DynExp::ModuleInstance& Instance)
2833  {
2834  auto ModuleParams = DynExp::dynamic_Params_cast<WidefieldMicroscope>(Instance.ParamsGetter());
2835  auto ModuleData = DynExp::dynamic_ModuleData_cast<WidefieldMicroscope>(Instance.ModuleDataGetter());
2836 
2837  const auto EmitterDestiny = CalcMarkerToConfocalSpotDestiny(ModuleParams, ModuleData, ModuleData->GetAutoMeasureCurrentEmitter()->second.Position,
2838  { static_cast<qreal>(ModuleData->GetWidefieldPosition().x), static_cast<qreal>(ModuleData->GetWidefieldPosition().y) });
2839 
2840  if (ModuleData->GetLastCountRate() >= ModuleData->GetAutoMeasureCountRateThreshold() &&
2841  EmitterDestiny.DistTo(ModuleData->GetSamplePosition()) <= ModuleData->GetAutoMeasureOptimizationMaxDistance())
2842  {
2843  // Optimization succeeded.
2844  if (ModuleData->GetAutoMeasureSpectrumEnabled() && ModuleData->TestFeature(WidefieldMicroscopeData::FeatureType::InterModuleCommunicator))
2845  {
2846  if (ModuleData->TestFeature(WidefieldMicroscopeData::FeatureType::HBTSwitch))
2847  {
2848  SetHBTSwitch(ModuleParams, ModuleData, false);
2849 
2850  WaitingEndTimePoint = std::chrono::system_clock::now() + std::chrono::milliseconds(ModuleParams->WidefieldHBTTransitionTime);
2851 
2852  StateMachine.SetContext(IsCharacterizingSample() ? &AutoMeasureSampleCharacterizationSpectrumContext : &AutoMeasureCharacterizationSpectrumContext);
2853  return StateType::Waiting;
2854  }
2855  else
2856  return StateType::AutoMeasureCharacterizationSpectrumBegin;
2857  }
2858  else
2859  return StateType::AutoMeasureCharacterizationSpectrumFinished;
2860  }
2861 
2862  if (ModuleData->GetAutoMeasureOptimizeEnabled() && ModuleData->TestFeature(WidefieldMicroscopeData::FeatureType::ConfocalOptimization) &&
2863  ModuleData->GetSetupMode() == WidefieldMicroscopeData::SetupModeType::Confocal)
2864  {
2865  if (ModuleData->IncrementAutoMeasureCurrentOptimizationRerun() >= ModuleData->GetAutoMeasureMaxOptimizationReruns())
2866  {
2867  if (ModuleData->IncrementAutoMeasureCurrentOptimizationAttempt() <= ModuleData->GetAutoMeasureNumOptimizationAttempts())
2868  {
2869  BringMarkerToConfocalSpot(ModuleParams, ModuleData, ModuleData->GetAutoMeasureCurrentEmitter()->second.Position,
2870  { static_cast<qreal>(ModuleData->GetWidefieldPosition().x), static_cast<qreal>(ModuleData->GetWidefieldPosition().y) });
2871 
2872  return StateType::AutoMeasureCharacterizationGotoEmitter;
2873  }
2874  }
2875  else
2876  {
2877  InitializeConfocalOptimizer(ModuleData);
2878 
2879  return StateType::ConfocalOptimizationInit;
2880  }
2881  }
2882 
2883  ModuleData->GetAutoMeasureCurrentEmitter()->second.State = WidefieldMicroscopeData::LocalizedEmitterStateType::Failed;
2884  ModuleData->SetLocalizedPositionsStateChanged();
2885 
2886  ModuleData->IncrementAutoMeasureCurrentEmitter();
2887  return StateType::AutoMeasureCharacterizationStep;
2888  }
2889 
2890  StateType WidefieldMicroscope::AutoMeasureCharacterizationSpectrumBeginStateFunc(DynExp::ModuleInstance& Instance)
2891  {
2892  auto ModuleData = DynExp::dynamic_ModuleData_cast<WidefieldMicroscope>(Instance.ModuleDataGetter());
2893 
2894  ModuleData->GetAcqCommunicator()->PostEvent(*this, SpectrumViewer::RecordSpectrumEvent {
2895  BuildFilename(ModuleData, "_Emitter" + Util::ToStr(ModuleData->GetAutoMeasureCurrentEmitter()->first) + "_Spectrum.csv").string() });
2896 
2897  return StateType::SpectrumAcquisitionWaiting;
2898  }
2899 
2900  StateType WidefieldMicroscope::AutoMeasureCharacterizationSpectrumFinishedStateFunc(DynExp::ModuleInstance& Instance)
2901  {
2902  auto ModuleParams = DynExp::dynamic_Params_cast<WidefieldMicroscope>(Instance.ParamsGetter());
2903  auto ModuleData = DynExp::dynamic_ModuleData_cast<WidefieldMicroscope>(Instance.ModuleDataGetter());
2904 
2905  if (ModuleData->GetAutoMeasureHBTEnabled() && ModuleData->TestFeature(WidefieldMicroscopeData::FeatureType::HBT))
2906  {
2907  if (ModuleData->TestFeature(WidefieldMicroscopeData::FeatureType::HBTSwitch))
2908  {
2909  SetHBTSwitch(ModuleParams, ModuleData, true);
2910 
2911  WaitingEndTimePoint = std::chrono::system_clock::now() + std::chrono::milliseconds(ModuleParams->WidefieldHBTTransitionTime);
2912 
2913  StateMachine.SetContext(IsCharacterizingSample() ? &AutoMeasureSampleCharacterizationHBTContext : &AutoMeasureCharacterizationHBTContext);
2914  return StateType::Waiting;
2915  }
2916  else
2917  return StateType::AutoMeasureCharacterizationHBTBegin;
2918  }
2919 
2920  ModuleData->GetAutoMeasureCurrentEmitter()->second.State = WidefieldMicroscopeData::LocalizedEmitterStateType::Finished;
2921  ModuleData->SetLocalizedPositionsStateChanged();
2922 
2923  ModuleData->IncrementAutoMeasureCurrentEmitter();
2924  return StateType::AutoMeasureCharacterizationStep;
2925  }
2926 
2927  StateType WidefieldMicroscope::AutoMeasureCharacterizationHBTBeginStateFunc(DynExp::ModuleInstance& Instance)
2928  {
2929  auto ModuleData = DynExp::dynamic_ModuleData_cast<WidefieldMicroscope>(Instance.ModuleDataGetter());
2930 
2931  InitializeHBT(ModuleData);
2932 
2933  return StateType::AutoMeasureCharacterizationHBTWaitForInit;
2934  }
2935 
2936  StateType WidefieldMicroscope::AutoMeasureCharacterizationHBTWaitForInitStateFunc(DynExp::ModuleInstance& Instance)
2937  {
2938  auto ModuleData = DynExp::dynamic_ModuleData_cast<WidefieldMicroscope>(Instance.ModuleDataGetter());
2939  auto SPD1Data = DynExp::dynamic_InstrumentData_cast<DynExpInstr::TimeTagger>(ModuleData->GetSPD1()->GetInstrumentData());
2940 
2941  // If the number of already enqueued tasks is not checked and if the SPD's
2942  // read data task is slow, the queue might grow large.
2943  if (SPD1Data->GetNumEnqueuedTasks() < 10)
2944  ModuleData->GetSPD1()->ReadData();
2945 
2946  ModuleData->SetHBTTotalIntegrationTime(SPD1Data->GetHBTResults().IntegrationTime);
2947 
2948  if (HBTIntegrationTimeBeforeReset <= std::chrono::milliseconds(10) || ModuleData->GetHBTTotalIntegrationTime() < HBTIntegrationTimeBeforeReset)
2949  return StateType::HBTAcquiring;
2950 
2951  return StateType::AutoMeasureCharacterizationHBTWaitForInit;
2952  }
2953 
2954  StateType WidefieldMicroscope::AutoMeasureCharacterizationHBTFinishedStateFunc(DynExp::ModuleInstance& Instance)
2955  {
2956  auto ModuleData = DynExp::dynamic_ModuleData_cast<WidefieldMicroscope>(Instance.ModuleDataGetter());
2957 
2958  auto Filename = BuildFilename(ModuleData, "_Emitter" + Util::ToStr(ModuleData->GetAutoMeasureCurrentEmitter()->first) + "_g2.csv");
2959  std::stringstream CSVData;
2960 
2961  CSVData = ModuleData->AssembleCSVHeader(false, true, false);
2962  ModuleData->WriteHBTResults(CSVData);
2963 
2964  ModuleData->GetAutoMeasureCurrentEmitter()->second.State = WidefieldMicroscopeData::LocalizedEmitterStateType::Finished;
2965  ModuleData->SetLocalizedPositionsStateChanged();
2966 
2967  if (!Util::SaveToFile(QString::fromUtf16(Filename.u16string().c_str()), CSVData.str()))
2968  Util::EventLogger().Log("Saving the g2 result failed.", Util::ErrorType::Error);
2969 
2970  ModuleData->IncrementAutoMeasureCurrentEmitter();
2971  return StateType::AutoMeasureCharacterizationStep;
2972  }
2973 
2974  StateType WidefieldMicroscope::AutoMeasureSampleStepStateFunc(DynExp::ModuleInstance& Instance)
2975  {
2976  auto ModuleData = DynExp::dynamic_ModuleData_cast<WidefieldMicroscope>(Instance.ModuleDataGetter());
2977 
2978  if (IsSampleMoving(ModuleData))
2979  return StateType::AutoMeasureSampleStep;
2980 
2981  // AutofocusBeginStateFunc() checks whether the FeatureType::FocusAdjustment feature is set.
2982  return StartAutofocus(ModuleData);
2983  }
2984 
2985  StateType WidefieldMicroscope::AutoMeasureSampleReadCellIDStateFunc(DynExp::ModuleInstance& Instance)
2986  {
2987  auto ModuleData = DynExp::dynamic_ModuleData_cast<WidefieldMicroscope>(Instance.ModuleDataGetter());
2988 
2989  return InitiateReadCellIDFromImage(ModuleData);
2990  }
2991 
2992  StateType WidefieldMicroscope::AutoMeasureSampleReadCellIDFinishedStateFunc(DynExp::ModuleInstance& Instance)
2993  {
2994  auto ModuleData = DynExp::dynamic_ModuleData_cast<WidefieldMicroscope>(Instance.ModuleDataGetter());
2995 
2996  // It was not possible to extract the cell ID from the image, so just increment the previous id
2997  // (hoping that we are still at the right place on the sample).
2998  if (!ModuleData->GetCellID().Valid)
2999  {
3000  ModuleData->SetCellIDToLastCellID();
3001  ModuleData->IncrementCellID();
3002 
3003  Util::EventLogger().Log("Reading a cell ID failed. Estimating it to " +
3004  ModuleData->GetCellID().IDString + ".", Util::ErrorType::Warning);
3005  }
3006 
3007  // Cannot continue if current cell's ID does not comply with certain criteria.
3008  // In that case, we wouldn't know where we are on the sample. Then, better abort the
3009  // measurement instead of damaging anything by moving the sample around blindly.
3010  if (Util::NumToT<int>(ModuleData->GetCellID().X_id) < ModuleData->GetAutoMeasureCellRangeFrom().x() ||
3011  Util::NumToT<int>(ModuleData->GetCellID().Y_id) < ModuleData->GetAutoMeasureCellRangeFrom().y() ||
3012  Util::NumToT<int>(ModuleData->GetCellID().X_id) > ModuleData->GetAutoMeasureCellRangeTo().x() ||
3013  Util::NumToT<int>(ModuleData->GetCellID().Y_id) > ModuleData->GetAutoMeasureCellRangeTo().y())
3014  {
3015  ModuleData->SetUIMessage("The current cell's ID is outside the specified cell range. Probably moved in wrong direction? Characterizing the sample cannot continue.");
3016 
3017  return ResetState(ModuleData);
3018  }
3019 
3020  if (ModuleData->GetLastCellID().Valid && ModuleData->GetLastCellID() >= ModuleData->GetCellID())
3021  {
3022  ModuleData->SetUIMessage("The current cell's ID is not larger than the previous cell's ID. Probably moved in wrong direction? Characterizing the sample cannot continue.");
3023 
3024  return ResetState(ModuleData);
3025  }
3026 
3027  if (ModuleData->GetAutoMeasureLocalizationType() == WidefieldMicroscopeWidget::LocalizationType::LocalizeEmittersFromImage)
3028  return StartAutoMeasureLocalization(ModuleData);
3029  else
3030  return InitiateLocalizationFromImage(ModuleData);
3031  }
3032 
3033  StateType WidefieldMicroscope::AutoMeasureSampleLocalizeStateFunc(DynExp::ModuleInstance& Instance)
3034  {
3035  auto ModuleData = DynExp::dynamic_ModuleData_cast<WidefieldMicroscope>(Instance.ModuleDataGetter());
3036 
3037  // Do not record LED/Widefield images in case no emitters could be recalled from cell.
3038  if (ModuleData->GetLocalizedPositions().empty())
3039  {
3040  // This is required since the position is not updated because image recording is skipped.
3041  // Though, AutoMeasureSampleAdvanceCellStateFunc() expects the widefield position to be
3042  // set to the current sample position. So, set the position here manually.
3043  ModuleData->SetWidefieldPosition(ModuleData->GetSamplePosition());
3044 
3045  return StateType::AutoMeasureSampleAdvanceCell;
3046  }
3047 
3048  return StartAutoMeasureLocalization(ModuleData);
3049  }
3050 
3051  StateType WidefieldMicroscope::AutoMeasureSampleFindEmittersStateFunc(DynExp::ModuleInstance& Instance)
3052  {
3053  auto ModuleData = DynExp::dynamic_ModuleData_cast<WidefieldMicroscope>(Instance.ModuleDataGetter());
3054 
3055  if (ModuleData->TestFeature(WidefieldMicroscopeData::FeatureType::InterModuleCommunicator))
3056  ModuleData->GetAcqCommunicator()->PostEvent(*this, SpectrumViewer::SetSilentModeEvent{ false });
3057 
3058  if (ModuleData->GetAutoMeasureLocalizationType() == WidefieldMicroscopeWidget::LocalizationType::LocalizeEmittersFromImage)
3059  return InitiateLocalizationFromImage(ModuleData);
3060  else
3061  return StateType::WidefieldLocalizationFinished;
3062  }
3063 
3064  StateType WidefieldMicroscope::AutoMeasureSampleCharacterizeStateFunc(DynExp::ModuleInstance& Instance)
3065  {
3066  auto ModuleData = DynExp::dynamic_ModuleData_cast<WidefieldMicroscope>(Instance.ModuleDataGetter());
3067 
3068  return StartAutoMeasureCharacterization(ModuleData);
3069  }
3070 
3081  StateType WidefieldMicroscope::AutoMeasureSampleAdvanceCellStateFunc(DynExp::ModuleInstance& Instance)
3082  {
3083  auto ModuleData = DynExp::dynamic_ModuleData_cast<WidefieldMicroscope>(Instance.ModuleDataGetter());
3084 
3085  if (ModuleData->GetWidefieldPosition().IsEmpty())
3086  {
3087  ModuleData->SetUIMessage("The current widefield image's position is invalid. Characterizing the sample cannot continue.");
3088 
3089  return ResetState(ModuleData);
3090  }
3091 
3092  // Has finished?
3093  if (Util::NumToT<int>(ModuleData->GetCellID().X_id) == ModuleData->GetAutoMeasureCellRangeTo().x() &&
3094  Util::NumToT<int>(ModuleData->GetCellID().Y_id) == ModuleData->GetAutoMeasureCellRangeTo().y())
3095  return StateType::AutoMeasureSampleFinished;
3096 
3097  // Not finished yet, so advance to next cell.
3098  if (Util::NumToT<int>(ModuleData->GetCellID().X_id) == ModuleData->GetAutoMeasureCellRangeTo().x())
3099  MoveSampleTo({
3100  ModuleData->GetWidefieldPosition().x - Util::NumToT<WidefieldMicroscopeData::PositionType>(ModuleData->GetAutoMeasureCellSkip().x()) * (ModuleData->GetAutoMeasureCellLineLength() - 1),
3101  ModuleData->GetWidefieldPosition().y + Util::NumToT<WidefieldMicroscopeData::PositionType>(ModuleData->GetAutoMeasureCellSkip().y())
3102  }, ModuleData);
3103  else
3104  MoveSampleTo({
3105  ModuleData->GetWidefieldPosition().x + Util::NumToT<WidefieldMicroscopeData::PositionType>(ModuleData->GetAutoMeasureCellSkip().x()),
3106  ModuleData->GetWidefieldPosition().y
3107  }, ModuleData);
3108 
3109  return StartAutoMeasureSampleCharacterization(ModuleData);
3110  }
3111 }
Implementation of a module to control a combined widefield and confocal microscope.
Implements a circular data stream based on Util::circularbuf using samples of type BasicSample.
virtual size_t GetNumSamplesWritten() const noexcept override
Determines the number of samples which have been written to the stream in total. Before overflowing,...
PositionPoint SampleHomePosition
Location set by the user as a home position in nm.
DynExpInstr::WidefieldLocalizationCellIDType LastCellID
DynExp::LinkedObjectWrapperContainer< DynExpInstr::DigitalOut > LEDSwitch
static QColor GetLocalizedEmitterColor(LocalizedEmitterStateType State)
void WriteConfocalScanResults(std::stringstream &Stream) const
WidefieldMicroscopeWidget::LocalizationType AutoMeasureLocalizationType
PositionPoint WidefieldPosition
Location where the current widefield image has been taken in nm.
LocalizedPositionsMapType::iterator AutoMeasureCurrentEmitter
Iterator to the emitter being characterized.
DynExpInstr::WidefieldLocalizationCellIDType CurrentCellID
bool SetAutoMeasureFirstEmitter(Util::MarkerGraphicsView::MarkerType::IDType FirstEmitterID) noexcept
Returns true in case of success, false otherwise.
LocalizedPositionsMapType::iterator AutoMeasureFirstEmitter
Iterator to the first emitter to be characterized.
PositionPoint GetSamplePosition() const
Returns current sample position.
QPoint ConfocalSpotImagePosition
Location of confocal spot in units of px within widefield image.
DynExpInstr::CameraData::TimeType CameraTimeType
DynExpInstr::PositionerStageData::PositionType PositionType
DynExp::LinkedObjectWrapperContainer< DynExpInstr::DigitalOut > PumpSwitch
std::vector< std::unique_ptr< QSurfaceDataRow > > QSurfaceDataRowsType
PositionPoint AutoMeasureCurrentCellPosition
Center position of the current cell in nm where an automated measurement takes place.
void ResetImpl(dispatch_tag< QModuleDataBase >) override final
void WriteHBTResults(std::stringstream &Stream) const
void SetLocalizedPositions(LocalizedPositionsMapType &&Positions)
static const char * GetLocalizedEmitterStateString(LocalizedEmitterStateType State)
std::map< Util::MarkerGraphicsView::MarkerType::IDType, LocalizedEmitterType > LocalizedPositionsMapType
void AppendLocalizedPosition(LocalizedPositionsMapType::value_type &&Position)
PositionPoint HBTSamplePosition
Location in nm where the HBT measurement has been started.
int AutoMeasureCurrentImageSet
Index of the image set being recorded if auto-measure localization is running, -1 otherwise.
bool TestFeature(const std::array< FeatureType, N > &Flags) const
std::stringstream AssembleCSVHeader(bool IncludeConfocalScan, bool IncludeHBT, bool IncludeAutoMeasure) const
void OnCaptureWidefieldImage(DynExp::ModuleInstance *Instance, bool) const
void OnConfocalSPDExposureTimeChanged(DynExp::ModuleInstance *Instance, int Value) const
const Util::StateMachineContext< StateMachineStateType > AutoMeasureSampleCharacterizationContext
void OnAutofocus(DynExp::ModuleInstance *Instance, bool) const
void OnOptimizePositions(DynExp::ModuleInstance *Instance, bool) const
void OnAutoMeasureCellRangeFromXChanged(DynExp::ModuleInstance *Instance, int Value) const
std::chrono::microseconds HBTIntegrationTimeBeforeReset
const Util::StateMachineContext< StateMachineStateType > AutoMeasureSampleContext
void OnRunCharacterizationFromID(DynExp::ModuleInstance *Instance, Util::MarkerGraphicsView::MarkerType::IDType ID) const
const Util::StateMachineContext< StateMachineStateType > AutoMeasureSampleLocalizationContext
void OnHBTBinWidthChanged(DynExp::ModuleInstance *Instance, int Value) const
void OnGoToHomePosition(DynExp::ModuleInstance *Instance, bool) const
void OnAutoMeasureMaxOptimizationRerunsChanged(DynExp::ModuleInstance *Instance, int Value) const
void OnConfocalConfocalWidthChanged(DynExp::ModuleInstance *Instance, int Value) const
StateType InitiateReadCellIDFromImage(Util::SynchronizedPointer< ModuleDataType > &ModuleData) const
void MoveSampleTo(const ModuleDataType::PositionPoint &Point, Util::SynchronizedPointer< ModuleDataType > &ModuleData) const
static ModuleDataType::PositionPoint PositionPointFromPixelDist(Util::SynchronizedPointer< const ParamsType > &ModuleParams, Util::SynchronizedPointer< ModuleDataType > &ModuleData, const PosT x, const PosT y)
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...
bool IsCharacterizingSample() const noexcept
Returns true if an entire sample (multiple cells) are processed, false if only a single cell is proce...
const Util::StateMachineContext< StateMachineStateType > AutoMeasureSampleRecenterCellContext
void OnConfocalConfocalDistPerPixelChanged(DynExp::ModuleInstance *Instance, int Value) const
void OnAutoMeasureNumberImageSetsChanged(DynExp::ModuleInstance *Instance, int Value) const
const std::shared_ptr< AtomicWidefieldImageProcessingStateType > WidefieldCellIDState
void OnAutoMeasureCountRateThresholdChanged(DynExp::ModuleInstance *Instance, int Value) const
void OnWidefieldLEDExposureTimeChanged(DynExp::ModuleInstance *Instance, int Value) const
void OnGeneralConfocalPowerChanged(DynExp::ModuleInstance *Instance, double Value) const
void OnAutoMeasureOptimizationMaxDistanceChanged(DynExp::ModuleInstance *Instance, int Value) const
void OnToggleAutoMeasureSpectrumEnabled(DynExp::ModuleInstance *Instance, int State) const
WidefieldMicroscope(const std::thread::id OwnerThreadID, DynExp::ParamsBasePtrType &&Params)
const std::shared_ptr< AtomicPositionerStateType > ConfocalScanPositionerStateY
void OnConfocalOptimizationInitZStepSizeChanged(DynExp::ModuleInstance *Instance, double Value) const
ModuleDataType::PositionPoint CalcMarkerToConfocalSpotDestiny(Util::SynchronizedPointer< const ParamsType > &ModuleParams, Util::SynchronizedPointer< ModuleDataType > &ModuleData, QPoint MarkerPos, QPointF SamplePos) const
void OnConfocalOptimizationInitXYStepSizeChanged(DynExp::ModuleInstance *Instance, double Value) const
void OnGeneralFocusConfocalOffsetVoltageChanged(DynExp::ModuleInstance *Instance, double Value) const
void OnGoToSamplePos(DynExp::ModuleInstance *Instance, QPointF SamplePos) const
void OnAutoMeasureCellRangeToXChanged(DynExp::ModuleInstance *Instance, int Value) const
void OnResetCellID(DynExp::ModuleInstance *Instance, bool) const
const std::shared_ptr< AtomicWidefieldImageProcessingStateType > WidefieldLocalizationState
void OnSaveCurrentImage(DynExp::ModuleInstance *Instance, QString Filename) const
void OnAutoMeasureImagePositionScatterRadius(DynExp::ModuleInstance *Instance, int Value) const
void UpdateUIChild(const ModuleBase::ModuleDataGetterType &ModuleDataGetter) override final
void OnCaptureLEDImage(DynExp::ModuleInstance *Instance, bool) const
void OnToggleAutoMeasureHBTEnabled(DynExp::ModuleInstance *Instance, int State) const
void OnConfocalConfocalHeightChanged(DynExp::ModuleInstance *Instance, int Value) const
void OnAutoMeasureSavePathChanged(DynExp::ModuleInstance *Instance, QString Path) const
const Util::StateMachineContext< StateMachineStateType > AutoMeasureSampleCharacterizationHBTContext
gsl_multimin_fminimizer *const GSLConfocalOptimizationState
void OnWidefieldLocalizeEmitters(DynExp::ModuleInstance *Instance, bool) const
void OnConfocalOptimizationToleranceChanged(DynExp::ModuleInstance *Instance, double Value) const
void OnToggleAutoMeasureOptimizeEnabled(DynExp::ModuleInstance *Instance, int State) const
void OnHHBTMaxIntegrationTimeChanged(DynExp::ModuleInstance *Instance, double Value) const
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 OnPerformConfocalScan(DynExp::ModuleInstance *Instance, bool) const
const std::shared_ptr< AtomicPositionerStateType > ConfocalScanPositionerStateX
void OnTogglePumpLightSource(DynExp::ModuleInstance *Instance, bool State) const
void OnWidefieldApplyPumpExposureTime(DynExp::ModuleInstance *Instance, bool) const
void RecordImage(Util::SynchronizedPointer< ModuleDataType > &ModuleData) const
void ConfocalSurfaceSelectedPointChanged(DynExp::ModuleInstance *Instance, QPoint Position) const
const std::shared_ptr< AtomicPositionerStateType > ConfocalScanPositionerStateZ
void OnWidefieldApplyLEDExposureTime(DynExp::ModuleInstance *Instance, bool) const
bool IsSampleMoving(Util::SynchronizedPointer< ModuleDataType > &ModuleData) const
Checks whether the sample is moving in x- or y-direction. The z-direction is ignored currently since ...
void OnAutoMeasureInitialImageSetWaitTimeChanged(DynExp::ModuleInstance *Instance, int Value) const
void OnToggleHBTMirror(DynExp::ModuleInstance *Instance, bool Checked) const
void OnAutoMeasureRunLocalization(DynExp::ModuleInstance *Instance, bool) const
std::atomic< PositionerStateType > AtomicPositionerStateType
void OnHBTBinCountChanged(DynExp::ModuleInstance *Instance, int Value) const
void OnGeneralFocusZeroVoltageChanged(DynExp::ModuleInstance *Instance, double Value) const
Util::StateMachine< StateMachineStateType > StateMachine
void OnAutoMeasureLocalizationTypeChanged(DynExp::ModuleInstance *Instance, int Value) const
void OnWidefieldReadCellID(DynExp::ModuleInstance *Instance, bool) const
StateType ResetState(Util::SynchronizedPointer< ModuleDataType > &ModuleData) const
Aborts a measurement or experimental sequence and continues with the ready state.
void OnSetupModeChanged(DynExp::ModuleInstance *Instance, QAction *Action) const
void OnAutoMeasureCellSkipYChanged(DynExp::ModuleInstance *Instance, int Value) const
const Util::StateMachineContext< StateMachineStateType > AutoMeasureSampleCharacterizationSpectrumContext
void OnTerminate(DynExp::ModuleInstance *Instance, bool) const
void OnAutoMeasureRunCharacterization(DynExp::ModuleInstance *Instance, bool) const
void OnWidefieldAnalyzeImageDistortion(DynExp::ModuleInstance *Instance, bool) const
void OnSetHomePosition(DynExp::ModuleInstance *Instance, bool) const
void UpdatePumpPower(Util::SynchronizedPointer< ModuleDataType > &ModuleData) const
void OnAutoMeasureCellRangeToYChanged(DynExp::ModuleInstance *Instance, int Value) const
StateType StartAutoMeasureCharacterization(Util::SynchronizedPointer< ModuleDataType > &ModuleData, Util::MarkerGraphicsView::MarkerType::IDType FirstEmitterID=-1) const
std::atomic< WidefieldImageProcessingStateType > AtomicWidefieldImageProcessingStateType
void OnMeasureHBT(DynExp::ModuleInstance *Instance, bool) const
void ResetImpl(dispatch_tag< QModuleBase >) override final
std::list< WidefieldMicroscopeData::PositionPoint > ConfocalScanPositions
void OnGeneralSetZeroFocus(DynExp::ModuleInstance *Instance, bool) const
void OnWidefieldPumpExposureTimeChanged(DynExp::ModuleInstance *Instance, int Value) const
void OnGeneralWidefieldPowerChanged(DynExp::ModuleInstance *Instance, double Value) const
void OnAutoMeasureCellRangeFromYChanged(DynExp::ModuleInstance *Instance, int Value) const
void PrepareImageRecording(Util::SynchronizedPointer< ModuleDataType > &ModuleData) const
void OnToggleLEDLightSource(DynExp::ModuleInstance *Instance, bool State) const
void OnStopAction(DynExp::ModuleInstance *Instance, bool) const
ModuleDataType::QSurfaceDataRowsType CalculateConfocalScanPositions(const int Width, const int Height, const int DistPerPixel, const WidefieldMicroscopeData::PositionPoint CenterPosition) const
void OnBringMarkerToConfocalSpot(DynExp::ModuleInstance *Instance, QPoint MarkerPos, QPointF SamplePos) const
std::chrono::milliseconds GetMainLoopDelay() const override final
Specifies in which time intervals the module's event queue runs to handle pending events.
void OnWidefieldImageClicked(DynExp::ModuleInstance *Instance, QPoint Position) const
void OnAutoMeasureNumOptimizationAttemptsChanged(DynExp::ModuleInstance *Instance, int Value) const
const Util::StateMachineContext< StateMachineStateType > AutoMeasureSampleCharacterizationOptimizationContext
void OnGeneralApplyZeroFocus(DynExp::ModuleInstance *Instance, bool) const
void BringMarkerToConfocalSpot(Util::SynchronizedPointer< const ParamsType > &ModuleParams, Util::SynchronizedPointer< ModuleDataType > &ModuleData, QPoint MarkerPos, QPointF SamplePos) const
void OnAutoMeasureCellSkipXChanged(DynExp::ModuleInstance *Instance, int Value) const
void OnAutoMeasureRunSampleCharacterization(DynExp::ModuleInstance *Instance, bool) const
void OnGeneralFocusCurrentVoltageChanged(DynExp::ModuleInstance *Instance, double Value) const
void OnWidefieldFindConfocalSpot(DynExp::ModuleInstance *Instance, bool) const
Wrapper holding a pointer to an exception and providing functionality for accessing it....
Definition: Instrument.h:86
void ClearError()
Removes the stored exception. If this method is called by a task's CallbackFunc in case of an excepti...
Definition: Instrument.h:117
static void Register(const ModuleBase &Listener, CallableT EventFunc)
Registers/Subscribes module Listener to the event with the event function EventFunc....
Definition: Module.h:1028
static void Deregister(const ModuleBase &Listener)
Deregisters/unsubscribes module Listener from the event. Indirectly calls ModuleBase::RemoveRegistere...
Definition: Module.h:1034
ModuleDataTypeSyncPtrType GetModuleData(const std::chrono::milliseconds Timeout=GetModuleDataTimeoutDefault)
Locks the mutex of the module data class instance ModuleData assigned to this ModuleBase instance and...
Definition: Module.cpp:202
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
void Exit() noexcept
Might be called from anywhere where this ModuleInstance instance is accessible to make the associated...
Definition: Module.h:813
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
void SetFocus() noexcept
Focuses/activates Widget and moves it on top of other windows if possible. Does nothing if any of Wid...
Definition: Module.cpp:678
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
Base class for all tasks being processed by instruments. The class must not contain public virtual fu...
Definition: Instrument.h:892
Logs events like errors and writes them immediately to a HTML file in a human-readable format....
Definition: Util.h:1061
void Log(const std::string &Message, const ErrorType Type=ErrorType::Info, const size_t Line=0, const std::string &Function="", const std::string &File="", const int ErrorCode=0, const std::stacktrace &Trace={}) noexcept
Logs an event from information specified manually.
Definition: Util.cpp:309
Data to operate on is invalid for a specific purpose. This indicates a corrupted data structure or fu...
Definition: Exception.h:163
void mouseClickEvent(QPoint Position)
Thrown when some operation or feature is temporarily or permanently not available.
Definition: Exception.h:286
Denotes that e.g. a remote gRPC service failed.
Definition: Exception.h:357
Pointer to lock a class derived from ISynchronizedPointerLockable for synchronizing between threads....
Definition: Util.h:170
auto get() const noexcept
Returns the managed (locked) object.
Definition: Util.h:241
Thrown when an operation timed out before it could be completed, especially used for locking shared d...
Definition: Exception.h:261
@ Y
Y component of the signal in cartesian coordinates.
@ X
X component of the signal in cartesian coordinates.
WidefieldMicroscopeData::PositionPoint operator-(const WidefieldMicroscopeData::PositionPoint &lhs, const WidefieldMicroscopeData::PositionPoint &rhs)
WidefieldMicroscopeData::PositionPoint operator+(const WidefieldMicroscopeData::PositionPoint &lhs, const WidefieldMicroscopeData::PositionPoint &rhs)
const QColor blue(42, 130, 218)
constexpr auto Ready
std::unique_ptr< ParamsBase > ParamsBasePtrType
Alias for a pointer to the parameter system base class ParamsBase.
Definition: Object.h:1807
DynExpErrorCodes
DynExp's error codes
Definition: Exception.h:22
std::string ToStr(const T &Value, int Precision=-1)
Converts a (numeric) value of type T to a std::string using operator<< of std::stringstream.
Definition: Util.h:625
bool SaveToFile(const QString &Filename, std::string_view Text)
Saves a std::string_view to a file (using QFile). Creates a new file or truncates an existing file's ...
Definition: QtUtil.cpp:236
EventLogger & EventLog()
This function holds a static EventLogger instance and returns a reference to it. DynExp uses only one...
Definition: Util.cpp:509
std::chrono::duration< double, std::pico > picoseconds
Extends std::chrono by a duration data type for picoseconds.
Definition: Util.h:762
std::chrono::duration< double > seconds
Extends std::chrono by a duration data type for seconds capable of storing fractions of seconds.
Definition: Util.h:761
Accumulates include statements to provide a precompiled header.