4#include "moc_SpectrumViewer.cpp"
5#include "ui_SpectrumViewer.h"
11 : QModuleWidget(Owner, parent),
13 DataSeries(nullptr), DataChart(nullptr), XAxis(nullptr), YAxis(nullptr)
18 this->addAction(
ui->action_Run);
19 this->addAction(
ui->action_Stop);
23 ui->Spectrum->setRenderHint(QPainter::Antialiasing);
30 ui->SBExposureTime->setRange(ModuleData->MinExposureTime.count(), ModuleData->MaxExposureTime.count());
31 ui->SBExposureTime->setSuffix(
" " + QString::fromStdString(Util::ToUnitStr<DynExpInstr::SpectrometerData::TimeType>()));
32 ui->SBLowerFrequency->setRange(ModuleData->MinFrequency, ModuleData->MaxFrequency);
34 ui->SBUpperFrequency->setRange(ModuleData->MinFrequency, ModuleData->MaxFrequency);
48 XAxis =
new QValueAxis(
this);
49 YAxis =
new QValueAxis(
this);
51 XAxis->setLabelFormat(
"%d");
53 YAxis->setLabelFormat(
"%d");
70 const QSignalBlocker Blocker(
ui->action_SilentMode);
71 ui->action_SilentMode->setChecked(ModuleData->SilentModeEnabled);
74 if (!
ui->SBExposureTime->hasFocus())
76 const QSignalBlocker Blocker(
ui->SBExposureTime);
77 ui->SBExposureTime->setValue(ModuleData->CurrentExposureTime.count());
80 if (!
ui->SBLowerFrequency->hasFocus())
82 const QSignalBlocker Blocker(
ui->SBLowerFrequency);
83 ui->SBLowerFrequency->setValue(ModuleData->CurrentLowerFrequency);
86 if (!
ui->SBUpperFrequency->hasFocus())
88 const QSignalBlocker Blocker(
ui->SBUpperFrequency);
89 ui->SBUpperFrequency->setValue(ModuleData->CurrentUpperFrequency);
92 switch (ModuleData->CapturingState)
95 ui->LState->setText(
" Acquiring spectrum...");
99 ui->LState->setText(
" The spectrometer is in a warning state.");
103 ui->LState->setText(
" The spectrometer is in an error state.");
107 ui->LState->setText(
" Ready");
108 ui->LState->setStyleSheet(
"");
112 && ModuleData->CapturingProgress > 0);
113 ui->PBProgress->setValue(ModuleData->CapturingProgress > 0 ? Util::NumToT<int>(ModuleData->CapturingProgress) : 0);
155 if (Filename.isEmpty())
159 QMessageBox::warning(
this,
"DynExp - Error",
"Error writing data to file.");
175 std::stringstream CSVData;
176 CSVData << std::setprecision(6);
177 CSVData <<
"ExposureTime = " << ExposureTime.count() <<
" " << Util::ToUnitStr<DynExpInstr::SpectrometerData::TimeType>() <<
"\n";
178 CSVData <<
"HEADER_END\n";
182 for (
const auto& Sample : Points)
183 CSVData << Sample.x() <<
";" << Sample.y() <<
"\n";
185 return CSVData.str();
203 CurrentLowerFrequency = 0.0;
204 CurrentUpperFrequency = 0.0;
205 SilentModeEnabled =
false;
207 CapturingProgress = 0.0;
208 AutoSaveFilename.clear();
210 SpectrumRecordingPaused =
false;
212 UIInitialized =
false;
219 auto ModuleData = DynExp::dynamic_ModuleData_cast<SpectrumViewer>(Instance.
ModuleDataGetter());
220 auto InstrData = DynExp::dynamic_InstrumentData_cast<DynExpInstr::Spectrometer>(ModuleData->GetSpectrometer()->GetInstrumentData());
222 ModuleData->CurrentExposureTime = InstrData->GetCurrentExposureTime();
223 ModuleData->CurrentLowerFrequency = InstrData->GetCurrentLowerFrequency();
224 ModuleData->CurrentUpperFrequency = InstrData->GetCurrentUpperFrequency();
225 ModuleData->SilentModeEnabled = InstrData->GetSilentModeEnabled();
226 ModuleData->CapturingState = InstrData->GetCapturingState();
227 ModuleData->CapturingProgress = InstrData->GetCapturingProgress();
229 if (InstrData->HasSpectrum() && !ModuleData->SpectrumRecordingPaused)
231 ModuleData->CurrentSpectrum = ProcessSpectrum(InstrData->GetSpectrum(), ModuleData);
233 if (!ModuleData->CurrentSpectrum.Points.empty() && !ModuleData->AutoSaveFilename.empty())
235 if (ModuleData->GetCommunicator().valid())
236 ModuleData->GetCommunicator()->PostEvent(*
this,
FinishedEvent{});
238 ModuleData->AutoSaveFilename.clear();
242 NumFailedUpdateAttempts = 0;
246 if (NumFailedUpdateAttempts++ >= 3)
255 NumFailedUpdateAttempts = 0;
260 auto Widget = std::make_unique<SpectrumViewerWidget>(*
this);
274 auto Widget = GetWidget<SpectrumViewerWidget>();
275 auto ModuleData = DynExp::dynamic_ModuleData_cast<SpectrumViewer>(ModuleDataGetter());
277 if (!ModuleData->IsUIInitialized())
279 Widget->InitializeUI(ModuleData);
280 ModuleData->SetUIInitialized();
283 Widget->UpdateUI(ModuleData);
285 if (!ModuleData->CurrentSpectrum.Points.empty())
286 Widget->SetData(std::move(ModuleData->CurrentSpectrum), ModuleData->AcquisitionExposureTime);
293 TransformedSpectrum.
FrequencyUnit = Spectrum.GetFrequencyUnit();
294 TransformedSpectrum.
IntensityUnit = Spectrum.GetIntensityUnit();
296 if (!Spectrum.HasSpectrum())
297 return TransformedSpectrum;
299 double YMin(std::numeric_limits<double>::max()), YMax(std::numeric_limits<double>::lowest());
300 for (
const auto& Sample : Spectrum.GetSpectrum())
302 TransformedSpectrum.
Points.append({ Sample.first, Sample.second });
304 YMin = std::min(YMin, Sample.second);
305 YMax = std::max(YMax, Sample.second);
308 TransformedSpectrum.
MinValues = { Spectrum.GetSpectrum().begin()->first, YMin};
309 TransformedSpectrum.
MaxValues = { Spectrum.GetSpectrum().rbegin()->first, YMax};
311 if (!TransformedSpectrum.
Points.empty() && !ModuleData->AutoSaveFilename.empty())
312 SaveSpectrum(TransformedSpectrum, ModuleData);
314 return TransformedSpectrum;
320 if (!
Util::SaveToFile(QString::fromStdString(ModuleData->AutoSaveFilename), Spectrum.
ToStr(ModuleData->CurrentExposureTime)))
333 auto ModuleParams = DynExp::dynamic_Params_cast<SpectrumViewer>(Instance->
ParamsGetter());
334 auto ModuleData = DynExp::dynamic_ModuleData_cast<SpectrumViewer>(Instance->
ModuleDataGetter());
336 Instance->
LockObject(ModuleParams->Spectrometer, ModuleData->GetSpectrometer());
337 if (ModuleParams->Communicator.ContainsID())
338 Instance->
LockObject(ModuleParams->Communicator, ModuleData->GetCommunicator());
340 ModuleData->FrequencyUnit = ModuleData->GetSpectrometer()->GetFrequencyUnit();
341 ModuleData->IntensityUnit = ModuleData->GetSpectrometer()->GetIntensityUnit();
342 ModuleData->MinFrequency = ModuleData->GetSpectrometer()->GetMinFrequency();
343 ModuleData->MaxFrequency = ModuleData->GetSpectrometer()->GetMaxFrequency();
345 auto InstrData = DynExp::dynamic_InstrumentData_cast<DynExpInstr::Spectrometer>(ModuleData->GetSpectrometer()->GetInstrumentData());
346 ModuleData->MinExposureTime = InstrData->GetMinExposureTime();
347 ModuleData->MaxExposureTime = InstrData->GetMaxExposureTime();
352 auto ModuleData = DynExp::dynamic_ModuleData_cast<SpectrumViewer>(Instance->
ModuleDataGetter());
367 auto ModuleData = DynExp::dynamic_ModuleData_cast<SpectrumViewer>(Instance->
ModuleDataGetter());
372 ModuleData->SpectrumRecordingPaused =
false;
373 ModuleData->AcquisitionExposureTime = ModuleData->CurrentExposureTime;
374 ModuleData->GetSpectrometer()->Record();
379 auto ModuleData = DynExp::dynamic_ModuleData_cast<SpectrumViewer>(Instance->
ModuleDataGetter());
381 ModuleData->SpectrumRecordingPaused =
false;
382 ModuleData->AutoSaveFilename.clear();
383 ModuleData->GetSpectrometer()->Abort();
388 auto ModuleData = DynExp::dynamic_ModuleData_cast<SpectrumViewer>(Instance->
ModuleDataGetter());
390 ModuleData->GetSpectrometer()->SetSilentMode(Checked);
395 auto ModuleData = DynExp::dynamic_ModuleData_cast<SpectrumViewer>(Instance->
ModuleDataGetter());
402 auto ModuleData = DynExp::dynamic_ModuleData_cast<SpectrumViewer>(Instance->
ModuleDataGetter());
403 auto InstrData = DynExp::dynamic_InstrumentData_cast<DynExpInstr::Spectrometer>(ModuleData->GetSpectrometer()->GetInstrumentData());
405 if (Value < InstrData->GetCurrentUpperFrequency())
406 ModuleData->GetSpectrometer()->SetFrequencyRange(Value, InstrData->GetCurrentUpperFrequency());
411 auto ModuleData = DynExp::dynamic_ModuleData_cast<SpectrumViewer>(Instance->
ModuleDataGetter());
412 auto InstrData = DynExp::dynamic_InstrumentData_cast<DynExpInstr::Spectrometer>(ModuleData->GetSpectrometer()->GetInstrumentData());
414 if (Value > InstrData->GetCurrentLowerFrequency())
415 ModuleData->GetSpectrometer()->SetFrequencyRange(InstrData->GetCurrentLowerFrequency(), Value);
420 auto ModuleData = DynExp::dynamic_ModuleData_cast<SpectrumViewer>(Instance->
ModuleDataGetter());
423 ModuleData->AutoSaveFilename = SaveFilename +
".csv";
428 OnRunClicked(Instance,
false);
433 OnStopClicked(Instance,
false);
438 auto ModuleData = DynExp::dynamic_ModuleData_cast<SpectrumViewer>(Instance->
ModuleDataGetter());
439 ModuleData->SpectrumRecordingPaused =
true;
444 auto ModuleData = DynExp::dynamic_ModuleData_cast<SpectrumViewer>(Instance->
ModuleDataGetter());
445 ModuleData->SpectrumRecordingPaused =
false;
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)
This event signals that an action (like a measurement) started by a TriggerEvent has been completed.
void ResetImpl(dispatch_tag< QModuleDataBase >) override final
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 OnTrigger(DynExp::ModuleInstance *Instance) const
void OnSetFilename(DynExp::ModuleInstance *Instance, const std::string &SaveFilename) const
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 OnStop(DynExp::ModuleInstance *Instance) const
void OnResumeSpectrumRecording(DynExp::ModuleInstance *Instance) const
void OnExposureTimeChanged(DynExp::ModuleInstance *Instance, int Value) const
static void Register(const ModuleBase &Listener, CallableT EventFunc, ItemIDType CommunicatorID=ItemIDNotSet)
Registers/Subscribes module Listener to the event with the event function EventFunc....
static void Deregister(const ModuleBase &Listener)
Deregisters/unsubscribes module Listener from the event, regardless of the inter-module communicator ...
Refer to ParamsBase::dispatch_tag.
Defines data for a thread belonging to a ModuleBase instance. Refer to RunnableInstance.
const ModuleBase::ModuleDataGetterType ModuleDataGetter
Getter for module's data. Refer to ModuleBase::ModuleDataGetterType.
Refer to ParamsBase::dispatch_tag.
const Object::ParamsGetterType ParamsGetter
Invoke to obtain the parameters (derived from ParamsBase) of Owner.
void UnlockObject(LinkedObjectWrapperContainer< ObjectT > &ObjectWrapperContainer)
Unlocks an Object instance stored in the LinkedObjectWrapperContainer ObjectWrapperContainer....
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...
const auto & GetOwner() const noexcept
Returns Owner.
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.
Holds a CallableMemberWrapper and invokes its callable when being destroyed.
Pointer to lock a class derived from ISynchronizedPointerLockable for synchronizing between threads....
Thrown when an operation timed out before it could be completed, especially used for locking shared d...
constexpr auto DefaultQChartTheme
constexpr auto StatusBarWarningStyleSheet
constexpr auto StatusBarErrorStyleSheet
constexpr auto StatusBarBusyStyleSheet
DynExpErrorCodes
DynExp's error codes
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 ...
EventLogger & EventLog()
This function holds a static EventLogger instance and returns a reference to it. DynExp uses only one...
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....
Accumulates include statements to provide a precompiled header.