Loading...
Searching...
No Matches
basetraceplotwidget.cpp
Go to the documentation of this file.
/* This code comes right from the msXpertSuite software project.
*
* msXpertSuite - mass spectrometry software suite
* -----------------------------------------------
* Copyright(C) 2009,...,2018 Filippo Rusconi
*
* http://www.msxpertsuite.org
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* END software license
*/
/////////////////////// StdLib includes
#include <vector>
/////////////////////// Qt includes
#include <QVector>
/////////////////////// Local includes
#include "basetraceplotwidget.h"
#include "pappsomspp/core/exception/exceptionnotpossible.h"
#include "pappsomspp/core/pappsoexception.h"
namespace pappso
{
BaseTracePlotWidget::BaseTracePlotWidget(QWidget *parent)
: BasePlotWidget(parent)
{
// We can afford to call createAllAncillaryItems() in this derived class
// because all the items will have been created *before* the addition of plots
// and then the rendering order will hide them to the viewer, since the
// rendering order is according to the order in which the items have been
// created.
//
// The fact that the ancillary items are created before trace plots is not a
// problem because the trace plots are sparse and do not effectively hide the
// data.
//
// But, in the color map plot widgets, we cannot afford to create the
// ancillary items *before* the plot itself because then, the rendering of the
// plot (created after) would screen off the ancillary items (created before).
//
// So, the createAllAncillaryItems() function needs to be called in the
// derived classes at the most appropriate moment in the setting up of the
// widget.
createAllAncillaryItems();
}
BaseTracePlotWidget::BaseTracePlotWidget(QWidget *parent,
const QString &x_axis_label,
const QString &y_axis_label)
: BasePlotWidget(parent, x_axis_label, y_axis_label)
{
// We can afford to call createAllAncillaryItems() in this derived class
// because all the items will have been created *before* the addition of plots
// and then the rendering order will hide them to the viewer, since the
// rendering order is according to the order in which the items have been
// created.
//
// The fact that the ancillary items are created before trace plots is not a
// problem because the trace plots are sparse and do not effectively hide the
// data.
//
// But, in the color map plot widgets, we cannot afford to create the
// ancillary items *before* the plot itself because then, the rendering of the
// plot (created after) would screen off the ancillary items (created before).
//
// So, the createAllAncillaryItems() function needs to be called in the
// derived classes at the most appropriate moment in the setting up of the
// widget.
createAllAncillaryItems();
}
//! Destruct \c this BaseTracePlotWidget instance.
/*!
The destruction involves clearing the history, deleting all the axis range
history items for x and y axes.
*/
BaseTracePlotWidget::~BaseTracePlotWidget()
{
}
void
BaseTracePlotWidget::setGraphData(int graph_index,
const std::vector<double> &keys,
const std::vector<double> &values)
{
QCPGraph *graph_p = graph(graph_index);
if(graph_p == nullptr)
qFatal("Programming error.");
return setGraphData(graph_p, keys, values);
}
void
BaseTracePlotWidget::setGraphData(QCPGraph *graph_p,
const std::vector<double> &keys,
const std::vector<double> &values)
{
if(graph_p == nullptr)
qFatal("Pointer cannot be nullptr.");
// Version that is now deprecated (20200924)
// graph_p->setData(QVector<double>::fromStdVector(keys),
// QVector<double>::fromStdVector(values));
QVector<double> key_qvector;
QVector<double> value_qvector;
#if 0
// Now replace the graph's data. Note that the data are
// inherently sorted (true below).
// The begin() -- end() ranges constructor did not work as of
// Qt 5.14.2 this day: 20200721
key_qvector =
QVector(keys.begin(),
keys.end());
value_qvector =
QVector(values.begin(),
values.end());
#endif
for(auto &value : keys)
key_qvector.push_back(value);
for(auto &value : values)
value_qvector.push_back(value);
graph_p->setData(key_qvector, value_qvector, true);
graph_p->setPen(m_pen);
rescaleAxes();
resetAxesRangeHistory();
replot();
}
void
BaseTracePlotWidget::clearGraphData(int graph_index)
{
QCPGraph *graph_p = graph(graph_index);
if(graph_p == nullptr)
qFatal("Programming error.");
graph_p->data().clear();
rescaleAxes();
resetAxesRangeHistory();
replot();
}
QCPGraph *
BaseTracePlotWidget::addTrace(const pappso::Trace &trace, const QColor &color)
{
// qDebug();
if(!color.isValid())
throw PappsoException(
QString("The color to be used for the plot graph is invalid."));
// This seems to be unpleasant.
// setFocus();
QCPGraph *graph_p = addGraph();
graph_p->setLayer("plotsLayer");
// Now depracated as of 20200924
// graph_p->setData(QVector<double>::fromStdVector(trace.xValues()),
// QVector<double>::fromStdVector(trace.yValues()));
QVector<double> key_qvector;
QVector<double> value_qvector;
#if 0
// Now replace the graph's data. Note that the data are
// inherently sorted (true below).
// The begin() -- end() ranges constructor did not work as of
// Qt 5.14.2 this day: 20200721
key_qvector =
QVector(trace.xValues().begin(),
.trace.xValues()end());
value_qvector =
QVector(trace.yValues().begin(),
trace.yValues().end());
#endif
for(auto &value : trace.xValues())
{
key_qvector.push_back(value);
}
for(auto &value : trace.yValues())
{
value_qvector.push_back(value);
}
#if 0
qDebug() << "The size of the x values for trace is:" << key_qvector.size()
<< "and for y values is:" << value_qvector.size();
QString text;
for(qsizetype iter = 0; iter < key_qvector.size(); ++iter)
text += QString("(%1,%2)\n")
.arg(key_qvector.at(iter), 0, 'f', 6)
.arg(value_qvector.at(iter), 0, 'f', 6);
qDebug().noquote() << text;
#endif
graph_p->setData(key_qvector, value_qvector, true);
QPen pen = graph()->pen();
pen.setColor(color);
graph()->setPen(pen);
// Connect the signal of selection change so that we can re-emit it for the
// widget that is using *this widget.
connect(graph_p,
static_cast<void (QCPAbstractPlottable::*)(bool)>(
&QCPAbstractPlottable::selectionChanged),
[this, graph_p]() {
emit plottableSelectionChangedSignal(graph_p, graph_p->selected());
});
// Rescaling the axes is actually unpleasant if there are more than one
// graph in the plot widget and that we are adding one. So only, rescale if
// the number of graphs is == 1, that is we are adding the first one.
if(graphCount() == 1)
{
rescaleAxes();
resetAxesRangeHistory();
}
replot();
return graph_p;
}
QCPBars *
BaseTracePlotWidget::addBars(const pappso::Trace &bars, const QColor &color)
{
qDebug();
if(!color.isValid())
throw PappsoException(
QString("The color to be used for the plot graph is invalid."));
// This seems to be unpleasant.
// setFocus();
QCPBars *bars_p = new QCPBars(xAxis, yAxis);
bars_p->setWidthType(QCPBars::WidthType::wtPlotCoords);
bars_p->setWidth(0.0005);
bars_p->setLayer("plotsLayer");
// Now depracated as of 20200924
// graph_p->setData(QVector<double>::fromStdVector(trace.xValues()),
// QVector<double>::fromStdVector(trace.yValues()));
std::vector<double> x_values = bars.xValues();
QVector<double> key_qvector;
key_qvector.assign(x_values.begin(), x_values.end());
std::vector<double> y_values = bars.yValues();
QVector<double> value_qvector;
value_qvector.assign(y_values.begin(), y_values.end());
qDebug() << "The size of the x values for trace is:" << key_qvector.size()
<< "and for y values is:" << value_qvector.size();
#if 0
qDebug() << "The size of the x values for trace is:" << key_qvector.size()
<< "and for y values is:" << value_qvector.size();
QString text;
for(qsizetype iter = 0; iter < key_qvector.size(); ++iter)
text += QString("(%1,%2)\n")
.arg(key_qvector.at(iter), 0, 'f', 6)
.arg(value_qvector.at(iter), 0, 'f', 6);
qDebug().noquote() << text;
#endif
bars_p->setData(key_qvector, value_qvector, true);
QPen pen = graph()->pen();
pen.setColor(color);
graph()->setPen(pen);
// Connect the signal of selection change so that we can re-emit it for the
// widget that is using *this widget.
connect(bars_p,
static_cast<void (QCPAbstractPlottable::*)(bool)>(
&QCPAbstractPlottable::selectionChanged),
[this, bars_p]() {
emit plottableSelectionChangedSignal(bars_p, bars_p->selected());
});
// Rescaling the axes is actually unpleasant if there are more than one
// graph in the plot widget and that we are adding one. So only, rescale if
// the number of graphs is == 1, that is we are adding the first one.
if(graphCount() == 1)
{
rescaleAxes();
resetAxesRangeHistory();
}
replot();
return bars_p;
}
//! Find a minimal integration range starting at an existing data point
/*!
If the user clicks onto a plot at a location that is not a true data point,
get a data range that begins at the preceding data point and that ends at
the clicked location point.
*/
bool
BaseTracePlotWidget::findIntegrationLowerRangeForKey(int index,
double key,
QCPRange &range)
{
// Given a key double value, we want to know what is the range that will
// frame correctly the key double value if that key value is not exactly
// the one of a point of the trace.
// First of all get the keys of the graph.
QCPGraph *theGraph = graph(index);
if(theGraph == nullptr)
throw ExceptionNotPossible(
"basetraceplotwidget.cpp @ indIntegrationLowerRangeForKey() -- ERROR "
"theGraph cannot be nullptr.");
// QCPGraphDataContainer is a typedef QCPDataContainer<QCPGraphData> and
// QCPDataContainer< DataType > is a Class Template. So in this context,
// DataType is QCPGraphData.
// QCPGraphData is the data point, that is the (key,value) pair.
QSharedPointer<QCPGraphDataContainer> graph_data_container_p =
theGraph->data();
QCPDataRange dataRange = graph_data_container_p->dataRange();
if(!dataRange.isValid())
return false;
if(!dataRange.size())
return false;
if(dataRange.size() > 1)
{
double firstKey = graph_data_container_p->at(dataRange.begin())->key;
double lastKey = graph_data_container_p->at(dataRange.end())->key;
// There is one check to be done: the user might erroneously set the mouse
// cursor beyond the last point of the graph. If that is the case, then
// upper key needs to be that very point. All we need to do is return the
// lower key, that is the pre-last key of the keys list. No need to
// iterate in the keys list.
if(key > lastKey)
{
// No need to search for the key in the keys, just get the lower key
// immediately, that is, the key that is one slot left the last key.
range.lower = graph_data_container_p->at(dataRange.end() - 2)->key;
range.upper = graph_data_container_p->at(dataRange.end() - 1)->key;
return true;
}
// Likewise, if the cursor is set left of the first plot point, then that
// will be the lower range point. All we need is to provide the upper
// range point as the second point of the plot.
if(key < firstKey)
{
range.lower = firstKey;
range.upper = graph_data_container_p->at(dataRange.begin() + 1)->key;
return true;
}
// Finally the generic case where the user point to any point *in* the
// graph.
range.lower =
graph_data_container_p->findBegin(key, /*expandedRange*/ true)->key;
range.upper =
std::prev(graph_data_container_p->findEnd(key, /*expandedRange*/ true))
->key;
return true;
}
return false;
}
std::vector<double>
BaseTracePlotWidget::getValuesX(int graph_index) const
{
std::vector<double> keys;
QCPGraph *graph_p = graph(graph_index);
if(graph_p == nullptr)
qFatal("Programming error.");
QSharedPointer<QCPGraphDataContainer> graph_data_container_p =
graph_p->data();
// Iterate in the keys
auto beginIt = graph_data_container_p->begin();
auto endIt = graph_data_container_p->end();
for(auto iter = beginIt; iter != endIt; ++iter)
keys.push_back(iter->key);
return keys;
}
std::vector<double>
BaseTracePlotWidget::getValuesY(int graph_index) const
{
std::vector<double> values;
QCPGraph *graph_p = graph(graph_index);
if(graph_p == nullptr)
qFatal("Programming error.");
QSharedPointer<QCPGraphDataContainer> graph_data_container_p =
graph_p->data();
// Iterate in the values
auto beginIt = graph_data_container_p->begin();
auto endIt = graph_data_container_p->end();
for(auto iter = beginIt; iter != endIt; ++iter)
values.push_back(iter->key);
return values;
}
QCPRange
BaseTracePlotWidget::getValueRangeOnKeyRange(QCPAbstractPlottable *plottable_p,
bool &ok)
{
// The X axis range is set. But we want to find for that X axis range the
// min and max Y values. This function is useful when the user asks that
// while changing the X axis range, the trace be always in full scale on the
// Y axis.
QCPRange key_range(xAxis->range().lower, xAxis->range().upper);
if(plottable_p != nullptr)
{
return plottable_p->getValueRange(ok, QCP::SignDomain::sdBoth, key_range);
}
else
{
// How many graphs are currently plotted in this plot widget ?
int graph_count = graphCount();
// Iterate in each graph and get the y max value. Then compare with the
// largest one and update if necessary. Store the pointer to the graph
// that has a larger y value. At the end of the iteration, it will be
// the winner.
double temp_min_value = std::numeric_limits<double>::max();
double temp_max_value = std::numeric_limits<double>::min();
bool found_range = false;
for(int iter = 0; iter < graph_count; ++iter)
{
QCPGraph *plottable_p = graph(iter);
QCPRange value_range =
plottable_p->getValueRange(ok, QCP::SignDomain::sdBoth, key_range);
if(ok)
found_range = true;
if(value_range.lower < temp_min_value)
temp_min_value = value_range.lower;
if(value_range.upper > temp_max_value)
temp_max_value = value_range.upper;
}
// At this point return the range.
ok = found_range;
return QCPRange(temp_min_value, temp_max_value);
}
}
QCPRange
BaseTracePlotWidget::getValueRangeOnKeyRange(int index, bool &ok)
{
// The X axis range is set. But we want to find for that X axis range the
// min and max Y values. This function is useful when the user asks that
// while changing the X axis range, the trace be always in full scale on the
// Y axis.
QCPAbstractPlottable *plottable_p = plottable(index);
if(plottable_p == nullptr)
qFatal("Programming error.");
return getValueRangeOnKeyRange(plottable_p, ok);
}
double
BaseTracePlotWidget::getYatX(double x, QCPGraph *graph_p)
{
if(graph_p == nullptr)
qFatal("Programming error.");
QCPItemTracer *tracer_p = new QCPItemTracer(this);
tracer_p->setGraph(graph_p);
tracer_p->setInterpolating(true);
tracer_p->setGraphKey(x);
tracer_p->updatePosition();
double value = tracer_p->position->value();
tracer_p->setGraph(nullptr);
// Essential to do this because otherwise crash when closing the app.
removeItem(tracer_p);
return value;
}
double
BaseTracePlotWidget::getYatX(double x, int index)
{
QCPGraph *graph_p = graph(index);
if(graph_p == nullptr)
qFatal("Programming error.");
return getYatX(x, graph_p);
}
void
BaseTracePlotWidget::axisDoubleClickHandler(
QCPAxis *axis,
[[maybe_unused]] QCPAxis::SelectablePart part,
QMouseEvent *event)
{
// qDebug();
m_context.m_keyboardModifiers = QGuiApplication::queryKeyboardModifiers();
if(m_context.m_keyboardModifiers & Qt::ControlModifier)
{
// qDebug();
// If the Ctrl modifiers is active, then both axes are to be reset. Also
// the histories are reset also.
rescaleAxes();
resetAxesRangeHistory();
}
else
{
// qDebug();
// Only the axis passed as parameter is to be rescaled.
// Reset the range of that axis to the max view possible, but for the y
// axis check if the Shift keyboard key is pressed. If so the full scale
// should be calculated only on the data in the current x range.
if(axis->orientation() == Qt::Vertical)
{
if(m_context.m_keyboardModifiers & Qt::ShiftModifier)
{
// In this case, we want to make a rescale of the Y axis such
// that it displays full scale the data in the current X axis
// range only.
bool ok = false;
QCPRange value_range = getValueRangeOnKeyRange(nullptr, ok);
yAxis->setRange(value_range);
}
else
axis->rescale();
}
else
axis->rescale();
updateAxesRangeHistory();
event->accept();
}
// The double-click event does not cancel the mouse press event. That is, if
// left-double-clicking, at the end of the operation the button still
// "pressed". We need to remove manually the button from the pressed buttons
// context member.
m_context.m_pressedMouseButtons ^= event->button();
updateContextXandYAxisRanges();
emit plotRangesChangedSignal((QMouseEvent *)nullptr, m_context);
replot();
}
void
BaseTracePlotWidget::axisRescale()
{
double xLower = xAxis->range().lower;
double xUpper = xAxis->range().upper;
// Get the current y lower/upper range.
double yLower = yAxis->range().lower;
double yUpper = yAxis->range().upper;
// This function is called only when the user has clicked on the x/y axis or
// when the user has dragged the left mouse button with the Ctrl key
// modifier. The m_context.m_wasClickOnXAxis is then simulated in the mouse
// move handler. So we need to test which axis was clicked-on.
if(m_context.m_wasClickOnXAxis)
{
// We are changing the range of the X axis.
// What is the x delta ?
double xDelta =
m_context.m_currentDragPoint.x() - m_context.m_startDragPoint.x();
// If xDelta is < 0, the we were dragging from right to left, we are
// compressing the view on the x axis, by adding new data to the right
// hand size of the graph. So we add xDelta to the upper bound of the
// range. Otherwise we are uncompressing the view on the x axis and
// remove the xDelta from the upper bound of the range. This is why we
// have the
// '-'
// and not '+' below;
// qDebug() << "Setting xaxis:" << xLower << "--" << xUpper - xDelta;
xAxis->setRange(xLower, xUpper - xDelta);
// Old version
// if(xDelta < 0)
//{
//// The dragging operation was from right to left, we are enlarging
//// the range (thus, we are unzooming the view, since the widget
//// always has the same size).
// xAxis->setRange(xLower, xUpper + fabs(xDelta));
//}
// else
//{
//// The dragging operation was from left to right, we are reducing
//// the range (thus, we are zooming the view, since the widget
//// always has the same size).
// xAxis->setRange(xLower, xUpper - fabs(xDelta));
//}
// We may either leave the scale of the Y axis as is (default) or
// the user may want an automatic scale of the Y axis such that the
// data displayed in the new X axis range are full scale on the Y
// axis. For this, the Shift modifier key should be pressed.
if(m_context.m_keyboardModifiers & Qt::ShiftModifier)
{
// In this case, we want to make a rescale of the Y axis such that
// it displays full scale the data in the current X axis range only.
bool ok = false;
QCPRange value_range = getValueRangeOnKeyRange(nullptr, ok);
yAxis->setRange(value_range);
}
// else, do leave the Y axis range unchanged.
}
// End of
// if(m_context.m_wasClickOnXAxis)
else // that is, if(m_context.m_wasClickOnYAxis)
{
// We are changing the range of the Y axis.
// What is the y delta ?
double yDelta =
m_context.m_currentDragPoint.y() - m_context.m_startDragPoint.y();
// See above for an explanation of the computation.
yAxis->setRange(yLower, yUpper - yDelta);
// Old version
// if(yDelta < 0)
//{
//// The dragging operation was from top to bottom, we are enlarging
//// the range (thus, we are unzooming the view, since the widget
//// always has the same size).
// yAxis->setRange(yLower, yUpper + fabs(yDelta));
//}
// else
//{
//// The dragging operation was from bottom to top, we are reducing
//// the range (thus, we are zooming the view, since the widget
//// always has the same size).
// yAxis->setRange(yLower, yUpper - fabs(yDelta));
//}
}
// End of
// else // that is, if(m_context.m_wasClickOnYAxis)
// Update the context with the current axes ranges
updateContextXandYAxisRanges();
emit plotRangesChangedSignal((QMouseEvent *)nullptr, m_context);
replot();
}
void
BaseTracePlotWidget::axisReframe()
{
// qDebug();
// double sorted_start_drag_point_x =
// std::min(m_context.m_startDragPoint.x(), m_context.m_currentDragPoint.x());
// xAxis->setRange(sorted_start_drag_point_x,
// sorted_start_drag_point_x + fabs(m_context.m_xDelta));
xAxis->setRange(
QCPRange(m_context.m_xRegionRangeStart, m_context.m_xRegionRangeStop));
// Note that the y axis should be rescaled from current lower value to new
// upper value matching the y-axis position of the cursor when the mouse
// button was released.
yAxis->setRange(xAxis->range().lower,
std::max<double>(m_context.m_yRegionRangeStart,
m_context.m_yRegionRangeStop));
// qDebug() << "xaxis:" << xAxis->range().lower << "-" <<
// xAxis->range().upper
//<< "yaxis:" << yAxis->range().lower << "-" << yAxis->range().upper;
// If the shift modifier key is pressed, then the user want the y axis
// to be full scale.
if(m_context.m_keyboardModifiers & Qt::ShiftModifier)
{
bool ok = false;
QCPRange value_range = getValueRangeOnKeyRange(nullptr, ok);
yAxis->setRange(value_range);
}
// else do nothing, let the y axis range as is.
updateContextXandYAxisRanges();
updateAxesRangeHistory();
emit plotRangesChangedSignal((QMouseEvent *)nullptr, m_context);
replot();
}
void
BaseTracePlotWidget::axisZoom()
{
// Use the m_context.m_xRegionRangeStart/End values, but we need to sort the
// values before using them, because now we want to really have the lower x
// value. Simply craft a QCPRange that will swap the values if lower is not
// < than upper QCustomPlot calls this normalization).
xAxis->setRange(
QCPRange(m_context.m_xRegionRangeStart, m_context.m_xRegionRangeStop));
// If the shift modifier key is pressed, then the user want the y axis
// to be full scale.
if(m_context.m_keyboardModifiers & Qt::ShiftModifier)
{
bool ok = false;
QCPRange value_range = getValueRangeOnKeyRange(nullptr, ok);
yAxis->setRange(value_range);
}
else
yAxis->setRange(
QCPRange(m_context.m_yRegionRangeStart, m_context.m_yRegionRangeStop));
updateContextXandYAxisRanges();
updateAxesRangeHistory();
emit plotRangesChangedSignal((QMouseEvent *)nullptr, m_context);
replot();
}
void
BaseTracePlotWidget::axisPan()
{
// qDebug();
// Sanity check
if(!m_context.m_wasClickOnXAxis && !m_context.m_wasClickOnYAxis)
qFatal(
"This function can only be called if the mouse click was on one of the "
"axes");
if(m_context.m_wasClickOnXAxis)
{
xAxis->setRange(m_context.m_xRange.lower - m_context.m_xDelta,
m_context.m_xRange.upper - m_context.m_xDelta);
// If the shift modifier key is pressed, then the user want the y axis
// to be full scale.
if(m_context.m_keyboardModifiers & Qt::ShiftModifier)
{
bool ok = false;
QCPRange value_range = getValueRangeOnKeyRange(nullptr, ok);
yAxis->setRange(value_range);
}
// else nothing to do we do not change the y axis scale.
}
if(m_context.m_wasClickOnYAxis)
{
yAxis->setRange(m_context.m_yRange.lower - m_context.m_yDelta,
m_context.m_yRange.upper - m_context.m_yDelta);
}
updateContextXandYAxisRanges();
// qDebug() << "The updated context:" << m_context.toString();
// We cannot store the new ranges in the history, because the pan operation
// involved a huge quantity of micro-movements elicited upon each mouse move
// cursor event so we would have a huge history.
// updateAxesRangeHistory();
// Now that the contex has the right range values, we can emit the
// signal that will be used by this plot widget users, typically to
// abide by the x/y range lock required by the user.
emit plotRangesChangedSignal((QMouseEvent *)nullptr, m_context);
replot();
}
pappso::Trace
BaseTracePlotWidget::toTrace(int index, bool only_visible_range) const
{
QCPGraph *graph_p = graph(index);
return toTrace(graph_p, only_visible_range);
}
pappso::Trace
BaseTracePlotWidget::toTrace(const QCPGraph *graph_p, bool only_visible_range) const
{
if(graph_p == nullptr)
qFatal("Programming error. Pointer cannot be nullptr.");
pappso::Trace trace;
if(only_visible_range)
{
// qDebug() << "Only visible range.";
QCPRange x_axis_range = xAxis->range();
// qDebug() << "Returning for visible range:" << x_axis_range;
return toTrace(x_axis_range, graph_p);
}
else
{
qDebug() << "Failed to get key range. Will return full key range.";
}
QSharedPointer<QCPGraphDataContainer> graph_data_container_p = graph_p->data();
// Iterate in the *all* the trace keys
auto beginIt = graph_data_container_p->begin();
auto endIt = graph_data_container_p->end();
for(auto iter = beginIt; iter != endIt; ++iter)
trace.push_back(pappso::DataPoint(iter->key, iter->value));
return trace;
}
pappso::Trace
BaseTracePlotWidget::toTrace(const QCPRange &x_axis_range, int index) const
{
QCPGraph *graph_p = graph(index);
if(graph_p == nullptr)
qFatal("Programming error.");
return toTrace(x_axis_range, graph_p);
}
pappso::Trace
BaseTracePlotWidget::toTrace(const QCPRange &x_axis_range,
const QCPGraph *graph_p) const
{
// qDebug() << "to Trace only key visible range:" << x_axis_range;
// Make a Trace with the data in the range.
Trace data_trace;
QSharedPointer<QCPGraphDataContainer> graph_data_container_sp;
graph_data_container_sp = graph_p->data();
// Grab the iterator to the start to the x axis range
// If expandedRange is true, the data point just
// below sortKey will be considered, otherwise the one just above.
auto beginIt = graph_data_container_sp->findBegin(x_axis_range.lower,
/*expandedRange*/ false);
// Grab the iterator to the end of the axis range
// If expandedRange is true, the data point just
// above sortKey will be considered, otherwise the
// one just below.
auto endIt = graph_data_container_sp->findEnd(x_axis_range.upper,
/*expandedRange*/ false);
for(auto iter = beginIt; iter != endIt; ++iter)
data_trace.push_back(DataPoint(iter->key, iter->value));
return data_trace;
}
pappso::Trace
BaseTracePlotWidget::toTrace(const QCPRange &x_axis_range, const QCPBars *bars_p) const
{
// qDebug() << "to Trace only key visible range:" << x_axis_range;
// Make a Trace with the data in the range.
Trace data_trace;
QSharedPointer<QCPBarsDataContainer> bars_data_container_sp;
bars_data_container_sp = bars_p->data();
// Grab the iterator to the start to the x axis range
// If expandedRange is true, the data point just
// below sortKey will be considered, otherwise the one just above.
auto beginIt = bars_data_container_sp->findBegin(x_axis_range.lower,
/*expandedRange*/ false);
// Grab the iterator to the end of the axis range
// If expandedRange is true, the data point just
// above sortKey will be considered, otherwise the
// one just below.
auto endIt = bars_data_container_sp->findEnd(x_axis_range.upper,
/*expandedRange*/ false);
for(auto iter = beginIt; iter != endIt; ++iter)
data_trace.push_back(DataPoint(iter->key, iter->value));
return data_trace;
}
} // namespace pappso
basetraceplotwidget.h
pappso::BasePlotWidget::updateAxesRangeHistory
virtual void updateAxesRangeHistory()
Create new axis range history items and append them to the history.
Definition baseplotwidget.cpp:501
pappso::BasePlotWidget::plotRangesChangedSignal
void plotRangesChangedSignal(QMouseEvent *event, const pappso::BasePlotContext &context)
pappso::BasePlotWidget::createAllAncillaryItems
virtual void createAllAncillaryItems()
Definition baseplotwidget.cpp:215
pappso::BasePlotWidget::m_pen
QPen m_pen
Pen used to draw the graph and textual elements in the plot widget.
Definition baseplotwidget.h:367
pappso::BasePlotWidget::resetAxesRangeHistory
virtual void resetAxesRangeHistory()
Definition baseplotwidget.cpp:475
pappso::BasePlotWidget::BasePlotWidget
BasePlotWidget(QWidget *parent)
Definition baseplotwidget.cpp:49
pappso::BasePlotWidget::updateContextXandYAxisRanges
virtual void updateContextXandYAxisRanges()
Definition baseplotwidget.cpp:3302
pappso::BasePlotWidget::plottableSelectionChangedSignal
void plottableSelectionChangedSignal(QCPAbstractPlottable *plottable_p, bool selected)
pappso::BasePlotWidget::m_context
BasePlotContext m_context
Definition baseplotwidget.h:283
pappso::BaseTracePlotWidget::addBars
virtual QCPBars * addBars(const pappso::Trace &bars, const QColor &color)
Definition basetraceplotwidget.cpp:273
pappso::BaseTracePlotWidget::getValueRangeOnKeyRange
QCPRange getValueRangeOnKeyRange(QCPAbstractPlottable *plottable_p, bool &ok)
Definition basetraceplotwidget.cpp:489
pappso::BaseTracePlotWidget::findIntegrationLowerRangeForKey
virtual bool findIntegrationLowerRangeForKey(int index, double key, QCPRange &range)
Find a minimal integration range starting at an existing data point.
Definition basetraceplotwidget.cpp:361
pappso::BaseTracePlotWidget::axisDoubleClickHandler
virtual void axisDoubleClickHandler(QCPAxis *axis, QCPAxis::SelectablePart part, QMouseEvent *event) override
Definition basetraceplotwidget.cpp:595
pappso::BaseTracePlotWidget::axisRescale
virtual void axisRescale() override
RANGE-related functions.
Definition basetraceplotwidget.cpp:664
pappso::BaseTracePlotWidget::~BaseTracePlotWidget
virtual ~BaseTracePlotWidget()
Destruct this BaseTracePlotWidget instance.
Definition basetraceplotwidget.cpp:98
pappso::BaseTracePlotWidget::setGraphData
virtual void setGraphData(int graph_index, const std::vector< double > &keys, const std::vector< double > &values)
Definition basetraceplotwidget.cpp:103
pappso::BaseTracePlotWidget::getValuesY
std::vector< double > getValuesY(int index) const
Definition basetraceplotwidget.cpp:466
pappso::BaseTracePlotWidget::BaseTracePlotWidget
BaseTracePlotWidget(QWidget *parent=0)
Definition basetraceplotwidget.cpp:43
pappso::BaseTracePlotWidget::addTrace
virtual QCPGraph * addTrace(const pappso::Trace &trace, const QColor &color)
Definition basetraceplotwidget.cpp:177
pappso::BaseTracePlotWidget::getValuesX
std::vector< double > getValuesX(int index) const
Definition basetraceplotwidget.cpp:443
pappso::BaseTracePlotWidget::axisPan
virtual void axisPan() override
Definition basetraceplotwidget.cpp:865
pappso::BaseTracePlotWidget::axisZoom
virtual void axisZoom() override
Definition basetraceplotwidget.cpp:830
pappso::BaseTracePlotWidget::clearGraphData
virtual void clearGraphData(int graph_index)
Definition basetraceplotwidget.cpp:162
pappso::BaseTracePlotWidget::toTrace
pappso::Trace toTrace(int index, bool only_visible_range=false) const
Definition basetraceplotwidget.cpp:919
pappso::BaseTracePlotWidget::getYatX
double getYatX(double x, QCPGraph *graph_p)
Definition basetraceplotwidget.cpp:562
pappso::BaseTracePlotWidget::axisReframe
virtual void axisReframe() override
Definition basetraceplotwidget.cpp:783
pappso::ExceptionNotPossible
Definition exceptionnotpossible.h:29
pappso::PappsoException
Definition pappsoexception.h:41
pappso::Trace
A simple container of DataPoint instances.
Definition trace.h:152
pappso::Trace::xValues
std::vector< pappso_double > xValues() const
Definition trace.cpp:697
pappso::Trace::yValues
std::vector< pappso_double > yValues() const
Definition trace.cpp:711
exceptionnotpossible.h
pappso
tries to keep as much as possible monoisotopes, removing any possible C13 peaks and changes multichar...
Definition aa.cpp:39
pappso::PeptideIonCter::x
@ x
Definition peptide.h:92
pappsoexception.h
pappso::DataPoint
Definition datapoint.h:22