diff options
-rw-r--r-- | doc/man/geoptimiser.1 | 8 | ||||
-rw-r--r-- | src/geoptimiser.c | 2746 |
2 files changed, 1467 insertions, 1287 deletions
diff --git a/doc/man/geoptimiser.1 b/doc/man/geoptimiser.1 index d56bf86a..10bf6dce 100644 --- a/doc/man/geoptimiser.1 +++ b/doc/man/geoptimiser.1 @@ -87,9 +87,15 @@ Sets the minimum number of peaks that should fall within a pixel, across all ind .PD 0 .IP "\fB-p\fR \fIn\fR" +.IP \fB--min-num-pixels-per-conn-group=\fR\fIn\fR +.PD +Sets the minimum number of pixels that contribute to the geometry opimization (see the \fB--min-num-peaks-per-pixel\fR option above ) that a connected group should have for the group to be optimized independently. The default value is 100. + +.PD 0 +.IP "\fB-p\fR \fIn\fR" .IP \fB--min-num-peaks-per-panel=\fR\fIn\fR .PD -Sets the minimum number of peaks that should appear in a panel for the panel's geometry to be optimized independently. The default value is 100. +This option has been renamd to \fB--min-num-pixels-per-conn-group\fR. It has been deprecated and will soon be removed. It is currently mapped to the \fB--min-num-pixels-per-conn-group\fR option. .PD 0 .IP "\fB-l\fR" diff --git a/src/geoptimiser.c b/src/geoptimiser.c index ba38f63c..e1d59f05 100644 --- a/src/geoptimiser.c +++ b/src/geoptimiser.c @@ -68,34 +68,54 @@ static void show_help(const char *s) printf( "Refines detector geometry.\n" "\n" -" -h, --help Display this help message.\n" +" -h, --help Display this help message.\n" "\n" -" --version Print CrystFEL version number and\n" -" exit.\n" -" -i, --input=<filename> Specify stream file to be used for \n" -" geometry optimization.\n" -" -g. --geometry=<filename> Input detector geometry.\n" -" -o, --output=<filename> Output detector geometry.\n" -" -q, --quadrants=<rg_coll> Rigid group collection for quadrants.\n" -" -c, --connected=<rg_coll> Rigid group collection for connected\n" -" ASICs.\n" -" --no-error-maps Do not generate error map PNGs.\n" -" -x, --min-num-peaks-per-pixel=<num> Minimum number of peaks per pixel.\n" -" Default: 3. \n" -" -p, --min-num-peaks-per-panel=<num> Minimum number of peaks per pixel.\n" -" Default: 100.\n" -" -l, --most-freq-clen Use only the most frequent camera\n" -" length.\n" -" -s, --individual-dist-offset Use a distance offset for each panel.\n" -" Default: whole-detector offset.\n" -" --no-stretch Do not optimize distance offset.\n" -" Default: distance offset is optimized\n" -" -m --max-peak-dist=<num> Maximum distance between predicted and\n" -" detected peaks (in pixels)\n" -" Default: 4.0 pixels.\n" +" --version Print CrystFEL version number and\n" +" exit.\n" +" -i, --input=<filename> Specify stream file to be used for \n" +" geometry optimization.\n" +" -g. --geometry=<file> Get detector geometry from file.\n" +" -o, --output=<filename> Output stream.\n" +" -q, --quadrants=<rg_coll> Rigid group collection for quadrants.\n" +" -c, --connected=<rg_coll> Rigid group collection for connected\n" +" ASICs.\n" +" --no-error-maps Do not generate error map PNGs.\n" +" -x, --min-num-peaks-per-pixel=<num> Minimum number of peaks per pixel.\n" +" Default: 3. \n" +" --min-num-peaks-per-panel=<num> DEPRECATED. This option has been\n" +" renamed to --min-num-pixels-per-conn-group.\n" +" -p, --min-num-pixels-per-conn-group=<num> Minimum number of useful pixels pern" +" connected group.\n" +" f Default: 100.\n" +" -l, --most-freq-clen Use only the most frequent camera\n" +" length.\n" +" -s, --individual-dist-offset Use a distance offset for each panel.\n" +" Default: whole-detector offset.\n" +" --no-stretch Do not optimize distance offset.\n" +" Default: distance offset is optimized\n" +" -m --max-peak-dist=<num> Maximum distance between predicted and\n" +" detected peaks (in pixels)\n" +" Default: 4.0 pixels.\n" ); } +struct geoptimiser_params +{ + char *infile; + char *outfile; + char *geometry_filename; + int min_num_peaks_per_pix; + int min_num_pix_per_conn_group; + int only_best_distance; + int nostretch; + int individual_coffset; + int error_maps; + int enforce_cspad_layout; + int no_cspad; + double max_peak_dist; + const char *command_line; +}; + struct connected_data { @@ -127,19 +147,76 @@ struct pattern_list { }; -struct single_pix_displ +struct single_pixel_displ { double dfs; double dss; - struct single_pix_displ* ne; + struct single_pixel_displ* ne; +}; + + +struct pixel_displ_list +{ + struct single_pixel_displ *pix_displ_list; + struct single_pixel_displ **curr_pix_displ; + int *num_pix_displ; }; struct connected_stretch_and_angles { double *stretch_coeff; - unsigned int *num_angles; - int num_coeff; + long *num_angles; + long num_coeff; +}; + +struct cell_params +{ + double a; + double b; + double c; + double alpha; + double beta; + double gamma; +}; + + +struct avg_displacements +{ + double *displ_x; + double *displ_y; + double *displ_abs; +}; + + +struct avg_rot_and_stretch +{ + double *aver_ang; + double *aver_str; + int *aver_num_ang; +}; + + +struct avg_shift +{ + double *aver_x; + double *aver_y; + int *aver_num_sh; +}; + +struct pixel_maps +{ + double *pix_to_x; + double *pix_to_y; +}; + + +struct enhanced_det +{ + struct detector *det; + int width; + int height; + int num_pix; }; @@ -176,9 +253,8 @@ static Reflection *find_closest_reflection(RefList *rlist, for ( refl = first_refl(rlist, &iter); - refl != NULL; - refl = next_refl(refl, iter) ) - { + refl != NULL; + refl = next_refl(refl, iter) ) { double ds; double rfs, rss; double rx, ry; @@ -248,7 +324,7 @@ static double extract_f_from_stuff(const char *field_name, if ( strncmp(stuff->fields[i], field_name_plus_equal, strlen(field_name_plus_equal)) == 0 ) { - return atoi(stuff->fields[i]+ + return atof(stuff->fields[i]+ strlen(field_name_plus_equal)); } } @@ -261,7 +337,6 @@ static double extract_f_from_stuff(const char *field_name, static struct pattern_list *read_patterns_from_steam_file(const char *infile, struct detector *det) { - Stream *st; struct pattern_list *pattern_list; @@ -390,7 +465,7 @@ static struct pattern_list *read_patterns_from_steam_file(const char *infile, patn->unit_cells = new_unit_cells; crystal_reflist = crystal_get_reflections( - cur.crystals[i]); + cur.crystals[i]); for ( refl = first_refl(crystal_reflist, &iter); refl != NULL; @@ -402,7 +477,6 @@ static struct pattern_list *read_patterns_from_steam_file(const char *infile, get_indices(refl, &h, &k, &l); n = add_refl(patn->ref_list, h, k, l); copy_data(n, refl); - } } @@ -445,13 +519,14 @@ static struct rvec get_q_from_xyz(double rx, double ry, double dist, double l) } -static void compute_avg_cell_parameters(struct pattern_list *pattern_list, - double *avcp) +static struct cell_params *compute_avg_cell_parameters(struct pattern_list + *pattern_list) { int numavc; int j, i; double minc[6]; double maxc[6]; + double avg_cpar[6]; for (j=0; j<6; j++) { minc[j] = 1e10; @@ -484,7 +559,7 @@ static void compute_avg_cell_parameters(struct pattern_list *pattern_list, cpar[5] = rad2deg(cpar[5]); for ( j=0; j<6; j++ ) { - avcp[j] += cpar[j]; + avg_cpar[j] += cpar[j]; if (cpar[j]<minc[j]) minc[j] = cpar[j]; if (cpar[j]>maxc[j]) maxc[j] = cpar[j]; } @@ -495,33 +570,41 @@ static void compute_avg_cell_parameters(struct pattern_list *pattern_list, } if ( numavc>0 ) { - for ( j=0; j<6; j++ ) avcp[j] /= numavc; + for ( j=0; j<6; j++ ) avg_cpar[j] /= numavc; } + struct cell_params *cparams = malloc(sizeof(struct cell_params)); + + cparams->a = avg_cpar[0]; + cparams->b = avg_cpar[1]; + cparams->c = avg_cpar[2]; + cparams->alpha = avg_cpar[3]; + cparams->beta = avg_cpar[4]; + cparams->gamma = avg_cpar[5]; + STATUS("Average cell coordinates:\n"); STATUS("Average a, b, c (in nm): %6.3f, %6.3f, %6.3f\n", - avcp[0],avcp[1],avcp[2]); + cparams->a, cparams->b, cparams->c); STATUS("Minimum -Maximum a, b, c:\n" "\t%6.3f - %6.3f,\n" "\t%6.3f - %6.3f,\n" "\t%6.3f - %6.3f\n", minc[0], maxc[0], minc[1], maxc[1], minc[2], maxc[2]); STATUS("Average alpha,beta,gamma in degrees: %6.3f, %6.3f, %6.3f\n", - avcp[3], avcp[4], avcp[5]); + cparams->alpha, cparams->beta, cparams->gamma); STATUS("Minimum - Maximum alpha,beta,gamma in degrees:\n" "\t%5.2f - %5.2f,\n" "\t%5.2f - %5.2f,\n" "\t%5.2f - %5.2f\n", minc[3], maxc[3], minc[4], maxc[4], minc[5], maxc[5]); + return cparams; } -static double compute_clen_to_use(struct pattern_list *pattern_list, - double istep, double *avcp, - double max_peak_distance, - int only_best_distance, - double* min_braggp_dist) +static double pick_clen_to_use(struct geoptimiser_params *gparams, + struct pattern_list *pattern_list, + double avg_res, struct cell_params *cparams) { int cp, i, u; int num_clens; @@ -530,9 +613,8 @@ static double compute_clen_to_use(struct pattern_list *pattern_list, int *clens_population; double *clens; double *lambdas; - double irecistep; + double min_braggp_dist; double clen_to_use; - double *braggp_dist; struct rvec cqu; max_clens = 1024; @@ -586,16 +668,16 @@ static double compute_clen_to_use(struct pattern_list *pattern_list, clens_new = realloc(clens_population, (max_clens+1024)*sizeof(double)); lambdas_new = realloc(clens_population, - (max_clens+1024)*sizeof(double)); + (max_clens+1024)*sizeof(double)); if ( clens_new == NULL || clens_population_new == NULL || lambdas_new == NULL) { ERROR("Failed to allocate memory for " "camera length list\n"); - free(clens); - free(clens_population); - free(lambdas); - return -1.0; + free(clens); + free(clens_population); + free(lambdas); + return -1.0; } max_clens += 1024; @@ -605,7 +687,6 @@ static double compute_clen_to_use(struct pattern_list *pattern_list, } clens[num_clens] = pattern_list->patterns[cp]->clen; - clens_population[num_clens] = 1; lambdas[num_clens] = pattern_list->patterns[cp]->lambda; num_clens++; @@ -618,37 +699,34 @@ static double compute_clen_to_use(struct pattern_list *pattern_list, } if ( num_clens == 1 ) { - STATUS("All patterns in the stream file have the same camera " - "length: %f m.\n", + STATUS("All patterns have the same camera length: %f m.\n", clens[0]); } else { STATUS("%i different camera lengths were found for the input " - "patterns in the stream file:\n", num_clens); + "patterns:\n", num_clens); } - braggp_dist = calloc(num_clens, sizeof(double)); - *min_braggp_dist = 999999.0; best_clen = 0; clen_to_use = clens[0]; for ( i=0; i<num_clens; i++) { if ( clens_population[i] >0) { - cqu = get_q_from_xyz(1/istep, 0, clens[i], lambdas[i]); - - irecistep = 1/cqu.u; - - braggp_dist[i] = fmin(fmin(irecistep/avcp[0], - irecistep/avcp[1]), - irecistep/avcp[2]); - if (braggp_dist[i] < *min_braggp_dist) { - *min_braggp_dist = braggp_dist[i]; - } - STATUS("Camera length %0.4f m was found %i times in the " - "stream file.\n" - "Corresponding minimum inter-bragg peak distance " - "is (based on average cell parameters): " - " %0.1f pixels.\n", + cqu = get_q_from_xyz(1.0/avg_res, 0, clens[i], lambdas[i]); + + min_braggp_dist = fmin(fmin((1.0/cqu.u)/cparams->a, + (1.0/cqu.u)/cparams->b), + (1.0/cqu.u)/cparams->c); + STATUS("Camera length %0.4f m was found %i times.\n" + "Minimum inter-bragg peak distance (based on " + "average cell parameters): %0.1f pixels.\n", clens[i], clens_population[i], - braggp_dist[i]); + min_braggp_dist); + if ( min_braggp_dist<1.2*gparams->max_peak_dist ) { + STATUS("WARNING: The distance between Bragg " + "peaks is too small: " + "%0.1f < 1.2*%0.1f pixels.\n", + min_braggp_dist, + gparams->max_peak_dist); + } if ( clens_population[i] > clens_population[best_clen] ) { best_clen = i; clen_to_use = clens[best_clen]; @@ -656,24 +734,23 @@ static double compute_clen_to_use(struct pattern_list *pattern_list, } } - if ( only_best_distance ) { - STATUS("Only the %i patterns with clen=%0.4f m will be used.\n", + if ( gparams->only_best_distance ) { + STATUS("Only %i patterns with CLEN=%0.4f m will be used.\n", clens_population[best_clen], clen_to_use); - *min_braggp_dist = braggp_dist[best_clen]; } free(clens); free(lambdas); free(clens_population); - free(braggp_dist); + return clen_to_use; } -static double comp_median(double *arr, unsigned int n) +static double comp_median(double *arr, long n) { - int low, high, median, middle, ll, hh; + long low, high, median, middle, ll, hh; double A; if (n<1) return 0.0; @@ -739,7 +816,7 @@ static double comp_median(double *arr, unsigned int n) /* Re-set active partition */ if ( hh<=median ) low = ll; - if ( hh>=median ) high = hh-1; + if ( hh>=median ) high = hh-1; } return 0.0; @@ -767,199 +844,211 @@ static int find_quad_for_connected(struct rigid_group *rg, } -static void free_all_curr_pix_displ(struct single_pix_displ *all_pix_displ, - struct single_pix_displ **curr_pix_displ, - int num_pix_in_slab) +static int fill_avg_pixel_displ(struct pixel_displ_list *pix_displ_list, + int pix_index, + struct avg_displacements *avg_displ) { - int i; - struct single_pix_displ *curr = NULL; - struct single_pix_displ *next = NULL; + double *list_fs_displ; + double *list_ss_displ; + int count = 0; + int ei; + + list_fs_displ = calloc(pix_displ_list->num_pix_displ[pix_index], + sizeof(double)); + if ( list_fs_displ == NULL ) { + ERROR("Failed to allocate memory for pixel statistics.\n"); + return 1; + } + list_ss_displ = calloc(pix_displ_list->num_pix_displ[pix_index], + sizeof(double)); + if ( list_ss_displ == NULL ) { + ERROR("Failed to allocate memory for pixel statistics.\n"); + free(list_fs_displ); + return 1; + } - for ( i=0; i<num_pix_in_slab; i++ ) { + pix_displ_list->curr_pix_displ[pix_index] = + &pix_displ_list->pix_displ_list[pix_index]; - curr = &all_pix_displ[i]; + for ( ei=0; ei<pix_displ_list->num_pix_displ[pix_index]; ei++ ) { + struct single_pixel_displ * pixel_displ_entry; + pixel_displ_entry = pix_displ_list->curr_pix_displ[pix_index]; - if ( curr->ne != NULL ) { - curr = curr->ne; - while ( curr != NULL ) { - next = curr->ne; - free(curr); - curr = next; - } - } - } + if ( pixel_displ_entry->dfs == -10000.0 ) break; + list_fs_displ[count] = pixel_displ_entry->dfs; + list_ss_displ[count] = pixel_displ_entry->dss; + count++; + if ( pixel_displ_entry->ne == NULL ) { + break; + } else { + pix_displ_list->curr_pix_displ[pix_index] = + pix_displ_list->curr_pix_displ[pix_index]->ne; + } + } + + if ( count < 1 ) { + free(list_fs_displ); + free(list_ss_displ); + return 0; + } - free(curr_pix_displ); - free(all_pix_displ); + avg_displ->displ_x[pix_index] = comp_median(list_fs_displ, count); + avg_displ->displ_y[pix_index] = comp_median(list_ss_displ, count); + avg_displ->displ_abs[pix_index] = modulus2d(avg_displ->displ_x[pix_index], + avg_displ->displ_y[pix_index]); + free(list_fs_displ); + free(list_ss_displ); + + return 0; } -static int fill_pixel_statistics(int *num_pix_displ, - struct single_pix_displ** curr_pix_displ, - struct single_pix_displ* all_pix_displ, - struct connected_data *conn_data, - int ifs, int iss, int di, int aw, int dfv, - double *displ_x, - double *displ_y, double *displ_abs) +static int allocate_next_element(struct single_pixel_displ** curr_pix_displ, + int pix_index) { - double *cPxAfs; - double *cPxAss; - int cnu = 0; - - cPxAfs = calloc(num_pix_displ[ifs+aw*iss], sizeof(double)); - if ( cPxAfs == NULL ) { + curr_pix_displ[pix_index]->ne = malloc(sizeof(struct single_pixel_displ)); + if ( curr_pix_displ[pix_index]->ne == NULL ) { ERROR("Failed to allocate memory for pixel statistics.\n"); return 1; } - cPxAss = calloc(num_pix_displ[ifs+aw*iss], sizeof(double)); - if ( cPxAss == NULL ) { - ERROR("Failed to allocate memory for pixel statistics.\n"); - free(cPxAfs); - return 1; - } - curr_pix_displ[ifs+aw*iss] = &all_pix_displ[ifs+aw*iss]; + curr_pix_displ[pix_index] = curr_pix_displ[pix_index]->ne; - while (1) { - if (curr_pix_displ[ifs+aw*iss]->dfs == dfv) break; - cPxAfs[cnu] = curr_pix_displ[ifs+aw*iss]->dfs; - cPxAss[cnu] = curr_pix_displ[ifs+aw*iss]->dss; - cnu++; - if ( curr_pix_displ[ifs+aw*iss]->ne == NULL ) break; - curr_pix_displ[ifs+aw*iss] = curr_pix_displ[ifs+aw*iss]->ne; - } + return 0; +} + + +static int add_distance_to_list(struct enhanced_det *edet, + struct imagefeature *imfe, + struct pixel_displ_list *pix_displ_list, + Reflection *refl, double fx, double fy) +{ + int pix_index; + double rfs, rss; + double crx, cry; + + pix_index = ((int)rint(imfe->fs) + edet->width*(int)rint(imfe->ss)); - if ( cnu < 1 ) return 0; + if ( pix_displ_list->num_pix_displ[pix_index]>0 ) { - displ_x[ifs+aw*iss] = comp_median(cPxAfs, cnu); - displ_y[ifs+aw*iss] = comp_median(cPxAss, cnu); - displ_abs[ifs+aw*iss] = modulus2d(displ_x[ifs+aw*iss], - displ_y[ifs+aw*iss]); - conn_data[di].n_peaks_in_conn++; + int ret; - free(cPxAfs); - free(cPxAss); + ret = allocate_next_element(pix_displ_list->curr_pix_displ, + pix_index); + + if ( ret != 0) return ret; + + } + + get_detector_pos(refl, &rfs, &rss); + compute_x_y(edet->det, rfs, rss, &crx, &cry); + pix_displ_list->curr_pix_displ[pix_index]->dfs = (fx-crx); + pix_displ_list->curr_pix_displ[pix_index]->dss = (fy-cry); + pix_displ_list->curr_pix_displ[pix_index]->ne = NULL; + pix_displ_list->num_pix_displ[pix_index]++; return 0; } - -static int compute_panel_statistics(struct rg_collection *connected, - int *num_pix_displ, - struct single_pix_displ** curr_pix_displ, - struct single_pix_displ* all_pix_displ, - struct connected_data *conn_data, - int di, int ip, int np, - double dfv, - int aw, double *displ_x, - double *displ_y, double *displ_abs) +static int count_pixels_with_min_peaks( struct panel *p, int min_num_peaks, + struct pixel_displ_list *pix_displ_list, + struct enhanced_det *edet) { - struct panel *p; + int pix_index; + int pixel_count = 0; int ifs, iss; - p = connected->rigid_groups[di]->panels[ip]; - for ( ifs=p->min_fs; ifs<p->max_fs+1; ifs++ ) { for ( iss=p->min_ss; iss<p->max_ss+1; iss++ ) { - if ( num_pix_displ[ifs+aw*iss]>=np ) { - - int ret; - - ret = fill_pixel_statistics(num_pix_displ, - curr_pix_displ, - all_pix_displ, - conn_data, - ifs, iss, di, aw, - dfv, displ_x, - displ_y, displ_abs); - - if ( ret == -2 ) { - break; - } else if ( ret != 0 ) { - return ret; - } - } else { - displ_x[ifs+aw*iss] = dfv; - displ_y[ifs+aw*iss] = dfv; - displ_abs[ifs+aw*iss] = dfv; + pix_index = ifs+edet->width*iss; + + if ( pix_displ_list->num_pix_displ[pix_index] >= + min_num_peaks ) { + pixel_count += 1; } } } - return 0; + return pixel_count; } - -static int allocate_next_element(struct single_pix_displ** curr_pix_displ, - int ipx) +static void adjust_min_peaks_per_conn(struct enhanced_det *edet, + struct rg_collection *connected, + struct geoptimiser_params *gparams, + struct connected_data *conn_data, + struct pixel_displ_list *pix_displ_list) { - curr_pix_displ[ipx]->ne = malloc(sizeof(struct single_pix_displ)); - if ( curr_pix_displ[ipx]->ne == NULL ) { - ERROR("Failed to allocate memory for pixel statistics.\n"); - return 1; - } - curr_pix_displ[ipx] = curr_pix_displ[ipx]->ne; + int min_num_peaks, di, ip; + struct panel *p; - return 0; -} + STATUS("Adjusting the minimum number of measurements per pixel in " + "order to have enough measurements for each connected group.\n"); + for ( di=0; di<connected->n_rigid_groups; di++ ) { -static int compute_pixel_statistics(struct pattern_list *pattern_list, - struct detector *det, - struct rg_collection *connected, - struct rg_collection *quadrants, - int num_pix_in_slab, - int max_peak_distance, int aw, - double dfv, - double min_num_peaks_per_pixel, - double min_num_peaks_per_panel, - int only_best_distance, - double clen_to_use, - double *slab_to_x, double *slab_to_y, - struct connected_data *conn_data, - double *displ_x, - double *displ_y, double *displ_abs, - struct single_pix_displ* all_pix_displ, - struct single_pix_displ** curr_pix_displ, - int *num_pix_displ) -{ - int ipx, cp, ich, di, ip, np; + for ( min_num_peaks=gparams->min_num_peaks_per_pix; + min_num_peaks>0; min_num_peaks-- ) { - for (di=0; di<connected->n_rigid_groups; di++) { + int di_count = 0; + + for (ip=0; ip<connected->rigid_groups[di]->n_panels; + ip++) { + + int pix_count; + + p = connected->rigid_groups[di]->panels[ip]; - conn_data[di].num_quad = find_quad_for_connected( - connected->rigid_groups[di], - quadrants); - conn_data[di].cang = 0.0; - conn_data[di].cstr = 1.0; - conn_data[di].sh_x = dfv; - conn_data[di].sh_y = dfv; - conn_data[di].num_peaks_per_pixel = 1; - conn_data[di].name = connected->rigid_groups[di]->name; - conn_data[di].n_peaks_in_conn = 0; - } + pix_count = count_pixels_with_min_peaks(p, + min_num_peaks, + pix_displ_list, + edet); + + di_count += pix_count; + } + conn_data[di].n_peaks_in_conn = di_count; + if ( di_count >= + gparams->min_num_pix_per_conn_group ) { + conn_data[di].num_peaks_per_pixel = + min_num_peaks; + break; + } + } - for ( ipx=0; ipx<num_pix_in_slab; ipx++ ) { - all_pix_displ[ipx].dfs = dfv; - all_pix_displ[ipx].dss = dfv; - all_pix_displ[ipx].ne = NULL; - curr_pix_displ[ipx] = &all_pix_displ[ipx]; - num_pix_displ[ipx] = 0; + STATUS("Minimum number of measurement " + "per pixel for connected group " + "%s has been set to %i\n", + conn_data[di].name, + conn_data[di].num_peaks_per_pixel); } +} + + +static int compute_pixel_displacements(struct pattern_list *pattern_list, + struct enhanced_det *edet, + struct rg_collection *connected, + struct geoptimiser_params *gparams, + double clen_to_use, + struct connected_data *conn_data, + struct avg_displacements *avg_displ, + struct pixel_displ_list *pix_displ_list) +{ + int cp, ich; + + STATUS("Computing pixel displacements.\n"); for ( cp=0; cp<pattern_list->n_patterns; cp++ ) { ImageFeatureList *flist = pattern_list->patterns[cp]->im_list; - if ( only_best_distance ) { + if ( gparams->only_best_distance ) { if ( fabs(pattern_list->patterns[cp]->clen-clen_to_use) > - 0.0001 ) { + 0.0001 ) { continue; } } @@ -970,87 +1059,99 @@ static int compute_pixel_statistics(struct pattern_list *pattern_list, double min_dist; double fx, fy; - double rfs, rss; - double crx, cry; Reflection *refl; + int ret; RefList *rlist = pattern_list->patterns[cp]->ref_list; struct imagefeature *imfe = image_get_feature(flist, ich); - compute_x_y(det, imfe->fs, imfe->ss, &fx, &fy); + compute_x_y(edet->det, imfe->fs, imfe->ss, &fx, &fy); - refl = find_closest_reflection(rlist, fx, fy, det, + refl = find_closest_reflection(rlist, fx, fy, edet->det, &min_dist); if ( refl == NULL ) continue; - if ( min_dist < max_peak_distance ) { + if ( min_dist < gparams->max_peak_dist ) { - int ipx = ((int)rint(imfe->fs) + aw* - (int)rint(imfe->ss)); - if ( num_pix_displ[ipx]>0 ) { + ret = add_distance_to_list(edet, imfe, + pix_displ_list, + refl, fx, fy); - int ret; + if ( ret != 0 ) return ret; - ret = allocate_next_element(curr_pix_displ, - ipx); + } + } + } - if ( ret != 0) return ret; + return 0; +} - } - get_detector_pos(refl, &rfs, &rss); - compute_x_y(det, rfs, rss, &crx, &cry); - get_detector_pos(refl, &rfs, &rss); - curr_pix_displ[ipx]->dfs = (fx-crx); - curr_pix_displ[ipx]->dss = (fy-cry); - curr_pix_displ[ipx]->ne = NULL; - num_pix_displ[ipx]++; - } - } +static int compute_avg_pix_displ(struct pixel_displ_list *pix_displ_list, + int num_peaks_per_pixel,int pix_index, + struct avg_displacements *avg_displ) +{ + int ret; + + if ( pix_displ_list->num_pix_displ[pix_index] >= + num_peaks_per_pixel ) { + + ret = fill_avg_pixel_displ(pix_displ_list, + pix_index, + avg_displ); + if ( ret !=0 ) return ret; + } else { + avg_displ->displ_x[pix_index] = -10000.0; + avg_displ->displ_y[pix_index] = -10000.0; + avg_displ->displ_abs[pix_index] = -10000.0; } - for ( np=min_num_peaks_per_pixel; np>0; np-- ) { - for ( di=0; di<connected->n_rigid_groups; di++ ) { - if ( conn_data[di].num_peaks_per_pixel>np ) { - continue; - } + return 0; - for (ip=0; ip<connected->rigid_groups[di]->n_panels; - ip++) { +} - int ret; - - ret = compute_panel_statistics(connected, - num_pix_displ, - curr_pix_displ, - all_pix_displ, - conn_data, di, ip, - np, - dfv, - aw, - displ_x, - displ_y, - displ_abs); - - if ( ret !=0 ) return ret; - } +static int compute_avg_displacements(struct enhanced_det *edet, + struct rg_collection *connected, + struct pixel_displ_list *pix_displ_list, + struct connected_data *conn_data, + struct avg_displacements *avg_displ) +{ + int di, ip, ifs, iss; + int pix_index, ret; + struct panel *p; + + for ( di=0; di<connected->n_rigid_groups; di++ ) { + + for (ip=0; ip<connected->rigid_groups[di]->n_panels; + ip++) { + + p = connected->rigid_groups[di]->panels[ip]; + + for ( ifs=p->min_fs; ifs<p->max_fs+1; ifs++ ) { + for ( iss=p->min_ss; iss<p->max_ss+1; iss++ ) { - if ( conn_data[di].n_peaks_in_conn >= - min_num_peaks_per_panel ) { - conn_data[di].num_peaks_per_pixel = np; + pix_index = ifs+edet->width*iss; + + ret = compute_avg_pix_displ(pix_displ_list, + conn_data[di].num_peaks_per_pixel, + pix_index, avg_displ); + + if ( ret != 0 ) return ret; + + } } } - } - return 0; + } + return 0; } static double compute_error(struct rg_collection *connected, - int aw, + struct enhanced_det* edet, struct connected_data *conn_data, int *num_pix_displ, double *displ_abs) @@ -1072,13 +1173,17 @@ static double compute_error(struct rg_collection *connected, for (ifs=p->min_fs; ifs<p->max_fs+1; ifs++) { for (iss=p->min_ss; iss<p->max_ss+1; iss++) { - if ( num_pix_displ[ifs+aw*iss]>= + + int pix_index; + pix_index = ifs+edet->width*iss; + + if ( num_pix_displ[pix_index]>= conn_data[di].num_peaks_per_pixel ) { double cer; - cer = displ_abs[ifs+aw*iss]* - displ_abs[ifs+aw*iss]; + cer = displ_abs[pix_index]* + displ_abs[pix_index]; connected_error += cer; num_connected_error++; total_error += cer; @@ -1093,11 +1198,10 @@ static double compute_error(struct rg_collection *connected, connected_error /= (double)num_connected_error; connected_error = sqrt(connected_error); - STATUS("Connected group %s: \n" - " Pixels with more than %d measurements: %i " - " Error: <delta^2> = %0.4f pixels.\n", - conn_data[di].name, conn_data[di].num_peaks_per_pixel, - num_connected_error, + STATUS("Error for connected group %s: %d pixels with " + "more than %d peaks: <delta^2> = %0.4f pixels.\n", + conn_data[di].name, num_connected_error, + conn_data[di].num_peaks_per_pixel, connected_error); } } @@ -1113,120 +1217,184 @@ static double compute_error(struct rg_collection *connected, } -static void fill_coordinate_matrices(struct detector *det, int aw, - double *slab_to_x, double *slab_to_y) +static struct pixel_maps *initialize_pixel_maps(struct enhanced_det *edet) { + int pi; + struct pixel_maps *pixel_maps; - for ( pi=0; pi<det->n_panels; pi++ ) { + pixel_maps = malloc(sizeof(struct pixel_maps)); + pixel_maps->pix_to_x = malloc(edet->num_pix*sizeof(double)); + if ( pixel_maps->pix_to_x == NULL ) { + free(pixel_maps); + return NULL; + } + + pixel_maps->pix_to_y = malloc(edet->num_pix*sizeof(double)); + if ( pixel_maps->pix_to_x == NULL ) { + ERROR("Failed to allocate memory for pixel maps.\n"); + free(pixel_maps->pix_to_x); + free(pixel_maps); + return NULL; + } + + for ( pi=0; pi<edet->det->n_panels; pi++ ) { struct panel *p; int iss, ifs; - p = &det->panels[pi]; + p = &edet->det->panels[pi]; - for (iss=p->min_ss; iss < p->max_ss+1; iss++) { - for (ifs=p->min_fs; ifs < p->max_fs+1; ifs++) { + for (iss=p->min_ss; iss < p->max_ss+1; iss++) { + for (ifs=p->min_fs; ifs < p->max_fs+1; ifs++) { double xs, ys; + int pix_index; - compute_x_y(det, ifs, iss, &xs, &ys); - - slab_to_x[iss*aw+ifs] = xs; - slab_to_y[iss*aw+ifs] = ys; + pix_index = iss*edet->width+ifs; + compute_x_y(edet->det, ifs, iss, &xs, &ys); + pixel_maps->pix_to_x[pix_index] = xs; + pixel_maps->pix_to_y[pix_index] = ys; } } } + + return pixel_maps; } -static int correct_empty_panels(struct rg_collection *quadrants, - struct rg_collection *connected, - int min_num_peaks_per_panel, - struct connected_data *conn_data) +void free_pixel_maps(struct pixel_maps* pixel_maps) { - double *aver_ang; - double *aver_str; - int *aver_num_ang; + free(pixel_maps->pix_to_x); + free(pixel_maps->pix_to_y); + free(pixel_maps); +} - int di,i; - aver_ang = malloc(quadrants->n_rigid_groups*sizeof(double)); - if ( aver_ang == NULL ) { + +struct avg_rot_and_stretch* initialize_avg_rot_stretch( + int num_rigid_groups) +{ + int i; + + struct avg_rot_and_stretch *avg_rot_str; + + avg_rot_str = malloc(sizeof(struct avg_rot_and_stretch)); + if ( avg_rot_str == NULL ) { ERROR("Failed to allocate memory to correct empty panels.|n"); - return 1; + return NULL; + } + + avg_rot_str->aver_ang = malloc(num_rigid_groups*sizeof(double)); + if ( avg_rot_str->aver_ang == NULL ) { + ERROR("Failed to allocate memory to correct empty panels.|n"); + free(avg_rot_str); + return NULL; } - aver_str = malloc(quadrants->n_rigid_groups*sizeof(double)); - if ( aver_str == NULL ) { + + avg_rot_str->aver_str = malloc(num_rigid_groups*sizeof(double)); + if ( avg_rot_str->aver_str == NULL ) { ERROR("Failed to allocate memory to correct empty panels.|n"); - free(aver_ang); - return 1; + free(avg_rot_str->aver_ang); + free(avg_rot_str); + return NULL; } - aver_num_ang = malloc(quadrants->n_rigid_groups*sizeof(int)); - if ( aver_num_ang == NULL ) { + + avg_rot_str->aver_num_ang = malloc(num_rigid_groups*sizeof(int)); + if ( avg_rot_str->aver_num_ang == NULL ) { ERROR("Failed to allocate memory to correct empty panels.|n"); - free(aver_ang); - free(aver_str); - return 1; + free(avg_rot_str->aver_ang); + free(avg_rot_str->aver_str); + free(avg_rot_str); + return NULL; } - for (i=0; i<quadrants->n_rigid_groups; i++) { - aver_ang[i] = 0; - aver_str[i] = 0; - aver_num_ang[i] = 0; + for (i=0; i<num_rigid_groups; i++) { + avg_rot_str->aver_ang[i] = 0.0; + avg_rot_str->aver_str[i] = 0.0; + avg_rot_str->aver_num_ang[i] = 0; + } + + return avg_rot_str; +} + + +void free_avg_angle_and_stretches(struct avg_rot_and_stretch* avg_rot_str) +{ + free(avg_rot_str->aver_ang); + free(avg_rot_str->aver_str); + free(avg_rot_str->aver_num_ang); +} + + +static int compute_rot_stretch_for_empty_panels( + struct rg_collection *quadrants, + struct rg_collection *connected, + struct geoptimiser_params *gparams, + struct connected_data *conn_data) +{ + struct avg_rot_and_stretch *avg_rot_str; + int di,i; + + STATUS("Computing rotation and elongation corrections for groups " + "without the required number of measurements.\n"); + + avg_rot_str = initialize_avg_rot_stretch(quadrants->n_rigid_groups); + if ( avg_rot_str == NULL ) { + return 1; } for (di=0; di<connected->n_rigid_groups; di++) { - if ( conn_data[di].n_peaks_in_conn>=min_num_peaks_per_panel ) { - aver_ang[conn_data[di].num_quad] += conn_data[di].cang; - aver_str[conn_data[di].num_quad] += conn_data[di].cstr; - aver_num_ang[conn_data[di].num_quad]++; + if ( conn_data[di].n_peaks_in_conn >= + gparams->min_num_pix_per_conn_group ) { + avg_rot_str->aver_ang[conn_data[di].num_quad] += + conn_data[di].cang; + avg_rot_str->aver_str[conn_data[di].num_quad] += + conn_data[di].cstr; + avg_rot_str->aver_num_ang[conn_data[di].num_quad]++; } } for ( i=0; i<quadrants->n_rigid_groups; i++ ) { - if ( aver_num_ang[i]>0 ) { - aver_ang[i] /= (double)aver_num_ang[i]; - aver_str[i] /= (double)aver_num_ang[i]; + if ( avg_rot_str->aver_num_ang[i] > 0 ) { + avg_rot_str->aver_ang[i] /= + (double)avg_rot_str->aver_num_ang[i]; + avg_rot_str->aver_str[i] /= + (double)avg_rot_str->aver_num_ang[i]; } } for ( di=0; di<connected->n_rigid_groups; di++ ) { - if ( conn_data[di].n_peaks_in_conn<min_num_peaks_per_panel ) { - if (aver_num_ang[conn_data[di].num_quad]>0) { + if ( conn_data[di].n_peaks_in_conn < + gparams->min_num_pix_per_conn_group ) { + if ( avg_rot_str->aver_num_ang[conn_data[di].num_quad] + > 0) { conn_data[di].cang = - aver_ang[conn_data[di].num_quad]; + avg_rot_str->aver_ang[conn_data[di].num_quad]; conn_data[di].cstr = - aver_str[conn_data[di].num_quad]; - STATUS("Connected group %s has not enough peaks " - "(%i). Using average angle: %0.4f degrees\n", - conn_data[di].name, + avg_rot_str->aver_str[conn_data[di].num_quad]; + STATUS("Connected group %s has only %i useful " + "pixels. Using average angle: %0.4f " + "degrees\n", conn_data[di].name, conn_data[di].n_peaks_in_conn, conn_data[di].cang); } else { - STATUS("Connected group %s has not enough peaks " - "(%i). Left unchanged\n", + STATUS("Connected group %s does not have enough " + " peaks (%i). It will not be moved.\n", conn_data[di].name, conn_data[di].n_peaks_in_conn); } } } - free(aver_ang); - free(aver_str); - free(aver_num_ang); - - return 0; + return 0; } -static void correct_angle_and_stretch(struct rg_collection *connected, - struct detector *det, - struct connected_data *conn_data, - double use_clen, double stretch_coeff, - int individual_coffset) +static void correct_corner_coordinates(struct rg_collection *connected, + struct connected_data *conn_data) { int di, ip; @@ -1235,55 +1403,26 @@ static void correct_angle_and_stretch(struct rg_collection *connected, for ( ip=0; ip<connected->rigid_groups[di]->n_panels; ip++ ) { struct panel *p; - double newx, newy; p = connected->rigid_groups[di]->panels[ip]; - newx = - p->fsx*cos(conn_data[di].cang)- - p->fsy*sin(conn_data[di].cang); - newy = - p->fsx*sin(conn_data[di].cang)+ - p->fsy*cos(conn_data[di].cang); - p->fsx = newx; - p->fsy = newy; - newx = - p->ssx*cos(conn_data[di].cang)- - p->ssy*sin(conn_data[di].cang); - newy = - p->ssx*sin(conn_data[di].cang)+ - p->ssy*cos(conn_data[di].cang); - p->ssx = newx; - p->ssy = newy; - } - } - - - if ( individual_coffset == 0 ) { - - int pi; + if ( ip == 0 ) { - for (pi=0; pi<det->n_panels; pi++) { - det->panels[pi].coffset -= use_clen*(1.0-stretch_coeff); - } - STATUS("Using a single offset distance for the whole detector: " - "%f m.\n", det->panels[0].coffset); + p->cnx *= conn_data[di].cstr; + p->cny *= conn_data[di].cstr; - for ( di=0; di<connected->n_rigid_groups; di++ ) { - conn_data[di].cstr = stretch_coeff; - } + } else { - } else { + struct panel *p0; + double delta_x, delta_y; - STATUS("Using an individual distance for each connected group.\n"); - for ( di=0; di<connected->n_rigid_groups; di++ ) { - for ( ip=0; ip<connected->rigid_groups[di]->n_panels; - ip++ ) { + p0 = connected->rigid_groups[di]->panels[0]; - struct panel *p; + delta_x = p->cnx-p0->cnx/conn_data[di].cstr; + delta_y = p->cny-p0->cny/conn_data[di].cstr; - p = connected->rigid_groups[di]->panels[ip]; - p->coffset -= (1.0-conn_data[di].cstr)*p->clen; + p->cnx = p0->cnx + delta_x; + p->cny = p0->cny + delta_y; } } @@ -1291,90 +1430,125 @@ static void correct_angle_and_stretch(struct rg_collection *connected, } -static void shift_panels(struct rg_collection *connected, - struct connected_data *conn_data) +static void correct_rotation_and_stretch(struct rg_collection *connected, + struct detector *det, + struct connected_data *conn_data, + double clen_to_use, + double stretch_coeff, + struct geoptimiser_params *gparams) { int di, ip; + STATUS("Applying rotation and stretch corrections.\n"); for ( di=0; di<connected->n_rigid_groups; di++ ) { for ( ip=0; ip<connected->rigid_groups[di]->n_panels; ip++ ) { struct panel *p; + double new_fsx, new_fsy, new_ssx, new_ssy; p = connected->rigid_groups[di]->panels[ip]; - if ( ip == 0 ) { + new_fsx = p->fsx*cos(conn_data[di].cang)- + p->fsy*sin(conn_data[di].cang); + new_fsy = p->fsx*sin(conn_data[di].cang)+ + p->fsy*cos(conn_data[di].cang); + new_ssx = p->ssx*cos(conn_data[di].cang)- + p->ssy*sin(conn_data[di].cang); + new_ssy = p->ssx*sin(conn_data[di].cang)+ + p->ssy*cos(conn_data[di].cang); + p->fsx = new_fsx; + p->fsy = new_fsy; + p->ssx = new_ssx; + p->ssy = new_ssy; + } + } - p->cnx *= conn_data[di].cstr; - p->cny *= conn_data[di].cstr; - } else { + if ( gparams->individual_coffset ) { - struct panel *p0; - double delta_x, delta_y; - - p0 = connected->rigid_groups[di]->panels[0]; + STATUS("Using individual distances for rigid panels.\n"); + for ( di=0; di<connected->n_rigid_groups; di++ ) { + for ( ip=0; ip<connected->rigid_groups[di]->n_panels; + ip++ ) { - delta_x = (p->cnx-p0->cnx/conn_data[di].cstr); - delta_y = (p->cny-p0->cny/conn_data[di].cstr); + struct panel *p; - p->cnx = p0->cnx + delta_x * cos(conn_data[di].cang) - - delta_y * sin(conn_data[di].cang); - p->cny = p0->cny + delta_x * sin(conn_data[di].cang) - + delta_y * cos(conn_data[di].cang); + p = connected->rigid_groups[di]->panels[ip]; + p->coffset -= (1.0-conn_data[di].cstr)*clen_to_use; } } + + } else { + + int pi; + + for ( di=0; di<connected->n_rigid_groups; di++ ) { + conn_data[di].cstr = stretch_coeff; + } + + for ( pi=0; pi<det->n_panels; pi++) { + det->panels[pi].coffset -= clen_to_use*(1.0-stretch_coeff); + } + STATUS("Using a single offset distance for the whole " + "detector: %f m. Stretch ceofficient: %0.4f\n", + det->panels[0].coffset, stretch_coeff); } + + correct_corner_coordinates(connected, conn_data); } -static void recompute_panel(struct connected_data *conn_data, int di, int ip, - struct rg_collection *connected, - double *slab_to_x, - double *slab_to_y, - double *recomputed_slab_to_x, - double *recomputed_slab_to_y, - double *displ_x, double *displ_y, - double stretch_coeff, int aw, int *num_pix_displ) +static void adjust_panel(struct connected_data *conn_data, int di, int ip, + struct rg_collection *connected, + struct pixel_maps *pixel_maps, + struct pixel_maps *recomputed_pixel_maps, + struct avg_displacements *avg_displ, + double stretch_coeff, + struct enhanced_det *edet, int *num_pix_displ) { - double c_stretch; struct panel *p; int ifs, iss; c_stretch = conn_data[di].cstr; - if ( fabs(c_stretch)<FLT_EPSILON ) c_stretch = - stretch_coeff; + //TODO + + if ( fabs(c_stretch)<FLT_EPSILON ) c_stretch = stretch_coeff; p = connected->rigid_groups[di]->panels[ip]; for ( ifs=p->min_fs; ifs<p->max_fs+1; ifs++ ) { for ( iss=p->min_ss; iss<p->max_ss+1; iss++ ) { - recomputed_slab_to_x[ifs+aw*iss] /= c_stretch; - recomputed_slab_to_y[ifs+aw*iss] /= c_stretch; - if ( num_pix_displ[ifs+aw*iss] >= + + int pix_index = ifs+edet->width*iss; + + recomputed_pixel_maps->pix_to_x[pix_index] /= c_stretch; + recomputed_pixel_maps->pix_to_y[pix_index] /= c_stretch; + if ( num_pix_displ[pix_index] >= conn_data[di].num_peaks_per_pixel) { - displ_x[ifs+aw*iss] -= (slab_to_x[ifs+aw*iss]- - recomputed_slab_to_x[ifs+aw*iss]); - displ_y[ifs+aw*iss] -= (slab_to_y[ifs+aw*iss]- - recomputed_slab_to_y[ifs+aw*iss]); + avg_displ->displ_x[pix_index] -= + (pixel_maps->pix_to_x[pix_index]- + recomputed_pixel_maps->pix_to_x[pix_index]); + avg_displ->displ_y[pix_index] -= + (pixel_maps->pix_to_y[pix_index]- + recomputed_pixel_maps->pix_to_y[pix_index]); } } } } -static void recompute_differences(struct rg_collection *connected, - double *slab_to_x, double *slab_to_y, - double *recomputed_slab_to_x, - double *recomputed_slab_to_y, - struct connected_data *conn_data, - double stretch_coeff, int aw, - double *displ_x, double *displ_y, - int *num_pix_displ) +static void adjust_displ_for_stretch(struct rg_collection *connected, + struct pixel_maps *pixel_maps, + struct pixel_maps *recomputed_pixel_maps, + struct connected_data *conn_data, + double stretch_coeff, + struct enhanced_det *edet, + struct avg_displacements *avg_displ, + int *num_pix_displ) { int di, ip; @@ -1382,47 +1556,57 @@ static void recompute_differences(struct rg_collection *connected, for ( di=0; di<connected->n_rigid_groups; di++ ) { for (ip=0; ip<connected->rigid_groups[di]->n_panels; ip++) { - - recompute_panel(conn_data, di, ip, connected, - slab_to_x, slab_to_y, - recomputed_slab_to_x, - recomputed_slab_to_y, - displ_x, displ_y, - stretch_coeff, aw, num_pix_displ); + adjust_panel(conn_data, di, ip, connected, + pixel_maps, recomputed_pixel_maps, + avg_displ, stretch_coeff, edet, + num_pix_displ); } } } -static void fill_av_in_panel(struct rg_collection *connected, int di, int ip, - struct connected_data *conn_data, - int *num_pix_displ, int aw, - double *av_in_panel_fs, - double *av_in_panel_ss, - double *displ_x, double *displ_y) +static void fill_av_conn(struct rg_collection *connected, int di, + struct connected_data *conn_data, + int *num_pix_displ, struct enhanced_det *edet, + double *list_displ_in_conn_fs, + double *list_displ_in_conn_ss, + struct avg_displacements *avg_displ) { struct panel *p; - int ifs, iss; + int ifs, iss, ip; - p = connected->rigid_groups[di]->panels[ip]; + int counter = 0; - for ( ifs=p->min_fs; ifs<p->max_fs+1; ifs++ ) { - for ( iss=p->min_ss; iss<p->max_ss+1; iss++ ) { + for (ip=0; ip<connected->rigid_groups[di]->n_panels; ip++) { + + p = connected->rigid_groups[di]->panels[ip]; + + for ( ifs=p->min_fs; ifs<p->max_fs+1; ifs++ ) { + for ( iss=p->min_ss; iss<p->max_ss+1; iss++ ) { - if (num_pix_displ[ifs+aw*iss]>= - conn_data[di].num_peaks_per_pixel) { - av_in_panel_fs[conn_data[di].n_peaks_in_conn] = - displ_x[ifs+aw*iss]; - av_in_panel_ss[conn_data[di].n_peaks_in_conn] = - displ_y[ifs+aw*iss]; - conn_data[di].n_peaks_in_conn++; + int pix_index = ifs+edet->width*iss; + + if ( num_pix_displ[pix_index] >= + conn_data[di].num_peaks_per_pixel ) { + list_displ_in_conn_fs[counter] = + avg_displ->displ_x[pix_index]; + list_displ_in_conn_ss[counter] = + avg_displ->displ_y[pix_index]; + counter++; + } } } } + + if ( counter != conn_data[di].n_peaks_in_conn ) { + printf("counter: %i n_peaks_in_conn: %i\n", + counter, conn_data[di].n_peaks_in_conn); + exit(0); + } } -static void fill_con_data_sh(struct connected_data *conn_data, +static void fill_conn_data_sh(struct connected_data *conn_data, double *av_in_panel_fs, double *av_in_panel_ss, int di, double max_peak_distance) @@ -1431,11 +1615,11 @@ static void fill_con_data_sh(struct connected_data *conn_data, conn_data[di].n_peaks_in_conn); conn_data[di].sh_y = comp_median(av_in_panel_ss, conn_data[di].n_peaks_in_conn); - STATUS("Panel %s, num of considered pixels: %i, shifts (in pixels) x,y: %0.8f, %0.8f\n", + STATUS("Panel %s, num pixels: %i, shifts (in pixels) X,Y: %0.8f, %0.8f\n", conn_data[di].name, conn_data[di].n_peaks_in_conn, conn_data[di].sh_x, conn_data[di].sh_y); - if ( modulus2d(conn_data[di].sh_x, conn_data[di].sh_y) > - 0.8*max_peak_distance ) { + if ( modulus2d(conn_data[di].sh_x, conn_data[di].sh_y ) > + 0.8*max_peak_distance ) { STATUS(" WARNING: absolute shift is: %0.1f > 0.8*%0.1f pixels." " Increase the value of the max_peak_distance parameter!\n", modulus2d(conn_data[di].sh_x, conn_data[di].sh_y), @@ -1444,162 +1628,183 @@ static void fill_con_data_sh(struct connected_data *conn_data, } -static int compute_shifts(struct rg_collection *connected, - struct connected_data *conn_data, - int *num_pix_displ, int aw, - int min_num_peaks_per_panel, - double dfv, double max_peak_distance, - double *displ_x, double *displ_y) +static int compute_shift(struct rg_collection *connected, + struct connected_data *conn_data, + int *num_pix_displ, + struct enhanced_det *edet, + struct geoptimiser_params *gparams, + struct avg_displacements *avg_displ) { - STATUS("Computing average shifts for connected groups.\n"); + STATUS("Computing shift corrections.\n"); - int di, ip; + int di; for ( di=0; di<connected->n_rigid_groups; di++ ) { - int cmaxfs; - int cmaxss; - int num_all_pixels; - double *av_in_panel_fs; - double *av_in_panel_ss; + double *list_displ_in_conn_fs; + double *list_displ_in_conn_ss; - cmaxfs = connected->rigid_groups[di]->panels[0]->max_fs+1- - connected->rigid_groups[di]->panels[0]->min_fs; - cmaxss = connected->rigid_groups[di]->panels[0]->max_ss+1- - connected->rigid_groups[di]->panels[0]->min_ss; - - num_all_pixels = cmaxfs*cmaxss*connected->rigid_groups[di]->n_panels; - - av_in_panel_fs = malloc(num_all_pixels*sizeof(double)); - if ( av_in_panel_fs == NULL ) { + list_displ_in_conn_fs = malloc(conn_data[di].n_peaks_in_conn* + sizeof(double)); + if ( list_displ_in_conn_fs == NULL ) { ERROR("Failed to allocate memory for computing shifts\n"); return 1; } - av_in_panel_ss = malloc(num_all_pixels*sizeof(double)); - if ( av_in_panel_ss == NULL ) { + list_displ_in_conn_ss = malloc(conn_data[di].n_peaks_in_conn* + sizeof(double)); + if ( list_displ_in_conn_ss == NULL ) { ERROR("Failed to allocate memory for computing shifts\n"); - free(av_in_panel_fs); + free(list_displ_in_conn_fs); return 1; } - conn_data[di].n_peaks_in_conn = 0; - - for (ip=0; ip<connected->rigid_groups[di]->n_panels; ip++) { + fill_av_conn(connected, di, conn_data, num_pix_displ, edet, + list_displ_in_conn_fs, list_displ_in_conn_ss, + avg_displ); - fill_av_in_panel(connected, di, ip, conn_data, - num_pix_displ, aw, av_in_panel_fs, - av_in_panel_ss, displ_x, displ_y); - - } - - if ( conn_data[di].n_peaks_in_conn>=min_num_peaks_per_panel ) { - - fill_con_data_sh(conn_data, av_in_panel_fs, - av_in_panel_ss, di, - max_peak_distance); + if ( conn_data[di].n_peaks_in_conn >= + gparams->min_num_pix_per_conn_group ) { + fill_conn_data_sh(conn_data, list_displ_in_conn_fs, + list_displ_in_conn_ss, di, + gparams->max_peak_dist); } else { - conn_data[di].sh_x = dfv; - conn_data[di].sh_y = dfv; + conn_data[di].sh_x = -10000.0; + conn_data[di].sh_y = -10000.0; } - free(av_in_panel_fs); - free(av_in_panel_ss); - } + free(list_displ_in_conn_fs); + free(list_displ_in_conn_ss); + } return 0; } -static int compute_shifts_for_empty_panels(struct rg_collection *quadrants, - struct rg_collection *connected, - struct connected_data *conn_data, - int min_num_peaks_per_panel) +struct avg_shift *initialize_avg_shift(int num_rigid_groups) { + struct avg_shift *avg_sh; + int i; - double *aver_x; - double *aver_y; - int *num_aver; - int di, i; + avg_sh = malloc(sizeof(struct avg_shift)); + if ( avg_sh == NULL ) { + ERROR("Failed to allocate memory to compute shifts for " + "empty panels.\n"); + return NULL; + } - // shifts for empty - aver_x = malloc(quadrants->n_rigid_groups*sizeof(double)); - if ( aver_x == NULL ) { + avg_sh->aver_x = malloc(num_rigid_groups*sizeof(double)); + if ( avg_sh->aver_x == NULL ) { ERROR("Failed to allocate memory to compute shifts for " "empty panels.\n"); - return 1; + free(avg_sh); + return NULL; } - aver_y = malloc(quadrants->n_rigid_groups*sizeof(double)); - if ( aver_y == NULL ) { + avg_sh->aver_y = malloc(num_rigid_groups*sizeof(double)); + if ( avg_sh->aver_y == NULL ) { ERROR("Failed to allocate memory to compute shifts for " "empty panels.\n"); - free(aver_x); - return 1; + free(avg_sh->aver_x); + free(avg_sh); + return NULL; } - num_aver = malloc(quadrants->n_rigid_groups*sizeof(int)); - if ( num_aver == NULL ) { + avg_sh->aver_num_sh = malloc(num_rigid_groups*sizeof(int)); + if ( avg_sh->aver_num_sh == NULL ) { ERROR("Failed to allocate memory to compute shifts for " "empty panels.\n"); - free(aver_x); - free(aver_y); - return 1; + free(avg_sh->aver_x); + free(avg_sh->aver_y); + free(avg_sh); + return NULL; } - for ( i=0; i<quadrants->n_rigid_groups; i++ ) { - aver_x[i] = 0; - aver_y[i] = 0; - num_aver[i] = 0; + for ( i=0; i<num_rigid_groups; i++ ) { + avg_sh->aver_x[i] = 0.0; + avg_sh->aver_y[i] = 0.0; + avg_sh->aver_num_sh[i] = 0; } + return avg_sh; +} + + +void free_avg_shift(struct avg_shift *av_sh) { + free(av_sh->aver_x); + free(av_sh->aver_y); + free(av_sh->aver_num_sh); + free(av_sh); +} + + +static int compute_shift_for_empty_panels(struct rg_collection *quadrants, + struct rg_collection *connected, + struct connected_data *conn_data, + struct geoptimiser_params* gparams) +{ + + struct avg_shift *av_sh; + int di, i; + + STATUS("Computing shift corrections for groups without the required " + "number of measurements.\n"); + av_sh = initialize_avg_shift(quadrants->n_rigid_groups); + if ( av_sh == NULL ) return 1; + for ( di=0; di<connected->n_rigid_groups; di++ ) { - if ( conn_data[di].n_peaks_in_conn>=min_num_peaks_per_panel ) { - aver_x[conn_data[di].num_quad] += conn_data[di].sh_x; - aver_y[conn_data[di].num_quad] += conn_data[di].sh_y; - num_aver[conn_data[di].num_quad]++; + if ( conn_data[di].n_peaks_in_conn >= + gparams->min_num_pix_per_conn_group ) { + av_sh->aver_x[conn_data[di].num_quad] += + conn_data[di].sh_x; + av_sh->aver_y[conn_data[di].num_quad] += + conn_data[di].sh_y; + av_sh->aver_num_sh[conn_data[di].num_quad]++; } } for ( i=0; i<quadrants->n_rigid_groups; i++ ) { - if (num_aver[i]>0) { - aver_x[i] /= (double)num_aver[i]; - aver_y[i] /= (double)num_aver[i]; + if (av_sh->aver_num_sh[i]>0) { + av_sh->aver_x[i] /= (double)av_sh->aver_num_sh[i]; + av_sh->aver_y[i] /= (double)av_sh->aver_num_sh[i]; } } for (di=0; di<connected->n_rigid_groups; di++) { - if ( conn_data[di].n_peaks_in_conn<min_num_peaks_per_panel ) { - if ( num_aver[conn_data[di].num_quad]>0 ) { - conn_data[di].sh_x = aver_x[conn_data[di].num_quad]; - conn_data[di].sh_y = aver_y[conn_data[di].num_quad]; - STATUS("Panel %s has not enough (%i) peaks. " - "Using average shifts (in pixels) X,Y: " - "%0.2f,%0.2f\n", conn_data[di].name, + if ( conn_data[di].n_peaks_in_conn < + gparams->min_num_pix_per_conn_group ) { + if ( av_sh->aver_num_sh[conn_data[di].num_quad] > 0 ) { + conn_data[di].sh_x = + av_sh->aver_x[conn_data[di].num_quad]; + conn_data[di].sh_y = + av_sh->aver_y[conn_data[di].num_quad]; + STATUS("Panel %s doesn't not have eough (%i) " + "peaks. Using average shifts (in pixels) " + "X,Y: %0.2f,%0.2f\n", conn_data[di].name, conn_data[di].n_peaks_in_conn, conn_data[di].sh_x, conn_data[di].sh_y); } else { STATUS("Panel %s has not enough (%i) peaks. " - "Left unchanged.\n", + "It will not be moved.\n", conn_data[di].name, conn_data[di].n_peaks_in_conn); } } } - free(aver_x); - free(aver_y); - free(num_aver); + free_avg_shift(av_sh); return 0; } -static void correct_shifts(struct rg_collection *connected, - struct connected_data *conn_data, - double dfv, double clen_to_use) +static void correct_shift(struct rg_collection *connected, + struct connected_data *conn_data, + double clen_to_use) { int di; int ip; + STATUS("Applying shift corrections.\n"); + for ( di=0;di<connected->n_rigid_groups;di++ ) { for (ip=0; ip<connected->rigid_groups[di]->n_panels; ip++) { @@ -1607,300 +1812,246 @@ static void correct_shifts(struct rg_collection *connected, p = connected->rigid_groups[di]->panels[ip]; - if ( conn_data[di].sh_x>dfv+1.0 && - conn_data[di].sh_y > dfv+1.0 ) { + if ( conn_data[di].sh_x > -9999.0 && + conn_data[di].sh_y > -9999.0 ) { p->cnx -= conn_data[di].sh_x; p->cny -= conn_data[di].sh_y; } else { - STATUS("For some reason connected group %s is " - "empty! Left unchanged.\n", - p->name); + STATUS("For some reason shifts for panel %s has " + "not been computed!\n", p->name); } } } } -static void a_s_counting_loop(int *num_pix_displ, int ifs, int iss, - int di, struct connected_data *conn_data, - int aw, double *slab_to_x, - double *slab_to_y, struct panel *p0, - struct panel *p1, double *displ_x, - double *displ_y, double minrad, - int *num_ang) +static struct connected_stretch_and_angles *initialize_connected_stretch_angles( + struct rg_collection *connected) { - double coX, coY, cdX, cdY; - - if ( num_pix_displ[ifs+aw*iss]>= - conn_data[di].num_peaks_per_pixel ) { - - int ifs1, iss1; - int max_fs1_tmp = p0->max_fs; - int max_ss1_tmp = p0->max_ss; - - coX = slab_to_x[ifs+aw*iss]; - coY = slab_to_y[ifs+aw*iss]; - cdX = coX - displ_x[ifs+aw*iss]; - cdY = coY - displ_y[ifs+aw*iss]; - - for (ifs1=ifs+1; ifs1<max_fs1_tmp+1; ifs1++) { - - if ( ifs1 == max_fs1_tmp ) { - max_fs1_tmp = p1->max_fs; - } - - for (iss1=iss+1; iss1<max_ss1_tmp+1; iss1++) { - - if ( iss1 == max_ss1_tmp ) { - max_ss1_tmp = p1->max_ss; - } - - if ( num_pix_displ[ifs1+aw*iss1]>= - conn_data[di].num_peaks_per_pixel ) { - - double dist; - double coX1, coY1, cdX1, cdY1; - double len1, len2; - - dist = modulus2d(ifs-ifs1,iss-iss1); - if ( dist < minrad ) continue; - coX1 = slab_to_x[ifs1+aw*iss1]; - coY1 = slab_to_y[ifs1+aw*iss1]; - cdX1 = - coX1 - displ_x[ifs1+aw*iss1]; - cdY1 = - coY1 - displ_y[ifs1+aw*iss1]; - - len1 = modulus2d(coX1-coX, coY1-coY); - len2 = modulus2d(cdX1-cdX, cdY1-cdY); - if ( len1<FLT_EPSILON || - len2<FLT_EPSILON ) { - continue; - } + struct connected_stretch_and_angles *csaa; - *num_ang = *num_ang+1; - } - } - } + csaa = malloc(sizeof(struct connected_stretch_and_angles)); + if ( csaa == NULL ) { + ERROR("Failed to allocate memory to compute angles and " + "stretch.\n"); + return NULL; + } + csaa->stretch_coeff = malloc(connected->n_rigid_groups*sizeof(double)); + if ( csaa->stretch_coeff == NULL ) { + ERROR("Failed to allocate memory to compute angles and " + "stretch.\n"); + free(csaa); + return NULL; } + csaa->num_angles = malloc(connected->n_rigid_groups*sizeof(long)); + if ( csaa->num_angles == NULL ) { + ERROR("Failed to allocate memory to compute angles and " + "stretch.\n"); + free(csaa->stretch_coeff); + free(csaa); + return NULL; + } + csaa->num_coeff=0; + return csaa; } -static int a_s_processing_loop(int *num_pix_displ, int ifs, int iss, - int di, struct connected_data *conn_data, - int aw, double *slab_to_x, - double *slab_to_y, struct panel *p0, - struct panel *p1, double *displ_x, - double *displ_y, double minrad, - int max_num_ang, int *num_ang, - double *angles, double *stretches) +static void scan_p1(int ip0, int ip1, struct rg_collection *connected, + struct avg_displacements *avg_displ, + struct connected_data *conn_data, + struct enhanced_det *edet, + struct pixel_maps *pixel_maps, + int* num_pix_displ, + int di, double min_dist, + long *num_ang, int ifs0, int iss0, + double c_x0, double c_y0, double cd_x0, double cd_y0, + int compute, double *angles, double *stretches) { - double coX, coY, cdX, cdY; - if ( num_pix_displ[ifs+aw*iss]>= - conn_data[di].num_peaks_per_pixel ) { + int iss1, ifs1; - int ifs1, iss1; - int max_fs1_tmp = p0->max_fs; - int max_ss1_tmp = p0->max_ss; + struct panel *p1 = connected->rigid_groups[di]->panels[ip1]; - if ( *num_ang>=max_num_ang ) return -2; + int min_ss_p1, min_fs_p1; - coX = slab_to_x[ifs+aw*iss]; - coY = slab_to_y[ifs+aw*iss]; - cdX = coX - displ_x[ifs+aw*iss]; - cdY = coY - displ_y[ifs+aw*iss]; + if ( ip0 == ip1 ) { + min_fs_p1 = ifs0; + min_ss_p1 = iss0; + } else { + min_fs_p1 = p1->min_fs; + min_ss_p1 = p1->min_ss; + } - for (ifs1=ifs+1; ifs1<max_fs1_tmp+1; ifs1++) { + for ( iss1=min_ss_p1; iss1<p1->max_ss+1; iss1++ ) { - if ( ifs1 == max_fs1_tmp ) { - max_fs1_tmp = p1->max_fs; - } + for ( ifs1=min_fs_p1; ifs1<p1->max_fs+1; ifs1++ ) { - for (iss1=iss+1; iss1<max_ss1_tmp+1; iss1++) { + int pix_index1 = ifs1+edet->width*iss1; + + if ( num_pix_displ[pix_index1]>= + conn_data[di].num_peaks_per_pixel ) { - if ( iss1 == max_ss1_tmp ) { - max_ss1_tmp = p1->max_ss; + double dist; + double c_x1, c_y1, cd_x1, cd_y1; + double d_c_x, d_c_y, d_cd_x, d_cd_y; + double len1, len2; + + c_x1 = pixel_maps->pix_to_x[pix_index1]; + c_y1 = pixel_maps->pix_to_y[pix_index1]; + cd_x1 = c_x1 - avg_displ->displ_x[pix_index1]; + cd_y1 = c_y1 - avg_displ->displ_y[pix_index1]; + d_c_x = c_x1-c_x0; + d_c_y = c_y1-c_y0; + d_cd_x = cd_x1-cd_x0; + d_cd_y = cd_y1-cd_y0; + + dist = modulus2d(d_c_x,d_c_y); + if ( dist < min_dist ) continue; + + len1 = modulus2d(d_c_x, d_c_y); + len2 = modulus2d(d_cd_x, d_cd_y); + if ( len1<FLT_EPSILON || len2<FLT_EPSILON ) { + continue; } - if ( num_pix_displ[ifs1+aw*iss1]>= - conn_data[di].num_peaks_per_pixel ) { + if (compute) { - double dist; - double coX1, coY1, cdX1, cdY1; - double len1, len2; - double scalM; + double scal_m; double multlen; - if ( *num_ang>=max_num_ang ) return -2; - dist = modulus2d(ifs-ifs1,iss-iss1); - if (dist<minrad) return 0; - coX1 = slab_to_x[ifs1+aw*iss1]; - coY1 = slab_to_y[ifs1+aw*iss1]; - cdX1 = - coX1 - displ_x[ifs1+aw*iss1]; - cdY1 = - coY1 - displ_y[ifs1+aw*iss1]; - - len1 = modulus2d(coX1-coX, coY1-coY); - len2 = modulus2d(cdX1-cdX, cdY1-cdY); - scalM = (coX1-coX)*(cdX1-cdX)+ - (coY1-coY)*(cdY1-cdY)- - FLT_EPSILON; - if ( len1<FLT_EPSILON || - len2<FLT_EPSILON ) { - return 0; - } + scal_m = d_c_x * d_cd_x+ + d_c_y * d_cd_y - + FLT_EPSILON; multlen = len1*len2; - if ( fabs(scalM)>=multlen ) { + if ( fabs(scal_m)>=multlen ) { angles[*num_ang] = 0.0; } else { - angles[*num_ang] = 1.0; - - angles[*num_ang] = - acos(scalM/multlen); + angles[*num_ang] = acos(scal_m + /multlen); - if ((coY1-coY)*(cdX1-cdX)- - (coX1-coX)*(cdY1-cdY) < 0) { + if (d_c_y * d_cd_x - + d_c_x * d_cd_y < 0) { angles[*num_ang] *= -1.; } } stretches[*num_ang] = len1/len2; - - *num_ang = *num_ang+1; } + + *num_ang = *num_ang+1; } } } - return 0; } +static void scan_p0(int ip0, struct rg_collection *connected, + struct avg_displacements *avg_displ, + struct connected_data *conn_data, + struct enhanced_det *edet, + struct pixel_maps *pixel_maps, + int* num_pix_displ, + int di, double min_dist, + long *num_ang, int compute, + double *angles, double *stretches) +{ + + int iss0, ifs0, ip1; + + struct panel *p0 = connected->rigid_groups[di]->panels[ip0]; + for ( iss0=p0->min_ss; iss0<p0->max_ss+1; iss0++ ) { -static int compute_angles_and_stretch(struct rg_collection *connected, - struct connected_data *conn_data, - int *num_pix_displ, - double *slab_to_x, - double *slab_to_y, - double *displ_x, - double *displ_y, - int aw, - int min_num_peaks_per_panel, - double dist_coeff_ang_str, - int num_peaks_per_pixel, - double man_stretching_coeff, - double *stretch_coeff) + for ( ifs0=p0->min_fs; ifs0<p0->max_fs+1; ifs0++ ) { + + int pix_index0 = ifs0+edet->width*iss0; + + if ( num_pix_displ[pix_index0]>= + conn_data[di].num_peaks_per_pixel ) { + + double c_x0, c_y0, cd_x0, cd_y0; + + c_x0 = pixel_maps->pix_to_x[pix_index0]; + c_y0 = pixel_maps->pix_to_y[pix_index0]; + cd_x0 = c_x0 - avg_displ->displ_x[pix_index0]; + cd_y0 = c_y0 - avg_displ->displ_y[pix_index0]; + + for ( ip1=ip0; + ip1<connected->rigid_groups[di]->n_panels; + ip1++ ) { + scan_p1(ip0, ip1, connected, avg_displ, + conn_data, edet, pixel_maps, + num_pix_displ, di, min_dist, + num_ang, ifs0, iss0, c_x0, + c_y0, cd_x0, cd_y0, compute, + angles, stretches); + } + } + } + } +} + + +static double compute_rotation_and_stretch(struct rg_collection *connected, + struct connected_data *conn_data, + struct enhanced_det *edet, + int *num_pix_displ, + struct pixel_maps *pixel_maps, + struct avg_displacements *avg_displ, + double dist_coeff_for_rot_str, + struct geoptimiser_params *gparams) { int di; - int num_coeff; double stretch_cf; struct connected_stretch_and_angles *csaa; - csaa = malloc(sizeof(struct connected_stretch_and_angles)); + STATUS("Computing rotation and stretch corrections.\n"); + + csaa = initialize_connected_stretch_angles(connected); if ( csaa == NULL ) { - ERROR("Failed to allocate memory to compute angles and " - "stretch.\n"); - return 1; - } - csaa->stretch_coeff = malloc(connected->n_rigid_groups*sizeof(double)); - if ( csaa->stretch_coeff == NULL ) { - ERROR("Failed to allocate memory to compute angles and " - "stretch.\n"); - free(csaa); - return 1; - } - csaa->num_angles = malloc(connected->n_rigid_groups*sizeof(unsigned int)); - if ( csaa->num_angles == NULL ) { - ERROR("Failed to allocate memory to compute angles and " - "stretch.\n"); - free(csaa->stretch_coeff); - free(csaa); - return 1; + return -1.0; } - csaa->num_coeff=0; - for ( di=0; di<connected->n_rigid_groups; di++ ) { - if ( conn_data[di].n_peaks_in_conn<min_num_peaks_per_panel ) { + if ( conn_data[di].n_peaks_in_conn < + gparams->min_num_pix_per_conn_group ) { continue; } - unsigned int max_num_ang = 0; + long max_num_ang = 0; + double min_dist; double* angles; double* stretches; - int cmaxfs; - int cmaxss; - - struct panel *p; - double minrad; - int num_ang = 0; - int ip0, ip1; + struct panel *first_p; + long num_ang = 0; + int ip0; + int num_pix_first_p; - p = connected->rigid_groups[di]->panels[0]; + first_p = connected->rigid_groups[di]->panels[0]; - cmaxfs = p->max_fs+1-p->min_fs; - cmaxss = p->max_ss+1-p->min_ss; + num_pix_first_p = (first_p->max_fs+1-first_p->min_fs)* + (first_p->max_ss+1-first_p->min_ss); // TODO: MINRAD HERE IS NOT UNIVERSAL - minrad = dist_coeff_ang_str*sqrt(cmaxfs*cmaxss* - connected->rigid_groups[di]->n_panels); + min_dist = dist_coeff_for_rot_str*sqrt(num_pix_first_p* + connected->rigid_groups[di]->n_panels); for ( ip0=0; ip0<connected->rigid_groups[di]->n_panels; ip0++ ) { - struct panel *p0 = connected->rigid_groups[di]->panels[ip0]; - - for ( ip1=0; ip1<connected->rigid_groups[di]->n_panels; - ip1++ ) { - - struct panel *p1 = - connected->rigid_groups [di]->panels[ip1]; - - int ifs, iss; - int min_fs_tmp = p0->min_fs; - int max_fs_tmp = p0->max_fs; - int min_ss_tmp = p0->min_ss; - int max_ss_tmp = p0->max_ss; - - for (ifs=min_fs_tmp; ifs<max_fs_tmp+1; ifs++) { - - if ( ifs == max_fs_tmp ) { - min_fs_tmp = p1->min_fs; - max_fs_tmp = p1->max_fs; - } - - for (iss=min_ss_tmp; iss<max_ss_tmp+1; - iss++) { - - if ( iss == max_ss_tmp ) { - min_ss_tmp = p1->min_ss; - max_ss_tmp = p1->max_ss; - } - - a_s_counting_loop(num_pix_displ, - ifs, iss, di, conn_data, - aw, slab_to_x, slab_to_y, - p0, p1, displ_x, - displ_y, minrad, - &num_ang); - - } - } - } + scan_p0(ip0, connected, avg_displ, conn_data, edet, + pixel_maps, num_pix_displ, di, min_dist, + &num_ang, 0, NULL, NULL); } - max_num_ang = conn_data[di].n_peaks_in_conn* - conn_data[di].n_peaks_in_conn; max_num_ang = num_ang+1; angles = malloc(max_num_ang*sizeof(double)); @@ -1910,7 +2061,7 @@ static int compute_angles_and_stretch(struct rg_collection *connected, free(csaa->stretch_coeff); free(csaa->num_angles); free(csaa); - return 1; + return -1.0; } stretches = malloc(max_num_ang*sizeof(double)); if ( stretches == NULL ) { @@ -1920,71 +2071,25 @@ static int compute_angles_and_stretch(struct rg_collection *connected, free(csaa->stretch_coeff); free(csaa->num_angles); free(csaa); - return 1; + return -1.0; } num_ang = 0; for ( ip0=0; ip0<connected->rigid_groups[di]->n_panels; ip0++ ) { - struct panel *p0 = connected->rigid_groups[di]->panels[ip0]; - - for ( ip1=0; ip1<connected->rigid_groups[di]->n_panels; - ip1++ ) { - - struct panel *p1 = - connected->rigid_groups [di]->panels[ip1]; - - int ifs, iss; - int min_fs_tmp = p0->min_fs; - int max_fs_tmp = p0->max_fs; - int min_ss_tmp = p0->min_ss; - int max_ss_tmp = p0->max_ss; - - for (ifs=min_fs_tmp; ifs<max_fs_tmp+1; ifs++) { - - if ( ifs == max_fs_tmp ) { - min_fs_tmp = p1->min_fs; - max_fs_tmp = p1->max_fs; - } - - for (iss=min_ss_tmp; iss<max_ss_tmp+1; - iss++) { - - int ret; - - if ( iss == max_ss_tmp ) { - min_ss_tmp = p1->min_ss; - max_ss_tmp = p1->max_ss; - } - - ret = a_s_processing_loop( - num_pix_displ, - ifs, iss, di, - conn_data, - aw, slab_to_x, - slab_to_y, - p0, p1, displ_x, - displ_y, minrad, - max_num_ang, - &num_ang, angles, - stretches); - - if ( ret == -2 ) break; - } - } - } + scan_p0(ip0, connected, avg_displ, conn_data, edet, + pixel_maps, num_pix_displ, di, min_dist, + &num_ang, 1, angles, stretches); } - if ( num_ang<1 ) continue; - conn_data[di].cang = -comp_median(angles,num_ang); - conn_data[di].cstr = comp_median(stretches,num_ang); + if ( num_ang < 1 ) continue; + conn_data[di].cang = -comp_median(angles, num_ang); + conn_data[di].cstr = comp_median(stretches, num_ang); - STATUS("Connected group %s:\n" - " Number of measurements: %i Angle: %0.4f deg " - "Stretch coefficient: %0.4f\n", - conn_data[di].name, num_ang, conn_data[di].cang, - conn_data[di].cstr); + STATUS("Panel %s, num: %li, angle: %0.4f deg, stretch coeff: " + "%0.4f\n", conn_data[di].name, num_ang, conn_data[di].cang, + conn_data[di].cstr); csaa->stretch_coeff[csaa->num_coeff] = conn_data[di].cstr; csaa->num_angles[csaa->num_coeff] = num_ang; @@ -1994,55 +2099,57 @@ static int compute_angles_and_stretch(struct rg_collection *connected, free(stretches); } + stretch_cf = 1.0; + + printf("Computing overall stretch coefficient.\n"); - num_coeff = csaa->num_coeff; + if ( csaa->num_coeff>0 ) { - stretch_cf = 1; - if (num_coeff>0) { + int peaks_per_p; - int ipp; + peaks_per_p = gparams->min_num_peaks_per_pix; - for ( ipp=num_peaks_per_pixel; ipp>=0; ipp-- ) { + while ( peaks_per_p>=0 ) { double total_num; - int di; + long di; + stretch_cf = 0; total_num = 0; - for ( di=0; di<num_coeff; di++ ) { - if ( conn_data[di].num_peaks_per_pixel>=ipp ) { + for ( di=0; di<csaa->num_coeff; di++ ) { + if ( conn_data[di].num_peaks_per_pixel >= + peaks_per_p ) { + stretch_cf += csaa->stretch_coeff[di]* + (double)csaa->num_angles[di]; total_num += csaa->num_angles[di]; } } - if ( total_num>1 ) { - total_num = 1./total_num; - } else { - continue; - } - stretch_cf = 0; - for ( di=0; di<num_coeff; di++ ) { - if ( conn_data[di].num_peaks_per_pixel>=ipp ) { - stretch_cf += - total_num*csaa->stretch_coeff[di]* - (double)csaa->num_angles[di]; - } + + if ( total_num > 0 ) { + + stretch_cf /= total_num; + + printf("(Using only connected groups for which " + "the minimum number of measurements per " + "pixel is %i).\n", peaks_per_p); + break; } - break; + peaks_per_p--; } } - if ( stretch_cf<FLT_EPSILON ) { + if ( stretch_cf < FLT_EPSILON ) { stretch_cf = 1.0; } - STATUS("The average stretch coefficient for all patterns is %0.4f\n", + STATUS("The global stretch coefficient for the patterns is %0.4f\n", stretch_cf); - if ( man_stretching_coeff>FLT_EPSILON ) { - stretch_cf = man_stretching_coeff; - STATUS("Using manually set stretch coefficient: %0.4f\n", - stretch_cf); - + if ( gparams->nostretch ) { + stretch_cf = 1.0; + STATUS("However, distance offset will not be optimized, so the " + "stretching coefficient has been set to 1.0\n"); for ( di=0; di<connected->n_rigid_groups; di++ ) { - conn_data[di].cstr = man_stretching_coeff; + conn_data[di].cstr = stretch_cf; } } @@ -2051,9 +2158,7 @@ static int compute_angles_and_stretch(struct rg_collection *connected, free(csaa->num_angles); free(csaa); - *stretch_coeff = stretch_cf; - - return 0; + return stretch_cf; } @@ -2114,19 +2219,18 @@ static int unpack_slab(struct image *image) } for ( ss=0; ss<p->h; ss++ ) { - for ( fs=0; fs<p->w; fs++ ) { + for ( fs=0; fs<p->w; fs++ ) { - int idx; - int cfs, css; + int idx; + int cfs, css; - cfs = fs+p->min_fs; - css = ss+p->min_ss; - idx = cfs + css*image->width; + cfs = fs+p->min_fs; + css = ss+p->min_ss; + idx = cfs + css*image->width; - image->dp[pi][fs+p->w*ss] = image->data[idx]; - image->bad[pi][fs+p->w*ss] = 0; - - } + image->dp[pi][fs+p->w*ss] = image->data[idx]; + image->bad[pi][fs+p->w*ss] = 0; + } } } @@ -2188,8 +2292,7 @@ static int draw_detector(cairo_surface_t *surf, struct image *image, } -static int save_data_to_png(char *filename, struct detector *det, - int max_fs, int max_ss, double default_fill_value, +static int save_data_to_png(char *filename, struct enhanced_det *edet, double *data) { struct image im; @@ -2201,18 +2304,18 @@ static int save_data_to_png(char *filename, struct detector *det, cairo_status_t r; cairo_surface_t *surf; - im.data = malloc((max_fs+1)*(max_ss+1)*sizeof(float)); + im.data = malloc((edet->width)*(edet->height)*sizeof(float)); if ( im.data == NULL ) { ERROR("Failed to allocate memory to save data.\n"); return 1; } - im.det = det; - im.width = max_fs+1; - im.height = max_ss+1; + im.det = edet->det; + im.width = edet->width; + im.height = edet->height; im.flags = NULL; - for ( i=0; i<(max_fs+1)*(max_ss+1); i++) { - if ( data[i] == default_fill_value ) { + for ( i=0; i<(edet->width)*(edet->height); i++) { + if ( data[i] == -10000.0) { im.data[i] = 0.0; } else if ( data[i] > 1.0) { im.data[i] = 1.0; @@ -2264,61 +2367,9 @@ static int save_data_to_png(char *filename, struct detector *det, #endif /* HAVE_SAVE_TO_PNG */ -static void calculate_panel_correction(int di, int ip, int aw, - int *num_pix_displ, - struct rg_collection *connected, - struct connected_data *conn_data) -{ - struct panel *p; - int ifs, iss; - - p = connected->rigid_groups[di]->panels[ip]; - for (ifs=p->min_fs; ifs<p->max_fs+1; ifs++) { - for (iss=p->min_ss; iss<p->max_ss+1; iss++) { - if ( num_pix_displ[ifs+aw*iss]>= - conn_data[di].num_peaks_per_pixel ) { - conn_data[di].n_peaks_in_conn++; - } - } - } - -} - - -static void compute_abs_displ(struct rg_collection *connected, - struct connected_data *conn_data, - int *num_pix_displ, - double dfv, int di, int ip, int aw, - double *displ_x, - double *displ_y, - double *displ_abs) -{ - struct panel *p; - int ifs, iss; - - if (conn_data[di].sh_x < dfv+1) return; - - p = connected->rigid_groups[di]->panels[ip]; - - for (ifs=p->min_fs; ifs<p->max_fs+1; ifs++) { - for (iss=p->min_ss; iss<p->max_ss+1; iss++) { - if ( num_pix_displ[ifs+aw*iss]>= - conn_data[di].num_peaks_per_pixel ) { - displ_x[ifs+aw*iss] -= conn_data[di].sh_x; - displ_y[ifs+aw*iss] -= conn_data[di].sh_y; - displ_abs[ifs+aw*iss] = modulus2d( - displ_x[ifs+aw*iss], - displ_y[ifs+aw*iss] - ); - } else { - displ_abs[ifs+aw*iss] = dfv; - } - } - } -} - -int check_and_enforce_cspad_dist(struct detector *det, int enforce) +int check_and_enforce_cspad_dist(struct geoptimiser_params *gparams, + struct detector *det) { int np = 0; int num_errors_found = 0; @@ -2334,7 +2385,7 @@ int check_and_enforce_cspad_dist(struct detector *det, int enforce) struct panel *op = &det->panels[np+1]; dist2 = (( ep->cnx - op->cnx )*( ep->cnx - op->cnx ) + - ( ep->cny - op->cny )*( ep->cny - op->cny )); + ( ep->cny - op->cny )*( ep->cny - op->cny )); if ( dist2 > (dist_to_check+tol)*(dist_to_check+tol) || dist2 < (dist_to_check-tol)*(dist_to_check-tol) ) { @@ -2345,7 +2396,7 @@ int check_and_enforce_cspad_dist(struct detector *det, int enforce) "is outside acceptable margins.\n", ep->name, op->name); - if ( enforce ) { + if ( gparams->enforce_cspad_layout ) { double new_op_cx, new_op_cy; @@ -2368,7 +2419,7 @@ int check_and_enforce_cspad_dist(struct detector *det, int enforce) STATUS("Warning: relative orientation between panels " "%s and %s is incorrect.\n", ep->name, op->name); - if ( enforce ) { + if ( gparams->enforce_cspad_layout ) { STATUS("Enforcing relative orientation....\n"); @@ -2385,67 +2436,313 @@ int check_and_enforce_cspad_dist(struct detector *det, int enforce) } - } + } return num_errors_found; } +static struct connected_data *initialize_conn_data(struct rg_collection *quadrants, + struct rg_collection *connected) +{ + + struct connected_data *conn_data; + + conn_data = malloc(connected->n_rigid_groups* + sizeof(struct connected_data)); + + int di; + + for (di=0; di<connected->n_rigid_groups; di++) { + + conn_data[di].num_quad = find_quad_for_connected( + connected->rigid_groups[di], + quadrants); + conn_data[di].cang = 0.0; + conn_data[di].cstr = 1.0; + conn_data[di].sh_x = -10000.0; + conn_data[di].sh_y = -10000.0; + conn_data[di].num_peaks_per_pixel = 1; + conn_data[di].name = connected->rigid_groups[di]->name; + conn_data[di].n_peaks_in_conn = 0; + } + + return conn_data; +} + + +static struct pixel_displ_list *initialize_pixel_displacement_list( + struct enhanced_det *edet) +{ + + struct pixel_displ_list *pix_displ_list; + int ipx; + + pix_displ_list = malloc(sizeof(struct pixel_displ_list)); + + pix_displ_list->pix_displ_list = calloc(edet->num_pix, + sizeof(struct single_pixel_displ)); + if ( pix_displ_list->pix_displ_list == NULL ) { + ERROR("Error allocating memory for pixel displacement data.\n"); + free(pix_displ_list); + return NULL; + } + pix_displ_list->curr_pix_displ = calloc(edet->num_pix, + sizeof(struct single_pixel_displ*)); + if ( pix_displ_list->curr_pix_displ == NULL ) { + ERROR("Error allocating memory for pixel displacement data.\n"); + free(pix_displ_list->pix_displ_list); + free(pix_displ_list); + return NULL; + } + pix_displ_list->num_pix_displ = calloc(edet->num_pix, sizeof(int)); + if ( pix_displ_list->num_pix_displ == NULL ) { + ERROR("Error allocating memory for pixel displacement data.\n"); + free(pix_displ_list->curr_pix_displ); + free(pix_displ_list->pix_displ_list); + free(pix_displ_list); + return NULL; + } + + for ( ipx=0; ipx<edet->num_pix; ipx++ ) { + pix_displ_list->pix_displ_list[ipx].dfs = -10000.0; + pix_displ_list->pix_displ_list[ipx].dss = -10000.0; + pix_displ_list->pix_displ_list[ipx].ne = NULL; + pix_displ_list->curr_pix_displ[ipx] = &pix_displ_list->pix_displ_list[ipx]; + pix_displ_list->num_pix_displ[ipx] = 0; + } + + return pix_displ_list; +} + + +static void free_pixel_displacement_list( + struct pixel_displ_list *pix_displ_list, + struct enhanced_det *edet) +{ + int i; + struct single_pixel_displ *curr = NULL; + struct single_pixel_displ *next = NULL; + + for ( i=0; i<edet->num_pix; i++ ) { + + curr = &pix_displ_list->pix_displ_list[i]; + + if ( curr->ne != NULL ) { + curr = curr->ne; + while ( curr != NULL ) { + next = curr->ne; + free(curr); + curr = next; + } + } + } + + free(pix_displ_list->curr_pix_displ); + free(pix_displ_list->pix_displ_list); + free(pix_displ_list->num_pix_displ); + free(pix_displ_list); +} + + +static struct avg_displacements *initialize_average_displacement( + struct enhanced_det *edet) + +{ + static struct avg_displacements *avg_displ; + + avg_displ = malloc(sizeof(struct avg_displacements)); + avg_displ->displ_x = calloc(edet->num_pix, sizeof(double)); + if ( avg_displ->displ_x == NULL ) { + ERROR("Error allocating memory for pixel properties.\n"); + return NULL; + } + avg_displ->displ_y = calloc(edet->num_pix, sizeof(double)); + if ( avg_displ->displ_y == NULL ) { + ERROR("Error allocating memory for pixel properties.\n"); + free(avg_displ->displ_x); + free(avg_displ); + return NULL; + } + avg_displ->displ_abs = calloc(edet->num_pix, sizeof(double)); + if ( avg_displ->displ_abs == NULL ) { + ERROR("Error allocating memory for pixel properties.\n"); + free(avg_displ->displ_x); + free(avg_displ->displ_y); + free(avg_displ); + return NULL; + } + + return avg_displ; +} + + +static void free_avg_displacement(struct avg_displacements * avg_displ) +{ + free(avg_displ->displ_x); + free(avg_displ->displ_y); + free(avg_displ->displ_abs); + free(avg_displ); +} + + +static void free_pattern_list(struct pattern_list *pattern_list) +{ + + int pti; + + for ( pti=0; pti<pattern_list->n_patterns; pti++ ) { + int nuc; + + image_feature_list_free(pattern_list->patterns[pti]->im_list); + reflist_free(pattern_list->patterns[pti]->ref_list); + for ( nuc=0; nuc<pattern_list->patterns[pti]->n_unit_cells; + nuc++) { + cell_free(pattern_list->patterns[pti]->unit_cells[nuc]); + } + free(pattern_list->patterns[pti]->filename); + free(pattern_list->patterns[pti]); + } + free(pattern_list); +} + + +static int *extract_num_pix_free_displ_list(struct pixel_displ_list *pix_displ_list, + struct enhanced_det *edet) +{ + int *num_pix; + + int i; + struct single_pixel_displ *curr = NULL; + struct single_pixel_displ *next = NULL; + + for ( i=0; i<edet->num_pix; i++ ) { + + curr = &pix_displ_list->pix_displ_list[i]; + + if ( curr->ne != NULL ) { + curr = curr->ne; + while ( curr != NULL ) { + next = curr->ne; + free(curr); + curr = next; + } + } + } + + num_pix = pix_displ_list->num_pix_displ; + + free(pix_displ_list->curr_pix_displ); + free(pix_displ_list->pix_displ_list); + free(pix_displ_list); + + return num_pix; +} + + +static void recompute_panel_avg_displ(struct rg_collection *connected, + struct connected_data *conn_data, + int *num_pix_displ, int di, int ip, + struct enhanced_det *edet, + struct avg_displacements *avg_displ) +{ + struct panel *p; + int ifs, iss; + + if (conn_data[di].sh_x < -9999.0) return; + + p = connected->rigid_groups[di]->panels[ip]; + + for ( ifs=p->min_fs; ifs<p->max_fs+1; ifs++ ) { + for ( iss=p->min_ss; iss<p->max_ss+1; iss++ ) { + + int pix_index = ifs+edet->width*iss; + + if ( num_pix_displ[pix_index]>= + conn_data[di].num_peaks_per_pixel ) { + avg_displ->displ_x[pix_index] -= conn_data[di].sh_x; + avg_displ->displ_y[pix_index] -= conn_data[di].sh_y; + avg_displ->displ_abs[pix_index] = modulus2d( + avg_displ->displ_x[pix_index], + avg_displ->displ_y[pix_index] + ); + } else { + avg_displ->displ_abs[pix_index] = -10000.0; + } + } + } +} + + +void recompute_avg_displ(struct rg_collection *connected, + struct connected_data *conn_data, + int *num_pix_displ, + struct enhanced_det *edet, + struct avg_displacements *avg_displ) +{ + + int di, ip; + + for ( di=0;di<connected->n_rigid_groups;di++ ) { + for (ip=0; ip<connected->rigid_groups[di]->n_panels; ip++) { + + recompute_panel_avg_displ(connected, conn_data, + num_pix_displ, di, ip, edet, + avg_displ); + + } + } +} + -int optimize_geometry(char *infile, char *outfile, char *geometry_filename, - struct detector *det, struct rg_collection* quadrants, - struct rg_collection* connected, - int min_num_peaks_per_pixel, int min_num_peaks_per_panel, - int only_best_distance, int nostretch, - int individual_coffset, int error_maps, - int enforce_cspad_layout, int no_cspad, - double max_peak_dist, const char *command_line) +int optimize_geometry(struct geoptimiser_params *gparams, + struct detector *det, + struct rg_collection *quadrants, + struct rg_collection *connected) { - int num_pix_in_slab; int max_fs = 0; int max_ss = 0; - int aw = 0; - int pi, di, ip, pti; - int ret1, ret2; + int pi; int ret; int write_ret; int maybe_cspad = 0; - int *num_pix_displ; double res_sum; - double istep; + double avg_res; double clen_to_use; - double man_stretching_coeff = 0.0; - double avc[6] = {0.,0.,0.,0.,0.,0.}; - double dfv = -10000.0; + // for angles and stretch calculation use - // only pixels which are distco*size_panel - // away - double dist_coeff_ang_str = 0.2; - double *displ_x; - double *displ_y; - double *displ_abs; - double totalError; - double min_braggp_dist; + // only pixels which are distco*size_panel + // away + double dist_coeff_for_rot_str = 0.2; + double total_error; - double* slab_to_x; - double* slab_to_y; - double* recomputed_slab_to_x; - double* recomputed_slab_to_y; - double stretch_coeff = 1; + struct pixel_maps *pixel_maps; + struct pixel_maps *recomputed_pixel_maps; + double stretch_coeff = 1.0; - struct single_pix_displ *all_pix_displ; - struct single_pix_displ **curr_pix_displ; struct connected_data *conn_data = NULL; struct pattern_list *pattern_list; + struct cell_params *cell_params; + struct enhanced_det edet; + struct avg_displacements *avg_displ; + struct pixel_displ_list *pix_displ_list; - if ( nostretch ) man_stretching_coeff = 1.0; + STATUS("Maximum distance between peaks: %0.1f pixels.\n", + gparams->max_peak_dist); - if ( det->n_panels == 64 ) { + STATUS("Minimum number of measurements for a pixel to be included in the " + "refinement: %i\n", + gparams->min_num_peaks_per_pix); + STATUS("Minimum number of measurements for connected group for accurate " + "estimation of position/orientation: %i\n", + gparams->min_num_pix_per_conn_group); + + if (det->n_panels == 64 ) { maybe_cspad = 1; } - if ( maybe_cspad && !no_cspad ) { + if ( maybe_cspad && !gparams->no_cspad ) { int num_errors = 0; @@ -2454,14 +2751,13 @@ int optimize_geometry(char *infile, char *outfile, char *geometry_filename, "connected ASICS.\n"); STATUS("If the detector is not a CSPAD, please rerun the " "program with the --no-cspad option.\n"); - if ( enforce_cspad_layout ) { + if ( gparams->enforce_cspad_layout ) { STATUS("Enforcing CSPAD layout...\n"); } - num_errors = check_and_enforce_cspad_dist(det, - enforce_cspad_layout); + num_errors = check_and_enforce_cspad_dist(gparams, det); - if ( enforce_cspad_layout ) { + if ( gparams->enforce_cspad_layout ) { int geom_wr; @@ -2469,9 +2765,10 @@ int optimize_geometry(char *infile, char *outfile, char *geometry_filename, "Please restart geometry optimization using the " "optimized geometry from this run as input geometry " "file.\n"); - geom_wr = write_detector_geometry_2(geometry_filename, - outfile, det, - command_line, 1); + geom_wr = write_detector_geometry_2( + gparams->geometry_filename, + gparams->outfile, det, + gparams->command_line, 1); if ( geom_wr != 0 ) { ERROR("Error in writing output geometry file.\n"); return 1; @@ -2480,9 +2777,9 @@ int optimize_geometry(char *infile, char *outfile, char *geometry_filename, return 0; } - if ( !enforce_cspad_layout && num_errors > 0 ) { + if ( !gparams->enforce_cspad_layout && num_errors > 0 ) { ERROR("Relative distance and orientation of connected " - "panels do not respect the CSPAD layout.\n" + "ASICS do not respect the CSPAD layout.\n" "Geometry optimization cannot continue.\n" "Please rerun the program with the " "--enforce-cspad-layout option.\n"); @@ -2490,13 +2787,17 @@ int optimize_geometry(char *infile, char *outfile, char *geometry_filename, } } - pattern_list = read_patterns_from_steam_file(infile, det); + pattern_list = read_patterns_from_steam_file(gparams->infile, det); if ( pattern_list->n_patterns < 1 ) { ERROR("Error reading stream file\n"); return 1; } - compute_avg_cell_parameters(pattern_list, avc); + cell_params = compute_avg_cell_parameters(pattern_list); + if ( cell_params == NULL ) { + free(pattern_list); + return 1; + } res_sum = 0; for ( pi=0; pi<det->n_panels; pi++ ) { @@ -2509,362 +2810,224 @@ int optimize_geometry(char *infile, char *outfile, char *geometry_filename, } res_sum += det->panels[pi].res; } + avg_res = res_sum/det->n_panels; - istep = res_sum/det->n_panels; - - aw = max_fs+1; + edet.det = det; + edet.width = max_fs+1; + edet.height = max_ss+1; + edet.num_pix = (max_fs+1)*(max_ss+1); - clen_to_use = compute_clen_to_use(pattern_list, istep, avc, - max_peak_dist, - only_best_distance, - &min_braggp_dist); + clen_to_use = pick_clen_to_use(gparams, pattern_list, avg_res, + cell_params); if ( clen_to_use == -1.0 ) return 1; - if ( max_peak_dist == -1.0 ) { - STATUS ("Setting maximum distance for peak search to 0.5*" - "minimum Bragg peak distance from the data\n"); - max_peak_dist = 0.5*min_braggp_dist; - } - STATUS("Maximum distance for peak search: %0.1f pixels.\n", max_peak_dist); - if ( min_braggp_dist<1.2*max_peak_dist ) { - STATUS("WARNING: The maximum distance for peak search " - "is too small compared to minimum Bragg peak " - "distance: %0.1f < 1.2*%0.1f pixels.\n", - min_braggp_dist, - max_peak_dist); - } - - STATUS("Minimum number of measurements for a pixel to be included in the " - "refinement: %i\n", - min_num_peaks_per_pixel); - STATUS("Minimum number of measurements per connected group for accurate " - "estimation of position/orientation: %i\n", - min_num_peaks_per_panel); - - num_pix_in_slab = (max_fs+1)*(max_ss+1); - displ_x = calloc(num_pix_in_slab,sizeof(double)); - if ( displ_x == NULL ) { - ERROR("Error allocating memory for pixel properties.\n"); - return 1; - } - displ_y = calloc(num_pix_in_slab,sizeof(double)); - if ( displ_y == NULL ) { - ERROR("Error allocating memory for pixel properties.\n"); - free(displ_x); - return 1; - } - displ_abs = calloc(num_pix_in_slab,sizeof(double)); - if ( displ_abs == NULL ) { - ERROR("Error allocating memory for pixel properties.\n"); - free(displ_x); - free(displ_y); + avg_displ = initialize_average_displacement(&edet); + if ( avg_displ == NULL ) { + free(cell_params); + free(pattern_list); return 1; } - slab_to_x = malloc(num_pix_in_slab*sizeof(double)); - slab_to_y = malloc(num_pix_in_slab*sizeof(double)); - if ( slab_to_x == NULL ) { + pixel_maps = initialize_pixel_maps(&edet); + if ( pixel_maps == NULL ) { ERROR("Failed to allocate memory for pixel maps.\n"); - free(displ_x); - free(displ_y); - free(displ_abs); - return 1; - } - slab_to_y = malloc(num_pix_in_slab*sizeof(double)); - if ( slab_to_y == NULL ) { - ERROR("Failed to allocate memory for pixel maps.\n"); - free(displ_x); - free(displ_y); - free(displ_abs); - free(slab_to_x); + free_avg_displacement(avg_displ); + free(cell_params); + free(pattern_list); return 1; } - fill_coordinate_matrices(det, aw, slab_to_x, slab_to_y); - - all_pix_displ = calloc(num_pix_in_slab, - sizeof(struct single_pix_displ)); - if ( all_pix_displ == NULL ) { - ERROR("Error allocating memory for connected structure data.\n"); - free(displ_x); - free(displ_y); - free(displ_abs); - free(slab_to_x); - free(slab_to_y); - return 1; - } - curr_pix_displ = calloc(num_pix_in_slab, - sizeof(struct single_pix_displ*)); - if ( curr_pix_displ == NULL ) { + pix_displ_list = initialize_pixel_displacement_list(&edet); + if ( pix_displ_list == NULL ) { ERROR("Error allocating memory for connected structure data.\n"); - free(displ_x); - free(displ_y); - free(displ_abs); - free(slab_to_x); - free(slab_to_y); - free(all_pix_displ); - return 1; - } - num_pix_displ = calloc(num_pix_in_slab, sizeof(int)); - if ( num_pix_displ == NULL ) { - ERROR("Error allocating memory for connected structure data.\n"); - free(displ_x); - free(displ_y); - free(displ_abs); - free(slab_to_x); - free(slab_to_y); - free(all_pix_displ); - free(curr_pix_displ); + free_avg_displacement(avg_displ); + free_pixel_maps(pixel_maps); + free(pattern_list); return 1; } - conn_data = malloc(connected->n_rigid_groups* - sizeof(struct connected_data)); + conn_data = initialize_conn_data(quadrants, connected); if ( conn_data == NULL ) { ERROR("Error allocating memory for connected structure data.\n"); - free(displ_x); - free(displ_y); - free(displ_abs); - free(slab_to_x); - free(slab_to_y); - free(all_pix_displ); - free(curr_pix_displ); - free(num_pix_displ); + free_avg_displacement(avg_displ); + free_pixel_maps(pixel_maps); + free_pixel_displacement_list(pix_displ_list, &edet); + free(pattern_list); return 1; } - STATUS("Computing pixel statistics.\n"); - ret = compute_pixel_statistics(pattern_list, det, connected, quadrants, - num_pix_in_slab, max_peak_dist, - aw, dfv, - min_num_peaks_per_pixel, - min_num_peaks_per_panel, - only_best_distance, - clen_to_use, slab_to_x, - slab_to_y, conn_data, - displ_x, displ_y, displ_abs, - all_pix_displ, - curr_pix_displ, - num_pix_displ); + + ret = compute_pixel_displacements(pattern_list, &edet, connected, + gparams, clen_to_use, conn_data, + avg_displ, pix_displ_list); if ( ret != 0 ) { - free(displ_x); - free(displ_y); - free(displ_abs); - free(slab_to_x); - free(slab_to_y); - free_all_curr_pix_displ(all_pix_displ, curr_pix_displ, - num_pix_in_slab); - free(num_pix_displ); + free_avg_displacement(avg_displ); + free_pixel_maps(pixel_maps); + free_pixel_displacement_list(pix_displ_list, &edet); free(conn_data); + free(pattern_list); return 1; } - free_all_curr_pix_displ(all_pix_displ, curr_pix_displ, num_pix_in_slab); - for ( pti=0; pti<pattern_list->n_patterns; pti++ ) { - int nuc; + free_pattern_list(pattern_list); - image_feature_list_free(pattern_list->patterns[pti]->im_list); - reflist_free(pattern_list->patterns[pti]->ref_list); - for ( nuc=0; nuc<pattern_list->patterns[pti]->n_unit_cells; - nuc++) { - cell_free(pattern_list->patterns[pti]->unit_cells[nuc]); - } - free(pattern_list->patterns[pti]->filename); - free(pattern_list->patterns[pti]); + adjust_min_peaks_per_conn(&edet, connected, gparams, conn_data, + pix_displ_list); + + ret = compute_avg_displacements(&edet, connected, pix_displ_list, + conn_data, avg_displ); + if ( ret != 0 ) { + free_avg_displacement(avg_displ); + free_pixel_maps(pixel_maps); + free_pixel_displacement_list(pix_displ_list, &edet); + free(conn_data); + return 1; } - free(pattern_list); - if ( error_maps ) { - STATUS("Saving pixel position errors before correction.\n"); + num_pix_displ = extract_num_pix_free_displ_list(pix_displ_list, &edet); + + STATUS("Computing error before correction.\n"); + total_error = compute_error(connected, &edet, conn_data, + num_pix_displ, avg_displ->displ_abs); + + STATUS("Detector-wide error before correction <delta^2> = %0.4f pixels.\n", + total_error); + + if ( gparams->error_maps ) { + STATUS("Saving error map before correction.\n"); #ifdef HAVE_SAVE_TO_PNG - ret1 = save_data_to_png("error_map_before.png", det, max_fs, max_ss, - dfv, displ_abs); - if ( ret1!=0 ) { + ret = save_data_to_png("error_map_before.png", &edet, + avg_displ->displ_abs); + if ( ret != 0 ) { ERROR("Error while writing data to file.\n"); + + free_avg_displacement(avg_displ); + free_pixel_maps(pixel_maps); free(conn_data); - free(displ_x); - free(displ_y); - free(displ_abs); free(num_pix_displ); - free(slab_to_x); - free(slab_to_y); return 1; } #else /* HAVE_SAVE_TO_PNG */ - STATUS("ERROR: geoptimiser was compiled without GTK and cairo " + ERROR("WARNING: geoptimiser was compiled without GTK and cairo " "support. Error maps will not be saved.\n"); #endif /* HAVE_SAVE_TO_PNG */ } - STATUS("Computing initial error.\n"); - totalError = compute_error(connected, aw, conn_data, - num_pix_displ, displ_abs); - - STATUS("The total initial error <delta^2> = %0.4f pixels.\n", - totalError); - STATUS("Now calculating corrections.\n"); - - for ( di=0;di<connected->n_rigid_groups;di++ ) { - - conn_data[di].n_peaks_in_conn = 0; - - for (ip=0; ip<connected->rigid_groups[di]->n_panels; ip++) { - - calculate_panel_correction(di, ip, aw, num_pix_displ, - connected, conn_data); - } - } - - STATUS("Calculating angles and elongations.\n"); - - ret = compute_angles_and_stretch(connected, conn_data, - num_pix_displ, - slab_to_x, slab_to_y, - displ_x, displ_y, - aw, - min_num_peaks_per_panel, - dist_coeff_ang_str, - min_num_peaks_per_pixel, - man_stretching_coeff, &stretch_coeff); - - if ( ret != 0 ) { + stretch_coeff = compute_rotation_and_stretch(connected, conn_data, + &edet, num_pix_displ, + pixel_maps, avg_displ, + dist_coeff_for_rot_str, + gparams); + if ( stretch_coeff < 0.0 ) { + free_avg_displacement(avg_displ); + free_pixel_maps(pixel_maps); free(conn_data); - free(displ_x); - free(displ_y); - free(displ_abs); free(num_pix_displ); - free(slab_to_x); - free(slab_to_y); return 1; } - ret = correct_empty_panels(quadrants, connected, min_num_peaks_per_panel, - conn_data); + ret = compute_rot_stretch_for_empty_panels(quadrants, connected, + gparams, conn_data); if ( ret != 0 ) { + free_avg_displacement(avg_displ); + free_pixel_maps(pixel_maps); free(conn_data); - free(displ_x); - free(displ_y); - free(displ_abs); free(num_pix_displ); - free(slab_to_x); - free(slab_to_y); return 1; } - correct_angle_and_stretch(connected, det, conn_data, clen_to_use, - stretch_coeff, individual_coffset); - shift_panels(connected, conn_data); + correct_rotation_and_stretch(connected, edet.det, conn_data, + clen_to_use, stretch_coeff, + gparams); - recomputed_slab_to_x = malloc(num_pix_in_slab*sizeof(double)); - if ( recomputed_slab_to_x == NULL ) { - ERROR("Failed to allocate memory for pixel maps.\n"); - free(displ_x); - free(displ_y); - free(displ_abs); - free(slab_to_x); - free(slab_to_y); - free(num_pix_displ); + recomputed_pixel_maps = initialize_pixel_maps(&edet); + if ( recomputed_pixel_maps == NULL ) { + free_avg_displacement(avg_displ); + free_pixel_maps(pixel_maps); free(conn_data); - return 1; - } - recomputed_slab_to_y = malloc(num_pix_in_slab*sizeof(double)); - if ( recomputed_slab_to_y == NULL ) { - ERROR("Failed to allocate memory for pixel maps.\n"); - free(displ_x); - free(displ_y); - free(displ_abs); - free(slab_to_x); - free(slab_to_y); free(num_pix_displ); - free(conn_data); - free(recomputed_slab_to_x); return 1; } - fill_coordinate_matrices(det, aw, recomputed_slab_to_x, - recomputed_slab_to_y); + adjust_displ_for_stretch(connected, pixel_maps, + recomputed_pixel_maps, + conn_data, + stretch_coeff, &edet, avg_displ, + num_pix_displ); - recompute_differences(connected, slab_to_x, slab_to_y, - recomputed_slab_to_x, - recomputed_slab_to_y, conn_data, - stretch_coeff, aw, displ_x, displ_y, - num_pix_displ); - - ret = compute_shifts(connected, conn_data, num_pix_displ, aw, - min_num_peaks_per_panel, dfv, - max_peak_dist, displ_x, displ_y ); - - if ( ret != 0 ) return 1; - - compute_shifts_for_empty_panels(quadrants, connected, conn_data, - min_num_peaks_per_panel); - - for ( di=0;di<connected->n_rigid_groups;di++ ) { - for (ip=0; ip<connected->rigid_groups[di]->n_panels; ip++) { - - compute_abs_displ(connected, conn_data, - num_pix_displ, dfv, di, ip, aw, - displ_x, displ_y, displ_abs); - - } + ret = compute_shift(connected, conn_data, num_pix_displ, &edet, + gparams, avg_displ); + if ( ret != 0 ) { + free_avg_displacement(avg_displ); + free_pixel_maps(pixel_maps); + free(conn_data); + free(num_pix_displ); + free_pixel_maps(recomputed_pixel_maps); + return 1; } - correct_shifts(connected, conn_data, dfv, clen_to_use); + compute_shift_for_empty_panels(quadrants, connected, conn_data, + gparams); + + correct_shift(connected, conn_data, clen_to_use); - if ( error_maps ) { + recompute_avg_displ(connected, conn_data, + num_pix_displ, &edet, + avg_displ); + if ( gparams->error_maps ) { #ifdef HAVE_SAVE_TO_PNG - STATUS("Saving pixel position errors after correction.\n"); - ret2 = save_data_to_png("error_map_after.png", det, max_fs, max_ss, - dfv, displ_abs); - if ( ret2 !=0 ) { + STATUS("Saving error map after correction.\n"); + + ret = save_data_to_png("error_map_after.png", &edet, + avg_displ->displ_abs); + if ( ret !=0 ) { ERROR("Error while writing data to file.\n"); + + free_avg_displacement(avg_displ); + free_pixel_maps(pixel_maps); free(conn_data); - free(displ_x); - free(displ_y); - free(displ_abs); free(num_pix_displ); - free(slab_to_x); - free(slab_to_y); - free(recomputed_slab_to_x); - free(recomputed_slab_to_y); + free_pixel_maps(recomputed_pixel_maps); return 1; } #else /* HAVE_SAVE_TO_PNG */ STATUS("ERROR: geoptimiser was compiled without GTK and cairo " - "support. Error maps will not be saved.\n"); + "support.\n Error maps will not be saved.\n"); #endif /* HAVE_SAVE_TO_PNG */ } - STATUS("Computing final error.\n"); - totalError = compute_error(connected, aw, conn_data, num_pix_displ, - displ_abs); + STATUS("Computing errors after correction.\n"); + total_error = compute_error(connected, &edet, conn_data, + num_pix_displ, avg_displ->displ_abs); - STATUS("The total final error <delta^2> = %0.4f pixels.\n",totalError); + STATUS("Detector-wide error after correction <delta^2> = %0.4f pixels.\n", + total_error); - write_ret = write_detector_geometry_2(geometry_filename, outfile, det, - command_line, 1); + write_ret = write_detector_geometry_2(gparams->geometry_filename, + gparams->outfile, edet.det, + gparams->command_line, 1); if ( write_ret != 0 ) { ERROR("Error in writing output geometry file.\n"); return 1; } STATUS("All done!\n"); - if ( error_maps ) { + if ( gparams->error_maps ) { #ifdef HAVE_SAVE_TO_PNG @@ -2874,65 +3037,71 @@ int optimize_geometry(char *infile, char *outfile, char *geometry_filename, #endif /* HAVE_SAVE_TO_PNG */ } + free_avg_displacement(avg_displ); + free_pixel_maps(pixel_maps); free(conn_data); - free(displ_x); - free(displ_y); - free(displ_abs); free(num_pix_displ); - free(slab_to_x); - free(slab_to_y); - free(recomputed_slab_to_x); - free(recomputed_slab_to_y); + free_pixel_maps(recomputed_pixel_maps); return 0; } + int main(int argc, char *argv[]) { int c, i; int ret_val; char buffer[256]; char command_line[1024]; - char *outfile = NULL; - char *infile = NULL; - char *geometry_filename = NULL; + char *quadrant_coll_name = NULL; char *connected_coll_name = NULL; - int min_num_peaks_per_pixel = 3; - int min_num_peaks_per_panel = 100; - int only_best_distance = 0; - int enforce_cspad_layout = 0; - int nostretch = 0; - int individual_coffset = 0; - int no_cspad = 0; - int error_maps = 1; - double max_peak_dist = -1.0; + struct geoptimiser_params *gparams; struct detector *det = NULL; struct rg_collection *quadrants; struct rg_collection *connected; struct beam_params beam; + gparams = malloc(sizeof(struct geoptimiser_params)); + + gparams->outfile = NULL; + gparams->infile = NULL; + gparams->geometry_filename = NULL; + gparams->min_num_peaks_per_pix = 3; + gparams->min_num_pix_per_conn_group = 100; + gparams->only_best_distance = 0; + gparams->enforce_cspad_layout = 0; + gparams->nostretch = 0; + gparams->individual_coffset = 0; + gparams->no_cspad = 0; + gparams->error_maps = 1; + gparams->max_peak_dist = 4.0; + const struct option longopts[] = { - /* Options with long and short versions */ - {"help", 0, NULL, 'h'}, - {"version", 0, NULL, 10 }, - {"input", 1, NULL, 'i'}, - {"output", 1, NULL, 'o'}, - {"geometry", 1, NULL, 'g'}, - {"quadrants", 1, NULL, 'q'}, - {"connected", 1, NULL, 'c'}, - {"min-num-peaks-per-pixel", 1, NULL, 'x'}, - {"min-num-peaks-per-panel", 1, NULL, 'p'}, - {"most-few-clen", 0, NULL, 'l'}, - {"max-peak-dist", 1, NULL, 'm'}, - {"individual-dist-offset", 0, NULL, 's'}, - - /* Long-only options with no arguments */ - {"no-stretch", 0, &nostretch, 1}, - {"no-error-maps", 0, &error_maps, 0}, - {"enforce-cspad-layout", 0, &enforce_cspad_layout, 1}, - {"no-cspad", 0, &no_cspad, 1}, + /* Options with long and short versions */ + {"help", 0, NULL, 'h'}, + {"version", 0, NULL, 10 }, + {"input", 1, NULL, 'i'}, + {"output", 1, NULL, 'o'}, + {"geometry", 1, NULL, 'g'}, + {"quadrants", 1, NULL, 'q'}, + {"connected", 1, NULL, 'c'}, + {"min-num-peaks-per-pixel", 1, NULL, 'x'}, + {"min-num-pixels-per-conn-group", 1, NULL, 'p'}, + {"most-few-clen", 0, NULL, 'l'}, + {"max-peak-dist", 1, NULL, 'm'}, + {"individual-dist-offset", 0, NULL, 's'}, + + /* Long-only options with no arguments */ + {"no-stretch", 0, &gparams->nostretch, 1}, + {"no-error-maps", 0, &gparams->error_maps, 0}, + {"enforce-cspad-layout", 0, &gparams->enforce_cspad_layout, 1}, + {"no-cspad", 0, &gparams->no_cspad, 1}, + + /* Long-only options with arguments */ + {"min-num-peaks-per-panel", 1, NULL, 11}, + {0, 0, NULL, 0} }; @@ -2953,16 +3122,17 @@ int main(int argc, char *argv[]) return 0; case 'o' : - outfile = strdup(optarg); + gparams->outfile = strdup(optarg); break; case 'i' : - infile = strdup(optarg); + gparams->infile = strdup(optarg); break; case 'g' : - geometry_filename = strdup(optarg); - det = get_detector_geometry(geometry_filename, &beam); + gparams->geometry_filename = strdup(optarg); + det = get_detector_geometry(gparams->geometry_filename, + &beam); if ( det == NULL ) { ERROR("Failed to read detector geometry from " "'%s'\n", optarg); @@ -2979,39 +3149,48 @@ int main(int argc, char *argv[]) break; case 'x' : - min_num_peaks_per_pixel = atoi(optarg); + gparams->min_num_peaks_per_pix = atoi(optarg); break; case 'p' : - min_num_peaks_per_panel = atoi(optarg); + gparams->min_num_pix_per_conn_group = atoi(optarg); break; case 'l' : - only_best_distance = 1; + gparams->only_best_distance = 1; break; case 'm' : - max_peak_dist = strtof(optarg, NULL); + gparams->max_peak_dist = strtof(optarg, NULL); break; case 's' : - individual_coffset = 1; + gparams->individual_coffset = 1; + break; + + case 11: + ERROR("WARNING: The --min-num-peaks-per-panel option has been " + "renamed to --min-num-pixels-per-conn-group. The " + "old option has been deprecated and will " + "soon be removed. It is currently remapped to " + "--min-num-pixels-per-conn-group\n"); + gparams->min_num_pix_per_conn_group = atoi(optarg); break; } } - if ( geometry_filename == NULL ) { + if ( gparams->geometry_filename == NULL ) { ERROR("You must provide a geometry to optimize.\n"); return 1; } - if ( infile == NULL ) { + if ( gparams->infile == NULL ) { ERROR("You must provide an input stream file.\n"); return 1; } - if ( outfile == NULL ) { + if ( gparams->outfile == NULL ) { ERROR("You must provide an output filename.\n"); return 1; } @@ -3052,12 +3231,7 @@ int main(int argc, char *argv[]) } g_type_init(); - ret_val = optimize_geometry(infile, outfile, geometry_filename, det, - quadrants, connected, min_num_peaks_per_pixel, - min_num_peaks_per_panel, only_best_distance, - nostretch, individual_coffset, error_maps, - enforce_cspad_layout, no_cspad, - max_peak_dist, command_line); + ret_val = optimize_geometry(gparams, det, quadrants, connected); return ret_val; } |