From 4e2043ec4ba4d4e5175b90c76b15243a93a96505 Mon Sep 17 00:00:00 2001 From: leonarski_f Date: Mon, 18 May 2026 12:54:24 +0200 Subject: [PATCH] jfjoch_viewer: Add Image B-factor --- broker/OpenAPIConvert.cpp | 1 + broker/jfjoch_api.yaml | 1 + common/Plot.h | 2 +- reader/JFJochHDF5Reader.cpp | 1 + reader/JFJochHttpReader.cpp | 1 + reader/JFJochReaderDataset.h | 1 + receiver/JFJochReceiverPlots.cpp | 8 +++ receiver/JFJochReceiverPlots.h | 1 + .../windows/JFJochViewerImageListWindow.cpp | 63 ++++++++++++++----- viewer/windows/JFJochViewerImageListWindow.h | 3 +- 10 files changed, 66 insertions(+), 16 deletions(-) diff --git a/broker/OpenAPIConvert.cpp b/broker/OpenAPIConvert.cpp index cf684946..db90e0b0 100644 --- a/broker/OpenAPIConvert.cpp +++ b/broker/OpenAPIConvert.cpp @@ -885,6 +885,7 @@ PlotType ConvertPlotType(const std::optional& input) { if (input == "integrated_reflections") return PlotType::IntegratedReflections; if (input == "image_scale_factor") return PlotType::ImageScaleFactor; if (input == "image_scale_cc") return PlotType::ImageScaleCC; + if (input == "image_scale_b") return PlotType::ImageScaleBFactor; throw JFJochException(JFJochExceptionCategory::InputParameterInvalid, "Plot type not recognized"); diff --git a/broker/jfjoch_api.yaml b/broker/jfjoch_api.yaml index a45e852f..f44cf5d6 100644 --- a/broker/jfjoch_api.yaml +++ b/broker/jfjoch_api.yaml @@ -118,6 +118,7 @@ components: - integrated_reflections - image_scale_factor - image_scale_cc + - image_scale_b roi: in: query name: roi diff --git a/common/Plot.h b/common/Plot.h index 6385ddd4..840e7fc1 100644 --- a/common/Plot.h +++ b/common/Plot.h @@ -16,7 +16,7 @@ enum class PlotType { ROISum, ROIMean, ROIMaxCount, ROIPixels, ROIWeightedX, ROIWeightedY, PacketsReceived, MaxValue, ResolutionEstimate, ProfileRadius, Mosaicity, BFactor, PixelSum, StrongPixels, RefinementBeamX, RefinementBeamY, ImageProcessingTime, IntegratedReflections, - ImageScaleFactor, ImageScaleCC + ImageScaleFactor, ImageScaleCC, ImageScaleBFactor }; enum class PlotAzintUnit { diff --git a/reader/JFJochHDF5Reader.cpp b/reader/JFJochHDF5Reader.cpp index 90b78775..5b13cce7 100644 --- a/reader/JFJochHDF5Reader.cpp +++ b/reader/JFJochHDF5Reader.cpp @@ -291,6 +291,7 @@ void JFJochHDF5Reader::ReadFile(const std::string &filename) { dataset->b_factor = master_file->ReadOptVector("/entry/MX/bFactor"); dataset->image_scale_factor = master_file->ReadOptVector("/entry/MX/imageScaleFactor"); dataset->image_scale_cc = master_file->ReadOptVector("/entry/MX/imageScaleCC"); + dataset->image_scale_b = master_file->ReadOptVector("/entry/MX/imageScaleBFactor"); dataset->integrated_reflections = master_file->ReadOptVector("/entry/MX/integratedReflections"); } if (master_file->Exists("/entry/image")) diff --git a/reader/JFJochHttpReader.cpp b/reader/JFJochHttpReader.cpp index 18264e7b..c3fb1732 100644 --- a/reader/JFJochHttpReader.cpp +++ b/reader/JFJochHttpReader.cpp @@ -185,6 +185,7 @@ std::shared_ptr JFJochHttpReader::UpdateDataset_i() { dataset->integrated_reflections = GetPlot_i("integrated_reflections"); dataset->image_scale_factor = GetPlot_i("image_scale_factor"); dataset->image_scale_cc = GetPlot_i("image_scale_cc"); + dataset->image_scale_b = GetPlot_i("image_scale_b"); if (msg->start_message->goniometer) dataset->experiment.Goniometer(msg->start_message->goniometer); diff --git a/reader/JFJochReaderDataset.h b/reader/JFJochReaderDataset.h index 2befe05c..0540c07c 100644 --- a/reader/JFJochReaderDataset.h +++ b/reader/JFJochReaderDataset.h @@ -43,6 +43,7 @@ struct JFJochReaderDataset { std::vector integrated_reflections; std::vector image_scale_factor; std::vector image_scale_cc; + std::vector image_scale_b; std::vector max_value; diff --git a/receiver/JFJochReceiverPlots.cpp b/receiver/JFJochReceiverPlots.cpp index f8d90e60..b230c5e5 100644 --- a/receiver/JFJochReceiverPlots.cpp +++ b/receiver/JFJochReceiverPlots.cpp @@ -108,6 +108,7 @@ void JFJochReceiverPlots::Setup(const DiffractionExperiment &experiment, const A integrated_reflections.Clear(r); image_scale_factor.Clear(r); image_scale_cc.Clear(r); + image_scale_b.Clear(r); refinement_time.Clear(r); spot_finding_time.Clear(r); @@ -173,6 +174,7 @@ void JFJochReceiverPlots::Add(const DataMessage &msg, const AzimuthalIntegration indexing_solution.AddElement(msg.number, msg.indexing_result); image_scale_factor.AddElement(msg.number, msg.image_scale_factor); image_scale_cc.AddElement(msg.number, msg.image_scale_cc); + image_scale_b.AddElement(msg.number, msg.image_scale_b_factor); { std::unique_lock ul(m); @@ -328,6 +330,9 @@ MultiLinePlot JFJochReceiverPlots::GetPlots(const PlotRequest &request) { case PlotType::ImageScaleCC: ret = image_scale_cc.GetMeanPlot(nbins, start, incr, request.fill_value); break; + case PlotType::ImageScaleBFactor: + ret = image_scale_b.GetMeanPlot(nbins, start, incr, request.fill_value); + break; case PlotType::ImageScaleFactor: ret = image_scale_factor.GetMeanPlot(nbins, start, incr, request.fill_value); break; @@ -552,6 +557,9 @@ void JFJochReceiverPlots::GetPlotRaw(std::vector &v, PlotType type, const case PlotType::ImageScaleFactor: v = image_scale_factor.ExportArray(); break; + case PlotType::ImageScaleBFactor: + v = image_scale_b.ExportArray(); + break; case PlotType::ROISum: case PlotType::ROIMaxCount: case PlotType::ROIPixels: diff --git a/receiver/JFJochReceiverPlots.h b/receiver/JFJochReceiverPlots.h index e55446fa..49bb4a40 100644 --- a/receiver/JFJochReceiverPlots.h +++ b/receiver/JFJochReceiverPlots.h @@ -69,6 +69,7 @@ class JFJochReceiverPlots { StatusVector integrated_reflections; StatusVector image_scale_factor; StatusVector image_scale_cc; + StatusVector image_scale_b; // StatusVector objects are fully thread-safe (protected by internal mutex) // It is OK to have concurrent access to StatusVector diff --git a/viewer/windows/JFJochViewerImageListWindow.cpp b/viewer/windows/JFJochViewerImageListWindow.cpp index 597d9fda..bf5bf698 100644 --- a/viewer/windows/JFJochViewerImageListWindow.cpp +++ b/viewer/windows/JFJochViewerImageListWindow.cpp @@ -7,6 +7,11 @@ #include #include +namespace { + constexpr int ScaleSortRole = Qt::UserRole + 1; + constexpr double ScaleNotAvailableSortValue = -1.0e100; +} + JFJochViewerImageListWindow::JFJochViewerImageListWindow(QWidget *parent) : JFJochHelperWindow(parent) { QWidget *centralWidget = new QWidget(this); @@ -21,6 +26,7 @@ JFJochViewerImageListWindow::JFJochViewerImageListWindow(QWidget *parent) : JFJo proxyModel = new QSortFilterProxyModel(this); proxyModel->setSourceModel(tableModel); + proxyModel->setSortRole(ScaleSortRole); tableView->setModel(proxyModel); tableView->sortByColumn(0, Qt::AscendingOrder); @@ -45,15 +51,16 @@ JFJochViewerImageListWindow::JFJochViewerImageListWindow(QWidget *parent) : JFJo void JFJochViewerImageListWindow::setupTableModel() { - tableModel->setColumnCount(8); + tableModel->setColumnCount(9); tableModel->setHeaderData(0, Qt::Horizontal, "#"); - tableModel->setHeaderData(1, Qt::Horizontal, "Background"); - tableModel->setHeaderData(2, Qt::Horizontal, "Indexing"); + tableModel->setHeaderData(1, Qt::Horizontal, "Bkg"); + tableModel->setHeaderData(2, Qt::Horizontal, "Index"); tableModel->setHeaderData(3, Qt::Horizontal, "Spots"); - tableModel->setHeaderData(4, Qt::Horizontal, "Res. estimate"); - tableModel->setHeaderData(5, Qt::Horizontal, "Max"); + tableModel->setHeaderData(4, Qt::Horizontal, "Res. [A]"); + tableModel->setHeaderData(5, Qt::Horizontal, "Max val"); tableModel->setHeaderData(6, Qt::Horizontal, "Scale factor"); - tableModel->setHeaderData(7, Qt::Horizontal, "Scale CC [%]"); + tableModel->setHeaderData(7, Qt::Horizontal, "Scale CC"); +tableModel->setHeaderData(8, Qt::Horizontal, "Scale B [A^2]"); } void JFJochViewerImageListWindow::addDataRow(int imageNumber, double backgroundEstimate, @@ -62,15 +69,18 @@ void JFJochViewerImageListWindow::addDataRow(int imageNumber, double backgroundE double resolutionEstimate, int64_t max_value, double image_scale_factor, - double image_scale_cc_percent) { + double image_scale_cc_percent, + double image_scale_b) { QList rowItems; QStandardItem *imageItem = new QStandardItem(); imageItem->setData(imageNumber, Qt::DisplayRole); + imageItem->setData(imageNumber, ScaleSortRole); rowItems.append(imageItem); QStandardItem *bgItem = new QStandardItem(); bgItem->setData(backgroundEstimate, Qt::DisplayRole); + bgItem->setData(backgroundEstimate, ScaleSortRole); rowItems.append(bgItem); QStandardItem *indexingItem = new QStandardItem(indexingResult); @@ -78,30 +88,50 @@ void JFJochViewerImageListWindow::addDataRow(int imageNumber, double backgroundE QStandardItem *spotItem = new QStandardItem(); spotItem->setData(spotCount, Qt::DisplayRole); + spotItem->setData(spotCount, ScaleSortRole); rowItems.append(spotItem); QStandardItem *resolutionItem = new QStandardItem(); - resolutionItem->setData(resolutionEstimate, Qt::DisplayRole); + resolutionItem->setData(QString::number(resolutionEstimate, 'f', 2), Qt::DisplayRole); + resolutionItem->setData(resolutionEstimate, ScaleSortRole); rowItems.append(resolutionItem); QStandardItem *maxValueItem = new QStandardItem(); maxValueItem->setData(static_cast(max_value), Qt::DisplayRole); + maxValueItem->setData(static_cast(max_value), ScaleSortRole); rowItems.append(maxValueItem); QStandardItem *scaleFactorItem = new QStandardItem(); - if (std::isfinite(image_scale_factor)) + if (std::isfinite(image_scale_factor)) { scaleFactorItem->setData(image_scale_factor, Qt::DisplayRole); - else + scaleFactorItem->setData(image_scale_factor, ScaleSortRole); + } else { scaleFactorItem->setData("N/A", Qt::DisplayRole); + scaleFactorItem->setData(ScaleNotAvailableSortValue, ScaleSortRole); + } rowItems.append(scaleFactorItem); QStandardItem *scaleCCItem = new QStandardItem(); - if (std::isfinite(image_scale_cc_percent)) - scaleCCItem->setData(image_scale_cc_percent, Qt::DisplayRole); - else + if (std::isfinite(image_scale_cc_percent)) { + scaleCCItem->setData(QString::number(image_scale_cc_percent, 'f', 1) + "%", Qt::DisplayRole); + + scaleCCItem->setData(image_scale_cc_percent, ScaleSortRole); + } else { scaleCCItem->setData("N/A", Qt::DisplayRole); + scaleCCItem->setData(ScaleNotAvailableSortValue, ScaleSortRole); + } rowItems.append(scaleCCItem); + QStandardItem *scaleBItem = new QStandardItem(); + if (std::isfinite(image_scale_b)) { + scaleBItem->setData(QString::number(image_scale_b, 'f', 2), Qt::DisplayRole); + scaleBItem->setData(image_scale_b, ScaleSortRole); + } else { + scaleBItem->setData("N/A", Qt::DisplayRole); + scaleBItem->setData(ScaleNotAvailableSortValue, ScaleSortRole); + } + rowItems.append(scaleBItem); + tableModel->appendRow(rowItems); } @@ -148,6 +178,10 @@ void JFJochViewerImageListWindow::datasetLoaded(std::shared_ptrimage_scale_cc.size() > i) image_scale_cc_percent = dataset->image_scale_cc[i] * 100.0; + double image_scale_b = NAN; + if (dataset->image_scale_b.size() > i) + image_scale_b = dataset->image_scale_b[i]; + addDataRow(i + 1, bkg_estimate, indexing_result, @@ -155,7 +189,8 @@ void JFJochViewerImageListWindow::datasetLoaded(std::shared_ptr