aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas White <taw@physics.org>2020-12-16 16:01:58 +0100
committerThomas White <taw@physics.org>2020-12-16 16:01:58 +0100
commit9da7f1b3f6a4245eb0c35fb32d32c60d60538eb2 (patch)
tree0af0ee5b82a5966aadcfd5f9446c7889a3eeba5c
parentb4f243ec2c704e510655de8ea34c9fc16f454390 (diff)
Add flag_{lessthan,morethan,equal} in geometry file
This makes handling Pilatus/Eiger files, as well as many others, much easier.
-rw-r--r--doc/man/crystfel_geometry.56
-rw-r--r--libcrystfel/src/datatemplate.c35
-rw-r--r--libcrystfel/src/datatemplate_priv.h13
-rw-r--r--libcrystfel/src/image.c46
4 files changed, 98 insertions, 2 deletions
diff --git a/doc/man/crystfel_geometry.5 b/doc/man/crystfel_geometry.5
index b8674f13..9435a900 100644
--- a/doc/man/crystfel_geometry.5
+++ b/doc/man/crystfel_geometry.5
@@ -211,6 +211,12 @@ The corner of this panel, defined as the first point in the panel to appear in t
The maximum value, in ADU, before the pixel will be considered as bad. That is, the saturation value for the panel.
.PD 0
+.IP \fBflag_lessthan
+.IP \fBflag_morethan
+.IP \fBflag_equal
+Mark pixels as "bad" if their values are respectively less than, more than or equal to the given value. Note carefully that the inequalities are strict, not inclusive: "less than", not "less than or equal to".
+
+.PD 0
.IP \fBmask\fR
If you have a bad pixel mask, you can include it in the HDF5 file as data blocks with the same structure and size as the panel data. You need to specify the location of each panel's mask data block using this property, and two bitmasks (see below). The number of placeholders ('%') in the \fBmask\fR must be the same for all panels. They will be substituted with the same values as used for the placeholders in the \fBdata\fR fields, although there may be fewer of them for \fBmask\fR than for \fBdata\fR.
diff --git a/libcrystfel/src/datatemplate.c b/libcrystfel/src/datatemplate.c
index 76a61893..18b09c12 100644
--- a/libcrystfel/src/datatemplate.c
+++ b/libcrystfel/src/datatemplate.c
@@ -466,6 +466,25 @@ int set_dim(struct panel_template *panel, int dimension,
}
+static int add_flag_value(struct panel_template *p,
+ float val,
+ enum flag_value_type type)
+{
+ int i;
+
+ for ( i=0; i<MAX_FLAG_VALUES; i++ ) {
+ if ( p->flag_types[i] == FLAG_NOTHING ) {
+ p->flag_types[i] = type;
+ p->flag_values[i] = val;
+ return 0;
+ }
+ }
+
+ ERROR("Too many flag values.\n");
+ return 1;
+}
+
+
static int parse_field_for_panel(struct panel_template *panel, const char *key,
const char *val, DataTemplate *det)
{
@@ -531,6 +550,20 @@ static int parse_field_for_panel(struct panel_template *panel, const char *key,
panel->pixel_pitch = 1.0/atof(val);
} else if ( strcmp(key, "max_adu") == 0 ) {
panel->max_adu = atof(val);
+
+ } else if ( strcmp(key, "flag_equal") == 0 ) {
+ if ( add_flag_value(panel, atof(val), FLAG_EQUAL) ) {
+ reject = -1;
+ }
+ } else if ( strcmp(key, "flag_lessthan") == 0 ) {
+ if ( add_flag_value(panel, atof(val), FLAG_LESSTHAN) ) {
+ reject = -1;
+ }
+ } else if ( strcmp(key, "flag_morethan") == 0 ) {
+ if ( add_flag_value(panel, atof(val), FLAG_MORETHAN) ) {
+ reject = -1;
+ }
+
} else if ( strcmp(key, "badrow_direction") == 0 ) {
ERROR("WARNING 'badrow_direction' is ignored in this version.\n");
} else if ( strcmp(key, "no_index") == 0 ) {
@@ -915,6 +948,8 @@ DataTemplate *data_template_new_from_string(const char *string_in)
defaults.clen_for_centering = NAN;
defaults.adu_scale = NAN;
defaults.adu_scale_unit = ADU_PER_PHOTON;
+ for ( i=0; i<MAX_FLAG_VALUES; i++ ) defaults.flag_values[i] = 0;
+ for ( i=0; i<MAX_FLAG_VALUES; i++ ) defaults.flag_types[i] = FLAG_NOTHING;
defaults.max_adu = +INFINITY;
defaults.mask = NULL;
defaults.mask_file = NULL;
diff --git a/libcrystfel/src/datatemplate_priv.h b/libcrystfel/src/datatemplate_priv.h
index 9d4f8f26..593ebaa8 100644
--- a/libcrystfel/src/datatemplate_priv.h
+++ b/libcrystfel/src/datatemplate_priv.h
@@ -55,6 +55,15 @@ enum wavelength_unit
WAVELENGTH_PHOTON_EV
};
+#define MAX_FLAG_VALUES (16)
+
+enum flag_value_type
+{
+ FLAG_NOTHING,
+ FLAG_EQUAL,
+ FLAG_MORETHAN,
+ FLAG_LESSTHAN
+};
/* Special values for dimension IDs */
#define DIM_FS (-1)
@@ -107,6 +116,10 @@ struct panel_template
/** Treat pixel as unreliable if higher than this */
double max_adu;
+ /** Pixels with exactly this value will be marked as bad */
+ enum flag_value_type flag_types[MAX_FLAG_VALUES];
+ signed int flag_values[MAX_FLAG_VALUES];
+
/** Location of data in file (possibly with placeholders) */
char *data;
diff --git a/libcrystfel/src/image.c b/libcrystfel/src/image.c
index 2b609e51..d50bcf43 100644
--- a/libcrystfel/src/image.c
+++ b/libcrystfel/src/image.c
@@ -36,6 +36,7 @@
#include <math.h>
#include <stdio.h>
#include <sys/stat.h>
+#include <fenv.h>
#include "image.h"
#include "utils.h"
@@ -629,6 +630,36 @@ static void set_image_parameters(struct image *image,
}
+static int flag_value(float pixel, struct panel_template *p)
+{
+ int i;
+ for ( i=0; i<MAX_FLAG_VALUES; i++ ) {
+
+ float fv = p->flag_values[i];
+
+ switch ( p->flag_types[i] ) {
+
+ case FLAG_NOTHING:
+ break;
+
+ case FLAG_LESSTHAN:
+ if ( pixel < fv ) return 1;
+ break;
+
+ case FLAG_MORETHAN:
+ if ( pixel > fv ) return 1;
+ break;
+
+ case FLAG_EQUAL:
+ if ( rint(pixel) == fv) return 1;
+ break;
+
+ }
+ }
+ return 0;
+}
+
+
static int create_badmap(struct image *image,
const DataTemplate *dtempl,
int no_mask_data)
@@ -665,17 +696,28 @@ static int create_badmap(struct image *image,
/* Add bad regions (skip if panel is bad anyway) */
if ( !p->bad ) {
+
int fs, ss;
+ fenv_t envp;
+
+ fegetenv(&envp);
+ fesetround(1); /* Round to nearest
+ * (for flag_value) */
+
for ( fs=0; fs<p_w; fs++ ) {
for ( ss=0; ss<p_h; ss++ ) {
+ float val = image->dp[i][fs+ss*p_w];
if ( data_template_in_bad_region(dtempl, i, fs, ss)
- || isnan(image->dp[i][fs+ss*p_w])
- || isinf(image->dp[i][fs+ss*p_w]) )
+ || isnan(val)
+ || isinf(val)
+ || flag_value(val, p) )
{
image->bad[i][fs+ss*p_w] = 1;
}
}
}
+
+ fesetenv(&envp);
}
/* Load mask (skip if panel is bad anyway) */