Math traces bugfixes + comments
This commit is contained in:
parent
cf31fd7908
commit
17454ebba2
@ -297,6 +297,8 @@ void Trace::fromMath()
|
||||
{
|
||||
source = Source::Math;
|
||||
clear();
|
||||
mathUpdateEnd = 0;
|
||||
mathUpdateBegin = numeric_limits<unsigned int>::max();
|
||||
updateMathTracePoints();
|
||||
scheduleMathCalculation(0, data.size());
|
||||
emit typeChanged(this);
|
||||
@ -386,10 +388,10 @@ bool Trace::resolveMathSourceHashes()
|
||||
return success;
|
||||
}
|
||||
|
||||
bool Trace::updateMathTracePoints()
|
||||
void Trace::updateMathTracePoints()
|
||||
{
|
||||
if(!mathSourceTraces.size()) {
|
||||
return false;
|
||||
return;
|
||||
}
|
||||
double startX = std::numeric_limits<double>::lowest();
|
||||
double stopX = std::numeric_limits<double>::max();
|
||||
@ -410,25 +412,20 @@ bool Trace::updateMathTracePoints()
|
||||
}
|
||||
}
|
||||
unsigned int samples = round((stopX - startX) / stepSize + 1);
|
||||
bool fullUpdate = false;
|
||||
// qDebug() << "Updated trace points, now"<<samples<<"points from"<<startX<<"to"<<stopX;
|
||||
if(samples != data.size()) {
|
||||
auto oldSize = data.size();
|
||||
data.resize(samples);
|
||||
fullUpdate = true;
|
||||
if(oldSize < samples) {
|
||||
for(unsigned int i=oldSize;i<samples;i++) {
|
||||
data[i].x = startX + i * stepSize;
|
||||
data[i].y = numeric_limits<complex<double>>::quiet_NaN();
|
||||
}
|
||||
}
|
||||
}
|
||||
if(samples > 0 && (startX != data.front().x || stopX != data.back().x)) {
|
||||
fullUpdate = true;
|
||||
}
|
||||
if(fullUpdate) {
|
||||
// steps changed, complete update required
|
||||
mathUpdateBegin = 0;
|
||||
mathUpdateEnd = samples;
|
||||
for(unsigned int i=0;i<samples;i++) {
|
||||
data[i].x = startX + i * stepSize;
|
||||
data[i].y = numeric_limits<complex<double>>::quiet_NaN();
|
||||
}
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@ -441,6 +438,7 @@ void Trace::mathSourceTraceDeleted(Trace *t)
|
||||
|
||||
void Trace::scheduleMathCalculation(unsigned int begin, unsigned int end)
|
||||
{
|
||||
// qDebug() << "Scheduling calculation from"<<begin<<"to"<<end;
|
||||
if(source != Source::Math) {
|
||||
return;
|
||||
}
|
||||
@ -462,6 +460,7 @@ void Trace::calculateMath()
|
||||
{
|
||||
lastMathUpdate = QTime::currentTime();
|
||||
if(mathUpdateBegin >= data.size() || mathUpdateEnd >= data.size() + 1) {
|
||||
qWarning() << "Not calculating math trace, out of limits. Requested from" << mathUpdateBegin << "to" << mathUpdateEnd <<" but data is of size" << data.size();
|
||||
return;
|
||||
}
|
||||
if(mathFormula.isEmpty()) {
|
||||
@ -573,8 +572,25 @@ bool Trace::addMathSource(Trace *t, QString variableName)
|
||||
connect(t, &Trace::dataChanged, this, [=](unsigned int begin, unsigned int end){
|
||||
updateMathTracePoints();
|
||||
auto startX = t->sample(begin).x;
|
||||
auto stopX = t->sample(end).x;
|
||||
scheduleMathCalculation(index(startX), index(stopX));
|
||||
auto stopX = t->sample(end-1).x;
|
||||
|
||||
// qDebug() << "Source update from"<<startX<<"to"<<stopX<<". Index from"<<begin<<"to"<<end;
|
||||
|
||||
auto calcIndex = [&](double x) -> int {
|
||||
if(data.size() == 0) {
|
||||
return 0;
|
||||
}
|
||||
auto lower = lower_bound(data.begin(), data.end(), x, [](const Data &lhs, const double x) -> bool {
|
||||
return lhs.x < x;
|
||||
});
|
||||
if(lower == data.end()) {
|
||||
// actually beyond the last sample, return the index of the last anyway to avoid access past data
|
||||
return data.size() - 1;
|
||||
}
|
||||
return lower - data.begin();
|
||||
};
|
||||
|
||||
scheduleMathCalculation(calcIndex(startX), calcIndex(stopX)+1);
|
||||
});
|
||||
return true;
|
||||
}
|
||||
@ -1050,6 +1066,28 @@ bool Trace::isVisible()
|
||||
return visible;
|
||||
}
|
||||
|
||||
bool Trace::canBePaused()
|
||||
{
|
||||
switch(source) {
|
||||
case Source::Live:
|
||||
return true;
|
||||
case Source::File:
|
||||
return false;
|
||||
case Source::Calibration:
|
||||
return false;
|
||||
case Source::Math:
|
||||
// depends on the math, if it depends on any live data, it may be paused
|
||||
for(auto ms : mathSourceTraces) {
|
||||
if(ms.first->canBePaused()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
void Trace::pause()
|
||||
{
|
||||
if(!paused) {
|
||||
|
@ -66,6 +66,7 @@ public:
|
||||
QString name() { return _name; }
|
||||
QColor color() { return _color; }
|
||||
bool isVisible();
|
||||
bool canBePaused();
|
||||
void pause();
|
||||
void resume();
|
||||
bool isPaused();
|
||||
@ -163,6 +164,9 @@ public:
|
||||
void setMathFormula(const QString &newMathFormula);
|
||||
bool mathFormularValid() const;
|
||||
|
||||
// When loading setups, some traces may be used as a math source before they are loaded.
|
||||
// If that happens, their hashes are added to a list. Call this function for every new trace
|
||||
// after all traces from the setup file have been created. It will look for the missing traces
|
||||
bool resolveMathSourceHashes();
|
||||
|
||||
public slots:
|
||||
@ -171,11 +175,23 @@ public slots:
|
||||
void addMarker(Marker *m);
|
||||
void removeMarker(Marker *m);
|
||||
|
||||
// functions for handling source == Source::Math
|
||||
// Functions for handling source == Source::Math
|
||||
|
||||
// Checks whether the trace data depends on trace t.
|
||||
// If onlyDirectDependency is true, only the direct math sources are checked (i.e. the math sources of this trace).
|
||||
// If onlyDirectDependency is false, math sources and all their sources are checked recursively
|
||||
bool mathDependsOn(Trace *t, bool onlyDirectDependency = false);
|
||||
// Checks whether a trace can potentially be used as a math source. It can not be used if:
|
||||
// - it is the trace itself
|
||||
// - it is in a different domain than an already used math source
|
||||
// - it depends on this trace
|
||||
bool canAddAsMathSource(Trace *t);
|
||||
// Adds another trace as a math source, with a custom variable name. The same trace may be added multiple times with
|
||||
// different names, older variable names will be replaced with the new one
|
||||
bool addMathSource(Trace *t, QString variableName);
|
||||
// Removes a trace as a math source (if its variable name is still used in the mathFormula, this will break the calculation)
|
||||
void removeMathSource(Trace *t);
|
||||
// Retrieves the variable name used for the specified trace. If the trace is not used as a math source, an emptry string is returned
|
||||
QString getSourceVariableName(Trace *t);
|
||||
|
||||
signals:
|
||||
@ -194,13 +210,25 @@ signals:
|
||||
private slots:
|
||||
void markerVisibilityChanged(Marker *m);
|
||||
|
||||
// functions for handling source == Source::Math
|
||||
bool updateMathTracePoints();
|
||||
void mathSourceTraceDeleted(Trace *t);
|
||||
void scheduleMathCalculation(unsigned int begin, unsigned int end);
|
||||
void calculateMath();
|
||||
void clearMathSources();
|
||||
// Functions for handling source == Source::Math
|
||||
|
||||
// Updates the datapoints, based on the available span of all math sources.
|
||||
// The least common span is used for this trace. This function only creates the datapoints
|
||||
// and sets the X coordinate. The Y coordinates are set in calculateMath()
|
||||
void updateMathTracePoints();
|
||||
// Keeps track of deleted traces and removes them from the math sources
|
||||
void mathSourceTraceDeleted(Trace *t);
|
||||
// Schedules an update of this trace, should be called whenever any source data changes.
|
||||
// As it is likely that multiple source traces will change directly after each other, no
|
||||
// calculation is performed directly. Instead the calculation is only scheduled and executed
|
||||
// shortly after. This prevents calculating data that will be overwritten immediately afterwards
|
||||
void scheduleMathCalculation(unsigned int begin, unsigned int end);
|
||||
// Actually calculates the Y coordinate values of this trace. It expects that the data vector is
|
||||
// already set up with the required amount of points and X coordinates
|
||||
void calculateMath();
|
||||
// Removes all math sources, use this when switching to a different source mode
|
||||
void clearMathSources();
|
||||
// Attempts to add a math source using the trace hash instead of a pointer (when loading setups)
|
||||
bool addMathSource(unsigned int hash, QString variableName);
|
||||
|
||||
private:
|
||||
@ -209,6 +237,10 @@ private:
|
||||
QColor _color;
|
||||
Source source;
|
||||
|
||||
// Hash for identifying the trace when loading/saving setup files.
|
||||
// When writing setup files, the hash is created from the JSON representation of the trace.
|
||||
// When loading setup files, the hash specified in the setup file is used (prevents different
|
||||
// hashes when the JSON format changes in newer versions)
|
||||
unsigned int hash;
|
||||
bool hashSet;
|
||||
bool JSONskipHash;
|
||||
|
@ -63,7 +63,7 @@ void TraceModel::toggleVisibility(unsigned int index)
|
||||
|
||||
void TraceModel::togglePause(unsigned int index)
|
||||
{
|
||||
if (index < traces.size()) {
|
||||
if (index < traces.size() && traces[index]->canBePaused()) {
|
||||
if(traces[index]->isPaused()) {
|
||||
traces[index]->resume();
|
||||
} else {
|
||||
@ -118,7 +118,7 @@ QVariant TraceModel::data(const QModelIndex &index, int role) const
|
||||
}
|
||||
break;
|
||||
case ColIndexPlayPause:
|
||||
if (role == Qt::DecorationRole && trace->getSource() == Trace::Source::Live) { // TODO trace needs function to check if it may change due to live data
|
||||
if (role == Qt::DecorationRole && trace->canBePaused()) {
|
||||
if (trace->isPaused()) {
|
||||
return QIcon(":/icons/pause.svg");
|
||||
} else {
|
||||
|
@ -530,6 +530,9 @@ void TraceWaterfall::traceDataChanged(unsigned int begin, unsigned int end)
|
||||
data.back()[i] = trace->sample(i);
|
||||
if(yAxis.getAutorange() && !YAxisUpdateRequired) {
|
||||
double val = yAxis.sampleToCoordinate(trace->sample(i));
|
||||
if(isnan(val) || isinf(val)) {
|
||||
continue;
|
||||
}
|
||||
if(val < min) {
|
||||
min = val;
|
||||
}
|
||||
|
@ -781,6 +781,11 @@ void TraceXYPlot::updateAxisTicks()
|
||||
continue;
|
||||
}
|
||||
|
||||
if(isnan(point.y()) || isinf(point.y())) {
|
||||
// skip NaN and Infty values
|
||||
continue;
|
||||
}
|
||||
|
||||
if(point.y() > max) {
|
||||
max = point.y();
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user