From 189da15810deabd739d7c11c6e95fea55739fe60 Mon Sep 17 00:00:00 2001 From: Thomas White Date: Sat, 1 Aug 2020 15:13:49 +0200 Subject: Initial import from archive --- src/dpsynth.c | 291 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 291 insertions(+) create mode 100644 src/dpsynth.c (limited to 'src/dpsynth.c') diff --git a/src/dpsynth.c b/src/dpsynth.c new file mode 100644 index 0000000..33e9c3e --- /dev/null +++ b/src/dpsynth.c @@ -0,0 +1,291 @@ +/* + * dpsynth.c + * + * Draw synthetic diffraction patterns + * + * (c) 2006-2009 Thomas White + * (c) 2007-2008 Alex Eggeman + * + * synth2d - Two-Dimensional Crystallographic Fourier Synthesis + * + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include +#include + +#if HAVE_CAIRO +#include +#endif + +#include + +#include "reflist.h" +#include "data.h" +#include "displaywindow.h" +#include "colwheel.h" +#include "gsf.h" +#include "normalise.h" + +typedef struct { + GtkWidget *image_widget; + GdkPixbuf *pixbuf; + GtkWidget *window; + unsigned int width; + unsigned int height; + unsigned int colour; + +} DPSynthWindow; + +#if HAVE_CAIRO +static void dpsynth_swizzle_data(unsigned char *data, + size_t width, size_t height) +{ + size_t i, x, y; + uint32_t *dataw; + + for ( i=0; i<4*width*height; i+=4 ) { + unsigned char a, r, g, b; + r = data[i]; g = data[i+1]; b = data[i+2]; a = data[i+3]; + data[i] = b; data[i+1] = g; data[i+2] = r; data[i+3] = a; + } + + /* Now make it be the right way up */ + dataw = (uint32_t *)data; + for ( y=0; ywidth, dpsynth->height); + + if ( cairo_surface_status(surface) != CAIRO_STATUS_SUCCESS ) { + fprintf(stderr, "Couldn't create Cairo surface\n"); + cairo_surface_destroy(surface); + return NULL; + } + + dctx = cairo_create(surface); + + /* Black background */ + cairo_rectangle(dctx, 0.0, 0.0, dpsynth->width, dpsynth->height); + cairo_set_source_rgb(dctx, 0.0, 0.0, 0.0); + + cairo_fill(dctx); + + max_u = 0.0; max_v = 0.0; max_intensity = 0.0; + max_res = 0.0; + /* NB This isn't really "the angle between a* and b*" */ + theta = data_gamma()-M_PI_2; + as = 1/(data_a() * cos(theta)); + bs = 1/(data_b() * cos(theta)); + for ( i=0; in_reflections; i++ ) { + + double u, v, intensity, ph, res; + + /* Convert to intensity */ + intensity = pow(reflections->refs[i].amplitude, 2.0); + ph = reflections->refs[i].phase_known; + + res = resolution(reflections->refs[i].h, + reflections->refs[i].k, + reflections->refs[i].l, + data_a(), data_b(), data_c(), data_gamma()); + if ( res > max_res ) max_res = res; + + if ( intensity != 0 ) { + u = (double)reflections->refs[i].h * as * cos(theta); + v = (double)reflections->refs[i].h * as * sin(theta) + + reflections->refs[i].k * bs; + if ( fabs(u) > fabs(max_u) ) max_u = fabs(u); + if ( fabs(v) > fabs(max_v) ) max_v = fabs(v); + if ( fabs(intensity) > fabs(max_intensity) ) + max_intensity = fabs(intensity); + } + + } + + max_u *= 2.5; + max_v *= 2.5; + printf("DP: Maximum resolution is %f nm^-1\n", max_res); + + if ( max_intensity > 0 ) { + + scale = ((double)dpsynth->width-50.0) / (2*max_u); + if ( ((double)dpsynth->height-50.0) / (2*max_v) < scale ) + scale = ((double)dpsynth->height-50.0) / (2*max_v); + + sep_u = as * scale * cos(theta); + sep_v = bs * scale; + max_r = ((sep_u < sep_v)?sep_u:sep_v) / 2; + + for ( i=0; in_reflections; i++ ) { + + double u, v, intensity, ph, val; + + intensity = pow(reflections->refs[i].amplitude, 2.0); + ph = reflections->refs[i].phase_known; + val = 2.0*intensity/max_intensity; + + if ( intensity != 0 ) { + + u = (double)reflections->refs[i].h * as + * cos(theta); + v = (double)reflections->refs[i].h * as + * sin(theta) + reflections->refs[i].k * bs; + + cairo_arc(dctx, ((double)dpsynth->width/2) + +u*scale*2, + ((double)dpsynth->height/2) + +v*scale*2, max_r, 0, 2*M_PI); + + + if ( dpsynth->colour == 0 ) { + cairo_set_source_rgb(dctx, val, val, val); } else { + cairo_set_source_rgb(dctx, + colwheel_red(val, ph), + colwheel_green(val, ph), + colwheel_blue(val, ph) + ); + } + cairo_fill(dctx); + + } + + } + + } else { + max_r = 4.0; + } + + /* Centre marker */ + cairo_arc(dctx, (double)dpsynth->width/2, + (double)dpsynth->height/2, max_r, 0, 2*M_PI); + cairo_set_source_rgb(dctx, 1.0, 0.0, 0.0); + cairo_fill(dctx); + + cairo_surface_flush(surface); + + data = cairo_image_surface_get_data(surface); + dpsynth_swizzle_data(data, cairo_image_surface_get_width(surface), + cairo_image_surface_get_height(surface)); + pixbuf = gdk_pixbuf_new_from_data(data, GDK_COLORSPACE_RGB, TRUE, 8, + cairo_image_surface_get_width(surface), + cairo_image_surface_get_height(surface), + cairo_image_surface_get_stride(surface), + (GdkPixbufDestroyNotify)dpsynth_free_data, dctx); + + return pixbuf; +#else + /* Cannot do this without Cairo */ + return NULL; +#endif +} + +static void dpsynth_close(GtkWidget *widget, DPSynthWindow *dpsynth) +{ + free(dpsynth); +} + +void dpsynth_update(DPSynthWindow *dpsynth, ReflectionList *reflections) +{ + if ( dpsynth->pixbuf ) gdk_pixbuf_unref(dpsynth->pixbuf); + + dpsynth->pixbuf = dpsynth_render_pixbuf(dpsynth, reflections); + if ( !dpsynth->pixbuf ) return; + + if ( dpsynth->image_widget ) { + g_object_set(G_OBJECT(dpsynth->image_widget), "pixbuf", + dpsynth->pixbuf, NULL); + } else { + dpsynth->image_widget = gtk_image_new_from_pixbuf( + dpsynth->pixbuf); + gtk_container_add(GTK_CONTAINER(dpsynth->window), + GTK_WIDGET(dpsynth->image_widget)); + gtk_widget_show(dpsynth->image_widget); + } +} + +DPSynthWindow *dpsynth_open(ReflectionList *reflections, const char *title, + int colour) +{ + DPSynthWindow *dpsynth; + + dpsynth = malloc(sizeof(DPSynthWindow)); + dpsynth->width = 512; + dpsynth->height = 512; + dpsynth->pixbuf = NULL; + dpsynth->image_widget = NULL; + dpsynth->colour = colour; + + dpsynth->window = gtk_window_new(GTK_WINDOW_TOPLEVEL); + gtk_window_set_title(GTK_WINDOW(dpsynth->window), title); + g_signal_connect(GTK_OBJECT(dpsynth->window), "destroy", + G_CALLBACK(dpsynth_close), dpsynth); + gtk_widget_show_all(dpsynth->window); + + dpsynth_update(dpsynth, reflections); + + return dpsynth; +} + +/* "Glue" - to be removed eventually... */ +DPSynthWindow *dpsynth_main_dpsynth = NULL; +static void dpsynth_main_close(GtkWidget *widget, DPSynthWindow *dpsynth) { + dpsynth_main_dpsynth = NULL; +} +void dpsynth_main_update(ReflectionList *reflections) { + if ( !dpsynth_main_dpsynth ) return; + dpsynth_update(dpsynth_main_dpsynth, reflections); +} +void dpsynth_main_open(ReflectionList *reflections) { + if ( dpsynth_main_dpsynth ) return; + dpsynth_main_dpsynth = dpsynth_open(reflections, "Diffraction Pattern", 0); + g_signal_connect(GTK_OBJECT(dpsynth_main_dpsynth->window), "destroy", G_CALLBACK(dpsynth_main_close), dpsynth_main_dpsynth); +} + +DPSynthWindow *dpsynth_sim_dpsynth = NULL; +static void dpsynth_simdp_close(GtkWidget *widget, DPSynthWindow *dpsynth) { + dpsynth_sim_dpsynth = NULL; +} +void dpsynth_simdp_update(ReflectionList *reflections) { + if ( !dpsynth_sim_dpsynth ) return; + dpsynth_update(dpsynth_sim_dpsynth, reflections); +} +void dpsynth_simdp_open(ReflectionList *reflections) { + if ( dpsynth_sim_dpsynth ) return; + dpsynth_sim_dpsynth = dpsynth_open(reflections, "Simulated Diffraction Pattern", 0); + g_signal_connect(GTK_OBJECT(dpsynth_sim_dpsynth->window), "destroy", G_CALLBACK(dpsynth_simdp_close), dpsynth_sim_dpsynth); +} -- cgit v1.2.3