From 4464b2fc8d2840d489a839e4973fab1e71144efc Mon Sep 17 00:00:00 2001 From: Thomas White Date: Tue, 23 Aug 2022 15:56:57 +0200 Subject: GUI: Add resolution rings It will refuse to draw the rings if the detector is too far from being flat (as judged by detgeom_mean_camera_length). Otherwise, the drawing is exactly the same as was done by hdfsee. --- src/crystfel_gui.c | 33 +++++++++++++++++++++++ src/crystfelimageview.c | 70 +++++++++++++++++++++++++++++++++++++++++++++++++ src/crystfelimageview.h | 4 +++ src/gui_project.c | 6 +++++ src/gui_project.h | 1 + 5 files changed, 114 insertions(+) (limited to 'src') diff --git a/src/crystfel_gui.c b/src/crystfel_gui.c index 066422a3..1c439b18 100644 --- a/src/crystfel_gui.c +++ b/src/crystfel_gui.c @@ -275,6 +275,8 @@ void update_imageview(struct crystfelproject *proj) proj->show_peaks); crystfel_image_view_set_show_centre(CRYSTFEL_IMAGE_VIEW(proj->imageview), proj->show_centre); + crystfel_image_view_set_resolution_rings(CRYSTFEL_IMAGE_VIEW(proj->imageview), + proj->resolution_rings); crystfel_image_view_set_image(CRYSTFEL_IMAGE_VIEW(proj->imageview), proj->cur_image); @@ -670,6 +672,30 @@ static gint show_centre_sig(GtkWidget *w, struct crystfelproject *proj) } +static gint resolution_rings_sig(GtkWidget *w, struct crystfelproject *proj) +{ + int tr = gtk_toggle_action_get_active(GTK_TOGGLE_ACTION(w)); + + if ( tr && proj->cur_image == NULL ) { + error_box(proj, "Load some images first!\n"); + return FALSE; + } + + if ( tr && isnan(detgeom_mean_camera_length(proj->cur_image->detgeom)) ) { + error_box(proj, "Cannot display resolution rings accurately " + "because detector is not flat enough"); + tr = FALSE; + gtk_toggle_action_set_active(GTK_TOGGLE_ACTION(w), FALSE); + } + + proj->resolution_rings = tr; + crystfel_image_view_set_resolution_rings(CRYSTFEL_IMAGE_VIEW(proj->imageview), + tr); + + return FALSE; +} + + static gint show_peaks_sig(GtkWidget *w, struct crystfelproject *proj) { proj->show_peaks = gtk_toggle_action_get_active(GTK_TOGGLE_ACTION(w)); @@ -711,6 +737,7 @@ static void add_menu_bar(struct crystfelproject *proj, GtkWidget *vbox) " " " " " " + " " " " " " "" @@ -757,6 +784,8 @@ static void add_menu_bar(struct crystfelproject *proj, GtkWidget *vbox) G_CALLBACK(label_refls_sig), FALSE }, { "CentreAction", NULL, "Beam centre", NULL, NULL, G_CALLBACK(show_centre_sig), FALSE }, + { "ResolutionRingsAction", NULL, "Resolution rings", NULL, NULL, + G_CALLBACK(resolution_rings_sig), FALSE }, { "RescanOnChangeAction", NULL, "Rescan streams when changing frame", NULL, NULL, G_CALLBACK(rescan_on_change_sig), FALSE }, }; @@ -1165,6 +1194,10 @@ int main(int argc, char *argv[]) gtk_toggle_action_set_active(GTK_TOGGLE_ACTION(act), proj.label_refls); + act = gtk_ui_manager_get_action(proj.ui, "/mainwindow/view/resrings"); + gtk_toggle_action_set_active(GTK_TOGGLE_ACTION(act), + proj.resolution_rings); + act = gtk_ui_manager_get_action(proj.ui, "/mainwindow/tools/rescanonchange"); gtk_toggle_action_set_active(GTK_TOGGLE_ACTION(act), proj.rescan_on_change); diff --git a/src/crystfelimageview.c b/src/crystfelimageview.c index 74d8cca5..88cfb149 100644 --- a/src/crystfelimageview.c +++ b/src/crystfelimageview.c @@ -603,6 +603,48 @@ static void draw_refls(cairo_t *cr, } +static double ring_radius(double d, double wl, double z) +{ + double theta = asin(wl / (2.0*d)); + return z * tan(2.0*theta); +} + + +static void show_ring(cairo_t *cr, double wl, double mean_z, + double d, const char *label, + double r, double g, double b) +{ + cairo_text_extents_t size; + double bs, lw; + double radius = ring_radius(d, wl, mean_z); + + if ( isnan(radius) ) return; + + bs = 17.0; + lw = 1.0; + cairo_device_to_user_distance(cr, &bs, &lw); + bs = fabs(bs); + lw = fabs(lw); + + cairo_save(cr); + + cairo_arc(cr, 0.0, 0.0, radius, 0.0, 2.0*M_PI); + cairo_set_source_rgb(cr, r, g, b); + cairo_set_line_width(cr, lw); + cairo_stroke(cr); + + cairo_rotate(cr, -M_PI/4.0); + cairo_scale(cr, 1.0, -1.0); + cairo_set_font_size(cr, bs); + cairo_text_extents(cr, label, &size); + cairo_translate(cr, -size.width/2.0, radius-5.0*lw); + cairo_show_text(cr, label); + cairo_fill(cr); + + cairo_restore(cr); +} + + static double crystal_cols[][3] = { {0.0, 1.0, 0.0}, /* bright green */ @@ -673,6 +715,24 @@ static gint draw_sig(GtkWidget *window, cairo_t *cr, CrystFELImageView *iv) } } + if ( iv->resolution_rings ) { + double wl = iv->image->lambda; + double mean_z = detgeom_mean_camera_length(iv->image->detgeom); + if ( !isnan(mean_z) ) { + show_ring(cr, wl, mean_z, 10.0e-10, "10A", 1.0, 0.0, 0.0); + show_ring(cr, wl, mean_z, 9.0e-10, "9A", 1.0, 0.0, 0.0); + show_ring(cr, wl, mean_z, 8.0e-10, "8A", 1.0, 0.0, 0.0); + show_ring(cr, wl, mean_z, 7.0e-10, "7A", 1.0, 0.5, 0.0); + show_ring(cr, wl, mean_z, 6.0e-10, "6A", 1.0, 1.0, 0.0); + show_ring(cr, wl, mean_z, 5.0e-10, "5A", 0.0, 1.0, 0.0); + show_ring(cr, wl, mean_z, 4.0e-10, "4A", 0.2, 1.0, 0.2); + show_ring(cr, wl, mean_z, 3.0e-10, "3A", 0.4, 1.0, 0.4); + show_ring(cr, wl, mean_z, 2.0e-10, "2A", 0.6, 1.0, 0.6); + show_ring(cr, wl, mean_z, 1.0e-10, "1A", 0.8, 1.0, 0.8); + show_ring(cr, wl, mean_z, 0.5e-10, "0.5A", 1.0, 1.0, 1.0); + } + } + cairo_restore(cr); return FALSE; @@ -847,6 +907,7 @@ GtkWidget *crystfel_image_view_new() iv->label_refls = 1; iv->need_rerender = 0; iv->need_recentre = 1; + iv->resolution_rings = 0; g_signal_connect(G_OBJECT(iv), "destroy", G_CALLBACK(destroy_sig), iv); @@ -1165,3 +1226,12 @@ void crystfel_image_view_set_refl_box_size(CrystFELImageView *iv, iv->need_rerender = 1; redraw(iv); } + + +void crystfel_image_view_set_resolution_rings(CrystFELImageView *iv, + int rings) +{ + iv->resolution_rings = rings; + iv->need_rerender = 1; + redraw(iv); +} diff --git a/src/crystfelimageview.h b/src/crystfelimageview.h index c53e4980..aa7d61d2 100644 --- a/src/crystfelimageview.h +++ b/src/crystfelimageview.h @@ -94,6 +94,7 @@ struct _crystfelimageview int label_refls; float peak_box_size; float refl_box_size; + int resolution_rings; }; struct _crystfelimageviewclass @@ -133,4 +134,7 @@ extern void crystfel_image_view_set_peak_box_size(CrystFELImageView *iv, extern void crystfel_image_view_set_refl_box_size(CrystFELImageView *iv, float box_size); +extern void crystfel_image_view_set_resolution_rings(CrystFELImageView *iv, + int rings); + #endif /* CRYSTFELIMAGEVIEW_H */ diff --git a/src/gui_project.c b/src/gui_project.c index 7ab4e367..00a217af 100644 --- a/src/gui_project.c +++ b/src/gui_project.c @@ -534,6 +534,10 @@ static void handle_var(const char *key, const char *val, proj->show_centre = parse_int(val); } + if ( strcmp(key, "resolution_rings") == 0 ) { + proj->resolution_rings = parse_int(val); + } + if ( strcmp(key, "rescan_on_change") == 0 ) { proj->rescan_on_change = parse_int(val); } @@ -1136,6 +1140,7 @@ int save_project(struct crystfelproject *proj) } fprintf(fh, "show_centre %i\n", proj->show_centre); + fprintf(fh, "resolution_rings %i\n", proj->resolution_rings); fprintf(fh, "show_peaks %i\n", proj->show_peaks); fprintf(fh, "show_refls %i\n", proj->show_refls); fprintf(fh, "label_refls %i\n", proj->label_refls); @@ -1229,6 +1234,7 @@ int default_project(struct crystfelproject *proj) /* Default parameter values */ proj->show_centre = 1; + proj->resolution_rings = 0; proj->show_peaks = 1; proj->show_refls = 1; proj->label_refls = 1; diff --git a/src/gui_project.h b/src/gui_project.h index 8ec81ee2..546bae9a 100644 --- a/src/gui_project.h +++ b/src/gui_project.h @@ -302,6 +302,7 @@ struct crystfelproject { char **filenames; char **events; int show_centre; + int resolution_rings; int rescan_on_change; int show_peaks; -- cgit v1.2.3