DynExp
Highly flexible laboratory automation for dynamically changing experiments.
Loading...
Searching...
No Matches
WidefieldMicroscope.cpp
Go to the documentation of this file.
1// This file is part of DynExp.
2
3#include "stdafx.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
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
247
255
257 {
258 return CurrentCellID.Valid ?
260 }
261
266
272
277
282
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
317
319 {
320 Features = {};
322
324 LEDLightTurnedOn = false;
325 PumpLightTurnedOn = false;
326 MinPumpPower = .0;
327 MaxPumpPower = .0;
331 MinFocusVoltage = .0;
332 MaxFocusVoltage = .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
356 SPDExposureTime = std::chrono::milliseconds(100);
361
365 LastCountRate = .0;
366
368 HBTBinCount = 256;
369 HBTMaxIntegrationTime = std::chrono::microseconds(0);
372 HBTTotalIntegrationTime = std::chrono::microseconds(0);
373 HBTDataPoints.clear();
376
377 AutoMeasureRunning = false;
378 AutoMeasureSavePath.clear();
382 AutoMeasureInitialImageSetWaitTime = std::chrono::seconds(30);
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
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
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 {
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
619 { Util::NumToT<WidefieldMicroscopeData::PositionType>(SamplePos.x()), Util::NumToT<WidefieldMicroscopeData::PositionType>(SamplePos.y()) },
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
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
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 {
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 {
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
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
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)
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
Accumulates include statements to provide a precompiled header.