Quantum Phenomena Explorer 7.9.8
Interactive quantum-phenomena Explorer Tutor — source documentation
Loading...
Searching...
No Matches
quantumkapitzadiracplotwidget.cpp
Go to the documentation of this file.
1/**
2 * @file quantumkapitzadiracplotwidget.cpp
3 * @brief Implements the quantumkapitzadiracplotwidget visualization component used by QPE.
4 * @ingroup qpe_graphics
5 *
6 * Source: @c graphics/renderer/quantumkapitzadiracplotwidget.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 <QPainter>
15#include <QPaintEvent>
16#include <QPainterPath>
17#include <QPen>
18
19#include <algorithm>
20#include <cmath>
21
22namespace {
23
24/**
25 * @brief Performs heat color.
26 * @param value Value to assign or evaluate.
27 */
28QColor heatColor(double value)
29{
30 const double v = std::max(0.0, std::min(1.0, value));
31 if (v < 0.35) {
32 const double u = v / 0.35;
33 return QColor(static_cast<int>(7 + 16 * u),
34 static_cast<int>(12 + 75 * u),
35 static_cast<int>(28 + 150 * u));
36 }
37 if (v < 0.72) {
38 const double u = (v - 0.35) / 0.37;
39 return QColor(static_cast<int>(23 + 28 * u),
40 static_cast<int>(87 + 145 * u),
41 static_cast<int>(178 + 58 * u));
42 }
43 const double u = (v - 0.72) / 0.28;
44 return QColor(static_cast<int>(51 + 204 * u),
45 static_cast<int>(232 + 23 * u),
46 static_cast<int>(236 - 92 * u));
47}
48
49} // namespace
50
52 : QWidget(parent)
53{
54 setAutoFillBackground(false);
55}
56
58{
59 history_ = &history;
60 update();
61}
62
64{
65 history_ = nullptr;
66 update();
67}
68
70{
71 return QSize(650, 430);
72}
73
75{
76 Q_UNUSED(event);
77 QPainter p(this);
78 p.setRenderHint(QPainter::Antialiasing, true);
79 p.fillRect(rect(), QColor(11, 16, 22));
80
81 QFont title = font();
82 title.setBold(true);
83 p.setFont(title);
84 p.setPen(QColor(224, 234, 242));
85 p.drawText(QRect(12, 7, width() - 24, 24), Qt::AlignLeft | Qt::AlignVCenter,
86 QStringLiteral("Kapitza-Dirac diffraction — momentum orders from a light grating"));
87
88 if (!history_ || !history_->configured() || history_->empty()) {
89 p.setFont(font());
90 p.setPen(QColor(150, 166, 180));
91 p.drawText(QRect(20, 50, width() - 40, height() - 70),
92 Qt::AlignCenter | Qt::TextWordWrap,
93 QStringLiteral("Load Kapitza-Dirac Diffraction and press Play"));
94 return;
95 }
96
97 const std::vector<qpe::QuantumKapitzaDiracSample2D> &samples = history_->samples();
99 const qpe::QuantumKapitzaDiracSample2D &last = samples.back();
100
101 const int left = 62;
102 const int right = 18;
103 const int top = 40;
104 const int gap = 38;
105 const int barsH = std::max(120, height() / 3);
106 const int carpetBottom = height() - barsH - gap;
107 QRect carpet(left, top, std::max(20, width() - left - right),
108 std::max(90, carpetBottom - top));
109 QRect bars(left, carpet.bottom() + gap, carpet.width(),
110 std::max(80, height() - (carpet.bottom() + gap) - 28));
111
112 p.setPen(QColor(62, 77, 90));
113 p.setBrush(QColor(6, 11, 16));
114 p.drawRect(carpet);
115 p.drawRect(bars);
116
117 double maxP = 1.0e-12;
118 for (const qpe::QuantumKapitzaDiracSample2D &s : samples) {
119 for (float v : s.momentumProbability) maxP = std::max(maxP, static_cast<double>(v));
120 }
121 const std::size_t bins = last.momentumProbability.size();
122 if (bins > 0u) {
123 for (std::size_t row = 0u; row < samples.size(); ++row) {
124 const qpe::QuantumKapitzaDiracSample2D &s = samples[row];
125 const int y0 = carpet.top() + static_cast<int>(
126 static_cast<double>(row) / samples.size() * carpet.height());
127 const int y1 = carpet.top() + static_cast<int>(
128 static_cast<double>(row + 1u) / samples.size() * carpet.height());
129 for (std::size_t col = 0u; col < s.momentumProbability.size(); ++col) {
130 const int x0 = carpet.left() + static_cast<int>(
131 static_cast<double>(col) / bins * carpet.width());
132 const int x1 = carpet.left() + static_cast<int>(
133 static_cast<double>(col + 1u) / bins * carpet.width());
134 const double q = std::sqrt(std::max(0.0,
135 static_cast<double>(s.momentumProbability[col])) / maxP);
136 p.fillRect(QRect(x0, y0, std::max(1, x1 - x0 + 1),
137 std::max(1, y1 - y0 + 1)), heatColor(q));
138 }
139 }
140
141 const double pMin = last.momentumMin;
142 const double pMax = last.momentumMin +
143 last.momentumStep * static_cast<double>(bins > 0u ? bins - 1u : 0u);
144 const auto mapP = [&](double momentum) {
145 const double u = (momentum - pMin) / std::max(1.0e-12, pMax - pMin);
146 return carpet.left() + u * carpet.width();
147 };
148 p.setPen(QPen(QColor(255, 205, 78, 180), 1.0, Qt::DashLine));
149 for (int n = -config.maximumOrder; n <= config.maximumOrder; ++n) {
150 const double px = static_cast<double>(n) * last.reciprocalMomentum;
151 if (px < pMin || px > pMax) continue;
152 p.drawLine(QPointF(mapP(px), carpet.top()), QPointF(mapP(px), carpet.bottom()));
153 }
154 p.setPen(QColor(180, 197, 210));
155 p.drawText(QRect(carpet.left(), carpet.bottom() + 4, carpet.width(), 20),
156 Qt::AlignCenter,
157 QStringLiteral("p_x — gold guides: n G, G=2 pi hbar / a"));
158 p.drawText(QRect(4, carpet.top(), left - 10, 20),
159 Qt::AlignRight | Qt::AlignVCenter, QStringLiteral("t=0"));
160 p.drawText(QRect(4, carpet.bottom() - 20, left - 10, 20),
161 Qt::AlignRight | Qt::AlignVCenter,
162 QStringLiteral("%1").arg(last.time, 0, 'f', 2));
163 }
164
165 const int orderCount = static_cast<int>(last.orderProbability.size());
166 if (orderCount > 0) {
167 double maxOrderP = 1.0e-12;
168 for (float v : last.orderProbability) maxOrderP = std::max(maxOrderP, static_cast<double>(v));
169 const double cellW = static_cast<double>(bars.width()) / orderCount;
170 for (int i = 0; i < orderCount; ++i) {
171 const double v = static_cast<double>(last.orderProbability[static_cast<std::size_t>(i)]);
172 const double h = v / maxOrderP * (bars.height() - 30);
173 const QRectF r(bars.left() + i * cellW + 0.12 * cellW,
174 bars.bottom() - h,
175 0.76 * cellW,
176 h);
177 p.fillRect(r, QColor(83, 211, 238));
178 p.setPen(QColor(205, 220, 231));
179 const int n = i - config.maximumOrder;
180 p.drawText(QRectF(bars.left() + i * cellW, bars.bottom() + 3,
181 cellW, 20), Qt::AlignCenter,
182 QString::number(n));
183 }
184 p.setPen(QColor(180, 197, 210));
185 p.drawText(QRect(4, bars.top(), left - 10, 20),
186 Qt::AlignRight | Qt::AlignVCenter,
187 QStringLiteral("Pmax"));
188 p.drawText(QRect(bars.left(), bars.bottom() + 22, bars.width(), 20),
189 Qt::AlignCenter,
190 QStringLiteral("diffraction order n"));
191 }
192
193 p.setPen(QColor(225, 235, 242));
194 const QString stage = last.pulseActive ? QStringLiteral("LIGHT PULSE ON") :
195 (last.time >= config.pulseStartTime + config.pulseDuration
196 ? QStringLiteral("free expansion") : QStringLiteral("before pulse"));
197 p.drawText(QRect(bars.left() + 8, bars.top() + 5, bars.width() - 16, 20),
198 Qt::AlignLeft | Qt::AlignVCenter,
199 QStringLiteral("%1 samples=%2 t=%3 G=%4 pulse area beta=%5")
200 .arg(stage)
201 .arg(static_cast<qulonglong>(samples.size()))
202 .arg(last.time, 0, 'f', 3)
203 .arg(last.reciprocalMomentum, 0, 'f', 4)
204 .arg(qpe::QuantumKapitzaDirac2D::pulseArea(config, history_->hbar()), 0, 'f', 3));
205}
void setData(const qpe::QuantumKapitzaDiracHistory2D &history)
Sets data.
void paintEvent(QPaintEvent *event) override
Paints event.
QuantumKapitzaDiracPlotWidget(QWidget *parent=nullptr)
Performs quantum kapitza dirac plot widget.
QSize minimumSizeHint() const override
Performs minimum size hint.
const qpe::QuantumKapitzaDiracHistory2D * history_
static double pulseArea(const QuantumKapitzaDirac2DConfig &config, double hbar) noexcept
Performs pulse area.
Implements the Quantum Kapitza Dirac History2D component.
bool empty() const noexcept
Returns whether the object contains no data.
const std::vector< QuantumKapitzaDiracSample2D > & samples() const noexcept
Samples s.
double hbar() const noexcept
Carries out hbar.
const QuantumKapitzaDirac2DConfig & config() const noexcept
Returns config.
bool configured() const noexcept
Returns configured.
Declares the quantumkapitzadiracplotwidget visualization component used by QPE.
Configuration values for Quantum Kapitza Dirac2D Config.
Data structure used by the Quantum Kapitza Dirac Sample2D component.