DynExp
Highly flexible laboratory automation for dynamically changing experiments.
Loading...
Searching...
No Matches
WidefieldMicroscopeWidget.cpp
Go to the documentation of this file.
1// This file is part of DynExp.
2
3#include "stdafx.h"
5#include "moc_WidefieldMicroscopeWidget.cpp"
6#include "ui_WidefieldMicroscope.h"
8
10{
12 : CurrentState(nullptr), CurrentContext(nullptr),
13 StateLabel(new QLabel(Owner)),
14 CellIDLabel(new QLabel(Owner)), CellIDContextMenu(new QMenu(Owner)),
15 HomePosLabel(new QLabel(Owner)),
16 PumpPowerLabel(new QLabel(Owner)),
17 ImageCoordinatesGroup(new QWidget(Owner)), ImageCoordinatesLayout(new QHBoxLayout),
18 XCoordLabel(new QLabel(Owner)), YCoordLabel(new QLabel(Owner))
19 {
20 CellIDLabel->setContextMenuPolicy(Qt::ContextMenuPolicy::CustomContextMenu);
21 PumpPowerLabel->setMinimumWidth(140);
22 XCoordLabel->setAlignment(Qt::AlignmentFlag::AlignRight);
23 YCoordLabel->setAlignment(Qt::AlignmentFlag::AlignRight);
27 }
28
30 {
31 if (CurrentContext && !std::string(CurrentContext->GetDescription()).empty())
32 StateLabel->setText(QString(" ") + CurrentContext->GetDescription());
33 else
34 StateLabel->setText(CurrentState ? (QString(" ") + CurrentState->GetDescription()) : "< Unknown >");
35
36 if (CurrentState && CurrentState->GetState() != StateType::Ready)
37 StateLabel->setStyleSheet(DynExpUI::StatusBarBusyStyleSheet);
38 else
39 StateLabel->setStyleSheet("");
40 }
41
43 : QModuleWidget(Owner, parent),
44 ui(std::make_unique<Ui::WidefieldMicroscope>()),
45 StatusBar(this),
46 WidefieldConfocalModeActionGroup(new QActionGroup(this)), MainGraphicsView(nullptr),
47 MainGraphicsScene(new QGraphicsScene(this)), CurrentConfocalSpotPosition(0, 0),
48 EmitterListContextMenu(new QMenu(this)), ConfocalMapContextMenu(new QMenu(this)),
49 ConfocalGraph(nullptr), NumItemsInArray(0),
50 ConfocalSurfaceMinCounts(std::numeric_limits<decltype(ConfocalSurfaceMinCounts)>::max()), ConfocalSurfaceMaxCounts(0),
51 HBTGraph(nullptr),
53 {
54 ui->setupUi(this);
55
56 // For shortcuts
57 this->addAction(ui->action_Stop_current_action);
58 this->addAction(ui->action_Optimize_positions);
59 this->addAction(ui->action_Save_Image);
60 this->addAction(ui->action_Save_Image);
61 this->addAction(ui->action_Zoom_in);
62 this->addAction(ui->action_Zoom_out);
63 this->addAction(ui->action_Zoom_reset);
64 this->addAction(ui->action_Zoom_fit);
65 this->addAction(ui->action_EmitterList_Edit_name);
66 this->addAction(ui->action_EmitterList_Remove_entry);
67
68 ui->action_Zoom_fit->setChecked(true);
69
70 // Status bar
71 ui->MainStatusBar->addWidget(StatusBar.StateLabel, 4);
72 ui->MainStatusBar->addWidget(StatusBar.CellIDLabel, 1);
73 ui->MainStatusBar->addWidget(StatusBar.HomePosLabel, 2);
74 ui->MainStatusBar->addWidget(StatusBar.PumpPowerLabel, 1);
75 ui->MainStatusBar->addPermanentWidget(StatusBar.ImageCoordinatesGroup, 2);
76
77 StatusBar.CellIDContextMenu->addAction(ui->action_Reset_CellID);
78 connect(StatusBar.CellIDLabel, &QWidget::customContextMenuRequested, this, &WidefieldMicroscopeWidget::OnCellIDContextMenuRequested);
79
80 // Tool bar
81 WidefieldConfocalModeActionGroup->addAction(ui->action_Widefield_mode);
82 WidefieldConfocalModeActionGroup->addAction(ui->action_Widefield_mode);
83 WidefieldConfocalModeActionGroup->addAction(ui->action_Confocal_mode);
84
85 // Main image
86 MainGraphicsView = new Util::MarkerGraphicsView(ui->MainHSplitter);
87 MainGraphicsView->setObjectName(QString::fromUtf8("MainGraphicsView"));
88 MainGraphicsView->setMinimumSize(QSize(300, 200));
89 ui->MainHSplitter->addWidget(MainGraphicsView);
90
93 MainGraphicsView->setAlignment(Qt::AlignLeft | Qt::AlignTop);
94 MainGraphicsView->viewport()->installEventFilter(this);
95 MainGraphicsView->viewport()->setMouseTracking(true);
96
97 MainGraphicsView->contextMenu()->addSeparator();
98 MainGraphicsView->contextMenu()->addAction(ui->action_Zoom_in);
99 MainGraphicsView->contextMenu()->addAction(ui->action_Zoom_out);
100 MainGraphicsView->contextMenu()->addAction(ui->action_Zoom_reset);
101 MainGraphicsView->contextMenu()->addAction(ui->action_Zoom_fit);
102 MainGraphicsView->contextMenu()->addSeparator();
103 MainGraphicsView->contextMenu()->addAction(ui->action_Save_Image);
104
105 // Emitter list
106 EmitterListContextMenu->addAction(ui->action_EmitterList_Edit_name);
107 EmitterListContextMenu->addAction(ui->action_EmitterList_Remove_entry);
108 EmitterListContextMenu->addSeparator();
109 EmitterListContextMenu->addAction(ui->action_EmitterList_Go_to_sample_position);
110 EmitterListContextMenu->addAction(ui->action_EmitterList_Bring_marker_to_confocal_spot);
111 EmitterListContextMenu->addSeparator();
112 EmitterListContextMenu->addAction(ui->action_EmitterList_Run_characterization_from_ID);
113
114 // Graph to display confocal scans
115 ConfocalMapContextMenu->addAction(ui->action_confocal_map_save_raw_data);
116 ConfocalMapContextMenu->addAction(ui->action_confocal_map_reset);
117 ui->BConfocalGraphTools->setMenu(ConfocalMapContextMenu);
118
119 connect(ui->WidgetConfocalGraph, &QQuickWidget::statusChanged, [this, &Owner](QQuickWidget::Status Status) {
120 if (Status == QQuickWidget::Status::Ready && ui->WidgetConfocalGraph->rootObject())
121 {
122 auto BackendVariant = ui->WidgetConfocalGraph->rootObject()->property("backend");
123 ConfocalGraph = BackendVariant.isValid() ? BackendVariant.value<DynExpQuick::DynExpSurfaceGraphBackend*>() : nullptr;
124
125 if (!ConfocalGraph)
126 return;
127
128 ConfocalGraph->GetXValueAxis()->setLabelFormat("%.0f");
129 ConfocalGraph->GetXValueAxis()->setAutoAdjustRange(true);
130 ConfocalGraph->GetXValueAxis()->setTitle("X in nm");
131 ConfocalGraph->GetXValueAxis()->setTitleVisible(true);
132 ConfocalGraph->GetYValueAxis()->setLabelFormat("%.0f");
133 ConfocalGraph->GetYValueAxis()->setAutoAdjustRange(false);
134 ConfocalGraph->GetYValueAxis()->setTitle("Count rate in Hz");
135 ConfocalGraph->GetYValueAxis()->setTitleVisible(true);
136 ConfocalGraph->GetZValueAxis()->setLabelFormat("%.0f");
137 ConfocalGraph->GetZValueAxis()->setAutoAdjustRange(true);
138 ConfocalGraph->GetZValueAxis()->setTitle("Y in nm");
139 ConfocalGraph->GetZValueAxis()->setTitleVisible(true);
140 ConfocalGraph->UpdateData();
141
142 Owner.RegisterConfocalGraphEvents(ConfocalGraph);
143 connect(ConfocalGraph, &DynExpQuick::DynExpSurfaceGraphBackend::selectedPointChanged, this, [this]() { NumItemsInArray = 0; });
144 }
145 });
146 ui->WidgetConfocalGraph->loadFromModule("Modules.DynExpQuick", "QDynExpSurfaceGraph");
147
148 // Graph to display HBT result
149 connect(ui->WidgetHBTGraph, &QQuickWidget::statusChanged, [this](QQuickWidget::Status Status) {
150 if (Status == QQuickWidget::Status::Ready && ui->WidgetHBTGraph->rootObject())
151 {
152 auto BackendVariant = ui->WidgetHBTGraph->rootObject()->property("backend");
153 HBTGraph = BackendVariant.isValid() ? BackendVariant.value<DynExpQuick::DynExpLineGraphBackend*>() : nullptr;
154
155 if (HBTGraph)
156 HBTGraph->InsertSeries("g2");
157 }
158 });
159 ui->WidgetHBTGraph->loadFromModule("Modules.DynExpQuick", "QDynExpLineGraph");
160 HBTPlotInfo.XUnit = DynExp::Units::UnitType::Time_ps;
161 HBTPlotInfo.YUnit = DynExp::Units::UnitType::Counts;
162 HBTPlotInfo.YLabel = "g(2)";
163
164 // Characterization steps
165 CharacterizationStepsContextMenu->addAction(ui->action_CharacterizationSteps_Widefield_PLE);
166 CharacterizationStepsContextMenu->addAction(ui->action_CharacterizationSteps_Optimize);
167 CharacterizationStepsContextMenu->addAction(ui->action_CharacterizationSteps_Spectrum);
168 CharacterizationStepsContextMenu->addAction(ui->action_CharacterizationSteps_Confocal_PLE);
169 CharacterizationStepsContextMenu->addAction(ui->action_CharacterizationSteps_HBT);
170 connect(CharacterizationStepsContextMenu, &QMenu::aboutToShow, this, &WidefieldMicroscopeWidget::OnCharacterizationStepsContextMenuRequested);
171 ui->BAutoMeasureCharacterizationSteps->setMenu(CharacterizationStepsContextMenu);
172 }
173
174 const WidefieldMicroscope& WidefieldMicroscopeWidget::GetCastOwner() const noexcept
175 {
176 return static_cast<const WidefieldMicroscope&>(GetOwner());
177 }
178
179 void WidefieldMicroscopeWidget::InitializeUI(Util::SynchronizedPointer<WidefieldMicroscopeData>& ModuleData)
180 {
181 if (!GetUIInitialized())
182 {
183 ui->action_Toogle_LED_light_source->setEnabled(ModuleData->TestFeature(WidefieldMicroscopeData::FeatureType::LEDLightToggle));
184 ui->action_Toogle_pump_light_source->setEnabled(ModuleData->TestFeature(WidefieldMicroscopeData::FeatureType::PumpLightToggle));
185 ui->GBGeneralLaserPowers->setEnabled(ModuleData->TestFeature(WidefieldMicroscopeData::FeatureType::SetPumpPower));
186
187 auto WidefieldTabIndex = ui->TabWidget->indexOf(ui->TabWidefield);
188 auto ConfocalTabIndex = ui->TabWidget->indexOf(ui->TabConfocal);
189 auto HBTTabIndex = ui->TabWidget->indexOf(ui->TabHBT);
190 ui->TabWidget->setTabVisible(WidefieldTabIndex, ModuleData->TestFeature(WidefieldMicroscopeData::FeatureType::Widefield));
191 ui->TabWidget->setTabVisible(ConfocalTabIndex, ModuleData->TestFeature(WidefieldMicroscopeData::FeatureType::Confocal));
192 ui->TabWidget->setTabVisible(HBTTabIndex, ModuleData->TestFeature(WidefieldMicroscopeData::FeatureType::HBT));
193
194 ui->SBGeneralWidefieldPower->setMinimum(ModuleData->GetMinPumpPower());
195 ui->SBGeneralWidefieldPower->setMaximum(ModuleData->GetMaxPumpPower());
196 ui->SBGeneralWidefieldPower->setSingleStep(std::abs(ModuleData->GetMaxPumpPower() - ModuleData->GetMinPumpPower()) / 100.0);
197 ui->SBGeneralConfocalPower->setMinimum(ModuleData->GetMinPumpPower());
198 ui->SBGeneralConfocalPower->setMaximum(ModuleData->GetMaxPumpPower());
199 ui->SBGeneralConfocalPower->setSingleStep(std::abs(ModuleData->GetMaxPumpPower() - ModuleData->GetMinPumpPower()) / 100.0);
200 if (ModuleData->TestFeature(WidefieldMicroscopeData::FeatureType::FocusAdjustment))
201 {
202 ui->SBGeneralFocusCurrentVoltage->setMinimum(ModuleData->GetMinFocusVoltage());
203 ui->SBGeneralFocusCurrentVoltage->setMaximum(ModuleData->GetMaxFocusVoltage());
204 ui->SBGeneralFocusCurrentVoltage->setSingleStep(std::abs(ModuleData->GetMaxFocusVoltage() - ModuleData->GetMinFocusVoltage()) / 100.0);
205 ui->SBGeneralFocusZeroVoltage->setMinimum(ModuleData->GetMinFocusVoltage());
206 ui->SBGeneralFocusZeroVoltage->setMaximum(ModuleData->GetMaxFocusVoltage());
207 ui->SBGeneralFocusZeroVoltage->setSingleStep(std::abs(ModuleData->GetMaxFocusVoltage() - ModuleData->GetMinFocusVoltage()) / 100.0);
208 ui->SBGeneralFocusConfocalOffsetVoltage->setMinimum(-std::abs(ModuleData->GetMinFocusVoltage()) - std::abs(ModuleData->GetMaxFocusVoltage()));
209 ui->SBGeneralFocusConfocalOffsetVoltage->setMaximum(std::abs(ModuleData->GetMinFocusVoltage()) + std::abs(ModuleData->GetMaxFocusVoltage()));
210 ui->SBGeneralFocusConfocalOffsetVoltage->setSingleStep(std::abs(ModuleData->GetMaxFocusVoltage() - ModuleData->GetMinFocusVoltage()) / 100.0);
211 }
212 else
213 ui->GBGeneralFocus->setVisible(false);
214 if (!ModuleData->TestFeature(WidefieldMicroscopeData::FeatureType::WidefieldConfocalSwitch))
215 {
216 ui->LGeneralWidefieldPower->setText("Power in any mode");
217 ui->LGeneralConfocalPower->setVisible(false);
218 ui->SBGeneralConfocalPower->setVisible(false);
219 ui->LGeneralFocusConfocalOffsetVoltage->setVisible(false);
220 ui->SBGeneralFocusConfocalOffsetVoltage->setVisible(false);
221 }
222
223 ui->SBWidefieldLEDExposureTime->setMinimum(ModuleData->GetMinCameraExposureTime().count());
224 ui->SBWidefieldLEDExposureTime->setMaximum(ModuleData->GetMaxCameraExposureTime().count());
225 ui->SBWidefieldPumpExposureTime->setMinimum(ModuleData->GetMinCameraExposureTime().count());
226 ui->SBWidefieldPumpExposureTime->setMaximum(ModuleData->GetMaxCameraExposureTime().count());
227
228 ui->TWEmitterList->setColumnWidth(EmitterListColumnType::EmitterName, 96);
229 ui->TWEmitterList->setColumnWidth(EmitterListColumnType::Sample_x, 134);
230 ui->TWEmitterList->setColumnWidth(EmitterListColumnType::Sample_y, 134);
231 ui->TWEmitterList->setColumnWidth(EmitterListColumnType::EmitterState, 134);
232
233 ui->action_CharacterizationSteps_Widefield_PLE->setVisible(ModuleData->TestFeature(WidefieldMicroscopeData::FeatureType::PLEInterModuleCommunicator));
234 ui->action_CharacterizationSteps_Optimize->setVisible(ModuleData->TestFeature(WidefieldMicroscopeData::FeatureType::ConfocalOptimization));
235 ui->action_CharacterizationSteps_Spectrum->setVisible(ModuleData->TestFeature(WidefieldMicroscopeData::FeatureType::SpectrumInterModuleCommunicator));
236 ui->action_CharacterizationSteps_Confocal_PLE->setVisible(ModuleData->TestFeature(WidefieldMicroscopeData::FeatureType::PLEInterModuleCommunicator));
237 ui->action_CharacterizationSteps_HBT->setVisible(ModuleData->TestFeature(WidefieldMicroscopeData::FeatureType::HBT));
238
239 UIInitialized = true;
240 }
241 }
242
243 void WidefieldMicroscopeWidget::SetUIState(const StateMachineStateType* State, const Util::StateMachineContext<StateMachineStateType>* Context,
245 {
246 bool IsReady = State->GetState() == StateType::Ready;
247 StatusBar.CurrentState = State;
248 StatusBar.CurrentContext = Context;
249
250 StatusBar.CellIDLabel->setText(ModuleData->HasCellID() ? QString::fromStdString(ModuleData->GetCellID().IDString) : "< Unknown cell ID. >");
251 StatusBar.CellIDLabel->setToolTip(ModuleData->HasCellID() ?
252 ("(" + QString::number(ModuleData->GetCellID().X_id) + ", " + QString::number(ModuleData->GetCellID().Y_id) + ")") : "n/a");
253
254 QString HomePosString = "home: (" + QString::number(ModuleData->GetSampleHomePosition().x) + " nm, " + QString::number(ModuleData->GetSampleHomePosition().y) + " nm)";
255 StatusBar.HomePosLabel->setText(ModuleData->GetSampleHomePosition().IsEmpty() ? "< No home position set. >" : HomePosString);
256
257 StatusBar.PumpPowerLabel->setText(ModuleData->TestFeature(WidefieldMicroscopeData::FeatureType::MeasurePumpPower) ?
258 (" Pump power: " + QString::number(ModuleData->GetMeasuredPumpPower(), 'f', 2) + " V") : "");
259 if (ModuleData->GetPumpLightTurnedOn())
260 StatusBar.PumpPowerLabel->setStyleSheet(DynExpUI::StatusBarRunningStyleSheet);
261 else
262 StatusBar.PumpPowerLabel->setStyleSheet("");
263
264 MainGraphicsView->EnableActions(IsReady);
265 ui->action_Save_Image->setEnabled(IsReady);
266 ui->action_Stop_current_action->setEnabled(!IsReady);
267 ui->action_Set_home_position->setEnabled(IsReady && ModuleData->TestFeature(WidefieldMicroscopeData::FeatureType::Confocal));
268 ui->action_Go_home_position->setEnabled(IsReady && ModuleData->TestFeature(WidefieldMicroscopeData::FeatureType::Confocal));
269 ui->action_Widefield_mode->setEnabled(IsReady && ModuleData->TestFeature(WidefieldMicroscopeData::FeatureType::WidefieldConfocalSwitch));
270 ui->action_Confocal_mode->setEnabled(IsReady && ModuleData->TestFeature(WidefieldMicroscopeData::FeatureType::WidefieldConfocalSwitch));
271 ui->action_Autofocus->setEnabled(IsReady && ModuleData->TestFeature(WidefieldMicroscopeData::FeatureType::FocusAdjustment));
272 ui->action_Optimize_positions->setEnabled(IsReady && ModuleData->TestFeature(WidefieldMicroscopeData::FeatureType::ConfocalOptimization)
273 && ModuleData->GetSetupMode() == WidefieldMicroscopeData::SetupModeType::Confocal);
274 ui->action_Toggle_HBT_mirror->setEnabled(IsReady && ModuleData->TestFeature(WidefieldMicroscopeData::FeatureType::HBTSwitch));
275 ui->action_Reset_CellID->setEnabled(IsReady);
276 ui->GBGeneralLaserPowers->setEnabled(IsReady && ModuleData->TestFeature(WidefieldMicroscopeData::FeatureType::SetPumpPower));
277 ui->GBGeneralFocus->setEnabled(IsReady && ModuleData->TestFeature(WidefieldMicroscopeData::FeatureType::FocusAdjustment));
278 ui->SBWidefieldLEDExposureTime->setEnabled(IsReady &&
279 ModuleData->TestFeature(WidefieldMicroscopeData::FeatureType::Widefield) && ModuleData->GetWidefieldCamera()->CanSetExposureTime());
280 ui->BWidefieldApplyLEDExposureTime->setEnabled(IsReady &&
281 ModuleData->TestFeature(WidefieldMicroscopeData::FeatureType::Widefield) && ModuleData->GetWidefieldCamera()->CanSetExposureTime());
282 ui->SBWidefieldPumpExposureTime->setEnabled(IsReady &&
283 ModuleData->TestFeature(WidefieldMicroscopeData::FeatureType::Widefield) && ModuleData->GetWidefieldCamera()->CanSetExposureTime());
284 ui->BWidefieldApplyPumpExposureTime->setEnabled(IsReady &&
285 ModuleData->TestFeature(WidefieldMicroscopeData::FeatureType::Widefield) && ModuleData->GetWidefieldCamera()->CanSetExposureTime());
286 ui->BWidefieldFindConfocalSpot->setEnabled(IsReady && ModuleData->TestFeature(WidefieldMicroscopeData::FeatureType::WidefieldConfocalSwitch));
287 ui->BWidefieldLEDCapture->setEnabled(IsReady);
288 ui->BWidefieldCapture->setEnabled(IsReady);
289 ui->BReadCellID->setEnabled(IsReady && ModuleData->TestFeature(WidefieldMicroscopeData::FeatureType::WidefieldLocalization));
290 ui->BAnalyzeImageDistortion->setEnabled(IsReady && ModuleData->TestFeature(WidefieldMicroscopeData::FeatureType::WidefieldLocalization));
291 ui->BLocalizeEmitters->setEnabled(IsReady && ModuleData->TestFeature(WidefieldMicroscopeData::FeatureType::WidefieldLocalization));
292 ui->action_EmitterList_Edit_name->setEnabled(IsReady);
293 ui->action_EmitterList_Remove_entry->setEnabled(IsReady);
294 ui->action_EmitterList_Go_to_sample_position->setEnabled(IsReady);
295 ui->action_EmitterList_Bring_marker_to_confocal_spot->setEnabled(IsReady);
296 ui->action_EmitterList_Run_characterization_from_ID->setEnabled(IsReady);
297 ui->SBConfocalWidth->setEnabled(IsReady);
298 ui->SBConfocalHeight->setEnabled(IsReady);
299 ui->SBConfocalDistPerPixel->setEnabled(IsReady);
300 ui->SBConfocalSPDExposureTime->setEnabled(IsReady);
301 ui->SBConfocalOptimizationInitXYStepSize->setEnabled(IsReady && ModuleData->TestFeature(WidefieldMicroscopeData::FeatureType::ConfocalOptimization));
302 ui->SBConfocalOptimizationInitZStepSize->setEnabled(IsReady && ModuleData->TestFeature(WidefieldMicroscopeData::FeatureType::ConfocalOptimization));
303 ui->SBConfocalOptimizationTolerance->setEnabled(IsReady && ModuleData->TestFeature(WidefieldMicroscopeData::FeatureType::ConfocalOptimization));
304 ui->BConfocalScan->setEnabled(IsReady);
305 ui->action_confocal_map_save_raw_data->setEnabled(IsReady);
306 ui->SBHBTBinWidth->setEnabled(IsReady);
307 ui->SBHBTBinCount->setEnabled(IsReady);
308 ui->BHBTSaveData->setEnabled(IsReady);
309 ui->BHBT->setEnabled(IsReady);
310 ui->GBAutoMeasureGeneralSettings->setEnabled(IsReady);
311 ui->GBAutoMeasureLocalizationSettings->setEnabled(IsReady);
312 ui->GBAutoMeasureCharacterizationSettings->setEnabled(IsReady);
313 ui->GBAutoMeasureCellSettings->setEnabled(IsReady);
314 ui->BAutoMeasureRunLocalization->setEnabled(IsReady && ModuleData->TestFeature(WidefieldMicroscopeData::FeatureType::Widefield));
315 ui->BAutoMeasureRunCharacterization->setEnabled(IsReady);
316 ui->BAutoMeasureRunSampleCharacterization->setEnabled(IsReady && ModuleData->TestFeature(WidefieldMicroscopeData::FeatureType::Widefield) &&
317 ModuleData->TestFeature(WidefieldMicroscopeData::FeatureType::WidefieldLocalization));
318 }
319
320 void WidefieldMicroscopeWidget::UpdateUIData(Util::SynchronizedPointer<WidefieldMicroscopeData>& ModuleData)
321 {
322 // Toolbar
323 ui->action_Toogle_LED_light_source->setChecked(ModuleData->GetLEDLightTurnedOn());
324 ui->action_Toogle_pump_light_source->setChecked(ModuleData->GetPumpLightTurnedOn());
325 ui->action_Widefield_mode->setChecked(ModuleData->GetSetupMode() == WidefieldMicroscopeData::SetupModeType::Widefield);
326 ui->action_Confocal_mode->setChecked(ModuleData->GetSetupMode() == WidefieldMicroscopeData::SetupModeType::Confocal);
327
328 // General
329 // QDoubleSpinBox::setValue() emits QDoubleSpinBox::valueChanged().
330 if (!ui->SBGeneralWidefieldPower->hasFocus())
331 ui->SBGeneralWidefieldPower->setValue(ModuleData->GetWidefieldPumpPower());
332 if (!ui->SBGeneralConfocalPower->hasFocus())
333 ui->SBGeneralConfocalPower->setValue(ModuleData->GetConfocalPumpPower());
334 if (!ui->SBGeneralFocusCurrentVoltage->hasFocus())
335 ui->SBGeneralFocusCurrentVoltage->setValue(ModuleData->GetFocusCurrentVoltage());
336 if (!ui->SBGeneralFocusZeroVoltage->hasFocus())
337 ui->SBGeneralFocusZeroVoltage->setValue(ModuleData->GetFocusZeroVoltage());
338 if (!ui->SBGeneralFocusConfocalOffsetVoltage->hasFocus())
339 ui->SBGeneralFocusConfocalOffsetVoltage->setValue(ModuleData->GetFocusConfocalOffsetVoltage());
340
341 // MainGraphicsView
342 if (ModuleData->TestFeature(WidefieldMicroscopeData::FeatureType::SampleXYPositioning))
343 {
344 auto SamplePosition = ModuleData->GetSamplePosition();
345 MainGraphicsView->SetCurrentImagePos({ static_cast<qreal>(SamplePosition.x), static_cast<qreal>(SamplePosition.y) });
346 }
347 else
348 MainGraphicsView->SetCurrentImagePos({ });
349 }
350
351 void WidefieldMicroscopeWidget::UpdateWidefieldUIData(Util::SynchronizedPointer<WidefieldMicroscopeData>& ModuleData)
352 {
353 if (!ui->SBWidefieldLEDExposureTime->hasFocus())
354 ui->SBWidefieldLEDExposureTime->setValue(ModuleData->GetLEDCameraExposureTime().count());
355
356 if (!ui->SBWidefieldPumpExposureTime->hasFocus())
357 ui->SBWidefieldPumpExposureTime->setValue(ModuleData->GetWidefieldCameraExposureTime().count());
358
359 if (ModuleData->IsCurrentImageAvlbl())
360 {
361 // SetMainGraphicsImage creates a deep copy of the current image.
362 SetMainGraphicsImage(ModuleData->GetCurrentImage());
363 ModuleData->ResetCurrentImageAvlbl();
364 }
365
366 if (!SaveWidefieldImageFilename.isEmpty())
367 {
368 ModuleData->EnqueueEvent(DynExp::MakeEvent(&GetCastOwner(), &WidefieldMicroscope::OnSaveCurrentImage, SaveWidefieldImageFilename));
369
370 SaveWidefieldImageFilename.clear();
371 }
372
373 if (ModuleData->HaveLocalizedPositionsChanged())
374 {
375 MainGraphicsView->RemoveMarkers(true);
376 for (const auto& Position : ModuleData->GetLocalizedPositions())
377 MainGraphicsView->AddMarker(Position.second.Position, QColorConstants::DarkYellow, true, Position.first, "Emitter " + Util::ToStr(Position.first));
378
379 ModuleData->ResetLocalizedPositionsChanged();
380 }
381
382 if (CurrentConfocalSpotPosition != ModuleData->GetConfocalSpotImagePosition())
383 {
384 MainGraphicsView->RemoveMarker(CurrentConfocalSpotPosition);
385 MainGraphicsView->AddMarker(ModuleData->GetConfocalSpotImagePosition(), QColorConstants::Red, false, -1, "Confocal spot");
386
387 CurrentConfocalSpotPosition = ModuleData->GetConfocalSpotImagePosition();
388 }
389
390 if (MainGraphicsView->HaveMarkersChanged())
391 {
392 // Copy intended.
393 const auto LocalizedPositions = ModuleData->GetLocalizedPositions();
394 ModuleData->ClearLocalizedPositions();
395
396 bool SortingEnabled = ui->TWEmitterList->isSortingEnabled();
397 ui->TWEmitterList->setSortingEnabled(false);
398
399 ui->TWEmitterList->clearContents();
400 ui->TWEmitterList->setRowCount(0);
401
402 auto& Markers = MainGraphicsView->GetMarkers();
403 for (const auto& Marker : Markers)
404 {
405 const auto Row = ui->TWEmitterList->rowCount();
406 ui->TWEmitterList->insertRow(Row);
407
408 QTableWidgetItem* IDItem = new QTableWidgetItem;
409 WidefieldMicroscopeData::LocalizedEmitterStateType LocalizedEmitterState = WidefieldMicroscopeData::LocalizedEmitterStateType::NotSet;
410 if (Marker.GetID() >= 0)
411 {
412 IDItem->setData(Qt::EditRole, Marker.GetID());
413 IDItem->setData(Qt::UserRole, Marker.GetID());
414
415 auto OldLocalizedPosition = LocalizedPositions.find(Marker.GetID());
416 if (OldLocalizedPosition != LocalizedPositions.cend())
417 LocalizedEmitterState = OldLocalizedPosition->second.State;
418 ModuleData->AppendLocalizedPosition({ Marker.GetID(), { Marker.GetMarkerPos(), LocalizedEmitterState } });
419 }
420 else
421 {
422 IDItem->setData(Qt::UserRole, Util::MarkerGraphicsView::MarkerType::IDType(-1));
423 IDItem->setText("n/a");
424 }
425
426 ui->TWEmitterList->setItem(Row, EmitterListColumnType::EmitterID, IDItem);
427 ui->TWEmitterList->setItem(Row, EmitterListColumnType::EmitterName, new QTableWidgetItem(Marker.GetName().data()));
428 ui->TWEmitterList->setItem(Row, EmitterListColumnType::Image_x, new QTableWidgetItem(QString::number(Marker.GetMarkerPos().x())));
429 ui->TWEmitterList->item(Row, EmitterListColumnType::Image_x)->setData(Qt::ItemDataRole::UserRole, Marker.GetMarkerPos().x());
430 ui->TWEmitterList->setItem(Row, EmitterListColumnType::Image_y, new QTableWidgetItem(QString::number(Marker.GetMarkerPos().y())));
431 ui->TWEmitterList->item(Row, EmitterListColumnType::Image_y)->setData(Qt::ItemDataRole::UserRole, Marker.GetMarkerPos().y());
432 ui->TWEmitterList->setItem(Row, EmitterListColumnType::Sample_x, new QTableWidgetItem(Marker.GetImagePos().isNull() ? "n/a" : QString::number(Marker.GetImagePos().x(), 'f', 0)));
433 ui->TWEmitterList->item(Row, EmitterListColumnType::Sample_x)->setData(Qt::ItemDataRole::UserRole, Marker.GetImagePos().x());
434 ui->TWEmitterList->setItem(Row, EmitterListColumnType::Sample_y, new QTableWidgetItem(Marker.GetImagePos().isNull() ? "n/a" : QString::number(Marker.GetImagePos().y(), 'f', 0)));
435 ui->TWEmitterList->item(Row, EmitterListColumnType::Sample_y)->setData(Qt::ItemDataRole::UserRole, Marker.GetImagePos().y());
436 ui->TWEmitterList->setItem(Row, EmitterListColumnType::EmitterState, new QTableWidgetItem(WidefieldMicroscopeData::GetLocalizedEmitterStateString(LocalizedEmitterState)));
437 ui->TWEmitterList->item(Row, EmitterListColumnType::EmitterState)->setForeground(WidefieldMicroscopeData::GetLocalizedEmitterColor(LocalizedEmitterState));
438 }
439
440 ui->TWEmitterList->setSortingEnabled(SortingEnabled);
441
442 ModuleData->ResetLocalizedPositionsChanged();
443 ModuleData->ResetAutoMeasureCurrentEmitter();
444 }
445
446 if (ModuleData->HaveLocalizedPositionsStateChanged())
447 {
448 for (int i = 0; i < ui->TWEmitterList->rowCount(); ++i)
449 {
450 auto ID = ui->TWEmitterList->item(i, EmitterListColumnType::EmitterID)->data(Qt::ItemDataRole::UserRole).value<Util::MarkerGraphicsView::MarkerType::IDType>();
451 auto Emitter = ModuleData->GetLocalizedPositions().find(ID);
452 if (Emitter == ModuleData->GetLocalizedPositions().cend())
453 continue;
454
455 ui->TWEmitterList->item(i, EmitterListColumnType::EmitterState)->setText(WidefieldMicroscopeData::GetLocalizedEmitterStateString(Emitter->second.State));
456 ui->TWEmitterList->item(i, EmitterListColumnType::EmitterState)->setForeground(WidefieldMicroscopeData::GetLocalizedEmitterColor(Emitter->second.State));
457 }
458
459 ModuleData->ClearLocalizedPositionsStateChanged();
460 }
461
462 switch (EmitterListTask)
463 {
464 case EmitterListTaskType::GoToSamplePos:
465 ModuleData->EnqueueEvent(DynExp::MakeEvent(&GetCastOwner(), &WidefieldMicroscope::OnGoToSamplePos, SamplePos));
466 EmitterListTask = EmitterListTaskType::None;
467 break;
468 case EmitterListTaskType::MarkerToConfocalSpot:
469 ModuleData->EnqueueEvent(DynExp::MakeEvent(&GetCastOwner(), &WidefieldMicroscope::OnBringMarkerToConfocalSpot, MarkerPos, SamplePos));
470 EmitterListTask = EmitterListTaskType::None;
471 break;
472 case EmitterListTaskType::RunCharacterization:
473 ModuleData->EnqueueEvent(DynExp::MakeEvent(&GetCastOwner(), &WidefieldMicroscope::OnRunCharacterizationFromID, MarkerID));
474 EmitterListTask = EmitterListTaskType::None;
475 break;
476 default: break;
477 }
478 }
479
480 void WidefieldMicroscopeWidget::UpdateConfocalUIData(Util::SynchronizedPointer<WidefieldMicroscopeData>& ModuleData)
481 {
482 if (!ui->SBConfocalWidth->hasFocus())
483 ui->SBConfocalWidth->setValue(ModuleData->GetConfocalScanWidth());
484 if (!ui->SBConfocalHeight->hasFocus())
485 ui->SBConfocalHeight->setValue(ModuleData->GetConfocalScanHeight());
486 if (!ui->SBConfocalDistPerPixel->hasFocus())
487 ui->SBConfocalDistPerPixel->setValue(ModuleData->GetConfocalScanDistPerPixel());
488 if (!ui->SBConfocalOptimizationInitXYStepSize->hasFocus())
489 ui->SBConfocalOptimizationInitXYStepSize->setValue(ModuleData->GetConfocalOptimizationInitXYStepSize());
490 if (!ui->SBConfocalOptimizationInitZStepSize->hasFocus())
491 ui->SBConfocalOptimizationInitZStepSize->setValue(ModuleData->GetConfocalOptimizationInitZStepSize());
492 if (!ui->SBConfocalOptimizationTolerance->hasFocus())
493 ui->SBConfocalOptimizationTolerance->setValue(ModuleData->GetConfocalOptimizationTolerance());
494
495 if (ModuleData->HasConfocalScanSurfacePlotRows())
496 {
497 NumItemsInArray = 0;
498 ConfocalSurfaceMinCounts = std::numeric_limits<decltype(ConfocalSurfaceMinCounts)>::max();
499 ConfocalSurfaceMaxCounts = 0;
500
501 ConfocalGraph->GetProxy()->resetArray(ModuleData->GetConfocalScanSurfacePlotRows());
502 ConfocalGraph->ResetSelectedPoint();
503 }
504
505 if (ModuleData->GetConfocalScanResults().size() > NumItemsInArray)
506 {
507 QPoint Selection = { -1, -1 };
508 for (auto i = NumItemsInArray; i < ModuleData->GetConfocalScanResults().size(); ++i)
509 {
510 const auto& ResultItem = ModuleData->GetConfocalScanResults()[i];
511 if (ResultItem.first.RowIndex < 0 || ResultItem.first.ColumnIndex < 0)
512 continue;
513
514 QSurfaceDataItem SurfaceItem = ConfocalGraph->GetProxy()->itemAt(ResultItem.first.RowIndex, ResultItem.first.ColumnIndex);
515 SurfaceItem.setY(ResultItem.second);
516 ConfocalGraph->GetProxy()->setItem(ResultItem.first.RowIndex, ResultItem.first.ColumnIndex, SurfaceItem);
517
518 if (ConfocalGraph->GetSelectedPoint().x() == ResultItem.first.RowIndex &&
519 ConfocalGraph->GetSelectedPoint().y() == ResultItem.first.ColumnIndex)
520 Selection = { ResultItem.first.RowIndex, ResultItem.first.ColumnIndex };
521
522 ConfocalSurfaceMinCounts = std::min(ConfocalSurfaceMinCounts, ResultItem.second);
523 ConfocalSurfaceMaxCounts = std::max(ConfocalSurfaceMaxCounts, ResultItem.second);
524
525 ++NumItemsInArray;
526 }
527
528 if (Selection.x() >= 0 && Selection.y() >= 0)
529 {
530 QSurfaceDataItem SurfaceItem = ConfocalGraph->GetProxy()->itemAt(Selection.x(), Selection.y());
531 SurfaceItem.setY(ConfocalSurfaceMaxCounts * 1.03);
532 ConfocalGraph->GetProxy()->setItem(Selection.x(), Selection.y(), SurfaceItem);
533 }
534
535 if (ConfocalSurfaceMinCounts < std::numeric_limits<decltype(ConfocalSurfaceMinCounts)>::max() && ConfocalSurfaceMaxCounts > 0 &&
536 ConfocalSurfaceMinCounts < ConfocalSurfaceMaxCounts)
537 ConfocalGraph->GetYValueAxis()->setRange(ConfocalSurfaceMinCounts, ConfocalSurfaceMaxCounts * 1.03);
538 else
539 ConfocalGraph->GetYValueAxis()->setRange(ConfocalSurfaceMaxCounts - 1, ConfocalSurfaceMaxCounts + 1);
540
541 ConfocalGraph->UpdateData();
542 }
543 }
544
545 void WidefieldMicroscopeWidget::UpdateHBTUIData(Util::SynchronizedPointer<WidefieldMicroscopeData>& ModuleData)
546 {
547 if (!ui->SBHBTBinWidth->hasFocus())
548 ui->SBHBTBinWidth->setValue(ModuleData->GetHBTBinWidth().count());
549 if (!ui->SBHBTBinCount->hasFocus())
550 ui->SBHBTBinCount->setValue(Util::NumToT<int>(ModuleData->GetHBTBinCount()));
551 if (!ui->SBHBTAcquisitionTime->hasFocus())
552 ui->SBHBTAcquisitionTime->setValue(static_cast<double>(ModuleData->GetHBTMaxIntegrationTime().count()) / std::chrono::microseconds::period::den);
553 ui->LEHBTTotalIntegrationTime->setText(QString::number(ModuleData->GetHBTTotalIntegrationTime().count() / std::chrono::microseconds::period::den) + " s");
554
555 if (ui->WidgetHBTGraph->isVisible() && HBTGraph)
556 {
557 HBTPlotInfo.Reset();
558 HBTPlotInfo.MaxSampleCountPerSeries = Util::NumToT<size_t>(ModuleData->GetHBTDataPoints().size());
559 HBTPlotInfo.MinValues = ModuleData->GetHBTDataPointsMinValues();
560 HBTPlotInfo.MaxValues = ModuleData->GetHBTDataPointsMaxValues();
561 HBTPlotInfo.AdjustAxesLimits();
562 HBTPlotInfo.ReprocessSamples(ModuleData->GetHBTDataPoints(), 0);
563
564 HBTGraph->UpdateSeries(0, ModuleData->GetHBTDataPoints(), HBTPlotInfo);
565 HBTGraph->UpdateData(HBTPlotInfo);
566
567 ui->LEHBTMinValue->setText(QString::number(ModuleData->GetHBTDataPointsMinValues().y()));
568 }
569 }
570
571 void WidefieldMicroscopeWidget::UpdateAutoMeasureUIData(Util::SynchronizedPointer<WidefieldMicroscopeData>& ModuleData, bool IsCharacterizingSample)
572 {
573 {
574 const QSignalBlocker Blocker(ui->LEAutoMeasureSavePath);
575 ui->LEAutoMeasureSavePath->setText(QString::fromUtf16(ModuleData->GetAutoMeasureSavePath().u16string().c_str()));
576 } // Blocker unlocked here.
577
578 if (!ui->SBAutoMeasureNumberImageSets->hasFocus())
579 ui->SBAutoMeasureNumberImageSets->setValue(ModuleData->GetAutoMeasureNumberImageSets());
580 if (!ui->SBAutoMeasureInitialImageSetWaitTime->hasFocus())
581 ui->SBAutoMeasureInitialImageSetWaitTime->setValue(ModuleData->GetAutoMeasureInitialImageSetWaitTime().count());
582 if (!ui->SBAutoMeasureImagePositionScatterRadius->hasFocus())
583 ui->SBAutoMeasureImagePositionScatterRadius->setValue(ModuleData->GetAutoMeasureImagePositionScatterRadius());
584 if (!ui->CBAutoMeasureLocalize->hasFocus())
585 ui->CBAutoMeasureLocalize->setCurrentIndex(ModuleData->GetAutoMeasureLocalizationType());
586 if (!ui->SBAutoMeasureOptimizationAttempts->hasFocus())
587 ui->SBAutoMeasureOptimizationAttempts->setValue(ModuleData->GetAutoMeasureNumOptimizationAttempts());
588 if (!ui->SBAutoMeasureOptimizationReruns->hasFocus())
589 ui->SBAutoMeasureOptimizationReruns->setValue(ModuleData->GetAutoMeasureMaxOptimizationReruns());
590 if (!ui->SBAutoMeasureOptimizationMaxDistance->hasFocus())
591 ui->SBAutoMeasureOptimizationMaxDistance->setValue(ModuleData->GetAutoMeasureOptimizationMaxDistance());
592 if (!ui->SBAutoMeasureCountRateThreshold->hasFocus())
593 ui->SBAutoMeasureCountRateThreshold->setValue(ModuleData->GetAutoMeasureCountRateThreshold());
594 if (!ui->SBAutoMeasureCellRangeFromX->hasFocus())
595 ui->SBAutoMeasureCellRangeFromX->setValue(ModuleData->GetAutoMeasureCellRangeFrom().x());
596 if (!ui->SBAutoMeasureCellRangeFromY->hasFocus())
597 ui->SBAutoMeasureCellRangeFromY->setValue(ModuleData->GetAutoMeasureCellRangeFrom().y());
598 if (!ui->SBAutoMeasureCellRangeToX->hasFocus())
599 ui->SBAutoMeasureCellRangeToX->setValue(ModuleData->GetAutoMeasureCellRangeTo().x());
600 if (!ui->SBAutoMeasureCellRangeToY->hasFocus())
601 ui->SBAutoMeasureCellRangeToY->setValue(ModuleData->GetAutoMeasureCellRangeTo().y());
602 if (!ui->SBAutoMeasureCellSkipX->hasFocus())
603 ui->SBAutoMeasureCellSkipX->setValue(ModuleData->GetAutoMeasureCellSkip().x());
604 if (!ui->SBAutoMeasureCellSkipY->hasFocus())
605 ui->SBAutoMeasureCellSkipY->setValue(ModuleData->GetAutoMeasureCellSkip().y());
606
607 if (ModuleData->GetAutoMeasureCurrentImageSet() >= 0 && ModuleData->GetAutoMeasureCurrentImageSet() < ModuleData->GetAutoMeasureNumberImageSets())
608 {
609 ui->LAutoMeasureCellProgress->setText("Recording image set " + QString::number(ModuleData->GetAutoMeasureCurrentImageSet() + 1) +
610 " / " + QString::number(ModuleData->GetAutoMeasureNumberImageSets()));
611 ui->PBAutoMeasureCellProgress->setValue(static_cast<int>(100.0 * ModuleData->GetAutoMeasureCurrentImageSet() / ModuleData->GetAutoMeasureNumberImageSets()));
612 ui->PBAutoMeasureCellProgress->setVisible(true);
613 }
614 else if (ModuleData->IsAutoMeasureRunning())
615 {
616 const auto EmitterCount = std::distance(ModuleData->GetAutoMeasureFirstEmitter(), ModuleData->GetLocalizedPositions().end());
617 const auto CurrentEmitter = EmitterCount - std::distance(ModuleData->GetAutoMeasureCurrentEmitter(), ModuleData->GetLocalizedPositions().end());
618
619 ui->LAutoMeasureCellProgress->setText("Emitter " + QString::number(CurrentEmitter + 1) +
620 " / " + QString::number(EmitterCount) + ", " +
621 QString::number(ModuleData->GetNumFinishedLocalizedPositions()) + " successful, " +
622 QString::number(ModuleData->GetNumFailedLocalizedPositions()) + " failed");
623 ui->PBAutoMeasureCellProgress->setValue(static_cast<int>(100.0 * CurrentEmitter / EmitterCount));
624 ui->PBAutoMeasureCellProgress->setVisible(true);
625 }
626 else
627 {
628 ui->LAutoMeasureCellProgress->setText("Ready");
629 ui->PBAutoMeasureCellProgress->setVisible(false);
630 }
631
632 ui->GBAutoMeasureSampleProgress->setVisible(IsCharacterizingSample && ModuleData->HasCellID());
633 if (IsCharacterizingSample && ModuleData->HasCellID())
634 {
635 const auto CurrentCell = ModuleData->GetAutoMeasureCurrentCellIndex();
636 const auto CellCount = ModuleData->GetAutoMeasureCellCount();
637
638 ui->LAutoMeasureSampleProgress->setText("Cell " + QString::number(CurrentCell + 1) +
639 " / " + QString::number(CellCount));
640 ui->PBAutoMeasureSampleProgress->setValue(static_cast<int>(100.0 * CurrentCell / CellCount));
641 }
642 }
643
644 void WidefieldMicroscopeWidget::SetMainGraphicsImage(const QImage& Image) noexcept
645 {
646 MainGraphicsPixmap = QPixmap::fromImage(Image); // deep copy
647 MainGraphicsPixmap.detach(); // just to be sure...
648 }
649
650 void WidefieldMicroscopeWidget::UpdateScene()
651 {
652 if (MainGraphicsView->isVisible() && !MainGraphicsView->visibleRegion().isEmpty())
653 {
654 MainGraphicsPixmapItem->setPixmap(MainGraphicsPixmap);
655 MainGraphicsScene->update();
656
657 OnZoomFitClicked(ui->action_Zoom_fit->isChecked());
658 }
659
660 StatusBar.Update();
661 }
662
663 bool WidefieldMicroscopeWidget::eventFilter(QObject* obj, QEvent* event)
664 {
665 if (MainGraphicsView->viewport())
666 if (event->type() == QEvent::MouseMove)
667 {
668 OnImageMouseMove(static_cast<QMouseEvent*>(event));
669
670 return true;
671 }
672
673 return QObject::eventFilter(obj, event);
674 }
675
676 void WidefieldMicroscopeWidget::resizeEvent(QResizeEvent* event)
677 {
678 OnZoomFitClicked(ui->action_Zoom_fit->isChecked());
679 }
680
681 bool WidefieldMicroscopeWidget::StoreTWEmitterListSelection()
682 {
683 if (ui->TWEmitterList->selectedItems().empty())
684 return false;
685
686 const auto Row = ui->TWEmitterList->selectedItems()[0]->row();
687
688 MarkerPos = { ui->TWEmitterList->item(Row, EmitterListColumnType::Image_x)->data(Qt::ItemDataRole::UserRole).toInt(),
689 ui->TWEmitterList->item(Row, EmitterListColumnType::Image_y)->data(Qt::ItemDataRole::UserRole).toInt() };
690 SamplePos = { ui->TWEmitterList->item(Row, EmitterListColumnType::Sample_x)->data(Qt::ItemDataRole::UserRole).toReal(),
691 ui->TWEmitterList->item(Row, EmitterListColumnType::Sample_y)->data(Qt::ItemDataRole::UserRole).toReal() };
692 MarkerID = ui->TWEmitterList->item(Row, EmitterListColumnType::EmitterID)->data(Qt::ItemDataRole::UserRole).value<decltype(MarkerID)>();
693
694 return true;
695 }
696
697 void WidefieldMicroscopeWidget::OnSaveImageClicked()
698 {
699 auto Filename = Util::PromptSaveFilePathModule(this, "Save image", ".png", "Portable Network Graphics image (*.png)");
700 if (Filename.isEmpty())
701 return;
702
703 SaveWidefieldImageFilename = Filename;
704 }
705
706 void WidefieldMicroscopeWidget::OnZoomResetClicked()
707 {
708 ui->action_Zoom_fit->setChecked(false);
709 MainGraphicsView->ZoomReset();
710 }
711
712 void WidefieldMicroscopeWidget::OnZoomInClicked()
713 {
714 ui->action_Zoom_fit->setChecked(false);
715 MainGraphicsView->ZoomIn();
716 }
717
718 void WidefieldMicroscopeWidget::OnZoomOutClicked()
719 {
720 ui->action_Zoom_fit->setChecked(false);
721 MainGraphicsView->ZoomOut();
722 }
723
724 void WidefieldMicroscopeWidget::OnZoomFitClicked(bool Checked)
725 {
726 if (Checked)
727 MainGraphicsView->fitInView(MainGraphicsPixmapItem, Qt::AspectRatioMode::KeepAspectRatio);
728 }
729
730 void WidefieldMicroscopeWidget::OnImageMouseMove(QMouseEvent* Event)
731 {
732 auto LocalPoint = MainGraphicsView->mapFromGlobal(Event->globalPosition().toPoint());
733
734 if (!MainGraphicsView->items(LocalPoint).empty())
735 {
736 auto Point = MainGraphicsView->mapToScene(LocalPoint).toPoint();
737
738 StatusBar.XCoordLabel->setText("X:" + QString::number(Point.x()));
739 StatusBar.YCoordLabel->setText("Y:" + QString::number(Point.y()));
740 }
741 }
742
743 void WidefieldMicroscopeWidget::OnCellIDContextMenuRequested(const QPoint& Position)
744 {
745 StatusBar.CellIDContextMenu->exec(StatusBar.CellIDLabel->mapToGlobal(Position));
746 }
747
748 void WidefieldMicroscopeWidget::OnEmitterListCellClicked(int Row, int Column)
749 {
750 if (!StoreTWEmitterListSelection())
751 MainGraphicsView->DeselectMarkers();
752 else
753 MainGraphicsView->SelectMarker(MarkerPos);
754 }
755
756 void WidefieldMicroscopeWidget::OnEmitterListCellDoubleClicked(int Row, int Column)
757 {
758 if (StoreTWEmitterListSelection())
759 EmitterListTask = EmitterListTaskType::MarkerToConfocalSpot;
760 }
761
762 void WidefieldMicroscopeWidget::OnEmitterListContextMenuRequested(const QPoint& Position)
763 {
764 EmitterListContextMenu->exec(ui->TWEmitterList->mapToGlobal(Position));
765 }
766
767 void WidefieldMicroscopeWidget::OnEmitterListDeleteEntryClicked()
768 {
769 for (int i = 0; i < ui->TWEmitterList->selectedItems().size(); ++i)
770 {
771 const auto Row = ui->TWEmitterList->selectedItems()[i]->row();
772 const QPoint Pos = { ui->TWEmitterList->item(Row, EmitterListColumnType::Image_x)->data(Qt::ItemDataRole::UserRole).toInt(),
773 ui->TWEmitterList->item(Row, EmitterListColumnType::Image_y)->data(Qt::ItemDataRole::UserRole).toInt() };
774
775 MainGraphicsView->RemoveMarker(Pos, true);
776 }
777 }
778
779 void WidefieldMicroscopeWidget::OnEmitterListEditEntryClicked()
780 {
781 if (ui->TWEmitterList->selectedItems().empty() || !StoreTWEmitterListSelection())
782 return;
783
784 const auto Row = ui->TWEmitterList->selectedItems()[0]->row();
785 const auto OldName = ui->TWEmitterList->item(Row, EmitterListColumnType::EmitterName)->text();
786
787 bool OKClicked = false;
788 QString NewName = QInputDialog::getText(this, "Edit name",
789 QString("Enter new name for marker \"") + OldName + "\":", QLineEdit::Normal, OldName, &OKClicked);
790
791 if (OKClicked)
792 MainGraphicsView->RenameMarker(MarkerPos, NewName.toStdString());
793 }
794
795 void WidefieldMicroscopeWidget::OnEmitterListGoToSamplePositionClicked()
796 {
797 if (StoreTWEmitterListSelection())
798 EmitterListTask = EmitterListTaskType::GoToSamplePos;
799 }
800
801 void WidefieldMicroscopeWidget::OnEmitterListBringMarkerToConfocalSpotClicked()
802 {
803 if (StoreTWEmitterListSelection())
804 EmitterListTask = EmitterListTaskType::MarkerToConfocalSpot;
805 }
806
807 void WidefieldMicroscopeWidget::OnEmitterListRunCharacterizationFromID()
808 {
809 if (StoreTWEmitterListSelection())
810 EmitterListTask = EmitterListTaskType::RunCharacterization;
811 }
812
813 void WidefieldMicroscopeWidget::OnConfocalMapResetClicked()
814 {
815 ConfocalGraph->ResetCamera();
816 ConfocalGraph->ResetSelectedPoint();
817 }
818
819 void WidefieldMicroscopeWidget::OnConfocalMapSaveRawDataClicked()
820 {
821 if (!ConfocalGraph->GetProxy()->rowCount())
822 return;
823
824 auto Filename = Util::PromptSaveFilePathModule(this, "Save data", ".csv", " Comma-separated values file (*.csv)");
825 if (Filename.isEmpty())
826 return;
827
828 std::stringstream CSVData;
829 {
830 auto ModuleData = DynExp::dynamic_ModuleData_cast<WidefieldMicroscope>(GetOwner().GetModuleData());
831
832 CSVData = ModuleData->AssembleCSVHeader(true, false, false);
833 ModuleData->WriteConfocalScanResults(CSVData);
834 } // ModuleData unlocked here.
835
836 if (!Util::SaveToFile(Filename, CSVData.str()))
837 QMessageBox::warning(this, "DynExp - Error", "Error writing data to file.");
838 }
839
840 void WidefieldMicroscopeWidget::OnHBTSaveRawDataClicked()
841 {
842 auto Filename = Util::PromptSaveFilePathModule(this, "Save data", ".csv", " Comma-separated values file (*.csv)");
843 if (Filename.isEmpty())
844 return;
845
846 std::stringstream CSVData;
847 {
848 auto ModuleData = DynExp::dynamic_ModuleData_cast<WidefieldMicroscope>(GetOwner().GetModuleData());
849
850 CSVData = ModuleData->AssembleCSVHeader(false, true, false);
851 ModuleData->WriteHBTResults(CSVData);
852 } // ModuleData unlocked here.
853
854 if (!Util::SaveToFile(Filename, CSVData.str()))
855 QMessageBox::warning(this, "DynExp - Error", "Error writing data to file.");
856 }
857
858 void WidefieldMicroscopeWidget::OnAutoMeasureSavePathBrowseClicked()
859 {
860 auto Filename = Util::PromptSaveFilePathModule(this, "Select directory and filename prefix for saving data in auto-measure mode",
861 ".csv", " Comma-separated values file (*.csv)");
862 if (Filename.isEmpty())
863 return;
864
865 // Emits signal to update module data accordingly.
866 ui->LEAutoMeasureSavePath->setText(Filename);
867 }
868
869 void WidefieldMicroscopeWidget::OnCharacterizationStepsContextMenuRequested()
870 {
871 auto ModuleData = DynExp::dynamic_ModuleData_cast<WidefieldMicroscope>(GetOwner().GetModuleData());
872
873 ui->action_CharacterizationSteps_Widefield_PLE->setChecked(ModuleData->GetAutoMeasureWidefieldPLEEnabled());
874 ui->action_CharacterizationSteps_Optimize->setChecked(ModuleData->GetAutoMeasureOptimizeEnabled());
875 ui->action_CharacterizationSteps_Spectrum->setChecked(ModuleData->GetAutoMeasureSpectrumEnabled());
876 ui->action_CharacterizationSteps_Confocal_PLE->setChecked(ModuleData->GetAutoMeasureConfocalPLEEnabled());
877 ui->action_CharacterizationSteps_HBT->setChecked(ModuleData->GetAutoMeasureHBTEnabled());
878 }
879}
User interface belonging to the DynExpModule::Widefield::WidefieldMicroscope module.
Implementation of a module to control a combined widefield and confocal microscope.
WidefieldMicroscopeWidget(WidefieldMicroscope &Owner, QModuleWidget *parent=nullptr)
DynExpQuick::DynExpSurfaceGraphBackend * ConfocalGraph
QModuleBase & Owner
Module owning this user interface window (reference, because it should never change nor be nullptr).
Definition Module.h:1486
QModuleWidget(QModuleBase &Owner, QWidget *Parent=nullptr)
Constructs a QModuleWidget instance.
Definition Module.cpp:451
Implements a QGraphicsView the user can interact with to insert graphical markers....
Definition QtUtil.h:379
auto contextMenu() const noexcept
Definition QtUtil.h:446
State machine context as used by class StateMachine. A state machine context holds a map with keys an...
Definition Util.h:1420
State machine state as used by class StateMachine. A state mainly wraps a state function of the membe...
Definition Util.h:1363
constexpr StateEnumType GetState() const noexcept
Returns the state's unique identifier.
Definition Util.h:1379
Pointer to lock a class derived from ISynchronizedPointerLockable for synchronizing between threads....
Definition Util.h:171
constexpr auto StatusBarRunningStyleSheet
constexpr auto StatusBarBusyStyleSheet
@ Counts
Count rate in counts per second (cps)
auto MakeEvent(ReceiverType *Receiver, typename DefaultEvent< ReceiverType, std::tuple< std::remove_reference_t< ArgsTs >... > >::EventFuncPtrType EventFuncPtr, ArgsTs &&...Args)
Creates an event of type DefaultEvent.
Definition Module.h:811
std::string ToStr(const T &Value, int Precision=-1)
Converts a (numeric) value of type T to a std::string using operator<< of std::stringstream.
Definition Util.h:684
bool SaveToFile(const QString &Filename, std::string_view Text)
Saves a std::string_view to a file (using QFile). Creates a new file or truncates an existing file's ...
Definition QtUtil.cpp:236
QString PromptSaveFilePathModule(DynExp::QModuleWidget *Parent, const QString &Title, const QString &DefaultSuffix, const QString &NameFilter)
Works as PromptOpenFilePath() but asks the user to select a single file which does not need to exist....
Definition QtUtil.cpp:143
Accumulates include statements to provide a precompiled header.