35#include "moo_params.h"
36#include "moo_badpix.h"
37#include "moo_single.h"
39#include "moo_localise.h"
40#include "moo_loc_single.h"
41#include "moo_detector.h"
42#include "moo_fibres_table.h"
43#include "moo_line_table.h"
83_moo_get_flux(cpl_vector *fluxes,
double posy)
87 int nx = cpl_vector_get_size(fluxes);
88 int pos1 = (int)floor(posy);
91 double flux1 = cpl_vector_get(fluxes, pos1 - 1);
92 while (isnan(flux1)) {
94 flux1 = cpl_vector_get(fluxes, pos1 - 1);
101 while (isnan(flux2)) {
103 flux2 = cpl_vector_get(fluxes, pos2 - 1);
105 flux = flux1 + (posy - pos1) * (flux2 - flux1);
121_moo_get_image_flux(
const cpl_image *fluxes,
int x,
double posy)
125 int ny = cpl_image_get_size_y(fluxes);
126 int pos1 = (int)floor(posy);
129 double flux1 = cpl_image_get(fluxes, x, pos1, &rej);
132 flux1 = cpl_image_get(fluxes, x, pos1, &rej);
142 flux2 = cpl_image_get(fluxes, x, pos2, &rej);
144 double diff = pos2 - pos1;
145 flux = (pos2 - posy) / diff * flux1 + (posy - pos1) / diff * flux2;
160_moo_get_flux_integrate_low(cpl_vector *fluxes,
double posy,
double *cbin)
164 int ipos = (int)round(posy);
166 flux = cpl_vector_get(fluxes, ipos - 1);
167 double frac = ipos + 0.5 - posy;
169 *cbin = posy + frac / 2.;
184_moo_get_flux_integrate_up(cpl_vector *fluxes,
double posy,
double *cbin)
188 int ipos = (int)round(posy);
190 flux = cpl_vector_get(fluxes, ipos - 1);
191 double frac = posy - (ipos - 0.5);
193 *cbin = posy - frac / 2.;
211_moo_extract_profile(cpl_vector *fluxes,
double ymin,
double ymax)
213 cpl_ensure(fluxes, CPL_ERROR_NULL_INPUT, NULL);
214 cpl_ensure((ymax - ymin) > 0, CPL_ERROR_ILLEGAL_INPUT, NULL);
217 int y2 = floor(ymax);
218 int size = y2 - y1 + 3;
220 cpl_bivector *points = cpl_bivector_new(size);
221 cpl_vector *y = cpl_bivector_get_x(points);
222 cpl_vector *f = cpl_bivector_get_y(points);
224 double fmin = _moo_get_flux(fluxes, ymin);
225 double fmax = _moo_get_flux(fluxes, ymax);
227 cpl_vector_set(y, 0, ymin);
228 cpl_vector_set(f, 0, fmin);
229 cpl_vector_set(y, size - 1, ymax);
230 cpl_vector_set(f, size - 1, fmax);
233 for (i = y1; i <= y2; i++) {
234 double flux = cpl_vector_get(fluxes, i - 1);
235 cpl_vector_set(y, i - y1 + 1, i);
236 cpl_vector_set(f, i - y1 + 1, flux);
243_moo_extract_profile_integrate(cpl_vector *fluxes,
double ymin,
double ymax)
245 cpl_ensure(fluxes, CPL_ERROR_NULL_INPUT, NULL);
246 cpl_ensure((ymax - ymin) > 0, CPL_ERROR_ILLEGAL_INPUT, NULL);
250 double fmin = _moo_get_flux_integrate_low(fluxes, ymin, &ycmin);
251 double fmax = _moo_get_flux_integrate_up(fluxes, ymax, &ycmax);
252 int y1 = ceil(ycmin);
253 int y2 = floor(ycmax);
255 int size = y2 - y1 + 3;
257 cpl_bivector *points = cpl_bivector_new(size);
258 cpl_vector *y = cpl_bivector_get_x(points);
259 cpl_vector *f = cpl_bivector_get_y(points);
261 cpl_vector_set(y, 0, ycmin);
262 cpl_vector_set(f, 0, fmin);
263 cpl_vector_set(y, size - 1, ycmax);
264 cpl_vector_set(f, size - 1, fmax);
268 for (i = y1; i <= y2; i++) {
269 double flux = cpl_vector_get(fluxes, i - 1);
270 cpl_vector_set(y, i - y1 + 1, i);
271 cpl_vector_set(f, i - y1 + 1, flux);
290_moo_profile_find_thresh_positions(cpl_vector *fluxes,
297 int size = cpl_vector_get_size(fluxes);
299 int centroid_ylow = (int)floor(centroid_y);
300 int centroid_yup = centroid_ylow + 1;
302 double centroid_f = _moo_get_flux(fluxes, centroid_y);
305 double f1 = centroid_f;
306 double y1 = centroid_y;
333 for (i = centroid_yup; i > 0; i--) {
334 double f2 = cpl_vector_get(fluxes, i - 1);
336 if (f2 <= thresh_low) {
337 *y_low = i + (thresh_low - f2) / (f1 - f2) * (y1 - i);
338 if ((isnan(*y_low))) {
339 *y_low = (y1 + i) / 2.0;
350 for (i = centroid_ylow; i < size - 1; i++) {
351 double f2 = cpl_vector_get(fluxes, i - 1);
353 if (f2 <= thresh_up) {
354 *y_up = i + (thresh_up - f2) / (f1 - f2) * (y1 - i);
355 if ((isnan(*y_up))) {
356 *y_up = (y1 + i) / 2.0;
382_moo_profile_find_image_thresh_positions(
const cpl_image *fluxes,
392 int ny = cpl_image_get_size_y(fluxes);
393 int centroid_ylow = (int)floor(centroid_y);
394 int centroid_yup = centroid_ylow + 1;
396 double centroid_f = _moo_get_image_flux(fluxes, x, centroid_y);
398 double f1 = centroid_f;
399 double y1 = centroid_y;
401 for (i = centroid_yup; i > 0; i--) {
403 f2 = cpl_image_get(fluxes, x, i, &rej);
405 if (f2 <= thresh_low) {
406 *y_low = i + (thresh_low - f2) / (f1 - f2) * (y1 - i);
407 if ((isnan(*y_low))) {
408 *y_low = (y1 + i) / 2.0;
419 for (i = centroid_ylow; i < ny; i++) {
421 f2 = cpl_image_get(fluxes, x, i, &rej);
423 if (f2 <= thresh_up) {
424 *y_up = i + (thresh_up - f2) / (f1 - f2) * (y1 - i);
425 if ((isnan(*y_up))) {
426 *y_up = (y1 + i) / 2.0;
446_check_trace_guess(
double center,
double width)
448 int flag = MOONS_FLAG_GOOD;
450 if (isnan(center) || isnan(width)) {
451 flag = MOONS_FLAG_NAN_IN_TRACE_GUESS;
468_check_bpm(hdrl_image *himg,
int x,
double center,
double width)
470 int flag = MOONS_FLAG_GOOD;
471 const cpl_mask *bpm = hdrl_image_get_mask_const(himg);
473 int lly = (int)(center - width / 2);
474 int ury = (int)(center + width / 2);
476 cpl_mask *extractm = cpl_mask_extract(bpm, x, lly, x, ury);
478 int nbrej = cpl_mask_count(extractm);
480 cpl_mask_delete(extractm);
483 flag = MOONS_FLAG_BADPIX;
501_check_snr(cpl_vector *fluxes,
509 int flag = MOONS_FLAG_GOOD;
511 double centroid_flux = _moo_get_flux(fluxes, centroid_y);
512 double centroid_err = _moo_get_flux(errs, centroid_y);
514 double b1_flux = _moo_get_flux(fluxes, b1_y);
515 double b1_err = _moo_get_flux(errs, b1_y);
517 double b2_flux = _moo_get_flux(fluxes, b2_y);
518 double b2_err = _moo_get_flux(errs, b2_y);
520 double b_flux = (b1_flux + b2_flux) / 2.0;
525 double A = centroid_flux - b_flux;
526 double eA = sqrt(centroid_err * centroid_err +
527 (b1_err * b1_err + b2_err * b2_err) / 4);
528 double snrA = A / eA;
530 if (snrA <= ref_snr) {
531 flag = MOONS_FLAG_NON_SIGNIFICANT_FLUX;
553_moo_profile_find_background_flux(cpl_vector *fluxes,
563 int size = cpl_vector_get_size(fluxes);
565 int centroid_y1 = (int)floor(centroid);
566 int centroid_y2 = centroid_y1 + 1;
567 double centroid_f = _moo_get_flux(fluxes, centroid);
569 double b1 = centroid_f;
571 int end = centroid_y1 - width;
577 for (i = centroid_y1; i > end; i--) {
578 double v1 = cpl_vector_get(fluxes, i - 1);
586 double b2 = centroid_f;
589 end = centroid_y2 + width;
594 for (i = centroid_y2; i <= end; i++) {
595 double v1 = cpl_vector_get(fluxes, i - 1);
602 *thresh_low = b1 + (centroid_f - b1) * frac;
603 *thresh_up = b2 + (centroid_f - b2) * frac;
621_moo_profile_find_image_background_flux(
const cpl_image *fluxes,
632 int ny = cpl_image_get_size_y(fluxes);
634 int centroid_y1 = (int)floor(centroid);
635 int centroid_y2 = centroid_y1 + 1;
636 double centroid_f = _moo_get_image_flux(fluxes, x, centroid);
639 double b1 = centroid_f;
641 int end = centroid_y1 - width;
647 for (i = centroid_y1; i > end; i--) {
649 double v1 = cpl_image_get(fluxes, x, i, &rej);
650 if (v1 < b1 && rej == 0) {
656 double b2 = centroid_f;
659 end = centroid_y2 + width;
664 for (i = centroid_y2; i <= end; i++) {
666 double v1 = cpl_image_get(fluxes, x, i, &rej);
668 if (v1 < b2 && rej == 0) {
673 *thresh_low = b1 + (centroid_f - b1) * frac;
674 *thresh_up = b2 + (centroid_f - b2) * frac;
690_moo_detect_x_edges(cpl_table *tracking_table,
700 int size = cpl_table_get_nrow(tracking_table);
702 for (
int x = 0; x < hwidth; x++) {
703 int flag = cpl_table_get_int(tracking_table,
704 MOO_TRACKING_LOC_TABLE_FLAG, x, NULL);
709 double ratio = (double)nbgood / (
double)hwidth;
710 for (
int x = 0; x < hwidth; x++) {
711 cpl_table_set_double(tracking_table, MOO_TRACKING_LOC_TABLE_XGOOD_RATIO,
714 if (ratio >= min_frac) {
719 for (
int x = hwidth; x < size - hwidth; x++) {
720 int total = 2 * hwidth + 1;
722 for (
int j = x - hwidth; j <= x + hwidth; j++) {
724 cpl_table_get_int(tracking_table,
725 MOO_TRACKING_LOC_TABLE_FLAG, j, NULL);
730 ratio = (double)nbgood / (
double)total;
731 cpl_table_set_double(tracking_table,
732 MOO_TRACKING_LOC_TABLE_XGOOD_RATIO, x, ratio);
733 if (ratio >= min_frac) {
742 for (
int x = size - hwidth; x < size; x++) {
743 int flag = cpl_table_get_int(tracking_table,
744 MOO_TRACKING_LOC_TABLE_FLAG, x, NULL);
749 ratio = (double)nbgood / (
double)hwidth;
750 for (
int x = size - hwidth; x < size; x++) {
751 cpl_table_set_double(tracking_table,
752 MOO_TRACKING_LOC_TABLE_XGOOD_RATIO, x, ratio);
755 if (ratio >= min_frac) {
760 for (
int x = size - hwidth - 1; x >= hwidth; x--) {
761 int total = 2 * hwidth + 1;
764 for (
int j = x - hwidth; j <= x + hwidth; j++) {
766 cpl_table_get_int(tracking_table,
767 MOO_TRACKING_LOC_TABLE_FLAG, j, NULL);
773 ratio = (double)nbgood / (
double)total;
774 cpl_table_set_double(tracking_table,
775 MOO_TRACKING_LOC_TABLE_XGOOD_RATIO, x,
777 if (ratio >= min_frac) {
787_moo_localise_row(hdrl_image *himg,
795 cpl_table *tracking_loc_table,
797 cpl_vector *last_width_vect,
802 double y1, y2, center = NAN, width = NAN;
805 cpl_table_set_int(tracking_loc_table, MOO_TRACKING_LOC_TABLE_X, idx, x);
806 double last_width = cpl_vector_get_median_const(last_width_vect);
807 const cpl_image *img = hdrl_image_get_image_const(himg);
808 const cpl_image *error = hdrl_image_get_error_const(himg);
809 const cpl_mask *mask = cpl_image_get_bpm_const(img);
810 cpl_vector *fluxes = cpl_vector_new_from_image_column(img, x);
811 cpl_vector *errs = cpl_vector_new_from_image_column(error, x);
813 int size = cpl_vector_get_size(fluxes);
814 for (
int i = 1; i < size; i++) {
815 int rej = cpl_mask_get(mask, x, i);
817 cpl_vector_set(fluxes, i - 1, NAN);
820 int flag = _check_bpm(himg, x, *last_center, last_width);
822 if (flag == MOONS_FLAG_GOOD) {
823 double thresh_low, thresh_up, b1_y, b2_y, snr;
824 _moo_profile_find_background_flux(fluxes, *last_center, last_width,
825 frac, &b1_y, &b2_y, &thresh_low,
829 _check_snr(fluxes, errs, *last_center, b1_y, b2_y, ref_snr, &snr);
830 cpl_table_set_double(tracking_loc_table, MOO_TRACKING_LOC_TABLE_SNR,
833 if (flag == MOONS_FLAG_GOOD) {
834 _moo_profile_find_thresh_positions(fluxes, *last_center, thresh_low,
835 thresh_up, &y1, &y2);
836 cpl_errorstate prev_state = cpl_errorstate_get();
837 cpl_bivector *points = _moo_extract_profile(fluxes, y1, y2);
838 if (points != NULL) {
840 cpl_bivector_delete(points);
842 double wdiff = width - last_width;
844 (center - *last_center) / sqrt(fabs(x - *last_x));
845 cpl_table_set_double(tracking_loc_table,
846 MOO_TRACKING_LOC_TABLE_WDIFF, idx, wdiff);
847 cpl_table_set_double(tracking_loc_table,
848 MOO_TRACKING_LOC_TABLE_YDIFF, idx, ydiff);
849 if (fabs(wdiff) < wdiff_lim) {
850 if (fabs(ydiff) < ydiff_lim) {
857 cpl_table_set_double(tracking_loc_table,
858 MOO_TRACKING_LOC_TABLE_YCENTROID,
860 cpl_table_set_double(tracking_loc_table,
861 MOO_TRACKING_LOC_TABLE_YMIN, idx,
863 cpl_table_set_double(tracking_loc_table,
864 MOO_TRACKING_LOC_TABLE_YMAX, idx,
866 cpl_table_set_int(tracking_loc_table,
867 MOO_TRACKING_LOC_TABLE_FLAG, idx,
869 *last_center = center;
871 int vsize = cpl_vector_get_size(last_width_vect);
872 for (
int iv = 0; iv < vsize - 1; iv++) {
873 double lv = cpl_vector_get(last_width_vect, iv + 1);
874 cpl_vector_set(last_width_vect, iv, lv);
876 cpl_vector_set(last_width_vect, vsize - 1, width);
880 cpl_table_set_int(tracking_loc_table,
881 MOO_TRACKING_LOC_TABLE_FLAG, idx,
882 MOONS_FLAG_YDIFF_OUTLIERS);
888 cpl_table_set_int(tracking_loc_table,
889 MOO_TRACKING_LOC_TABLE_FLAG, idx,
890 MOONS_FLAG_WDIFF_OUTLIERS);
896 cpl_errorstate_set(prev_state);
897 cpl_table_set_int(tracking_loc_table,
898 MOO_TRACKING_LOC_TABLE_FLAG, idx,
899 MOONS_FLAG_NOPROFILE);
904 cpl_table_set_int(tracking_loc_table, MOO_TRACKING_LOC_TABLE_FLAG,
905 idx, MOONS_FLAG_NON_SIGNIFICANT_FLUX);
910 cpl_table_set_int(tracking_loc_table, MOO_TRACKING_LOC_TABLE_FLAG, idx,
915 cpl_vector_delete(fluxes);
916 cpl_vector_delete(errs);
921_moo_localise_tchebychev_fit(moo_loc_single *res,
924 cpl_table *tracking_table,
928 cpl_error_code status = CPL_ERROR_NONE;
932 cpl_image *measured_centroids = res->m_centroids;
933 cpl_image *fit_centroids = res->f_centroids;
934 cpl_image *wlow = res->f_wlow;
935 cpl_image *wup = res->f_wup;
936 cpl_image *mlow = res->m_wlow;
937 cpl_image *mup = res->m_wup;
938 cpl_image *flags = res->flags;
940 int nx = cpl_image_get_size_x(measured_centroids);
942 for (
int i = 1; i <= nx; i++) {
944 cpl_table_get_double(tracking_table,
945 MOO_TRACKING_LOC_TABLE_YCENTROID, i - 1, NULL);
947 cpl_table_get_double(tracking_table, MOO_TRACKING_LOC_TABLE_YMIN,
950 cpl_table_get_double(tracking_table, MOO_TRACKING_LOC_TABLE_YMAX,
952 int flag = cpl_table_get_int(tracking_table,
953 MOO_TRACKING_LOC_TABLE_FLAG, i - 1, NULL);
954 cpl_image_set(measured_centroids, i, fibnum, yc);
955 cpl_image_set(mlow, i, fibnum, yl);
956 cpl_image_set(mup, i, fibnum, yu);
957 cpl_image_set(flags, i, fibnum, flag);
958 cpl_image_set(fit_centroids, i, fibnum, NAN);
959 cpl_image_set(wlow, i, fibnum, NAN);
960 cpl_image_set(wup, i, fibnum, NAN);
965 _moo_detect_x_edges(tracking_table, xlim_hwin, xlim_fracmin, &xmin, &xmax);
968 cpl_msg_debug(
"moo_localise",
969 "Fibre #%d detected on pixel range %d - %d", fibnum, xmin,
973 cpl_table_get_data_int(tracking_table, MOO_TRACKING_LOC_TABLE_FLAG);
975 cpl_table_get_data_int(tracking_table, MOO_TRACKING_LOC_TABLE_X);
977 cpl_table_get_data_double(tracking_table,
978 MOO_TRACKING_LOC_TABLE_YCENTROID);
980 cpl_bivector *cpos = cpl_bivector_new(nx);
981 cpl_vector *vx = cpl_bivector_get_x(cpos);
982 cpl_vector *vy = cpl_bivector_get_y(cpos);
984 for (
int i = 0; i < nx; i++) {
985 cpl_vector_set(vx, i, (
double)cposx[i]);
986 cpl_vector_set(vy, i, cposy[i]);
994 for (
int i = xmin; i <= xmax; i++) {
995 double fyc = cpl_vector_get(vy, i - 1);
996 cpl_table_set(tracking_table, MOO_TRACKING_LOC_TABLE_FITYCENTROID,
998 cpl_image_set(fit_centroids, i, fibnum, fyc);
1002 cpl_table_get_data_double(tracking_table,
1003 MOO_TRACKING_LOC_TABLE_YMIN);
1005 for (
int i = 0; i < nx; i++) {
1006 cpl_vector_set(vy, i, cposylow[i]);
1013 for (
int i = xmin; i <= xmax; i++) {
1014 double yl = cpl_vector_get(vy, i - 1);
1016 cpl_table_get(tracking_table,
1017 MOO_TRACKING_LOC_TABLE_FITYCENTROID, i - 1, NULL);
1018 double val = yc - yl;
1022 cpl_table_set(tracking_table, MOO_TRACKING_LOC_TABLE_FITYMIN, i - 1,
1024 cpl_image_set(wlow, i, fibnum, val);
1028 cpl_table_get_data_double(tracking_table,
1029 MOO_TRACKING_LOC_TABLE_YMAX);
1031 for (
int i = 0; i < nx; i++) {
1032 cpl_vector_set(vy, i, cposyup[i]);
1039 for (
int i = xmin; i <= xmax; i++) {
1040 double yu = cpl_vector_get(vy, i - 1);
1042 cpl_table_get(tracking_table,
1043 MOO_TRACKING_LOC_TABLE_FITYCENTROID, i - 1, NULL);
1044 double val = yu - yc;
1048 cpl_table_set(tracking_table, MOO_TRACKING_LOC_TABLE_FITYMAX, i - 1,
1050 cpl_image_set(wup, i, fibnum, val);
1052 cpl_bivector_delete(cpos);
1054 cpl_msg_error(
"moo_localise",
1055 "Fibre #%d : localisation fitting (polynomial degree "
1056 "%d) failed : negative lower width",
1058 status = CPL_ERROR_ILLEGAL_OUTPUT;
1061 cpl_msg_error(
"moo_localise",
1062 "Fibre #%d : localisation fitting (polynomial degree "
1063 "%d) failed : negative upper width",
1065 status = CPL_ERROR_ILLEGAL_OUTPUT;
1069 cpl_msg_error(
"moo_localise",
1070 "Fibre #%d : localisation tracking failed", fibnum);
1071 status = CPL_ERROR_ILLEGAL_OUTPUT;
1076static cpl_error_code
1077_moo_localise_fibre(fibre *f,
1086 double goodptsfrac_min,
1088 double xlim_fracmin,
1089 moo_loc_single *res,
1090 cpl_table **all_tracked)
1092 cpl_table *tracking_loc_table = NULL;
1093 cpl_error_code status = CPL_ERROR_NONE;
1096 cpl_msg_indent_more();
1098 int nx = hdrl_image_get_size_x(himg);
1099 int ny = hdrl_image_get_size_y(himg);
1101 double min = (double)ny;
1103 tracking_loc_table = cpl_table_new(nx);
1104 cpl_table_new_column(tracking_loc_table, MOO_TRACKING_LOC_TABLE_FIBNUM,
1106 cpl_table_new_column(tracking_loc_table, MOO_TRACKING_LOC_TABLE_X,
1108 cpl_table_new_column(tracking_loc_table, MOO_TRACKING_LOC_TABLE_YCENTROID,
1110 cpl_table_new_column(tracking_loc_table, MOO_TRACKING_LOC_TABLE_YMIN,
1112 cpl_table_new_column(tracking_loc_table, MOO_TRACKING_LOC_TABLE_YMAX,
1114 cpl_table_new_column(tracking_loc_table, MOO_TRACKING_LOC_TABLE_WDIFF,
1116 cpl_table_new_column(tracking_loc_table, MOO_TRACKING_LOC_TABLE_YDIFF,
1118 cpl_table_new_column(tracking_loc_table, MOO_TRACKING_LOC_TABLE_SNR,
1120 cpl_table_new_column(tracking_loc_table, MOO_TRACKING_LOC_TABLE_FLAG,
1122 cpl_table_new_column(tracking_loc_table, MOO_TRACKING_LOC_TABLE_XGOOD_RATIO,
1124 cpl_table_new_column(tracking_loc_table,
1125 MOO_TRACKING_LOC_TABLE_FITYCENTROID, CPL_TYPE_DOUBLE);
1126 cpl_table_new_column(tracking_loc_table, MOO_TRACKING_LOC_TABLE_FITYMIN,
1128 cpl_table_new_column(tracking_loc_table, MOO_TRACKING_LOC_TABLE_FITYMAX,
1131 for (
int i = 0; i < nx; i++) {
1132 cpl_table_set_int(tracking_loc_table, MOO_TRACKING_LOC_TABLE_FIBNUM, i,
1135 cpl_table_set_int(tracking_loc_table, MOO_TRACKING_LOC_TABLE_X, cx - 1, cx);
1136 cpl_table_set_double(tracking_loc_table, MOO_TRACKING_LOC_TABLE_YCENTROID,
1137 cx - 1, (f->center));
1138 cpl_table_set_double(tracking_loc_table, MOO_TRACKING_LOC_TABLE_YMIN,
1140 cpl_table_set_double(tracking_loc_table, MOO_TRACKING_LOC_TABLE_YMAX,
1142 cpl_table_set_int(tracking_loc_table, MOO_TRACKING_LOC_TABLE_FLAG, cx - 1,
1145 double last_center = f->center;
1146 cpl_vector *last_width = cpl_vector_new(3);
1147 cpl_vector_fill(last_width, f->width);
1151 int nb_follow_invalid = 0;
1152 for (
int i = cx + 1; i <= nx; i++) {
1154 _moo_localise_row(himg, i, wdiff_lim, ydiff_lim, frac, ref_snr,
1155 &min, &max, tracking_loc_table, &last_center,
1156 last_width, &last_x);
1159 nb_follow_invalid++;
1163 nb_follow_invalid = 0;
1165 if (nb_follow_invalid > xgap_max) {
1166 for (
int j = i + 1; j <= nx; j++) {
1168 cpl_table_set_int(tracking_loc_table, MOO_TRACKING_LOC_TABLE_X,
1170 cpl_table_set_int(tracking_loc_table,
1171 MOO_TRACKING_LOC_TABLE_FLAG, j - 1,
1172 MOONS_FLAG_XMAX_GAP);
1177 last_center = f->center;
1178 cpl_vector_fill(last_width, f->width);
1180 nb_follow_invalid = 0;
1182 for (
int i = cx - 1; i > 0; i--) {
1184 _moo_localise_row(himg, i, wdiff_lim, ydiff_lim, frac, ref_snr,
1185 &min, &max, tracking_loc_table, &last_center,
1186 last_width, &last_x);
1188 nb_follow_invalid++;
1192 nb_follow_invalid = 0;
1194 if (nb_follow_invalid > xgap_max) {
1195 for (
int j = i - 1; j > 0; j--) {
1197 cpl_table_set_int(tracking_loc_table, MOO_TRACKING_LOC_TABLE_X,
1199 cpl_table_set_int(tracking_loc_table,
1200 MOO_TRACKING_LOC_TABLE_FLAG, j - 1,
1201 MOONS_FLAG_XMAX_GAP);
1206 cpl_vector_delete(last_width);
1208 cpl_msg_debug(
"moo_localise",
"Fraction of invalid detection %.2f %%",
1209 (
double)nb_invalid / (
double)nx * 100.);
1210 f->goodfrac = (1. - nb_invalid / (double)nx) * 100.;
1211 cpl_msg_indent_less();
1212 if (f->goodfrac >= goodptsfrac_min) {
1213 status = _moo_localise_tchebychev_fit(res, f->num, deg_poly,
1214 tracking_loc_table, xlim_hwin,
1218 f->health = MOO_FIBRES_TABLE_HEALTH_NEWLY_BROKEN;
1220 *all_tracked = tracking_loc_table;
1225_moo_localise_col_flux_from_guess(hdrl_image *himg,
1226 cpl_table *tracking_loc_table,
1236 int flag = MOONS_FLAG_GOOD;
1239 const cpl_image *img = hdrl_image_get_image_const(himg);
1240 const cpl_image *error = hdrl_image_get_error_const(himg);
1242 cpl_vector *fluxes = cpl_vector_new_from_image_column(img, x);
1243 cpl_vector *errs = cpl_vector_new_from_image_column(error, x);
1245 if (strcmp(method, MOO_LOCALISE_METHOD_BARYCENTER) == 0) {
1246 double thresh_low, thresh_up;
1249 _moo_profile_find_image_background_flux(img, x, *yc, *width, frac,
1250 &b1_y, &b2_y, &thresh_low,
1253 _moo_profile_find_image_thresh_positions(img, x, *yc, thresh_low,
1256 cpl_errorstate prev_state = cpl_errorstate_get();
1257 cpl_bivector *points = _moo_extract_profile_integrate(fluxes, *yl, *yu);
1259 if (points != NULL) {
1262 cpl_bivector_delete(points);
1263 flag = _check_snr(fluxes, errs, *yc, b1_y, b2_y, ref_snr, &snr);
1264 cpl_table_set_double(tracking_loc_table, MOO_TRACKING_LOC_TABLE_SNR,
1268 cpl_errorstate_set(prev_state);
1269 flag = MOONS_FLAG_NOPROFILE;
1273 cpl_errorstate prev_state = cpl_errorstate_get();
1274 double gc = *yc, gwidth, background = 0, area, sigma = *width / 4.0;
1275 cpl_bivector *points = _moo_extract_profile_integrate(fluxes, *yl, *yu);
1283 cpl_fit_mode fit_pars = CPL_FIT_CENTROID | CPL_FIT_STDEV | CPL_FIT_AREA;
1286 if (!cpl_errorstate_is_equal(prev_state)) {
1287 cpl_errorstate_set(prev_state);
1288 flag = MOONS_FLAG_BADPROFILE;
1303 double thresh = background + (ycval - background) * frac;
1316 double thresh_low, thresh_up;
1317 double b1_y, b2_y, snr;
1319 _moo_profile_find_background_flux(fluxes, gc, *width, frac,
1320 &b1_y, &b2_y, &thresh_low,
1323 flag = _check_snr(fluxes, errs, gc, b1_y, b2_y, ref_snr, &snr);
1330 flag = MOONS_FLAG_NARROWPROFILE;
1333 cpl_bivector_delete(points);
1336 cpl_vector_delete(fluxes);
1337 cpl_vector_delete(errs);
1343_moo_localise_col_from_guess(hdrl_image *himg,
1348 cpl_table *tracking_table,
1354 double width = wl + wu;
1355 double yl = yc - wl;
1356 double yu = yc + wu;
1358 int fl = _check_trace_guess(center, width);
1359 if (fl != MOONS_FLAG_GOOD) {
1363 fl = _check_bpm(himg, x, center, width);
1364 if (fl != MOONS_FLAG_GOOD) {
1368 fl = _moo_localise_col_flux_from_guess(himg, tracking_table, x, ¢er,
1369 &width, &yl, &yu, method, frac,
1372 if (fl == MOONS_FLAG_GOOD) {
1373 cpl_table_set_double(tracking_table, MOO_TRACKING_LOC_TABLE_YCENTROID,
1375 cpl_table_set_double(tracking_table, MOO_TRACKING_LOC_TABLE_YMIN, x - 1,
1377 cpl_table_set_double(tracking_table, MOO_TRACKING_LOC_TABLE_YMAX, x - 1,
1385_moo_localise_fibre_from_guess(
int fibnum,
1387 cpl_image *gcentroid,
1390 moo_localise_params *params,
1392 double goodptsfrac_min,
1394 moo_loc_single *res,
1395 cpl_table **all_tracked)
1398 cpl_table *tracking_loc_table = NULL;
1400 cpl_errorstate prestate = cpl_errorstate_get();
1401 cpl_ensure(himg != NULL, CPL_ERROR_NULL_INPUT, 0);
1403 int xlim_hwin = params->loc_xlim_hwin;
1404 double xlim_fracmin = params->loc_xlim_fracmin;
1406 cpl_msg_indent_more();
1408 cpl_msg_debug(
"moo_localise",
"Localise fibres %d using guess localisation",
1410 int nx = hdrl_image_get_size_x(himg);
1412 tracking_loc_table = cpl_table_new(nx);
1413 cpl_table_new_column(tracking_loc_table, MOO_TRACKING_LOC_TABLE_FIBNUM,
1415 cpl_table_new_column(tracking_loc_table, MOO_TRACKING_LOC_TABLE_X,
1417 cpl_table_new_column(tracking_loc_table,
1418 MOO_TRACKING_LOC_TABLE_GUESS_YCENTROID,
1420 cpl_table_new_column(tracking_loc_table, MOO_TRACKING_LOC_TABLE_GUESS_WLO,
1422 cpl_table_new_column(tracking_loc_table, MOO_TRACKING_LOC_TABLE_GUESS_WUP,
1424 cpl_table_new_column(tracking_loc_table, MOO_TRACKING_LOC_TABLE_YCENTROID,
1426 cpl_table_new_column(tracking_loc_table, MOO_TRACKING_LOC_TABLE_YMIN,
1428 cpl_table_new_column(tracking_loc_table, MOO_TRACKING_LOC_TABLE_YMAX,
1430 cpl_table_new_column(tracking_loc_table, MOO_TRACKING_LOC_TABLE_WDIFF,
1432 cpl_table_new_column(tracking_loc_table, MOO_TRACKING_LOC_TABLE_YDIFF,
1434 cpl_table_new_column(tracking_loc_table, MOO_TRACKING_LOC_TABLE_SNR,
1436 cpl_table_new_column(tracking_loc_table, MOO_TRACKING_LOC_TABLE_FLAG,
1438 cpl_table_new_column(tracking_loc_table, MOO_TRACKING_LOC_TABLE_XGOOD_RATIO,
1440 cpl_table_new_column(tracking_loc_table,
1441 MOO_TRACKING_LOC_TABLE_FITYCENTROID, CPL_TYPE_DOUBLE);
1442 cpl_table_new_column(tracking_loc_table, MOO_TRACKING_LOC_TABLE_FITYMIN,
1444 cpl_table_new_column(tracking_loc_table, MOO_TRACKING_LOC_TABLE_FITYMAX,
1447 for (
int i = 0; i < nx; i++) {
1448 cpl_table_set_int(tracking_loc_table, MOO_TRACKING_LOC_TABLE_FIBNUM, i,
1454 for (
int i = 1; i <= nx; i++) {
1456 double yc = cpl_image_get(gcentroid, i, fibnum, &rej);
1457 double wl = cpl_image_get(gwlo, i, fibnum, &rej);
1458 double wu = cpl_image_get(gwup, i, fibnum, &rej);
1459 cpl_table_set_int(tracking_loc_table, MOO_TRACKING_LOC_TABLE_X, i - 1,
1461 cpl_table_set_double(tracking_loc_table,
1462 MOO_TRACKING_LOC_TABLE_GUESS_YCENTROID, i - 1, yc);
1463 cpl_table_set_double(tracking_loc_table,
1464 MOO_TRACKING_LOC_TABLE_GUESS_WLO, i - 1, wl);
1465 cpl_table_set_double(tracking_loc_table,
1466 MOO_TRACKING_LOC_TABLE_GUESS_WUP, i - 1, wu);
1467 int flag = MOONS_FLAG_GOOD;
1468 moo_try_check(flag = _moo_localise_col_from_guess(
1469 himg, i, yc, wl, wu, tracking_loc_table,
1470 params->method, params->relativethresh, ref_snr),
1472 cpl_table_set_int(tracking_loc_table, MOO_TRACKING_LOC_TABLE_FLAG,
1475 if (flag != MOONS_FLAG_GOOD) {
1479 cpl_msg_debug(
"moo_localise",
"Fraction of invalid detection %.1f %%",
1480 nb_invalid / (
double)nx * 100);
1481 double frac_good = (1 - nb_invalid / (double)nx) * 100;
1483 if (frac_good > goodptsfrac_min) {
1484 _moo_localise_tchebychev_fit(res, fibnum, deg_poly, tracking_loc_table,
1485 xlim_hwin, xlim_fracmin);
1489 cpl_image *measured_centroids = res->m_centroids;
1490 cpl_image *fit_centroids = res->f_centroids;
1491 cpl_image *wlow = res->f_wlow;
1492 cpl_image *wup = res->f_wup;
1493 cpl_image *mlow = res->m_wlow;
1494 cpl_image *mup = res->m_wup;
1495 cpl_image *flags = res->flags;
1497 for (
int i = 1; i <= nx; i++) {
1499 cpl_table_get_int(tracking_loc_table,
1500 MOO_TRACKING_LOC_TABLE_FLAG, i - 1, NULL);
1501 double yc = cpl_table_get_double(tracking_loc_table,
1502 MOO_TRACKING_LOC_TABLE_YCENTROID,
1505 cpl_table_get_double(tracking_loc_table,
1506 MOO_TRACKING_LOC_TABLE_YMIN, i - 1, NULL);
1508 cpl_table_get_double(tracking_loc_table,
1509 MOO_TRACKING_LOC_TABLE_YMAX, i - 1, NULL);
1510 cpl_image_set(measured_centroids, i, fibnum, yc);
1511 cpl_image_set(mlow, i, fibnum, yl);
1512 cpl_image_set(mup, i, fibnum, yu);
1514 cpl_image_set(flags, i, fibnum, flag);
1515 cpl_image_set(fit_centroids, i, fibnum, NAN);
1516 cpl_image_set(wlow, i, fibnum, NAN);
1517 cpl_image_set(wup, i, fibnum, NAN);
1522 *all_tracked = tracking_loc_table;
1523 cpl_msg_indent_less();
1525 if (!cpl_errorstate_is_equal(prestate)) {
1526 cpl_errorstate_dump(prestate, CPL_FALSE, cpl_errorstate_dump_one);
1528 cpl_errorstate_set(prestate);
1533static moo_loc_single *
1534_moo_localise_single_from_guess(moo_single *single,
1535 moo_loc_single *guess,
1539 const int *indexext,
1540 moo_localise_params *params,
1543 const char *filename,
1545 double goodptsfrac_min,
1549 int nmissing_fibres = 0;
1550 moo_loc_single *res = NULL;
1551 cpl_table **all_tracked = NULL;
1553 cpl_ensure(single != NULL, CPL_ERROR_NULL_INPUT, NULL);
1554 cpl_ensure(guess != NULL, CPL_ERROR_NULL_INPUT, NULL);
1556 cpl_errorstate prestate = cpl_errorstate_get();
1558 cpl_msg_info(
"moo_localise",
"goodptsfrac-min %f", goodptsfrac_min);
1560 int nx = hdrl_image_get_size_x(himg);
1565 res->m_centroids = cpl_image_new(nx, nb_total, CPL_TYPE_DOUBLE);
1566 res->f_centroids = cpl_image_new(nx, nb_total, CPL_TYPE_DOUBLE);
1567 res->m_wlow = cpl_image_new(nx, nb_total, CPL_TYPE_DOUBLE);
1568 res->f_wlow = cpl_image_new(nx, nb_total, CPL_TYPE_DOUBLE);
1569 res->m_wup = cpl_image_new(nx, nb_total, CPL_TYPE_DOUBLE);
1570 res->f_wup = cpl_image_new(nx, nb_total, CPL_TYPE_DOUBLE);
1571 res->flags = cpl_image_new(nx, nb_total, CPL_TYPE_INT);
1572 res->header = cpl_propertylist_new();
1578 all_tracked = cpl_calloc(nb_total,
sizeof(cpl_table *));
1581#pragma omp parallel default(none) \
1582 shared(all_tracked, nb_total, health, res, degpoly, goodptsfrac_min, \
1583 ref_snr, params, gwup, gwlo, gcentroids, himg, nmissing_fibres, \
1584 names, nx, indexes, indexext, single)
1588 for (
int f = 1; f <= nb_total; f++) {
1590 int idx = cpl_array_get_cplsize(indexes, f - 1, NULL);
1592 if (health[idx] == MOO_FIBRES_TABLE_HEALTH_GOOD) {
1594 _moo_localise_fibre_from_guess(f, himg, gcentroids, gwlo,
1595 gwup, params, degpoly,
1596 goodptsfrac_min, ref_snr,
1597 res, &all_tracked[f - 1]);
1599 if (detected == 0) {
1600 cpl_msg_info(
"moo_localise",
1601 "Bad detection fibre indexext %d with name %s",
1602 indexext[idx], names[idx]);
1603 health[idx] = MOO_FIBRES_TABLE_HEALTH_NEWLY_BROKEN;
1607 cpl_msg_info(
"moo_localise",
1608 "Bad health fibre indexext %d with name %s",
1609 indexext[idx], names[idx]);
1610 for (
int i = 1; i <= nx; i++) {
1611 cpl_image_set(res->m_centroids, i, f, NAN);
1612 cpl_image_set(res->m_wlow, i, f, NAN);
1613 cpl_image_set(res->m_wup, i, f, NAN);
1614 cpl_image_set(res->flags, i, f, MOONS_FLAG_BROKEN_FIBRE);
1615 cpl_image_set(res->f_centroids, i, f, NAN);
1616 cpl_image_set(res->f_wlow, i, f, NAN);
1617 cpl_image_set(res->f_wup, i, f, NAN);
1624 for (
int f = 0; f < nb_total; f++) {
1625 if (health[f] == MOO_FIBRES_TABLE_HEALTH_NEWLY_BROKEN) {
1626 health[f] = MOO_FIBRES_TABLE_HEALTH_BROKEN;
1631#if MOO_DEBUG_LOCALISE_TRACKING
1633 char *name = cpl_sprintf(
"%s_TRACKING_LOC_TABLE.fits", res->extname);
1634 cpl_table *test = NULL;
1636 for (
int i = 0; i < nb_total; i++) {
1637 cpl_table *t = all_tracked[i];
1639 test = cpl_table_duplicate(t);
1645 for (
int i = first; i < nb_total; i++) {
1646 cpl_table *t = all_tracked[i];
1648 moo_table_append(test, t);
1651 cpl_table_save(test, NULL, NULL, name, CPL_IO_CREATE);
1652 cpl_table_delete(test);
1659 if (all_tracked != NULL) {
1660 for (
int i = 0; i < nb_total; i++) {
1661 if (all_tracked[i] != NULL) {
1662 cpl_table_delete(all_tracked[i]);
1665 cpl_free(all_tracked);
1668 if (!cpl_errorstate_is_equal(prestate)) {
1696_moo_localise_from_guess(moo_det *det,
1698 moo_localise_params *params,
1699 const char *locname,
1702 cpl_errorstate prestate = cpl_errorstate_get();
1704 cpl_ensure(det != NULL, CPL_ERROR_NULL_INPUT, NULL);
1705 cpl_ensure(guess != NULL, CPL_ERROR_NULL_INPUT, NULL);
1706 cpl_ensure(params != NULL, CPL_ERROR_NULL_INPUT, NULL);
1709 cpl_ensure(fibres_table != NULL, CPL_ERROR_ILLEGAL_INPUT, NULL);
1711 const char *filename = locname;
1712 moo_loc *loc = NULL;
1716 cpl_msg_info(
"moo_localise",
"Create TRACE localisation");
1717 cpl_msg_indent_more();
1719 cpl_table *loc_fibre_table = NULL;
1721 const int *indexext = NULL;
1722 const char **names = NULL;
1723 cpl_array *indexes = NULL;
1725 loc_fibre_table = cpl_table_duplicate(fibres_table);
1726 moo_try_check(health = cpl_table_get_data_int(loc_fibre_table,
1727 MOO_FIBRES_TABLE_HEALTH),
1730 moo_try_check(indexext = cpl_table_get_data_int(loc_fibre_table,
1731 MOO_FIBRES_TABLE_INDEXEXT),
1734 moo_try_check(names =
1735 cpl_table_get_data_string_const(loc_fibre_table,
1736 MOO_FIBRES_TABLE_FIBRE),
1739 for (i = 1; i <= 2; i++) {
1742 int nb_total = cpl_array_get_size(indexes);
1744 for (j = 0; j < 3; j++) {
1745 int idx = (i - 1) * 3 + j;
1746 int polydeg = params->polydeg[idx];
1747 double ref_snr = params->ref_snr[idx];
1748 double goodptsfrac_min = params->goodptsfrac_min[idx] * 100.;
1752 if (s1 != NULL && lguess != NULL) {
1753 cpl_msg_info(
"moo_localise",
"Localising %d fibres in %s",
1756 moo_loc_single *ls =
1757 _moo_localise_single_from_guess(s1, lguess, nb_total,
1758 health, names, indexext,
1759 params, j, i, filename,
1760 polydeg, goodptsfrac_min,
1764 moo_loc_single_compute_qc_trace(ls, polydeg, lguess);
1769 cpl_array_delete(indexes);
1776 cpl_msg_indent_less();
1778 if (!cpl_errorstate_is_equal(prestate)) {
1779 cpl_array_delete(indexes);
1780 cpl_table_delete(loc_fibre_table);
1781 loc_fibre_table = NULL;
1790_moo_bckg_poly_eval(cpl_polynomial *fit1d,
double v)
1797 double c0, c1, c2, c3, c4;
1798 c0 = cpl_polynomial_get_coeff(fit1d, &p0);
1799 c1 = cpl_polynomial_get_coeff(fit1d, &p1);
1800 c2 = cpl_polynomial_get_coeff(fit1d, &p2);
1801 c3 = cpl_polynomial_get_coeff(fit1d, &p3);
1802 c4 = cpl_polynomial_get_coeff(fit1d, &p4);
1803 double b = c0 + v * c1 + v * v * c2 + v * v * v * c3 + v * v * v * v * c4;
1808static cpl_error_code
1809_moo_localise_background_fit_rmin(cpl_table *fibre_loc_table,
int winhsize)
1811 cpl_ensure_code(winhsize >= 0, CPL_ERROR_ILLEGAL_INPUT);
1814 cpl_table_get_data_double(fibre_loc_table, MOO_FIBRE_LOC_TABLE_FLUX);
1815 double *errs = cpl_table_get_data_double(fibre_loc_table,
1816 MOO_FIBRE_LOC_TABLE_FLUX_ERR);
1817 int ny = cpl_table_get_nrow(fibre_loc_table);
1818 int winsize = 2 * winhsize + 1;
1821 for (
int i = 0; i < winsize; i++) {
1822 double b = fluxes[i];
1823 if (isnan(fluxes[ib])) {
1826 else if (!isnan(b) && fluxes[ib] > b) {
1830 double b = fluxes[ib];
1831 double be = errs[ib];
1832 for (
int i = 0; i < winhsize; i++) {
1833 cpl_table_set_double(fibre_loc_table, MOO_FIBRE_LOC_TABLE_BACKGROUND, i,
1835 cpl_table_set_double(fibre_loc_table,
1836 MOO_FIBRE_LOC_TABLE_BACKGROUND_ERR, i, be);
1839 for (
int i = ny - winsize; i < ny; i++) {
1841 if (isnan(fluxes[ib])) {
1844 else if (!isnan(b) && fluxes[ib] > b) {
1850 for (
int i = ny - winhsize; i < ny; i++) {
1851 cpl_table_set_double(fibre_loc_table, MOO_FIBRE_LOC_TABLE_BACKGROUND, i,
1853 cpl_table_set_double(fibre_loc_table,
1854 MOO_FIBRE_LOC_TABLE_BACKGROUND_ERR, i, be);
1856 for (
int i = winhsize; i < ny - winhsize; i++) {
1858 for (
int j = i - winhsize; j < i + winhsize; j++) {
1860 if (isnan(fluxes[ib])) {
1863 else if (!isnan(b) && fluxes[ib] > b) {
1869 cpl_table_set_double(fibre_loc_table, MOO_FIBRE_LOC_TABLE_BACKGROUND, i,
1871 cpl_table_set_double(fibre_loc_table,
1872 MOO_FIBRE_LOC_TABLE_BACKGROUND_ERR, i, be);
1874 return CPL_ERROR_NONE;
1877static cpl_error_code
1878_moo_localise_background_fit_poly(cpl_table *fibre_loc_table,
1884 cpl_error_code error1d = CPL_ERROR_NONE;
1885 cpl_polynomial *fit1d = NULL;
1886 cpl_polynomial *errfit1d = NULL;
1887 cpl_matrix *samppos1d = NULL;
1888 cpl_vector *fitvals = NULL;
1889 cpl_vector *errvals = NULL;
1890 const cpl_boolean sampsym = CPL_FALSE;
1891 const cpl_size maxdeg1d = polydeg;
1892 double min_thresh_flux = 0.12;
1893 double min_kappa_flux = 2;
1895 cpl_table_get_data_double(fibre_loc_table, MOO_FIBRE_LOC_TABLE_FLUX);
1896 double *errs = cpl_table_get_data_double(fibre_loc_table,
1897 MOO_FIBRE_LOC_TABLE_FLUX_ERR);
1899 cpl_table_get_data_double(fibre_loc_table, MOO_FIBRE_LOC_TABLE_Y);
1901 cpl_table_get_data_int(fibre_loc_table, MOO_FIBRE_LOC_TABLE_BCKGFITTED);
1902 int ny = cpl_table_get_nrow(fibre_loc_table);
1903 fitvals = cpl_vector_new(ny);
1904 for (
int i = 0; i < ny; i++) {
1905 cpl_vector_set(fitvals, i, fluxes[i]);
1909 cpl_vector_delete(fitvals);
1914 for (
int i = 0; i < ny; i++) {
1915 if (fluxes[i] < min_flux) {
1923 fit1d = cpl_polynomial_new(1);
1924 errfit1d = cpl_polynomial_new(1);
1925 samppos1d = cpl_matrix_new(1, nb);
1926 fitvals = cpl_vector_new(nb);
1927 errvals = cpl_vector_new(nb);
1929 for (
int i = 0; i < ny; i++) {
1930 if (fitted[i] == 1) {
1931 cpl_matrix_set(samppos1d, 0, nb, ytab[i]);
1932 cpl_vector_set(fitvals, nb, fluxes[i]);
1933 cpl_vector_set(errvals, nb, errs[i]);
1937 error1d = cpl_polynomial_fit(fit1d, samppos1d, &sampsym, fitvals, NULL,
1938 CPL_FALSE, NULL, &maxdeg1d);
1939 error1d = cpl_polynomial_fit(errfit1d, samppos1d, &sampsym, errvals, NULL,
1940 CPL_FALSE, NULL, &maxdeg1d);
1942 cpl_vector *vdiff = cpl_vector_new(nb);
1944 for (
int i = 0; i < niter; i++) {
1946 for (
int j = 0; j < ny; j++) {
1950 double b = _moo_bckg_poly_eval(fit1d, v);
1951 double flux = fluxes[j];
1952 double diff = flux - b;
1953 cpl_vector_set(vdiff, nb, diff);
1958 double stdev = cpl_vector_get_stdev(vdiff);
1959 cpl_msg_info(
"test",
"niter %d stdev %f", i + 1, stdev);
1961 for (
int j = 0; j < ny; j++) {
1965 double b = _moo_bckg_poly_eval(fit1d, v);
1966 double flux = fluxes[j];
1967 double diff = flux - b;
1968 if ((diff > kup * stdev) || (diff < -klo * stdev)) {
1976 cpl_polynomial_delete(fit1d);
1977 cpl_polynomial_delete(errfit1d);
1978 cpl_matrix_delete(samppos1d);
1979 cpl_vector_delete(fitvals);
1980 cpl_vector_delete(errvals);
1981 cpl_vector_delete(vdiff);
1990 vdiff = cpl_vector_new(nb);
1991 fit1d = cpl_polynomial_new(1);
1992 errfit1d = cpl_polynomial_new(1);
1993 samppos1d = cpl_matrix_new(1, nb);
1994 fitvals = cpl_vector_new(nb);
1995 errvals = cpl_vector_new(nb);
1998 for (
int j = 0; j < ny; j++) {
1999 if (fitted[j] == 1) {
2000 cpl_matrix_set(samppos1d, 0, nb, ytab[j]);
2001 cpl_vector_set(fitvals, nb, fluxes[j]);
2002 cpl_vector_set(errvals, nb, errs[j]);
2006 error1d = cpl_polynomial_fit(fit1d, samppos1d, &sampsym, fitvals, NULL,
2007 CPL_FALSE, NULL, &maxdeg1d);
2008 error1d = cpl_polynomial_fit(errfit1d, samppos1d, &sampsym, errvals,
2009 NULL, CPL_FALSE, NULL, &maxdeg1d);
2012 for (
int i = 0; i < ny; i++) {
2014 double b = _moo_bckg_poly_eval(fit1d, v);
2015 double be = _moo_bckg_poly_eval(errfit1d, v);
2016 cpl_table_set_double(fibre_loc_table, MOO_FIBRE_LOC_TABLE_BACKGROUND, i,
2018 cpl_table_set_double(fibre_loc_table,
2019 MOO_FIBRE_LOC_TABLE_BACKGROUND_ERR, i, be);
2022 cpl_polynomial_delete(fit1d);
2023 cpl_polynomial_delete(errfit1d);
2024 cpl_matrix_delete(samppos1d);
2025 cpl_vector_delete(fitvals);
2026 cpl_vector_delete(errvals);
2027 cpl_vector_delete(vdiff);
2032_moo_localise_flag_detected(cpl_table *table,
double *max)
2034 cpl_array *flagged = NULL;
2036 cpl_table_select_all(table);
2037 cpl_table_and_selected_int(table, MOO_FIBRE_LOC_TABLE_FLAG, CPL_EQUAL_TO,
2039 cpl_table *seltable = cpl_table_extract_selected(table);
2040 int size = cpl_table_get_nrow(seltable);
2043 cpl_table_get_data_double(seltable, MOO_FIBRE_LOC_TABLE_FLUX);
2044 cpl_vector *vfluxes = cpl_vector_wrap(size, fluxes);
2045 *max = cpl_vector_get_max(vfluxes) * 0.5;
2047 cpl_table_and_selected_double(table, MOO_FIBRE_LOC_TABLE_FLUX,
2048 CPL_GREATER_THAN, *max);
2049 flagged = cpl_table_where_selected(table);
2050 cpl_vector_unwrap(vfluxes);
2052 cpl_table_delete(seltable);
2057static cpl_error_code
2058_moo_localise_detect_fibres(cpl_array *flagged,
2059 cpl_table *fibre_loc_table,
2060 cpl_table *detect_loc_table,
2063 cpl_ensure_code(flagged != NULL, CPL_ERROR_NULL_INPUT);
2065 int nb_flagged = cpl_array_get_size(flagged);
2070 int nrow = cpl_table_get_nrow(fibre_loc_table);
2072 for (
int i = 0; i < nb_flagged; i++) {
2076 int index = cpl_array_get_cplsize(flagged, i, NULL);
2077 cpl_table_set_int(fibre_loc_table, MOO_FIBRE_LOC_TABLE_FLAG, index, n);
2078 int fy = (int)cpl_table_get_double(fibre_loc_table,
2079 MOO_FIBRE_LOC_TABLE_Y, index, NULL);
2081 cpl_table_get_double(fibre_loc_table, MOO_FIBRE_LOC_TABLE_FLUX,
2083 cpl_table_select_all(detect_loc_table);
2084 if (index < (nrow - 1)) {
2085 int fy_after = (int)cpl_table_get_double(fibre_loc_table,
2086 MOO_FIBRE_LOC_TABLE_Y,
2089 nbsel1 = cpl_table_and_selected_int(detect_loc_table,
2090 MOO_DETECT_LOC_TABLE_YMIN,
2091 CPL_EQUAL_TO, fy_after);
2094 cpl_array *sel = cpl_table_where_selected(detect_loc_table);
2095 for (
int j = 0; j < nbsel1; j++) {
2096 cpl_size idx = cpl_array_get_cplsize(sel, j, NULL);
2098 cpl_table_set_int(detect_loc_table,
2099 MOO_DETECT_LOC_TABLE_YMIN, idx, fy);
2100 cpl_table_set_double(detect_loc_table,
2101 MOO_DETECT_LOC_TABLE_FLUX_YMIN, idx,
2104 cpl_array_delete(sel);
2109 int fy_before = (int)cpl_table_get_double(fibre_loc_table,
2110 MOO_FIBRE_LOC_TABLE_Y,
2113 cpl_table_select_all(detect_loc_table);
2114 nbsel2 = cpl_table_and_selected_int(detect_loc_table,
2115 MOO_DETECT_LOC_TABLE_YMAX,
2116 CPL_EQUAL_TO, fy_before);
2119 cpl_array *sel = cpl_table_where_selected(detect_loc_table);
2121 for (
int j = 0; j < nbsel2; j++) {
2122 cpl_size idx = cpl_array_get_cplsize(sel, j, NULL);
2123 cpl_table_set_int(detect_loc_table,
2124 MOO_DETECT_LOC_TABLE_YMAX, idx, fy);
2125 cpl_table_set_double(detect_loc_table,
2126 MOO_DETECT_LOC_TABLE_FLUX_YMAX, idx,
2129 cpl_array_delete(sel);
2133 if (nbsel1 == 0 && nbsel2 == 0) {
2140 else if (fy == (ymin + ysize)) {
2141 if (index < (nrow - 1)) {
2143 (int)cpl_table_get_double(fibre_loc_table,
2144 MOO_FIBRE_LOC_TABLE_Y,
2146 int ystep = fy_after - fy;
2155 cpl_table_set_size(detect_loc_table, nb);
2156 cpl_table_set_int(detect_loc_table, MOO_DETECT_LOC_TABLE_NUM,
2158 cpl_table_set_int(detect_loc_table, MOO_DETECT_LOC_TABLE_YMIN,
2160 cpl_table_select_all(fibre_loc_table);
2161 cpl_table_and_selected_double(fibre_loc_table,
2162 MOO_FIBRE_LOC_TABLE_Y,
2163 CPL_EQUAL_TO, ymin);
2164 cpl_array *sel = cpl_table_where_selected(fibre_loc_table);
2165 cpl_size idx = cpl_array_get_cplsize(sel, 0, NULL);
2166 cpl_array_delete(sel);
2168 cpl_table_get_double(fibre_loc_table,
2169 MOO_FIBRE_LOC_TABLE_FLUX, idx, NULL);
2170 cpl_table_set_double(detect_loc_table,
2171 MOO_DETECT_LOC_TABLE_FLUX_YMIN, nb - 1,
2173 cpl_table_set_int(detect_loc_table, MOO_DETECT_LOC_TABLE_YMAX,
2175 cpl_table_select_all(fibre_loc_table);
2176 cpl_table_and_selected_double(fibre_loc_table,
2177 MOO_FIBRE_LOC_TABLE_Y,
2178 CPL_EQUAL_TO, ymax);
2179 sel = cpl_table_where_selected(fibre_loc_table);
2180 idx = cpl_array_get_cplsize(sel, 0, NULL);
2181 cpl_array_delete(sel);
2184 cpl_table_get_double(fibre_loc_table,
2185 MOO_FIBRE_LOC_TABLE_FLUX, idx, NULL);
2186 cpl_table_set_double(detect_loc_table,
2187 MOO_DETECT_LOC_TABLE_FLUX_YMAX, nb - 1,
2198 cpl_table_set_size(detect_loc_table, nb);
2199 cpl_table_set_int(detect_loc_table, MOO_DETECT_LOC_TABLE_NUM, nb - 1,
2201 cpl_table_set_int(detect_loc_table, MOO_DETECT_LOC_TABLE_YMIN, nb - 1,
2204 cpl_table_select_all(fibre_loc_table);
2205 cpl_table_and_selected_double(fibre_loc_table, MOO_FIBRE_LOC_TABLE_Y,
2206 CPL_EQUAL_TO, ymin);
2207 cpl_array *sel = cpl_table_where_selected(fibre_loc_table);
2208 cpl_size idx = cpl_array_get_cplsize(sel, 0, NULL);
2209 cpl_array_delete(sel);
2211 cpl_table_get_double(fibre_loc_table, MOO_FIBRE_LOC_TABLE_FLUX, idx,
2213 cpl_table_set_double(detect_loc_table, MOO_DETECT_LOC_TABLE_FLUX_YMIN,
2216 cpl_table_set_int(detect_loc_table, MOO_DETECT_LOC_TABLE_YMAX, nb - 1,
2218 cpl_table_select_all(fibre_loc_table);
2219 cpl_table_and_selected_double(fibre_loc_table, MOO_FIBRE_LOC_TABLE_Y,
2220 CPL_EQUAL_TO, ymax);
2221 sel = cpl_table_where_selected(fibre_loc_table);
2222 idx = cpl_array_get_cplsize(sel, 0, NULL);
2223 cpl_array_delete(sel);
2226 cpl_table_get_double(fibre_loc_table, MOO_FIBRE_LOC_TABLE_FLUX, idx,
2228 cpl_table_set_double(detect_loc_table, MOO_DETECT_LOC_TABLE_FLUX_YMAX,
2232 return CPL_ERROR_NONE;
2235static cpl_error_code
2236_moo_localise_band(moo_single *single,
2239 const char *backg_method,
2242 double backg_clip_kappalow,
2243 double backg_clip_kappaup,
2244 int backg_clip_niter,
2245 double detect_noisemult_thresh,
2250 cpl_table **out_detect_loc_table,
2251 cpl_table **out_fibre_loc_table)
2253 cpl_table *detect_loc_table = NULL;
2255 double klo = backg_clip_kappalow;
2256 double kup = backg_clip_kappaup;
2257 int niter = backg_clip_niter;
2259 int polydeg = backg_polydeg;
2261 double kthresh = detect_noisemult_thresh;
2263 cpl_ensure_code(single != NULL, CPL_ERROR_NULL_INPUT);
2265 cpl_msg_indent_more();
2268 int ny = hdrl_image_get_size_y(himg);
2271 cpl_table *fibre_loc_table = cpl_table_new(ny);
2272 cpl_table_new_column(fibre_loc_table, MOO_FIBRE_LOC_TABLE_Y,
2274 cpl_table_new_column(fibre_loc_table, MOO_FIBRE_LOC_TABLE_FLUX,
2276 cpl_table_new_column(fibre_loc_table, MOO_FIBRE_LOC_TABLE_FLUX_ERR,
2278 cpl_table_new_column(fibre_loc_table, MOO_FIBRE_LOC_TABLE_BAD,
2280 cpl_table_new_column(fibre_loc_table, MOO_FIBRE_LOC_TABLE_BACKGROUND,
2282 cpl_table_new_column(fibre_loc_table, MOO_FIBRE_LOC_TABLE_BACKGROUND_ERR,
2284 cpl_table_new_column(fibre_loc_table, MOO_FIBRE_LOC_TABLE_THRESH,
2286 cpl_table_new_column(fibre_loc_table, MOO_FIBRE_LOC_TABLE_BCKGFITTED,
2288 cpl_table_new_column(fibre_loc_table, MOO_FIBRE_LOC_TABLE_FLAG,
2291 detect_loc_table = cpl_table_new(0);
2292 cpl_table_new_column(detect_loc_table, MOO_DETECT_LOC_TABLE_NUM,
2294 cpl_table_new_column(detect_loc_table, MOO_DETECT_LOC_TABLE_YMIN,
2296 cpl_table_new_column(detect_loc_table, MOO_DETECT_LOC_TABLE_YMAX,
2298 cpl_table_new_column(detect_loc_table, MOO_DETECT_LOC_TABLE_FLUX_YMIN,
2300 cpl_table_new_column(detect_loc_table, MOO_DETECT_LOC_TABLE_FLUX_YMAX,
2303 for (y = 1; y <= ny; y++) {
2305 hdrl_image *extract = hdrl_image_extract(himg, cx - band_width / 2, y,
2306 cx + band_width / 2, y);
2308 val = hdrl_image_get_median(extract);
2310 cpl_table_set_double(fibre_loc_table, MOO_FIBRE_LOC_TABLE_Y, y - 1,
2312 cpl_table_set_double(fibre_loc_table, MOO_FIBRE_LOC_TABLE_FLUX, y - 1,
2314 cpl_table_set_double(fibre_loc_table, MOO_FIBRE_LOC_TABLE_FLUX_ERR,
2316 cpl_table_set_int(fibre_loc_table, MOO_FIBRE_LOC_TABLE_BAD, y - 1,
2318 cpl_table_set_int(fibre_loc_table, MOO_FIBRE_LOC_TABLE_BCKGFITTED,
2320 cpl_table_set_int(fibre_loc_table, MOO_FIBRE_LOC_TABLE_FLAG, y - 1, 0);
2321 hdrl_image_delete(extract);
2325 cpl_table_select_all(fibre_loc_table);
2326 cpl_table_and_selected_int(fibre_loc_table, MOO_FIBRE_LOC_TABLE_BAD,
2328 cpl_table_erase_selected(fibre_loc_table);
2330 ny = cpl_table_get_nrow(fibre_loc_table);
2331 if (strcmp(backg_method, MOO_LOCALISE_BACKG_METHOD_POLYNOMIAL) == 0) {
2334 "Background polynomial (%d degree) fit : kappa (lo %f, up %f) \
2336 polydeg, klo, kup, niter);
2338 _moo_localise_background_fit_poly(fibre_loc_table, polydeg, klo, kup,
2342 cpl_msg_info(
"moo_localise",
2343 "Background running median fit (winhsize %d)",
2346 _moo_localise_background_fit_rmin(fibre_loc_table, backg_winhsize);
2350 double *backgrounds =
2351 cpl_table_get_data_double(fibre_loc_table,
2352 MOO_FIBRE_LOC_TABLE_BACKGROUND);
2353 double *backgrounds_err =
2354 cpl_table_get_data_double(fibre_loc_table,
2355 MOO_FIBRE_LOC_TABLE_BACKGROUND_ERR);
2356 for (
int i = 0; i < ny; i++) {
2357 double t = backgrounds[i] + kthresh * backgrounds_err[i];
2358 cpl_table_set_double(fibre_loc_table, MOO_FIBRE_LOC_TABLE_THRESH, i, t);
2361 if (strcmp(backg_method, MOO_LOCALISE_BACKG_METHOD_POLYNOMIAL) == 0) {
2362 for (
int n = 1; n <= detect_niter; n++) {
2364 cpl_array *flagged =
2365 _moo_localise_flag_detected(fibre_loc_table, &thresh);
2367 cpl_table_select_all(fibre_loc_table);
2368 int nb_sel = cpl_table_and_selected_int(fibre_loc_table,
2369 MOO_FIBRE_LOC_TABLE_FLAG,
2372 cpl_table_and_selected_double(fibre_loc_table,
2373 MOO_FIBRE_LOC_TABLE_THRESH,
2374 CPL_GREATER_THAN, thresh);
2377 cpl_msg_info(
"test",
2378 "niter %d/%d : find in sel (%d) "
2381 "%d threshold points greater than %f",
2382 n, detect_niter, nb_sel, lower, thresh);
2383 cpl_array_delete(flagged);
2386 _moo_localise_detect_fibres(flagged, fibre_loc_table,
2387 detect_loc_table, n);
2388 cpl_array_delete(flagged);
2392 cpl_table_unselect_all(fibre_loc_table);
2393 cpl_table_or_selected(fibre_loc_table, MOO_FIBRE_LOC_TABLE_FLUX,
2394 CPL_GREATER_THAN, MOO_FIBRE_LOC_TABLE_THRESH);
2395 cpl_array *flagged = cpl_table_where_selected(fibre_loc_table);
2396 int nb_peaks = cpl_array_get_size(flagged);
2397 cpl_msg_info(
"moo_localise",
2398 "Filter peaks using ktresh (%f) : find %d peaks", kthresh,
2400 _moo_localise_detect_fibres(flagged, fibre_loc_table, detect_loc_table,
2402 cpl_array_delete(flagged);
2404#if MOO_DEBUG_LOCALISE_BAND
2406 char *testname = NULL;
2408 if (strcmp(backg_method, MOO_LOCALISE_BACKG_METHOD_POLYNOMIAL) == 0) {
2409 testname = cpl_sprintf(
"%s_FIB_LOC_TABLE_n%d.fits", single->extname,
2413 testname = cpl_sprintf(
"%s_FIB_LOC_TABLE_h%d.fits", single->extname,
2416 cpl_table_save(fibre_loc_table, NULL, NULL, testname, CPL_IO_CREATE);
2420 cpl_propertylist *slist = cpl_propertylist_new();
2421 cpl_propertylist_append_bool(slist, MOO_DETECT_LOC_TABLE_YMIN, FALSE);
2422 cpl_table_sort(detect_loc_table, slist);
2423 cpl_propertylist_delete(slist);
2425 int nrow = cpl_table_get_nrow(detect_loc_table);
2426 int nbdetected_valid_flux = 0;
2427 for (
int i = 0; i < nrow; i++) {
2429 int ymin = cpl_table_get_int(detect_loc_table,
2430 MOO_DETECT_LOC_TABLE_YMIN, i, &rej);
2431 int ymax = cpl_table_get_int(detect_loc_table,
2432 MOO_DETECT_LOC_TABLE_YMAX, i, &rej);
2434 nbdetected_valid_flux++;
2437 cpl_table_set_invalid(detect_loc_table,
2438 MOO_DETECT_LOC_TABLE_FLUX_YMIN, i);
2441 cpl_table_erase_invalid(detect_loc_table);
2445 "Number of detected fibres vs. expected valid fibres : %d / %d",
2446 nbdetected_valid_flux, nb_expected);
2448 *nb_detected = nbdetected_valid_flux;
2449 *out_detect_loc_table = detect_loc_table;
2450 *out_fibre_loc_table = fibre_loc_table;
2451 cpl_msg_indent_less();
2452 return CPL_ERROR_NONE;
2456_moo_localise_bandauto(moo_single *single,
2459 const char *backg_method,
2462 double backg_clip_kappalow,
2463 double backg_clip_kappaup,
2464 int backg_clip_niter,
2468 int *out_nb_detected,
2469 double *out_detected_noisemult_thresh)
2471 fibre *fibres_tab = NULL;
2472 double low_limit = NAN;
2473 double high_limit = NAN;
2475 double detect_noisemult_thresh = 1.0;
2476 int nb_detected = 0;
2477 cpl_table *detect_loc_table = NULL;
2478 cpl_table *fibre_loc_table = NULL;
2479 double klo = backg_clip_kappalow;
2480 double kup = backg_clip_kappaup;
2481 int polydeg = backg_polydeg;
2482 cpl_msg_info(
"moo_localise",
2483 "1) Detect centroid using "
2484 "central band (center=%d,width=%d)",
2486 cpl_msg_indent_more();
2488 if (strcmp(backg_method, MOO_LOCALISE_BACKG_METHOD_POLYNOMIAL) == 0) {
2489 cpl_msg_info(
"moo_localise",
2490 "background method %s "
2491 "background fit with degree %d kappa_lo %f kappa_up "
2493 backg_method, polydeg, klo, kup, backg_clip_niter);
2496 cpl_msg_info(
"moo_localise",
2497 "Estimate background with method %s using winhsize %d",
2498 backg_method, backg_winhsize);
2501 for (
int niter = 1; niter <= max_niter; niter++) {
2502 cpl_msg_info(__func__,
"do niter %d/%d: using %f range[%f,%f]", niter,
2503 max_niter, detect_noisemult_thresh, low_limit, high_limit);
2504 _moo_localise_band(single, cx, band_width, backg_method, backg_winhsize,
2505 backg_polydeg, backg_clip_kappalow,
2506 backg_clip_kappaup, backg_clip_niter,
2507 detect_noisemult_thresh, detect_niter, frac,
2508 nb_expected, &nb_detected, &detect_loc_table,
2511 if (nb_detected == nb_expected) {
2515 cpl_table_delete(detect_loc_table);
2516 cpl_table_delete(fibre_loc_table);
2517 detect_loc_table = NULL;
2518 fibre_loc_table = NULL;
2520 if (nb_detected > nb_expected) {
2521 low_limit = detect_noisemult_thresh;
2522 detect_noisemult_thresh *= 2;
2525 high_limit = detect_noisemult_thresh;
2526 detect_noisemult_thresh /= 2;
2528 if (!isnan(low_limit) && !isnan(high_limit)) {
2529 detect_noisemult_thresh = 0.5 * (low_limit + high_limit);
2532 if (nb_detected < nb_expected) {
2533 cpl_msg_error(
"moo_localise",
"Failure in detection mask computation");
2534 char *testname = NULL;
2536 testname = cpl_sprintf(
"DETECT_LOC_TABLE_%s.fits", single->extname);
2538 cpl_table_save(detect_loc_table, NULL, NULL, testname, CPL_IO_CREATE);
2542 cpl_table_new_column(detect_loc_table, MOO_DETECT_LOC_TABLE_YBCKGMIN,
2544 cpl_table_new_column(detect_loc_table, MOO_DETECT_LOC_TABLE_YBCKGMAX,
2546 cpl_table_new_column(detect_loc_table,
2547 MOO_DETECT_LOC_TABLE_FLUX_YBCKGMIN,
2549 cpl_table_new_column(detect_loc_table,
2550 MOO_DETECT_LOC_TABLE_FLUX_YBCKGMAX,
2552 cpl_table_new_column(detect_loc_table, MOO_DETECT_LOC_TABLE_YTMIN,
2554 cpl_table_new_column(detect_loc_table, MOO_DETECT_LOC_TABLE_YTMAX,
2556 cpl_table_new_column(detect_loc_table, MOO_DETECT_LOC_TABLE_FLUX_YTMIN,
2558 cpl_table_new_column(detect_loc_table, MOO_DETECT_LOC_TABLE_FLUX_YTMAX,
2560 cpl_table_new_column(detect_loc_table, MOO_DETECT_LOC_TABLE_YBARY,
2562 cpl_table_new_column(detect_loc_table, MOO_DETECT_LOC_TABLE_FLUX_YBARY,
2564 cpl_table_new_column(detect_loc_table, MOO_DETECT_LOC_TABLE_YWIDTH,
2566 cpl_table_new_column(detect_loc_table, MOO_DETECT_LOC_TABLE_FIBNUM,
2568 fibres_tab = (fibre *)cpl_calloc(nb_detected,
sizeof(fibre));
2570 for (
int f = 0; f < nb_detected; f++) {
2571 fibres_tab[f].health = MOO_FIBRES_TABLE_HEALTH_GOOD;
2574 int ny = cpl_table_get_nrow(fibre_loc_table);
2576 cpl_table_get_data_double(fibre_loc_table, MOO_FIBRE_LOC_TABLE_FLUX);
2578 cpl_table_get_data_double(fibre_loc_table, MOO_FIBRE_LOC_TABLE_Y);
2580 int size_y = hdrl_image_get_size_y(himg);
2582 cpl_vector *bandflux = cpl_vector_new(size_y);
2583 cpl_vector_fill(bandflux, NAN);
2584 for (
int i = 0; i < ny; i++) {
2585 int px = (int)tposy[i];
2586 double flux = tfluxes[i];
2587 cpl_vector_set(bandflux, px - 1, flux);
2589 double *fluxes = cpl_vector_get_data(bandflux);
2590 if (fibres_tab != NULL) {
2591 for (
int i = 0; i < nb_detected; i++) {
2592 int ymin = cpl_table_get_int(detect_loc_table,
2593 MOO_DETECT_LOC_TABLE_YMIN, i, NULL);
2594 int ymax = cpl_table_get_int(detect_loc_table,
2595 MOO_DETECT_LOC_TABLE_YMAX, i, NULL);
2596 int ysize = ymax - ymin + 1;
2597 cpl_vector *vfluxes = cpl_vector_new(ysize);
2598 cpl_vector *pos = cpl_vector_new(ysize);
2600 for (
int j = ymin; j <= ymax; j++) {
2601 double f = fluxes[j - 1];
2602 cpl_vector_set(vfluxes, j - ymin, f);
2603 cpl_vector_set(pos, j - ymin, j);
2606 cpl_bivector *points = cpl_bivector_wrap_vectors(pos, vfluxes);
2607 double center = NAN;
2612 cpl_bivector_unwrap_vectors(points);
2613 cpl_vector_delete(vfluxes);
2614 cpl_vector_delete(pos);
2616 double thresh_low = NAN, thresh_up = NAN, b_ylow = NAN, b_yup,
2618 _moo_profile_find_background_flux(bandflux, center, width, frac,
2619 &b_ylow, &b_yup, &thresh_low,
2621 _moo_profile_find_thresh_positions(bandflux, center, thresh_low,
2622 thresh_up, &y1, &y2);
2625 cpl_table_set_double(detect_loc_table, MOO_DETECT_LOC_TABLE_YTMIN,
2627 cpl_table_set_double(detect_loc_table, MOO_DETECT_LOC_TABLE_YTMAX,
2629 cpl_table_set_double(detect_loc_table,
2630 MOO_DETECT_LOC_TABLE_YBCKGMIN, i, b_ylow);
2631 cpl_table_set_double(detect_loc_table,
2632 MOO_DETECT_LOC_TABLE_YBCKGMAX, i, b_yup);
2634 double fb_ylow = _moo_get_flux(bandflux, b_ylow);
2636 double fb_yup = _moo_get_flux(bandflux, b_yup);
2638 cpl_table_set_double(detect_loc_table,
2639 MOO_DETECT_LOC_TABLE_FLUX_YBCKGMIN, i,
2641 cpl_table_set_double(detect_loc_table,
2642 MOO_DETECT_LOC_TABLE_FLUX_YBCKGMAX, i, fb_yup);
2643 cpl_table_set_double(detect_loc_table,
2644 MOO_DETECT_LOC_TABLE_FLUX_YTMIN, i,
2646 cpl_table_set_double(detect_loc_table,
2647 MOO_DETECT_LOC_TABLE_FLUX_YTMAX, i, thresh_up);
2649 points = _moo_extract_profile(bandflux, y1, y2);
2652 cpl_table_set_double(detect_loc_table, MOO_DETECT_LOC_TABLE_YBARY,
2654 double fbary = _moo_get_flux(bandflux, center);
2655 cpl_table_set_double(detect_loc_table,
2656 MOO_DETECT_LOC_TABLE_FLUX_YBARY, i, fbary);
2657 cpl_table_set_double(detect_loc_table, MOO_DETECT_LOC_TABLE_YWIDTH,
2659 cpl_bivector_delete(points);
2662 fibres_tab[fibidx].ymin = y1;
2663 fibres_tab[fibidx].ymax = y2;
2664 fibres_tab[fibidx].center = center;
2665 fibres_tab[fibidx].width = width;
2666 int fibnum = fibidx + 1;
2667 fibres_tab[fibidx].num = fibnum;
2668 cpl_table_set_int(detect_loc_table, MOO_DETECT_LOC_TABLE_FIBNUM, i,
2672#if MOO_DEBUG_LOCALISE_BAND
2675 cpl_sprintf(
"%s_DETECT_LOC_TABLE.fits", single->extname);
2676 cpl_table_save(detect_loc_table, NULL, NULL, testname, CPL_IO_CREATE);
2680 *out_nb_detected = nb_detected;
2681 *out_detected_noisemult_thresh = detect_noisemult_thresh;
2682 cpl_vector_delete(bandflux);
2683 cpl_table_delete(fibre_loc_table);
2684 cpl_table_delete(detect_loc_table);
2688static moo_loc_single *
2689_moo_localise_single(moo_single *single,
2690 moo_localise_params *params,
2691 cpl_table *loc_fibre_table,
2695 const char *filename,
2697 double goodptsfrac_min,
2701 moo_loc_single *res = NULL;
2702 fibre *fibres_tab = NULL;
2703 cpl_error_code status = CPL_ERROR_NONE;
2705 cpl_image *m_centroids = NULL;
2706 cpl_image *f_centroids = NULL;
2707 cpl_image *m_wlow = NULL;
2708 cpl_image *f_wlow = NULL;
2709 cpl_image *m_wup = NULL;
2710 cpl_image *f_wup = NULL;
2711 cpl_image *flags = NULL;
2712 cpl_table **all_tracked = NULL;
2713 cpl_ensure(single != NULL, CPL_ERROR_NULL_INPUT, NULL);
2714 cpl_ensure(loc_fibre_table != NULL, CPL_ERROR_NULL_INPUT, NULL);
2715 cpl_ensure(params != NULL, CPL_ERROR_NULL_INPUT, NULL);
2720 cpl_table_get_data_int(loc_fibre_table, MOO_FIBRES_TABLE_HEALTH);
2723 cpl_image *img = hdrl_image_get_image(himg);
2725 int didx = type + (ntas - 1) * 3;
2726 int nx = cpl_image_get_size_x(img);
2727 int band_width = params->centralwidth;
2728 int cx = params->centralpos;
2729 const char *backg_method = params->backg_method;
2731 int backg_polydeg = params->backg_polydeg[didx];
2732 int backg_winhsize = params->backg_winhsize[didx];
2733 double backg_clip_kappalow = params->backg_clip_kappalow[didx];
2734 double backg_clip_kappaup = params->backg_clip_kappaup[didx];
2735 int backg_clip_niter = params->backg_clip_niter[didx];
2736 double detect_noisemult_thresh = 1;
2737 int detect_niter = params->detect_niter[didx];
2738 float frac = params->relativethresh;
2739 double ref_snr = params->ref_snr[didx];
2740 int xgap_max = params->xgap_max;
2742 int nb_detected = 0;
2745 _moo_localise_bandauto(single, cx, band_width, backg_method,
2746 backg_winhsize, backg_polydeg,
2747 backg_clip_kappalow, backg_clip_kappaup,
2748 backg_clip_niter, detect_niter, frac, nb_good,
2749 &nb_detected, &detect_noisemult_thresh);
2750 cpl_ensure(fibres_tab != NULL, CPL_ERROR_UNSPECIFIED, NULL);
2755 res->header = cpl_propertylist_new();
2757 res->m_centroids = cpl_image_new(nx, nb_detected, CPL_TYPE_DOUBLE);
2758 res->f_centroids = cpl_image_new(nx, nb_detected, CPL_TYPE_DOUBLE);
2759 res->m_wlow = cpl_image_new(nx, nb_detected, CPL_TYPE_DOUBLE);
2760 res->f_wlow = cpl_image_new(nx, nb_detected, CPL_TYPE_DOUBLE);
2761 res->m_wup = cpl_image_new(nx, nb_detected, CPL_TYPE_DOUBLE);
2762 res->f_wup = cpl_image_new(nx, nb_detected, CPL_TYPE_DOUBLE);
2763 res->flags = cpl_image_new(nx, nb_detected, CPL_TYPE_INT);
2765 double wdiff_lim = params->wdiff_lim;
2766 double ydiff_lim = params->ydiff_lim;
2767 int xlim_hwin = params->loc_xlim_hwin;
2768 double xlim_fracmin = params->loc_xlim_fracmin;
2769 cpl_msg_info(
"moo_localise",
2770 "2) Loop on fibre localisation (tracking + fitting)");
2771 cpl_msg_indent_more();
2772 cpl_msg_info(
"moo_localise",
"min_snr %f xgap_max %d goodptsfrac-min %f",
2773 ref_snr, xgap_max, goodptsfrac_min);
2775 all_tracked = cpl_calloc(nb_detected,
sizeof(cpl_table *));
2779#pragma omp parallel default(none) \
2780 shared(all_tracked, nb_detected, fibres_tab, himg, cx, degpoly, wdiff_lim, \
2781 ydiff_lim, xlim_hwin, xlim_fracmin, frac, res, nx, ref_snr, \
2782 xgap_max, goodptsfrac_min) reduction(+ : nb_failed, nb_broken)
2786 for (
int f = 1; f <= nb_detected; f++) {
2788 cpl_error_code lstatus = CPL_ERROR_NONE;
2789 fibre *fib = &(fibres_tab[f - 1]);
2792 _moo_localise_fibre(fib, himg, cx, degpoly, wdiff_lim,
2793 ydiff_lim, frac, ref_snr, xgap_max,
2794 goodptsfrac_min, xlim_hwin, xlim_fracmin,
2795 res, &all_tracked[f - 1]);
2796 if (lstatus != CPL_ERROR_NONE) {
2799 else if (fib->health == MOO_FIBRES_TABLE_HEALTH_NEWLY_BROKEN) {
2801 for (
int i = 1; i <= nx; i++) {
2802 cpl_image_set(res->m_centroids, i, num, NAN);
2803 cpl_image_set(res->m_wlow, i, num, NAN);
2804 cpl_image_set(res->m_wup, i, num, NAN);
2805 cpl_image_set(res->flags, i, num, MOONS_FLAG_BROKEN_FIBRE);
2806 cpl_image_set(res->f_centroids, i, num, NAN);
2807 cpl_image_set(res->f_wlow, i, num, NAN);
2808 cpl_image_set(res->f_wup, i, num, NAN);
2810 cpl_msg_info(
"moo_localise",
2811 "New broken fibre %d/%d : goodfrac %f", num,
2812 nb_detected, fib->goodfrac);
2818#if MOO_DEBUG_LOCALISE_TRACKING
2820 char *name = cpl_sprintf(
"%s_TRACKING_LOC_TABLE.fits", res->extname);
2821 cpl_table *test = NULL;
2823 for (
int i = 0; i < nb_detected; i++) {
2824 cpl_table *t = all_tracked[i];
2826 test = cpl_table_duplicate(t);
2832 for (
int i = first; i < nb_detected; i++) {
2833 cpl_table *t = all_tracked[i];
2835 moo_table_append(test, t);
2838 cpl_table_save(test, NULL, NULL, name, CPL_IO_CREATE);
2839 cpl_table_delete(test);
2845 int nb_localise = nb_detected - nb_broken;
2846 cpl_msg_info(
"moo_localise",
2847 "Number of detected fibres after localisation : %d",
2849 cpl_msg_indent_less();
2851 if (nb_failed > 0) {
2852 status = CPL_ERROR_UNSPECIFIED;
2853 cpl_error_set(__func__, status);
2857 if ((nb_good == nb_detected) || (nb_good == nb_localise)) {
2858 m_centroids = cpl_image_new(nx, nb, CPL_TYPE_DOUBLE);
2859 f_centroids = cpl_image_new(nx, nb, CPL_TYPE_DOUBLE);
2860 m_wlow = cpl_image_new(nx, nb, CPL_TYPE_DOUBLE);
2861 f_wlow = cpl_image_new(nx, nb, CPL_TYPE_DOUBLE);
2862 m_wup = cpl_image_new(nx, nb, CPL_TYPE_DOUBLE);
2863 f_wup = cpl_image_new(nx, nb, CPL_TYPE_DOUBLE);
2864 flags = cpl_image_new(nx, nb, CPL_TYPE_INT);
2866 for (
int f = 0; f < nb; f++) {
2867 int idx = cpl_array_get_cplsize(indexes, f, NULL);
2868 int h = health[idx];
2871 cpl_table_set_int(loc_fibre_table, MOO_FIBRES_TABLE_INDEXEXT, idx,
2874 if (h == MOO_FIBRES_TABLE_HEALTH_BROKEN) {
2875 for (
int i = 1; i <= nx; i++) {
2876 cpl_image_set(m_centroids, i, num, NAN);
2877 cpl_image_set(m_wlow, i, num, NAN);
2878 cpl_image_set(m_wup, i, num, NAN);
2879 cpl_image_set(flags, i, num, MOONS_FLAG_BROKEN_FIBRE);
2880 cpl_image_set(f_centroids, i, num, NAN);
2881 cpl_image_set(f_wlow, i, num, NAN);
2882 cpl_image_set(f_wup, i, num, NAN);
2886 int fh = fibres_tab[fib_idx].health;
2887 if ((nb_good == nb_detected) &&
2888 (fh == MOO_FIBRES_TABLE_HEALTH_NEWLY_BROKEN)) {
2889 cpl_table_set_int(loc_fibre_table, MOO_FIBRES_TABLE_HEALTH,
2893 while (fibres_tab[fib_idx].health ==
2894 MOO_FIBRES_TABLE_HEALTH_NEWLY_BROKEN) {
2898 int fnum = fibres_tab[fib_idx].num;
2900 goodfrac[idx] = fibres_tab[fib_idx].goodfrac;
2902 for (
int i = 1; i <= nx; i++) {
2905 cpl_image_get(res->m_centroids, i, fnum, &rej);
2907 cpl_image_get(res->f_centroids, i, fnum, &rej);
2908 double mwlo = cpl_image_get(res->m_wlow, i, fnum, &rej);
2909 double mwu = cpl_image_get(res->m_wup, i, fnum, &rej);
2910 double fwlo = cpl_image_get(res->f_wlow, i, fnum, &rej);
2911 double fwu = cpl_image_get(res->f_wup, i, fnum, &rej);
2912 double flag = cpl_image_get(res->flags, i, fnum, &rej);
2913 cpl_image_set(m_centroids, i, num, mcentroid);
2914 cpl_image_set(m_wlow, i, num, mwlo);
2915 cpl_image_set(m_wup, i, num, mwu);
2916 cpl_image_set(flags, i, num, flag);
2917 cpl_image_set(f_centroids, i, num, fcentroid);
2918 cpl_image_set(f_wlow, i, num, fwlo);
2919 cpl_image_set(f_wup, i, num, fwu);
2924 cpl_image_delete(res->m_centroids);
2925 res->m_centroids = m_centroids;
2926 cpl_image_delete(res->f_centroids);
2927 res->f_centroids = f_centroids;
2928 cpl_image_delete(res->m_wlow);
2929 res->m_wlow = m_wlow;
2930 cpl_image_delete(res->m_wup);
2932 cpl_image_delete(res->flags);
2934 cpl_image_delete(res->f_wlow);
2935 res->f_wlow = f_wlow;
2936 cpl_image_delete(res->f_wup);
2940 cpl_error_set_message(
2941 "moo_localise", CPL_ERROR_UNSPECIFIED,
2942 "Localise fibres (%d) and expected fibres (%d) doesnt match",
2943 nb_localise, nb_good);
2944 status = CPL_ERROR_UNSPECIFIED;
2947 cpl_free(fibres_tab);
2950 if (all_tracked != NULL) {
2951 for (
int i = 0; i < nb_detected; i++) {
2952 if (all_tracked[i] != NULL) {
2953 cpl_table_delete(all_tracked[i]);
2956 cpl_free(all_tracked);
2958 if (status != CPL_ERROR_NONE) {
2965_moo_localise_create_guess(moo_det *det,
2966 moo_localise_params *params,
2967 const char *locname,
2970 cpl_array *indexes = NULL;
2971 cpl_errorstate prestate = cpl_errorstate_get();
2973 cpl_ensure(det != NULL, CPL_ERROR_ILLEGAL_INPUT, NULL);
2974 cpl_ensure(params != NULL, CPL_ERROR_ILLEGAL_INPUT, NULL);
2975 cpl_ensure(locname != NULL, CPL_ERROR_ILLEGAL_INPUT, NULL);
2978 cpl_ensure(fibres_table != NULL, CPL_ERROR_ILLEGAL_INPUT, NULL);
2980 const char *filename = locname;
2981 moo_loc *loc = NULL;
2986 cpl_msg_info(
"moo_localise",
"Create GUESS localisation");
2987 cpl_msg_indent_more();
2989 cpl_table *loc_fibre_table = cpl_table_duplicate(fibres_table);
2991 loc->fibre_table = loc_fibre_table;
2993 cpl_table_new_column(loc_fibre_table, MOO_FIBRES_TABLE_INDEXEXT,
2995 const char *goodfracname[] = { MOO_FIBRES_TABLE_GOODPTSFRAC_RI,
2996 MOO_FIBRES_TABLE_GOODPTSFRAC_YJ,
2997 MOO_FIBRES_TABLE_GOODPTSFRAC_H };
2999 for (i = 1; i <= 2; i++) {
3001 int nbtotal = cpl_array_get_size(indexes);
3003 for (j = 0; j < 3; j++) {
3004 int idx = (i - 1) * 3 + j;
3005 double goodptsfrac_min = params->goodptsfrac_min[idx] * 100.;
3006 int dx = params->polydeg[idx];
3009 cpl_table_get_data_float(loc_fibre_table, goodfracname[j]);
3012 cpl_msg_info(
"moo_localise",
3013 "Localising %s : Total number of fibres from "
3016 cpl_msg_indent_more();
3017 moo_loc_single *ls = NULL;
3019 moo_try_check(ls = _moo_localise_single(s1, params,
3021 nbtotal, j, i, filename,
3022 dx, goodptsfrac_min,
3027 moo_loc_single_compute_qc_guess(ls, dx);
3030 cpl_msg_indent_less();
3034 cpl_array_delete(indexes);
3037 cpl_msg_indent_less();
3038 cpl_table_select_all(loc_fibre_table);
3039 int nb_newly_broken =
3040 cpl_table_and_selected_int(loc_fibre_table, MOO_FIBRES_TABLE_HEALTH,
3042 MOO_FIBRES_TABLE_HEALTH_NEWLY_BROKEN);
3044 if (nb_newly_broken > 0) {
3045 indexes = cpl_table_where_selected(loc_fibre_table);
3046 for (i = 0; i < nb_newly_broken; i++) {
3047 int idx = cpl_array_get_cplsize(indexes, i, NULL);
3048 cpl_table_set_int(loc_fibre_table, MOO_FIBRES_TABLE_HEALTH, idx,
3049 MOO_FIBRES_TABLE_HEALTH_BROKEN);
3051 cpl_array_delete(indexes);
3057 if (!cpl_errorstate_is_equal(prestate)) {
3058 if (indexes != NULL) {
3059 cpl_array_delete(indexes);
3094 const cpl_frame *guess_loc,
3095 moo_localise_params *params,
3096 const char *locname)
3098 cpl_ensure(det != NULL, CPL_ERROR_NULL_INPUT, NULL);
3099 cpl_ensure(params != NULL, CPL_ERROR_NULL_INPUT, NULL);
3101 cpl_errorstate prestate = cpl_errorstate_get();
3103 moo_loc *result = NULL;
3104 moo_loc *guess = NULL;
3109 if (guess_loc != NULL) {
3111 moo_try_check(result = _moo_localise_from_guess(det, guess, params,
3112 locname, badpix_level),
3116 moo_try_check(result = _moo_localise_create_guess(det, params, locname,
3123 if (!cpl_errorstate_is_equal(prestate)) {
#define MOO_BADPIX_OUTSIDE_DATA_RANGE
#define MOO_BADPIX_COSMETIC
moo_single * moo_det_load_single(moo_det *self, moo_detector_type type, int num, int level)
Load the type part in DET and return it.
cpl_table * moo_det_get_fibre_table(moo_det *self)
Get the FIBRE TABLE in DET.
const char * moo_detector_get_extname(moo_detector_type type, int ntas)
Get the extension name of a detector.
enum _moo_detector_type_ moo_detector_type
The type code type.
int moo_fibres_table_filter_health(cpl_table *table)
Filter bad health data in fibre table.
cpl_array * moo_fibres_table_get_spectro_indexext(cpl_table *table, int num)
get the index of a spectro in the fibre table sort by spetcro,indexext
cpl_array * moo_fibres_table_get_spectro_index(cpl_table *table, int num)
get the index of a spectro in the fibre table sort by index on the slit
cpl_error_code moo_fibres_table_add_locguess_cols(cpl_table *table)
add localise guess additional columns
void moo_loc_single_delete(moo_loc_single *self)
Delete a moo_loc_single.
cpl_image * moo_loc_single_get_f_wup(moo_loc_single *self)
Get image of width low.
cpl_image * moo_loc_single_get_f_centroids(moo_loc_single *self)
Get image of fit centroids.
moo_loc_single * moo_loc_single_create(const char *filename, const char *extname)
Create a new moo_loc_single from the given LOC filename.
cpl_image * moo_loc_single_get_f_wlo(moo_loc_single *self)
Get image of width low.
moo_loc * moo_loc_create(const char *filename)
Create a new empty LOC filename.
moo_loc_single * moo_loc_get_single(moo_loc *self, moo_detector_type type, int ntas)
Get the type part in LOC and return it.
cpl_error_code moo_loc_add_fibre_table(moo_loc *self, cpl_table *fibre_table)
Add fibre table to LOC filename and update moo_loc structure.
moo_loc * moo_loc_load(const cpl_frame *locframe)
Load a LOC frame and create a moo_loc.
cpl_error_code moo_loc_add_single(moo_loc *self, moo_loc_single *single, moo_detector_type type, int ntas, int keep_points)
Add LOC_SINGLE extension to LOC filename and update moo_loc structure.
cpl_table * moo_loc_get_fibre_table(moo_loc *self)
Get the FIBRE TABLE in LOC.
void moo_loc_delete(moo_loc *self)
Delete a moo_loc.
hdrl_image * moo_single_get_image(moo_single *self)
Get the IMAGE part (DATA,ERR) of single DET.
moo_loc * moo_localise(moo_det *det, const cpl_frame *guess_loc, moo_localise_params *params, const char *locname)
To localise the centroid of fibre spectrum on frames.
cpl_error_code moo_qc_set_missingfib(cpl_propertylist *plist, int num, const char *val)
Set the QC.MISSINGFIB value.
cpl_error_code moo_qc_set_nmissingfib(cpl_propertylist *plist, int val)
Set the QC.NMISSINGFIB value.
cpl_error_code moo_qc_set_qc_detect_noisemult(cpl_propertylist *plist, double val)
Set the QC.DETECT.NOISEMULT value.
cpl_error_code moo_gaussian_eval_inv(double y, double x0, double sigma, double offset, double area, double *x1, double *x2)
Find the x positions of the gaussian at the given y position.
double moo_vector_get_min(const cpl_vector *v, int *flags)
Find minimum values in a vector using flags.
double moo_gaussian_eval(double x, double x0, double sigma, double offset, double area)
Evaluate the gaussian at the given x position.
cpl_error_code moo_gaussian_fit(cpl_bivector *points, cpl_fit_mode fit_pars, double *center, double *width, double *background, double *area)
Fit the data with a gaussian.
double moo_vector_get_max(const cpl_vector *v, int *flags)
Find maximum values in a vector using flags.
cpl_error_code moo_tchebychev_fit(cpl_bivector *data, int *flag, int degree, double xmin, double xmax, double ymin, double ymax)
Computes Tchebitchev transformation of data.
double moo_vector_get_percentile(cpl_vector *v, double f)
Get percentile of input vector.
cpl_error_code moo_barycenter_fit(cpl_bivector *points, double *center, double *width)
Fit positions using weighted fluxes.