79static double met_Sep_2016[64] = {-0.000338233 ,-0.000282107 ,0.000345582 ,0.000381979 ,0.000326764 ,-0.000225664 ,5.35555e-05 ,0.00060938 ,-0.000205619 ,-0.000265577 ,0.00017356 ,0.000265687 ,0.000295987 ,3.05255e-05 ,-0.000498407 ,0.000232075 ,0.00502058 ,0.002045925 ,-0.000110657 ,-0.000403592 ,-0.000065043 ,-0.000433645 ,-0.000626545 ,3.29765e-05 ,-0.001694525 ,-0.0011684 ,6.2795e-06 ,-0.001584115 ,-0.000735553 ,-0.000868538 ,-0.000985087 ,-0.0008204 ,0.000768577 ,0.000848342 ,-0.000134943 ,-0.000385157 ,-8.68822e-05 ,-0.000757366 ,0.000446051 ,-0.000231723 ,0.000790425 ,-0.000638897 ,0.000503496 ,-7.78205e-05 ,0.000287366 ,0.000243789 ,0.000083288 ,-0.000125138 ,-0.000147337 ,4.14224e-05 ,0.000123082 ,-0.00117179 ,4.54785e-05 ,-0.000186707 ,0.000682836 ,0.00090649 ,0.000357256 ,-0.002133845 ,-0.00151895 ,-0.00150048 ,-0.00266423 ,-0.0030716 ,0.000599228 ,-0.001078583};
80static double met_Mar_2017[64] = {0.000481474 ,0.000678173 ,0.00022232 ,9.04735e-05 ,0.001030283 ,0.000400478 ,0.000199579 ,0.000610902 ,0.000870061 ,0.001148845 ,0.000706636 ,0.000491999 ,0.00093158 ,0.001224225 ,0.000652115 ,0.001117025 ,0.00481452 ,0.002359475 ,0.000641491 ,0.000126103 ,0.000158341 ,0.001455785 ,0.000227113 ,0.000366087 ,-0.000372672 ,-0.000814455 ,0.000403834 ,-0.00072791 ,-0.000422227 ,0.000413887 ,-0.000024651 ,0.000106683 ,0.00092596 ,0.000327427 ,0.000775269 ,0.000906505 ,0.000108337 ,-0.000214467 ,0.001249965 ,0.000694693 ,0.000718101 ,0.00083926 ,0.00138818 ,0.00131215 ,0.001113065 ,0.00134113 ,0.000972572 ,0.00073247 ,-3.35943e-05 ,0.000312545 ,0.000365923 ,0.000510906 ,0.000955084 ,0.000808904 ,0.000403238 ,-0.000150186 ,0.000200673 ,-0.00078668 ,-0.00078133 ,-0.00039955 ,-0.00226333 ,-0.00177287 ,0.000435995 ,-0.000397403};
81static double met_Jun_2017[64] = {0.00029923 ,5.42185e-05 ,-0.000023823 ,0.000187444 ,0.000650675 ,0.000135629 ,-0.000047364 ,0.000479489 ,0.000463565 ,0.000536066 ,0.000528847 ,0.000874895 ,0.000702853 ,0.000438988 ,0.000183642 ,0.000536044 ,0.004829985 ,0.00215068 ,5.94134e-05 ,-0.000164468 ,-4.89301e-05 ,0.000400028 ,-0.000277333 ,-0.000169422 ,-0.00136967 ,-0.000998661 ,0.000244959 ,-0.00123726 ,-0.000404182 ,-0.000511517 ,-0.000398515 ,-0.000314167 ,0.000546602 ,0.000547136 ,0.000388259 ,0.000108443 ,-0.000266431 ,-0.000734324 ,0.000946866 ,0.0001005 ,0.000739434 ,0.000530113 ,0.000821013 ,0.000748435 ,0.00094666 ,0.00102861 ,-0.00013052 ,0.000576223 ,-0.000657692 ,-0.000293389 ,0.000146337 ,-0.000338176 ,0.000241386 ,0.00005168 ,0.000495891 ,-1.76273e-05 ,8.84135e-05 ,-0.00153857 ,-0.000850848 ,-0.000986058 ,-0.002700175 ,-0.002620785 ,0.000440797 ,-0.00063843};
82static double met_Jul_2017[64] = {8.19405e-05 ,-0.000061716 ,0.000067827 ,0.000234624 ,0.000521161 ,0.000031451 ,0.000211139 ,0.000578157 ,0.000316435 ,0.000431433 ,0.000431228 ,0.000761259 ,0.000576742 ,0.000299923 ,0.00034315 ,0.000561323 ,0.004834095 ,0.00208259 ,-0.000155192 ,-0.000120373 ,-0.000328756 ,0.000265791 ,-0.000249398 ,-0.000310416 ,-0.001047503 ,-0.000884526 ,0.000431645 ,-0.000890023 ,-0.000330709 ,-0.000540866 ,-0.0002067 ,-0.000334498 ,0.00035945 ,0.000683828 ,0.000464533 ,0.000166613 ,-0.000276387 ,-0.00088093 ,0.001283446 ,0.00016521 ,0.000578248 ,0.000334565 ,0.000762716 ,0.000521964 ,0.000757276 ,0.000959739 ,0.000035001 ,0.000442429 ,-0.0006928 ,-0.000105863 ,-0.00006137 ,-0.000454825 ,-0.000157343 ,-5.68635e-05 ,0.000296553 ,-3.80711e-05 ,0.000384616 ,-0.00149983 ,-0.000650183 ,-0.00076473 ,-0.002494945 ,-0.00246317 ,0.000794264 ,-0.000337915};
83static double met_Aug_2017[64] = {0.000225917 ,0.00033629 ,1.70956e-05 ,0.000178987 ,0.00103744 ,0.000275415 ,0.000107582 ,0.000678724 ,0.000402821 ,0.000713535 ,0.000518528 ,0.000607008 ,0.000506748 ,0.000640514 ,0.000300349 ,0.000522693 ,0.005585285 ,0.00305222 ,0.000771553 ,0.001006485 ,0.000618719 ,0.00130769 ,0.000419028 ,0.000491215 ,-0.000815277 ,-0.000646205 ,0.000640702 ,-0.000881775 ,-0.000200994 ,-0.000258582 ,-0.000465663 ,-0.00004838 ,0.000591627 ,0.000615608 ,0.000197913 ,0.000352664 ,-0.000113565 ,-0.000637229 ,0.001241975 ,-6.659e-06 ,0.000649339 ,0.000641595 ,0.000673658 ,0.000657426 ,0.001263897 ,0.001258565 ,0.000050901 ,0.000318844 ,-9.23866e-05 ,0.00065074 ,0.000793493 ,0.000600095 ,0.001049984 ,0.000858337 ,0.000786737 ,0.000737051 ,0.000576774 ,-0.001384295 ,-0.000642989 ,-0.0008569 ,-0.00208747 ,-0.00247888 ,0.00108834 ,-0.000190064};
90 cpl_vector * values_y0,
91 cpl_vector * values_sigma,
95 const char * resolution);
98 cpl_vector * values_x0,
99 cpl_vector * values_y0,
100 cpl_vector * values_sigma,
101 cpl_size iy_min, cpl_size iy_max,
102 const char * resolution);
128 cpl_ensure (raw_data, CPL_ERROR_NULL_INPUT, NULL);
136 cpl_propertylist_append (dark_header, raw_header);
140 int isSky = strstr (dpr_type,
"SKY")?1:0;
156 cpl_msg_warning (cpl_func,
"The DARK data has no IMAGING_DATA_SC");
160 cpl_msg_info (cpl_func,
"Computing the %s of SC",isSky?
"SKY":
"DARK");
169 cpl_image * median_img = cpl_imagelist_collapse_create (imglist);
175 cpl_imagelist * temp_imglist = cpl_imagelist_duplicate (imglist);
176 cpl_imagelist_subtract_image (temp_imglist, median_img);
177 cpl_imagelist_power (temp_imglist, 2.0);
178 cpl_image * stdev_img = cpl_imagelist_collapse_create (temp_imglist);
179 FREE (cpl_imagelist_delete, temp_imglist);
180 cpl_image_power (stdev_img, 0.5);
185 double mean_qc = cpl_image_get_median (median_img);
186 double darkrms = cpl_image_get_median (stdev_img);
193 size_t acq_dark_zero_count = 0;
194 for(
int i=0; i < cpl_imagelist_get_size(acq_imglist); i++)
196 cpl_mask * acq_zero_mask = cpl_mask_threshold_image_create(cpl_imagelist_get(acq_imglist, i), -FLT_MIN, FLT_MIN);
197 acq_dark_zero_count+= cpl_mask_count(acq_zero_mask);
198 cpl_mask_delete(acq_zero_mask);
204 cpl_msg_info (cpl_func,
"QC_MEDIAN%s_SC = %e",isSky?
"SKY":
"DARK", mean_qc);
205 cpl_msg_info (cpl_func,
"QC_%sRMS_SC = %e",isSky?
"SKY":
"DARK", darkrms);
209 img_plist = cpl_propertylist_duplicate (img_plist);
212 img_plist = cpl_propertylist_duplicate (img_plist);
222 cpl_msg_warning (cpl_func,
"The DARK data has no IMAGING_DATA_FT");
226 cpl_msg_info(cpl_func,
"Computing the %s of FT",isSky?
"SKY":
"DARK");
234 cpl_table_cast_column (table_ft,
"PIX",
"PIX", CPL_TYPE_DOUBLE);
240 cpl_image * median_img = cpl_imagelist_collapse_median_create (imglist);
241 cpl_image * mean_img = cpl_imagelist_collapse_create (imglist);
246 cpl_imagelist_subtract_image (imglist, mean_img);
247 cpl_imagelist_power (imglist, 2.0);
248 cpl_image * stdev_img = cpl_imagelist_collapse_create (imglist);
249 cpl_image_power (stdev_img, 0.5);
252 cpl_imagelist_power (imglist, 0.5);
253 cpl_imagelist_add_image (imglist, mean_img);
263 double mean_qc = cpl_image_get_mean (median_img);
264 double darkrms = cpl_image_get_mean (stdev_img);
270 cpl_msg_info (cpl_func,
"QC_MEDIAN%s_FT = %e",isSky?
"SKY":
"DARK", mean_qc);
271 cpl_msg_info (cpl_func,
"QC_%sRMS_FT = %e",isSky?
"SKY":
"DARK", darkrms);
274 cpl_table * median_table = cpl_table_extract (table_ft, 0, 1);
276 cpl_table_set_array (median_table,
"PIX", 0, median_array);
277 FREE (cpl_array_unwrap, median_array);
286 cpl_table * stdev_table = cpl_table_extract (table_ft, 0, 1);
288 cpl_table_set_array (stdev_table,
"PIX", 0, stdev_array);
289 FREE (cpl_array_unwrap, stdev_array);
305 cpl_msg_warning (cpl_func,
"The DARK data has no METROLOGY");
311 cpl_msg_info(cpl_func,
"Computing the %s of METROLOGY",isSky?
"SKY":
"DARK");
316 cpl_table_cast_column (table_met,
"VOLT",
"VOLT", CPL_TYPE_DOUBLE);
322 cpl_image * median_img = cpl_imagelist_collapse_median_create (imglist);
323 cpl_image * mean_img = cpl_imagelist_collapse_create (imglist);
328 cpl_imagelist_subtract_image (imglist, mean_img);
329 cpl_imagelist_power (imglist, 2.0);
330 cpl_image * stdev_img = cpl_imagelist_collapse_create (imglist);
331 cpl_image_power (stdev_img, 0.5);
334 cpl_imagelist_power (imglist, 0.5);
335 cpl_imagelist_add_image (imglist, mean_img);
345 double mean_qc = cpl_image_get_mean_window (median_img,1,1,64,1);
346 double darkrms = cpl_image_get_mean_window (stdev_img,1,1,64,1);
347 double darkmin = cpl_image_get_min_window (median_img,1,1,64,1);
348 double darkmax = cpl_image_get_max_window (median_img,1,1,64,1);
349 if (darkmin>0) darkmin=0;
350 if (darkmax<0) darkmax=0;
357 cpl_msg_info (cpl_func,
"QC_MEDIAN%s_MET = %e",
"DARK", mean_qc);
358 cpl_msg_info (cpl_func,
"QC_%sRMS_MET = %e",
"DARK", darkrms);
359 cpl_msg_info (cpl_func,
"QC_%sRANGE_MET = %e",
"DARK", darkmax-darkmin);
362 cpl_table * median_table = cpl_table_extract (table_met, 0, 1);
366 for (cpl_size diode = 64; diode < 80; diode++){
367 cpl_array_set(median_array, diode, 0);
371 double time_mjd_obs= cpl_propertylist_get_double (raw_header,
"MJD-OBS");
374 for (cpl_size diode = 0; diode < 64; diode++)
376 if (time_mjd_obs < 57747) cpl_array_set(median_array, diode,
met_Sep_2016[diode]);
377 else if (time_mjd_obs < 57851) cpl_array_set(median_array, diode,
met_Mar_2017[diode]);
378 else if (time_mjd_obs < 57924) cpl_array_set(median_array, diode,
met_Jun_2017[diode]);
379 else if (time_mjd_obs < 57990) cpl_array_set(median_array, diode,
met_Jul_2017[diode]);
380 else if (time_mjd_obs < 58208.01) cpl_array_set(median_array, diode,
met_Aug_2017[diode]);
383 cpl_table_set_array (median_table,
"VOLT", 0, median_array);
384 FREE (cpl_array_unwrap, median_array);
393 cpl_table * stdev_table = cpl_table_extract (table_met, 0, 1);
395 cpl_table_set_array (stdev_table,
"VOLT", 0, stdev_array);
396 FREE (cpl_array_unwrap, stdev_array);
410 cpl_msg_warning (cpl_func,
"The DARK data has no IMAGING_DATA_ACQ");
414 cpl_msg_info (cpl_func,
"Computing the %s of ACQ",isSky?
"SKY":
"DARK");
420 cpl_image * median_img = cpl_imagelist_collapse_median_create (imglist);
425 double mean_qc = cpl_image_get_median (median_img);
428 cpl_msg_info (cpl_func,
"QC_MEDIAN%s_ACQ = %e",isSky?
"SKY":
"DARK", mean_qc);
434 img_plist = cpl_propertylist_duplicate (img_plist);
460 cpl_ensure (data, CPL_ERROR_NULL_INPUT, NULL);
470 for (
int file = 1; file < ndata; file++) {
473 cpl_image_divide_scalar (darksc_image, ndata);
480 for (
int file = 1; file < ndata; file++) {
483 cpl_image_divide_scalar (stdevsc_image, ndata);
489 cpl_array * darkft_array;
491 for (
int file = 1; file < ndata; file++) {
494 cpl_array_divide_scalar (darkft_array, ndata);
500 cpl_array * errft_array;
502 for (
int file = 1; file < ndata; file++) {
505 cpl_array_divide_scalar (errft_array, ndata);
537 cpl_vector * values_y0,
538 cpl_vector * values_sigma,
539 cpl_image * mean_img,
540 int ref_x,
int ref_y,
542 const char * resolution)
545 cpl_ensure_code (values_x0, CPL_ERROR_NULL_INPUT);
546 cpl_ensure_code (values_y0, CPL_ERROR_NULL_INPUT);
547 cpl_ensure_code (values_sigma, CPL_ERROR_NULL_INPUT);
548 cpl_ensure_code (mean_img, CPL_ERROR_NULL_INPUT);
549 cpl_ensure_code (resolution, CPL_ERROR_NULL_INPUT);
552 int middle = floor (size_profile / 2);
555 int nx = cpl_image_get_size_x (mean_img);
556 int ny = cpl_image_get_size_y (mean_img);
558 cpl_ensure_code (ref_x > 0 && ref_x < nx, CPL_ERROR_ILLEGAL_INPUT);
559 cpl_ensure_code (ref_y > 0 && ref_y < ny, CPL_ERROR_ILLEGAL_INPUT);
563 double y0, y0_ = ref_y;
564 double sigma, sigma_ = 0;
569 while (coord_x <= nx) {
572 cpl_vector * line_data;
573 line_data = cpl_vector_new_from_image_column (mean_img,
578 cpl_vector * y_data, * z_data;
579 y_data = cpl_vector_new (size_profile);
581 if (! (strcmp(resolution,
"LOW") && strcmp(resolution,
"MED")) ) {
583 for (cpl_size i = 0; i < size_profile; i++){
584 cpl_vector_set (y_data, i, ref_y - size_profile/2 + i);
586 z_data = cpl_vector_extract (line_data,
587 ref_y - size_profile/2,
588 ref_y - size_profile/2+size_profile-1, 1);
592 if ((ref_y - middle) <= 0 ) {
593 for (cpl_size i = 0; i < size_profile; i++){
594 cpl_vector_set (y_data, i, i);
596 z_data = cpl_vector_extract (line_data, 0,
597 size_profile - 1, 1);
599 else if ((ref_y - middle + size_profile) >= ny ){
600 for (cpl_size i = 0; i < size_profile; i++){
601 cpl_vector_set (y_data, i, ny - size_profile + i);
603 z_data = cpl_vector_extract (line_data,
608 for (cpl_size i = 0; i < size_profile; i++){
609 cpl_vector_set(y_data, i, ref_y + (i - middle));
611 z_data = cpl_vector_extract (line_data, ref_y - middle,
612 ref_y - middle + size_profile - 1, 1);
617 cpl_errorstate prestate = cpl_errorstate_get();
618 double area, mse, offset = 0;
619 cpl_vector_fit_gaussian (y_data, NULL, z_data, NULL,
620 CPL_FIT_ALL, &y0, &sigma, &area,
621 &offset, &mse, NULL, NULL);
625 if (cpl_error_get_code() == CPL_ERROR_CONTINUE){
626 cpl_errorstate_set (prestate);
627 if (coord_x == ref_x) {
634 cpl_msg_warning (cpl_func,
"Cannot fit profile of channel %d, new y0=%e", coord_x, y0);
641 if ((fabs(y0 - y0_) >= 1) && (coord_x != ref_x)) {
642 cpl_msg_warning (cpl_func,
"Too much difference of channel %d with previous (%e pixels)", coord_x, y0 - y0_);
649 if (! (strcmp(resolution,
"HIGH"))) {
658 cpl_vector_set (values_x0, (coord_x - 1), coord_x - 1);
659 cpl_vector_set (values_y0, (coord_x - 1), y0);
660 cpl_vector_set (values_sigma, (coord_x - 1), sigma);
665 FREE (cpl_vector_delete, line_data);
666 FREE (cpl_vector_delete, z_data);
667 FREE (cpl_vector_delete, y_data);
676 if (! (strcmp(resolution,
"HIGH"))) {
677 ref_y = cpl_vector_get (values_y0, (ref_x - 1));
683 while (coord_x > 0) {
686 cpl_vector * line_data;
687 line_data = cpl_vector_new_from_image_column (mean_img,
692 cpl_vector * y_data, * z_data;
693 y_data = cpl_vector_new(size_profile);
695 if (! (strcmp(resolution,
"LOW") && strcmp(resolution,
"MED")) ) {
697 for (cpl_size i = 0; i < size_profile; i++){
698 cpl_vector_set(y_data, i, ref_y - size_profile/2 + i);
700 z_data = cpl_vector_extract (line_data,
701 ref_y - size_profile/2,
702 ref_y - size_profile/2 +size_profile-1, 1);
706 if ((ref_y - middle) <= 0 ){
707 for (cpl_size i = 0; i < size_profile; i++){
708 cpl_vector_set(y_data, i, i);
710 z_data = cpl_vector_extract (line_data, 0,
711 size_profile - 1, 1);
713 else if ((ref_y - middle + size_profile) >= ny ){
714 for (cpl_size i = 0; i < size_profile; i++){
715 cpl_vector_set(y_data, i, ny - size_profile + i);
717 z_data = cpl_vector_extract (line_data,
722 for (cpl_size i = 0; i < size_profile; i++){
723 cpl_vector_set(y_data, i, ref_y + (i - middle));
725 z_data = cpl_vector_extract (line_data, ref_y - middle,
726 ref_y - middle + size_profile - 1, 1);
731 cpl_errorstate prestate = cpl_errorstate_get();
732 double area, mse, offset = 0;
733 cpl_vector_fit_gaussian (y_data, NULL, z_data, NULL,
734 CPL_FIT_ALL, &y0, &sigma, &area,
735 &offset, &mse, NULL, NULL);
739 if (cpl_error_get_code() == CPL_ERROR_CONTINUE){
740 cpl_errorstate_set (prestate);
741 if (coord_x == ref_x-1){
748 cpl_msg_warning (cpl_func,
"Cannot fit profile of channel %d, new y0=%e", coord_x, y0);
755 if ((fabs(y0 - y0_) >= 1) && (coord_x != ref_x-1)) {
756 cpl_msg_warning (cpl_func,
"Too much difference of channel %d with previous (%e pixels)", coord_x, y0 - y0_);
763 if (! (strcmp(resolution,
"HIGH"))) {
772 cpl_vector_set (values_x0, (coord_x - 1), coord_x);
773 cpl_vector_set (values_y0, (coord_x - 1), y0 );
774 cpl_vector_set (values_sigma, (coord_x - 1), sigma);
779 FREE (cpl_vector_delete, line_data);
780 FREE (cpl_vector_delete, z_data);
781 FREE (cpl_vector_delete, y_data);
787 return CPL_ERROR_NONE;
815 cpl_vector * values_x0,
816 cpl_vector * values_y0,
817 cpl_vector * values_sigma,
824 cpl_ensure (values_x0, CPL_ERROR_NULL_INPUT, NULL);
825 cpl_ensure (values_y0, CPL_ERROR_NULL_INPUT, NULL);
826 cpl_ensure (values_sigma, CPL_ERROR_NULL_INPUT, NULL);
827 cpl_ensure (mean_img, CPL_ERROR_NULL_INPUT, NULL);
828 cpl_ensure (mode, CPL_ERROR_NULL_INPUT, NULL);
831 cpl_size nx = cpl_image_get_size_x (mean_img);
832 cpl_size ny = cpl_image_get_size_y (mean_img);
834 cpl_msg_info (cpl_func,
"iy_min = %lld, iy_max = %lld, ny = %lld",
837 cpl_ensure (iy_min >= 0 && iy_min < ny, CPL_ERROR_ILLEGAL_INPUT, NULL);
838 cpl_ensure (iy_max >= 0 && iy_max < ny, CPL_ERROR_ILLEGAL_INPUT, NULL);
844 cpl_matrix * matrix = cpl_matrix_wrap (1, nx, cpl_vector_get_data(values_x0));
848 cpl_polynomial * y0_poly = cpl_polynomial_new(1);
850 cpl_vector * temp_median = cpl_vector_filter_median_create(values_y0,3);
851 cpl_polynomial_fit (y0_poly, matrix, NULL, temp_median, NULL,
852 CPL_FALSE, NULL, &power);
853 cpl_vector_delete (temp_median);
857 cpl_polynomial * sigma_poly = cpl_polynomial_new(1);
859 cpl_polynomial_fit (sigma_poly, matrix, NULL, values_sigma,
860 NULL, CPL_FALSE, NULL, &power);
864 cpl_vector * valuesfit_y0 = cpl_vector_new(nx);
865 cpl_vector * valuesfit_sig = cpl_vector_new(nx);
867 for (cpl_size ix = 0; ix < nx; ix++){
869 result = cpl_polynomial_eval_1d (y0_poly, cpl_vector_get(values_x0, ix), NULL);
870 cpl_vector_set(valuesfit_y0, ix, result);
871 result = cpl_polynomial_eval_1d (sigma_poly, cpl_vector_get(values_x0, ix), NULL);
872 cpl_vector_set(valuesfit_sig, ix, result);
874 FREE (cpl_polynomial_delete, y0_poly);
875 FREE (cpl_polynomial_delete, sigma_poly);
876 cpl_matrix_unwrap (matrix);
882 cpl_image * region_img;
883 region_img = cpl_image_new (nx, ny, CPL_TYPE_DOUBLE);
884 cpl_image_fill_window (region_img, 1,1,nx,ny, 0.0);
887 for (cpl_size ix = 0; ix < nx; ix++){
889 double sum_flux = 0, sum_flux2 = 0;
892 for (cpl_size iy = iy_min; iy <= iy_max; iy++ ){
897 if (!strcmp (mode,
"PROFILE")) {
898 result = cpl_image_get (mean_img, ix+1, iy+1, &nv);
901 else if (!strcmp (mode,
"BOX")) {
902 result = ( (fabs(iy - cpl_vector_get (valuesfit_y0, ix)) < 3 ) ? 1.0 : 0.0);
905 else if (!strcmp (mode,
"GAUSS")) {
906 result = (iy - cpl_vector_get (valuesfit_y0, ix)) /
907 cpl_vector_get (valuesfit_sig, ix);
908 result = exp( - pow (result, 2) / 2);
910 cpl_msg_error (cpl_func,
"BUG, report to DRS team");
915 cpl_image_set (region_img, ix + 1, iy + 1, result);
919 sum_flux2 += result * result;
924 for (cpl_size iy = iy_min; iy <= iy_max; iy++ ) {
925 double img_j = cpl_image_get (region_img, ix+1, iy+1, &nv);
926 if (img_j / sum_flux < 1e-7)
927 cpl_image_set (region_img, ix+1, iy+1, 0.0);
932 if (!strcmp (mode,
"PROFILE") || !strcmp (mode,
"GAUSS") ) {
934 double sum_flux = 0.0;
935 double sum_flux2 = 0.0;
936 for (cpl_size iy = iy_min; iy <= iy_max; iy++ ) {
937 double img_j = cpl_image_get (region_img, ix+1, iy+1, &nv);
939 sum_flux2 += img_j * img_j;
942 for (cpl_size iy = iy_min; iy <= iy_max; iy++ ) {
943 double img_j = cpl_image_get (region_img, ix+1, iy+1, &nv);
944 cpl_image_set (region_img, ix+1, iy+1, img_j * sum_flux / sum_flux2);
951 FREE (cpl_vector_delete, valuesfit_y0);
952 FREE (cpl_vector_delete, valuesfit_sig);
996 int nflat,
const cpl_parameterlist * params)
1000 cpl_ensure (flats_data, CPL_ERROR_NULL_INPUT, NULL);
1001 cpl_ensure (dark_map, CPL_ERROR_NULL_INPUT, NULL);
1005 CPL_ERROR_ILLEGAL_INPUT, NULL);
1020 cpl_array * array_flux_FT = cpl_array_new(nflat, CPL_TYPE_DOUBLE);
1021 cpl_array * array_flux_SC = cpl_array_new(nflat, CPL_TYPE_DOUBLE);
1027 cpl_msg_warning (cpl_func,
"The FLAT data has no IMAGING_DATA_FT");
1034 cpl_table * darkft_table;
1039 cpl_image * darkft_img;
1043 cpl_imagelist *imglist_ft = cpl_imagelist_new ();
1044 for (
int file = 0; file < nflat; file++) {
1046 cpl_table * dataft_table;
1050 cpl_imagelist * imglistft_tmp;
1054 cpl_imagelist_subtract_image (imglistft_tmp, darkft_img);
1057 cpl_imagelist_set (imglist_ft, cpl_imagelist_collapse_create (imglistft_tmp), file);
1061 cpl_array_set(array_flux_FT, file, cpl_image_get_flux(cpl_imagelist_get(imglist_ft, file)));
1065 cpl_image * flatft_img = cpl_imagelist_collapse_create (imglist_ft);
1066 cpl_imagelist_delete (imglist_ft);
1073 cpl_table_set_array (flatft_table,
"PIX", 0, flatft_array);
1076 FREE (cpl_array_unwrap, flatft_array);
1090 cpl_table * detector_table;
1092 cpl_ensure (detector_table, CPL_ERROR_ILLEGAL_INPUT, NULL);
1102 int nb_region = cpl_table_get_nrow (detector_table);
1105 cpl_image * dark_img, * bad_img;
1108 cpl_ensure (dark_img && bad_img, CPL_ERROR_ILLEGAL_INPUT, NULL);
1116 cpl_imagelist * temp_imglist = cpl_imagelist_new ();
1118 for (
int file = 0; file < nflat; file++){
1121 cpl_imagelist * data_imglist;
1125 data_imglist = cpl_imagelist_duplicate (data_imglist);
1126 cpl_imagelist_subtract_image (data_imglist, dark_img);
1130 cpl_image * collapsed_img = cpl_imagelist_collapse_create (data_imglist);
1131 FREE (cpl_imagelist_delete, data_imglist);
1134 cpl_imagelist_set (temp_imglist, collapsed_img,
1135 cpl_imagelist_get_size (temp_imglist));
1138 cpl_array_set(array_flux_SC, file, cpl_image_get_flux(collapsed_img));
1144 cpl_image * allflat_img;
1145 allflat_img = cpl_imagelist_collapse_create (temp_imglist);
1146 FREE (cpl_imagelist_delete, temp_imglist);
1152 int fullstartx = ext_dim[0] + det_startx - 2;
1156 cpl_image * flatsc_img;
1157 flatsc_img = cpl_image_extract (allflat_img, ext_dim[0], 1,
1158 ext_dim[0] + ext_dim[1] - 1,
1159 cpl_image_get_size_y (allflat_img));
1165 cpl_propertylist * flat_plist = cpl_propertylist_new ();
1167 cpl_propertylist_update_int (flat_plist,
PROFILE_STARTX, ext_dim[0]);
1168 cpl_propertylist_update_int (flat_plist,
PROFILE_NX, ext_dim[1]);
1177 cpl_msg_info (cpl_func,
"Computing the PROFILE of SC");
1181 cpl_image ** median_img = cpl_calloc (4,
sizeof(cpl_image *));
1185 cpl_size size_kernel = !strcmp (resolution,
"HIGH") ? 15 : 5;
1186 cpl_msg_info (cpl_func,
"Median filtering over %lld spectral pixels", size_kernel);
1187 cpl_mask * kernel = cpl_mask_new (size_kernel, 1);
1188 cpl_mask_not (kernel);
1190 for (
int file = 0; file < nflat; file++){
1192 cpl_propertylist * flat_header;
1196 cpl_imagelist * data_imglist;
1198 cpl_ensure (flat_header && data_imglist, CPL_ERROR_NULL_INPUT, NULL);
1201 data_imglist = cpl_imagelist_duplicate (data_imglist);
1202 cpl_imagelist_subtract_image (data_imglist, dark_img);
1206 cpl_image * collapsed_img = cpl_imagelist_collapse_create (data_imglist);
1208 FREE (cpl_imagelist_delete, data_imglist);
1211 cpl_image * filtered_img = cpl_image_duplicate (collapsed_img);
1212 cpl_image_filter_mask (filtered_img, collapsed_img, kernel,
1213 CPL_FILTER_MEDIAN, CPL_BORDER_FILTER);
1217 cpl_image * crop_img;
1218 crop_img = cpl_image_extract (filtered_img, ext_dim[0], 1,
1219 ext_dim[0] + ext_dim[1] - 1,
1220 cpl_image_get_size_y (filtered_img));
1226 median_img[id] = crop_img;
1231 FREE (cpl_mask_delete, kernel);
1234 int nx = cpl_image_get_size_x (median_img[0]);
1235 int ny = cpl_image_get_size_y (median_img[0]);
1239 cpl_ensure (profile_width > 0, CPL_ERROR_ILLEGAL_INPUT, NULL);
1244 cpl_propertylist * flat_header;
1249 if ( cpl_propertylist_get_float(flat_header,
"MJD-OBS") > 57728 ){
1253 if (! (strcmp(resolution,
"LOW") && strcmp(resolution,
"MED")) && !strcmp(pola_mode,
"COMB")) {
1254 size_profile = ny/nb_region;
1255 cpl_msg_info(cpl_func,
"Use a computed size_profile of %d", size_profile);
1258 size_profile = (fmod(profile_width, 2) == 0) ? profile_width + 1 : profile_width;
1259 cpl_msg_info(cpl_func,
"Use a given size profile of %d", size_profile);
1266 if (! (strcmp(resolution,
"LOW") && strcmp(resolution,
"MED"))) {
1267 size_profile = (ny-(nb_region+1)*n_darkline)/nb_region;
1268 cpl_msg_info(cpl_func,
"Use a computed size_profile of %d", size_profile);
1271 size_profile = (fmod(profile_width, 2) == 0) ? profile_width + 1 : profile_width;
1272 cpl_msg_info(cpl_func,
"Use a given size profile of %d", size_profile);
1277 cpl_table * profile_table = cpl_table_new (1);
1280 cpl_array * dimension = cpl_array_new (2, CPL_TYPE_INT);
1281 cpl_array_set (dimension, 0, nx);
1282 cpl_array_set (dimension, 1, ny);
1283 for (
int region = 0; region < nb_region; region ++){
1285 cpl_table_new_column_array (profile_table, data,
1286 CPL_TYPE_DOUBLE, nx * ny);
1287 cpl_table_set_column_dimensions (profile_table, data, dimension);
1289 FREE (cpl_array_delete, dimension);
1292 cpl_table * params_table = cpl_table_new (nb_region);
1293 cpl_table_new_column_array (params_table,
"CENTERY", CPL_TYPE_DOUBLE, nx);
1294 cpl_table_new_column_array (params_table,
"WIDTH", CPL_TYPE_DOUBLE, nx);
1299 cpl_image * mask_img = NULL;
1302 "gravity.calib.force-badpix-to-zero") )
1305 "forced to zero in profiles");
1306 cpl_image_fill_window (mask_img, 1, 1, nx, ny, 1.0);
1310 "forced to zero in profiles");
1311 mask_img = cpl_image_extract (bad_img, ext_dim[0], 1,
1312 ext_dim[0] + ext_dim[1] - 1, ny);
1313 cpl_image_threshold (mask_img, 0.5, 0.5, 1.0, 0.0);
1318 if ( !strcmp (resolution,
"LOW") )
1321 " are forced to zero in profiles.");
1323 double threshold = cpl_propertylist_get_double (dark_header,
QC_DARKRMS_SC);
1324 cpl_image * mask2_img = cpl_image_duplicate (flatsc_img);
1325 cpl_image_threshold (mask2_img, threshold, threshold, 0.0, 1.0);
1332 "gravity.calib.profile-mode",
"AUTO");
1334 if (!strcmp(mode,
"AUTO")) {
1335 if (!strcmp(resolution,
"LOW")) mode =
"PROFILE";
1336 if (!strcmp(resolution,
"MED")) mode =
"PROFILE";
1337 if (!strcmp(resolution,
"HIGH")) mode =
"BOX";
1340 cpl_msg_info (cpl_func,
"Profile computed with mode: %s (%s)", mode, resolution);
1343 for (
int region = 0; region < nb_region ; region++) {
1351 cpl_image * mean_img;
1352 mean_img = cpl_image_add_create (median_img[tel_1],
1354 cpl_image_divide_scalar (mean_img, 2);
1367 if ( window_mode == 1 ){
1368 if (! (strcmp(resolution,
"LOW") && strcmp(resolution,
"MED")) && !strcmp(pola_mode,
"COMB") ) {
1370 ref_y = (region+1)*(size_profile)-size_profile/2;
1373 ref_x = ref0_x - (1 + ext_dim[0]);
1378 if (! (strcmp(resolution,
"LOW") && strcmp(resolution,
"MED")) ) {
1380 ref_y = (region+1)*(size_profile+n_darkline)-size_profile/2;
1383 ref_x = ref0_x - (1 + ext_dim[0]);
1391 cpl_vector * values_x0 = cpl_vector_new (nx);
1392 cpl_vector * values_y0 = cpl_vector_new (nx);
1393 cpl_vector * values_sigma = cpl_vector_new (nx);
1396 mean_img, ref_x, ref_y, size_profile,
1401 cpl_array * values_arr;
1402 values_arr = cpl_array_wrap_double (cpl_vector_get_data (values_y0), nx);
1403 cpl_table_set_array (params_table,
"CENTERY", region, values_arr);
1404 cpl_array_unwrap (values_arr);
1406 values_arr = cpl_array_wrap_double (cpl_vector_get_data(values_sigma), nx);
1407 cpl_table_set_array (params_table,
"WIDTH", region, values_arr);
1408 cpl_array_unwrap (values_arr);
1416 cpl_size iy_min = 0, iy_max = ny-1;
1417 if (! (strcmp(resolution,
"LOW") && strcmp(resolution,
"MED")) ){
1418 iy_min = ref_y - size_profile/2;
1419 iy_max = ref_y + size_profile/2-1;
1423 cpl_image * region_img;
1425 values_y0, values_sigma,
1426 iy_min, iy_max, mode);
1427 FREE (cpl_vector_delete, values_x0);
1428 FREE (cpl_vector_delete, values_y0);
1429 FREE (cpl_vector_delete, values_sigma);
1437 cpl_table_set_array (profile_table,
GRAVI_DATA[region], 0, array);
1438 FREE (cpl_array_unwrap, array);
1447 cpl_propertylist * profile_plist = cpl_propertylist_new ();
1449 cpl_propertylist_copy_property (profile_plist, flat_plist,
PROFILE_STARTX);
1450 cpl_propertylist_copy_property (profile_plist, flat_plist,
PROFILE_NX);
1455 cpl_propertylist * params_plist = cpl_propertylist_duplicate (profile_plist);
1469 for (
int file = 0; file < nflat; file++){
1470 sprintf (qc_name,
"ESO QC FLATFLUX FT%i", file+1);
1471 qc_value = cpl_array_get(array_flux_FT, file, NULL);
1472 cpl_propertylist_append_double (main_header, qc_name, qc_value);
1473 cpl_propertylist_set_comment (main_header, qc_name,
"[ADU] Total flux per DIT");
1474 cpl_msg_info (cpl_func,
"%s = %f [ADU]", qc_name, qc_value);
1476 for (
int file = 0; file < nflat; file++){
1477 sprintf (qc_name,
"ESO QC FLATFLUX SC%i", file+1);
1478 qc_value = cpl_array_get(array_flux_SC, file, NULL);
1479 cpl_propertylist_append_double (main_header, qc_name, qc_value);
1480 cpl_propertylist_set_comment (main_header, qc_name,
"[ADU] Total flux per DIT");
1481 cpl_msg_info (cpl_func,
"%s = %f [ADU]", qc_name, qc_value);
1484 for (
int reg = 0; reg < nb_region; reg += 12) {
1487 qc_value = cpl_array_get_median (cpl_table_get_array (params_table,
"CENTERY", reg));
1488 qc_value = floor (qc_value * 1e6) * 1e-6;
1489 sprintf (qc_name,
"ESO QC PROFILE_CENTER SC%i MED", reg+1);
1490 cpl_propertylist_append_double (main_header, qc_name, qc_value);
1491 cpl_propertylist_set_comment (main_header, qc_name,
"[pixel] position of region");
1492 cpl_msg_info (cpl_func,
"%s = %f [pixel]", qc_name, qc_value);
1495 qc_value = cpl_array_get_median (cpl_table_get_array (params_table,
"WIDTH", reg));
1496 qc_value = floor (qc_value * 1e6) * 1e-6;
1497 sprintf (qc_name,
"ESO QC PROFILE_WIDTH SC%i MED", reg+1);
1498 cpl_propertylist_append_double (main_header, qc_name, qc_value);
1499 cpl_propertylist_set_comment (main_header, qc_name,
"[pixel] width of region");
1500 cpl_msg_info (cpl_func,
"%s = %f [pixel]", qc_name, qc_value);
1503 idx = 1 * ext_dim[1] / 6;
1504 qc_value = cpl_array_get (cpl_table_get_array (params_table,
"CENTERY", reg), idx, NULL);
1505 qc_value = floor (qc_value * 1e6) * 1e-6;
1506 sprintf (qc_name,
"ESO QC PROFILE_CENTER SC%i LEFT", reg+1);
1507 cpl_propertylist_append_double (main_header, qc_name, qc_value);
1508 cpl_propertylist_set_comment (main_header, qc_name,
"[pixel] at STARTX+NX/6");
1509 cpl_msg_info (cpl_func,
"%s = %f [pixel] for x=%lld", qc_name, qc_value, idx);
1512 idx = 5 * ext_dim[1] / 6;
1513 qc_value = cpl_array_get (cpl_table_get_array (params_table,
"CENTERY", reg), idx, NULL);
1514 qc_value = floor (qc_value * 1e6) * 1e-6;
1515 sprintf (qc_name,
"ESO QC PROFILE_CENTER SC%i RIGHT", reg+1);
1516 cpl_propertylist_append_double (main_header, qc_name, qc_value);
1517 cpl_propertylist_set_comment (main_header, qc_name,
"[pixel] at STARTX+5*NX/6");
1518 cpl_msg_info (cpl_func,
"%s = %f [pixel] for x=%lld", qc_name, qc_value, idx);
1526 FREE (cpl_free, ext_dim);
1527 cpl_array_delete(array_flux_FT);
1528 cpl_array_delete(array_flux_SC);
1556 const cpl_size maxdeg = 1, mindeg = 0;
1557 const cpl_size slope_deg = 1;
1561 cpl_ensure (flats_data, CPL_ERROR_NULL_INPUT, NULL);
1562 cpl_ensure (dark_map, CPL_ERROR_NULL_INPUT, NULL);
1566 CPL_ERROR_ILLEGAL_INPUT, NULL);
1570 cpl_msg_info (cpl_func,
"Search for 4-shutter sequence");
1574 for (
int i = 0; i < nrawgain; i++){
1578 gain_file[0] = (flats_data[i]);
1581 gain_file[1] = (flats_data[i]);
1584 gain_file[2] = (flats_data[i]);
1587 gain_file[3] = (flats_data[i]);
1595 cpl_propertylist * output_plist = cpl_propertylist_new();
1604 cpl_msg_warning (cpl_func,
"The FLAT data has no IMAGING_DATA_SC");
1612 cpl_size size = cpl_image_get_size_x (image) * cpl_image_get_size_y (image);
1615 cpl_vector * vector_var = cpl_vector_new (4*size);
1616 cpl_matrix * matrix_mean = cpl_matrix_new (1, 4*size);
1619 cpl_msg_info (cpl_func,
"DARK and BADPIX of SC are not used");
1622 for (
int file = 0; file < 4; file++) {
1625 cpl_imagelist * data_imglist;
1629 cpl_imagelist * imglist1 = cpl_imagelist_new ();
1630 cpl_imagelist * imglist2 = cpl_imagelist_new ();
1631 for (cpl_size i = 0; i < cpl_imagelist_get_size (data_imglist); i ++){
1632 image = cpl_image_cast (cpl_imagelist_get (data_imglist, i), CPL_TYPE_DOUBLE);
1633 cpl_imagelist_set (imglist1, image, i);
1634 cpl_imagelist_set (imglist2, cpl_image_power_create (image, 2), i);
1636 cpl_image * image1_mean = cpl_imagelist_collapse_create (imglist1);
1637 cpl_image * image2_mean = cpl_imagelist_collapse_create (imglist2);
1638 FREE (cpl_imagelist_delete, imglist1);
1639 FREE (cpl_imagelist_delete, imglist2);
1643 cpl_size nx = cpl_image_get_size_x (image1_mean);
1644 cpl_size ny = cpl_image_get_size_y (image1_mean);
1645 for (cpl_size i = 0; i < nx; i ++) {
1646 for (cpl_size j = 0; j < ny; j ++) {
1647 cpl_vector_set (vector_var, file * size + (j + ny*i),
1648 cpl_image_get (image2_mean, i+1, j+1, &nv) -
1649 pow (cpl_image_get (image1_mean, i+1, j+1, &nv), 2));
1650 cpl_matrix_set (matrix_mean, 0, file * size + (j + ny*i),
1651 cpl_image_get (image1_mean, i+1, j+1, &nv));
1664 cpl_polynomial * fit_slope = cpl_polynomial_new (1);
1665 cpl_polynomial_fit (fit_slope, matrix_mean, NULL, vector_var, NULL,
1666 CPL_FALSE, &mindeg, &maxdeg);
1669 double slope = cpl_polynomial_get_coeff (fit_slope, &slope_deg);
1670 cpl_msg_info (cpl_func,
"mean gain SC = %.4f [adu/e-] Mean gain of detector", slope);
1671 cpl_propertylist_append_double (output_plist,
QC_MEANGAIN_SC, slope);
1672 cpl_propertylist_set_comment (output_plist,
QC_MEANGAIN_SC,
"[adu/e-] Mean gain of SC detector" );
1675 cpl_vector_delete (vector_var);
1676 cpl_matrix_delete (matrix_mean);
1677 cpl_polynomial_delete (fit_slope);
1687 cpl_msg_warning (cpl_func,
"The FLAT data has no IMAGING_DATA_FT");
1694 cpl_table * dark_table;
1699 cpl_size size = cpl_table_get_column_depth (dark_table,
"PIX");
1702 cpl_vector * vector_var = cpl_vector_new (4 * size);
1703 cpl_matrix * matrix_mean = cpl_matrix_new (1, 4 * size);
1706 for (
int file = 0; file < 4; file++) {
1709 cpl_table * data_table;
1711 cpl_table_cast_column (data_table,
"PIX",
"PIX", CPL_TYPE_DOUBLE);
1716 cpl_imagelist_subtract_image (data_imglist, dark_img);
1719 cpl_image * mean_img = cpl_imagelist_collapse_create (data_imglist);
1722 cpl_imagelist_subtract_image (data_imglist, mean_img);
1723 cpl_imagelist_power (data_imglist, 2.0);
1724 cpl_image * var_img = cpl_imagelist_collapse_create (data_imglist);
1726 FREE (cpl_imagelist_delete, data_imglist);
1730 cpl_size nx = cpl_image_get_size_x (mean_img);
1731 cpl_size ny = cpl_image_get_size_y (mean_img);
1732 for (cpl_size i = 0; i < nx; i ++) {
1733 for (cpl_size j = 0; j < ny; j ++) {
1734 cpl_vector_set (vector_var, file * size + (j + ny*i),
1735 cpl_image_get (var_img, i+1, j+1, &nv));
1736 cpl_matrix_set (matrix_mean, 0, file * size + (j + ny*i),
1737 cpl_image_get (mean_img, i+1, j+1, &nv));
1749 cpl_polynomial * fit_slope = cpl_polynomial_new (1);
1750 cpl_polynomial_fit (fit_slope, matrix_mean, NULL, vector_var, NULL,
1751 CPL_FALSE, &mindeg, &maxdeg);
1754 double slope = cpl_polynomial_get_coeff (fit_slope, &slope_deg);
1755 cpl_msg_info (cpl_func,
"mean gain FT = %.4f [adu/e-] Mean gain of detector", slope);
1756 cpl_propertylist_append_double (output_plist,
QC_MEANGAIN_FT, slope);
1757 cpl_propertylist_set_comment (output_plist,
QC_MEANGAIN_FT,
"[adu/e-] Mean gain of FT detector");
1760 FREE (cpl_vector_delete, vector_var);
1761 FREE (cpl_matrix_delete, matrix_mean);
1762 FREE (cpl_polynomial_delete, fit_slope);
1767 cpl_free (gain_file);
1771 return output_plist;
1809 const cpl_parameterlist * params)
1813 cpl_ensure (dark_map, CPL_ERROR_NULL_INPUT, NULL);
1814 cpl_ensure (params, CPL_ERROR_NULL_INPUT, NULL);
1815 cpl_ensure (nflat==4 || nflat==0, CPL_ERROR_ILLEGAL_INPUT, NULL);
1823 cpl_propertylist_append (bad_header, dark_header);
1830 cpl_msg_warning (cpl_func,
"The DARK map has no IMAGING_DATA_FT");
1847 cpl_size n_row = cpl_table_get_nrow (dark_table);
1848 cpl_ensure (n_row == 1, CPL_ERROR_ILLEGAL_INPUT, NULL);
1849 cpl_ensure (n_row == cpl_table_get_nrow (std_table), CPL_ERROR_ILLEGAL_INPUT, NULL);
1857 double dark_rms = cpl_propertylist_get_double (dark_header,
QC_DARKRMS_FT);
1858 double dark_mean = cpl_propertylist_get_double (dark_header,
QC_MEANDARK_FT);
1863 double range_max = dark_mean + bad_dark_factor * dark_rms;
1864 cpl_msg_info (cpl_func,
"FT threshold on mean value = %f",range_max);
1867 double std_min = 1e-3;
1870 cpl_size npix = cpl_table_get_column_depth (dark_table,
"PIX");
1871 cpl_array * std_array = cpl_table_get_data_array (std_table,
"PIX")[0];
1872 cpl_vector * std_vector = cpl_vector_new (npix);
1873 for (cpl_size pix = 0; pix < npix; pix++) {
1874 cpl_vector_set (std_vector, pix, cpl_array_get (std_array, pix, NULL));
1876 cpl_vector_sort (std_vector, CPL_SORT_ASCENDING);
1878 cpl_size percentil = (int) npix*0.875;
1879 double std_max = cpl_vector_get (std_vector, percentil)*(1+bad_dark_factor/8.75);
1880 cpl_msg_info (cpl_func,
"FT threshold on std value = %f",std_max);
1883 int count_bp_dark = 0;
1886 cpl_table * bad_table = cpl_table_extract (dark_table, 0, 1);
1889 cpl_array * dark_array = cpl_table_get_data_array (dark_table,
"PIX")[0];
1890 cpl_array * bad_array = cpl_table_get_data_array (bad_table,
"PIX")[0];
1892 for (cpl_size pix = 0; pix < npix; pix++) {
1893 cpl_array_set (bad_array, pix, 0);
1894 int pixel_removed=0;
1896 if ((pix == bad_pix_number_A)||(pix == bad_pix_number_B))
1900 cpl_msg_info(cpl_func,
"Detected a bad FT pixel at position %lli based on reduction option", pix+1);
1903 if (cpl_array_get (dark_array, pix, NULL) > range_max) {
1906 cpl_msg_info(cpl_func,
"Detected a bad FT pixel at position %lli based on its mean flux: %f ADU", pix+1, cpl_array_get (dark_array, pix, NULL));
1909 if (cpl_array_get (std_array, pix, NULL) < std_min) {
1912 cpl_msg_warning(cpl_func,
"Detected a bad FT pixel at position %lli based on its low rms: %f ADU", pix+1, cpl_array_get (std_array, pix, NULL));
1913 }
else if (cpl_array_get (std_array, pix, NULL) > std_max) {
1916 cpl_msg_warning(cpl_func,
"Detected a bad FT pixel at position %lli based on its high rms: %f ADU", pix+1, cpl_array_get (std_array, pix, NULL));
1918 if (pixel_removed == 1) count_bp_dark ++;
1923 cpl_msg_warning (cpl_func,
"Option to remove low flux pixels applied, but no FLATs were provided");
1926 cpl_ensure (flats_data, CPL_ERROR_NULL_INPUT, NULL);
1927 cpl_msg_info (cpl_func,
"FLATs used to remove low flux values on FT");
1929 cpl_array * flat_array_sum = cpl_array_new (npix, CPL_TYPE_DOUBLE);
1930 cpl_array_fill_window (flat_array_sum, 0, npix, 0);
1932 int count_bp_lowflux = 0;
1934 for (
int f = 0; f<nflat; f++) {
1936 cpl_size n_row = cpl_table_get_nrow (flat);
1937 for (
int row = 0; row<n_row; row++) {
1938 cpl_array * flat_array = cpl_table_get_data_array (flat,
"PIX")[row];
1939 cpl_array_add (flat_array_sum, flat_array);
1940 cpl_array_subtract (flat_array_sum, dark_array);
1943 for (cpl_size pix = 0; pix < npix-1; pix+=2) {
1945 double pix1=cpl_array_get (flat_array_sum, pix, NULL);
1946 double pix2=cpl_array_get (flat_array_sum, pix+1, NULL);
1958 if ((cpl_array_get (bad_array, pix, NULL)==0)&&(cpl_array_get (bad_array, pix+1, NULL)==0))
1960 if (pix1 < pix2 / 3)
1963 count_bp_lowflux ++;
1965 else if (pix2 < pix1 / 3)
1968 count_bp_lowflux ++;
1972 cpl_msg_info (cpl_func,
"removed %.3f percents of FT pixels because of low flux",(100.0 * count_bp_lowflux)/ npix);
1974 cpl_array_delete(flat_array_sum);
1980 cpl_propertylist_append_int (bad_header,
QC_BADPIX_FT, count_bp_dark);
1981 cpl_msg_info (cpl_func,
"QC_BADPIX_FT = %d", count_bp_dark);
1987 FREE (cpl_vector_delete, std_vector);
1995 cpl_msg_warning (cpl_func,
"The DARK map has no IMAGING_DATA_SC");
2007 cpl_size nx = cpl_image_get_size_x (dark_img);
2008 cpl_size ny = cpl_image_get_size_y (dark_img);
2012 cpl_image * darkhf_img = cpl_image_cast (dark_img, CPL_TYPE_DOUBLE);
2013 cpl_mask * kernel = cpl_mask_new (9, 9);
2014 cpl_mask_not (kernel);
2015 cpl_image_filter_mask (darkhf_img, dark_img, kernel, CPL_FILTER_MEDIAN, CPL_BORDER_FILTER);
2016 FREE (cpl_mask_delete, kernel);
2018 cpl_image_subtract (darkhf_img, dark_img);
2019 cpl_image_multiply_scalar (darkhf_img, -1.0);
2026 double dark_rms = cpl_propertylist_get_double (dark_header,
QC_DARKRMS_SC);
2027 double dark_mean = cpl_image_get_mean (darkhf_img);
2028 double dark_max = dark_mean + 2*bad_dark_factor * dark_rms;
2029 double dark_min = dark_mean - 2*bad_dark_factor * dark_rms;
2032 double dark_rms_std = cpl_image_get_stdev (std_img);
2033 double std_max = bad_dark_factor * dark_rms_std;
2034 double std_min = 0.05 * dark_rms_std;
2038 cpl_msg_warning (cpl_func,
"Don't detect SC bapixels in mode LOW");
2047 cpl_image * flat_img = NULL, * flatmed_img = NULL, * flatmask_img = NULL;
2050 cpl_msg_info (cpl_func,
"No FLATs provided, detect only DARK");
2053 cpl_ensure (flats_data, CPL_ERROR_NULL_INPUT, NULL);
2054 cpl_msg_info (cpl_func,
"FLATs used to detect badpix on SC");
2057 flat_img = cpl_image_new (nx,ny,CPL_TYPE_DOUBLE);
2058 cpl_image_fill_window (flat_img, 1, 1, nx, ny, 0.0);
2063 for (
int f = 0; f<nflat; f++) {
2064 cpl_image * img = cpl_imagelist_collapse_median_create (
2067 cpl_image_subtract (img, dark_img);
2070 cpl_image_subtract_scalar (img, bias);
2071 cpl_image_add (flat_img, img);
2078 cpl_size kernel_x = 5;
2079 if (nx > 100) kernel_x = 11;
2080 if (nx > 1000) kernel_x = 31;
2081 cpl_msg_info (cpl_func,
"Kernel of (%lld,%i) pixels for median filtering", kernel_x, 1);
2082 cpl_mask * kernel = cpl_mask_new (kernel_x, 1);
2083 cpl_mask_not (kernel);
2086 flatmed_img = cpl_image_duplicate (flat_img);
2087 cpl_image_filter_mask (flatmed_img, flat_img, kernel, CPL_FILTER_MEDIAN, CPL_BORDER_FILTER);
2088 FREE (cpl_mask_delete, kernel);
2091 double threshold = 100.0;
2092 flatmask_img = cpl_image_duplicate (flatmed_img);
2093 cpl_image_threshold (flatmask_img, threshold, threshold, 0, 1.0);
2095 double fraction = cpl_image_get_flux (flatmask_img) / (nx*ny) * 100.0;
2096 cpl_msg_info (cpl_func,
"Fraction of detector illuminated = %.2f%% (>%.1f adu)",
2097 fraction, threshold);
2107 int count_bp_dark = 0;
2108 int count_bp_rms = 0;
2109 int count_bp_flat = 0;
2113 cpl_image * bad_img = cpl_image_new (nx, ny, CPL_TYPE_INT);
2116 for (cpl_size i = 0; i < nx; i++){
2117 for (cpl_size j = 0; j < ny; j++){
2118 int nv = 0, is_bad = 0, flag = 0;
2121 double dij = cpl_image_get (darkhf_img, i + 1, j + 1, &nv);
2122 if ( (dij > dark_max)||
2129 double stdij = cpl_image_get (std_img, i + 1, j + 1, &nv);
2130 if ( (stdij > std_max) ||
2131 (stdij < std_min) ) {
2138 double flat = cpl_image_get (flat_img, i + 1, j + 1, &nv);
2139 double med = cpl_image_get (flatmed_img, i + 1, j + 1, &nv);
2140 double mask = cpl_image_get (flatmask_img, i + 1, j + 1, &nv);
2141 if ( flat < 0.5 * med && mask && i>4 && i<nx-4 ) {
2149 cpl_image_set (bad_img, i + 1, j + 1, flag);
2159 cpl_propertylist_append_int (bad_header,
QC_BADPIX_SC, count_bp);
2160 cpl_msg_info (cpl_func,
"QC_BADPIX_SC (total) = %d (%.2f%%)",
2161 count_bp, (100.0 * count_bp) / (nx*ny));
2163 cpl_msg_info (cpl_func,
"QC_BADPIX_DARK_SC = %d", count_bp_dark);
2165 cpl_msg_info (cpl_func,
"QC_BADPIX_RMS_SC = %d", count_bp_rms);
2167 cpl_msg_info (cpl_func,
"QC_BADPIX_FLAT_SC = %d", count_bp_flat);
2179 cpl_msg_warning (cpl_func,
"The DARK map has no IMAGING_DATA_ACQ");
2190 cpl_image * darkhf_img = cpl_image_cast (dark_img, CPL_TYPE_DOUBLE);
2191 cpl_mask * kernel = cpl_mask_new (21, 21);
2192 cpl_mask_not (kernel);
2193 cpl_image_filter_mask (darkhf_img, dark_img, kernel, CPL_FILTER_MEDIAN, CPL_BORDER_FILTER);
2194 FREE (cpl_mask_delete, kernel);
2196 cpl_image_subtract (darkhf_img, dark_img);
2197 cpl_image_multiply_scalar (darkhf_img, -1.0);
2198 cpl_image_abs (darkhf_img);
2202 double dark_std = cpl_image_get_median (darkhf_img);
2203 cpl_msg_info (cpl_func,
"DARK_ACQ_STD = %e", dark_std);
2206 double threshold = 20 * dark_std + 1e-10;
2207 cpl_image_threshold (darkhf_img, threshold, threshold, 0, 1);
2208 cpl_image * bad_img = cpl_image_cast (darkhf_img, CPL_TYPE_INT);
2211 for (cpl_size x=2; x<cpl_image_get_size_x (bad_img);x++) {
2212 for (cpl_size y=2; y<cpl_image_get_size_y (bad_img);y++) {
2214 if (cpl_image_get (bad_img,x,y-1,&nv) &&
2215 cpl_image_get (bad_img,x,y+1,&nv) &&
2216 cpl_image_get (bad_img,x-1,y,&nv) &&
2217 cpl_image_get (bad_img,x+1,y,&nv)) {
2218 cpl_image_set (bad_img,x,y, 1);
2224 cpl_size count_bp = 0;
2228 for (cpl_size x=0; x<cpl_image_get_size_x (bad_img);x++) {
2229 for (cpl_size y=0; y<cpl_image_get_size_y (bad_img);y++) {
2230 if (cpl_image_get (bad_img,x+1,y+1,&nv)) count_bp++;
2234 cpl_propertylist_append_int (bad_header,
"ESO QC BADPIX ACQ", count_bp);
2274 const cpl_parameterlist * params)
2278 cpl_ensure (dark_map, CPL_ERROR_NULL_INPUT, NULL);
2279 cpl_ensure (params, CPL_ERROR_NULL_INPUT, NULL);
2280 cpl_ensure (nflat==4 || nflat==0, CPL_ERROR_ILLEGAL_INPUT, NULL);
2288 cpl_propertylist_append (biasmask_header, dark_header);
2295 cpl_size nx = cpl_image_get_size_x (dark_img);
2296 cpl_size ny = cpl_image_get_size_y (dark_img);
2300 cpl_image * flat_img = cpl_image_new (nx,ny,CPL_TYPE_DOUBLE);
2301 cpl_image_fill_window (flat_img, 1, 1, nx, ny, 0.0);
2306 for (
int f = 0; f<nflat; f++) {
2307 cpl_image * img = cpl_imagelist_collapse_median_create (
2310 cpl_image_subtract (img, dark_img);
2313 cpl_image_subtract_scalar (img, bias);
2314 cpl_image_add (flat_img, img);
2321 cpl_size kernel_x = 5;
2322 if (nx > 100) kernel_x = 11;
2323 if (nx > 1000) kernel_x = 31;
2324 cpl_msg_info (cpl_func,
"Kernel of (%lld,%i) pixels for median filtering", kernel_x, 1);
2325 cpl_mask * kernel = cpl_mask_new (kernel_x, 1);
2326 cpl_mask_not (kernel);
2329 cpl_image * flatmed_img = cpl_image_duplicate (flat_img);
2330 cpl_image_filter_mask (flatmed_img, flat_img, kernel, CPL_FILTER_MEDIAN, CPL_BORDER_FILTER);
2331 FREE (cpl_mask_delete, kernel);
2334 double threshold = 100.0;
2335 cpl_image * biasmask_img = cpl_image_duplicate (flatmed_img);
2336 cpl_image_threshold (biasmask_img, threshold, threshold, 1.0, 0.0);
2338 double fraction = cpl_image_get_flux (biasmask_img) / (nx*ny) * 100.0;
2339 cpl_msg_info (cpl_func,
"Fraction of detector in bias mask = %.2f%% (<%.1f adu)",
2340 fraction, threshold);
2351 return biasmask_map;
2377 const cpl_parameterlist * params)
2381 cpl_ensure (data, CPL_ERROR_NULL_INPUT, NULL);
2382 cpl_ensure (params, CPL_ERROR_NULL_INPUT, NULL);
2390 cpl_propertylist_append (piezotf_header, data_header);
2405 int base1,base2,base3,sign1,sign2,sign3;
2406 int ndit_small, dit_matrix;
2407 double twoPi = 2.0 * CPL_MATH_PI;
2415 const char * dpr_type = cpl_propertylist_get_string(data_header,
"ESO DPR TYPE");
2416 if (strcmp(dpr_type,
"PIEZOTF") == 0)
2417 actuator = cpl_strdup(
"PIEZO_DL_OFFSET");
2418 else if (strcmp(dpr_type,
"VLTITF") == 0)
2419 actuator = cpl_strdup(
"VLTI_DL_OFFSET");
2422 cpl_msg_error(cpl_func,
"ESO DPR TYPE = %s is not supported!!!", dpr_type);
2425 cpl_msg_info(cpl_func,
"Using %s actuator (DPR.TYPE=%s)", actuator, dpr_type);
2429 cpl_size ndit = cpl_table_get_nrow (opdc);
2430 ndit_small=ndit-nsmooth-(nresp+1);
2431 cpl_msg_info (cpl_func,
"Preparing matrix inversion with NDIT = %lld",ndit);
2432 cpl_array** opd = cpl_table_get_data_array (opdc,
"OPD");
2433 cpl_array** piezo = cpl_table_get_data_array (opdc, actuator);
2438 cpl_array * phase_array = cpl_array_new(
GRAVI_NBASE, CPL_TYPE_DOUBLE);
2439 cpl_array * piezo_array = cpl_array_new(
ntel, CPL_TYPE_DOUBLE);
2440 cpl_matrix * phase_matrix = cpl_matrix_new (ndit_small*
GRAVI_NBASE,1);
2441 cpl_matrix * piezo_matrix = cpl_matrix_new (ndit_small*
GRAVI_NBASE, nresp*
ntel);
2442 cpl_matrix * piezo_header_resp = cpl_matrix_new (nresp*
ntel,1);
2445 for (cpl_size dit = 0 ; dit < ndit-1 ; dit ++)
2446 for (cpl_size base = 0 ; base <
GRAVI_NBASE; base ++)
2448 phase=cpl_array_get(opd[dit+1],base, NULL)-cpl_array_get(opd[dit],base, NULL);
2449 phase-= twoPi * floor( phase / twoPi );
2450 if (phase > CPL_MATH_PI) phase -= twoPi;
2451 cpl_array_set(opd[dit+1],base, phase+cpl_array_get(opd[dit],base, NULL));
2456 for (cpl_size dit = 0 ; dit < ndit-nsmooth; dit ++)
2459 cpl_array_fill_window (phase_array, 0,
GRAVI_NBASE, 0.0);
2460 for (cpl_size smooth = 0 ; smooth < nsmooth; smooth ++)
2461 cpl_array_add( phase_array, opd[smooth+dit] );
2462 cpl_array_multiply_scalar (phase_array, -1.0 / nsmooth);
2463 cpl_array_add( phase_array, opd[ (
int) (nsmooth/2+dit) ] );
2466 cpl_array_fill_window_double (piezo_array, 0,
ntel, 0.0);
2467 for (cpl_size smooth = 0 ; smooth < nsmooth; smooth ++)
2468 cpl_array_add( piezo_array, piezo[smooth+dit] );
2469 cpl_array_multiply_scalar (piezo_array, -1.0 / nsmooth);
2470 cpl_array_add( piezo_array, piezo[ (
int) (nsmooth/2+dit) ] );
2473 if (( dit-(nresp+1) >= 0 )&( dit-(nresp+1) < ndit_small))
2474 for (cpl_size base = 0 ; base <
GRAVI_NBASE; base ++)
2476 int dit_matrix =dit-(nresp+1)+base*ndit_small;
2477 cpl_matrix_set(phase_matrix,dit_matrix,0,cpl_array_get(phase_array, base, NULL));
2481 for (cpl_size tel = 0 ; tel <
ntel; tel ++)
2520 for (cpl_size resp = 0 ; resp < nresp; resp ++)
2521 if (( dit-(nresp+1)+(1+resp) >= 0 )&( dit-(nresp+1)+(1+resp) < ndit_small))
2523 dit_matrix =dit-(nresp+1)+(1+resp)+base1*ndit_small;
2524 cpl_matrix_set(piezo_matrix,dit_matrix,resp*
ntel+tel,sign1*cpl_array_get(piezo_array, tel, NULL));
2525 dit_matrix =dit-(nresp+1)+(1+resp)+base2*ndit_small;
2526 cpl_matrix_set(piezo_matrix,dit_matrix,resp*
ntel+tel,sign2*cpl_array_get(piezo_array, tel, NULL));
2527 dit_matrix =dit-(nresp+1)+(1+resp)+base3*ndit_small;
2528 cpl_matrix_set(piezo_matrix,dit_matrix,resp*
ntel+tel,sign3*cpl_array_get(piezo_array, tel, NULL));
2532 CPLCHECK_NUL (
"Cannot create matrix for SVD inversion");
2536 cpl_matrix * piezo_resp = cpl_matrix_solve_normal(piezo_matrix,phase_matrix);
2537 cpl_matrix * residuals_fit = cpl_matrix_product_create(piezo_matrix,piezo_resp);
2538 cpl_matrix_subtract (residuals_fit,phase_matrix);
2542 if (strcmp(dpr_type,
"VLTITF") == 0)
2544 for (cpl_size tel = 0 ; tel <
ntel; tel ++)
2547 for (cpl_size resp = 0 ; resp < nresp; resp ++)
2548 gain += cpl_matrix_get (piezo_resp, resp*
ntel+tel, 0);
2550 for (cpl_size resp = 0 ; resp < nresp; resp ++)
2551 cpl_matrix_set (piezo_resp, resp*
ntel+tel, 0, cpl_matrix_get (piezo_resp, resp*
ntel+tel, 0) / gain );
2557 for (cpl_size tel = 0 ; tel <
ntel; tel ++)
2558 for (cpl_size resp = 0 ; resp < nresp; resp ++)
2560 sprintf (name,
"ESO FT KAL P%lld_RESP%lld", tel+1, resp+1);
2561 if (cpl_propertylist_has (piezotf_header, name))
2562 cpl_matrix_set( piezo_header_resp, resp*
ntel+ tel, 0, cpl_propertylist_get_double (piezotf_header, name));
2564 cpl_matrix_set( piezo_header_resp, resp*
ntel+ tel, 0, 0.0);
2569 sprintf (qc_name,
"ESO QC FT KAL P_FIT");
2571 cpl_propertylist_set_comment (piezotf_header, qc_name,
"Fitting standard deviation [rad]");
2572 cpl_msg_info (cpl_func,
"Fit standard deviation = %e [rad]", cpl_matrix_get_stdev( residuals_fit ) );
2575 sprintf (name,
"ESO FT RATE");
2576 double sampling = cpl_propertylist_get_double (piezotf_header, name);
2579 for (cpl_size tel = 0 ; tel <
ntel; tel ++)
2581 for (cpl_size resp = 0 ; resp < nresp; resp ++)
2583 sprintf (qc_name,
"ESO QC FT KAL P%lld_RESP%lld", tel+1, resp+1);
2585 cpl_propertylist_set_comment (piezotf_header, qc_name,
"Computed Kalman response");
2587 cpl_msg_info (cpl_func,
"QC FT KAL P%lld_RESP%lld = %5.5g [rad/Volts]", tel+1, resp+1, cpl_matrix_get( piezo_resp, resp*
ntel+ tel,0 ));
2589 sprintf (qc_name,
"ESO QC FT KAL P%lld_RESP%lld DIFF", tel+1, resp+1);
2590 sprintf (ft_name,
"ESO FT KAL P%lld_RESP%lld", tel+1, resp+1);
2591 double ft_kal_diff = cpl_matrix_get( piezo_resp, resp*
ntel+ tel,0 ) -
2592 cpl_propertylist_get_double (data_header, ft_name);
2594 cpl_propertylist_set_comment (piezotf_header, qc_name,
"Comp-Nom Kalman resp");
2600 for (cpl_size resp = 0 ; resp < nresp; resp ++)
2601 QC_gain+=cpl_matrix_get( piezo_resp, resp*
ntel + tel,0 );
2603 sprintf (qc_name,
"ESO QC FT KAL P%lld_GAIN", tel+1);
2605 cpl_propertylist_set_comment (piezotf_header, qc_name,
"Open loop gain [rad/Volts]");
2609 double QC_delay=0.0;
2610 for (cpl_size resp = 0 ; resp < nresp; resp ++)
2611 QC_delay+=(resp+1)*cpl_matrix_get( piezo_resp, resp*
ntel + tel,0 )*sampling;
2614 sprintf (qc_name,
"ESO QC FT KAL P%lld_DELAY", tel+1);
2616 cpl_propertylist_set_comment (piezotf_header, qc_name,
"Open loop latency [ms]");
2620 for (cpl_size resp = 0 ; resp < nresp; resp ++)
2621 QC_std+=(cpl_matrix_get( piezo_resp, resp*
ntel + tel,0 ) - cpl_matrix_get( piezo_header_resp, resp*
ntel+ tel, 0))
2622 * (cpl_matrix_get( piezo_resp, resp*
ntel + tel,0 ) - cpl_matrix_get( piezo_header_resp, resp*
ntel+ tel, 0));
2624 sprintf (qc_name,
"ESO QC FT KAL P%lld_STDEV", tel+1);
2626 cpl_propertylist_set_comment (piezotf_header, qc_name,
"Stdev of RTC [radians]");
2629 CPLCHECK_NUL (
"Failed to generate and store QC parameters");
2632 cpl_array_delete(phase_array);
2633 cpl_array_delete(piezo_array);
2634 cpl_matrix_delete(phase_matrix);
2635 cpl_matrix_delete(piezo_matrix);
2636 cpl_matrix_delete(piezo_header_resp);
2637 cpl_matrix_delete(piezo_resp);
2638 cpl_matrix_delete(residuals_fit);
2664 cpl_ensure_code (imglist_sc, CPL_ERROR_NULL_INPUT);
2668 cpl_binary * bpm_ptr;
2670 const cpl_size nrow = cpl_imagelist_get_size (imglist_sc);
2671 img = cpl_imagelist_get (imglist_sc, 0);
2672 const cpl_size nx = cpl_image_get_size_x (img);
2673 const cpl_size ny = cpl_image_get_size_y (img);
2676 double clip_thresh = 5.;
2678 if (nrow <= 32) clip_thresh = 10;
2679 if (nrow <= 16) clip_thresh = 15;
2680 if (nrow <= 12) clip_thresh = 20;
2681 if (nrow <= 8) clip_thresh = 30;
2682 if (nrow <= 4) clip_thresh = 40;
2683 if (nrow < 4) clip_thresh = 50;
2685 cpl_msg_info (cpl_func,
"Number of images is %lld => cosmic ray detection threshold set to %f sigma", nrow, clip_thresh);
2690 cpl_array * med_val = cpl_array_new (nx, CPL_TYPE_DOUBLE);
2691 double * med_val_ptr = cpl_array_get_data_double (med_val);
2692 cpl_array * std_val = cpl_array_new (nx, CPL_TYPE_DOUBLE);
2693 double * std_val_ptr = cpl_array_get_data_double (std_val);
2696 cpl_vector * row_val = cpl_vector_new (nrow);
2697 double * row_ptr = cpl_vector_get_data (row_val);
2700 cpl_array * good_x = cpl_array_new (nx, CPL_TYPE_DOUBLE);
2701 double * good_x_ptr = cpl_array_get_data_double (good_x);
2702 cpl_array * good_y = cpl_array_new (nx, CPL_TYPE_DOUBLE);
2703 double * good_y_ptr = cpl_array_get_data_double (good_y);
2704 cpl_array * CR_x = cpl_array_new (nx, CPL_TYPE_DOUBLE);
2705 double * CR_x_ptr = cpl_array_get_data_double (CR_x);
2709 cpl_vector * xref = cpl_vector_new(nx + 2);
2710 double * xref_ptr = cpl_vector_get_data(xref);
2711 cpl_vector * yref = cpl_vector_new(nx + 2);
2712 double * yref_ptr = cpl_vector_get_data(yref);
2713 cpl_vector * xout = cpl_vector_new(nx);
2714 double * xout_ptr = cpl_vector_get_data(xout);
2715 cpl_vector * yout = cpl_vector_new(nx);
2716 double * yout_ptr = cpl_vector_get_data(yout);
2719 cpl_bivector * fref = cpl_bivector_wrap_vectors (xref, yref);
2720 cpl_bivector * fout = cpl_bivector_wrap_vectors (xout, yout);
2723 cpl_vector * cCR_vector = cpl_vector_new (nrow);
2724 cpl_vector_fill (cCR_vector, 0.0);
2725 double *cCR_vector_ptr = cpl_vector_get_data(cCR_vector);
2728 #define IMAGE_IDX(_nx, _x, _y) (_x + _nx * _y)
2731 for (cpl_size k = 0; k < ny; k++) {
2733 for (cpl_size i = 0; i < nx; i++) {
2735 for (cpl_size row = 0; row < nrow; row++) {
2736 img_ptr = cpl_image_get_data (cpl_imagelist_get (imglist_sc, row));
2738 row_ptr[row] = img_ptr[idx];
2742 double median = cpl_vector_get_median (row_val);
2743 med_val_ptr[i] = median;
2744 cpl_vector_subtract_scalar (row_val, median);
2745 cpl_vector_multiply (row_val, row_val);
2746 cpl_vector_sqrt (row_val);
2747 std_val_ptr[i] = cpl_vector_get_median (row_val) * CPL_MATH_STD_MAD;
2753 for (cpl_size row = 0; row < nrow; row++) {
2754 cpl_size nGood = 0, nCR = 0;
2757 img = cpl_imagelist_get (imglist_sc, row);
2758 img_ptr = cpl_image_get_data_double (img);
2759 bpm_ptr = cpl_mask_get_data (cpl_image_get_bpm (img));
2762 for (cpl_size i = 0; i < nx; i++) {
2764 cpl_binary nv = bpm_ptr[idx];
2765 double val = img_ptr[idx];
2766 if ((nv == 1) || (val > med_val_ptr[i] + clip_thresh * std_val_ptr[i])) {
2767 CR_x_ptr[nCR++] = i;
2769 good_x_ptr[nGood] = i;
2770 good_y_ptr[nGood++] = val;
2775 cCR_vector_ptr[row] += nCR;
2781 cpl_vector_fill(xref, 0.0);
2782 cpl_vector_fill(yref, 0.0);
2783 cpl_vector_fill(xout, 0.0);
2784 cpl_vector_fill(yout, 0.0);
2787 for (cpl_size i = 0; i < nGood; i++) {
2788 xref_ptr[i+1] = good_x_ptr[i];
2789 yref_ptr[i+1] = good_y_ptr[i];
2794 yref_ptr[0] = good_y_ptr[0];
2795 for (
int m = nGood+1; m < nx + 2; m++) {
2797 yref_ptr[m] = good_y_ptr[nGood-1];
2800 for (cpl_size i = 0; i < nCR; i++) {
2801 xout_ptr[i] = CR_x_ptr[i];
2805 cpl_bivector_interpolate_linear (fout, fref);
2809 for (cpl_size i = 0; i < nCR; i++) {
2810 cpl_size idx =
IMAGE_IDX (nx, xout_ptr[i], k);
2811 img_ptr[idx] = yout_ptr[i];
2812 bpm_ptr[idx] = CPL_BINARY_1;
2820 double percentage_CR_perpixel = cpl_vector_get_mean (cCR_vector) * 100 / (nx * ny);
2821 if (percentage_CR_perpixel > 1)
2822 cpl_msg_warning (cpl_func,
"Cosmic rays flagged on %g percents of the pixels", percentage_CR_perpixel);
2824 cpl_msg_info (cpl_func,
"Cosmic rays flagged on %g percent of the pixels", percentage_CR_perpixel);
2825 for (cpl_size row = 0; row < nrow; row++)
2826 if (cpl_vector_get (cCR_vector, row) > (nx * ny) / 1000)
2827 cpl_msg_warning (cpl_func,
"Cosmic rays detected on image %lli: %g", row+1, cpl_vector_get (cCR_vector, row));
2830 FREE (cpl_array_delete, med_val);
2831 FREE (cpl_array_delete, std_val);
2832 FREE (cpl_vector_delete, row_val);
2834 FREE (cpl_array_delete, good_x);
2835 FREE (cpl_array_delete, good_y);
2836 FREE (cpl_array_delete, CR_x);
2837 FREE (cpl_vector_delete, cCR_vector);
2839 FREE(cpl_vector_delete, xref);
2840 FREE(cpl_vector_delete, yref);
2841 FREE(cpl_vector_delete, xout);
2842 FREE(cpl_vector_delete, yout);
2844 FREE (cpl_bivector_unwrap_vectors, fref);
2845 FREE (cpl_bivector_unwrap_vectors, fout);
2848 return CPL_ERROR_NONE;
2864 cpl_size n = cpl_array_get_size(arr);
2865 cpl_array *result_arr = cpl_array_new(n, CPL_TYPE_DOUBLE);
2866 cpl_array *window_arr = cpl_array_new(size, CPL_TYPE_DOUBLE);
2867 const double *source_data = cpl_array_get_data_double_const(arr);
2869 for (
int i = 0; i < n; i++) {
2872 for (
int w = 0; w < size; w++) {
2873 int v = i + w - size / 2;
2874 v = (v < 0) ? -(v + 1) : ((v > n - 1) ? 2 * n - 1 - v : v);
2875 cpl_array_set_double(window_arr, w, source_data[v]);
2877 cpl_array_set_double(result_arr, i, cpl_array_get_median(window_arr));
2879 cpl_array_delete(window_arr);
2893 cpl_ensure(arr, CPL_ERROR_NULL_INPUT, 0.0);
2894 cpl_ensure(nstd > 0.0, CPL_ERROR_ILLEGAL_INPUT, 0.0);
2896 int n = cpl_array_get_size(arr);
2897 cpl_array *work_arr = cpl_array_duplicate(arr);
2899 int n_changed = 0, iterations = 0;
2900 const int maxiters = 5;
2903 double centre = cpl_array_get_median(work_arr);
2904 double std = cpl_array_get_stdev(work_arr);
2906 double lower_bound = centre - nstd * std;
2907 double upper_bound = centre + nstd * std;
2909 for (
int i = 0; i < n; i++) {
2911 double v = cpl_array_get_double(work_arr, i, &invalid);
2912 if (!invalid && (v < lower_bound || v > upper_bound)) {
2914 cpl_array_set_invalid(work_arr, i);
2917 if (++iterations > maxiters)
break;
2918 }
while(n_changed > 0);
2919 double std = cpl_array_get_stdev(work_arr);
2920 cpl_array_delete(work_arr);
2947 const cpl_parameterlist * params)
2951 cpl_ensure(data, CPL_ERROR_NULL_INPUT, NULL);
2952 cpl_ensure(naccept, CPL_ERROR_DATA_NOT_FOUND, NULL);
2953 cpl_ensure(params, CPL_ERROR_NULL_INPUT, NULL);
2955 int npol, nwave = 0;
2957 int num_components = cpl_parameter_get_int(
2958 cpl_parameterlist_find_const(params,
"gravity.calib.pca-components"));
2960 int median_filter_size = cpl_parameter_get_int(
2961 cpl_parameterlist_find_const(params,
"gravity.calib.pca-clean-size"));
2963 double median_filter_nstd = cpl_parameter_get_double(
2964 cpl_parameterlist_find_const(params,
"gravity.calib.pca-clean-nstd"));
2966 const char *fit_type = cpl_parameter_get_string(
2967 cpl_parameterlist_find_const(params,
"gravity.calib.pca-fit-type"));
2969 int fit_degree = cpl_parameter_get_int(
2970 cpl_parameterlist_find_const(params,
"gravity.calib.pca-fit-degree"));
2972 cpl_boolean save_residuals = cpl_parameter_get_bool(
2973 cpl_parameterlist_find_const(params,
"gravity.calib.pca-save-residuals"));
2975 cpl_propertylist *hdr = NULL, *wave_plist = NULL;
2976 cpl_table *wave_table = NULL, *vis_table = NULL, *pca_table = NULL;
2978 const char *telescope = NULL, *pola_mode = NULL, *spec_res = NULL;
2979 char colname_vis[100], colname_pca[100], colname_pca_fit[100], colname_mean[100], colname_residual[100];
2983 telescope = cpl_propertylist_get_string(hdr,
"TELESCOP");
2990 nwave = cpl_propertylist_get_int(wave_plist,
"NWAVE");
2994 cpl_table_cast_column(wave_table,
"EFF_WAVE",
"EFF_WAVE", CPL_TYPE_DOUBLE);
2995 cpl_table_multiply_scalar(wave_table,
"EFF_WAVE", 1.0e6);
2996 cpl_array *wave_arr = cpl_array_wrap_double(cpl_table_get_data_double(wave_table,
"EFF_WAVE"), nwave);
2999 vis_table = cpl_table_new(naccept);
3001 for(
int j = 0; j < npol; j++) {
3002 sprintf(colname_vis,
"PCA_VISPHI_BASE%d_POL%d", i, j);
3003 cpl_table_new_column_array(vis_table, colname_vis, CPL_TYPE_DOUBLE, nwave);
3008 for (
int n = 0; n < naccept; n++) {
3011 for (
int j = 0; j < npol; j++) {
3015 cpl_array *vis_arr = cpl_array_duplicate(cpl_table_get_array(vis_tmp,
"VISPHI", i));
3021 cpl_array *vis_centred = cpl_array_duplicate(vis_arr);
3022 cpl_array_subtract(vis_centred, vis_filt);
3026 for (
int k = 0; k < nwave; k++) {
3027 if (fabs(cpl_array_get(vis_centred, k, NULL)) > median_filter_nstd * std) {
3028 cpl_array_set(vis_arr, k, cpl_array_get(vis_filt, k, NULL));
3033 sprintf(colname_vis,
"PCA_VISPHI_BASE%d_POL%d", i, j);
3034 cpl_table_set_array(vis_table, colname_vis, n, vis_arr);
3036 cpl_array_delete(vis_filt);
3037 cpl_array_delete(vis_centred);
3038 cpl_array_delete(vis_arr);
3044 pca_table = cpl_table_new(nwave);
3048 for (
int j = 0; j < npol; j++) {
3049 sprintf(colname_vis,
"PCA_VISPHI_BASE%d_POL%d", i, j);
3052 cpl_matrix *vis_tmp = cpl_matrix_new(naccept, nwave);
3053 for (
int n = 0; n < naccept; n++) {
3054 const cpl_array *vis_arr_tmp = cpl_table_get_array(vis_table, colname_vis, n);
3055 for (
int w = 0; w < nwave; w++)
3056 cpl_matrix_set(vis_tmp, n, w, cpl_array_get(vis_arr_tmp, w, NULL));
3067 sprintf(colname_mean,
"PCA_MEAN_BASE%d_POL%d", i, j);
3068 cpl_table_new_column(pca_table, colname_mean, CPL_TYPE_DOUBLE);
3069 cpl_table_copy_data_double(pca_table, colname_mean, cpl_vector_get_data_const(mean));
3072 for (
int c = 0; c < num_components; c++) {
3073 sprintf(colname_pca,
"PCA_C%d_BASE%d_POL%d", c+1, i, j);
3075 cpl_table_new_column(pca_table, colname_pca, CPL_TYPE_DOUBLE);
3076 cpl_table_copy_data_double(pca_table, colname_pca, cpl_vector_get_data_const(cv));
3077 cpl_vector_delete(cv);
3080 cpl_vector_delete(mean);
3081 cpl_matrix_delete(vis_tmp);
3088 CPLCHECK_NUL(
"Failed to compute median averaged PCA components");
3091 for (
int c = 0; c < num_components; c++) {
3092 sprintf(colname_pca,
"PCA_C%d_MEDIAN", c+1);
3094 cpl_table_new_column(pca_table, colname_pca, CPL_TYPE_DOUBLE);
3095 cpl_table_copy_data_double(pca_table, colname_pca, cpl_vector_get_data(cmed));
3096 cpl_vector_delete(cmed);
3101 if (strcmp(fit_type,
"POLYNOMIAL") == 0) {
3103 if (err) cpl_error_set(cpl_func, err);
3106 if (err) cpl_error_set(cpl_func, err);
3111 for (
int c = 0; c < num_components; c++) {
3113 sprintf(colname_pca_fit,
"PCA_C%d_FIT", c+1);
3114 cpl_table_new_column(pca_table, colname_pca_fit, CPL_TYPE_DOUBLE);
3115 cpl_table_copy_data_double(pca_table, colname_pca_fit, cpl_vector_get_data_const(fit_vals));
3116 cpl_vector_delete(fit_vals);
3121 for (
int j = 0; j < npol; j++) {
3123 CPL_FALSE, CPL_FALSE);
3124 if (err) cpl_error_set(cpl_func, err);
3125 CPLCHECK_NUL(
"Failed to fit noise-free model to data");
3128 sprintf(colname_residual,
"PCA_RESID_BASE%d_POL%d", i, j);
3129 cpl_table_new_column_array(vis_table, colname_residual, CPL_TYPE_DOUBLE, nwave);
3131 for (
int n = 0; n < naccept; n++) {
3132 cpl_matrix *resid_row = cpl_matrix_extract_row(resid, n);
3133 cpl_array *resid_row_arr = cpl_array_wrap_double(cpl_matrix_get_data(resid_row), nwave);
3134 cpl_table_set_array(vis_table, colname_residual, n, resid_row_arr);
3135 cpl_array_unwrap(resid_row_arr);
3136 cpl_matrix_delete(resid_row);
3138 cpl_matrix_delete(resid);
3144 for (
int j = 0; j < npol; j++) {
3146 sprintf(colname_residual,
"PCA_RESID_BASE%d_POL%d", i, j);
3147 cpl_matrix *mat_tmp = cpl_matrix_new(naccept, nwave);
3148 for (
int n = 0; n < naccept; n++) {
3149 const cpl_array *residual_arr = cpl_table_get_array(vis_table, colname_residual, n);
3150 for (
int w = 0; w < nwave; w++) {
3151 cpl_matrix_set(mat_tmp, n, w, cpl_array_get(residual_arr, w, NULL));
3160 sprintf(colname_mean,
"PCA_FLAT_MEAN_BASE%d_POL%d", i, j);
3161 cpl_table_new_column(pca_table, colname_mean, CPL_TYPE_DOUBLE);
3162 cpl_table_copy_data_double(pca_table, colname_mean, cpl_vector_get_data_const(mean));
3164 cpl_matrix_delete(mat_tmp);
3170 for (
int j = 0; j < npol; j++) {
3172 CPL_TRUE, CPL_FALSE);
3173 if (err) cpl_error_set(cpl_func, err);
3174 CPLCHECK_NUL(
"Failed to fit noise-free model to data");
3177 sprintf(colname_residual,
"PCA_FLAT_RESID_BASE%d_POL%d", i, j);
3178 cpl_table_new_column_array(vis_table, colname_residual, CPL_TYPE_DOUBLE, nwave);
3180 for (
int n = 0; n < naccept; n++) {
3181 cpl_matrix *resid_row = cpl_matrix_extract_row(resid, n);
3182 cpl_array *resid_row_arr = cpl_array_wrap_double(cpl_matrix_get_data(resid_row), nwave);
3183 cpl_table_set_array(vis_table, colname_residual, n, resid_row_arr);
3184 cpl_array_unwrap(resid_row_arr);
3185 cpl_matrix_delete(resid_row);
3187 cpl_matrix_delete(resid);
3197 cpl_propertylist *
header = cpl_propertylist_new();
3198 cpl_propertylist_append_string(
header,
"TELESCOP", telescope);
3199 cpl_propertylist_append_string(
header,
"ESO INS POLA MODE", pola_mode);
3200 cpl_propertylist_append_string(
header,
"ESO INS SPEC RES", spec_res);
3201 cpl_propertylist_append_int(
header,
"NWAVE", nwave);
3202 cpl_propertylist_append_int(
header,
"PCA NCOMP", num_components);
3204 cpl_table *pca_result = cpl_table_new(nwave);
3205 cpl_table_duplicate_column(pca_result,
"EFF_WAVE", wave_table,
"EFF_WAVE");
3206 cpl_table_multiply_scalar(pca_result,
"EFF_WAVE", 1.0e-6);
3207 cpl_table_set_column_unit(pca_result,
"EFF_WAVE",
"m");
3210 for (
int j = 0; j < npol; j++) {
3211 sprintf(colname_mean,
"PCA_MEAN_BASE%d_POL%d", i, j);
3212 cpl_table_duplicate_column(pca_result, colname_mean, pca_table, colname_mean);
3217 for (
int c = 0; c < num_components; c++) {
3218 sprintf(colname_pca,
"PCA_C%d_BASE%d_POL%d", c+1, i, j);
3219 cpl_table_duplicate_column(pca_result, colname_pca, pca_table, colname_pca);
3224 for (
int c = 0; c < num_components; c++) {
3228 sprintf(colname_pca,
"PCA_C%d_FIT", c+1);
3229 cpl_table_duplicate_column(pca_result, colname_pca, pca_table, colname_pca);
3235 if (save_residuals) {
3237 cpl_table *pca_resid = cpl_table_new(naccept);
3238 cpl_propertylist *header_resid = cpl_propertylist_duplicate(
header);
3241 for (
int j = 0; j < npol; j++) {
3242 sprintf(colname_vis,
"PCA_VISPHI_BASE%d_POL%d", i, j);
3243 cpl_table_duplicate_column(pca_resid, colname_vis, vis_table, colname_vis);
3245 sprintf(colname_residual,
"PCA_RESID_BASE%d_POL%d", i, j);
3246 cpl_table_duplicate_column(pca_resid, colname_residual, vis_table, colname_residual);
3248 sprintf(colname_residual,
"PCA_FLAT_RESID_BASE%d_POL%d", i, j);
3249 cpl_table_duplicate_column(pca_resid, colname_residual, vis_table, colname_residual);
3255 cpl_array_unwrap(wave_arr);
3256 FREE(cpl_table_delete, pca_table);
3257 FREE(cpl_table_delete, vis_table);
3284 cpl_ensure_code(vis_data, CPL_ERROR_NULL_INPUT);
3285 cpl_ensure_code(calib_data, CPL_ERROR_NULL_INPUT);
3287 int ncomp, nwave, nwave_obs, npol;
3289 cpl_propertylist *calib_header = NULL, *vis_header = NULL, *obs_wave_plist = NULL;
3290 cpl_table *calib_table = NULL;
3291 const char *telescope = NULL, *pola_mode = NULL, *spec_res = NULL;
3292 char colname_calib[100], colname_vis[100], colname_mask[100], colname_vis_fit[100], colname_vis_resid[100];
3296 telescope = cpl_propertylist_get_string(vis_header,
"TELESCOP");
3300 vis_mjd = cpl_propertylist_get_double(vis_header,
"MJD-OBS");
3305 return cpl_error_set_message(cpl_func, CPL_ERROR_DATA_NOT_FOUND,
"No VISPHI flattening calibration");
3308 if (vis_mjd < cpl_propertylist_get_double(calib_header,
"PCA EPOCH BEGIN"))
3309 return cpl_error_set_message(cpl_func, CPL_ERROR_DATA_NOT_FOUND,
"VISPHI flattening calibration is too new for data");
3310 else if (vis_mjd > cpl_propertylist_get_double(calib_header,
"PCA EPOCH END"))
3311 return cpl_error_set_message(cpl_func, CPL_ERROR_DATA_NOT_FOUND,
"VISPHI flattening calibration is too old for data");
3314 return cpl_error_set_message(cpl_func, CPL_ERROR_DATA_NOT_FOUND,
"Calibration resolution does not match data");
3316 return cpl_error_set_message(cpl_func, CPL_ERROR_DATA_NOT_FOUND,
"Calibration polarisation mode does not match data");
3317 if (strcmp(cpl_propertylist_get_string(calib_header,
"TELESCOP"), telescope))
3318 return cpl_error_set_message(cpl_func, CPL_ERROR_DATA_NOT_FOUND,
"Calibration telescope does not match data");
3320 ncomp = cpl_propertylist_get_int(calib_header,
"PCA NCOMP");
3321 nwave = cpl_propertylist_get_int(calib_header,
"NWAVE");
3324 cpl_matrix *tmp_matrix = cpl_matrix_new(ncomp, nwave);
3325 for (
int c = 0; c < ncomp; c++) {
3326 sprintf(colname_calib,
"PCA_C%d_FIT", c + 1);
3327 for (
int w = 0; w < nwave; w++) {
3328 double val = cpl_table_get(calib_table, colname_calib, w, NULL);
3329 cpl_matrix_set(tmp_matrix, c, w, val);
3333 cpl_matrix_delete(tmp_matrix);
3337 nwave_obs = cpl_propertylist_get_int(obs_wave_plist,
"NWAVE");
3338 if (nwave != nwave_obs) {
3339 return cpl_error_set_message(cpl_func, CPL_ERROR_ILLEGAL_INPUT,
3340 "Input file wavelength axis does not match the calibrator");
3344 cpl_table *vis_table = cpl_table_new(nwave);
3346 for(
int j = 0; j < npol; j++) {
3347 sprintf(colname_vis,
"PCA_VISPHI_BASE%d_POL%d", i, j);
3348 cpl_table_new_column(vis_table, colname_vis, CPL_TYPE_DOUBLE);
3349 sprintf(colname_mask,
"PCA_MASK_BASE%d_POL%d", i, j);
3350 cpl_table_new_column(vis_table, colname_mask, CPL_TYPE_INT);
3355 for (
int j = 0; j < npol; j++) {
3359 const cpl_array *arr_tmp = cpl_table_get_array(vis_tmp,
"VISPHI", i);
3360 sprintf(colname_vis,
"PCA_VISPHI_BASE%d_POL%d", i, j);
3361 cpl_table_copy_data_double(vis_table, colname_vis, cpl_array_get_data_double_const(arr_tmp));
3364 arr_tmp = cpl_table_get_array(vis_tmp,
"FLAG", i);
3365 sprintf(colname_mask,
"PCA_MASK_BASE%d_POL%d", i, j);
3366 cpl_table_copy_data_int(vis_table, colname_mask, cpl_array_get_data_int_const(arr_tmp));
3367 cpl_table_cast_column(vis_table, colname_mask, colname_mask, CPL_TYPE_DOUBLE);
3377 for(
int j = 0; j < npol; j++) {
3378 sprintf(colname_vis,
"PCA_VISPHI_BASE%d_POL%d", i, j);
3379 sprintf(colname_mask,
"PCA_MASK_BASE%d_POL%d", i, j);
3380 sprintf(colname_calib,
"PCA_MEAN_BASE%d_POL%d", i, j);
3383 cpl_matrix *vis_tmp = cpl_matrix_wrap(1, nwave, cpl_table_get_data_double(vis_table, colname_vis));
3384 cpl_matrix *vis_mean = cpl_matrix_wrap(1, nwave, cpl_table_get_data_double(calib_table, colname_calib));
3385 cpl_matrix_subtract(vis_tmp, vis_mean);
3386 cpl_matrix *mask_tmp = cpl_matrix_wrap(1, nwave, cpl_table_get_data_double(vis_table, colname_mask));
3388 cpl_matrix_unwrap(vis_tmp);
3389 cpl_matrix_unwrap(mask_tmp);
3390 cpl_matrix_unwrap(vis_mean);
3396 for(
int j = 0; j < npol; j++) {
3398 CPL_FALSE, CPL_FALSE);
3399 if (err) cpl_error_set(cpl_func, err);
3403 sprintf(colname_vis_fit,
"PCA_VISPHI_MODEL_BASE%d_POL%d", i, j);
3404 cpl_table_new_column(vis_table, colname_vis_fit, CPL_TYPE_DOUBLE);
3407 sprintf(colname_calib,
"PCA_MEAN_BASE%d_POL%d", i, j);
3408 cpl_matrix *vis_mean = cpl_matrix_wrap(1, nwave, cpl_table_get_data_double(calib_table, colname_calib));
3409 cpl_matrix_add(model_eval, vis_mean);
3410 cpl_table_copy_data_double(vis_table, colname_vis_fit, cpl_matrix_get_data_const(model_eval));
3412 cpl_matrix_delete(model_eval);
3413 cpl_matrix_unwrap(vis_mean);
3416 sprintf(colname_vis_resid,
"PCA_VISPHI_RESID_BASE%d_POL%d", i, j);
3417 cpl_table_new_column(vis_table, colname_vis_resid, CPL_TYPE_DOUBLE);
3419 cpl_table_copy_data_double(vis_table, colname_vis_resid, cpl_matrix_get_data_const(resid));
3420 cpl_matrix_delete(resid);
3425 for (
int j = 0; j < npol; j++) {
3427 cpl_table_new_column_array(vis_tmp,
"VISPHI_MODEL", CPL_TYPE_DOUBLE, nwave);
3428 cpl_table_new_column_array(vis_tmp,
"VISPHI_FLAT", CPL_TYPE_DOUBLE, nwave);
3431 sprintf(colname_vis_fit,
"PCA_VISPHI_MODEL_BASE%d_POL%d", i, j);
3432 cpl_array *arr_tmp = cpl_array_wrap_double(
3433 cpl_table_get_data_double(vis_table, colname_vis_fit), nwave);
3434 cpl_table_set_array(vis_tmp,
"VISPHI_MODEL", i, arr_tmp);
3435 cpl_array_unwrap(arr_tmp);
3438 sprintf(colname_vis_resid,
"PCA_VISPHI_RESID_BASE%d_POL%d", i, j);
3439 arr_tmp = cpl_array_wrap_double(
3440 cpl_table_get_data_double(vis_table, colname_vis_resid), nwave);
3441 cpl_table_set_array(vis_tmp,
"VISPHI_FLAT", i, arr_tmp);
3442 cpl_array_unwrap(arr_tmp);
3445 CPLCHECK_MSG(
"Failed to add calibrated VISPHI to table");
3448 FREE(cpl_table_delete, vis_table);
3453 return CPL_ERROR_NONE;
#define IMAGE_IDX(_nx, _x, _y)
#define gravi_table_get_value(table, name, row, value)
typedefCPL_BEGIN_DECLS struct _gravi_data_ gravi_data
#define gravi_data_get_header(data)
#define gravi_data_get_oi_wave(data, type, pol, npol)
#define gravi_data_get_oi_vis(data, type, pol, npol)
#define gravi_data_get_oi_wave_plist(data, type, pol, npol)
#define gravi_data_get_img(data, ext)
cpl_image_multiply(flat_profiled, profile_crop)
cpl_propertylist * header
cpl_msg_info(cpl_func, "Compute WAVE_SCAN for %s", GRAVI_TYPE(type_data))
cpl_propertylist_update_double(header, "ESO QC MINWAVE SC", cpl_propertylist_get_double(plist, "ESO QC MINWAVE SC"))
cpl_image_delete(flat_profiled)
cpl_error_code gravi_pca_fit_components_polynomial(gravi_pca_model *self, const cpl_array *wave, int degree, int ncomp)
Fit polynomial model to each of a set of median-averaged PCA components.
cpl_error_code gravi_pca_refine_mean(gravi_pca_result *self, const cpl_matrix *residual)
Override the mean component calculated from the PCA decomposition. In conjunction with the fit_mean_s...
cpl_matrix * gravi_pca_get_data_residual(const gravi_pca_result *self)
Get residual (data - model).
cpl_error_code gravi_pca_set_component_signs(gravi_pca_result *self, const cpl_array *wave, const int ncomp)
Impose sign convention on PCA components.
gravi_pca_model * gravi_pca_create_model(const gravi_pca_result **results, int nres, int ncomp)
Compute median values of PCA components over a set of decomposition results.
void gravi_pca_result_delete(gravi_pca_result *self)
Deallocate a gravi_pca_result object.
gravi_pca_result * gravi_pca_create_result(const cpl_matrix *data, const cpl_matrix *mask)
Construct a new gravi_pca_result object from a matrix of visphi data.
cpl_vector * gravi_pca_get_component(const gravi_pca_result *self, int component)
Get components from PCA decomposition.
cpl_matrix * gravi_pca_get_data_fit(const gravi_pca_result *self)
Get noise-free model.
cpl_vector * gravi_pca_get_component_median(const gravi_pca_model *self, int component)
Get median-averaged component from a set of PCA decompositions.
cpl_error_code gravi_pca_decomp_matrix_svd(gravi_pca_result *self)
Perform PCA decomposition by calculating singular value decomposition.
void gravi_pca_model_delete(gravi_pca_model *self)
Deallocate a gravi_pca_model object.
cpl_error_code gravi_pca_fit_components_bspline(gravi_pca_model *self, const cpl_array *wave, int degree, int ncomp)
Fit B-spline model to each of a set of median-averaged PCA components.
cpl_vector * gravi_pca_get_component_fit(const gravi_pca_model *self, int component)
Get fit to components from PCA decomposition.
gravi_pca_model * gravi_pca_load_model(const cpl_matrix *components)
Create PCA model from existing set of components.
cpl_error_code gravi_pca_fit_model(gravi_pca_result *self, const gravi_pca_model *model, cpl_boolean fit_mean_subtracted, cpl_boolean verbose)
Fit model formed from linear combination of PCA components to data.
#define GRAVI_PROFILE_PARAMS_EXT
#define GRAVI_IMAGING_DETECTOR_FT_EXT
#define GRAVI_PROFILE_DATA_EXT
#define PROFILE_FULLSTARTX
#define GRAVI_IMAGING_DATA_FT_EXT
#define GRAVI_BIAS_MASK_SC_EXT
#define GRAVI_IMAGING_ERR_FT_EXT
#define GRAVI_IMAGING_DATA_SC_EXT
#define GRAVI_IMAGING_DATA_ACQ_EXT
#define GRAVI_IMAGING_ERR_SC_EXT
#define QC_BADPIX_FLAT_SC
#define GRAVI_PCA_RESID_EXT
#define GRAVI_IMAGING_DETECTOR_SC_EXT
#define QC_BADPIX_DARK_SC
#define GRAVI_METROLOGY_EXT
#define GRAVI_IMAGING_MASK_SC_EXT
#define GRAVI_METROLOGY_ERR_EXT
#define gravi_msg_function_exit(flag)
#define gravi_data_check_shutter_closed(data)
#define FREE(function, variable)
#define CPLCHECK_NUL(msg)
#define gravi_msg_function_start(flag)
#define CPLCHECK_MSG(msg)
#define gravi_data_check_shutter_open(data)
#define FREELOOP(function, variable, n)
static double met_Jun_2017[64]
gravi_data * gravi_compute_piezotf(gravi_data *data, const cpl_parameterlist *params)
Create piezo transfer function for Kalman Calibration & monitoring.
static double met_Mar_2017[64]
cpl_error_code gravi_flatten_vis(gravi_data *vis_data, gravi_data *calib_data)
Use PCA model to flatten observed visphi. The flattened data are added to the existing VIS table.
cpl_propertylist * gravi_compute_gain(gravi_data **flats_data, int nrawgain, gravi_data *dark_map)
Compute mean detector gain.
static double met_Aug_2017[64]
gravi_data * gravi_compute_profile(gravi_data **flats_data, gravi_data *dark_map, gravi_data *bad_map, int nflat, const cpl_parameterlist *params)
Computes the spatial profile of each spectrum for optimal extraction purpose.
cpl_image * gravi_create_profile_image(cpl_image *mean_img, cpl_vector *values_x0, cpl_vector *values_y0, cpl_vector *values_sigma, cpl_size iy_min, cpl_size iy_max, const char *resolution)
Create the profile image from image and/or fitted params.
double gravi_calc_sigmaclipped_stddev(const cpl_array *arr, double nstd)
Perform sigma-clipping on input array and return std of clipped array.
gravi_data * gravi_compute_pca(gravi_data **data, int naccept, const cpl_parameterlist *params)
Fit model for visphi flattening using PCA.
gravi_data * gravi_average_dark(gravi_data **data, cpl_size ndata)
Average several DARK calibration map.
gravi_data * gravi_compute_dark(gravi_data *raw_data)
Compute the DARK calibration map.
static double met_Sep_2016[64]
static double met_Jul_2017[64]
cpl_array * gravi_filter_array_median(const cpl_array *arr, int size)
Apply median filter on 1-D array.
cpl_error_code gravi_remove_cosmicrays_sc(cpl_imagelist *imglist_sc)
Remove cosmic rays via filtering through images.
gravi_data * gravi_compute_badpix(gravi_data *dark_map, gravi_data **flats_data, int nflat, const cpl_parameterlist *params)
Identify the bad pixels in the DARK map and create the BAD map.
gravi_data * gravi_compute_biasmask(gravi_data *dark_map, gravi_data **flats_data, int nflat, const cpl_parameterlist *params)
Create BIASMASK for SC from raw FLATs and raw DARK.
cpl_error_code gravi_fit_profile(cpl_vector *values_x0, cpl_vector *values_y0, cpl_vector *values_sigma, cpl_image *mean_img, int ref_x, int ref_y, int size_profile, const char *resolution)
Fit the profile parameters in an image.
cpl_image * gravi_image_from_column(cpl_table *table_data, const char *data_x, cpl_size row)
Create an image from a column array in table.
cpl_imagelist * gravi_imagelist_from_column(cpl_table *table_data, const char *data_x)
Create an imagelist from a column array in table.
double gravi_image_get_quantile(const cpl_image *img, double thr)
Compute the quantile of an image.
cpl_array * gravi_array_wrap_image(cpl_image *img)
Wrap the data of na image into an array.
cpl_imagelist * gravi_imagelist_wrap_column(cpl_table *table_data, const char *data_x)
Wrap a column array of a table into an imagelist.
cpl_error_code gravi_imagelist_unwrap_images(cpl_imagelist *imglist)
Unwrap an imagelist an all its images.
gravi_data * gravi_data_duplicate(const gravi_data *self)
Create a copy of the gravi data.
cpl_propertylist * gravi_data_get_plist(gravi_data *self, const char *extname)
Get the propertylist from EXTNAME.
gravi_data * gravi_data_new(int nb_ext)
Create an empty gravi_data.
cpl_error_code gravi_data_add_table(gravi_data *self, cpl_propertylist *plist, const char *extname, cpl_table *table)
Add a BINTABLE extension in gravi_data.
cpl_error_code gravi_data_add_img(gravi_data *self, cpl_propertylist *plist, const char *extname, cpl_image *image)
Add an IMAGE (single image) extension in gravi_data.
cpl_imagelist * gravi_data_get_cube(gravi_data *self, const char *extname)
Return a pointer on an IMAGE extension by its EXTNAME.
int gravi_data_has_extension(gravi_data *raw_calib, const char *ext_name)
Check if data has extension with given EXTNAME.
cpl_table * gravi_data_get_table(gravi_data *self, const char *extname)
Return a pointer on a table extension by its EXTNAME.
cpl_error_code gravi_data_copy_ext(gravi_data *output, gravi_data *input, const char *name)
Copy extensions from one data to another.
int gravi_param_get_bool(const cpl_parameterlist *parlist, const char *name)
int gravi_param_get_int(const cpl_parameterlist *parlist, const char *name)
const char * gravi_param_get_string_default(const cpl_parameterlist *parlist, const char *name, const char *def)
int gravi_pfits_get_pola_num(const cpl_propertylist *plist, int type_data)
const char * gravi_pfits_get_pola_mode(const cpl_propertylist *plist, int type_data)
cpl_error_code gravi_pfits_add_check(cpl_propertylist *header, const char *msg)
Add a QC.CHECK keyword to the header.
const char * gravi_pfits_get_spec_res(const cpl_propertylist *plist)
const char * gravi_pfits_get_resolution(const cpl_propertylist *plist)
const char * gravi_pfits_get_dpr_type(const cpl_propertylist *plist)
int gravi_pfits_get_window_start(const cpl_propertylist *plist)
cpl_error_code gravi_remove_badpixel_sc(cpl_imagelist *imglist_sc, cpl_image *bad_img)
Remove the badpixel of the SC.
cpl_error_code gravi_msg_warning(const char *component, const char *msg)
int gravi_check_shutter(cpl_propertylist *header, int t0, int t1, int t2, int t3)
int * gravi_image_extract_dimension(cpl_image *img_profile)
Compute startx and nx of the illuminated part of the image.
int gravi_get_shutter_id(cpl_propertylist *header)
int gravi_data_check_shutter_beam(gravi_data **datas, int nb_datas)
int gravi_region_get_tel(cpl_table *imaging_detector, int region, int beam)
Return the telescope id (0,1,2,3) in a beam of a region.
Type to hold average (median) components obtained from a set of PCA decompositions and/or best-fit mo...
Type to hold results of a PCA decomposition.