Quantum Phenomena Explorer 7.9.8
Interactive quantum-phenomena Explorer Tutor — source documentation
Loading...
Searching...
No Matches
quantumzenoplotwidget.cpp
Go to the documentation of this file.
1/**
2 * @file quantumzenoplotwidget.cpp
3 * @brief Implements the quantumzenoplotwidget visualization component used by QPE.
4 * @ingroup qpe_graphics
5 *
6 * Source: @c graphics/renderer/quantumzenoplotwidget.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
15
16#include <QPainter>
17#include <QPainterPath>
18#include <QPaintEvent>
19#include <QPen>
20#include <QString>
21
22#include <algorithm>
23#include <cmath>
24
26 : QWidget(parent)
27{
28 setAutoFillBackground(false);
29}
30
32 const qpe::QuantumZenoProfile2D &profile)
33{
34 history_ = &history;
35 profile_ = profile;
36 update();
37}
38
40{
41 history_ = nullptr;
43 update();
44}
45
47{
48 return QSize(620, 410);
49}
50
51void QuantumZenoPlotWidget::paintEvent(QPaintEvent *event)
52{
53 Q_UNUSED(event);
54 QPainter p(this);
55 p.setRenderHint(QPainter::Antialiasing, true);
56 p.setRenderHint(QPainter::TextAntialiasing, true);
57 p.fillRect(rect(), QColor(13, 17, 23));
58
59 const QColor text(210, 220, 230);
60 const QColor frame(70, 82, 94);
61 const QColor watched(80, 220, 235);
62 const QColor control(245, 170, 70);
63 const QColor boundary(235, 90, 105);
64
65 p.setPen(text);
66 p.drawText(QRect(8, 2, width() - 16, 20), Qt::AlignCenter,
67 QStringLiteral("Quantum Zeno effect: unmeasured escape vs repeatedly watched survival"));
68
69 const int marginL = 58;
70 const int marginR = 20;
71 const int top = 28;
72 const int gap = 38;
73 const int bottom = 30;
74 const int panelH = std::max(95, (height() - top - bottom - gap) / 2);
75 const QRect survivalRect(marginL, top,
76 std::max(20, width() - marginL - marginR), panelH);
77 const QRect profileRect(marginL, top + panelH + gap,
78 std::max(20, width() - marginL - marginR), panelH);
79
80 auto drawFrame = [&](const QRect &r, const QString &title) {
81 p.setPen(frame);
82 p.drawRect(r);
83 p.setPen(text);
84 p.drawText(QRect(r.left(), r.top() - 20, r.width(), 18), Qt::AlignLeft, title);
85 };
86 drawFrame(survivalRect, QStringLiteral("Survival probability"));
87 drawFrame(profileRect, QStringLiteral("Current X profile (each lane normalized for shape)"));
88
89 if (!history_ || !history_->configured() || history_->empty()) {
90 p.setPen(text);
91 p.drawText(rect(), Qt::AlignCenter,
92 QStringLiteral("Run the Quantum Zeno / Watched Escape preset"));
93 return;
94 }
95
96 const std::vector<qpe::QuantumZenoSample2D> &samples = history_->samples();
97 const qpe::QuantumZenoSample2D &latest = samples.back();
98 const qpe::QuantumZeno2DConfig &config = history_->config();
99 const double tMax = std::max(1.0e-9, samples.back().time);
100
101 auto mapT = [&](double t) {
102 return survivalRect.left() + t / tMax * survivalRect.width();
103 };
104 auto mapSurvival = [&](double v) {
105 const double clamped = std::max(0.0, std::min(1.0, v));
106 return survivalRect.bottom() - clamped * survivalRect.height();
107 };
108
109 p.setPen(QPen(frame, 1, Qt::DotLine));
110 for (int i = 1; i < 4; ++i) {
111 const double level = 0.25 * static_cast<double>(i);
112 const int yy = static_cast<int>(std::lround(mapSurvival(level)));
113 p.drawLine(survivalRect.left(), yy, survivalRect.right(), yy);
114 }
115
116 auto drawSurvival = [&](bool watchedSeries, const QColor &color) {
117 QPainterPath path;
118 bool started = false;
119 for (const qpe::QuantumZenoSample2D &sample : samples) {
120 const double value = watchedSeries
121 ? sample.watchedCumulativeSurvival
122 : sample.controlSurvival;
123 const QPointF q(mapT(sample.time), mapSurvival(value));
124 if (!started) { path.moveTo(q); started = true; }
125 else path.lineTo(q);
126 }
127 p.setPen(QPen(color, 2.2));
128 p.drawPath(path);
129 };
130 drawSurvival(false, control);
131 drawSurvival(true, watched);
132
133 p.setPen(control);
134 p.drawText(survivalRect.adjusted(8, 6, -8, -6),
135 Qt::AlignTop | Qt::AlignLeft,
136 QStringLiteral("upper control: no measurements"));
137 p.setPen(watched);
138 p.drawText(survivalRect.adjusted(8, 6, -8, -6),
139 Qt::AlignTop | Qt::AlignRight,
140 QStringLiteral("lower watched: repeated YES projections"));
141 p.setPen(text);
142 p.drawText(QRect(4, survivalRect.top(), 48, 18), Qt::AlignRight,
143 QStringLiteral("1.0"));
144 p.drawText(QRect(4, survivalRect.bottom() - 16, 48, 18), Qt::AlignRight,
145 QStringLiteral("0.0"));
146 p.drawText(QRect(survivalRect.left(), survivalRect.bottom() + 4,
147 survivalRect.width(), 20),
148 Qt::AlignRight,
149 QStringLiteral("t=%1 measurements=%2")
150 .arg(tMax, 0, 'f', 1)
151 .arg(static_cast<qulonglong>(latest.measurementCount)));
152
153 if (!profile_.control.empty() &&
154 profile_.control.size() == profile_.watched.size() && profile_.dx > 0.0) {
155 const double xMin = profile_.xMin;
156 const double xMax = xMin + profile_.dx *
157 static_cast<double>(profile_.control.size() - 1u);
158 double maxP = 0.0;
159 for (float v : profile_.control) maxP = std::max(maxP, static_cast<double>(v));
160 for (float v : profile_.watched) maxP = std::max(maxP, static_cast<double>(v));
161 maxP = std::max(maxP, 1.0e-12);
162
163 auto mapX = [&](double x) {
164 return profileRect.left() + (x - xMin) / (xMax - xMin) * profileRect.width();
165 };
166 auto mapP = [&](double value) {
167 return profileRect.bottom() - value / maxP * profileRect.height();
168 };
169
170 const int bx = static_cast<int>(std::lround(mapX(config.survivalBoundaryX)));
171 if (bx >= profileRect.left() && bx <= profileRect.right()) {
172 p.setPen(QPen(boundary, 1.5, Qt::DashLine));
173 p.drawLine(bx, profileRect.top(), bx, profileRect.bottom());
174 p.drawText(QRect(bx + 4, profileRect.top() + 4, 120, 18),
175 Qt::AlignLeft, QStringLiteral("measurement edge"));
176 }
177
178 auto drawProfile = [&](const std::vector<float> &values, const QColor &color) {
179 QPainterPath path;
180 bool started = false;
181 for (std::size_t i = 0u; i < values.size(); ++i) {
182 const double x = xMin + static_cast<double>(i) * profile_.dx;
183 const QPointF q(mapX(x), mapP(values[i]));
184 if (!started) { path.moveTo(q); started = true; }
185 else path.lineTo(q);
186 }
187 p.setPen(QPen(color, 2.0));
188 p.drawPath(path);
189 };
190 drawProfile(profile_.control, control);
191 drawProfile(profile_.watched, watched);
192
193 p.setPen(text);
194 p.drawText(profileRect.adjusted(8, 6, -8, -6),
195 Qt::AlignBottom | Qt::AlignLeft,
196 QStringLiteral("orange control cyan watched"));
197 p.drawText(QRect(profileRect.left(), profileRect.bottom() + 4,
198 profileRect.width(), 20),
199 Qt::AlignLeft,
200 QStringLiteral("x=%1").arg(xMin, 0, 'f', 1));
201 p.drawText(QRect(profileRect.left(), profileRect.bottom() + 4,
202 profileRect.width(), 20),
203 Qt::AlignRight,
204 QStringLiteral("x=%1").arg(xMax, 0, 'f', 1));
205 }
206}
QuantumZenoPlotWidget(QWidget *parent=nullptr)
Performs quantum zeno plot widget.
void setData(const qpe::QuantumZenoHistory2D &history, const qpe::QuantumZenoProfile2D &profile)
Sets data.
void clear()
Performs clear.
qpe::QuantumZenoProfile2D profile_
const qpe::QuantumZenoHistory2D * history_
void paintEvent(QPaintEvent *event) override
Paints event.
QSize minimumSizeHint() const override
Performs minimum size hint.
Implements the Quantum Zeno History2D component.
bool configured() const noexcept
Returns configured.
const QuantumZeno2DConfig & config() const noexcept
Returns config.
const std::vector< QuantumZenoSample2D > & samples() const noexcept
Samples s.
bool empty() const noexcept
Performs empty.
Declares the quantumzeno2d physics/numerical component used by QPE experiments.
Declares the quantumzenoplotwidget visualization component used by QPE.
Configuration values for Quantum Zeno2D Config.
Data structure used by the Quantum Zeno Profile2D component.
std::vector< float > control
std::vector< float > watched
Data structure used by the Quantum Zeno Sample2D component.