Quantum Phenomena Explorer 7.9.8
Interactive quantum-phenomena Explorer Tutor — source documentation
Loading...
Searching...
No Matches
quantumdriveplotwidget.cpp
Go to the documentation of this file.
1/**
2 * @file quantumdriveplotwidget.cpp
3 * @brief Implements the quantumdriveplotwidget visualization component used by QPE.
4 * @ingroup qpe_graphics
5 *
6 * Source: @c graphics/renderer/quantumdriveplotwidget.cpp. This file is part of Quantum Phenomena Explorer (QPE),
7 * maintained by Officina Turini. See LICENSE_IT.txt / LICENSE.txt for the
8 * QPE freeware source-available terms and THIRD_PARTY_NOTICES.txt for
9 * third-party components.
10 */
11
13
14#include <QPaintEvent>
15#include <QPainter>
16#include <QPainterPath>
17
18#include <algorithm>
19#include <cmath>
20#include <limits>
21
22namespace {
23const double Pi = 3.1415926535897932384626433832795;
24}
25
27 : QWidget(parent)
28{
29 setMinimumHeight(190);
30 setAutoFillBackground(false);
31}
32
34 const std::vector<qpe::ObservablesTimeSeries2DSample> &samples)
35{
36 samples_ = samples;
37 update();
38}
39
41 double amplitude,
42 double angularFrequency,
43 double phaseDegrees)
44{
45 meanValue_ = meanValue;
46 amplitude_ = amplitude;
47 angularFrequency_ = angularFrequency;
48 phaseRadians_ = phaseDegrees * Pi / 180.0;
49 update();
50}
51
53{
54 samples_.clear();
55 update();
56}
57
59{
60 return QSize(480, 190);
61}
62
63void QuantumDrivePlotWidget::paintEvent(QPaintEvent *event)
64{
65 Q_UNUSED(event);
66 QPainter painter(this);
67 painter.setRenderHint(QPainter::Antialiasing, true);
68 painter.setRenderHint(QPainter::TextAntialiasing, true);
69 painter.fillRect(rect(), QColor(15, 18, 23));
70
71 const QRectF plotRect(58.0, 28.0,
72 std::max(10.0, width() - 78.0),
73 std::max(10.0, height() - 66.0));
74 painter.setPen(QPen(QColor(78, 86, 96), 1.0));
75 for (int i = 0; i <= 4; ++i) {
76 const double u = static_cast<double>(i) / 4.0;
77 painter.drawLine(QPointF(plotRect.left() + u * plotRect.width(), plotRect.top()),
78 QPointF(plotRect.left() + u * plotRect.width(), plotRect.bottom()));
79 painter.drawLine(QPointF(plotRect.left(), plotRect.top() + u * plotRect.height()),
80 QPointF(plotRect.right(), plotRect.top() + u * plotRect.height()));
81 }
82 painter.setPen(QPen(QColor(170, 180, 190), 1.0));
83 painter.drawRect(plotRect);
84
85 double tMax = 8.0;
86 double xMaxAbs = std::max(1.0, std::abs(meanValue_) + std::abs(amplitude_));
87 double energyMin = std::numeric_limits<double>::infinity();
88 double energyMax = -std::numeric_limits<double>::infinity();
89 for (const qpe::ObservablesTimeSeries2DSample &sample : samples_) {
90 tMax = std::max(tMax, sample.time);
91 if (std::isfinite(sample.meanX)) xMaxAbs = std::max(xMaxAbs, std::abs(sample.meanX));
92 if (std::isfinite(sample.totalEnergy)) {
93 energyMin = std::min(energyMin, sample.totalEnergy);
94 energyMax = std::max(energyMax, sample.totalEnergy);
95 }
96 }
97 xMaxAbs *= 1.12;
98 if (!(energyMax > energyMin)) {
99 if (!std::isfinite(energyMin)) { energyMin = 0.0; energyMax = 1.0; }
100 else { energyMin -= 0.5; energyMax += 0.5; }
101 }
102 const double ePad = 0.10 * std::max(1.0e-6, energyMax - energyMin);
103 energyMin -= ePad;
104 energyMax += ePad;
105
106 const auto mapX = [plotRect, tMax](double t) {
107 return plotRect.left() + t / tMax * plotRect.width();
108 };
109 const auto mapPosition = [plotRect, xMaxAbs](double v) {
110 return plotRect.center().y() - v / xMaxAbs * 0.5 * plotRect.height();
111 };
112 const auto mapEnergy = [plotRect, energyMin, energyMax](double v) {
113 return plotRect.bottom() - (v - energyMin) / (energyMax - energyMin) * plotRect.height();
114 };
115
116 painter.setPen(QPen(QColor(125, 132, 142), 1.0, Qt::DashLine));
117 painter.drawLine(QPointF(plotRect.left(), mapPosition(0.0)),
118 QPointF(plotRect.right(), mapPosition(0.0)));
119
120 QPainterPath drivePath;
121 const int samples = 300;
122 for (int i = 0; i <= samples; ++i) {
123 const double t = tMax * static_cast<double>(i) / samples;
124 const double center = meanValue_ + amplitude_ * std::sin(angularFrequency_ * t + phaseRadians_);
125 const QPointF p(mapX(t), mapPosition(center));
126 if (i == 0) drivePath.moveTo(p); else drivePath.lineTo(p);
127 }
128 painter.setPen(QPen(QColor(175, 125, 255), 1.4, Qt::DashLine));
129 painter.drawPath(drivePath);
130
131 QPainterPath meanPath;
132 QPainterPath energyPath;
133 bool first = true;
134 for (const qpe::ObservablesTimeSeries2DSample &sample : samples_) {
135 const QPointF pm(mapX(sample.time), mapPosition(sample.meanX));
136 const QPointF pe(mapX(sample.time), mapEnergy(sample.totalEnergy));
137 if (first) {
138 meanPath.moveTo(pm);
139 energyPath.moveTo(pe);
140 first = false;
141 } else {
142 meanPath.lineTo(pm);
143 energyPath.lineTo(pe);
144 }
145 }
146 if (!first) {
147 painter.setPen(QPen(QColor(100, 220, 255), 2.2));
148 painter.drawPath(meanPath);
149 painter.setPen(QPen(QColor(255, 170, 105), 1.7));
150 painter.drawPath(energyPath);
151 } else {
152 painter.setPen(QColor(190, 195, 205));
153 painter.drawText(plotRect, Qt::AlignCenter,
154 QStringLiteral("Load a Driven Harmonic Trap and press Play"));
155 }
156
157 painter.setPen(QColor(210, 215, 222));
158 painter.drawText(QRectF(plotRect.left(), 2.0, plotRect.width(), 22.0),
159 Qt::AlignCenter,
160 QStringLiteral("Periodic drive: packet centre, trap centre and total energy"));
161 painter.setPen(QColor(100, 220, 255));
162 painter.drawText(QRectF(plotRect.left() + 8.0, plotRect.top() + 5.0, 90.0, 18.0),
163 Qt::AlignLeft, QStringLiteral("<x>"));
164 painter.setPen(QColor(175, 125, 255));
165 painter.drawText(QRectF(plotRect.left() + 52.0, plotRect.top() + 5.0, 120.0, 18.0),
166 Qt::AlignLeft, QStringLiteral("trap centre"));
167 painter.setPen(QColor(255, 170, 105));
168 painter.drawText(QRectF(plotRect.left() + 145.0, plotRect.top() + 5.0, 90.0, 18.0),
169 Qt::AlignLeft, QStringLiteral("<H>"));
170 painter.setPen(QColor(160, 168, 178));
171 painter.drawText(QRectF(plotRect.left(), plotRect.bottom() + 5.0,
172 plotRect.width(), 22.0),
173 Qt::AlignCenter, QStringLiteral("simulation time"));
174}
void paintEvent(QPaintEvent *event) override
Paints event.
void setDrive(double meanValue, double amplitude, double angularFrequency, double phaseDegrees)
Sets drive.
void setSamples(const std::vector< qpe::ObservablesTimeSeries2DSample > &samples)
Sets samples.
std::vector< qpe::ObservablesTimeSeries2DSample > samples_
QuantumDrivePlotWidget(QWidget *parent=nullptr)
Performs quantum drive plot widget.
QSize minimumSizeHint() const override
Performs minimum size hint.
Declares the quantumdriveplotwidget visualization component used by QPE.
Data record containing Observables Time Series2D Sample.