35#include "cr2res_qc_lines.h"
36#include "cr2res_trace.h"
37#include "cr2res_dfs.h"
38#include "cr2res_extract.h"
40#include "cr2res_calib.h"
41#include "cr2res_detlin.h"
42#include "cr2res_wave.h"
43#include "cr2res_pfits.h"
49static int cr2res_qc_wave_line_intens(
50 const cpl_bivector * spec,
75 const cpl_image * ima1,
76 const cpl_image * ima2,
85 if (ima1 == NULL || ima2 == NULL || ndit < 1)
return -1.0 ;
92 if ((ima = cpl_image_subtract_create(ima2, ima1)) == NULL)
return -1.0 ;
95 cpl_flux_get_noise_window(ima, NULL, hsize, nsamples, &ron, NULL) ;
96 cpl_image_delete(ima) ;
112 const hdrl_imagelist * hdrl_coeffs,
118 double qc_meda, qc_medb, qc_medc, qc_meda_err ;
121 if (hdrl_coeffs==NULL || meda==NULL || medb==NULL || medc==NULL ||
125 qc_meda = cpl_image_get_median(
127 qc_medb = cpl_image_get_median(
129 qc_medc = cpl_image_get_median(
131 qc_meda_err = cpl_image_get_median(
134 if (cpl_error_get_code())
return -1 ;
136 if (isnan(qc_meda) || isnan(qc_medb) || isnan(qc_medc))
return -1 ;
137 if (isnan(qc_meda_err)) qc_meda_err = -1.0 ;
142 *meda_err = qc_meda_err ;
157 const hdrl_imagelist * hdrl_coeffs,
163 double qc_detlin_median, qc_detlin_min, qc_detlin_max ;
166 hdrl_value value = {CR2RES_NONLIN_LEVEL, 0};
171 if (hdrl_coeffs==NULL || min_level==NULL || max_level==NULL)
return -1.0 ;
188 if (cpl_msg_get_level() == CPL_MSG_DEBUG){
191 CPL_TYPE_DOUBLE, NULL, CPL_IO_CREATE);
194 tmpmask = cpl_mask_new(width, height);
196 (
double)CR2RES_NONLIN_LEVEL,
197 (
double)CR2RES_NONLIN_LEVEL * (1.0 + (bpm_thresh/100)),
200 cpl_mask_delete(tmpmask);
208 cpl_msg_info(__func__,
"BPM has %d pix rejected",
209 (
int)cpl_mask_count(tmpmask));
212 if (isnan(qc_detlin_median) ||
213 isnan(qc_detlin_min) ||
214 isnan(qc_detlin_max)) {
215 cpl_mask_delete(tmpmask);
219 *min_level = qc_detlin_min ;
220 *max_level = qc_detlin_max ;
222 return qc_detlin_median ;
236 const cpl_table * tw,
241 int * order_idx_vals ;
242 const cpl_array * slit_frac ;
244 double * order_pos_loc ;
245 int i, j, cur_order, nb_order_idx_vals, n_full ;
249 if (tw == NULL || order_nb==NULL || order_pos==NULL || nbvals==NULL)
256 nrows = cpl_table_get_nrow(tw) ;
257 if (nrows <= 0)
return 0 ;
265 for (i=0 ; i<nb_order_idx_vals ; i++) {
266 cur_order = order_idx_vals[i] ;
268 for (j=0 ; j<nrows ; j++) {
269 if (cpl_table_get(tw, CR2RES_COL_ORDER, j, NULL) == cur_order) {
270 slit_frac = cpl_table_get_array(tw, CR2RES_COL_SLIT_FRACTION,j);
272 CR2RES_DECKER_NONE) {
282 order_nb_loc = cpl_malloc(n_full *
sizeof(
int)) ;
283 order_pos_loc = cpl_malloc(n_full *
sizeof(
double)) ;
289 for (i=0 ; i<nb_order_idx_vals ; i++) {
290 cur_order = order_idx_vals[i] ;
293 for (j=0 ; j<nrows ; j++) {
294 if (cpl_table_get(tw, CR2RES_COL_ORDER, j, NULL) == cur_order) {
295 slit_frac = cpl_table_get_array(tw, CR2RES_COL_SLIT_FRACTION,j);
297 CR2RES_DECKER_NONE) {
298 order_nb_loc[n_full] = cur_order ;
300 cpl_msg_debug(__func__,
"Order %d Pos : %g",
301 order_nb_loc[n_full], order_pos_loc[n_full]) ;
309 cpl_free(order_idx_vals);
313 *order_nb = order_nb_loc ;
314 *order_pos = order_pos_loc ;
326 const cpl_table * trace)
329 int * order_idx_values, nb_order_idx_values, central_order_idx, i;
330 int * traces, nb_traces;
331 double qc_trace_center_y ;
334 if (trace == NULL)
return -1.0 ;
337 qc_trace_center_y = 0;
340 &nb_order_idx_values);
341 array = cpl_array_wrap_int(order_idx_values, nb_order_idx_values);
344 central_order_idx = cpl_array_get_median(array);
345 cpl_array_unwrap(array);
349 for (i = 0; i < nb_traces; i++) {
352 CR2RES_DETECTOR_SIZE);
353 qc_trace_center_y += cpl_vector_get_mean(vector);
354 cpl_vector_delete(vector);
358 qc_trace_center_y /= nb_traces;
360 cpl_free(order_idx_values);
363 return qc_trace_center_y ;
376 const cpl_table * extracted)
378 cpl_array * col_names ;
380 const double * pspec ;
381 const double * pspec_err ;
385 cpl_size ncols, i, j, nrows, nmeds ;
386 int trace_nb, order ;
389 if (extracted == NULL)
return -1.0 ;
392 col_names = cpl_table_get_column_names(extracted);
393 ncols = cpl_table_get_ncol(extracted) ;
395 cpl_array_delete(col_names) ;
401 meds = cpl_vector_new(ncols);
403 for (i = 0; i < ncols; i++) {
405 const char *col_name;
406 col_name = cpl_array_get_string(col_names, i);
409 if (col_type != NULL && !strcmp(col_type, CR2RES_COL_SPEC_SUFFIX)) {
415 pspec = cpl_table_get_data_double_const(extracted, col_name) ;
416 pspec_err = cpl_table_get_data_double_const(extracted, err_col) ;
418 nrows = cpl_table_get_nrow(extracted) ;
419 snrs = cpl_vector_new(nrows) ;
420 for (j=0 ; j<nrows ; j++) {
422 if (fabs(pspec_err[j]) > 1e-3) {
423 snr = pspec[j]/pspec_err[j] ;
425 cpl_vector_set(snrs, j, snr) ;
427 cpl_vector_set(meds, nmeds, cpl_vector_get_median(snrs)) ;
429 cpl_vector_delete(snrs) ;
432 if (col_type != NULL) cpl_free(col_type) ;
434 cpl_array_delete(col_names) ;
436 cpl_vector_set_size(meds, nmeds);
437 med = cpl_vector_get_median(meds) ;
438 cpl_vector_delete(meds);
441 return med/sqrt(180) ;
453 const cpl_table * tw,
461 CR2RES_DETECTOR_SIZE)) == NULL) {
462 cpl_msg_warning(__func__,
463 "QC CENTWL - cannot find wl solution for order/trace %d/%d",
464 order_idx, CR2RES_QC_TRACE) ;
467 wl_central = cpl_vector_get(wls, (
int)(CR2RES_DETECTOR_SIZE/2)) ;
468 cpl_vector_delete(wls) ;
481 const cpl_table * tw,
488 if (tw == NULL)
return -1.0 ;
492 CR2RES_DETECTOR_SIZE)) == NULL) {
493 cpl_msg_warning(__func__,
494 "QC DISPWL - cannot find wl solution for order/trace %d/%d",
495 order_idx, CR2RES_QC_TRACE) ;
498 nbins = cpl_vector_get_size(wls) ;
499 wl_disp = (cpl_vector_get(wls, nbins-1) - cpl_vector_get(wls, 0)) / nbins;
500 cpl_vector_delete(wls) ;
521 for (i=0 ; i< QC_LINES_NUMBER ; i++)
522 if (qc_lines[i] > wmin && qc_lines[i] < wmax) nb_found++ ;
524 if (nb_found == 0)
return NULL ;
527 lines = cpl_vector_new(nb_found);
531 for (i=0 ; i< QC_LINES_NUMBER ; i++)
532 if (qc_lines[i] > wmin && qc_lines[i] < wmax)
533 cpl_vector_set(lines, nb_found++, qc_lines[i]) ;
547 const cpl_bivector * spec,
549 double * peak_height)
554 const cpl_vector * wave;
555 const cpl_vector * flux;
560 cpl_size window_width;
564 if (spec == NULL || peak_height == NULL)
return -1.0;
567 *peak_height = -1.0 ;
569 wave = cpl_bivector_get_x_const(spec);
570 flux = cpl_bivector_get_y_const(spec);
574 window_width = CR2RES_QC_WINDOW;
577 tmp = cpl_vector_duplicate(wave);
578 cpl_vector_subtract_scalar(tmp, wl);
579 cpl_vector_multiply(tmp, tmp);
580 pixel_pos = cpl_vector_get_minpos(tmp);
581 cpl_vector_delete(tmp);
584 if (pixel_pos == 0 || pixel_pos == cpl_vector_get_size(wave))
return -1.0;
588 if (cr2res_wave_fit_single_line(flux, unc, pixel_pos, window_width, 1, 0,
597 fwhm = cpl_vector_get(result, 1);
600 *peak_height = cpl_vector_get(result, 2) ;
601 cpl_vector_delete(result);
613 const cpl_bivector * spec)
615 cpl_bivector * intens_bgd ;
616 cpl_vector * ref_lines ;
625 wmin = cpl_vector_get(cpl_bivector_get_x_const(spec), 0);
626 wmax = cpl_vector_get(cpl_bivector_get_x_const(spec),
627 cpl_bivector_get_size(spec)-1) ;
629 if (ref_lines == NULL)
return NULL ;
632 nall = cpl_vector_get_size(ref_lines);
633 intens_bgd = cpl_bivector_new(nall) ;
634 pintens = cpl_bivector_get_x_data(intens_bgd) ;
635 pbgs = cpl_bivector_get_y_data(intens_bgd) ;
636 for (i=0 ; i < nall ; i++) {
638 curr_refline = cpl_vector_get(ref_lines, i) ;
639 cr2res_qc_wave_line_intens(spec, curr_refline,
640 &(pintens[i]), &(pbgs[i]));
641 cpl_msg_debug(__func__,
"Ref : %g, intens: %g, Bgd : %g",
642 curr_refline, pintens[i], pbgs[i]) ;
644 cpl_vector_delete(ref_lines) ;
657 const cpl_bivector * spec)
659 cpl_vector * ref_lines ;
660 cpl_vector * ref_lines_intens ;
661 double wmin, wmax, intens_med, intens, bgd;
665 wmin = cpl_vector_get(cpl_bivector_get_x_const(spec), 0);
666 wmax = cpl_vector_get(cpl_bivector_get_x_const(spec),
667 cpl_bivector_get_size(spec)-1) ;
669 if (ref_lines == NULL)
return -1.0 ;
675 nall = cpl_vector_get_size(ref_lines);
676 ref_lines_intens = cpl_vector_new(nall) ;
677 for (i=0 ; i < nall ; i++) {
678 cr2res_qc_wave_line_intens(spec, cpl_vector_get(ref_lines, i),
680 if (intens-bgd > 0.0) {
681 cpl_vector_set(ref_lines_intens, n, intens-bgd);
685 cpl_vector_delete(ref_lines) ;
687 cpl_vector_delete(ref_lines_intens) ;
690 cpl_vector_set_size(ref_lines_intens, n);
691 cpl_msg_info(__func__,
692 "Using %i of %i lines to estimate Intensity", n, nall);
696 intens_med = cpl_vector_get_median(ref_lines_intens) ;
697 cpl_vector_delete(ref_lines_intens) ;
711 const cpl_bivector * spec,
714 cpl_vector * ref_lines ;
715 cpl_vector * ref_lines_fwhm ;
716 cpl_vector * ref_lines_pos ;
717 double wmin, wmax, peak_height, min_fwhm_val,
723 if (spec == NULL || wl == NULL)
return -1.0 ;
729 wmin = cpl_vector_get(cpl_bivector_get_x_const(spec), 0);
730 wmax = cpl_vector_get(cpl_bivector_get_x_const(spec),
731 cpl_bivector_get_size(spec)-1) ;
733 if (ref_lines == NULL)
return -1.0 ;
739 nall = cpl_vector_get_size(ref_lines);
740 ref_lines_fwhm = cpl_vector_new(nall) ;
741 ref_lines_pos = cpl_vector_new(nall) ;
742 for (i=0 ; i<cpl_vector_get_size(ref_lines) ; i++) {
751 if (fwhm > 0.1 && fwhm < CR2RES_QC_WINDOW && peak_height > 0
752 && peak_height<CR2RES_SATURATED_LINES_THRESH) {
753 cpl_vector_set(ref_lines_fwhm, n, fwhm);
754 cpl_vector_set(ref_lines_pos, n, cpl_vector_get(ref_lines, i));
758 cpl_vector_delete(ref_lines) ;
760 cpl_vector_delete(ref_lines_fwhm) ;
761 cpl_vector_delete(ref_lines_pos) ;
764 cpl_vector_set_size(ref_lines_fwhm, n);
765 cpl_vector_set_size(ref_lines_pos, n);
768 idx = cpl_vector_get_minpos(ref_lines_fwhm) ;
770 cpl_vector_delete(ref_lines_fwhm) ;
771 cpl_vector_delete(ref_lines_pos) ;
774 min_fwhm_val = cpl_vector_get(ref_lines_fwhm, idx) ;
775 min_fwhm_pos = cpl_vector_get(ref_lines_pos, idx) ;
776 cpl_vector_delete(ref_lines_fwhm) ;
777 cpl_vector_delete(ref_lines_pos) ;
779 cpl_msg_info(__func__,
"Using the smallest FWHM %g of line at %g nm",
780 min_fwhm_val, min_fwhm_pos) ;
784 return min_fwhm_val ;
797 const cpl_image * ima,
798 const cpl_table * tw,
802 const double * pima ;
804 int i, j, nb_over, nb_total ;
807 if (ima == NULL || tw == NULL)
return -1.0 ;
808 if (cpl_image_get_size_x(ima) != CR2RES_DETECTOR_SIZE ||
809 cpl_image_get_size_y(ima) != CR2RES_DETECTOR_SIZE) {
812 pima = cpl_image_get_data_double_const(ima) ;
816 CR2RES_DETECTOR_SIZE);
817 plabel = cpl_image_get_data_int(labels) ;
819 nb_over = nb_total = 0 ;
821 for (j=0 ; j<CR2RES_DETECTOR_SIZE ; j++) {
822 for (i=0 ; i<CR2RES_DETECTOR_SIZE ; i++) {
823 if (plabel[i+j*CR2RES_DETECTOR_SIZE] == order_idx &&
824 !cpl_image_is_rejected(ima, i+1, j+1)) {
826 if (pima[i+j*CR2RES_DETECTOR_SIZE] >
827 CR2RES_DETECTOR_OVEREXP_THRESH) {
833 cpl_image_delete(labels) ;
834 if (nb_total == 0)
return -1.0 ;
835 return (
double)nb_over/(double)nb_total ;
846 const cpl_table * extracted)
851 cpl_vector * vector, *vector2;
855 if (extracted == NULL)
return -1.0 ;
860 data = cpl_table_get_data_double((cpl_table*) extracted, colname);
863 if (cpl_error_get_code() == CPL_ERROR_DATA_NOT_FOUND) {
869 nrows = cpl_table_get_nrow(extracted);
870 size = CR2RES_QC_SIZE;
871 if (nrows < size) size = nrows;
873 vector = cpl_vector_wrap(nrows, data);
874 vector2 = cpl_vector_extract(vector, (nrows - size)/ 2, (nrows + size)
876 qc_signal = cpl_vector_get_median(vector2);
878 cpl_vector_unwrap(vector);
879 cpl_vector_delete(vector2);
893 const cpl_table * extracted,
900 double wl_start, wl_stop ;
901 cpl_vector * vector, *vector2;
902 int nrows, wl_start_index, wl_stop_index, i ;
905 if (extracted == NULL)
return -1.0 ;
911 nrows = cpl_table_get_nrow(extracted);
914 if (!strcmp(setting,
"Y1029")) {
917 }
else if (!strcmp(setting,
"H1559")) {
920 }
else if (!strcmp(setting,
"K2217")) {
923 }
else if (!strcmp(setting,
"L3377")) {
926 }
else if (!strcmp(setting,
"M4266")) {
929 }
else if (!strcmp(setting,
"Y1028")) {
932 }
else if (!strcmp(setting,
"J1228")) {
935 }
else if (!strcmp(setting,
"H1567")) {
938 }
else if (!strcmp(setting,
"K2148")) {
943 if (wl_start < 0.0) {
944 cpl_msg_info(__func__,
945 "QC Standard Flux : No WL specified for setting %s", setting) ;
951 ext_data = cpl_table_get_data_double((cpl_table*) extracted, colname);
954 wl_data = cpl_table_get_data_double((cpl_table*) extracted, colname);
956 if (cpl_error_get_code() == CPL_ERROR_DATA_NOT_FOUND) {
961 wl_start_index = -1 ;
962 for (i=0 ; i<nrows ; i++) {
963 if (wl_data[i] > wl_start && wl_start_index < 0) {
970 for (i=0 ; i<nrows ; i++) {
971 if (wl_data[i] < wl_stop && wl_stop_index < 0) {
977 wl_stop_index = wl_start_index + CR2RES_QC_SIZE ;
980 if (wl_start_index < 0 || wl_stop_index >= cpl_table_get_nrow(extracted)) {
981 cpl_msg_warning(__func__,
982 "QC Standard Flux : Specified WL out of range %g-%g",
986 cpl_msg_info(__func__,
987 "QC STD FLUX : Trace %d Order %d WL start %g, idx range: [%d-%d]",
988 CR2RES_QC_TRACE, CR2RES_QC_ORDER, wl_start, wl_start_index,
991 vector = cpl_vector_wrap(nrows, ext_data);
992 vector2 = cpl_vector_extract(vector, wl_start_index, wl_stop_index, 1) ;
993 qc_flux = cpl_vector_get_mean(vector2);
994 cpl_vector_unwrap(vector);
995 cpl_vector_delete(vector2);
1011 const cpl_table * tw,
1012 const cpl_table * extracted,
1013 int ** out_order_idx_values,
1014 int * out_nb_order_idx_values)
1016 int * order_idx_values ;
1017 int nb_order_idx_values ;
1018 cpl_bivector * my_spec,
1024 if (tw==NULL || extracted==NULL || out_order_idx_values==NULL ||
1025 out_nb_order_idx_values==NULL)
return NULL ;
1029 &nb_order_idx_values) ;
1032 snrs = cpl_malloc(nb_order_idx_values *
sizeof(
double)) ;
1035 for (i=0 ; i<nb_order_idx_values ; i++) {
1038 order_idx_values[i], 1, &my_spec, &my_spec_err) == 0) {
1040 cpl_bivector_get_y(my_spec),
1041 cpl_bivector_get_y(my_spec_err));
1042 cpl_bivector_delete(my_spec);
1043 cpl_bivector_delete(my_spec_err);
1051 *out_order_idx_values = order_idx_values ;
1052 *out_nb_order_idx_values = nb_order_idx_values ;
1069 cpl_vector *snr_spec;
1073 snr_spec = cpl_vector_duplicate(spec);
1074 myerr = cpl_vector_duplicate(err);
1076 for (j=0 ; j<cpl_vector_get_size(myerr) ; j++) {
1078 err_val = cpl_vector_get(myerr,j) ;
1079 if (fabs(err_val) < 1e-3 || isnan(err_val)) {
1080 cpl_vector_set(myerr, j, 1.0) ;
1084 cpl_vector_divide(snr_spec, myerr) ;
1086 snr = cpl_vector_get_median(snr_spec) ;
1087 if (isnan(snr)) snr = -1.0 ;
1088 cpl_vector_delete(snr_spec) ;
1089 cpl_vector_delete(myerr) ;
1104 const cpl_table * tw,
1105 const cpl_table * extracted,
1106 int ** out_order_idx_values,
1107 int * out_nb_order_idx_values)
1109 int * order_idx_values ;
1110 int nb_order_idx_values ;
1111 cpl_bivector * my_spec,
1117 if (tw==NULL || extracted==NULL || out_order_idx_values==NULL ||
1118 out_nb_order_idx_values==NULL)
return NULL ;
1122 &nb_order_idx_values) ;
1125 snrs = cpl_malloc(nb_order_idx_values *
sizeof(
double)) ;
1128 for (i=0 ; i<nb_order_idx_values ; i++) {
1131 order_idx_values[i], 1, &my_spec, &my_spec_err) == 0) {
1133 cpl_bivector_get_y(my_spec),
1134 cpl_bivector_get_y(my_spec_err));
1135 cpl_bivector_delete(my_spec);
1136 cpl_bivector_delete(my_spec_err);
1144 *out_order_idx_values = order_idx_values ;
1145 *out_nb_order_idx_values = nb_order_idx_values ;
1160 cpl_vector *filt_spec;
1164 filt_spec = cpl_vector_new(cpl_vector_get_size(spec));
1167 for (
int j=0 ; j<cpl_vector_get_size(err) ; j++) {
1170 err_val = cpl_vector_get(err,j) ;
1171 spec_val = cpl_vector_get(spec,j) ;
1172 if (!(isnan(spec_val) || isnan(err_val) || spec_val==0.0)) {
1173 cpl_vector_set(filt_spec, filt_spec_size, spec_val);
1178 if (filt_spec_size > 4) {
1179 cpl_vector_set_size(filt_spec, filt_spec_size);
1181 cpl_vector *abs_diff = cpl_vector_new(filt_spec_size - 4);
1183 for (
int i = 2; i < filt_spec_size - 2; i++) {
1184 cpl_vector_set(abs_diff, i - 2, fabs(2.0 * cpl_vector_get(filt_spec, i) - cpl_vector_get(filt_spec, i - 2) - cpl_vector_get(filt_spec, i + 2)));
1187 double signal = cpl_vector_get_median(filt_spec);
1188 double noise = 0.6052697 * cpl_vector_get_median(abs_diff);
1190 cpl_vector_delete(abs_diff);
1191 cpl_vector_delete(filt_spec);
1193 return signal / noise;
1195 cpl_vector_delete(filt_spec) ;
1209 const cpl_table * slitfu,
1216 const double * data ;
1218 cpl_fit_mode fit_pars ;
1220 double qc_fwhm, x0, sigma, area, offset, extr_height;
1223 if (slitfu == NULL)
return -1 ;
1227 data = cpl_table_get_data_double_const(slitfu, colname);
1230 cpl_msg_warning(__func__,
"No slitfunc data: code %d",
1231 cpl_error_get_code());
1238 fit_pars = CPL_FIT_CENTROID + CPL_FIT_STDEV + CPL_FIT_AREA;
1241 nrow = cpl_table_get_nrow(slitfu);
1244 x = cpl_vector_new(nrow);
1245 y = cpl_vector_new(nrow);
1246 for (i = 0; i < nrow; i++){
1247 cpl_vector_set(x, i, i);
1248 cpl_vector_set(y, i, 0);
1254 for (j = 0; j < nrow; j++) {
1255 if (isnan(data[j]) | (data[j] > 1)){
1256 cpl_vector_set(y, j, 0);
1258 cpl_vector_set(y, j, data[j]);
1261 cpl_vector_fit_gaussian(x, NULL, y, NULL, fit_pars, &x0, &sigma,
1262 &area, &offset, NULL, NULL, NULL);
1263 if (cpl_error_get_code()) {
1264 cpl_msg_warning(__func__,
"Failed Fit for the slit PSF") ;
1268 qc_fwhm = 2.355 * sigma;
1273 extr_height = (nrow-1) / oversample -1;
1274 qc_fwhm *= extr_height / nrow;
1275 cpl_msg_debug(__func__,
"extr_height / nrow = %g",extr_height / nrow);
1278 cpl_vector_delete(x);
1279 cpl_vector_delete(y);
1295 int det_nr, max_nsat, nsat ;
1296 cpl_size i, k, nframes, nx, ny ;
1299 if (frameset == NULL)
return -1 ;
1303 nframes = cpl_frameset_get_size(frameset);
1305 for (i = 0; i < nframes; i++) {
1306 const cpl_frame *frame;
1308 frame = cpl_frameset_get_position_const(frameset, i);
1309 fname = cpl_frame_get_filename(frame);
1310 for (det_nr=1 ; det_nr<=CR2RES_NB_DETECTORS ; det_nr++) {
1315 pima = cpl_image_get_data_double(ima) ;
1316 nx = cpl_image_get_size_x(ima) ;
1317 ny = cpl_image_get_size_y(ima) ;
1318 for (k = 0 ; k<nx*ny ; k++) {
1319 if (pima[k] > CR2RES_DETECTOR_OVEREXP_THRESH) nsat++ ;
1323 cpl_msg_warning(__func__,
"NUMSAT - cannot load detector") ;
1326 if (nsat > max_nsat) max_nsat = nsat ;
1344static int cr2res_qc_wave_line_intens(
1345 const cpl_bivector * spec,
1353 const cpl_vector * wave;
1354 const cpl_vector * flux;
1357 cpl_size window_size;
1358 cpl_size n_inner, n_outer;
1359 double sum_inner, sum_outer;
1366 if (spec == NULL)
return -1 ;
1369 window_size = CR2RES_QC_WINDOW / 2;
1371 wave = cpl_bivector_get_x_const(spec);
1372 flux = cpl_bivector_get_y_const(spec);
1376 tmp = cpl_vector_duplicate(wave);
1377 cpl_vector_subtract_scalar(tmp, wl);
1378 cpl_vector_multiply(tmp, tmp);
1379 pixel_pos = cpl_vector_get_minpos(tmp);
1380 cpl_vector_delete(tmp);
1383 if (pixel_pos == 0 || pixel_pos == cpl_vector_get_size(wave))
return -1.0;
1391 for (cpl_size i = -window_size * 2; i < 2 * window_size; i++)
1395 if (k < 0 || k >= cpl_vector_get_size(flux)){
1398 value = cpl_vector_get(flux, k);
1402 if (llabs(i) < window_size){
1412 if (n_inner + n_outer == 0){
1417 if (n_inner != 0) sum_inner /= n_inner;
1418 if (n_outer != 0) sum_outer /= n_outer;
1421 *intens = sum_inner ;
1426int cr2res_qc_calculate_mean_and_rmsd(cpl_propertylist ***plists,
int size,
const int *sizes,
1427 const char *ref_keyword, cpl_propertylist *qc_main,
1428 const char *result_avg_keyword,
const char *result_rmsd_keyword) {
1430 cpl_errorstate status;
1432 status = cpl_errorstate_get();
1435 double sum_sq = 0.0;
1438 for (
int i = 0; i < size; i++) {
1439 for (
int j = 0; j<sizes[i]; j++){
1440 if (plists[i][j] != NULL) {
1441 double value = cpl_propertylist_get_double(plists[i][j], ref_keyword);
1442 if(!cpl_errorstate_is_equal(status)) {
1443 cpl_msg_debug(__func__,
"Cannot get keyword %s : %s", ref_keyword, cpl_error_get_message());
1444 cpl_errorstate_set(status);
1448 sum_sq += value * value;
1455 double mean = sum / count;
1460 rmsd = sqrt( (count*mean*mean - 2*mean*sum + sum_sq) / count);
1463 if (qc_main != NULL) {
1464 cpl_propertylist_append_double(qc_main, result_avg_keyword, mean);
1465 cpl_propertylist_append_double(qc_main, result_rmsd_keyword, rmsd);
1472cr2res_qc_dup_mtrlgy_key(cpl_frameset *framelist, cpl_propertylist *plist)
1481 const cpl_frame *frame;
1482 const cpl_frame *first_frame = NULL;
1483 cpl_frameset_iterator *it = NULL;
1484 cpl_propertylist *met_plist = NULL;
1486 cpl_errorstate status;
1488 it = cpl_frameset_iterator_new(framelist);
1489 frame = cpl_frameset_iterator_get_const(it);
1491 while (frame != NULL) {
1493 if (cpl_frame_get_group(frame) == CPL_FRAME_GROUP_RAW) {
1494 first_frame = frame;
1498 status = cpl_errorstate_get();
1500 cpl_frameset_iterator_advance(it, 1);
1502 if (cpl_error_get_code() == CPL_ERROR_ACCESS_OUT_OF_RANGE) {
1503 cpl_errorstate_set(status);
1506 frame = cpl_frameset_iterator_get_const(it);
1509 if (first_frame == NULL) {
1510 cpl_frameset_iterator_reset(it);
1511 frame = cpl_frameset_iterator_get_const(it);
1513 while (frame != NULL) {
1515 if (cpl_frame_get_group(frame) == CPL_FRAME_GROUP_CALIB) {
1516 first_frame = frame;
1520 status = cpl_errorstate_get();
1522 cpl_frameset_iterator_advance(it, 1);
1524 if (cpl_error_get_code() == CPL_ERROR_ACCESS_OUT_OF_RANGE) {
1525 cpl_errorstate_set(status);
1528 frame = cpl_frameset_iterator_get_const(it);
1532 cpl_frameset_iterator_delete(it);
1535 if (first_frame == NULL) {
1536 cpl_msg_debug(__func__,
"No suitable frame found for QC MTRLGY ID in sof.");
1541 status = cpl_errorstate_get();
1544 cpl_propertylist_load_regexp(cpl_frame_get_filename(first_frame), 0,
1545 CR2RES_HEADER_OCS_MTRLGY, 0);
1546 if (cpl_error_get_code() != CPL_ERROR_NONE) {
1547 cpl_msg_debug(__func__,
"Cannot read header for QC MTRLGY ID : %s", cpl_error_get_message());
1548 cpl_errorstate_set(status);
1552 if (plist != NULL) {
1555 cpl_propertylist_get_bool(met_plist, CR2RES_HEADER_OCS_MTRLGY);
1556 if (cpl_error_get_code() != CPL_ERROR_NONE) {
1557 cpl_msg_debug(__func__,
"Cannot get keyword %s : %s",
1558 CR2RES_HEADER_OCS_MTRLGY, cpl_error_get_message());
1559 cpl_errorstate_set(status);
1562 if (mtrlgy_st == 0) {
1563 cpl_propertylist_prepend_int(plist, CR2RES_HEADER_QC_MTRLGY_ID,
1567 cpl_propertylist_prepend_int(plist, CR2RES_HEADER_QC_MTRLGY_ID,
1570 if (cpl_error_get_code() != CPL_ERROR_NONE) {
1571 cpl_msg_debug(__func__,
"Cannot write keyword %s : %s",
1572 CR2RES_HEADER_QC_MTRLGY_ID,
1573 cpl_error_get_message());
1574 cpl_errorstate_set(status);
1579 if (met_plist != NULL){
1580 cpl_propertylist_delete(met_plist);
1588cr2res_qc_dup_chip_idx(cpl_propertylist *plist)
1591 cpl_errorstate status;
1593 status = cpl_errorstate_get();
1595 if (plist != NULL) {
1598 chip_idx = cpl_propertylist_get_int(plist, CR2RES_HEADER_CHIP_IDX);
1599 if (cpl_error_get_code() != CPL_ERROR_NONE) {
1600 cpl_msg_debug(__func__,
"Cannot get keyword %s : %s",
1601 CR2RES_HEADER_OCS_MTRLGY, cpl_error_get_message());
1602 cpl_errorstate_set(status);
1605 if (chip_idx >= 1 && chip_idx <= 3) {
1606 sprintf(
id,
"CHIP%d", chip_idx);
1607 cpl_propertylist_append_string(plist, CR2RES_HEADER_QC_DET_ID,
1609 if (cpl_error_get_code() != CPL_ERROR_NONE) {
1610 cpl_msg_debug(__func__,
"Cannot write keyword %s : %s",
1611 CR2RES_HEADER_QC_DET_ID,
1612 cpl_error_get_message());
1613 cpl_errorstate_set(status);
1617 cpl_msg_debug(__func__,
1618 "CHIP INDEX not recognized for QC DET ID: %d",
int cr2res_detlin_correct(hdrl_image *in, const hdrl_imagelist *detlin)
Apply the detector linearity correction.
char * cr2res_dfs_SLIT_FUNC_colname(int order_idx, int trace)
Get the SLIT_FUNC table column name for a given order/trace.
char * cr2res_dfs_SPEC_ERR_colname(int order_idx, int trace)
Get the ERR column name for a given order/trace.
char * cr2res_dfs_WAVELENGTH_colname(int order_idx, int trace)
Get the WAVELENGTH column name for a given order/trace.
char * cr2res_dfs_SPEC_colname_parse(const char *colname, int *order_idx, int *trace)
Parse a column name ORDER_TRACE_TYPE format.
char * cr2res_dfs_SPEC_colname(int order_idx, int trace)
Get the SPEC column name for a given order/trace.
hdrl_image * cr2res_io_load_image(const char *in, int detector)
Load an hdrl image from a image file.
double cr2res_qc_overexposed(const cpl_image *ima, const cpl_table *tw, int order_idx)
Computes the Overexposed fraction.
int cr2res_qc_numsat(const cpl_frameset *frameset)
Calculate the number of saturated pixels.
double cr2res_qc_flat_s2n(const cpl_table *extracted)
Computes the S2N on the flat.
double cr2res_qc_wave_resol_fwhm(const cpl_bivector *spec, double *wl)
Computes the lines Fwhm and return the smallest.
double * cr2res_qc_der_snr(const cpl_table *tw, const cpl_table *extracted, int **out_order_idx_values, int *out_nb_order_idx_values)
Computes the DER SNR of several spectra.
double cr2res_qc_wave_lamp_effic(const cpl_bivector *spec)
Computes the lamp efficiency.
double cr2res_dark_qc_ron(const cpl_image *ima1, const cpl_image *ima2, int hsize, int nsamples, int ndit)
The Read Out Noise computation.
int cr2res_qc_detlin_stat(const hdrl_imagelist *hdrl_coeffs, double *meda, double *medb, double *medc, double *meda_err)
Computes the detlin coeffs statѕ
double cr2res_qc_obs_nodding_signal(const cpl_table *extracted)
Computes the integrated flux over part of the spectrum.
double cr2res_qc_wave_central(const cpl_table *tw, int order_idx)
Computes the central WLEN of a given order.
int cr2res_qc_flat_order_positions(const cpl_table *tw, int **order_nb, double **order_pos, int *nbvals)
Compute the central orders positions.
double cr2res_qc_wave_line_fwhm(const cpl_bivector *spec, double wl, double *peak_height)
Computes one line Fwhm.
double cr2res_qc_flat_trace_center_y(const cpl_table *trace)
Computes the mean Y coord of the central order.
double cr2res_qc_compute_der_snr(cpl_vector *spec, cpl_vector *err)
Computes the DER SNR of one spectrum.
double cr2res_qc_wave_disp(const cpl_table *tw, int order_idx)
Computes the dispersion of a given order.
double cr2res_qc_obs_nodding_standard_flux(const cpl_table *extracted, char *setting)
Computes the standard flux over part of the spectrum.
cpl_bivector * cr2res_qc_lines_intens_bgd(const cpl_bivector *spec)
Computes the lines intensities / background.
double * cr2res_qc_snr(const cpl_table *tw, const cpl_table *extracted, int **out_order_idx_values, int *out_nb_order_idx_values)
Computes the SNR of several spectra.
cpl_vector * cr2res_qc_lines_collect(double wmin, double wmax)
Collect lines between 2 wavelengths.
double cr2res_qc_detlin(const hdrl_imagelist *hdrl_coeffs, double bpm_thresh, cpl_mask **outmask, double *min_level, double *max_level)
Computes the detlin median non linearity.
double cr2res_qc_compute_snr(cpl_vector *spec, cpl_vector *err)
Computes the SNR of one spectrum.
double cr2res_qc_obs_slit_psf(const cpl_table *slitfu, int order_idxp, int oversample)
Computes the FWHM of the PSF along the slit for a given order.
cpl_vector * cr2res_trace_get_ycen(const cpl_table *trace, int order_idx, int trace_nb, int size)
Retrieves the middle (All) polynomial from trace table and evaluates.
cpl_image * cr2res_trace_gen_image(cpl_table *trace, int nx, int ny)
Make an image out of the trace solution.
double cr2res_trace_get_trace_ypos(const cpl_table *traces, int idx)
Compute the y position of the trace.
cr2res_decker cr2res_trace_slit_fraction_info(const cpl_array *slit_frac, int *up_or_down)
Get a standard slit fraction information.
int * cr2res_get_trace_numbers(const cpl_table *trace_wave, int order_idx, int *nb_traces)
Get the trace numbers for a specified order_idx.
cpl_vector * cr2res_trace_get_wl(const cpl_table *trace_wave, int order_idx, int trace_nb, int size)
Get the Wavelength vector from a TRACE_WAVE table.
int * cr2res_trace_get_order_idx_values(const cpl_table *trace, int *nb_order_idx_values)
Count and return the different order_idx values from a TW table.
cpl_error_code hdrl_image_reject_value(hdrl_image *self, cpl_value mode)
Reject pixels with the specified special value(s)
cpl_error_code hdrl_image_reject_from_mask(hdrl_image *self, const cpl_mask *map)
set bpm of hdrl_image
cpl_mask * hdrl_image_get_mask(hdrl_image *himg)
get cpl bad pixel mask from image
cpl_error_code hdrl_image_add_scalar(hdrl_image *self, hdrl_value value)
Elementwise addition of a scalar to an image.
cpl_image * hdrl_image_get_error(hdrl_image *himg)
get error as cpl image
cpl_size hdrl_image_get_size_y(const hdrl_image *self)
return size of Y dimension of image
cpl_size hdrl_image_get_size_x(const hdrl_image *self)
return size of X dimension of image
cpl_image * hdrl_image_get_image(hdrl_image *himg)
get data as cpl image
hdrl_image * hdrl_image_new(cpl_size nx, cpl_size ny)
create new zero filled hdrl image
void hdrl_image_delete(hdrl_image *himg)
delete hdrl_image
hdrl_image * hdrl_imagelist_get(const hdrl_imagelist *himlist, cpl_size inum)
Get an image from a list of images.