jfjoch_viewer: Resolution estimate plot uses 1/d^2 as Y-axis

This commit is contained in:
2025-11-27 14:13:54 +01:00
parent c8940f9c99
commit 1df9da4d2e
3 changed files with 81 additions and 11 deletions
+2 -2
View File
@@ -80,7 +80,7 @@ void JFJochViewerDatasetInfo::datasetLoaded(std::shared_ptr<const JFJochReaderDa
if (dataset) {
UpdatePlot();
} else {
chart_view->loadValues<float>({}, 0);
chart_view->loadValues<float>({}, 0, false);
grid_scan_image->clear();
}
}
@@ -127,7 +127,7 @@ void JFJochViewerDatasetInfo::UpdatePlot() {
else if (val == 8)
data = dataset->b_factor;
chart_view->loadValues(data, image_number);
chart_view->loadValues(data, image_number, val == 7);
if (dataset->experiment.GetGridScan()) {
stack->setCurrentWidget(grid_scan_image);
grid_scan_image->loadData(data, dataset->experiment.GetGridScan().value());
+64 -6
View File
@@ -4,11 +4,12 @@
#include <QMenu>
#include <QApplication>
#include <QClipboard>
#include <QCategoryAxis>
#include "JFJochChartView.h"
JFJochChartView::JFJochChartView(QWidget *parent)
: QChartView(new QChart(), parent) {
: QChartView(new QChart(), parent) {
chart()->legend()->hide();
setRenderHint(QPainter::Antialiasing);
setRubberBand(QChartView::RubberBand::RectangleRubberBand);
@@ -17,7 +18,6 @@ JFJochChartView::JFJochChartView(QWidget *parent)
m_hoverLoadTimer = new QTimer(this);
m_hoverLoadTimer->setSingleShot(true);
connect(m_hoverLoadTimer, &QTimer::timeout, this, &JFJochChartView::onHoverLoadTimeout);
}
void JFJochChartView::setImage(int64_t val) {
@@ -107,7 +107,7 @@ void JFJochChartView::updateChart() {
chart()->createDefaultAxes();
// Set Y-axis behavior according to options
QValueAxis *axisY = qobject_cast<QValueAxis*>(chart()->axisY(series));
QValueAxis *axisY = qobject_cast<QValueAxis *>(chart()->axisY(series));
if (axisY) {
if (std::isfinite(dispMin) && std::isfinite(dispMax)) {
if (m_minYZeroEnabled) {
@@ -123,6 +123,51 @@ void JFJochChartView::updateChart() {
axisY->setRange(dispMin, dispMax);
}
}
// If Y is in 1/d^2, hide numeric labels and add a category axis with d labels
if (m_yOneOverD) {
axisY->setLabelsVisible(false); // keep grid/ticks from value axis
// Build a mirrored visible axis with labels in d (Å)
auto *axYcat = new QCategoryAxis();
axYcat->setLabelsPosition(QCategoryAxis::AxisLabelsPositionOnValue);
axYcat->setGridLineVisible(false);
axYcat->setMinorGridLineVisible(false);
axYcat->setTitleText(QStringLiteral("d (Å)"));
const int tickCountY = std::max(2, axisY->tickCount());
const double ymin = axisY->min();
const double ymax = axisY->max();
const double ystep = (tickCountY > 1) ? (ymax - ymin) / (tickCountY - 1) : 0.0;
for (int i = 0; i < tickCountY; ++i) {
const double yv = (i == tickCountY - 1) ? ymax : (ymin + i * ystep);
QString lab;
if (!(yv > 0.0)) {
lab = QStringLiteral(""); // invalid for d
} else if (std::abs(yv) < 1e-300) {
lab = QStringLiteral("");
} else {
const double d = 1.0 / std::sqrt(yv);
lab = QString("%1 Å").arg(d, 0, 'f', 2);
}
axYcat->append(lab, yv);
}
chart()->addAxis(axYcat, Qt::AlignLeft);
series->attachAxis(axYcat);
currentSeries->attachAxis(axYcat);
// Give a bit more room on the left so labels are not clipped
QMargins m = chart()->margins();
if (m.left() < 12) {
m.setLeft(12);
chart()->setMargins(m);
}
} else {
// Normal numeric labels
axisY->setTitleText(QString());
axisY->setLabelsVisible(true);
}
}
}
}
@@ -192,9 +237,22 @@ void JFJochChartView::mouseMoveEvent(QMouseEvent *event) {
ptOnChart.x(), plotArea.bottom()));
// Status bar text
QString text = QString("image = %1, value = %2")
.arg(idx)
.arg(values[static_cast<size_t>(idx)], 0, 'g', 6);
const double yv = values[static_cast<size_t>(idx)];
QString text;
if (m_yOneOverD) {
if (std::isfinite(yv) && yv > 0.0) {
const double d = 1.0 / std::sqrt(yv);
text = QString("image = %1, d = %2 Å")
.arg(idx)
.arg(d, 0, 'f', 2);
} else {
text = QString("image = %1, no resolution estimate").arg(idx);
}
} else {
text = QString("image = %1, value = %2")
.arg(idx)
.arg(yv, 0, 'g', 6);
}
emit writeStatusBar(text, 6000);
// Debounced image load on hover when Shift is pressed
+15 -3
View File
@@ -25,6 +25,7 @@ class JFJochChartView : public QChartView {
int64_t curr_image = 0;
bool m_minYZeroEnabled = true;
bool m_yOneOverD = false;
void updateChart();
@@ -51,10 +52,21 @@ public slots:
public:
template<class T>
void loadValues(const std::vector<T> &input, int64_t image) {
void loadValues(const std::vector<T> &input, int64_t image, bool one_over_d2) {
m_yOneOverD = one_over_d2;
values.resize(input.size());
for (int i = 0; i < input.size(); i++)
values[i] = static_cast<float>(input[i]);
for (int i = 0; i < input.size(); i++) {
if (one_over_d2) {
float d = static_cast<float>(input[i]);
if (!std::isfinite(d))
values[i] = 0.0f;
else
values[i] = 1.0f / (d * d);
} else
values[i] = static_cast<float>(input[i]);
}
curr_image = image;
updateChart();
}