Quantum Phenomena Explorer 7.9.8
Interactive quantum-phenomena Explorer Tutor — source documentation
Loading...
Searching...
No Matches
quantumtalbotplotwidget.cpp
Go to the documentation of this file.
1/**
2 * @file quantumtalbotplotwidget.cpp
3 * @brief Implements the quantumtalbotplotwidget visualization component used by QPE.
4 * @ingroup qpe_graphics
5 *
6 * Source: @c graphics/renderer/quantumtalbotplotwidget.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 <QImage>
15#include <QPaintEvent>
16#include <QPainter>
17#include <QPainterPath>
18
19#include <algorithm>
20#include <cmath>
21
22namespace {
23
24/**
25 * @brief Draws frame.
26 * @param painter The painter value used by the operation.
27 * @param rect The rect value used by the operation.
28 */
29void drawFrame(QPainter &painter, const QRectF &rect)
30{
31 painter.setPen(QPen(QColor(72, 80, 90), 1.0));
32 painter.drawRect(rect);
33}
34
35/**
36 * @brief Performs carpet colour.
37 * @param intensity The intensity value used by the operation.
38 */
39QRgb carpetColour(double intensity)
40{
41 const double v = std::max(0.0, std::min(1.0, intensity));
42 const int r = static_cast<int>(255.0 * std::pow(v, 1.55));
43 const int g = static_cast<int>(255.0 * std::pow(v, 0.72));
44 const int b = static_cast<int>(255.0 * std::min(1.0, 0.18 + 1.25 * std::pow(v, 0.90)));
45 return qRgb(r, g, b);
46}
47
48} // namespace
49
51 : QWidget(parent)
52{
53 setMinimumHeight(360);
54 setAutoFillBackground(false);
55}
56
58 double mass,
59 double hbar)
60{
61 history_ = &history;
62 mass_ = mass;
63 hbar_ = hbar;
64 update();
65}
66
68{
69 history_ = nullptr;
70 update();
71}
72
74{
75 return QSize(600, 380);
76}
77
79{
80 Q_UNUSED(event);
81
82 QPainter painter(this);
83 painter.setRenderHint(QPainter::Antialiasing, true);
84 painter.setRenderHint(QPainter::TextAntialiasing, true);
85 painter.fillRect(rect(), QColor(14, 17, 22));
86
87 const double left = 64.0;
88 const double right = 24.0;
89 const double top = 30.0;
90 const double bottom = 38.0;
91 const double gap = 36.0;
92 const double available = std::max(100.0, height() - top - bottom - gap);
93 const double carpetHeight = available * 0.68;
94 const QRectF carpetRect(left, top,
95 std::max(30.0, width() - left - right), carpetHeight);
96 const QRectF correlationRect(left, carpetRect.bottom() + gap,
97 carpetRect.width(), available - carpetHeight);
98
99 drawFrame(painter, carpetRect);
100 drawFrame(painter, correlationRect);
101
102 painter.setPen(QColor(214, 220, 228));
103 painter.drawText(QRectF(carpetRect.left(), 4.0, carpetRect.width(), 20.0),
104 Qt::AlignCenter,
105 QStringLiteral("Talbot carpet: transverse x-marginal versus time"));
106 painter.drawText(QRectF(correlationRect.left(), carpetRect.bottom() + 8.0,
107 correlationRect.width(), 20.0), Qt::AlignCenter,
108 QStringLiteral("Self-image correlation: original / half-period shifted"));
109
110 if (history_ == nullptr || history_->empty() || !history_->hasReference() ||
111 history_->gridWidth() < 2u || !(history_->dx() > 0.0f)) {
112 painter.setPen(QColor(220, 228, 238));
113 painter.drawText(carpetRect, Qt::AlignCenter,
114 QStringLiteral("Run the Quantum Talbot Self-Imaging preset"));
115 painter.drawText(correlationRect, Qt::AlignCenter,
116 QStringLiteral("The initial transverse comb builds its own x-time carpet"));
117 return;
118 }
119
120 const std::vector<qpe::QuantumTalbotSample2D> &samples = history_->samples();
121 const std::size_t columns = history_->gridWidth();
122 const int rows = static_cast<int>(samples.size());
123
124 if (columns > 0u && rows > 0) {
125 QImage image(static_cast<int>(columns), rows, QImage::Format_RGB32);
126 for (int row = 0; row < rows; ++row) {
127 const std::vector<float> &marginal = samples[static_cast<std::size_t>(row)].marginalX;
128 double rowMax = 0.0;
129 for (std::size_t x = 0u; x < std::min(columns, marginal.size()); ++x) {
130 rowMax = std::max(rowMax, static_cast<double>(marginal[x]));
131 }
132 rowMax = std::max(rowMax, 1.0e-30);
133 for (std::size_t x = 0u; x < columns; ++x) {
134 const double value = x < marginal.size()
135 ? static_cast<double>(marginal[x]) / rowMax : 0.0;
136 image.setPixel(static_cast<int>(x), row,
137 carpetColour(std::sqrt(std::max(0.0, value))));
138 }
139 }
140 painter.setRenderHint(QPainter::SmoothPixmapTransform, false);
141 painter.drawImage(carpetRect, image, QRectF(image.rect()));
142 painter.setRenderHint(QPainter::Antialiasing, true);
143 }
144
145 const double tMin = samples.front().time;
146 const double tMax = samples.back().time;
147 const double timeSpan = std::max(1.0e-12, tMax - tMin);
148 const double tTalbot = qpe::QuantumTalbot2D::talbotTime(
150
151 const auto mapTimeX = [correlationRect, tMin, timeSpan](double t) {
152 return correlationRect.left() + (t - tMin) / timeSpan * correlationRect.width();
153 };
154 const auto mapCorrelationY = [correlationRect](double v) {
155 const double clamped = std::max(0.0, std::min(1.0, v));
156 return correlationRect.bottom() - clamped * correlationRect.height();
157 };
158 const auto mapTimeY = [carpetRect, tMin, timeSpan](double t) {
159 return carpetRect.top() + (t - tMin) / timeSpan * carpetRect.height();
160 };
161
162 painter.setPen(QPen(QColor(72, 80, 90), 1.0));
163 for (int i = 1; i < 4; ++i) {
164 const double y = correlationRect.top() + i * correlationRect.height() / 4.0;
165 painter.drawLine(QPointF(correlationRect.left(), y),
166 QPointF(correlationRect.right(), y));
167 }
168
169 if (tTalbot > 0.0) {
170 for (int n = 1; n <= 12; ++n) {
171 const double t = 0.25 * static_cast<double>(n) * tTalbot;
172 if (t < tMin || t > tMax) continue;
173 const bool full = (n % 4) == 0;
174 const bool half = (n % 2) == 0 && !full;
175 const QColor guide = full ? QColor(245, 225, 120)
176 : (half ? QColor(220, 120, 245) : QColor(120, 145, 165));
177 painter.setPen(QPen(guide, full ? 1.5 : 1.0, Qt::DashLine));
178 painter.drawLine(QPointF(mapTimeX(t), correlationRect.top()),
179 QPointF(mapTimeX(t), correlationRect.bottom()));
180 painter.drawLine(QPointF(carpetRect.left(), mapTimeY(t)),
181 QPointF(carpetRect.right(), mapTimeY(t)));
182 }
183 }
184
185 QPainterPath directPath;
186 QPainterPath shiftedPath;
187 bool started = false;
188 for (const qpe::QuantumTalbotSample2D &sample : samples) {
189 const QPointF direct(mapTimeX(sample.time), mapCorrelationY(sample.directCorrelation));
190 const QPointF shifted(mapTimeX(sample.time), mapCorrelationY(sample.halfShiftCorrelation));
191 if (!started) {
192 directPath.moveTo(direct);
193 shiftedPath.moveTo(shifted);
194 started = true;
195 } else {
196 directPath.lineTo(direct);
197 shiftedPath.lineTo(shifted);
198 }
199 }
200
201 painter.setPen(QPen(QColor(80, 220, 255), 2.1));
202 painter.drawPath(directPath);
203 painter.setPen(QPen(QColor(235, 115, 255), 1.9));
204 painter.drawPath(shiftedPath);
205
206 painter.setPen(QColor(215, 224, 234));
207 painter.drawText(QRectF(4.0, correlationRect.top() - 8.0, 54.0, 18.0),
208 Qt::AlignRight | Qt::AlignVCenter, QStringLiteral("1.0"));
209 painter.drawText(QRectF(4.0, correlationRect.bottom() - 10.0, 54.0, 18.0),
210 Qt::AlignRight | Qt::AlignVCenter, QStringLiteral("0.0"));
211
212 const double physicalWidth = static_cast<double>(history_->gridWidth()) * history_->dx();
213 painter.drawText(QRectF(carpetRect.left(), carpetRect.bottom() + 2.0, 120.0, 20.0),
214 Qt::AlignLeft,
215 QStringLiteral("x = %1").arg(-0.5 * physicalWidth, 0, 'f', 2));
216 painter.drawText(QRectF(carpetRect.right() - 120.0, carpetRect.bottom() + 2.0, 120.0, 20.0),
217 Qt::AlignRight,
218 QStringLiteral("x = %1").arg(0.5 * physicalWidth, 0, 'f', 2));
219 painter.drawText(QRectF(correlationRect.left(), correlationRect.bottom() + 6.0, 90.0, 20.0),
220 Qt::AlignLeft, QString::number(tMin, 'f', 1));
221 painter.drawText(QRectF(correlationRect.right() - 90.0, correlationRect.bottom() + 6.0,
222 90.0, 20.0), Qt::AlignRight, QString::number(tMax, 'f', 1));
223 painter.drawText(QRectF(correlationRect.left(), correlationRect.bottom() + 4.0,
224 correlationRect.width(), 24.0), Qt::AlignCenter,
225 QStringLiteral("simulation time"));
226
227 const double legendY = carpetRect.bottom() + 2.0;
228 painter.setPen(QColor(80, 220, 255));
229 painter.drawText(QRectF(carpetRect.left() + 140.0, legendY, 170.0, 20.0), Qt::AlignLeft,
230 QStringLiteral("cyan: original image"));
231 painter.setPen(QColor(235, 115, 255));
232 painter.drawText(QRectF(carpetRect.left() + 310.0, legendY, 230.0, 20.0), Qt::AlignLeft,
233 QStringLiteral("magenta: shifted by a/2"));
234}
void paintEvent(QPaintEvent *event) override
Paints event.
const qpe::QuantumTalbotHistory2D * history_
QuantumTalbotPlotWidget(QWidget *parent=nullptr)
Performs quantum talbot plot widget.
QSize minimumSizeHint() const override
Performs minimum size hint.
void setData(const qpe::QuantumTalbotHistory2D &history, double mass, double hbar)
Sets data.
static double talbotTime(double period, double mass, double hbar=1.0) noexcept
Performs talbot time.
Implements the Quantum Talbot History2D component.
const QuantumTalbotInitialState2DConfig & config() const noexcept
Returns config.
std::size_t gridWidth() const noexcept
Carries out grid width.
const std::vector< QuantumTalbotSample2D > & samples() const noexcept
Samples s.
bool empty() const noexcept
Returns whether the object contains no data.
float dx() const noexcept
Returns the X-axis grid spacing.
bool hasReference() const noexcept
Returns whether reference.
QRgb carpetColour(double intensity)
Performs carpet colour.
void drawFrame(QPainter &painter, const QRectF &rect)
Draws frame.
Declares the quantumtalbotplotwidget visualization component used by QPE.
Data structure used by the Quantum Talbot Sample2D component.