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