jfjoch_viewer: Change mouse clicks to draw ROI (shift + ctrl with left click)
Some checks failed
Build Packages / build:rpm (ubuntu2404_nocuda) (push) Successful in 11m12s
Build Packages / build:rpm (rocky8_nocuda) (push) Successful in 12m18s
Build Packages / Generate python client (push) Successful in 22s
Build Packages / build:rpm (ubuntu2204) (push) Successful in 12m55s
Build Packages / build:rpm (ubuntu2204_nocuda) (push) Successful in 13m6s
Build Packages / Create release (push) Has been skipped
Build Packages / Build documentation (push) Successful in 32s
Build Packages / build:rpm (rocky8) (push) Successful in 13m12s
Build Packages / build:rpm (rocky8_sls9) (push) Successful in 13m18s
Build Packages / build:rpm (rocky9_nocuda) (push) Successful in 13m50s
Build Packages / build:rpm (rocky9) (push) Successful in 13m48s
Build Packages / build:rpm (ubuntu2404) (push) Successful in 6m50s
Build Packages / Unit tests (push) Failing after 49m46s

This commit is contained in:
2025-11-01 10:57:39 +01:00
parent 40c2e2ad59
commit 4f7f5bb36d

View File

@@ -88,24 +88,25 @@ void JFJochViewerImage::mousePressEvent(QMouseEvent *event) {
}
if (event->button() == Qt::LeftButton) {
setCursor(Qt::ClosedHandCursor); // Change cursor to indicate panning
lastMousePos = event->pos();
if (event->modifiers() & Qt::Modifier::SHIFT) {
setCursor(Qt::CursorShape::CrossCursor);
if (mouse_inside_roi)
mouse_event_type = MouseEventType::MovingROI;
else
mouse_event_type = MouseEventType::Panning;
if (mouse_inside_roi) {
roiEndPos = RoundPoint(mapToScene(event->pos()));
} else {
roiStartPos = RoundPoint(mapToScene(event->pos()));
roi_type = (event->modifiers() & Qt::Modifier::CTRL) ? RoiType::RoiCircle : RoiType::RoiBox;
}
mouse_event_type = MouseEventType::DrawingROI;
} else {
setCursor(Qt::ClosedHandCursor); // Change cursor to indicate panning
lastMousePos = event->pos();
} else if (event->buttons() & Qt::RightButton) {
setCursor(Qt::CursorShape::CrossCursor);
if (mouse_inside_roi)
roiEndPos = RoundPoint(mapToScene(event->pos()));
else {
roiStartPos = RoundPoint(mapToScene(event->pos()));
roi_type = (event->modifiers() == Qt::Modifier::SHIFT) ? RoiType::RoiCircle : RoiType::RoiBox;
if (mouse_inside_roi)
mouse_event_type = MouseEventType::MovingROI;
else
mouse_event_type = MouseEventType::Panning;
}
mouse_event_type = MouseEventType::DrawingROI;
}
QGraphicsView::mousePressEvent(event); // Call base implementation
}
@@ -120,7 +121,6 @@ void JFJochViewerImage::mouseMoveEvent(QMouseEvent *event) {
&& (coord.x() < image->Dataset().experiment.GetXPixelsNum())
&& (coord.y() >= 0)
&& (coord.y() < image->Dataset().experiment.GetYPixelsNum())) {
float res = image->Dataset().experiment.GetDiffractionGeometry().PxlToRes(coord.x(), coord.y());
float q = 2 * M_PI / res;
if (res <= 0)
@@ -139,12 +139,12 @@ void JFJochViewerImage::mouseMoveEvent(QMouseEvent *event) {
intensity_str = " Bad pxl ";
emit writeStatusBar(QString("x=%1 y=%2 %3 d=%4 Å")
.arg(coord.x(), 0, 'f', 1)
.arg(coord.y(), 0, 'f', 1)
.arg(intensity_str)
.arg(res, 0, 'f', 2));
.arg(coord.x(), 0, 'f', 1)
.arg(coord.y(), 0, 'f', 1)
.arg(intensity_str)
.arg(res, 0, 'f', 2));
} else
emit writeStatusBar("");
emit writeStatusBar("");
QPointF delta;
switch (mouse_event_type) {
@@ -193,14 +193,15 @@ void JFJochViewerImage::LoadImageInternal() {
return;
// Create a QImage with RGB format
QImage qimage(image->Dataset().experiment.GetXPixelsNum(), image->Dataset().experiment.GetYPixelsNum(), QImage::Format_RGB888);
QImage qimage(image->Dataset().experiment.GetXPixelsNum(), image->Dataset().experiment.GetYPixelsNum(),
QImage::Format_RGB888);
image_rgb.resize(image->Dataset().experiment.GetXPixelsNum() * image->Dataset().experiment.GetYPixelsNum());
rgb sat_color{};
int r,g,b,a;
int r, g, b, a;
feature_color.getRgb(&r, &g, &b, &a);
auto bad_color = rgb{.r = static_cast<uint8_t>(r), .g = static_cast<uint8_t>(g), .b= static_cast<uint8_t>(b)};
auto bad_color = rgb{.r = static_cast<uint8_t>(r), .g = static_cast<uint8_t>(g), .b = static_cast<uint8_t>(b)};
if (show_saturation) {
sat_color = bad_color;
@@ -236,16 +237,16 @@ void JFJochViewerImage::LoadImageInternal() {
pixmap = QPixmap::fromImage(qimage);
QGraphicsScene* currentScene = scene();
QGraphicsScene *currentScene = scene();
if (!currentScene) {
// First time - create a new scene
currentScene = new QGraphicsScene(this);
setScene(currentScene);
}
}
void JFJochViewerImage::DrawSpots() {// Compute current visible area in scene coordinates
void JFJochViewerImage::DrawSpots() {
// Compute current visible area in scene coordinates
const QRectF visibleRect = mapToScene(viewport()->geometry()).boundingRect();
for (const auto &s: image->ImageData().spots) {
@@ -274,7 +275,6 @@ void JFJochViewerImage::DrawSpots() {// Compute current visible area in scene co
}
void JFJochViewerImage::DrawPredictions() {
QFont font("Arial", 2); // Font for pixel value text
font.setPixelSize(2); // This will render very small text (1-pixel high).
@@ -295,10 +295,10 @@ void JFJochViewerImage::DrawPredictions() {
continue;
auto rect = scene()->addEllipse(s.predicted_x - spot_size + 0.5f,
s.predicted_y - spot_size + 0.5f,
2.0f * spot_size,
2.0f * spot_size,
pen);
s.predicted_y - spot_size + 0.5f,
2.0f * spot_size,
2.0f * spot_size,
pen);
// When zoomed in enough, draw "h k l" above the box
if (scale_factor >= 10.0) {
@@ -315,7 +315,6 @@ void JFJochViewerImage::DrawPredictions() {
textItem->setPos(text_x, text_y); // Position the text over the pixel
// textItem->setScale(1.0); // Scale down to 10% of the original size
}
}
}
@@ -324,9 +323,11 @@ void JFJochViewerImage::DrawResolutionRings() {
QRectF visibleRect = mapToScene(viewport()->geometry()).boundingRect();
int startX = std::max(0, static_cast<int>(std::floor(visibleRect.left())));
int endX = std::min(static_cast<int>(image->Dataset().experiment.GetXPixelsNum()), static_cast<int>(std::ceil(visibleRect.right())));
int endX = std::min(static_cast<int>(image->Dataset().experiment.GetXPixelsNum()),
static_cast<int>(std::ceil(visibleRect.right())));
int startY = std::max(0, static_cast<int>(std::floor(visibleRect.top())));
int endY = std::min(static_cast<int>(image->Dataset().experiment.GetYPixelsNum()), static_cast<int>(std::ceil(visibleRect.bottom())));
int endY = std::min(static_cast<int>(image->Dataset().experiment.GetYPixelsNum()),
static_cast<int>(std::ceil(visibleRect.bottom())));
auto geom = image->Dataset().experiment.GetDiffractionGeometry();
geom.PoniRot3_rad(0.0);
@@ -349,8 +350,10 @@ void JFJochViewerImage::DrawResolutionRings() {
radius = radius_x;
if (radius > 0)
res_ring = {geom.PxlToRes(radius / 2.0f),
geom.PxlToRes(radius / 1.02f)};
res_ring = {
geom.PxlToRes(radius / 2.0f),
geom.PxlToRes(radius / 1.02f)
};
else
res_ring = {};
}
@@ -369,12 +372,12 @@ void JFJochViewerImage::DrawResolutionRings() {
auto [x3,y3] = geom.ResPhiToPxl(d, M_PI);
auto [x4,y4] = geom.ResPhiToPxl(d, 3.0 * M_PI_2);
auto x_min = std::min({x1,x2,x3,x4});
auto x_max = std::max({x1,x2,x3,x4});
auto y_min = std::min({y1,y2,y3,y4});
auto y_max = std::max({y1,y2,y3,y4});
auto x_min = std::min({x1, x2, x3, x4});
auto x_max = std::max({x1, x2, x3, x4});
auto y_min = std::min({y1, y2, y3, y4});
auto y_max = std::max({y1, y2, y3, y4});
QRectF boundingRect(x_min, y_min, x_max - x_min, y_max-y_min);
QRectF boundingRect(x_min, y_min, x_max - x_min, y_max - y_min);
scene()->addEllipse(boundingRect, pen);
auto [x5,y5] = geom.ResPhiToPxl(d, phi_offset + 0);
@@ -383,7 +386,7 @@ void JFJochViewerImage::DrawResolutionRings() {
auto [x8,y8] = geom.ResPhiToPxl(d, phi_offset + 3.0 * M_PI_2);
QPointF point_1(x5, y5);
QPointF point_2(x6,y6);
QPointF point_2(x6, y6);
QPointF point_3(x7, y7);
QPointF point_4(x8, y8);
std::optional<QPointF> point;
@@ -404,7 +407,7 @@ void JFJochViewerImage::DrawResolutionRings() {
font.setPointSizeF(16.0 / sqrt(f)); // base 12pt around scale_factor ~10
QGraphicsTextItem *textItem = scene()->addText(
QString("%1 Å").arg(QString::number(d, 'f', 2)), font);
QString("%1 Å").arg(QString::number(d, 'f', 2)), font);
textItem->setDefaultTextColor(feature_color);
textItem->setPos(point.value());
}
@@ -424,7 +427,8 @@ void JFJochViewerImage::DrawTopPixels() {
for (auto iter = image->ValidPixels().crbegin();
iter != image->ValidPixels().rend() && i < show_highest_pixels;
iter++, i++)
DrawCross(iter->second % image->Dataset().experiment.GetXPixelsNum() + 0.5, iter->second / image->Dataset().experiment.GetXPixelsNum() + 0.5, 15, 3);
DrawCross(iter->second % image->Dataset().experiment.GetXPixelsNum() + 0.5,
iter->second / image->Dataset().experiment.GetXPixelsNum() + 0.5, 15, 3);
}
void JFJochViewerImage::updateROI() {
@@ -436,7 +440,7 @@ void JFJochViewerImage::updateROI() {
QPointF delta = roiStartPos - roiEndPos;
double radius = std::sqrt(delta.x() * delta.x() + delta.y() * delta.y());
roi_box = QRectF(roiStartPos.x() - radius, roiStartPos.y() - radius,
2 * radius, 2 * radius).normalized();
2 * radius, 2 * radius).normalized();
emit roiCircleUpdated(roiStartPos.x(), roiStartPos.y(), radius);
}
updateOverlay();
@@ -456,9 +460,11 @@ void JFJochViewerImage::updateOverlay() {
// Calculate the range of pixels to process
int startX = std::max(0, static_cast<int>(std::floor(visibleRect.left())));
int endX = std::min(static_cast<int>(image->Dataset().experiment.GetXPixelsNum()), static_cast<int>(std::ceil(visibleRect.right())));
int endX = std::min(static_cast<int>(image->Dataset().experiment.GetXPixelsNum()),
static_cast<int>(std::ceil(visibleRect.right())));
int startY = std::max(0, static_cast<int>(std::floor(visibleRect.top())));
int endY = std::min(static_cast<int>(image->Dataset().experiment.GetYPixelsNum()), static_cast<int>(std::ceil(visibleRect.bottom())));
int endY = std::min(static_cast<int>(image->Dataset().experiment.GetYPixelsNum()),
static_cast<int>(std::ceil(visibleRect.bottom())));
if (scale_factor > 20.0 && (endX - startX + 1) * (endY - startY + 1) < 500) {
// Iterate through the pixels within the visible range
@@ -482,7 +488,7 @@ void JFJochViewerImage::updateOverlay() {
textItem->setDefaultTextColor(Qt::black); // Text color
else
textItem->setDefaultTextColor(Qt::white); // Text color
textItem->setPos(x-0.7, y-0.8); // Position the text over the pixel
textItem->setPos(x - 0.7, y - 0.8); // Position the text over the pixel
textItem->setScale(0.2); // Scale down to 10% of the original size
}
}
@@ -509,7 +515,7 @@ void JFJochViewerImage::updateOverlay() {
scene()->addEllipse(roi_box, pen);
double pointRadius = 0.5;
QRectF pointBoundingBox = QRectF(roiStartPos.x() - pointRadius,roiStartPos.y() - pointRadius,
QRectF pointBoundingBox = QRectF(roiStartPos.x() - pointRadius, roiStartPos.y() - pointRadius,
2 * pointRadius, 2 * pointRadius);
scene()->addEllipse(pointBoundingBox, pen);
}
@@ -565,7 +571,8 @@ void JFJochViewerImage::setColorMap(int color_map) {
try {
color_scale.Select(static_cast<ColorScaleEnum>(color_map));
Redraw();
} catch (...) {}
} catch (...) {
}
}
void JFJochViewerImage::setResolutionRing(QVector<float> v) {
@@ -611,7 +618,8 @@ void JFJochViewerImage::showHighestPixels(int32_t v) {
void JFJochViewerImage::DrawSaturation() {
for (const auto &iter: image->SaturatedPixels())
DrawCross(iter % image->Dataset().experiment.GetXPixelsNum() + 0.5, iter / image->Dataset().experiment.GetXPixelsNum() + 0.5, 20, 4);
DrawCross(iter % image->Dataset().experiment.GetXPixelsNum() + 0.5,
iter / image->Dataset().experiment.GetXPixelsNum() + 0.5, 20, 4);
}
void JFJochViewerImage::DrawCross(float x, float y, float size, float width, float z) {
@@ -620,11 +628,11 @@ void JFJochViewerImage::DrawCross(float x, float y, float size, float width, flo
QPen pen(feature_color, width);
pen.setCosmetic(true);
QGraphicsLineItem *horizontalLine = scene()->addLine(x - sc_size,y, x + sc_size, y, pen);
QGraphicsLineItem *horizontalLine = scene()->addLine(x - sc_size, y, x + sc_size, y, pen);
QGraphicsLineItem *verticalLine = scene()->addLine(x, y - sc_size, x, y + sc_size, pen);
horizontalLine->setZValue(z); // Ensure it appears above other items
verticalLine->setZValue(z); // Ensure it appears above other items
verticalLine->setZValue(z); // Ensure it appears above other items
}
void JFJochViewerImage::showSaturation(bool input) {