DynExp
Highly flexible laboratory automation for dynamically changing experiments.
Loading...
Searching...
No Matches
SpectrumViewer.cpp
Go to the documentation of this file.
1// This file is part of DynExp.
2
3#include "stdafx.h"
4#include "moc_SpectrumViewer.cpp"
5#include "SpectrumViewer.h"
6
8{
10 : QModuleWidget(Owner, parent),
11 DataSeries(nullptr), DataChart(nullptr), XAxis(nullptr), YAxis(nullptr)
12 {
13 ui.setupUi(this);
14
15 // For shortcuts
16 this->addAction(ui.action_Run);
17 this->addAction(ui.action_Stop);
18
19 DataChart = new QChart();
20 ui.Spectrum->setChart(DataChart); // Takes ownership of DataChart.
21 ui.Spectrum->setRenderHint(QPainter::Antialiasing);
23 DataChart->legend()->setVisible(false);
24 }
25
27 {
28 ui.SBExposureTime->setRange(ModuleData->MinExposureTime.count(), ModuleData->MaxExposureTime.count());
29 ui.SBExposureTime->setSuffix(" " + QString::fromStdString(Util::ToUnitStr<DynExpInstr::SpectrometerData::TimeType>()));
30 ui.SBLowerFrequency->setRange(ModuleData->MinFrequency, ModuleData->MaxFrequency);
31 ui.SBLowerFrequency->setSuffix(" " + QString(DynExpInstr::SpectrometerData::FrequencyUnitTypeToStr(ModuleData->FrequencyUnit)));
32 ui.SBUpperFrequency->setRange(ModuleData->MinFrequency, ModuleData->MaxFrequency);
33 ui.SBUpperFrequency->setSuffix(" " + QString(DynExpInstr::SpectrometerData::FrequencyUnitTypeToStr(ModuleData->FrequencyUnit)));
34
35 if (XAxis)
36 {
37 DataChart->removeAxis(XAxis);
38 delete XAxis;
39 }
40 if (YAxis)
41 {
42 DataChart->removeAxis(YAxis);
43 delete YAxis;
44 }
45
46 XAxis = new QValueAxis(this);
47 YAxis = new QValueAxis(this);
48 XAxis->setTitleText(QString("Frequency in ") + DynExpInstr::SpectrometerData::FrequencyUnitTypeToStr(ModuleData->FrequencyUnit));
49 XAxis->setLabelFormat("%d");
50 YAxis->setTitleText(QString("Intensity in ") + DynExpInstr::SpectrometerData::IntensityUnitTypeToStr(ModuleData->IntensityUnit));
51 YAxis->setLabelFormat("%d");
52
53 // Chart takes ownership of axes.
54 DataChart->addAxis(XAxis, Qt::AlignBottom);
55 DataChart->addAxis(YAxis, Qt::AlignLeft);
56 }
57
59 {
60 ui.action_Save_CSV->setEnabled(ModuleData->CapturingState != DynExpInstr::SpectrometerData::CapturingStateType::Capturing);
61 ui.action_Run->setEnabled(ModuleData->CapturingState != DynExpInstr::SpectrometerData::CapturingStateType::Capturing);
62 ui.action_Stop->setEnabled(ModuleData->CapturingState == DynExpInstr::SpectrometerData::CapturingStateType::Capturing);
63 ui.SBExposureTime->setEnabled(ModuleData->CapturingState != DynExpInstr::SpectrometerData::CapturingStateType::Capturing);
64 ui.SBLowerFrequency->setEnabled(ModuleData->CapturingState != DynExpInstr::SpectrometerData::CapturingStateType::Capturing);
65 ui.SBUpperFrequency->setEnabled(ModuleData->CapturingState != DynExpInstr::SpectrometerData::CapturingStateType::Capturing);
66
67 {
68 const QSignalBlocker Blocker(ui.action_SilentMode);
69 ui.action_SilentMode->setChecked(ModuleData->SilentModeEnabled);
70 } // Blocker destroyed here.
71
72 if (!ui.SBExposureTime->hasFocus())
73 {
74 const QSignalBlocker Blocker(ui.SBExposureTime);
75 ui.SBExposureTime->setValue(ModuleData->CurrentExposureTime.count());
76 }
77
78 if (!ui.SBLowerFrequency->hasFocus())
79 {
80 const QSignalBlocker Blocker(ui.SBLowerFrequency);
81 ui.SBLowerFrequency->setValue(ModuleData->CurrentLowerFrequency);
82 }
83
84 if (!ui.SBUpperFrequency->hasFocus())
85 {
86 const QSignalBlocker Blocker(ui.SBUpperFrequency);
87 ui.SBUpperFrequency->setValue(ModuleData->CurrentUpperFrequency);
88 }
89
90 switch (ModuleData->CapturingState)
91 {
93 ui.LState->setText(" Acquiring spectrum...");
94 ui.LState->setStyleSheet(DynExpUI::StatusBarBusyStyleSheet);
95 break;
97 ui.LState->setText(" The spectrometer is in a warning state.");
98 ui.LState->setStyleSheet(DynExpUI::StatusBarWarningStyleSheet);
99 break;
101 ui.LState->setText(" The spectrometer is in an error state.");
102 ui.LState->setStyleSheet(DynExpUI::StatusBarErrorStyleSheet);
103 break;
104 default:
105 ui.LState->setText(" Ready");
106 ui.LState->setStyleSheet("");
107 }
108
109 ui.PBProgress->setVisible(ModuleData->CapturingState == DynExpInstr::SpectrometerData::CapturingStateType::Capturing
110 && ModuleData->CapturingProgress > 0);
111 ui.PBProgress->setValue(ModuleData->CapturingProgress > 0 ? Util::NumToT<int>(ModuleData->CapturingProgress) : 0);
112 }
113
115 {
116 if (SampleData.Points.empty() || IsSavingData)
117 return;
118
119 CurrentSpectrum = std::move(SampleData);
120 CurrentExposureTime = ExposureTime;
121
122 // DataSeries->replace() does not work...
123 DataChart->removeAllSeries();
124
125 DataSeries = new QLineSeries(this);
127 DataSeries->setPointsVisible(false);
128
129 DataChart->axes()[0]->setRange(CurrentSpectrum.MinValues.x(), CurrentSpectrum.MaxValues.x());
131 {
132 auto Factor = std::abs(CurrentSpectrum.MinValues.y()) * .01;
133 if (Factor == 0)
134 Factor = 2;
135
136 DataChart->axes()[1]->setRange(CurrentSpectrum.MinValues.y() - Factor, CurrentSpectrum.MaxValues.y() + Factor);
137 }
138 else
139 DataChart->axes()[1]->setRange(CurrentSpectrum.MinValues.y(), CurrentSpectrum.MaxValues.y());
140
141 DataChart->addSeries(DataSeries);
142 DataSeries->attachAxis(DataChart->axes()[0]);
143 DataSeries->attachAxis(DataChart->axes()[1]);
144 }
145
147 {
148 // As soon as FinishedSavingDataGuard is destroyed, IsSavingData is set back to false.
150 IsSavingData = true;
151
152 auto Filename = Util::PromptSaveFilePathModule(this, "Save data", ".csv", " Comma-separated values file (*.csv)");
153 if (Filename.isEmpty())
154 return;
155
157 QMessageBox::warning(this, "DynExp - Error", "Error writing data to file.");
158 }
159
170
172 {
173 std::stringstream CSVData;
174 CSVData << std::setprecision(6);
175 CSVData << "ExposureTime = " << ExposureTime.count() << " " << Util::ToUnitStr<DynExpInstr::SpectrometerData::TimeType>() << "\n";
176 CSVData << "HEADER_END\n";
177
178 CSVData << "f[" << DynExpInstr::SpectrometerData::FrequencyUnitTypeToStr(FrequencyUnit)
179 << "];I[" << DynExpInstr::SpectrometerData::IntensityUnitTypeToStr(IntensityUnit) << "]\n";
180 for (const auto& Sample : Points)
181 CSVData << Sample.x() << ";" << Sample.y() << "\n";
182
183 return CSVData.str();
184 }
185
190
192 {
195 MinFrequency = 0.0;
196 MaxFrequency = 0.0;
197 MinExposureTime = DynExpInstr::SpectrometerData::TimeType();
198 MaxExposureTime = DynExpInstr::SpectrometerData::TimeType();
200 AcquisitionExposureTime = DynExpInstr::SpectrometerData::TimeType();
201 CurrentLowerFrequency = 0.0;
202 CurrentUpperFrequency = 0.0;
203 SilentModeEnabled = false;
205 CapturingProgress = 0.0;
206 AutoSaveFilename.clear();
208 SpectrumRecordingPaused = false;
209
210 UIInitialized = false;
211 }
212
214 {
215 try
216 {
217 auto ModuleData = DynExp::dynamic_ModuleData_cast<SpectrumViewer>(Instance.ModuleDataGetter());
218 auto InstrData = DynExp::dynamic_InstrumentData_cast<DynExpInstr::Spectrometer>(ModuleData->GetSpectrometer()->GetInstrumentData());
219
220 ModuleData->CurrentExposureTime = InstrData->GetCurrentExposureTime();
221 ModuleData->CurrentLowerFrequency = InstrData->GetCurrentLowerFrequency();
222 ModuleData->CurrentUpperFrequency = InstrData->GetCurrentUpperFrequency();
223 ModuleData->SilentModeEnabled = InstrData->GetSilentModeEnabled();
224 ModuleData->CapturingState = InstrData->GetCapturingState();
225 ModuleData->CapturingProgress = InstrData->GetCapturingProgress();
226
227 if (InstrData->HasSpectrum() && !ModuleData->SpectrumRecordingPaused)
228 {
229 ModuleData->CurrentSpectrum = ProcessSpectrum(InstrData->GetSpectrum(), ModuleData);
230
231 if (!ModuleData->CurrentSpectrum.Points.empty())
232 {
233 if (ModuleData->GetCommunicator().valid() && !ModuleData->AutoSaveFilename.empty())
234 ModuleData->GetCommunicator()->PostEvent(*this, SpectrumFinishedRecordingEvent{});
235
236 ModuleData->AutoSaveFilename.clear();
237 }
238 }
239
240 NumFailedUpdateAttempts = 0;
241 } // ModuleData and instruments' data unlocked here.
242 catch (const Util::TimeoutException& e)
243 {
244 if (NumFailedUpdateAttempts++ >= 3)
245 Instance.GetOwner().SetWarning(e);
246 }
247
249 }
250
252 {
253 NumFailedUpdateAttempts = 0;
254 }
255
256 std::unique_ptr<DynExp::QModuleWidget> SpectrumViewer::MakeUIWidget()
257 {
258 auto Widget = std::make_unique<SpectrumViewerWidget>(*this);
259
260 Connect(Widget->GetUI().action_Run, &QAction::triggered, this, &SpectrumViewer::OnRunClicked);
261 Connect(Widget->GetUI().action_Stop, &QAction::triggered, this, &SpectrumViewer::OnStopClicked);
262 Connect(Widget->GetUI().action_SilentMode, &QAction::toggled, this, &SpectrumViewer::OnSilentModeToggled);
263 Connect(Widget->GetUI().SBExposureTime, QOverload<int>::of(&QSpinBox::valueChanged), this, &SpectrumViewer::OnExposureTimeChanged);
264 Connect(Widget->GetUI().SBLowerFrequency, QOverload<double>::of(&QDoubleSpinBox::valueChanged), this, &SpectrumViewer::OnLowerLimitChanged);
265 Connect(Widget->GetUI().SBUpperFrequency, QOverload<double>::of(&QDoubleSpinBox::valueChanged), this, &SpectrumViewer::OnUpperLimitChanged);
266
267 return Widget;
268 }
269
270 void SpectrumViewer::UpdateUIChild(const ModuleBase::ModuleDataGetterType& ModuleDataGetter)
271 {
272 auto Widget = GetWidget<SpectrumViewerWidget>();
273 auto ModuleData = DynExp::dynamic_ModuleData_cast<SpectrumViewer>(ModuleDataGetter());
274
275 if (!ModuleData->IsUIInitialized())
276 {
277 Widget->InitializeUI(ModuleData);
278 ModuleData->SetUIInitialized();
279 }
280
281 Widget->UpdateUI(ModuleData);
282
283 if (!ModuleData->CurrentSpectrum.Points.empty())
284 Widget->SetData(std::move(ModuleData->CurrentSpectrum), ModuleData->AcquisitionExposureTime);
285 }
286
289 {
290 SpectrumViewerWidget::SampleDataType TransformedSpectrum;
291 TransformedSpectrum.FrequencyUnit = Spectrum.GetFrequencyUnit();
292 TransformedSpectrum.IntensityUnit = Spectrum.GetIntensityUnit();
293
294 if (!Spectrum.HasSpectrum())
295 return TransformedSpectrum;
296
297 double YMin(std::numeric_limits<double>::max()), YMax(std::numeric_limits<double>::lowest());
298 for (const auto& Sample : Spectrum.GetSpectrum())
299 {
300 TransformedSpectrum.Points.append({ Sample.first, Sample.second });
301
302 YMin = std::min(YMin, Sample.second);
303 YMax = std::max(YMax, Sample.second);
304 }
305
306 TransformedSpectrum.MinValues = { Spectrum.GetSpectrum().begin()->first, YMin};
307 TransformedSpectrum.MaxValues = { Spectrum.GetSpectrum().rbegin()->first, YMax};
308
309 if (!ModuleData->AutoSaveFilename.empty())
310 SaveSpectrum(TransformedSpectrum, ModuleData);
311
312 return TransformedSpectrum;
313 }
314
317 {
318 if (!Util::SaveToFile(QString::fromStdString(ModuleData->AutoSaveFilename), Spectrum.ToStr(ModuleData->CurrentExposureTime)))
319 Util::EventLogger().Log("Saving spectrum as \"" + ModuleData->AutoSaveFilename + "\" to file failed.", Util::ErrorType::Error);
320 else
321 Util::EventLogger().Log("Saved spectrum as \"" + ModuleData->AutoSaveFilename + "\" to file.");
322 }
323
325 {
330
331 auto ModuleParams = DynExp::dynamic_Params_cast<SpectrumViewer>(Instance->ParamsGetter());
332 auto ModuleData = DynExp::dynamic_ModuleData_cast<SpectrumViewer>(Instance->ModuleDataGetter());
333
334 Instance->LockObject(ModuleParams->Spectrometer, ModuleData->GetSpectrometer());
335 if (ModuleParams->Communicator.ContainsID())
336 Instance->LockObject(ModuleParams->Communicator, ModuleData->GetCommunicator());
337
338 ModuleData->FrequencyUnit = ModuleData->GetSpectrometer()->GetFrequencyUnit();
339 ModuleData->IntensityUnit = ModuleData->GetSpectrometer()->GetIntensityUnit();
340 ModuleData->MinFrequency = ModuleData->GetSpectrometer()->GetMinFrequency();
341 ModuleData->MaxFrequency = ModuleData->GetSpectrometer()->GetMaxFrequency();
342
343 auto InstrData = DynExp::dynamic_InstrumentData_cast<DynExpInstr::Spectrometer>(ModuleData->GetSpectrometer()->GetInstrumentData());
344 ModuleData->MinExposureTime = InstrData->GetMinExposureTime();
345 ModuleData->MaxExposureTime = InstrData->GetMaxExposureTime();
346 }
347
349 {
350 auto ModuleData = DynExp::dynamic_ModuleData_cast<SpectrumViewer>(Instance->ModuleDataGetter());
351
352 Instance->UnlockObject(ModuleData->GetSpectrometer());
353 Instance->UnlockObject(ModuleData->GetCommunicator());
354
359 }
360
362 {
363 auto ModuleData = DynExp::dynamic_ModuleData_cast<SpectrumViewer>(Instance->ModuleDataGetter());
364
365 ModuleData->SpectrumRecordingPaused = false;
366 ModuleData->AcquisitionExposureTime = ModuleData->CurrentExposureTime;
367 ModuleData->GetSpectrometer()->Record();
368 }
369
371 {
372 auto ModuleData = DynExp::dynamic_ModuleData_cast<SpectrumViewer>(Instance->ModuleDataGetter());
373
374 ModuleData->SpectrumRecordingPaused = false;
375 ModuleData->AutoSaveFilename.clear();
376 ModuleData->GetSpectrometer()->Abort();
377 }
378
380 {
381 auto ModuleData = DynExp::dynamic_ModuleData_cast<SpectrumViewer>(Instance->ModuleDataGetter());
382
383 ModuleData->GetSpectrometer()->SetSilentMode(Checked);
384 }
385
387 {
388 auto ModuleData = DynExp::dynamic_ModuleData_cast<SpectrumViewer>(Instance->ModuleDataGetter());
389
390 ModuleData->GetSpectrometer()->SetExposureTime(DynExpInstr::SpectrometerData::TimeType(Value));
391 }
392
394 {
395 auto ModuleData = DynExp::dynamic_ModuleData_cast<SpectrumViewer>(Instance->ModuleDataGetter());
396 auto InstrData = DynExp::dynamic_InstrumentData_cast<DynExpInstr::Spectrometer>(ModuleData->GetSpectrometer()->GetInstrumentData());
397
398 if (Value < InstrData->GetCurrentUpperFrequency())
399 ModuleData->GetSpectrometer()->SetFrequencyRange(Value, InstrData->GetCurrentUpperFrequency());
400 }
401
403 {
404 auto ModuleData = DynExp::dynamic_ModuleData_cast<SpectrumViewer>(Instance->ModuleDataGetter());
405 auto InstrData = DynExp::dynamic_InstrumentData_cast<DynExpInstr::Spectrometer>(ModuleData->GetSpectrometer()->GetInstrumentData());
406
407 if (Value > InstrData->GetCurrentLowerFrequency())
408 ModuleData->GetSpectrometer()->SetFrequencyRange(InstrData->GetCurrentLowerFrequency(), Value);
409 }
410
411 void SpectrumViewer::OnRecordAndSaveSpectrum(DynExp::ModuleInstance* Instance, std::string SaveDataFilename) const
412 {
413 {
414 auto ModuleData = DynExp::dynamic_ModuleData_cast<SpectrumViewer>(Instance->ModuleDataGetter());
415
416 if (ModuleData->CapturingState == DynExpInstr::SpectrometerData::CapturingStateType::Capturing)
417 return;
418
419 ModuleData->SpectrumRecordingPaused = false;
420 ModuleData->AutoSaveFilename = SaveDataFilename;
421 } // ModuleData unlocked here.
422
423 OnRunClicked(Instance, false);
424 }
425
427 {
428 auto ModuleData = DynExp::dynamic_ModuleData_cast<SpectrumViewer>(Instance->ModuleDataGetter());
429 ModuleData->SpectrumRecordingPaused = true;
430 }
431
433 {
434 auto ModuleData = DynExp::dynamic_ModuleData_cast<SpectrumViewer>(Instance->ModuleDataGetter());
435 ModuleData->SpectrumRecordingPaused = false;
436 }
437}
Implementation of a module to plot the spectrum stored in a spectrometer instrument.
Type describing a spectrum as acquired by the Spectrometer instrument.
@ Warning
The spectrometer is in a warning state, but still ready to acquire a spectrum.
@ Capturing
The spectrometer is currently acquiring a spectrum.
@ Error
The spectrometer is in an error state.
@ Ready
The spectrometer is ready to acquire a spectrum.
static const char * IntensityUnitTypeToStr(const IntensityUnitType &Unit)
Returns a descriptive string of a respective intensity unit to be e.g. used in plots.
std::chrono::milliseconds TimeType
Time type describing the spectrometer's times like its exposure time.
static const char * FrequencyUnitTypeToStr(const FrequencyUnitType &Unit)
Returns a descriptive string of a respective frequency unit to be e.g. used in plots.
@ Counts
Number of counts (arbitrary unit)
void ResetImpl(dispatch_tag< QModuleDataBase >) override final
SpectrumViewerWidget(SpectrumViewer &Owner, QModuleWidget *parent=nullptr)
void UpdateUI(Util::SynchronizedPointer< SpectrumViewerData > &ModuleData)
void InitializeUI(Util::SynchronizedPointer< SpectrumViewerData > &ModuleData)
DynExpInstr::SpectrometerData::TimeType CurrentExposureTime
void SetData(SampleDataType &&SampleData, DynExpInstr::SpectrometerData::TimeType ExposureTime)
void OnRunClicked(DynExp::ModuleInstance *Instance, bool) const
void OnExit(DynExp::ModuleInstance *Instance) const override final
This event is triggered right before the module thread terminates (not due to an exception,...
void OnUpperLimitChanged(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 OnStopClicked(DynExp::ModuleInstance *Instance, bool) const
void OnInit(DynExp::ModuleInstance *Instance) const override final
This event is triggered right before the module thread starts. Override it to lock instruments this m...
void OnPauseSpectrumRecording(DynExp::ModuleInstance *Instance) const
void ResetImpl(dispatch_tag< QModuleBase >) override final
void OnLowerLimitChanged(DynExp::ModuleInstance *Instance, double Value) const
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...
void UpdateUIChild(const ModuleBase::ModuleDataGetterType &ModuleDataGetter) override final
void SaveSpectrum(const SpectrumViewerWidget::SampleDataType &Spectrum, Util::SynchronizedPointer< SpectrumViewerData > &ModuleData)
SpectrumViewerWidget::SampleDataType ProcessSpectrum(DynExpInstr::SpectrometerData::SpectrumType &&Spectrum, Util::SynchronizedPointer< SpectrumViewerData > &ModuleData)
void OnSilentModeToggled(DynExp::ModuleInstance *Instance, bool Checked) const
void OnResumeSpectrumRecording(DynExp::ModuleInstance *Instance) const
void OnRecordAndSaveSpectrum(DynExp::ModuleInstance *Instance, std::string SaveDataFilename) const
void OnExposureTimeChanged(DynExp::ModuleInstance *Instance, int Value) const
static void Register(const ModuleBase &Listener, CallableT EventFunc)
Registers/Subscribes module Listener to the event with the event function EventFunc....
Definition Module.h:1028
static void Deregister(const ModuleBase &Listener)
Deregisters/unsubscribes module Listener from the event. Indirectly calls ModuleBase::RemoveRegistere...
Definition Module.h:1034
Refer to ParamsBase::dispatch_tag.
Definition Module.h:189
Defines data for a thread belonging to a ModuleBase instance. Refer to RunnableInstance.
Definition Module.h:793
const ModuleBase::ModuleDataGetterType ModuleDataGetter
Getter for module's data. Refer to ModuleBase::ModuleDataGetterType.
Definition Module.h:825
Refer to ParamsBase::dispatch_tag.
Definition Object.h:2018
const Object::ParamsGetterType ParamsGetter
Invoke to obtain the parameters (derived from ParamsBase) of Owner.
Definition Object.h:3671
void UnlockObject(LinkedObjectWrapperContainer< ObjectT > &ObjectWrapperContainer)
Unlocks an Object instance stored in the LinkedObjectWrapperContainer ObjectWrapperContainer....
Definition Object.h:3570
void LockObject(const ParamsBase::Param< ObjectLink< ObjectT > > &LinkParam, LinkedObjectWrapperContainer< ObjectT > &ObjectWrapperContainer, std::chrono::milliseconds Timeout=ObjectLinkBase::LockObjectTimeoutDefault)
Locks an Object instance referenced by a parameter LinkParam of type ParamsBase::Param< ObjectLink< O...
Definition Object.h:3554
const auto & GetOwner() const noexcept
Returns Owner.
Definition Object.h:3524
Logs events like errors and writes them immediately to a HTML file in a human-readable format....
Definition Util.h:1061
void Log(const std::string &Message, const ErrorType Type=ErrorType::Info, const size_t Line=0, const std::string &Function="", const std::string &File="", const int ErrorCode=0, const std::stacktrace &Trace={}) noexcept
Logs an event from information specified manually.
Definition Util.cpp:309
Holds a CallableMemberWrapper and invokes its callable when being destroyed.
Definition Util.h:494
Pointer to lock a class derived from ISynchronizedPointerLockable for synchronizing between threads....
Definition Util.h:170
Thrown when an operation timed out before it could be completed, especially used for locking shared d...
Definition Exception.h:261
constexpr auto DefaultQChartTheme
constexpr auto StatusBarWarningStyleSheet
constexpr auto StatusBarErrorStyleSheet
constexpr auto StatusBarBusyStyleSheet
DynExpErrorCodes
DynExp's error codes
Definition Exception.h:22
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.
DynExpInstr::SpectrometerData::IntensityUnitType IntensityUnit
DynExpInstr::SpectrometerData::FrequencyUnitType FrequencyUnit
std::string ToStr(DynExpInstr::SpectrometerData::TimeType ExposureTime) const