jfjoch_viewer: Better display (to be tested) of pixel refine
Build Packages / Unit tests (push) Failing after 1s
Build Packages / build:rpm (ubuntu2404_nocuda) (push) Successful in 25m52s
Build Packages / build:rpm (ubuntu2204_nocuda) (push) Successful in 29m5s
Build Packages / build:rpm (rocky8_nocuda) (push) Successful in 29m54s
Build Packages / build:rpm (rocky8) (push) Successful in 31m55s
Build Packages / build:rpm (rocky8_sls9) (push) Successful in 32m12s
Build Packages / build:rpm (rocky9_nocuda) (push) Successful in 32m48s
Build Packages / build:rpm (rocky9_sls9) (push) Successful in 35m27s
Build Packages / Generate python client (push) Successful in 25s
Build Packages / build:rpm (rocky9) (push) Successful in 31m59s
Build Packages / Create release (push) Skipped
Build Packages / Build documentation (push) Successful in 1m36s
Build Packages / build:rpm (ubuntu2204) (push) Successful in 24m8s
Build Packages / XDS test (neggia plugin) (push) Successful in 17m46s
Build Packages / build:rpm (ubuntu2404) (push) Successful in 21m36s
Build Packages / XDS test (durin plugin) (push) Successful in 19m40s
Build Packages / XDS test (JFJoch plugin) (push) Successful in 19m38s
Build Packages / DIALS test (push) Successful in 26m30s
Build Packages / Unit tests (push) Failing after 1s
Build Packages / build:rpm (ubuntu2404_nocuda) (push) Successful in 25m52s
Build Packages / build:rpm (ubuntu2204_nocuda) (push) Successful in 29m5s
Build Packages / build:rpm (rocky8_nocuda) (push) Successful in 29m54s
Build Packages / build:rpm (rocky8) (push) Successful in 31m55s
Build Packages / build:rpm (rocky8_sls9) (push) Successful in 32m12s
Build Packages / build:rpm (rocky9_nocuda) (push) Successful in 32m48s
Build Packages / build:rpm (rocky9_sls9) (push) Successful in 35m27s
Build Packages / Generate python client (push) Successful in 25s
Build Packages / build:rpm (rocky9) (push) Successful in 31m59s
Build Packages / Create release (push) Skipped
Build Packages / Build documentation (push) Successful in 1m36s
Build Packages / build:rpm (ubuntu2204) (push) Successful in 24m8s
Build Packages / XDS test (neggia plugin) (push) Successful in 17m46s
Build Packages / build:rpm (ubuntu2404) (push) Successful in 21m36s
Build Packages / XDS test (durin plugin) (push) Successful in 19m40s
Build Packages / XDS test (JFJoch plugin) (push) Successful in 19m38s
Build Packages / DIALS test (push) Successful in 26m30s
This commit is contained in:
@@ -8,6 +8,7 @@
|
||||
#include <cstring>
|
||||
|
||||
#include "JFJochImageReadingWorker.h"
|
||||
#include "../reader/JFJochReaderImage.h" // JFJochReaderImage + GAP/ERROR/SATURATED sentinels
|
||||
#include "../image_analysis/LoadFCalcFromMtz.h"
|
||||
#include "../image_analysis/bragg_prediction/BraggPredictionFactory.h"
|
||||
#include "../image_analysis/geom_refinement/AssignSpotsToRings.h"
|
||||
@@ -69,6 +70,7 @@ JFJochImageReadingWorker::JFJochImageReadingWorker(const SpotFindingSettings &se
|
||||
indexing_settings(experiment.GetIndexingSettings()),
|
||||
azint_settings(experiment.GetAzimuthalIntegrationSettings()) {
|
||||
qRegisterMetaType<PixelRefineParams>("PixelRefineParams");
|
||||
qRegisterMetaType<QVector<QRect>>("QVector<QRect>");
|
||||
spot_finding_settings = settings;;
|
||||
|
||||
indexing = std::make_unique<IndexerThreadPool>(indexing_settings);
|
||||
@@ -798,6 +800,74 @@ std::shared_ptr<SimpleImage> JFJochImageReadingWorker::WrapFloatImage_i(const st
|
||||
return si;
|
||||
}
|
||||
|
||||
void JFJochImageReadingWorker::SquaredResidualWithImage_i(std::vector<float> &pred) const {
|
||||
// PredictImage() returns raw detector units (same as the measured counts), so
|
||||
// pred - measured is the per-pixel residual the model fails to explain. We plot
|
||||
// |pred - measured|^2: sign-free, so it needs no diverging colour scale and just
|
||||
// highlights where the model disagrees most. Masked / saturated pixels carry
|
||||
// sentinels rather than counts, so no comparison is possible -> NaN (gap).
|
||||
if (!current_image_ptr)
|
||||
return;
|
||||
const auto &img = current_image_ptr->Image();
|
||||
const size_t n = std::min(pred.size(), img.size());
|
||||
for (size_t i = 0; i < n; ++i) {
|
||||
const int32_t v = img[i];
|
||||
if (v == GAP_PXL_VALUE || v == ERROR_PXL_VALUE || v == SATURATED_PXL_VALUE) {
|
||||
pred[i] = NAN;
|
||||
} else {
|
||||
const float diff = pred[i] - static_cast<float>(v);
|
||||
pred[i] = diff * diff;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void JFJochImageReadingWorker::MaskMeasuredSentinels_i(std::vector<float> &img) const {
|
||||
// The chi^2 image is 0 outside shoeboxes; show masked/saturated pixels as a gap
|
||||
// (NaN) instead, so they read as "not comparable" rather than "zero cost".
|
||||
if (!current_image_ptr)
|
||||
return;
|
||||
const auto &measured = current_image_ptr->Image();
|
||||
const size_t n = std::min(img.size(), measured.size());
|
||||
for (size_t i = 0; i < n; ++i) {
|
||||
const int32_t v = measured[i];
|
||||
if (v == GAP_PXL_VALUE || v == ERROR_PXL_VALUE || v == SATURATED_PXL_VALUE)
|
||||
img[i] = NAN;
|
||||
}
|
||||
}
|
||||
|
||||
QVector<QRect> JFJochImageReadingWorker::BuildShoeboxes_i(const PixelRefineData &data) const {
|
||||
// One rectangle per fitted reflection: the shoebox the optimizer summed over,
|
||||
// centred on the predicted position with half-size data.shoebox_radius.
|
||||
QVector<QRect> boxes;
|
||||
boxes.reserve(static_cast<int>(data.reflections.size()));
|
||||
const int r = data.shoebox_radius;
|
||||
const int side = 2 * r + 1;
|
||||
for (const auto &refl : data.reflections) {
|
||||
if (!std::isfinite(refl.predicted_x) || !std::isfinite(refl.predicted_y))
|
||||
continue;
|
||||
const int cx = static_cast<int>(std::lround(refl.predicted_x));
|
||||
const int cy = static_cast<int>(std::lround(refl.predicted_y));
|
||||
boxes.push_back(QRect(cx - r, cy - r, side, side));
|
||||
}
|
||||
return boxes;
|
||||
}
|
||||
|
||||
std::vector<float> JFJochImageReadingWorker::BuildDisplayImage_i(const PixelRefineData &data,
|
||||
int display_mode) const {
|
||||
if (display_mode == PixelRefineParams::ChiSquared) {
|
||||
// The cost density the optimizer actually minimizes (weighted residual^2).
|
||||
const auto &img32 = current_image_ptr->Image();
|
||||
auto chi2 = pixel_refine_->ChiSquaredImage<int32_t>(img32.data(), *last_profile_, *pixel_pred_, data);
|
||||
MaskMeasuredSentinels_i(chi2);
|
||||
return chi2;
|
||||
}
|
||||
|
||||
auto pred = pixel_refine_->PredictImage(*last_profile_, *pixel_pred_, data, true);
|
||||
if (display_mode == PixelRefineParams::SquaredDifference)
|
||||
SquaredResidualWithImage_i(pred);
|
||||
return pred;
|
||||
}
|
||||
|
||||
void JFJochImageReadingWorker::LoadReference(QString path) {
|
||||
QMutexLocker ul(&m);
|
||||
try {
|
||||
@@ -840,8 +910,9 @@ void JFJochImageReadingWorker::PixelRefinePreview(PixelRefineParams params) {
|
||||
pixel_refine_->Run<int32_t>(img32.data(), *last_profile_, *pixel_pred_, d);
|
||||
emit pixelRefineResidual(d.final_cost, d.cc, static_cast<int64_t>(d.reflections.size()));
|
||||
|
||||
auto pred = pixel_refine_->PredictImage(*last_profile_, *pixel_pred_, d, true);
|
||||
emit predictedImageReady(WrapFloatImage_i(pred));
|
||||
auto display = BuildDisplayImage_i(d, params.display_mode);
|
||||
emit predictedImageReady(WrapFloatImage_i(display));
|
||||
emit predictedShoeboxes(BuildShoeboxes_i(d));
|
||||
} catch (const std::exception &e) {
|
||||
emit pixelRefineStatus(QString("PixelRefine preview failed: %1").arg(e.what()));
|
||||
}
|
||||
@@ -884,8 +955,9 @@ void JFJochImageReadingWorker::PixelRefineRun(PixelRefineParams params) {
|
||||
emit pixelRefineParamsRefined(out);
|
||||
emit pixelRefineResidual(d.final_cost, d.cc, static_cast<int64_t>(d.reflections.size()));
|
||||
|
||||
auto pred = pixel_refine_->PredictImage(*last_profile_, *pixel_pred_, d, true);
|
||||
emit predictedImageReady(WrapFloatImage_i(pred));
|
||||
auto display = BuildDisplayImage_i(d, params.display_mode);
|
||||
emit predictedImageReady(WrapFloatImage_i(display));
|
||||
emit predictedShoeboxes(BuildShoeboxes_i(d));
|
||||
|
||||
// Show the refined predictions on the main image too.
|
||||
auto new_image = std::make_shared<JFJochReaderImage>(*current_image_ptr);
|
||||
|
||||
Reference in New Issue
Block a user