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