29 std::vector<DynExpInstr::DataStreamBase::BasicSampleListType> BasicSamplesSeries;
37 ProcessedSamples.resize(
ModuleData->GetDataStreamInstrCount());
45 for (
size_t i = 0; i < ProcessedSamples.size(); ++i)
47 ProcessedSamples[i].Visible =
ModuleData->SampleDataList.size() == ProcessedSamples.size() ?
ModuleData->SampleDataList[i].Visible :
true;
48 if (!ProcessedSamples[i].Visible)
50 BasicSamplesSeries.push_back({});
56 auto InstrData = DynExp::dynamic_InstrumentData_cast<DynExpInstr::DataStreamInstrument>(
ModuleData->GetDataStreamInstr(i)->GetInstrumentData());
57 auto SampleStream = InstrData->GetSampleStream();
59 if (!
ModuleData->RollingView || !SampleStream->SeekEqual(std::ios_base::in))
60 SampleStream->SeekBeg(std::ios_base::in);
62 BasicSamplesSeries.emplace_back(SampleStream->ReadBasicSamples(SampleStream->GetStreamSizeRead()));
81 for (
size_t i = 0; i < ProcessedSamples.size(); ++i)
82 PlotInfo.
ProcessBasicSamples(std::move(BasicSamplesSeries[i]), ProcessedSamples[i].Samples, i);
88 ModuleData->SampleDataList = std::move(ProcessedSamples);
97 for (
size_t i = 0; i < ProcessedSamples.size(); ++i)
124 auto Backend = GetBackend<SignalPlotterBackend>();
125 auto ModuleData = DynExp::dynamic_ModuleData_cast<SignalPlotter>(ModuleDataGetter());
130 Backend->SetRollingView(
ModuleData->RollingView);
133 for (
const auto& InstrLabel :
ModuleData->GetDataStreamInstrLabels())
134 Backend->GetGraph()->InsertSeries(QString::fromStdString(InstrLabel));
142 for (
size_t i = 0; i <
ModuleData->GetDataStreamInstrCount(); ++i)
144 auto& SampleData =
ModuleData->SampleDataList.at(i);
145 auto& Series = Backend->GetGraph()->UpdateSeries(i, SampleData.Samples,
ModuleData->PlotInfo,
ModuleData->Running);
147 SampleData.Visible = Series.Visible;
156 auto ModuleParams = DynExp::dynamic_Params_cast<SignalPlotter>(Instance->
ParamsGetter());
159 ModuleData->LockInstruments(Instance, ModuleParams->DataStreamInstr);
162 for (
size_t i = 1; i <
ModuleData->GetDataStreamInstrCount(); ++i)
171 ModuleData->RollingView = ModuleParams->RollingView.Get();
172 ModuleData->Autoscale = ModuleParams->Autoscale.Get();
188 for (
size_t i = 0; i <
ModuleData->SampleDataList.size(); ++i)
191 ModuleData->GetDataStreamInstr(i)->ResetStreamSize();
198 auto ModuleParams = DynExp::dynamic_Params_cast<SignalPlotter>(
GetNonConstParams());
201 ModuleParams->RollingView = State;
207 auto ModuleParams = DynExp::dynamic_Params_cast<SignalPlotter>(
GetNonConstParams());
210 ModuleParams->Autoscale = State;
218 for (
size_t i = 0; i <
ModuleData->SampleDataList.size(); ++i)
222 auto InstrData = DynExp::dynamic_InstrumentData_cast<DynExpInstr::DataStreamInstrument>(
ModuleData->GetDataStreamInstr(i)->GetInstrumentData());
224 InstrData->GetSampleStream()->Clear();
238 if (Filename.isEmpty())
241 std::stringstream CSVData;
246 std::vector<std::pair<SampleIteratorType, SampleIteratorType>> SeriesIterators;
247 auto HeaderIterator =
ModuleData->GetDataStreamInstrLabels().cbegin();
251 for (
const auto& Series :
ModuleData->SampleDataList)
253 std::string Header(*HeaderIterator++);
258 SeriesIterators.emplace_back(Series.Samples.cbegin(), Series.Samples.cend());
260 Header = Object::RemoveCategoryAndName(Header);
261 std::erase_if(Header, [](
char c) {
return c ==
' ' || c ==
'_' || c ==
';'; });
262 CSVData <<
"X_" << Header << XUnit <<
";Y_" << Header << YUnit <<
";";
266 while (std::any_of(SeriesIterators.cbegin(), SeriesIterators.cend(), [](
auto& IteratorPair) { return IteratorPair.first != IteratorPair.second; }))
268 for (
auto& IteratorPair : SeriesIterators)
270 if (IteratorPair.first != IteratorPair.second)
272 CSVData << IteratorPair.first->x() / std::pow(10.0,
ModuleData->PlotInfo.Multiplier) <<
";" << IteratorPair.first->y() <<
";";
273 ++IteratorPair.first;
284 QMessageBox::warning(
GetWidget(),
"DynExp - Error",
"Error writing data to file.");
C++ backend of the SignalPlotter QML module.
Implementation of a module to plot the samples stored in data stream instruments.
void runningChanged(bool)
void rollingViewChanged(bool)
void autoscaleChanged(bool)
void ResetImpl(dispatch_tag< QMLModuleDataBase >) override final
QList< QPointF > Samples
Data points of a single data series to plot.
std::vector< SampleDataType > SampleDataList
Graph::LineGraphPlotInfo PlotInfo
void OnRollingViewChanged(DynExp::ModuleInstance *Instance, bool State) 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 OnExit(DynExp::ModuleInstance *Instance) const override final
This event is triggered right before the module thread terminates (not due to an exception,...
void OnAutoscaleChanged(DynExp::ModuleInstance *Instance, bool State) const
void OnRunningChanged(DynExp::ModuleInstance *Instance, bool State) const
std::atomic_bool IsSavingData
If data is currently being saved to file, do not update internal data.
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 MakeConnections(QObject *Backend) override final
Use QModuleBase::Connect() to connect Qt QML signals to the module's event functions.
size_t NumFailedUpdateAttempts
void FinishedSavingData() const noexcept
void UpdateUIChild(const ModuleBase::ModuleDataGetterType &ModuleDataGetter) override final
void ResetImpl(dispatch_tag< QMLModuleBase >) override final
QObject SignalContext
Does nothing but ensures that this module's Qt connections are disconnected when SignalContext is des...
void OnClearStream(DynExp::ModuleInstance *Instance) const
ModuleDataTypeSyncPtrType GetModuleData(const std::chrono::milliseconds Timeout=GetModuleDataTimeoutDefault)
Locks the mutex of the module data class instance ModuleData assigned to this ModuleBase instance and...
const std::unique_ptr< ModuleDataType > ModuleData
Module data belonging to this ModuleBase instance.
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.
ParamsTypeSyncPtrType GetNonConstParams(const std::chrono::milliseconds Timeout=GetParamsTimeoutDefault) const
Allows derived Objects to edit their own parameters - even in const task functions (for instruments) ...
void EnsureCallFromOwningThread() const
Asserts that the call to this function is performed from the thread which constructed this Object ins...
Refer to ParamsBase::dispatch_tag.
WidgetType * GetWidget() const
Getter for Widget.
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....
const Object::ParamsGetterType ParamsGetter
Invoke to obtain the parameters (derived from ParamsBase) of Owner.
const auto & GetOwner() const noexcept
Returns Owner.
std::atomic< bool > Running
Indicates whether the RunnableObject instance is running.
Holds a CallableMemberWrapper and invokes its callable when being destroyed.
Thrown when an operation timed out before it could be completed, especially used for locking shared d...
@ Arbitrary
Arbitrary units (a.u.)
const char * UnitTypeToStr(UnitType Unit)
Returns a descriptive string of the given unit's type (e.g. 'dBm').
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 ...
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.
DynExp::Units::UnitType XUnit
Joint unit of the plot's x axis.
void AdjustAxesLimits()
Adjusts MinValues and MaxValues to best display all data series.
void ReprocessSamples(const QList< QPointF > &Samples, const size_t SeriesIndex)
If data plotting is not enabled (running), the available and already plotted samples have to be repro...
void ResetHoveredSample()
Removes the stored hovered sample.
void Reset()
Resets the instance to generate information from new sample series.
bool ProcessBasicSamples(DynExpInstr::DataStreamBase::BasicSampleListType BasicSamples, QList< QPointF > &Samples, const size_t SeriesIndex)
Converts BasicSamples to displayable format and stores their minimal and maximal values in this DynEx...
void GenerateSampleTimingInfo(std::vector< DynExpInstr::DataStreamBase::BasicSampleListType > &BasicSamplesSeries)
Extracts sample timing information for x axis scaling from BasicSamples and stores the results in thi...