82 QPainter painter(
this);
83 painter.setRenderHint(QPainter::Antialiasing,
true);
84 painter.setRenderHint(QPainter::TextAntialiasing,
true);
85 painter.fillRect(rect(), QColor(14, 17, 22));
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);
99 drawFrame(painter, carpetRect);
100 drawFrame(painter, correlationRect);
102 painter.setPen(QColor(214, 220, 228));
103 painter.drawText(QRectF(carpetRect.left(), 4.0, carpetRect.width(), 20.0),
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"));
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"));
120 const std::vector<qpe::QuantumTalbotSample2D> &samples =
history_->
samples();
122 const int rows =
static_cast<int>(samples.size());
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;
129 for (std::size_t x = 0u; x < std::min(columns, marginal.size()); ++x) {
130 rowMax = std::max(rowMax,
static_cast<double>(marginal[x]));
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))));
140 painter.setRenderHint(QPainter::SmoothPixmapTransform,
false);
141 painter.drawImage(carpetRect, image, QRectF(image.rect()));
142 painter.setRenderHint(QPainter::Antialiasing,
true);
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);
151 const auto mapTimeX = [correlationRect, tMin, timeSpan](
double t) {
152 return correlationRect.left() + (t - tMin) / timeSpan * correlationRect.width();
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();
158 const auto mapTimeY = [carpetRect, tMin, timeSpan](
double t) {
159 return carpetRect.top() + (t - tMin) / timeSpan * carpetRect.height();
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));
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)));
185 QPainterPath directPath;
186 QPainterPath shiftedPath;
187 bool started =
false;
189 const QPointF direct(mapTimeX(sample.time), mapCorrelationY(sample.directCorrelation));
190 const QPointF shifted(mapTimeX(sample.time), mapCorrelationY(sample.halfShiftCorrelation));
192 directPath.moveTo(direct);
193 shiftedPath.moveTo(shifted);
196 directPath.lineTo(direct);
197 shiftedPath.lineTo(shifted);
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);
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"));
213 painter.drawText(QRectF(carpetRect.left(), carpetRect.bottom() + 2.0, 120.0, 20.0),
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),
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"));
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"));