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