00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028 #ifdef HAVE_CONFIG_H
00029 #include <config.h>
00030 #endif
00031
00032
00033
00034
00035
00036 #include <string.h>
00037 #include <math.h>
00038 #include <cpl.h>
00039
00040 #include "irplib_plugin.h"
00041 #include "irplib_utils.h"
00042 #include "irplib_calib.h"
00043
00044 #include "isaac_utils.h"
00045 #include "isaac_pfits.h"
00046 #include "isaac_dfs.h"
00047
00048
00049
00050
00051
00052 #define RECIPE_STRING "isaac_img_jitter"
00053
00054 #ifndef NEGLIG_OFF_DIFF
00055 #define NEGLIG_OFF_DIFF 0.1
00056 #endif
00057
00058 #define SQR(x) ((x)*(x))
00059
00060 #ifdef ISAAC_IMG_ERR_ESTIMATE
00061 #ifndef ISAAC_IMG_GAIN
00062
00063 #define ISAAC_IMG_GAIN 4.5
00064 #endif
00065
00066 #ifndef ISAAC_IMG_SATURATION_LEVEL
00067
00068 #define ISAAC_IMG_SATURATION_LEVEL 40000.0
00069 #endif
00070 #endif
00071
00072
00073
00074
00075
00076
00077 static cpl_image ** isaac_img_jitter_reduce(cpl_frameset *,
00078 const cpl_parameterlist *,
00079 const cpl_frameset *,
00080 const cpl_frameset *,
00081 const char *, const char *,
00082 const char *, cpl_vector **);
00083 static cpl_imagelist ** isaac_img_jitter_load(const cpl_frameset *,
00084 const cpl_frameset *);
00085 static cpl_vector * isaac_img_jitter_sky(cpl_imagelist **, cpl_imagelist *);
00086 static cpl_vector * isaac_img_jitter_sky_running(cpl_imagelist **);
00087 static cpl_image ** isaac_img_jitter_saa_nochop(cpl_imagelist *,
00088 const cpl_frameset *);
00089 static cpl_image ** isaac_img_jitter_saa_chop(cpl_imagelist *,
00090 const cpl_frameset *);
00091 static int isaac_img_jitter_chopping_classif(cpl_bivector *, int **, int **);
00092 static cpl_error_code isaac_img_jitter_sub_row_median(cpl_image *);
00093 static cpl_table * isaac_img_jitter_qc(cpl_image *);
00094 static double isaac_img_jitter_get_mode(cpl_vector *);
00095 static cpl_error_code isaac_img_jitter_save(cpl_frameset *, const cpl_image *,
00096 const cpl_image *,
00097 const cpl_table *,
00098 const cpl_vector *,
00099 const cpl_parameterlist *);
00100
00101 cpl_recipe_define(isaac_img_jitter, ISAAC_BINARY_VERSION,
00102 "Lars Lundin", PACKAGE_BUGREPORT, "2008",
00103 "ISAAC imaging jitter recipe",
00104 RECIPE_STRING " -- ISAAC imaging jitter recipe.\n"
00105 "The files listed in the Set Of Frames (sof-file) "
00106 "must be tagged:\n"
00107 "raw-file.fits " ISAAC_IMG_JITTER_OBJ_RAW " or\n"
00108 "raw-file.fits " ISAAC_IMG_JITTER_SKY_RAW " or\n"
00109 "raw-file.fits " ISAAC_IMG_JITTER_CHOP_RAW " or\n"
00110 "flat-file.fits " ISAAC_CALIB_FLAT " or\n"
00111 "bpm-file.fits " ISAAC_CALIB_BPM " or\n"
00112 "dark-file.fits " ISAAC_CALIB_DARK "\n");
00113
00114
00115
00116
00117
00118 static struct {
00119
00120 const char * offsets;
00121 const char * objects;
00122 int oddeven;
00123 int sky_minnb;
00124 int sky_halfw;
00125 int sky_rejmin;
00126 int sky_rejmax;
00127 int sx;
00128 int sy;
00129 int mx;
00130 int my;
00131 cpl_geom_combine comb_meth;
00132 int saa_refine;
00133 int rej_low;
00134 int rej_high;
00135 int row_med;
00136 int chopping;
00137
00138 double pixscale;
00139 double dit;
00140 int nb_obj_frames;
00141 int nb_sky_frames;
00142 int nb_rej_frames;
00143 double iq;
00144 int nbobjs;
00145 double fwhm_pix;
00146 double fwhm_arcsec;
00147 double fwhm_mode;
00148 double angle_med;
00149 double ellip_med;
00150 } isaac_img_jitter_config;
00151
00152
00153
00154
00155
00156
00164
00165 static
00166 cpl_error_code isaac_img_jitter_fill_parameterlist(cpl_parameterlist * self)
00167 {
00168 const char * context = PACKAGE "." RECIPE_STRING;
00169 cpl_error_code err;
00170
00171 cpl_ensure_code(self, CPL_ERROR_NULL_INPUT);
00172
00173
00174
00175
00176 err = irplib_parameterlist_set_string(self, PACKAGE, RECIPE_STRING,
00177 "offsets", NULL, "off", context,
00178 "An optional ASCII specification of the offsets "
00179 "in case those in FITS-headers are missing or wrong. "
00180 "The file must consist of one line per object FITS-"
00181 "file and each line must consist of two "
00182 "numbers which represent the shift in pixels of that "
00183 "image relative to the first image. The first line "
00184 "should thus comprise two zeros. Correct FITS-header "
00185 "offsets mean that the i'th X offset can be gotten "
00186 "from Xoffset_0 - Xoffset_i, where Xoffset_i is the "
00187 "value of ESO SEQ CUMOFFSETX and likewise for Y.");
00188 cpl_ensure_code(!err, err);
00189
00190
00191 err = irplib_parameterlist_set_string(self, PACKAGE, RECIPE_STRING,
00192 "objects", NULL, "objs", context,
00193 "objects file");
00194 cpl_ensure_code(!err, err);
00195
00196
00197 err = irplib_parameterlist_set_bool(self, PACKAGE, RECIPE_STRING, "oddeven",
00198 CPL_FALSE, NULL, context, "Flag to "
00199 "correct the oddeven column effect");
00200 cpl_ensure_code(!err, err);
00201
00202
00203 err = irplib_parameterlist_set_string(self, PACKAGE, RECIPE_STRING,
00204 "sky_par", "10,7,3,3", NULL, context,
00205 "Rejection parameters for sky "
00206 "filtering");
00207 cpl_ensure_code(!err, err);
00208
00209
00210 err = irplib_parameterlist_set_string(self, PACKAGE, RECIPE_STRING, "xcorr",
00211 "40,40,65,65", NULL, context, "Cross "
00212 "correlation search and measure "
00213 "sizes");
00214 cpl_ensure_code(!err, err);
00215
00216
00217 err = irplib_parameterlist_set_string(self, PACKAGE, RECIPE_STRING,
00218 "comb_meth", "union", NULL, context,
00219 "union / inter / first");
00220 cpl_ensure_code(!err, err);
00221
00222
00223 err = irplib_parameterlist_set_bool(self, PACKAGE, RECIPE_STRING,
00224 "saa_refine", CPL_TRUE, NULL, context,
00225 "Flag to refine the offsets");
00226 cpl_ensure_code(!err, err);
00227
00228
00229 err = irplib_parameterlist_set_string(self, PACKAGE, RECIPE_STRING, "rej",
00230 "2,2", NULL, context, "Low and high "
00231 "number of rejected values");
00232 cpl_ensure_code(!err, err);
00233
00234
00235 err = irplib_parameterlist_set_bool(self, PACKAGE, RECIPE_STRING,
00236 "row_med", CPL_TRUE, NULL, context,
00237 "Flag to subtract the median of each "
00238 "row");
00239 cpl_ensure_code(!err, err);
00240
00241 return CPL_ERROR_NONE;
00242 }
00243
00244
00245
00246
00254
00255 static int isaac_img_jitter(cpl_frameset * framelist,
00256 const cpl_parameterlist * parlist)
00257 {
00258 const char * sval;
00259 const char * badpix;
00260 const char * flat;
00261 const char * dark;
00262 cpl_frameset * objframes = NULL;
00263 cpl_frameset * skyframes = NULL;
00264 cpl_image ** combined = NULL;
00265 cpl_table * objs_stats = NULL;
00266 cpl_vector * sky_bg = NULL;
00267
00268 bug_if(0);
00269
00270
00271 isaac_img_jitter_config.pixscale = -1.0;
00272 isaac_img_jitter_config.dit = -1.0;
00273 isaac_img_jitter_config.iq = -1.0;
00274 isaac_img_jitter_config.nbobjs = -1;
00275 isaac_img_jitter_config.fwhm_pix = -1.0;
00276 isaac_img_jitter_config.fwhm_arcsec = -1.0;
00277 isaac_img_jitter_config.fwhm_mode = -1.0;
00278 isaac_img_jitter_config.offsets = NULL;
00279 isaac_img_jitter_config.objects = NULL;
00280 isaac_img_jitter_config.nb_obj_frames = 0;
00281 isaac_img_jitter_config.nb_rej_frames = 0;
00282 isaac_img_jitter_config.nb_sky_frames = 0;
00283
00284
00285
00286 isaac_img_jitter_config.offsets
00287 = irplib_parameterlist_get_string(parlist, PACKAGE, RECIPE_STRING,
00288 "offsets");
00289
00290
00291 isaac_img_jitter_config.objects
00292 = irplib_parameterlist_get_string(parlist, PACKAGE, RECIPE_STRING,
00293 "objects");
00294
00295
00296 isaac_img_jitter_config.oddeven
00297 = irplib_parameterlist_get_bool(parlist, PACKAGE, RECIPE_STRING,
00298 "oddeven");
00299
00300
00301 sval = irplib_parameterlist_get_string(parlist, PACKAGE, RECIPE_STRING,
00302 "sky_par");
00303
00304 bug_if(sval == NULL);
00305
00306 skip_if (sscanf(sval, "%d,%d,%d,%d",
00307 &isaac_img_jitter_config.sky_minnb,
00308 &isaac_img_jitter_config.sky_halfw,
00309 &isaac_img_jitter_config.sky_rejmin,
00310 &isaac_img_jitter_config.sky_rejmax) != 4);
00311
00312
00313 sval = irplib_parameterlist_get_string(parlist, PACKAGE, RECIPE_STRING,
00314 "xcorr");
00315 bug_if(sval == NULL);
00316
00317 skip_if (sscanf(sval, "%d,%d,%d,%d",
00318 &isaac_img_jitter_config.sx,
00319 &isaac_img_jitter_config.sy,
00320 &isaac_img_jitter_config.mx,
00321 &isaac_img_jitter_config.my) != 4);
00322
00323
00324 sval = irplib_parameterlist_get_string(parlist, PACKAGE, RECIPE_STRING,
00325 "comb_meth");
00326 bug_if(sval == NULL);
00327 if (!strcmp(sval, "union"))
00328 isaac_img_jitter_config.comb_meth = CPL_GEOM_UNION;
00329 else if (!strcmp(sval, "inter"))
00330 isaac_img_jitter_config.comb_meth = CPL_GEOM_INTERSECT;
00331 else if (!strcmp(sval, "first"))
00332 isaac_img_jitter_config.comb_meth = CPL_GEOM_FIRST;
00333 else {
00334 cpl_msg_error(cpl_func, "Invalid combine method specified");
00335 skip_if(1);
00336 }
00337
00338
00339 isaac_img_jitter_config.saa_refine
00340 = irplib_parameterlist_get_bool(parlist, PACKAGE, RECIPE_STRING,
00341 "saa_refine");
00342
00343
00344 sval = irplib_parameterlist_get_string(parlist, PACKAGE, RECIPE_STRING,
00345 "rej");
00346 bug_if(sval == NULL);
00347 skip_if (sscanf(sval, "%d,%d",
00348 &isaac_img_jitter_config.rej_low,
00349 &isaac_img_jitter_config.rej_high) != 2);
00350
00351
00352 isaac_img_jitter_config.row_med
00353 = irplib_parameterlist_get_bool(parlist, PACKAGE, RECIPE_STRING,
00354 "row_med");
00355
00356
00357 skip_if (isaac_dfs_set_groups(framelist));
00358
00359
00360 flat = isaac_extract_filename(framelist, ISAAC_CALIB_FLAT);
00361 dark = isaac_extract_filename(framelist, ISAAC_CALIB_DARK);
00362 badpix = isaac_extract_filename(framelist, ISAAC_CALIB_BPM);
00363
00364
00365 if ((objframes = isaac_extract_frameset(framelist,
00366 ISAAC_IMG_JITTER_OBJ_RAW)) != NULL) {
00367 isaac_img_jitter_config.chopping = 0;
00368 } else if ((objframes = isaac_extract_frameset(framelist,
00369 ISAAC_IMG_JITTER_CHOP_RAW)) != NULL) {
00370 isaac_img_jitter_config.chopping = 1;
00371 } else {
00372 cpl_msg_error(cpl_func, "Cannot find objs frames in the input list");
00373 skip_if(1);
00374 }
00375 skyframes = isaac_extract_frameset(framelist, ISAAC_IMG_JITTER_SKY_RAW);
00376
00377
00378 cpl_msg_info(cpl_func, "Apply the data recombination");
00379 cpl_msg_indent_more();
00380 if ((combined = isaac_img_jitter_reduce(framelist, parlist, objframes,
00381 skyframes, flat,
00382 dark, badpix, &sky_bg)) == NULL) {
00383 cpl_msg_error(cpl_func, "Cannot recombine the data");
00384 cpl_msg_indent_less();
00385 skip_if(1);
00386 }
00387 cpl_msg_indent_less();
00388
00389
00390 cpl_msg_info(cpl_func, "Compute QC parameters from the combined image");
00391 cpl_msg_indent_more();
00392 if ((objs_stats = isaac_img_jitter_qc(combined[0])) == NULL) {
00393 cpl_msg_warning(cpl_func, "Cannot compute all parameters");
00394 }
00395 cpl_msg_indent_less();
00396
00397
00398 cpl_msg_info(cpl_func, "Save the products");
00399 skip_if (isaac_img_jitter_save(framelist, combined[0], combined[1],
00400 objs_stats, sky_bg, parlist));
00401
00402 end_skip;
00403
00404 cpl_frameset_delete(objframes);
00405 cpl_frameset_delete(skyframes);
00406 if (combined != NULL) {
00407 cpl_image_delete(combined[0]);
00408 cpl_image_delete(combined[1]);
00409 cpl_free(combined);
00410 }
00411 cpl_table_delete(objs_stats);
00412 cpl_vector_delete(sky_bg);
00413
00414 return cpl_error_get_code();
00415 }
00416
00417
00428
00429 static
00430 cpl_image ** isaac_img_jitter_reduce(cpl_frameset * frameset,
00431 const cpl_parameterlist * parlist,
00432 const cpl_frameset * obj,
00433 const cpl_frameset * sky,
00434 const char * flat,
00435 const char * dark,
00436 const char * bpm,
00437 cpl_vector ** skybg)
00438 {
00439 #ifdef ISAAC_IMG_ERR_ESTIMATE
00440 cpl_propertylist * qclist;
00441 cpl_imagelist * err;
00442 #endif
00443 cpl_imagelist ** in;
00444 cpl_image ** combined;
00445 cpl_imagelist * corrected;
00446 cpl_image * cur_im;
00447 int i;
00448
00449 cpl_ensure(frameset != NULL, CPL_ERROR_NULL_INPUT, NULL);
00450 cpl_ensure(parlist != NULL, CPL_ERROR_NULL_INPUT, NULL);
00451
00452
00453 *skybg = NULL;
00454 combined = NULL;
00455
00456
00457 cpl_msg_info(cpl_func, "Load the input data");
00458 cpl_msg_indent_more();
00459 if ((in = isaac_img_jitter_load(obj, sky)) == NULL) {
00460 cpl_msg_error(cpl_func, "Cannot load input data");
00461 cpl_msg_indent_less();
00462 return NULL;
00463 }
00464 cpl_msg_indent_less();
00465
00466
00467 if (isaac_img_jitter_config.oddeven) {
00468 cpl_msg_info(cpl_func, "Apply the odd-even effect correction");
00469 cpl_msg_indent_more();
00470 corrected = cpl_imagelist_new();
00471 for (i=0; i<cpl_imagelist_get_size(in[0]); i++) {
00472 cpl_msg_info(cpl_func, "Correct object frame nb %d", i+1);
00473 if ((cur_im = isaac_oddeven_correct(
00474 cpl_imagelist_get(in[0], i))) == NULL) {
00475 cpl_msg_warning(cpl_func,"Problem in odd-even corr. %d",i+1);
00476 cpl_imagelist_delete(corrected);
00477 corrected = NULL;
00478 break;
00479 }
00480 cpl_imagelist_set(corrected, cur_im, i);
00481 }
00482
00483 if (corrected != NULL) {
00484 cpl_imagelist_delete(in[0]);
00485 in[0] = corrected;
00486 }
00487 cpl_msg_indent_less();
00488 }
00489
00490 #ifdef ISAAC_IMG_ERR_ESTIMATE
00491
00492
00493
00494 err = cpl_imagelist_duplicate(in[0]);
00495
00496
00497 if (dark != NULL) {
00498 cpl_image * dark_image;
00499
00500 cpl_msg_info(cpl_func, "Error propagation: Subtract the dark to the images");
00501
00502 if ((dark_image = cpl_image_load(dark, CPL_TYPE_FLOAT, 0, 0)) == NULL) {
00503 cpl_msg_error(cpl_func, "Cannot load the dark %s", dark);
00504 return NULL;
00505 }
00506
00507 if (cpl_imagelist_subtract_image(err, dark_image)!=CPL_ERROR_NONE) {
00508 cpl_msg_error(cpl_func, "Cannot apply the dark to the images");
00509 cpl_image_delete(dark_image);
00510 return NULL;
00511 }
00512 cpl_image_delete(dark_image);
00513 }
00514
00515
00516
00517 if (bpm != NULL) {
00518 cpl_image * bpm_im;
00519 cpl_msg_info(cpl_func, "Error propagation: Correct the bad pixels in the images");
00520
00521 if ((bpm_im = cpl_image_load(bpm, CPL_TYPE_INT, 0, 0)) == NULL) {
00522 cpl_msg_error(cpl_func, "Cannot load the bad pixel map %s", bpm);
00523 return NULL;
00524 }
00525
00526
00527 cpl_image_cast(bpm_im, CPL_TYPE_DOUBLE);
00528 cpl_image_threshold(bpm_im, 0.4, 0.6, 1, 0);
00529
00530 cpl_imagelist_multiply_image(err, bpm_im);
00531
00532
00533 cpl_image_delete(bpm_im);
00534 }
00535
00536 cpl_imagelist_threshold(err, 1, ISAAC_IMG_SATURATION_LEVEL,
00537 FLT_MAX, FLT_MAX);
00538 cpl_imagelist_divide_scalar(err, ISAAC_IMG_GAIN);
00539 cpl_imagelist_power(err, 0.5);
00540
00541
00542 if (flat != NULL) {
00543 cpl_image * flat_image;
00544 cpl_msg_info(cpl_func, "Error propagation: Divide the images by the flatfield");
00545
00546 if ((flat_image = cpl_image_load(flat, CPL_TYPE_FLOAT, 0, 0)) == NULL) {
00547 cpl_msg_error(cpl_func, "Cannot load the flat field %s", flat);
00548 return NULL;
00549 }
00550
00551 if (cpl_imagelist_divide_image(err, flat_image)!=CPL_ERROR_NONE) {
00552 cpl_msg_error(cpl_func, "Cannot apply the flatfield to the images");
00553 cpl_image_delete(flat_image);
00554 return NULL;
00555 }
00556 cpl_image_delete(flat_image);
00557 }
00558 cpl_imagelist_threshold(err, 1, ISAAC_IMG_SATURATION_LEVEL,
00559 FLT_MAX, FLT_MAX);
00560
00561
00562 #endif
00563
00564
00565 if (flat || dark || bpm) {
00566 cpl_msg_info(cpl_func, "Apply the calibrations");
00567 cpl_msg_indent_more();
00568 if (irplib_flat_dark_bpm_calib(in[0], flat, dark, bpm) == -1) {
00569
00570 cpl_msg_error(cpl_func, "Cannot calibrate the objects");
00571 cpl_imagelist_delete(in[0]);
00572 if (in[1]) cpl_imagelist_delete(in[1]);
00573 cpl_free(in);
00574 cpl_msg_indent_less();
00575 return NULL;
00576 }
00577 if (in[1]) {
00578 if (irplib_flat_dark_bpm_calib(in[1], flat, dark, bpm) == -1) {
00579
00580 cpl_msg_error(cpl_func, "Cannot calibrate the sky");
00581 cpl_imagelist_delete(in[0]);
00582 if (in[1]) cpl_imagelist_delete(in[1]);
00583 cpl_free(in);
00584 cpl_msg_indent_less();
00585 return NULL;
00586 }
00587 }
00588 cpl_msg_indent_less();
00589 }
00590
00591
00592 #ifdef ISAAC_IMG_ERR_ESTIMATE
00593
00594
00595 qclist = cpl_propertylist_new();
00596
00597 cpl_propertylist_update_string(qclist, CPL_DFS_PRO_CATG, "ISAAC_IMAGELIST");
00598 if(cpl_dfs_save_imagelist(frameset,
00599 NULL,
00600 parlist,
00601 frameset,
00602 NULL,
00603 in[0],
00604 CPL_BPP_IEEE_FLOAT,
00605 RECIPE_STRING,
00606 qclist,
00607 NULL,
00608 PACKAGE "/" PACKAGE_VERSION,
00609 "isaac_img_imagelist.fits")) {
00610
00611 (void)cpl_error_set_where(cpl_func);
00612 }
00613
00614 cpl_propertylist_update_string(qclist, CPL_DFS_PRO_CATG, "ISAAC_IMAGELISTERR");
00615 if(cpl_dfs_save_imagelist(frameset,
00616 NULL,
00617 parlist,
00618 frameset,
00619 NULL,
00620 err,
00621 CPL_BPP_IEEE_FLOAT,
00622 RECIPE_STRING,
00623 qclist,
00624 NULL,
00625 PACKAGE "/" PACKAGE_VERSION,
00626 "isaac_img_imagelist_error.fits")) {
00627
00628 (void)cpl_error_set_where(cpl_func);
00629 }
00630
00631 cpl_propertylist_delete(qclist);
00632 cpl_imagelist_delete(err);
00633 #endif
00634
00635
00636 if (isaac_img_jitter_config.chopping == 0) {
00637 cpl_msg_info(cpl_func, "Sky estimation and correction");
00638 cpl_msg_indent_more();
00639 if ((*skybg = isaac_img_jitter_sky(&(in[0]), in[1])) == NULL) {
00640 cpl_msg_error(cpl_func, "Cannot estimate the sky");
00641 cpl_imagelist_delete(in[0]);
00642 if (in[1]) cpl_imagelist_delete(in[1]);
00643 cpl_free(in);
00644 cpl_msg_indent_less();
00645 return NULL;
00646 }
00647 cpl_msg_indent_less();
00648 }
00649 isaac_img_jitter_config.nb_obj_frames = cpl_imagelist_get_size(in[0]);
00650 if (in[1] != NULL)
00651 isaac_img_jitter_config.nb_sky_frames = cpl_imagelist_get_size(in[1]);
00652 if (in[1]) cpl_imagelist_delete(in[1]);
00653 in[1] = NULL;
00654
00655
00656 cpl_msg_info(cpl_func, "Shift and add");
00657 cpl_msg_indent_more();
00658 if (isaac_img_jitter_config.chopping == 0) {
00659 combined = isaac_img_jitter_saa_nochop(in[0], obj);
00660 } else if (isaac_img_jitter_config.chopping == 1) {
00661 combined = isaac_img_jitter_saa_chop(in[0], obj);
00662 }
00663 if (combined == NULL) {
00664 cpl_msg_error(cpl_func, "Cannot apply the shift and add");
00665 cpl_imagelist_delete(in[0]);
00666 cpl_free(in);
00667 if (*skybg != NULL) cpl_vector_delete(*skybg);
00668 *skybg = NULL;
00669 cpl_msg_indent_less();
00670 return NULL;
00671 }
00672 cpl_imagelist_delete(in[0]);
00673 cpl_free(in);
00674 cpl_msg_indent_less();
00675
00676
00677 if (isaac_img_jitter_config.row_med) {
00678 cpl_msg_info(cpl_func, "Subtract the median from each row");
00679 skip_if(isaac_img_jitter_sub_row_median(combined[0]));
00680 }
00681
00682 end_skip;
00683
00684 return combined;
00685 }
00686
00687
00694
00695 static cpl_imagelist ** isaac_img_jitter_load(
00696 const cpl_frameset * obj,
00697 const cpl_frameset * sky)
00698 {
00699 cpl_imagelist ** isets;
00700 cpl_imagelist * chop_b;
00701 const cpl_frame * frame;
00702 cpl_propertylist * plist;
00703 const char * sval;
00704
00705
00706 if (obj == NULL) return NULL;
00707
00708
00709 cpl_ensure(!cpl_error_get_code(), cpl_error_get_code(), NULL);
00710
00711
00712 frame = cpl_frameset_get_frame_const(obj, 0);
00713 cpl_ensure(frame != NULL, cpl_error_get_code(), NULL);
00714
00715 plist=cpl_propertylist_load(cpl_frame_get_filename(frame), 0);
00716 cpl_ensure(!cpl_error_get_code(), cpl_error_get_code(), NULL);
00717
00718 isaac_img_jitter_config.pixscale = isaac_pfits_get_pixscale(plist);
00719 isaac_img_jitter_config.dit = isaac_pfits_get_dit(plist);
00720 sval = isaac_pfits_get_frame_type(plist);
00721 if (sval == NULL) {
00722 cpl_msg_error(cpl_func, "Could not get frame type for jitter");
00723 cpl_propertylist_delete(plist);
00724 return NULL;
00725 } else if ((isaac_img_jitter_config.chopping==0) && strcmp(sval, "INT")) {
00726 cpl_msg_error(cpl_func, "Wrong type for jitter: %s - Should be INT",
00727 sval);
00728 cpl_propertylist_delete(plist);
00729 return NULL;
00730 } else if ((isaac_img_jitter_config.chopping==1) && strcmp(sval, "CUBE1")) {
00731 cpl_msg_error(cpl_func, "Wrong type for chopping: %s - Should be CUBE1",
00732 sval);
00733 cpl_propertylist_delete(plist);
00734 return NULL;
00735 }
00736 cpl_propertylist_delete(plist);
00737 if (cpl_error_get_code()) {
00738 cpl_msg_error(cpl_func, "Missing keyword in FITS header");
00739 return NULL;
00740 }
00741
00742
00743 isets = cpl_malloc(2 * sizeof(cpl_imagelist *));
00744
00745
00746 if (isaac_img_jitter_config.chopping == 0) {
00747 isets[0] = cpl_imagelist_load_frameset(obj, CPL_TYPE_FLOAT, 1, 0);
00748 if (sky != NULL)
00749 isets[1] = cpl_imagelist_load_frameset(sky, CPL_TYPE_FLOAT, 1, 0);
00750 else isets[1] = NULL;
00751 } else if (isaac_img_jitter_config.chopping == 1) {
00752 isets[1] = NULL;
00753 isets[0] = cpl_imagelist_load_frameset(obj, CPL_TYPE_FLOAT, 1, 0);
00754 chop_b = cpl_imagelist_load_frameset(obj, CPL_TYPE_FLOAT, 2, 0);
00755 cpl_imagelist_subtract(isets[0], chop_b);
00756 cpl_imagelist_delete(chop_b);
00757 }
00758
00759
00760 if (isets[0] == NULL) {
00761 cpl_msg_error(cpl_func, "The objects frames could not be loaded");
00762 if (isets[1] != NULL) cpl_imagelist_delete(isets[1]);
00763 cpl_free(isets);
00764 return NULL;
00765 }
00766
00767 return isets;
00768 }
00769
00770
00777
00778 static cpl_vector * isaac_img_jitter_sky(
00779 cpl_imagelist ** objs,
00780 cpl_imagelist * skys)
00781 {
00782 cpl_image * sky;
00783 cpl_vector * bg;
00784 int sky_method;
00785 int nframes, nskys;
00786 double median;
00787 cpl_image * cur_ima;
00788 int i;
00789
00790
00791 bg = NULL;
00792 nframes = cpl_imagelist_get_size(*objs);
00793
00794
00795 if (isaac_img_jitter_config.sky_minnb > nframes) sky_method = 1;
00796 else sky_method = 2;
00797
00798
00799 if (skys != NULL) {
00800 cpl_msg_info(cpl_func, "Median of sky images");
00801
00802 nskys = cpl_imagelist_get_size(skys);
00803 bg = cpl_vector_new(nskys);
00804 for (i=0; i<nskys; i++) {
00805 median = cpl_image_get_median(cpl_imagelist_get(skys, i));
00806 cpl_vector_set(bg, i, median);
00807 }
00808
00809 if ((sky = cpl_imagelist_collapse_median_create(skys)) == NULL) {
00810 cpl_msg_error(cpl_func, "Cannot compute the median of sky images");
00811 cpl_vector_delete(bg);
00812 return NULL;
00813 }
00814
00815 if (cpl_imagelist_subtract_image(*objs, sky) != CPL_ERROR_NONE) {
00816 cpl_msg_error(cpl_func, "Cannot corr. the obj images from the sky");
00817 cpl_image_delete(sky);
00818 cpl_vector_delete(bg);
00819 return NULL;
00820 }
00821 cpl_image_delete(sky);
00822
00823 for (i=0; i<nframes; i++) {
00824 cur_ima = cpl_imagelist_get(*objs, i);
00825 median = cpl_image_get_median(cur_ima);
00826 cpl_image_subtract_scalar(cur_ima, median);
00827 }
00828 } else if (sky_method == 1) {
00829 cpl_msg_info(cpl_func, "Median of object images");
00830
00831 if ((sky = cpl_imagelist_collapse_median_create(*objs)) == NULL) {
00832 cpl_msg_error(cpl_func, "Cannot compute the median of obj images");
00833 return NULL;
00834 }
00835
00836 if (cpl_imagelist_subtract_image(*objs, sky) != CPL_ERROR_NONE) {
00837 cpl_msg_error(cpl_func, "Cannot corr. the obj images from the sky");
00838 cpl_image_delete(sky);
00839 return NULL;
00840 }
00841
00842 bg = cpl_vector_new(1);
00843 cpl_vector_set(bg, 0, cpl_image_get_median(sky));
00844 cpl_image_delete(sky);
00845
00846 for (i=0; i<nframes; i++) {
00847 cur_ima = cpl_imagelist_get(*objs, i);
00848 median = cpl_image_get_median(cur_ima);
00849 cpl_image_subtract_scalar(cur_ima, median);
00850 }
00851 } else if (sky_method == 2) {
00852 cpl_msg_info(cpl_func, "Running filter on object images");
00853
00854 if ((bg = isaac_img_jitter_sky_running(objs)) == NULL) {
00855 cpl_msg_error(cpl_func,
00856 "Cannot apply the running filter for the sky");
00857 return NULL;
00858 }
00859 }
00860
00861 return bg;
00862 }
00863
00864
00883
00884 static cpl_vector * isaac_img_jitter_sky_running(cpl_imagelist ** in)
00885 {
00886 int rejmin, rejmax, halfw;
00887 cpl_imagelist * filtres;
00888 int ni, nx, ny, pos;
00889 cpl_vector * medians;
00890 cpl_image * cur_ima;
00891 float * pcur_ima;
00892 cpl_image * tmp_ima;
00893 float * ptmp_ima;
00894 cpl_vector * localwin;
00895 int fr_p, to_p, n_curp;
00896 cpl_vector * bg;
00897 double bg_val, out;
00898 float one_med;
00899 int i, j, k;
00900
00901
00902 if (in==NULL || *in == NULL) return NULL;
00903
00904
00905 rejmin = isaac_img_jitter_config.sky_rejmin;
00906 rejmax = isaac_img_jitter_config.sky_rejmax;
00907 halfw = isaac_img_jitter_config.sky_halfw;
00908 ni = cpl_imagelist_get_size(*in);
00909 cur_ima = cpl_imagelist_get(*in, 0);
00910 nx = cpl_image_get_size_x(cur_ima);
00911 ny = cpl_image_get_size_y(cur_ima);
00912
00913
00914 if (((rejmin+rejmax)>=halfw) || (halfw<1) || (rejmin<0) || (rejmax<0)) {
00915 cpl_msg_error(cpl_func, "cannot run filter with rej parms %d (%d-%d)",
00916 halfw, rejmin, rejmax);
00917 return NULL;
00918 }
00919
00920 medians = cpl_vector_new(ni);
00921 for (i=0; i<ni; i++) {
00922 cur_ima = cpl_imagelist_get(*in, i);
00923 cpl_vector_set(medians, i, cpl_image_get_median(cur_ima));
00924 }
00925
00926 filtres = cpl_imagelist_new();
00927
00928
00929 bg = cpl_vector_new(ni);
00930
00931
00932 for (k=0; k<ni; k++) {
00933
00934 tmp_ima = cpl_image_new(nx, ny, CPL_TYPE_FLOAT);
00935 ptmp_ima = cpl_image_get_data_float(tmp_ima);
00936
00937 fr_p = k - halfw;
00938 to_p = k + halfw;
00939 if (fr_p<0) fr_p=0;
00940 if (to_p>(ni-1)) to_p=ni-1;
00941
00942
00943 n_curp = to_p - fr_p;
00944
00945
00946 localwin = cpl_vector_new(n_curp);
00947
00948 bg_val = 0.0;
00949
00950 for (pos=0; pos<nx*ny; pos++) {
00951
00952 j=0;
00953 for (i=fr_p; i<=to_p; i++) {
00954 if (i!=k) {
00955 cur_ima = cpl_imagelist_get(*in, i);
00956 pcur_ima = cpl_image_get_data_float(cur_ima);
00957 cpl_vector_set(localwin, j,
00958 (double)pcur_ima[pos]-cpl_vector_get(medians, i));
00959 j++;
00960 }
00961 }
00962
00963 cpl_vector_sort(localwin, 1);
00964
00965 out = 0.0;
00966 for (i=rejmin; i<(n_curp-rejmax); i++) {
00967 out += cpl_vector_get(localwin, i);
00968 }
00969
00970 out /= (double)(n_curp - rejmin - rejmax);
00971
00972 cur_ima = cpl_imagelist_get(*in, k);
00973 pcur_ima = cpl_image_get_data_float(cur_ima);
00974 ptmp_ima[pos] = pcur_ima[pos] -
00975 (float)(out + cpl_vector_get(medians, k));
00976
00977 bg_val += (out+cpl_vector_get(medians, k));
00978 }
00979 cpl_vector_delete(localwin);
00980 cpl_vector_set(bg, k, bg_val/(nx*ny));
00981 cpl_imagelist_set(filtres, tmp_ima, k);
00982 }
00983 cpl_imagelist_delete(*in);
00984 cpl_vector_delete(medians);
00985
00986
00987 for (i=0; i<ni; i++) {
00988 cur_ima = cpl_imagelist_get(filtres, i);
00989 one_med = cpl_image_get_median(cur_ima);
00990 cpl_image_subtract_scalar(cur_ima, one_med);
00991 }
00992 *in = filtres;
00993 return bg;
00994 }
00995
00996
01003
01004 static cpl_image ** isaac_img_jitter_saa_nochop(
01005 cpl_imagelist * in,
01006 const cpl_frameset * objframes)
01007 {
01008 const cpl_frame * frame;
01009 cpl_propertylist * plist;
01010 cpl_bivector * offsets_est;
01011 double * offsets_est_x;
01012 double * offsets_est_y;
01013 cpl_bivector * objs;
01014 double * objs_x;
01015 double * objs_y;
01016 cpl_apertures * aperts;
01017 cpl_image ** combined;
01018 cpl_vector * thresh_vect;
01019 cpl_image * diff;
01020 int nfiles;
01021 int nima;
01022 int refine =
01023 isaac_img_jitter_config.saa_refine ? 1 : 0;
01024 int i;
01025
01026
01027 nfiles = cpl_imagelist_get_size(in);
01028 if (cpl_frameset_get_size(objframes) != nfiles) {
01029 cpl_msg_error(cpl_func, "Invalid input objects sizes");
01030 return NULL;
01031 }
01032
01033
01034 cpl_msg_info(cpl_func, "Get the offsets estimation");
01035 offsets_est = NULL;
01036 if (isaac_img_jitter_config.offsets &&
01037 isaac_img_jitter_config.offsets[0] != (char)0) {
01038
01039 offsets_est = cpl_bivector_read(isaac_img_jitter_config.offsets);
01040 if ((offsets_est==NULL)||(cpl_bivector_get_size(offsets_est)!=nfiles)) {
01041 cpl_msg_error(cpl_func, "Cannot get offsets from %s",
01042 isaac_img_jitter_config.offsets);
01043 return NULL;
01044 }
01045 } else {
01046
01047 offsets_est = cpl_bivector_new(nfiles);
01048 offsets_est_x = cpl_bivector_get_x_data(offsets_est);
01049 offsets_est_y = cpl_bivector_get_y_data(offsets_est);
01050 for (i=0; i<nfiles; i++) {
01051 if (cpl_error_get_code()) {
01052 cpl_bivector_delete(offsets_est);
01053 offsets_est = NULL;
01054 break;
01055 }
01056
01057 frame = cpl_frameset_get_frame_const(objframes, i);
01058 plist=cpl_propertylist_load(cpl_frame_get_filename(frame),0);
01059 offsets_est_x[i] = -1.0 * isaac_pfits_get_cumoffsetx(plist);
01060 offsets_est_y[i] = -1.0 * isaac_pfits_get_cumoffsety(plist);
01061 cpl_propertylist_delete(plist);
01062 if (cpl_error_get_code()) {
01063 cpl_msg_warning(cpl_func, "Cannot get offsets from header");
01064 cpl_bivector_delete(offsets_est);
01065 offsets_est = NULL;
01066 break;
01067 }
01068 if (i > 0) {
01069
01070 offsets_est_x[i] -= offsets_est_x[0];
01071 offsets_est_y[i] -= offsets_est_y[0];
01072 }
01073 }
01074 if (i == nfiles) {
01075 offsets_est_x[0] = offsets_est_y[0] = 0.0;
01076 }
01077 }
01078
01079
01080 objs = NULL;
01081 if (isaac_img_jitter_config.objects &&
01082 isaac_img_jitter_config.objects[0] != (char)0) {
01083 cpl_msg_info(cpl_func, "Get the user provided correlation objects");
01084
01085 objs = cpl_bivector_read(isaac_img_jitter_config.objects);
01086 if (objs==NULL) {
01087 cpl_msg_error(cpl_func, "Cannot get objects from %s",
01088 isaac_img_jitter_config.objects);
01089 if (offsets_est) cpl_bivector_delete(offsets_est);
01090 return NULL;
01091 }
01092 }
01093
01094
01095 if (objs == NULL) {
01096 cpl_msg_info(cpl_func, "Get a cross-correlation point");
01097 thresh_vect = cpl_vector_new(4);
01098 cpl_vector_set(thresh_vect, 0, 5.0);
01099 cpl_vector_set(thresh_vect, 1, 2.0);
01100 cpl_vector_set(thresh_vect, 2, 1.0);
01101 cpl_vector_set(thresh_vect, 3, 0.5);
01102 diff = cpl_image_subtract_create(cpl_imagelist_get(in, 0),
01103 cpl_imagelist_get(in, 1));
01104 if ((aperts = cpl_apertures_extract_window(diff, thresh_vect,
01105 200, 200, 800, 800, NULL)) == NULL) {
01106 cpl_msg_error(cpl_func, "Cannot find any cross-correlation point");
01107 if (offsets_est) cpl_bivector_delete(offsets_est);
01108 cpl_vector_delete(thresh_vect);
01109 cpl_image_delete(diff);
01110 return NULL;
01111 }
01112 cpl_image_delete(diff);
01113 cpl_vector_delete(thresh_vect);
01114 cpl_apertures_sort_by_npix(aperts);
01115 objs = cpl_bivector_new(1);
01116 objs_x = cpl_bivector_get_x_data(objs);
01117 objs_y = cpl_bivector_get_y_data(objs);
01118 objs_x[0] = cpl_apertures_get_max_x(aperts, 1);
01119 objs_y[0] = cpl_apertures_get_max_y(aperts, 1);
01120 cpl_apertures_delete(aperts);
01121 if (objs == NULL) {
01122 cpl_msg_error(cpl_func, "Cannot find any cross-correlation point");
01123 if (offsets_est) cpl_bivector_delete(offsets_est);
01124 return NULL;
01125 }
01126 cpl_msg_info(cpl_func,
01127 "Correlation point: %g %g\n", objs_x[0], objs_y[0]);
01128 }
01129
01130
01131 cpl_msg_info(cpl_func, "Recombine the images set");
01132 cpl_msg_indent_more();
01133 if ((combined = cpl_geom_img_offset_combine(in, offsets_est, refine, objs,
01134 NULL, NULL,
01135 isaac_img_jitter_config.sx,
01136 isaac_img_jitter_config.sy,
01137 isaac_img_jitter_config.mx,
01138 isaac_img_jitter_config.my,
01139 isaac_img_jitter_config.rej_low,
01140 isaac_img_jitter_config.rej_high,
01141 isaac_img_jitter_config.comb_meth)) == NULL) {
01142 cpl_msg_error(cpl_func, "Cannot recombine the images");
01143 if (offsets_est) cpl_bivector_delete(offsets_est);
01144 cpl_bivector_delete(objs);
01145 cpl_msg_indent_less();
01146 return NULL;
01147 }
01148
01149 i = (int)(cpl_image_get_max(combined[1]));
01150 nima = cpl_imagelist_get_size(in);
01151 if ((nima > 3) && (nima>2*
01152 (isaac_img_jitter_config.rej_low+isaac_img_jitter_config.rej_high)))
01153 i += isaac_img_jitter_config.rej_low+isaac_img_jitter_config.rej_high;
01154 isaac_img_jitter_config.nb_rej_frames =
01155 isaac_img_jitter_config.nb_obj_frames - i;
01156 isaac_img_jitter_config.nb_obj_frames = i;
01157 cpl_msg_indent_less();
01158
01159
01160 if (offsets_est) cpl_bivector_delete(offsets_est);
01161 cpl_bivector_delete(objs);
01162 return combined;
01163 }
01164
01165
01166
01173
01174 static cpl_image ** isaac_img_jitter_saa_chop(
01175 cpl_imagelist * in,
01176 const cpl_frameset * objframes)
01177 {
01178 const cpl_frame * frame;
01179 cpl_propertylist * plist;
01180 cpl_bivector * offsets_est;
01181 cpl_bivector * offsets_est_nod;
01182 double * offsets_est_x;
01183 double * offsets_est_y;
01184 double * offsets_est_nod_x;
01185 double * offsets_est_nod_y;
01186 cpl_bivector * objs;
01187 cpl_image ** combined;
01188 cpl_vector * thresh_vect;
01189 int nfiles, nb_chop;
01190 int * chop_a;
01191 int * chop_b;
01192 cpl_imagelist * nodded;
01193 cpl_image * tmp_ima;
01194 int refine =
01195 isaac_img_jitter_config.saa_refine ? 1 : 0;
01196 int i;
01197
01198
01199 nfiles = cpl_imagelist_get_size(in);
01200 if (cpl_frameset_get_size(objframes) != nfiles) {
01201 cpl_msg_error(cpl_func, "Invalid input objects sizes");
01202 return NULL;
01203 }
01204
01205
01206 cpl_msg_info(cpl_func, "Get the offsets estimation");
01207 offsets_est = NULL;
01208 if (isaac_img_jitter_config.offsets &&
01209 isaac_img_jitter_config.offsets[0] != (char)0) {
01210
01211 offsets_est = cpl_bivector_read(isaac_img_jitter_config.offsets);
01212 if ((offsets_est==NULL) ||
01213 (cpl_bivector_get_size(offsets_est) != nfiles)) {
01214 cpl_msg_error(cpl_func, "Cannot get offsets from %s",
01215 isaac_img_jitter_config.offsets);
01216 return NULL;
01217 }
01218 offsets_est_x = cpl_bivector_get_x_data(offsets_est);
01219 offsets_est_y = cpl_bivector_get_y_data(offsets_est);
01220 } else {
01221
01222 offsets_est = cpl_bivector_new(nfiles);
01223 offsets_est_x = cpl_bivector_get_x_data(offsets_est);
01224 offsets_est_y = cpl_bivector_get_y_data(offsets_est);
01225 for (i=0; i<nfiles; i++) {
01226 if (cpl_error_get_code()) {
01227 cpl_bivector_delete(offsets_est);
01228 return NULL;
01229 }
01230
01231 frame = cpl_frameset_get_frame_const(objframes, i);
01232 plist=cpl_propertylist_load(cpl_frame_get_filename(frame),0);
01233 offsets_est_x[i] = -1.0 * isaac_pfits_get_cumoffsetx(plist);
01234 offsets_est_y[i] = -1.0 * isaac_pfits_get_cumoffsety(plist);
01235 cpl_propertylist_delete(plist);
01236 if (cpl_error_get_code()) {
01237 cpl_msg_warning(cpl_func, "Cannot get offsets from header");
01238 cpl_bivector_delete(offsets_est);
01239 return NULL;
01240 }
01241 }
01242
01243 for (i=1; i<nfiles; i++) {
01244 offsets_est_x[i] -= offsets_est_x[0];
01245 offsets_est_y[i] -= offsets_est_y[0];
01246 }
01247 offsets_est_x[0] = offsets_est_y[0] = 0.00;
01248 }
01249
01250
01251 if ((nb_chop=isaac_img_jitter_chopping_classif(offsets_est,
01252 &chop_a, &chop_b)) == -1) {
01253 cpl_msg_error(cpl_func, "cannot classify chopped frames");
01254 cpl_bivector_delete(offsets_est);
01255 return NULL;
01256 }
01257
01258
01259 nodded = cpl_imagelist_new();
01260 for (i=0; i<nb_chop; i++) {
01261 tmp_ima = cpl_image_subtract_create(
01262 cpl_imagelist_get(in, chop_a[i]),
01263 cpl_imagelist_get(in, chop_b[i]));
01264 cpl_imagelist_set(nodded, tmp_ima, i);
01265 }
01266
01267
01268 offsets_est_nod = cpl_bivector_new(nb_chop);
01269 offsets_est_nod_x = cpl_bivector_get_x_data(offsets_est_nod);
01270 offsets_est_nod_y = cpl_bivector_get_y_data(offsets_est_nod);
01271 for (i=0; i<nb_chop; i++) {
01272 offsets_est_nod_x[i] = offsets_est_x[chop_a[i]];
01273 offsets_est_nod_y[i] = offsets_est_y[chop_a[i]];
01274 }
01275 cpl_bivector_delete(offsets_est);
01276 cpl_free(chop_a);
01277 cpl_free(chop_b);
01278
01279
01280 objs = NULL;
01281 if (isaac_img_jitter_config.objects &&
01282 isaac_img_jitter_config.objects[0] != (char)0) {
01283 cpl_msg_info(cpl_func, "Get the user provided correlation objects");
01284
01285 objs = cpl_bivector_read(isaac_img_jitter_config.objects);
01286 if (objs==NULL) {
01287 cpl_msg_error(cpl_func, "Cannot get objects from %s",
01288 isaac_img_jitter_config.objects);
01289 cpl_bivector_delete(offsets_est_nod);
01290 cpl_imagelist_delete(nodded);
01291 return NULL;
01292 }
01293 }
01294
01295
01296 thresh_vect = cpl_vector_new(4);
01297 cpl_vector_set(thresh_vect, 0, 5.0);
01298 cpl_vector_set(thresh_vect, 1, 2.0);
01299 cpl_vector_set(thresh_vect, 2, 1.0);
01300 cpl_vector_set(thresh_vect, 3, 0.5);
01301
01302
01303 cpl_msg_info(cpl_func, "Recombine the images set");
01304 cpl_msg_indent_more();
01305 if ((combined = cpl_geom_img_offset_combine(nodded, offsets_est_nod,
01306 refine, objs, thresh_vect, NULL,
01307 isaac_img_jitter_config.sx,
01308 isaac_img_jitter_config.sy,
01309 isaac_img_jitter_config.mx,
01310 isaac_img_jitter_config.my,
01311 isaac_img_jitter_config.rej_low,
01312 isaac_img_jitter_config.rej_high,
01313 isaac_img_jitter_config.comb_meth)) == NULL) {
01314 cpl_msg_error(cpl_func, "Cannot recombine the images");
01315 cpl_bivector_delete(offsets_est_nod);
01316 cpl_imagelist_delete(nodded);
01317 if (objs) cpl_bivector_delete(objs);
01318 cpl_vector_delete(thresh_vect);
01319 cpl_msg_indent_less();
01320 return NULL;
01321 }
01322
01323 i = (int)(cpl_image_get_max(combined[1]));
01324 isaac_img_jitter_config.nb_rej_frames =
01325 isaac_img_jitter_config.nb_obj_frames - i;
01326 isaac_img_jitter_config.nb_obj_frames = i;
01327 cpl_msg_indent_less();
01328
01329
01330 cpl_vector_delete(thresh_vect);
01331 cpl_bivector_delete(offsets_est_nod);
01332 cpl_imagelist_delete(nodded);
01333 if (objs) cpl_bivector_delete(objs);
01334 return combined;
01335 }
01336
01337
01345
01346 static int isaac_img_jitter_chopping_classif(
01347 cpl_bivector * offsets,
01348 int ** chop_a,
01349 int ** chop_b)
01350 {
01351 int nb_obj;
01352 double * offsets_x;
01353 double * offsets_y;
01354 double throw_x,
01355 throw_y;
01356 double * dist;
01357 int * dcount;
01358 int max_count;
01359 int i_max, j_max;
01360 int classified;
01361 int i, j, k, l;
01362
01363
01364 if (offsets==NULL || chop_a==NULL || chop_b==NULL) return -1;
01365
01366
01367 *chop_a = *chop_b = NULL;
01368
01369
01370 nb_obj = cpl_bivector_get_size(offsets);
01371 offsets_x = cpl_bivector_get_x_data(offsets);
01372 offsets_y = cpl_bivector_get_y_data(offsets);
01373
01374
01375 if (nb_obj == 0) return -1;
01376
01377
01378 if (nb_obj%2) {
01379 cpl_msg_error(cpl_func, "odd number of frames in input [%d]", nb_obj);
01380 return -1;
01381 }
01382
01383
01384 dist = cpl_calloc(nb_obj*nb_obj, sizeof(double));
01385 dcount = cpl_calloc(nb_obj*nb_obj, sizeof(int));
01386 for (i=0; i<nb_obj; i++) {
01387 for (j=0; j<nb_obj; j++) {
01388 dist[i+j*nb_obj] = sqrt(SQR(offsets_x[i] - offsets_x[j]) +
01389 SQR(offsets_y[i] - offsets_y[j]));
01390 }
01391 }
01392
01393 for (i=0; i<nb_obj*nb_obj; i++) {
01394 for (j=0; j<nb_obj*nb_obj; j++)
01395 if (fabs(dist[i]-dist[j]) <= NEGLIG_OFF_DIFF) dcount[i] ++;
01396 }
01397
01398
01399 max_count = 0;
01400 i_max = 0;
01401 j_max = 0;
01402 for (i=0; i<nb_obj; i++){
01403 for (j=0; j<nb_obj; j++) {
01404 if ((dcount[i+j*nb_obj]>max_count)&&(dist[i+j*nb_obj]>0.5)){
01405 max_count = dcount[i+j*nb_obj];
01406 i_max = i;
01407 j_max = j;
01408 }
01409 }
01410 }
01411
01412
01413 throw_x = offsets_x[j_max] - offsets_x[i_max];
01414 throw_y = offsets_y[j_max] - offsets_y[i_max];
01415
01416 cpl_msg_info(cpl_func, "Typical (%d) non-zero throw is (%g, %g) from %d "
01417 "(%g, %g) to %d (%g, %g)", max_count, throw_x, throw_y,
01418 i_max, offsets_x[i_max], offsets_y[i_max],
01419 j_max, offsets_x[j_max], offsets_y[j_max]);
01420
01421
01422 cpl_free(dist);
01423 cpl_free(dcount);
01424
01425
01426 if ((throw_x == 0) && (throw_y == 0)) {
01427 cpl_msg_error(cpl_func, "Throw is equal to 0 - cannot classify");
01428 return -1;
01429 }
01430
01431
01432 *chop_a = cpl_calloc(nb_obj/2, sizeof(int));
01433 *chop_b = cpl_calloc(nb_obj/2, sizeof(int));
01434
01435 k = l = 0;
01436 for (i=0; i<nb_obj-1; i++) {
01437
01438
01439 if ((fabs(offsets_x[i]-offsets_x[i+1]+throw_x) < NEGLIG_OFF_DIFF) &&
01440 (fabs(offsets_y[i]-offsets_y[i+1]+throw_y) < NEGLIG_OFF_DIFF)) {
01441 (*chop_a)[k++] = i;
01442 (*chop_b)[l++] = i+1;
01443
01444 } else if ((fabs(offsets_x[i]-offsets_x[i+1]-throw_x) <
01445 NEGLIG_OFF_DIFF) &&
01446 (fabs(offsets_y[i]-offsets_y[i+1]-throw_y) <
01447 NEGLIG_OFF_DIFF)) {
01448 (*chop_b)[l++] = i;
01449 (*chop_a)[k++] = i+1;
01450
01451 }
01452 }
01453
01454 cpl_msg_info(cpl_func, "Found %d A- and %d B-frames (out of %d)", k, l,
01455 nb_obj);
01456
01457
01458 for (i=0; i<nb_obj; i++) {
01459 classified = 0;
01460
01461 for (j=0; j < nb_obj/2; j++) {
01462 if ((*chop_a)[j] == i || (*chop_b)[j] == i) classified = 1;
01463 }
01464 if (classified == 0) {
01465 cpl_msg_error(cpl_func, "Frame %d cannot be classified", i+1);
01466 cpl_free(*chop_a);
01467 cpl_free(*chop_b);
01468 *chop_a = *chop_b = NULL;
01469 return -1;
01470 }
01471 }
01472
01473
01474 if (k != l) {
01475 cpl_free(*chop_a);
01476 cpl_free(*chop_b);
01477 *chop_a = *chop_b = NULL;
01478 return -1;
01479 }
01480 return k;
01481 }
01482
01483
01490
01491 static cpl_error_code isaac_img_jitter_sub_row_median(cpl_image * self)
01492 {
01493 const int nx = cpl_image_get_size_x(self);
01494 const int ny = cpl_image_get_size_y(self);
01495 float * pself = cpl_image_get_data_float(self);
01496 int i, j;
01497
01498 bug_if(self == NULL);
01499 bug_if(cpl_image_get_type(self) != CPL_TYPE_FLOAT);
01500
01501
01502 for (j = 0; j < ny; j++, pself += nx) {
01503 cpl_errorstate prestate = cpl_errorstate_get();
01504 const double median = cpl_image_get_median_window(self, 1, j+1, nx, j+1);
01505
01506 if (cpl_errorstate_is_equal(prestate)) {
01507 for (i = 0; i < nx; i++) {
01508 pself[i] -= (float)median;
01509 }
01510 } else {
01511 cpl_msg_warning(cpl_func, "Could not subtract median from %d "
01512 "pixel(s) in row %d/%d (%d bad pixel(s))", nx, 1+j,
01513 ny, (int)cpl_image_count_rejected(self));
01514 cpl_errorstate_set(prestate);
01515 }
01516 }
01517
01518 end_skip;
01519
01520 return cpl_error_get_code();
01521 }
01522
01523
01529
01530 static cpl_table * isaac_img_jitter_qc(cpl_image * combined)
01531 {
01532 cpl_vector * thresh_vec;
01533 cpl_apertures * aperts;
01534 int nb_objs;
01535 double angle;
01536 double * fwhms_x;
01537 double * fwhms_y;
01538 cpl_table * out_tab;
01539 cpl_bivector * iqe;
01540 int nb_good;
01541 cpl_vector * fwhms_good;
01542 double * fwhms_good_data;
01543 double f_min, f_max, fr, fx, fy;
01544 int i, j;
01545
01546
01547 double seeing_min_arcsec = 0.1;
01548 double seeing_max_arcsec = 5.0;
01549 double seeing_fwhm_var = 0.2;
01550
01551
01552 if (combined == NULL) return NULL;
01553
01554
01555 thresh_vec = cpl_vector_new(4);
01556 cpl_vector_set(thresh_vec, 0, 5.0);
01557 cpl_vector_set(thresh_vec, 1, 2.0);
01558 cpl_vector_set(thresh_vec, 2, 1.0);
01559 cpl_vector_set(thresh_vec, 3, 0.5);
01560
01561
01562 if ((aperts = cpl_apertures_extract(combined, thresh_vec, NULL)) == NULL) {
01563 cpl_msg_error(cpl_func, "Cannot detect any aperture");
01564 cpl_vector_delete(thresh_vec);
01565 return NULL;
01566 }
01567 cpl_vector_delete(thresh_vec);
01568
01569
01570 nb_objs = cpl_apertures_get_size(aperts);
01571 isaac_img_jitter_config.nbobjs = nb_objs;
01572 fwhms_x = cpl_malloc(nb_objs * sizeof(double));
01573 fwhms_y = cpl_malloc(nb_objs * sizeof(double));
01574
01575
01576 out_tab = cpl_table_new(nb_objs);
01577 cpl_table_new_column(out_tab, "POS_X", CPL_TYPE_DOUBLE);
01578 cpl_table_new_column(out_tab, "POS_Y", CPL_TYPE_DOUBLE);
01579 cpl_table_new_column(out_tab, "ANGLE", CPL_TYPE_DOUBLE);
01580 cpl_table_new_column(out_tab, "FWHM_X", CPL_TYPE_DOUBLE);
01581 cpl_table_new_column(out_tab, "FWHM_Y", CPL_TYPE_DOUBLE);
01582 cpl_table_new_column(out_tab, "ELLIP", CPL_TYPE_DOUBLE);
01583 cpl_table_new_column(out_tab, "FLUX", CPL_TYPE_DOUBLE);
01584 for (i=0; i<nb_objs; i++) {
01585
01586 cpl_table_set_double(out_tab, "POS_X", i,
01587 cpl_apertures_get_centroid_x(aperts, i+1));
01588 cpl_table_set_double(out_tab, "POS_Y", i,
01589 cpl_apertures_get_centroid_y(aperts, i+1));
01590 cpl_table_set_double(out_tab, "FLUX", i,
01591 cpl_apertures_get_flux(aperts, i+1));
01592
01593 if ((iqe = cpl_image_iqe(combined,
01594 (int)cpl_apertures_get_centroid_x(aperts, i+1) - 10,
01595 (int)cpl_apertures_get_centroid_y(aperts, i+1) - 10,
01596 (int)cpl_apertures_get_centroid_x(aperts, i+1) + 10,
01597 (int)cpl_apertures_get_centroid_y(aperts, i+1) + 10))==NULL){
01598 cpl_error_reset();
01599 cpl_msg_warning(cpl_func, "Cannot get FWHM for obj at pos %g %g",
01600 cpl_apertures_get_centroid_x(aperts, i+1),
01601 cpl_apertures_get_centroid_y(aperts, i+1));
01602 fwhms_x[i] = -1.0;
01603 fwhms_y[i] = -1.0;
01604 angle = 0.0;
01605 } else {
01606 fwhms_x[i] = cpl_vector_get(cpl_bivector_get_x(iqe), 2);
01607 fwhms_y[i] = cpl_vector_get(cpl_bivector_get_x(iqe), 3);
01608 angle = cpl_vector_get(cpl_bivector_get_x(iqe), 4);
01609 cpl_bivector_delete(iqe);
01610 }
01611 cpl_table_set_double(out_tab, "ANGLE", i, angle);
01612 cpl_table_set_double(out_tab, "FWHM_X", i, fwhms_x[i]);
01613 cpl_table_set_double(out_tab, "FWHM_Y", i, fwhms_y[i]);
01614 if (fwhms_x[i] == 0.0) {
01615 cpl_msg_warning(cpl_func, "Infinite ELLIP for obj at pos %g %g",
01616 cpl_apertures_get_centroid_x(aperts, i+1),
01617 cpl_apertures_get_centroid_y(aperts, i+1));
01618 cpl_table_set_double(out_tab, "ELLIP", i, DBL_MAX);
01619 } else {
01620 cpl_table_set_double(out_tab, "ELLIP", i,
01621 fwhms_y[i] / fwhms_x[i]);
01622 }
01623 }
01624 cpl_apertures_delete(aperts);
01625
01626
01627 nb_good = 0;
01628 for (i=0; i<nb_objs; i++) {
01629 if ((fwhms_x[i] > 0.0) && (fwhms_y[i] > 0.0)) nb_good++;
01630 }
01631 if (nb_good == 0) {
01632 cpl_table_delete(out_tab);
01633 cpl_free(fwhms_x);
01634 cpl_free(fwhms_y);
01635 return NULL;
01636 }
01637
01638
01639 fwhms_good = cpl_vector_new(nb_good);
01640 fwhms_good_data = cpl_vector_get_data(fwhms_good);
01641 j=0;
01642 for (i=0; i<nb_objs; i++) {
01643 if ((fwhms_x[i] > 0.0) && (fwhms_y[i] > 0.0)) {
01644 fwhms_good_data[j] = (fwhms_x[i]+fwhms_y[i])/2.0;
01645 j++;
01646 }
01647 }
01648
01649
01650 if (nb_good < 3) {
01651
01652 isaac_img_jitter_config.fwhm_pix = fwhms_good_data[0];
01653 } else {
01654
01655 isaac_img_jitter_config.fwhm_pix = cpl_vector_get_median_const(fwhms_good);
01656 }
01657 isaac_img_jitter_config.fwhm_arcsec =
01658 isaac_img_jitter_config.fwhm_pix * isaac_img_jitter_config.pixscale;
01659
01660
01661 if (nb_good > 5) {
01662 isaac_img_jitter_config.fwhm_mode=isaac_img_jitter_get_mode(fwhms_good);
01663 isaac_img_jitter_config.fwhm_mode *= isaac_img_jitter_config.pixscale;
01664 }
01665 cpl_vector_delete(fwhms_good);
01666
01667
01668
01669 f_min = seeing_min_arcsec / isaac_img_jitter_config.pixscale;
01670 f_max = seeing_max_arcsec / isaac_img_jitter_config.pixscale;
01671
01672
01673 nb_good = 0;
01674 for (i=0; i<nb_objs; i++) {
01675 fx = fwhms_x[i];
01676 fy = fwhms_y[i];
01677 fr = 2.0 * fabs(fx-fy) / (fx+fy);
01678 if ((fx > f_min) && (fx < f_max) && (fy > f_min) && (fy < f_max) &&
01679 (fr < seeing_fwhm_var)) nb_good++;
01680 }
01681 if (nb_good == 0) {
01682 cpl_table_delete(out_tab);
01683 cpl_free(fwhms_x);
01684 cpl_free(fwhms_y);
01685 return NULL;
01686 }
01687
01688
01689 fwhms_good = cpl_vector_new(nb_good);
01690 fwhms_good_data = cpl_vector_get_data(fwhms_good);
01691 j=0;
01692 for (i=0; i<nb_objs; i++) {
01693 fx = fwhms_x[i];
01694 fy = fwhms_y[i];
01695 fr = 2.0 * fabs(fx-fy) / (fx+fy);
01696 if ((fx > f_min) && (fx < f_max) && (fy > f_min) && (fy < f_max) &&
01697 (fr < seeing_fwhm_var)) {
01698 fwhms_good_data[j] = (fx + fy)/2.0;
01699 j++;
01700 }
01701 }
01702 cpl_free(fwhms_x);
01703 cpl_free(fwhms_y);
01704
01705
01706 if (nb_good < 3) {
01707
01708 isaac_img_jitter_config.iq = fwhms_good_data[0];
01709 } else {
01710
01711 isaac_img_jitter_config.iq = cpl_vector_get_median_const(fwhms_good);
01712 }
01713 cpl_vector_delete(fwhms_good);
01714 isaac_img_jitter_config.iq *= isaac_img_jitter_config.pixscale;
01715
01716 isaac_img_jitter_config.angle_med = cpl_table_get_column_median(out_tab,
01717 "ANGLE");
01718 isaac_img_jitter_config.ellip_med = cpl_table_get_column_median(out_tab,
01719 "ELLIP");
01720 return out_tab;
01721 }
01722
01723
01729
01730 static double isaac_img_jitter_get_mode(cpl_vector * vec)
01731 {
01732 int nb;
01733 int nbins;
01734 double min, max;
01735 double bin_size;
01736 cpl_bivector * hist;
01737 cpl_vector * hist_x;
01738 cpl_vector * hist_y;
01739 double cur_val;
01740 int cur_bin;
01741 double max_val;
01742 int max_bin;
01743 double mode;
01744 int i;
01745
01746
01747 if (vec == NULL) return -1.0;
01748
01749
01750 nb = cpl_vector_get_size(vec);
01751
01752
01753 nbins = 10;
01754 min = cpl_vector_get_min(vec);
01755 max = cpl_vector_get_max(vec);
01756 bin_size = (max-min)/nbins;
01757 hist = cpl_bivector_new(nbins);
01758 hist_x = cpl_bivector_get_x(hist);
01759 hist_y = cpl_bivector_get_y(hist);
01760 cpl_vector_fill(hist_x, 0.0);
01761 cpl_vector_fill(hist_y, 0.0);
01762 for (i=0; i<nbins; i++) {
01763 cpl_vector_set(hist_x, i, min + i * bin_size);
01764 }
01765 for (i=0; i<nb; i++) {
01766 cur_val = cpl_vector_get(vec, i);
01767 cur_bin = (int)((cur_val - min) / bin_size);
01768 if (cur_bin >= nbins) cur_bin -= 1.0;
01769 cur_val = cpl_vector_get(hist_y, cur_bin);
01770 cur_val += 1.0;
01771 cpl_vector_set(hist_y, cur_bin, cur_val);
01772 }
01773
01774
01775 max_val = cpl_vector_get(hist_y, 0);
01776 max_bin = 0;
01777 for (i=0; i<nbins; i++) {
01778 cur_val = cpl_vector_get(hist_y, i);
01779 if (cur_val > max_val) {
01780 max_val = cur_val;
01781 max_bin = i;
01782 }
01783 }
01784 mode = cpl_vector_get(hist_x, max_bin);
01785 cpl_bivector_delete(hist);
01786 return mode;
01787 }
01788
01789
01801
01802 static
01803 cpl_error_code isaac_img_jitter_save(cpl_frameset * set,
01804 const cpl_image * combined,
01805 const cpl_image * contrib,
01806 const cpl_table * objs_stats,
01807 const cpl_vector * sky_bg,
01808 const cpl_parameterlist * parlist)
01809 {
01810 const cpl_frame * ref_frame
01811 = irplib_frameset_get_first_from_group(set, CPL_FRAME_GROUP_RAW);
01812 const char * filename = cpl_frame_get_filename(ref_frame);
01813 const int sz_skybg = sky_bg ? cpl_vector_get_size(sky_bg) : 0;
01814 cpl_propertylist * plist = NULL;
01815 cpl_propertylist * qclist = cpl_propertylist_new();
01816 const char * wcs_reg = "(CRVAL|CRPIX|CTYPE)[0-9]+|(CD)[0-9]+_[0-9]+";
01817 cpl_table * sky_bg_tab = NULL;
01818 int i;
01819
01820 bug_if(0);
01821 bug_if(combined == NULL);
01822 bug_if(contrib == NULL);
01823 bug_if(parlist == NULL);
01824
01825
01826 if (isaac_img_jitter_config.chopping == 0) {
01827 const char * key = "ESO QC BACKGD INSTMAG";
01828 const double pscale = isaac_img_jitter_config.pixscale;
01829 const double dit = isaac_img_jitter_config.dit;
01830 const double bg_mean = cpl_vector_get_mean(sky_bg);
01831 const double bg_stdev = sz_skybg < 2 ? 0.0
01832 : cpl_vector_get_stdev(sky_bg);
01833
01834
01835 bug_if(cpl_propertylist_append_double(qclist, "ESO QC BACKGD MEAN",
01836 bg_mean));
01837 bug_if(cpl_propertylist_append_double(qclist, "ESO QC BACKGD STDEV",
01838 bg_stdev));
01839
01840 if (pscale * dit != 0.0 && bg_mean / (pscale * pscale * dit) > 0.0) {
01841 const double bg_instmag = -2.5 * log10(bg_mean/(pscale*pscale*dit));
01842
01843 bug_if(cpl_propertylist_append_double(qclist, key, bg_instmag));
01844 } else {
01845 cpl_msg_warning(cpl_func, "Could not compute %s: dit=%g, pscale=%g, "
01846 "bg_mean=%g", key, dit, pscale, bg_mean);
01847 }
01848 }
01849
01850 cpl_propertylist_append_int(qclist, "ESO QC NBOBJS",
01851 isaac_img_jitter_config.nbobjs);
01852 cpl_propertylist_append_double(qclist, "ESO QC IQ",
01853 isaac_img_jitter_config.iq);
01854 cpl_propertylist_append_double(qclist, "ESO QC FWHM PIX",
01855 isaac_img_jitter_config.fwhm_pix);
01856 cpl_propertylist_append_double(qclist, "ESO QC FWHM ARCSEC",
01857 isaac_img_jitter_config.fwhm_arcsec);
01858 cpl_propertylist_append_double(qclist, "ESO QC FWHM MODE",
01859 isaac_img_jitter_config.fwhm_mode);
01860 cpl_propertylist_append_int(qclist, "ESO QC NB_OBJ_F",
01861 isaac_img_jitter_config.nb_obj_frames);
01862 cpl_propertylist_append_int(qclist, "ESO QC NB_SKY_F",
01863 isaac_img_jitter_config.nb_sky_frames);
01864 cpl_propertylist_append_int(qclist, "ESO QC NB_REJ_F",
01865 isaac_img_jitter_config.nb_rej_frames);
01866 cpl_propertylist_append_double(qclist, "ESO QC ANGLE MED",
01867 isaac_img_jitter_config.angle_med);
01868 cpl_propertylist_append_double(qclist, "ESO QC ELLIP MED",
01869 isaac_img_jitter_config.ellip_med);
01870 bug_if(0);
01871
01872
01873 plist = cpl_propertylist_load(filename, 0);
01874 skip_if(plist == NULL);
01875
01876
01877 bug_if(cpl_propertylist_copy_property_regexp(qclist, plist, wcs_reg, 0));
01878
01879
01880 (void)cpl_propertylist_erase_regexp(plist,
01881 "^(ARCFILE|MJD-OBS|INSTRUME"
01882 "|ESO TPL ID|ESO TPL NEXP"
01883 "|ESO DPR CATG"
01884 "|ESO DPR TECH|ESO DPR TYPE"
01885 "|DATE-OBS|ESO OBS ID"
01886 "|ESO INS PIXSCALE)$", 1);
01887
01888
01889 skip_if(irplib_dfs_save_image(set, parlist, set, combined,
01890 CPL_BPP_IEEE_FLOAT, RECIPE_STRING,
01891 ISAAC_IMG_JITTER_COMB, qclist, NULL,
01892 PACKAGE "/" PACKAGE_VERSION,
01893 RECIPE_STRING CPL_DFS_FITS));
01894 (void)cpl_propertylist_erase_regexp(qclist, wcs_reg, 0);
01895
01896
01897 skip_if (cpl_image_save(contrib, RECIPE_STRING CPL_DFS_FITS,
01898 CPL_BPP_16_UNSIGNED, NULL, CPL_IO_EXTEND));
01899
01900 if (sky_bg != NULL) {
01901
01902
01903
01904 sky_bg_tab = cpl_table_new(sz_skybg);
01905
01906 cpl_table_new_column(sky_bg_tab, "SKY_BG", CPL_TYPE_DOUBLE);
01907
01908 for (i = 0; i < sz_skybg; i++) {
01909 cpl_table_set_double(sky_bg_tab, "SKY_BG", i,
01910 cpl_vector_get(sky_bg, i));
01911 }
01912
01913 skip_if(irplib_dfs_save_table(set, parlist, set, sky_bg_tab, NULL,
01914 RECIPE_STRING, ISAAC_IMG_JITTER_BG,
01915 qclist, NULL, PACKAGE "/" PACKAGE_VERSION,
01916 RECIPE_STRING "_bg" CPL_DFS_FITS));
01917 cpl_table_delete(sky_bg_tab);
01918 sky_bg_tab = NULL;
01919 }
01920
01921
01922 if (objs_stats) {
01923 skip_if(irplib_dfs_save_table(set, parlist, set, objs_stats, NULL,
01924 RECIPE_STRING, ISAAC_IMG_JITTER_STARS,
01925 qclist, NULL, PACKAGE "/" PACKAGE_VERSION,
01926 RECIPE_STRING "_stars" CPL_DFS_FITS));
01927 }
01928
01929 bug_if(cpl_propertylist_append(plist, qclist));
01930 cpl_propertylist_empty(qclist);
01931
01932
01933 cpl_propertylist_update_string(plist, CPL_DFS_PRO_CATG,
01934 ISAAC_IMG_JITTER_COMB);
01935
01936
01937 skip_if (cpl_dfs_save_paf("ISAAC", RECIPE_STRING, plist,
01938 RECIPE_STRING CPL_DFS_PAF));
01939
01940 end_skip;
01941
01942 cpl_propertylist_delete(plist);
01943 cpl_propertylist_delete(qclist);
01944 cpl_table_delete(sky_bg_tab);
01945
01946 return cpl_error_get_code();
01947 }