aboutsummaryrefslogtreecommitdiff
path: root/libcrystfel/src/datatemplate.c
diff options
context:
space:
mode:
Diffstat (limited to 'libcrystfel/src/datatemplate.c')
-rw-r--r--libcrystfel/src/datatemplate.c134
1 files changed, 131 insertions, 3 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);
}