16 #include "Base/Util/Assert.h"
20 #include "Param/Distrib/Distributions.h"
22 #include <QVBoxLayout>
24 #include <qcustomplot.h>
28 const QPair<double, double> default_xrange(-0.1, 0.1);
29 const QPair<double, double> default_yrange(0.0, 1.1);
31 QPair<double, double> xRangeForValue(
double value);
32 QPair<double, double> xRangeForValues(
double value1,
double value2);
33 QPair<double, double> xRangeForValues(
const QVector<double>& xvec);
34 QPair<double, double> yRangeForValues(
const QVector<double>& yvec);
35 double optimalBarWidth(
double xmin,
double xmax,
int nbars = 1);
41 , m_plot(new QCustomPlot)
44 , m_resetAction(new QAction(this))
47 setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
52 m_label->setAlignment(Qt::AlignVCenter | Qt::AlignLeft);
53 m_label->setStyleSheet(
"background-color:white;");
56 auto* mainLayout =
new QVBoxLayout;
57 mainLayout->setMargin(0);
58 mainLayout->setSpacing(0);
59 mainLayout->addWidget(
m_plot, 1);
61 m_plot->setAttribute(Qt::WA_NoMousePropagation,
false);
62 setLayout(mainLayout);
64 setStyleSheet(
"background-color:white;");
85 }
catch (
const std::exception& ex) {
88 QString message = QString(
"Wrong parameters\n\n").append(QString::fromStdString(ex.what()));
99 QPoint point =
event->pos();
100 double xPos =
m_plot->xAxis->pixelToCoord(point.x());
101 double yPos =
m_plot->yAxis->pixelToCoord(point.y());
103 if (
m_plot->xAxis->range().contains(xPos) &&
m_plot->yAxis->range().contains(yPos)) {
104 QString text = QString(
"[x:%1, y:%2]").arg(xPos).arg(yPos);
111 if (event->button() == Qt::RightButton) {
112 QPoint point =
event->globalPos();
136 m_plot->clearPlottables();
137 m_plot->setInteractions(QCP::iRangeDrag | QCP::iRangeZoom | QCP::iSelectAxes
138 | QCP::iSelectLegend | QCP::iSelectPlottables);
139 m_plot->yAxis->setLabel(
"probability");
140 m_plot->xAxis2->setVisible(
true);
141 m_plot->yAxis2->setVisible(
true);
142 m_plot->xAxis2->setTickLabels(
false);
143 m_plot->yAxis2->setTickLabels(
false);
144 m_plot->xAxis2->setTicks(
false);
145 m_plot->yAxis2->setTicks(
false);
167 QVector<double> xPos = QVector<double>() << value;
168 QVector<double> yPos = QVector<double>() << 1.0;
171 plotVerticalLine(value, default_yrange.first, value, default_yrange.second);
178 size_t numberOfSamples =
m_item->numberOfSamples();
179 double sigmafactor(0.0);
181 sigmafactor =
m_item->sigmaFactor();
188 std::vector<double> xp =
189 dist->equidistantPoints(numberOfSamples, sigmafactor,
m_item->
limits());
190 std::vector<double> yp(xp.size());
191 std::transform(xp.begin(), xp.end(), yp.begin(),
192 [&](
double value) { return dist->probabilityDensity(value); });
193 double sumOfWeights = std::accumulate(yp.begin(), yp.end(), 0.0);
194 ASSERT(sumOfWeights != 0.0);
196 #if QT_VERSION >= QT_VERSION_CHECK(5, 14, 0)
197 QVector<double> xBar(xp.begin(), xp.end());
199 QVector<double> xBar = QVector<double>::fromStdVector(xp);
202 QVector<double> yBar(xBar.size());
203 std::transform(yp.begin(), yp.end(), yBar.begin(),
204 [&](
double value) { return value / sumOfWeights; });
209 auto xRange = xRangeForValues(xBar);
210 const int number_of_points = 400;
211 std::vector<double> xf =
212 dist->equidistantPointsInRange(number_of_points, xRange.first, xRange.second);
213 std::vector<double> yf(xf.size());
214 std::transform(xf.begin(), xf.end(), yf.begin(),
215 [&](
double value) { return dist->probabilityDensity(value); });
217 #if QT_VERSION >= QT_VERSION_CHECK(5, 14, 0)
218 QVector<double> xFunc(xf.begin(), xf.end());
220 QVector<double> xFunc = QVector<double>::fromStdVector(xf);
222 QVector<double> yFunc(xFunc.size());
223 std::transform(yf.begin(), yf.end(), yFunc.begin(),
224 [&](
double value) { return value / sumOfWeights; });
230 const QPair<double, double>& yRange)
232 m_xRange = QCPRange(xRange.first, xRange.second);
233 m_yRange = QCPRange(yRange.first, yRange.second);
240 ASSERT(!xbars.empty());
242 auto xRange = xRangeForValues(xbars);
243 auto yRange = yRangeForValues(ybars);
246 double barWidth(0.0);
247 if (xbars.size() == 1)
248 barWidth = optimalBarWidth(xRange.first, xRange.second, xbars.size());
250 barWidth = optimalBarWidth(xbars.front(), xbars.back(), xbars.size());
254 bars->setWidth(barWidth);
255 bars->setData(xbars, ybars);
260 auto xRange = xRangeForValues(xFunc);
261 auto yRange = yRangeForValues(yFunc);
265 m_plot->graph(0)->setData(xFunc, yFunc);
271 auto* line =
new QCPItemLine(
m_plot);
273 QPen pen(color, 1, Qt::DashLine);
275 line->setSelectable(
true);
277 line->start->setCoords(xMin, yMin);
278 line->end->setCoords(xMax, yMax);
285 if (limits.hasLowerLimit()) {
286 double value = limits.lowerLimit();
287 plotVerticalLine(value, default_yrange.first, value, default_yrange.second, Qt::red);
290 if (limits.hasUpperLimit()) {
291 double value = limits.upperLimit();
292 plotVerticalLine(value, default_yrange.first, value, default_yrange.second, Qt::red);
298 m_plot->xAxis->setLabel(xAxisName);
309 QPair<double, double> xRangeForValue(
double value)
311 const double range_factor(0.1);
313 double dr = (value == 0.0 ? 1.0 * range_factor : std::abs(value) * range_factor);
314 double xmin = value - dr;
315 double xmax = value + dr;
317 return QPair<double, double>(xmin, xmax);
322 QPair<double, double> xRangeForValues(
double value1,
double value2)
324 const double range_factor(0.1);
325 double dr = (value2 - value1) * range_factor;
328 return QPair<double, double>(value1 - dr, value2 + dr);
331 QPair<double, double> xRangeForValues(
const QVector<double>& xvec)
333 ASSERT(!xvec.isEmpty());
334 return xvec.size() == 1 ? xRangeForValue(xvec.front())
335 : xRangeForValues(xvec.front(), xvec.back());
338 QPair<double, double> yRangeForValues(
const QVector<double>& yvec)
340 const double range_factor(1.1);
341 double ymax = *std::max_element(yvec.begin(), yvec.end());
342 return QPair<double, double>(default_yrange.first, ymax * range_factor);
347 double optimalBarWidth(
double xmin,
double xmax,
int nbars)
349 double optimalWidth = (xmax - xmin) / 40.;
350 double width = (xmax - xmin) / nbars;
352 return optimalWidth < width ? optimalWidth : width;
Defines class CautionSign.
Defines class DistributionItem and several subclasses.
Defines class DistributionPlot.
Defines class DoubleDescriptor.
The CautionSign controls appearance of CautionSignWidget on top of parent widget.
void clear()
Clears caution message;.
void setCautionMessage(const QString &cautionMessage)
Shows caution sign on the screen. If clear of previous caution sign had happened just few msec ago,...
virtual std::unique_ptr< IDistribution1D > createDistribution(double scale=1.0) const =0
RealLimits limits() const
bool hasSigmaFactor() const
void plotFunction(const QVector< double > &xFunc, const QVector< double > &yFunc)
void setShowMouseCoords(bool b)
void plotLimits(const RealLimits &limits)
Plots red line denoting lower and upper limits, if any.
void plotVerticalLine(double xMin, double yMin, double xMax, double yMax, const QColor &color=Qt::blue)
CautionSign * m_cautionSign
void plot_single_value()
Plots a single bar corresponding to the value in DistributionNoteItem.
void plot_distributions()
DistributionPlot(QWidget *parent=nullptr)
void onMouseMove(QMouseEvent *event)
Generates label with current mouse position.
void init_plot()
Clears all plottables, resets axes to initial state.
void plot_multiple_values()
void setXAxisName(const QString &xAxisName)
void plotBars(const QVector< double > &xbars, const QVector< double > &ybars)
DistributionItem * m_item
void setItem(DistributionItem *item)
void setPlotRange(const QPair< double, double > &xRange, const QPair< double, double > &yRange)
void onMousePress(QMouseEvent *event)
void resetView()
Reset zoom range to initial state.