aboutsummaryrefslogtreecommitdiff
path: root/libcrystfel
diff options
context:
space:
mode:
authorThomas White <taw@physics.org>2022-09-22 14:07:34 +0200
committerThomas White <taw@physics.org>2022-09-22 14:07:34 +0200
commite8053e5386146bf88b2b45d028774da9f4439069 (patch)
tree2415e42b939631f5a100f255aec4dcfcfd2cfc4f /libcrystfel
parent7c42f8e2b675e017ab1144ca38c9e74c24d68266 (diff)
Implement data_template_get_2d_detgeom_if_possible
It is horrible. But it's contained inside the DataTemplate module.
Diffstat (limited to 'libcrystfel')
-rw-r--r--libcrystfel/src/datatemplate.c134
-rw-r--r--libcrystfel/src/datatemplate_priv.h3
-rw-r--r--libcrystfel/src/image.c11
-rw-r--r--libcrystfel/src/stream.c2
4 files changed, 138 insertions, 12 deletions
diff --git a/libcrystfel/src/datatemplate.c b/libcrystfel/src/datatemplate.c
index 8f909eb8..1075b349 100644
--- a/libcrystfel/src/datatemplate.c
+++ b/libcrystfel/src/datatemplate.c
@@ -1853,8 +1853,108 @@ static int im_get_length(struct image *image, const char *from,
}
+static int all_panels_reference_same_clen(const DataTemplate *dtempl)
+{
+ int i;
+ char *first_val = NULL;
+ char *first_units = NULL;
+ int fail = 0;
+
+ for ( i=0; i<dtempl->n_panels; i++ ) {
+ struct panel_template *p = &dtempl->panels[i];
+ char *val;
+ char *units;
+ if ( separate_value_and_units(p->cnz_from, &val, &units) ) {
+ /* Parse error */
+ return 0;
+ }
+ if ( i == 0 ) {
+ first_val = val;
+ first_units = units;
+ } else {
+ if ( strcmp(val, first_val) != 0 ) fail = 1;
+ if ( strcmp(units, first_units) != 0 ) fail = 1;
+ free(val);
+ free(units);
+ }
+ }
+
+ free(first_val);
+ free(first_units);
+ return fail;
+}
+
+
+static int all_coffsets_small(const DataTemplate *dtempl)
+{
+ int i;
+
+ for ( i=0; i<dtempl->n_panels; i++ ) {
+ struct panel_template *p = &dtempl->panels[i];
+ if ( p->cnz_offset > 10.0*p->pixel_pitch ) return 0;
+ }
+
+ return 1;
+}
+
+
+static int all_panels_same_clen(const DataTemplate *dtempl)
+{
+ int i;
+ double *zvals;
+ double total = 0.0;
+ double mean;
+
+ zvals = malloc(sizeof(double)*dtempl->n_panels);
+ if ( zvals == NULL ) return 0;
+
+ for ( i=0; i<dtempl->n_panels; i++ ) {
+ struct panel_template *p = &dtempl->panels[i];
+ if ( im_get_length(NULL, p->cnz_from, 1e-3, &zvals[i]) ) {
+ /* Can't get length because it used a header reference */
+ free(zvals);
+ return 0;
+ }
+ total += zvals[i];
+ }
+
+ mean = total/dtempl->n_panels;
+ for ( i=0; i<dtempl->n_panels; i++ ) {
+ struct panel_template *p = &dtempl->panels[i];
+ if ( fabs(zvals[i] - mean) > 10.0*p->pixel_pitch ) return 0;
+ }
+
+ free(zvals);
+
+ return 1;
+}
+
+
+static int all_panels_perpendicular_to_beam(const DataTemplate *dtempl)
+{
+ int i;
+
+ for ( i=0; i<dtempl->n_panels; i++ ) {
+ double z_diff;
+ struct panel_template *p = &dtempl->panels[i];
+ z_diff = p->fsz*PANEL_WIDTH(p) + p->ssz*PANEL_HEIGHT(p);
+ if ( z_diff > 10.0*p->pixel_pitch ) return 0;
+ }
+ return 1;
+}
+
+
+static int detector_flat(const DataTemplate *dtempl)
+{
+ return all_panels_perpendicular_to_beam(dtempl)
+ && ( (all_panels_reference_same_clen(dtempl) && all_coffsets_small(dtempl))
+ || all_panels_same_clen(dtempl) );
+}
+
+
struct detgeom *create_detgeom(struct image *image,
- const DataTemplate *dtempl)
+ const DataTemplate *dtempl,
+ int two_d_only)
{
struct detgeom *detgeom;
int i;
@@ -1875,6 +1975,12 @@ struct detgeom *create_detgeom(struct image *image,
detgeom->n_panels = dtempl->n_panels;
+ if ( two_d_only ) {
+ if ( !detector_flat(dtempl) ) return NULL;
+ if ( dtempl->shift_x_from != NULL ) return NULL;
+ if ( dtempl->shift_y_from != NULL ) return NULL;
+ }
+
for ( i=0; i<dtempl->n_panels; i++ ) {
struct detgeom_panel *p = &detgeom->panels[i];
@@ -1888,10 +1994,15 @@ struct detgeom *create_detgeom(struct image *image,
/* NB cnx,cny are in pixels, cnz is in m */
p->cnx = tmpl->cnx;
p->cny = tmpl->cny;
+
if ( im_get_length(image, tmpl->cnz_from, 1e-3, &p->cnz) )
{
- ERROR("Failed to read length from '%s'\n", tmpl->cnz_from);
- return NULL;
+ if ( two_d_only ) {
+ p->cnz = NAN;
+ } else {
+ ERROR("Failed to read length from '%s'\n", tmpl->cnz_from);
+ return NULL;
+ }
}
/* Apply offset (in m) and then convert cnz from
@@ -1959,4 +2070,21 @@ struct detgeom *create_detgeom(struct image *image,
return detgeom;
}
+
+/**
+ * Create a detgeom structure from the DataTemplate, if possible, and ignoring
+ * 3D information.
+ *
+ * This procedure will create a detgeom structure provided that the detector
+ * is close to lying in a single flat plane perpendicular to the beam
+ * direction. If certain things (e.g. panel z-positions) refer to headers,
+ * it might not be possible to determine that the detector is really flat
+ * until an image is loaded. Therefore you must gracefully handle a NULL
+ * return value from this routine.
+ *
+ * \returns the detgeom structure, or NULL if impossible.
+ */
+struct detgeom *data_template_get_2d_detgeom_if_possible(const DataTemplate *dt)
+{
+ return create_detgeom(NULL, dt, 1);
}
diff --git a/libcrystfel/src/datatemplate_priv.h b/libcrystfel/src/datatemplate_priv.h
index 3e61f216..26b90d6b 100644
--- a/libcrystfel/src/datatemplate_priv.h
+++ b/libcrystfel/src/datatemplate_priv.h
@@ -237,6 +237,7 @@ struct _datatemplate
extern double convert_to_m(double val, int units);
extern struct detgeom *create_detgeom(struct image *image,
- const DataTemplate *dtempl);
+ const DataTemplate *dtempl,
+ int two_d_only);
#endif /* DATATEMPLATE_PRIV_H */
diff --git a/libcrystfel/src/image.c b/libcrystfel/src/image.c
index 45b61bec..84088ead 100644
--- a/libcrystfel/src/image.c
+++ b/libcrystfel/src/image.c
@@ -412,11 +412,6 @@ static struct header_cache_entry *cached_header(struct image *image, const char
{
struct header_cache_entry *ce;
- if ( image == NULL ) {
- ERROR("Attempt to retrieve a header value without an image\n");
- return NULL;
- }
-
ce = find_cache_entry(image, from);
if ( ce != NULL ) return ce;
@@ -434,6 +429,8 @@ int image_read_header_float(struct image *image, const char *from, double *val)
{
struct header_cache_entry *ce;
+ if ( image == NULL ) return 1;
+
ce = cached_header(image, from);
if ( ce == NULL ) return 1;
@@ -1074,7 +1071,7 @@ struct image *image_create_for_simulation(const DataTemplate *dtempl)
return NULL;
}
- image->detgeom = create_detgeom(image, dtempl);
+ image->detgeom = create_detgeom(image, dtempl, 0);
if ( image->detgeom == NULL ) {
image_free(image);
return NULL;
@@ -1126,7 +1123,7 @@ static int do_image_read(struct image *image, const DataTemplate *dtempl,
}
profile_start("create-detgeom");
- image->detgeom = create_detgeom(image, dtempl);
+ image->detgeom = create_detgeom(image, dtempl, 0);
profile_end("create-detgeom");
if ( image->detgeom == NULL ) {
ERROR("Failed to read geometry information\n");
diff --git a/libcrystfel/src/stream.c b/libcrystfel/src/stream.c
index 3a4f5dae..0195e0ff 100644
--- a/libcrystfel/src/stream.c
+++ b/libcrystfel/src/stream.c
@@ -897,7 +897,7 @@ struct image *stream_read_chunk(Stream *st, StreamFlags srf)
if ( have_filename && have_ev ) {
/* Success */
if ( srf & STREAM_DATA_DETGEOM ) {
- image->detgeom = create_detgeom(image, st->dtempl_read);
+ image->detgeom = create_detgeom(image, st->dtempl_read, 0);
if ( image->detgeom == NULL ) {
image_free(image);
return NULL;