Quantum Phenomena Explorer 7.9.8
Interactive quantum-phenomena Explorer Tutor — source documentation
Loading...
Searching...
No Matches
quantumkleinheightscanplotwidget.cpp
Go to the documentation of this file.
1/**
2 * @file quantumkleinheightscanplotwidget.cpp
3 * @brief Implements the quantumkleinheightscanplotwidget visualization component used by QPE.
4 * @ingroup qpe_graphics
5 *
6 * Source: @c graphics/renderer/quantumkleinheightscanplotwidget.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
22 : QWidget(parent)
23{
24}
25
27 double currentBarrierHeight,
28 double packetTransmission)
29{
30 scan_ = scan;
31 currentBarrierHeight_ = currentBarrierHeight;
32 packetTransmission_ = packetTransmission;
33 update();
34}
35
42
44{
45 return QSize(690, 450);
46}
47
49{
50 Q_UNUSED(event);
51 QPainter p(this);
52 p.setRenderHint(QPainter::Antialiasing, true);
53 p.fillRect(rect(), QColor(9, 13, 19));
54
55 QFont titleFont = font();
56 titleFont.setBold(true);
57 p.setFont(titleFont);
58 p.setPen(QColor(230, 238, 246));
59 p.drawText(QRect(12, 6, width() - 24, 25), Qt::AlignLeft | Qt::AlignVCenter,
60 QStringLiteral("Klein barrier-height reference — stationary plane-wave T(V0)"));
61
62 if (!scan_.valid || scan_.points.empty()) {
63 p.setFont(font());
64 p.setPen(QColor(145, 162, 178));
65 p.drawText(QRect(20, 45, width() - 40, height() - 65),
66 Qt::AlignCenter | Qt::TextWordWrap,
67 QStringLiteral("Load the Klein Transmission vs Barrier Height preset."));
68 return;
69 }
70
71 const int left = 64, right = 24, top = 48, bottom = 58;
72 QRect plot(left, top, std::max(120, width() - left - right),
73 std::max(120, height() - top - bottom));
74 p.setBrush(QColor(5, 9, 15));
75 p.setPen(QColor(54, 72, 88));
76 p.drawRect(plot);
77
78 const double vmin = scan_.minimumBarrierHeight;
79 const double vmax = scan_.maximumBarrierHeight;
80 const auto xOf = [&](double v) {
81 return plot.left() + (v - vmin) / std::max(1.0e-12, vmax - vmin) * plot.width();
82 };
83 const auto yOf = [&](double transmission) {
84 return plot.bottom() - std::max(0.0, std::min(1.0, transmission)) * plot.height();
85 };
86
87 // Regime bands. These are explanatory overlays only; the curve itself is
88 // calculated from spinor matching and does not depend on the renderer.
89 const double low = std::max(vmin, std::min(vmax, scan_.lowerThreshold));
90 const double high = std::max(vmin, std::min(vmax, scan_.upperThreshold));
91 if (low > vmin)
92 p.fillRect(QRectF(xOf(vmin), plot.top(), xOf(low) - xOf(vmin), plot.height()), QColor(40, 85, 60, 45));
93 if (high > low)
94 p.fillRect(QRectF(xOf(low), plot.top(), xOf(high) - xOf(low), plot.height()), QColor(120, 85, 35, 55));
95 if (vmax > high)
96 p.fillRect(QRectF(xOf(high), plot.top(), xOf(vmax) - xOf(high), plot.height()), QColor(45, 70, 120, 45));
97
98 p.setFont(font());
99 p.setPen(QColor(77, 94, 109));
100 for (int i = 0; i <= 5; ++i) {
101 const double t = static_cast<double>(i) / 5.0;
102 const int y = static_cast<int>(std::lround(yOf(t)));
103 p.drawLine(plot.left(), y, plot.right(), y);
104 p.setPen(QColor(170, 184, 197));
105 p.drawText(QRect(7, y - 9, 50, 18), Qt::AlignRight | Qt::AlignVCenter,
106 QString::number(t, 'f', 1));
107 p.setPen(QColor(77, 94, 109));
108 }
109
110 for (int i = 0; i <= 8; ++i) {
111 const double v = vmin + (vmax - vmin) * static_cast<double>(i) / 8.0;
112 const int x = static_cast<int>(std::lround(xOf(v)));
113 p.drawLine(x, plot.top(), x, plot.bottom());
114 p.setPen(QColor(170, 184, 197));
115 p.drawText(QRect(x - 24, plot.bottom() + 5, 48, 20), Qt::AlignHCenter | Qt::AlignTop,
116 QString::number(v, 'f', 1));
117 p.setPen(QColor(77, 94, 109));
118 }
119
120 if (scan_.lowerThreshold >= vmin && scan_.lowerThreshold <= vmax) {
121 const int x = static_cast<int>(std::lround(xOf(scan_.lowerThreshold)));
122 p.setPen(QPen(QColor(255, 205, 95), 1.4, Qt::DashLine));
123 p.drawLine(x, plot.top(), x, plot.bottom());
124 }
125 if (scan_.upperThreshold >= vmin && scan_.upperThreshold <= vmax) {
126 const int x = static_cast<int>(std::lround(xOf(scan_.upperThreshold)));
127 p.setPen(QPen(QColor(255, 205, 95), 1.4, Qt::DashLine));
128 p.drawLine(x, plot.top(), x, plot.bottom());
129 }
130
131 QPainterPath path;
132 bool first = true;
133 for (const qpe::QuantumKleinHeightPoint2D &point : scan_.points) {
134 if (!point.valid) { first = true; continue; }
135 const QPointF q(xOf(point.barrierHeight), yOf(point.transmission));
136 if (first) { path.moveTo(q); first = false; }
137 else path.lineTo(q);
138 }
139 p.setPen(QPen(QColor(100, 220, 255), 2.4));
140 p.setBrush(Qt::NoBrush);
141 p.drawPath(path);
142
143 if (currentBarrierHeight_ >= vmin && currentBarrierHeight_ <= vmax) {
144 double referenceT = scan_.points.front().transmission;
145 for (std::size_t i = 1; i < scan_.points.size(); ++i) {
146 const auto &a0 = scan_.points[i - 1u];
147 const auto &a1 = scan_.points[i];
148 if (!a0.valid || !a1.valid) continue;
149 if (currentBarrierHeight_ <= a1.barrierHeight) {
150 const double f = (currentBarrierHeight_ - a0.barrierHeight) /
151 std::max(1.0e-12, a1.barrierHeight - a0.barrierHeight);
152 referenceT = a0.transmission + f * (a1.transmission - a0.transmission);
153 break;
154 }
155 }
156 const int x = static_cast<int>(std::lround(xOf(currentBarrierHeight_)));
157 p.setPen(QPen(QColor(255, 205, 95), 1.5, Qt::DashLine));
158 p.drawLine(x, plot.top(), x, plot.bottom());
159 p.setBrush(QColor(255, 205, 95));
160 p.setPen(Qt::NoPen);
161 p.drawEllipse(QPointF(xOf(currentBarrierHeight_), yOf(referenceT)), 5.0, 5.0);
162
163 if (packetTransmission_ >= 0.0 && packetTransmission_ <= 1.05) {
164 p.setBrush(QColor(255, 126, 126));
165 p.drawEllipse(QPointF(xOf(currentBarrierHeight_), yOf(packetTransmission_)), 5.0, 5.0);
166 }
167 }
168
169 p.setPen(QColor(188, 202, 214));
170 p.setFont(font());
171 p.drawText(QRect(plot.left(), plot.bottom() + 29, plot.width(), 22), Qt::AlignCenter,
172 QStringLiteral("barrier height V0 | cyan: plane-wave T(V0) yellow: current reference red: time-domain packet max P_right"));
173
174 p.setPen(QColor(235, 240, 245));
175 p.drawText(QRect(plot.left() + 8, plot.top() + 6, plot.width() - 16, 44),
176 Qt::AlignLeft | Qt::AlignTop,
177 QStringLiteral("E=%1 |p|=%2 angle=%3 deg width=%4 thresholds: %5 / %6")
178 .arg(scan_.incidentEnergy, 0, 'f', 4)
179 .arg(scan_.momentumMagnitude, 0, 'f', 4)
180 .arg(scan_.incidenceAngleDegrees, 0, 'f', 2)
181 .arg(scan_.barrierWidth, 0, 'f', 3)
182 .arg(scan_.lowerThreshold, 0, 'f', 4)
183 .arg(scan_.upperThreshold, 0, 'f', 4));
184
185 p.setPen(QColor(170, 184, 197));
186 const int labelY = plot.top() + 28;
187 p.drawText(QRect(static_cast<int>(xOf(vmin)) + 6, labelY, std::max(0, static_cast<int>(xOf(low) - xOf(vmin)) - 12), 20),
188 Qt::AlignCenter, QStringLiteral("positive branch"));
189 p.drawText(QRect(static_cast<int>(xOf(low)), labelY, std::max(0, static_cast<int>(xOf(high) - xOf(low))), 20),
190 Qt::AlignCenter, QStringLiteral("evanescent"));
191 p.drawText(QRect(static_cast<int>(xOf(high)), labelY, std::max(0, static_cast<int>(xOf(vmax) - xOf(high))), 20),
192 Qt::AlignCenter, QStringLiteral("supercritical Klein"));
193}
void setData(const qpe::QuantumKleinHeightScan2DResult &scan, double currentBarrierHeight, double packetTransmission=-1.0)
Sets data.
QSize minimumSizeHint() const override
Performs minimum size hint.
void paintEvent(QPaintEvent *event) override
Paints event.
qpe::QuantumKleinHeightScan2DResult scan_
QuantumKleinHeightScanPlotWidget(QWidget *parent=nullptr)
Performs quantum klein height scan plot widget.
Declares the quantumkleinheightscanplotwidget visualization component used by QPE.
Data structure used by the Quantum Klein Height Point2D component.
Data record containing Quantum Klein Height Scan2D Result.
std::vector< QuantumKleinHeightPoint2D > points