51 #include <irplib_utils.h>
54 #include <sinfo_pro_types.h>
55 #include <sinfo_product_config.h>
56 #include <sinfo_prepare_stacked_frames_config.h>
57 #include <sinfo_objnod_config.h>
58 #include <sinfo_new_objnod.h>
59 #include <sinfo_new_prepare_stacked_frames.h>
60 #include <sinfo_pro_save.h>
61 #include <sinfo_raw_types.h>
62 #include <sinfo_functions.h>
63 #include <sinfo_tpl_utils.h>
64 #include <sinfo_tpl_dfs.h>
65 #include <sinfo_hidden.h>
66 #include <sinfo_globals.h>
67 #include <sinfo_rec_utils.h>
69 #include <sinfo_dfs.h>
75 static int sinfo_utl_illumcorr_create(cpl_plugin *plugin);
76 static int sinfo_utl_illumcorr_exec(cpl_plugin *plugin);
77 static int sinfo_utl_illumcorr_destroy(cpl_plugin *plugin);
78 static int sinfo_utl_illumcorr(cpl_parameterlist *config, cpl_frameset *
set);
81 #define SINFO_DOUBLE_SWAP(a,b) { register double t=(a);(a)=(b);(b)=t; }
84 sinfo_tools_sort_double(
89 sinfo_get_dummy_object(cpl_frameset* obj_set);
92 sinfo_illumcorr_config_add (cpl_parameterlist *list);
95 create_illumcorr (
const char* plugin_id,
96 cpl_parameterlist *cpl_cfg,
100 sinfo_illumcorr_create_bins (cpl_imagelist *sky,
101 int llx,
int lly,
int urx,
int ury,
109 sinfo_juha_function1d_natural_spline(
double *,
double *,
int,
double *,
113 sinfo_function1d_search_value(
double *,
int,
double,
int *) ;
116 sinfo_vector_filter_median_create(
const cpl_vector * v,
int hw);
119 sinfo_juha_vector_filter_median_create(
const cpl_vector * v,
int hw);
122 sinfo_image_get_median_window (
const cpl_image *image,
123 int llx,
int lly,
int urx,
int ury);
130 static char sinfo_utl_illumcorr_description1[] =
131 "This recipe calculates illumination correction based on sky emission.\n"
132 "The input files are sky (or object) frames tagged\n"
133 " SKY_NODDING (OBJECT_NODDING)\n"
134 "Master calibration frames:\n";
137 static char sinfo_utl_illumcorr_description2[] =
138 "A corresponding (DIT) dark frame (tag=MASTER_DARK)"
139 "A corresponding (band,preoptics) wavelength map image (tag=WAVE_MAP)\n"
140 "A corresponding (band,preoptics) master flat field (tag=MASTER_FLAT_LAMP)\n"
141 "A corresponding (band,preoptics) master bad pixel map (tag=MASTER_BP_MAP)\n"
142 "A corresponding (band,preoptics) slitlets position frame (tag=SLIT_POS)\n"
143 "A corresponding (band) distortion table (tag=DISTORTION)\n"
144 "A corresponding (band) slitlet distance table (tag=SLITLETS_DISTANCE)\n";
147 static char sinfo_utl_illumcorr_description3[] =
148 "The output is a cube resulting from the analysis of sky emission\n"
152 static char sinfo_utl_illumcorr_description[1300];
166 sinfo_utl_illumcorr_create(cpl_plugin *plugin)
174 cpl_recipe *recipe = (cpl_recipe *)plugin;
175 recipe->parameters = cpl_parameterlist_new();
176 if(recipe->parameters == NULL) {
185 sinfo_product_config_add (recipe->parameters);
186 sinfo_prepare_stacked_frames_config_add(recipe->parameters);
187 sinfo_objnod_config_add(recipe->parameters);
188 sinfo_illumcorr_config_add (recipe->parameters);
202 sinfo_utl_illumcorr_exec(cpl_plugin *plugin)
205 cpl_recipe *recipe = (cpl_recipe *) plugin;
207 cpl_errorstate initial_errorstate = cpl_errorstate_get();
209 if(recipe->parameters == NULL) {
212 if(recipe->frames == NULL) {
215 code=sinfo_utl_illumcorr(recipe->parameters, recipe->frames);
217 if (!cpl_errorstate_is_equal(initial_errorstate)) {
220 cpl_errorstate_dump(initial_errorstate, CPL_FALSE, NULL);
235 sinfo_utl_illumcorr_destroy(cpl_plugin *plugin)
237 cpl_recipe *recipe = (cpl_recipe *) plugin;
244 cpl_parameterlist_delete(recipe->parameters);
263 cpl_recipe *recipe = cpl_calloc(1,
sizeof *recipe);
264 cpl_plugin *plugin = &recipe->interface;
266 strcpy(sinfo_utl_illumcorr_description,sinfo_utl_illumcorr_description1);
267 strcat(sinfo_utl_illumcorr_description,sinfo_utl_illumcorr_description2);
268 strcat(sinfo_utl_illumcorr_description,sinfo_utl_illumcorr_description3);
270 cpl_plugin_init(plugin,
272 SINFONI_BINARY_VERSION,
273 CPL_PLUGIN_TYPE_RECIPE,
274 "sinfo_utl_illumcorr",
275 "Object data reduction",
276 sinfo_utl_illumcorr_description,
278 "reunanen@strw.leidenuniv.nl",
280 sinfo_utl_illumcorr_create,
281 sinfo_utl_illumcorr_exec,
282 sinfo_utl_illumcorr_destroy);
284 cpl_pluginlist_append(list, plugin);
295 sinfo_utl_illumcorr(cpl_parameterlist *config, cpl_frameset *
set)
297 char outname[FILE_NAME_SZ];
308 cpl_frameset * obj_set=NULL;
309 cpl_frameset * sky_set=NULL;
310 cpl_frameset * cdb_set=NULL;
311 cpl_frameset * wrk_set=NULL;
312 cpl_frameset * stk_set=NULL;
313 cpl_frame * sky_frm=NULL;
315 cpl_frame * dup_frm=NULL;
316 cpl_frame * cdb_frm=NULL;
317 cpl_frame * wrk_frm=NULL;
318 cpl_frameset * ref_set=NULL;
320 cpl_frame * dark_frm=NULL;
325 cpl_image * ima1=NULL ;
326 cpl_image * ima2=NULL ;
327 cpl_image * resima=NULL ;
328 cpl_propertylist * plist=NULL ;
329 cpl_frame * product_frame=NULL;
330 const char *name_i=NULL;
333 sinfo_msg(
"Welcome to SINFONI Pipeline release %d.%d.%d",
334 SINFONI_MAJOR_VERSION,SINFONI_MINOR_VERSION,SINFONI_MICRO_VERSION);
336 if(sinfo_dfs_set_groups(
set)) {
341 dark_frm = cpl_frameset_find(
set,PRO_MASTER_DARK);
342 if (dark_frm == NULL) {
347 ref_set=cpl_frameset_duplicate(
set);
349 obj_set=cpl_frameset_new();
350 sky_set=cpl_frameset_new();
351 cdb_set=cpl_frameset_new();
352 fk = sinfo_fake_new();
354 sinfo_extract_obj_frames(
set,obj_set);
355 sinfo_extract_sky_frames(
set,sky_set);
356 sinfo_extract_mst_frames(
set,cdb_set);
358 nobj=cpl_frameset_get_size(obj_set);
359 nsky=cpl_frameset_get_size(sky_set);
360 ncdb=cpl_frameset_get_size(cdb_set);
362 if ((nobj==0) && (nsky==0)) {
364 cpl_frameset_delete(obj_set);
365 cpl_frameset_delete(sky_set);
366 cpl_frameset_delete(cdb_set);
367 cpl_frameset_delete(ref_set);
368 sinfo_fake_delete(&fk);
378 if( (sky_frm = sinfo_get_dummy_object(sky_set)) == NULL) {
380 cpl_frameset_delete(obj_set);
381 cpl_frameset_delete(sky_set);
382 cpl_frameset_delete(cdb_set);
383 cpl_frameset_delete(ref_set);
384 sinfo_fake_delete(&fk);
389 if( (sky_frm = sinfo_get_dummy_object(obj_set)) == NULL) {
391 cpl_frameset_delete(obj_set);
392 cpl_frameset_delete(sky_set);
393 cpl_frameset_delete(cdb_set);
394 cpl_frameset_delete(ref_set);
395 sinfo_fake_delete(&fk);
404 ima1 = cpl_image_load(cpl_frame_get_filename(sky_frm),CPL_TYPE_FLOAT,0,0);
405 ima2 = cpl_image_load(cpl_frame_get_filename(dark_frm),CPL_TYPE_FLOAT,0,0);
406 resima = cpl_image_subtract_create(ima1, ima2);
407 plist=cpl_propertylist_load(cpl_frame_get_filename(sky_frm), 0);
408 cpl_image_delete(ima1);
409 cpl_image_delete(ima2);
411 product_frame = cpl_frame_new();
412 cpl_frame_set_filename(product_frame,
"out_fake_object2.fits") ;
413 cpl_frame_set_tag(product_frame,
"OBJECT_NODDING") ;
414 cpl_frame_set_type(product_frame, CPL_FRAME_TYPE_IMAGE) ;
415 cpl_frame_set_group(product_frame, CPL_FRAME_GROUP_RAW) ;
417 cpl_propertylist_erase_regexp(plist,
"^ESO PRO CATG",0);
419 cpl_image_save(resima,
"out_fake_object2.fits", CPL_BPP_IEEE_FLOAT, plist,
421 cpl_propertylist_delete(plist) ;
422 cpl_image_delete(resima) ;
428 wrk_set=cpl_frameset_new();
430 dup_frm=cpl_frame_duplicate(product_frame);
431 cpl_frame_set_tag (dup_frm,
"OBJECT_NODDING");
432 cpl_frame_set_group (dup_frm ,CPL_FRAME_GROUP_RAW);
433 cpl_frameset_insert(wrk_set,dup_frm);
436 for(k=0;k<ncdb;k++) {
437 cdb_frm=cpl_frameset_get_frame(cdb_set,k);
438 dup_frm=cpl_frame_duplicate(cdb_frm);
439 cpl_frameset_insert(wrk_set,dup_frm);
444 sprintf(outname,
"%s%d%s",
"out_stack",i,
".fits");
445 if(-1 == sinfo_new_stack_frames(config,wrk_set,
446 PRO_OBJECT_NODDING_STACKED,i,fk,cpl_func)) {
448 cpl_frameset_delete(wrk_set);
450 cpl_frameset_delete(obj_set);
451 cpl_frameset_delete(sky_set);
452 cpl_frameset_delete(cdb_set);
453 cpl_frameset_delete(ref_set);
454 sinfo_fake_delete(&fk);
458 stk_set=cpl_frameset_new();
459 sinfo_contains_frames_kind(wrk_set,stk_set,PRO_STACKED);
460 nstk=cpl_frameset_get_size(stk_set);
462 for(k=0;k<nstk;k++) {
463 wrk_frm=cpl_frameset_get_frame(stk_set,k);
464 dup_frm = cpl_frame_duplicate(wrk_frm);
465 cpl_frameset_insert(
set,dup_frm);
467 cpl_frameset_delete(stk_set);
468 cpl_frameset_delete(wrk_set);
470 sinfo_msg(
"------------------------------") ;
471 sinfo_msg(
"CREATING SKY CUBE");
472 sinfo_msg(
"------------------------------") ;
475 if ( -1 == (ind=sinfo_new_objnod(cpl_func,config,
set, PRO_COADD_OBJ ) ) ) {
477 cpl_frameset_delete(obj_set);
478 cpl_frameset_delete(sky_set);
479 cpl_frameset_delete(cdb_set);
480 cpl_frameset_delete(ref_set);
481 sinfo_fake_delete(&fk);
485 sinfo_msg(
"------------------------------") ;
486 sinfo_msg(
"CREATED SKY CUBE");
487 sinfo_msg(
"------------------------------") ;
490 stk_set=cpl_frameset_new();
491 sinfo_contains_frames_kind(
set, stk_set, PRO_OBS_OBJ);
492 nstk=cpl_frameset_get_size(stk_set);
494 wrk_frm=cpl_frameset_get_frame(stk_set,0);
495 name_i = cpl_frame_get_filename(wrk_frm);
499 cpl_frameset_delete(obj_set);
500 cpl_frameset_delete(sky_set);
501 cpl_frameset_delete(cdb_set);
502 cpl_frameset_delete(ref_set);
503 sinfo_fake_delete(&fk);
504 cpl_frame_delete(sky_frm);
505 create_illumcorr (cpl_func, config,
set, name_i);
513 sinfo_get_dummy_object(cpl_frameset* obj_set)
516 cpl_imagelist* obj_list=NULL;
517 cpl_image* fake_object=NULL;
518 char filename[FILE_NAME_SZ];
519 cpl_frame* frame=NULL;
520 cpl_frame* object_frame=NULL;
522 cpl_propertylist* plist=NULL;
524 obj_list = cpl_imagelist_load_frameset(obj_set,CPL_TYPE_FLOAT,0,0);
525 fake_object = cpl_imagelist_collapse_median_create(obj_list);
527 frame = cpl_frameset_get_frame(obj_set,0);
528 strcpy(filename,cpl_frame_get_filename(frame));
530 if ((cpl_error_code)((plist = cpl_propertylist_load(filename, 0)) == NULL)) {
531 sinfo_msg_error(
"getting header from reference ima frame %s",filename);
532 cpl_propertylist_delete(plist) ;
536 if (sinfo_propertylist_has(plist, KEY_NAME_DPR_TYPE)) {
537 cpl_propertylist_set_string(plist, KEY_NAME_DPR_TYPE,
"OBJECT");
539 cpl_propertylist_append_string(plist, KEY_NAME_DPR_TYPE,
"OBJECT") ;
542 if (cpl_image_save(fake_object,
"out_fake_object.fits", CPL_BPP_IEEE_FLOAT,
543 plist,CPL_IO_DEFAULT)!=CPL_ERROR_NONE) {
545 cpl_propertylist_delete(plist) ;
548 cpl_propertylist_delete(plist);
550 object_frame = cpl_frame_new() ;
551 cpl_frame_set_filename(object_frame,
"out_fake_object.fits") ;
552 cpl_frame_set_tag(object_frame,
"OBJECT") ;
553 cpl_frame_set_type(object_frame, CPL_FRAME_TYPE_IMAGE);
557 cpl_frame_set_level(object_frame, CPL_FRAME_LEVEL_FINAL);
558 cpl_image_delete(fake_object);
559 cpl_imagelist_delete(obj_list);
565 sinfo_illumcorr_config_add (cpl_parameterlist *list)
573 p = cpl_parameter_new_range(
"sinfoni.illumcorr.spec_bin",
575 "Number of spectral planes to be combined ",
578 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"illumcorr-spec_bin");
579 cpl_parameterlist_append(list, p);
581 p = cpl_parameter_new_value(
"sinfoni.illumcorr.min_flux",
583 "Minimum flux in each spectral bin ",
586 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"illumcorr-min_flux");
587 cpl_parameterlist_append(list, p);
589 p = cpl_parameter_new_value(
"sinfoni.illumcorr.center_bins",
591 "Center the spectral bins at prominent "
592 "emission features ",
595 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"illumcorr-center_bins");
596 cpl_parameterlist_append(list, p);
598 p = cpl_parameter_new_enum(
"sinfoni.illumcorr.order",
600 "The order of the polynomial to be fitted "
605 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"illumcorr-order");
606 cpl_parameterlist_append(list, p);
608 p = cpl_parameter_new_value(
"sinfoni.illumcorr.sigma",
610 "Reject n-sigma deviant pixels on each slitlet ",
613 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"illumcorr-sigma");
614 cpl_parameterlist_append(list, p);
616 p = cpl_parameter_new_value(
"sinfoni.illumcorr.iterations",
618 "Number of sigma rejection iterations to run ",
621 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"illumcorr-iter");
622 cpl_parameterlist_append(list, p);
624 p = cpl_parameter_new_range(
"sinfoni.illumcorr.llx",
626 "Reference region coordinates ",
629 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"illumcorr-llx");
630 cpl_parameterlist_append(list, p);
632 p = cpl_parameter_new_range(
"sinfoni.illumcorr.lly",
634 "Reference region coordinates ",
637 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"illumcorr-lly");
638 cpl_parameterlist_append(list, p);
640 p = cpl_parameter_new_range(
"sinfoni.illumcorr.urx",
642 "Reference region coordinates ",
645 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"illumcorr-urx");
646 cpl_parameterlist_append(list, p);
648 p = cpl_parameter_new_range(
"sinfoni.illumcorr.ury",
650 "Reference region coordinates ",
653 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"illumcorr-ury");
654 cpl_parameterlist_append(list, p);
656 p = cpl_parameter_new_enum(
"sinfoni.illumcorr.smooth0",
658 "Smooth zeroth order terms by fitting "
659 "with polynomial (1),"
660 "with median filter (2) or not (0) ",
664 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"illumcorr-smooth0");
665 cpl_parameterlist_append(list, p);
667 p = cpl_parameter_new_value(
"sinfoni.illumcorr.smooth0_order",
669 "Order of the smoothing polynomial for 0th term",
672 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"illumcorr-smooth_order0");
673 cpl_parameterlist_append(list, p);
675 p = cpl_parameter_new_range(
"sinfoni.illumcorr.smooth0_size",
677 "Size of the median filter for 0th "
681 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"illumcorr-smooth0_size");
682 cpl_parameterlist_append(list, p);
684 p = cpl_parameter_new_value(
"sinfoni.illumcorr.smooth1",
686 "Smooth higher (>0) order polynomials ",
689 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"illumcorr-smooth");
690 cpl_parameterlist_append(list, p);
692 p = cpl_parameter_new_value(
"sinfoni.illumcorr.smooth1_order",
694 "Smoothing order for higher terms ",
697 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"illumcorr-smooth_order");
698 cpl_parameterlist_append(list, p);
700 p = cpl_parameter_new_value(
"sinfoni.illumcorr.illumcorr_sigma",
702 "Reject all fits for which the rms is "
703 "illumcorr-sigma times bigger than the "
704 "median rms in each spectral bin" ,
707 cpl_parameter_set_alias(p,CPL_PARAMETER_MODE_CLI,
708 "illumcorr-illumcorr_sigma");
709 cpl_parameterlist_append(list, p);
714 create_illumcorr (
const char* plugin_id,
715 cpl_parameterlist *cpl_cfg,
719 cpl_parameter *p=NULL;
725 cpl_imagelist *sky=NULL;
726 cpl_imagelist *binnedsky=NULL;
727 cpl_imagelist *result=NULL;
728 cpl_image *temp_image=NULL;
729 cpl_image *temp_image2=NULL;
742 double *inter_pos=NULL;
743 double *inter_val=NULL;
744 double *plane_pos=NULL;
745 double *plane_val=NULL;
752 cpl_vector *row=NULL;
753 cpl_vector *model=NULL;
754 cpl_vector *xpos=NULL;
755 cpl_vector *tempvector=NULL;
756 cpl_vector *tempvector2=NULL;
759 cpl_polynomial*poly=NULL;
760 cpl_polynomial *poly2=NULL;
761 double *temparray=NULL;
762 double *tempxarray=NULL;
763 double * tempsarray=NULL;
764 cpl_polynomial**coeffs=NULL;
766 double *rms_values=NULL;
767 double rms_array[32];
790 p = cpl_parameterlist_find(cpl_cfg,
"sinfoni.illumcorr.spec_bin");
791 spec_bin = cpl_parameter_get_int(p);
792 p = cpl_parameterlist_find(cpl_cfg,
"sinfoni.illumcorr.min_flux");
793 min_flux = cpl_parameter_get_double(p);
794 p = cpl_parameterlist_find(cpl_cfg,
"sinfoni.illumcorr.order");
795 _order = cpl_parameter_get_int(p);
796 p = cpl_parameterlist_find(cpl_cfg,
"sinfoni.illumcorr.sigma");
797 sigma = cpl_parameter_get_double(p);
798 p = cpl_parameterlist_find(cpl_cfg,
"sinfoni.illumcorr.llx");
799 llx = cpl_parameter_get_int(p);
800 p = cpl_parameterlist_find(cpl_cfg,
"sinfoni.illumcorr.lly");
801 lly = cpl_parameter_get_int(p);
802 p = cpl_parameterlist_find(cpl_cfg,
"sinfoni.illumcorr.urx");
803 urx = cpl_parameter_get_int(p);
804 p = cpl_parameterlist_find(cpl_cfg,
"sinfoni.illumcorr.ury");
805 ury = cpl_parameter_get_int(p);
806 p = cpl_parameterlist_find(cpl_cfg,
"sinfoni.illumcorr.illumcorr_sigma");
807 il_sigma = cpl_parameter_get_double(p);
809 p = cpl_parameterlist_find(cpl_cfg,
"sinfoni.illumcorr.smooth0");
810 smooth0 = cpl_parameter_get_int (p);
811 p = cpl_parameterlist_find(cpl_cfg,
"sinfoni.illumcorr.smooth0_order");
812 smooth_order0 = cpl_parameter_get_int (p);
813 p = cpl_parameterlist_find(cpl_cfg,
"sinfoni.illumcorr.smooth0_size");
814 smooth_size0 = cpl_parameter_get_int (p);
816 p = cpl_parameterlist_find(cpl_cfg,
"sinfoni.illumcorr.smooth1");
817 smooth = cpl_parameter_get_bool (p);
818 p = cpl_parameterlist_find(cpl_cfg,
"sinfoni.illumcorr.smooth1_order");
819 smooth_order = cpl_parameter_get_int (p);
821 p = cpl_parameterlist_find(cpl_cfg,
"sinfoni.illumcorr.iterations");
822 iter = cpl_parameter_get_int (p);
824 p = cpl_parameterlist_find(cpl_cfg,
"sinfoni.illumcorr.center_bins");
825 center_bins = cpl_parameter_get_bool (p);
832 sky = cpl_imagelist_load(name_i, CPL_TYPE_FLOAT, 0);
833 nplanes = cpl_imagelist_get_size(sky);
840 && isnan(cpl_image_get_mean_window(cpl_imagelist_get(sky, z1),
841 llx, lly, urx, ury)))
844 && isnan(cpl_image_get_mean_window(cpl_imagelist_get(sky, z2),
845 llx, lly, urx, ury)))
849 if (z1>=nplanes || z2 <0 || z2<=z1) {
851 cpl_imagelist_delete (sky);
854 sinfo_msg (
"Start z = %d, end z = %d", z1, z2);
856 binnedsky = cpl_imagelist_new ();
857 median = (
double*) cpl_calloc(nplanes/spec_bin,
sizeof(
double));
858 pos = (
double*) cpl_calloc(nplanes/spec_bin,
sizeof(
double));
859 temparray = (
double*) cpl_calloc(64,
sizeof(
double));
860 tempxarray= (
double*) cpl_calloc(64,
sizeof(
double));
861 tempsarray= (
double*) cpl_calloc (nplanes/spec_bin,
sizeof(
double));
862 plane_pos = (
double*) cpl_calloc (nplanes/spec_bin,
sizeof(
double));
863 plane_val = (
double*) cpl_calloc (nplanes/spec_bin,
sizeof(
double));
864 coeffs = (cpl_polynomial**) cpl_calloc(32*(nplanes/spec_bin),
865 sizeof(cpl_polynomial*));
866 rms_values= (
double*) cpl_calloc (32*(nplanes/spec_bin),
sizeof (double));
867 inter_pos = (
double*) cpl_calloc (nplanes,
sizeof(
double));
868 inter_val = (
double*) cpl_calloc (nplanes,
sizeof(
double));
870 model = cpl_vector_new(64);
871 xpos = cpl_vector_new(64);
874 cpl_vector_set(xpos, i, (
double)(i)-((
double)urx-(
double)llx)/2.0);
875 for (i=0; i<nplanes; i++)
876 inter_pos[i] = (
double)i;
887 if (center_bins == 1) {
888 sinfo_msg(
"Using centering on emission features\n");
889 nbins = sinfo_illumcorr_create_bins (sky,llx, lly, urx, ury,
891 &bin_start, &bin_end,
895 sinfo_msg(
"Using simple spectral binning - "
896 "not centering on emission features\n");
897 nbins = (z2-z1)/spec_bin;
898 bin_start = (
int*)cpl_calloc(nbins+1,
sizeof(
int));
899 bin_end = (
int*)cpl_calloc(nbins+1,
sizeof(
int));
900 for (i = 0; i<nbins; i++) {
901 bin_start[i] = z1+i*spec_bin;
902 bin_end[i] = z1+(i+1)*spec_bin - 1;
904 if (bin_end[nbins-1]<z2-spec_bin/10) {
905 bin_start[nbins] = bin_end[nbins-1]+1;
917 sinfo_msg(
"Binning the cube and calculating statistics\n");
918 for (i=0; i<nbins; i++) {
919 temp_image = cpl_image_duplicate(cpl_imagelist_get(sky, bin_start[i]));
920 median[i] = sinfo_image_get_median_window (temp_image, llx, lly, urx, ury);
921 pos[i] = median[i] * (double)bin_start[i];
922 cpl_imagelist_set (binnedsky, temp_image, i);
923 for (j=bin_start[i]+1; j<bin_end[i]; j++) {
924 temp_image2 = cpl_imagelist_get (sky, j);
925 cpl_image_add (temp_image, temp_image2);
926 temp = sinfo_image_get_median_window (temp_image2, llx, lly, urx, ury);
927 median[i] = median[i] + temp;
928 pos[i] = pos[i] + temp*(double)j;
930 temp2 =(double)(bin_end[i]-bin_start[i]+1);
931 cpl_image_divide_scalar (temp_image, temp2);
932 pos[i] = pos[i]/median[i];
933 median[i] = median[i] / temp2;
937 sinfo_msg(
"Fitting slitlets between x=%d - x=%d\n", llx, urx);
938 sinfo_msg(
"Fitting order %d\n", _order);
939 for (k=0;k<nbins; k++) {
940 if (median[k]>min_flux) {
941 for (j=0; j<32; j++) {
942 row=cpl_vector_new_from_image_row(cpl_imagelist_get(binnedsky,k),2*j+1);
944 for (i=llx; i<=urx; i++) {
945 if (!isnan(cpl_vector_get(row, i))) {
947 temparray[n] = cpl_vector_get(row, i);
948 tempxarray[n] = cpl_vector_get(xpos, i);
957 tempvector = cpl_vector_wrap (n, temparray);
958 tempvector2= cpl_vector_wrap (n, tempxarray);
959 poly = cpl_polynomial_fit_1d_create (tempvector2, tempvector,
963 sinfo_msg(
"Fitting failed (plane %d, row %d): %s",
964 k, j, (
char* ) cpl_error_get_message());
966 if (sigma>0 && iter>0) {
967 for (kk = 0; kk<iter; kk++) {
968 cpl_vector_fill_polynomial (model, poly, 0.0, 1.0);
969 cpl_vector_subtract (model, row);
973 for (i=llx; i<=urx; i++)
975 temparray[n++] = cpl_vector_get(model, i);
976 stddev = cpl_vector_get_stdev(tempvector);
978 for (i=llx; i<=urx; i++)
980 if (fabs(cpl_vector_get(model, i))>(stddev*sigma))
985 for (i=llx; i<=urx; i++) {
987 temparray[n] = cpl_vector_get(row, i);
988 tempxarray[n] = cpl_vector_get(xpos, i);
992 cpl_polynomial_delete(poly);
994 cpl_vector_unwrap (tempvector);
995 cpl_vector_unwrap (tempvector2);
996 tempvector = cpl_vector_wrap (n, temparray);
997 tempvector2= cpl_vector_wrap (n, tempxarray);
998 stddev = cpl_vector_get_stdev(tempvector);
1000 poly = cpl_polynomial_fit_1d_create (tempvector2,
1015 coeffs[j*nbins+k] = poly;
1016 rms_values[j*nbins+k] = sqrt(mse);
1019 coeffs[j*nbins+k] = NULL;
1021 cpl_vector_unwrap (tempvector);
1022 cpl_vector_unwrap (tempvector2);
1024 cpl_vector_delete(row);
1032 sinfo_msg(
"Writing dat out_illum.dat\n");
1033 dumpfile = fopen (
"out_illum.dat",
"w");
1034 fprintf (dumpfile,
"# slitlet, pos, median, rms, coeff0, coeff1...\n");
1035 for (slitlet = 0; slitlet<32; slitlet++)
1036 for (bin=0; bin<nbins; bin++) {
1037 poly = coeffs[slitlet*nbins+bin];
1039 fprintf (dumpfile,
"%d %f %f %f ",slitlet, pos[bin],
1041 rms_values[slitlet*nbins+bin]);
1042 for (i=0; i<(cpl_polynomial_get_degree(poly)+1); i++) {
1043 temp = cpl_polynomial_get_coeff (poly, &i);
1044 fprintf (dumpfile,
"%f ", temp);
1046 fprintf (dumpfile,
"\n");
1056 sinfo_msg(
"Removing poor fits - factor %f", il_sigma);
1060 sinfo_msg(
"max loop over bin =%d",nbins);
1061 for (bin=0; bin<nbins; bin++) {
1063 for (slitlet=0; slitlet<32; slitlet++)
1064 if (coeffs[slitlet*nbins+bin] != NULL)
1065 rms_array[k++] = rms_values[slitlet*nbins+bin];
1070 tempvector = cpl_vector_wrap (k, &rms_array[0]);
1071 temp = cpl_vector_get_median (tempvector);
1072 sinfo_msg(
"median temp=%g",temp);
1073 cpl_vector_unwrap (tempvector);
1074 for (slitlet=0; slitlet<32; slitlet++)
1075 if (coeffs[slitlet*nbins+bin] != NULL) {
1077 if (rms_values[slitlet*nbins+bin]>(il_sigma*temp)) {
1078 cpl_polynomial_delete(coeffs[slitlet*nbins+bin]);
1079 coeffs[slitlet*nbins+bin] = NULL;
1088 sinfo_msg(
"Removed %d poor fits out of %d. Bad coeffs=%d", n,i,nbad);
1091 sinfo_msg(
"Smoothing zeroth terms (order %d)", smooth_order0);
1095 for (slitlet = 0; slitlet<32; slitlet++) {
1097 for (bin=0; bin<nbins; bin++) {
1098 if (coeffs[slitlet*nbins+bin] != NULL) {
1099 poly = coeffs[slitlet*nbins+bin];
1101 temp = cpl_polynomial_get_coeff (poly, &i);
1102 plane_pos[k] = pos[bin];
1103 plane_val[k] = temp/median[bin];
1108 tempvector = cpl_vector_wrap (k, plane_pos);
1109 tempvector2= cpl_vector_wrap (k, plane_val);
1110 poly2 = cpl_polynomial_fit_1d_create (tempvector, tempvector2,
1111 smooth_order0, &mse);
1112 cpl_vector_unwrap (tempvector);
1113 cpl_vector_unwrap (tempvector2);
1114 for (bin=0; bin<nbins; bin++) {
1115 if (coeffs[slitlet*nbins+bin] != NULL) {
1116 poly = coeffs[slitlet*nbins+bin];
1118 temp2 = cpl_polynomial_eval_1d (poly2, pos[bin], NULL);
1119 cpl_polynomial_set_coeff (poly, &i, temp2*median[bin]);
1122 cpl_polynomial_delete(poly2);
1128 else if (smooth0 == 2) {
1129 sinfo_msg(
"Smoothing zeroth terms (median filter size %d)", smooth_size0);
1130 smooth_size0 = smooth_size0/2;
1131 if (smooth_size0 <= 0) smooth_size0 = 1;
1132 for (slitlet = 0; slitlet<32; slitlet++) {
1134 for (bin=0; bin<nbins; bin++) {
1135 if (coeffs[slitlet*nbins+bin] != NULL) {
1136 poly = coeffs[slitlet*nbins+bin];
1138 temp = cpl_polynomial_get_coeff (poly, &i);
1140 plane_val[k] = temp/median[bin];
1145 tempvector = cpl_vector_wrap (k, plane_val);
1146 tempvector2= sinfo_juha_vector_filter_median_create (tempvector,
1148 cpl_vector_unwrap (tempvector);
1150 for (bin=0; bin<nbins; bin++) {
1151 if (coeffs[slitlet*nbins+bin] != NULL) {
1152 poly = coeffs[slitlet*nbins+bin];
1154 cpl_polynomial_set_coeff(poly, &i, cpl_vector_get(tempvector2, kk++)
1158 cpl_vector_delete (tempvector2);
1164 sinfo_msg(
"Smoothing higher terms (with order %d)", smooth_order);
1165 for (slitlet = 0; slitlet<32; slitlet++) {
1166 if (order[slitlet]>0) {
1167 for (j=1; j<=order[slitlet]; j++) {
1169 for (bin=0; bin<nbins; bin++) {
1170 if (coeffs[slitlet*nbins+bin] != NULL) {
1171 poly = coeffs[slitlet*nbins+bin];
1174 temp2 = cpl_polynomial_get_coeff (poly, &j);
1175 plane_pos[k] = pos[bin];
1176 plane_val[k] = temp2/median[bin];
1181 tempvector = cpl_vector_wrap (k, plane_pos);
1182 tempvector2= cpl_vector_wrap (k, plane_val);
1183 poly2 = cpl_polynomial_fit_1d_create (tempvector, tempvector2,
1184 smooth_order, &mse);
1185 cpl_vector_unwrap (tempvector);
1186 cpl_vector_unwrap (tempvector2);
1187 for (bin=0; bin<nbins; bin++) {
1188 if (coeffs[slitlet*nbins+bin] != NULL) {
1189 poly = coeffs[slitlet*nbins+bin];
1192 temp2 = cpl_polynomial_eval_1d (poly2, pos[bin], NULL);
1193 cpl_polynomial_set_coeff (poly, &j, temp2*median[bin]);
1196 cpl_polynomial_delete(poly2);
1206 sinfo_msg(
"Creating cube for illumination correction\n");
1207 result = cpl_imagelist_new ();
1208 for (i=0; i<nplanes; i++) {
1209 temp_image = cpl_image_new (64, 64, CPL_TYPE_FLOAT);
1210 cpl_imagelist_set (result, temp_image, i);
1213 sinfo_msg(
"nplanes=%d spec_bin=%d",nplanes,spec_bin);
1215 sinfo_msg(
"Interpolating\n");
1216 for (slitlet = 0; slitlet<32; slitlet++) {
1217 for (i=0; i<64; i++) {
1219 for (bin=0; bin<nbins; bin++) {
1220 if (coeffs[slitlet*nbins+bin] != NULL) {
1221 plane_pos[k] = pos[bin];
1222 plane_val[k] = cpl_polynomial_eval_1d(coeffs[slitlet*nbins+bin],
1223 cpl_vector_get(xpos, i),NULL)/
1230 sinfo_juha_function1d_natural_spline (plane_pos, plane_val, k,
1231 &inter_pos[(
int)plane_pos[0]],
1232 &inter_val[(
int)plane_pos[0]],
1233 (
int)(plane_pos[k-1]-plane_pos[0]));
1234 for (j=0; j<=(int)plane_pos[0]; j++)
1235 inter_val[j] = inter_val[(
int)plane_pos[0]+1];
1236 for (j=(
int)plane_pos[k-1]-1; j<nplanes; j++)
1237 inter_val[j] = inter_val[(
int)plane_pos[k-1]-2];
1238 for (k=0; k<nplanes; k++) {
1239 data = cpl_image_get_data_float(cpl_imagelist_get(result, k));
1240 data[i + (2*slitlet)*64] = inter_val[k];
1241 data[i + (2*slitlet+1)*64] = inter_val[k];
1250 else if (nbins==1) {
1251 sinfo_msg(
"Filling the illumination cube\n");
1252 for (slitlet = 0; slitlet<32; slitlet++) {
1253 for (i=0; i<64; i++) {
1254 if (coeffs[slitlet] != NULL) {
1255 temp = cpl_polynomial_eval_1d(coeffs[slitlet],
1256 cpl_vector_get(xpos, i),NULL)/median[0];
1257 for (k=0; k<nplanes; k++) {
1258 data = cpl_image_get_data_float(cpl_imagelist_get(result, k));
1259 data[i + (2*slitlet)*64] = temp;
1260 data[i + (2*slitlet+1)*64] = temp;
1261 sinfo_msg(
"temp=%g",temp);
1271 sinfo_msg(
"Writing ima out_illum.fits\n");
1280 sinfo_pro_save_ims(result,sof,sof,
"out_illum.fits",
1281 PRO_ILL_COR,NULL,plugin_id, cpl_cfg);
1286 sinfo_msg(
"Writing dat out_illum2.dat\n");
1287 dumpfile = fopen (
"out_illum2.dat",
"w");
1288 fprintf (dumpfile,
"# slitlet, pos, median, rms, coeff0, coeff1...\n");
1289 for (slitlet = 0; slitlet<32; slitlet++)
1290 for (bin=0; bin<nbins; bin++) {
1291 poly = coeffs[slitlet*nbins+bin];
1293 fprintf (dumpfile,
"%d %f %f %f ",slitlet, pos[bin],
1295 rms_values[slitlet*nbins+bin]);
1296 for (i=0; i<(cpl_polynomial_get_degree(poly)+1); i++) {
1297 temp = cpl_polynomial_get_coeff (poly, &i);
1298 fprintf (dumpfile,
"%f ", temp);
1300 fprintf (dumpfile,
"\n");
1308 for (i = 0; i<32*nbins; i++)
1309 if (coeffs[i] != NULL)
1310 cpl_polynomial_delete(coeffs[i]);
1311 cpl_imagelist_delete (sky);
1312 cpl_imagelist_delete (binnedsky);
1313 cpl_imagelist_delete (result);
1316 cpl_free (temparray);
1317 cpl_free (tempxarray);
1318 cpl_free (tempsarray);
1320 cpl_free (inter_pos);
1321 cpl_free (inter_val);
1322 cpl_free (plane_pos);
1323 cpl_free (plane_val);
1324 cpl_free (rms_values);
1325 cpl_vector_delete (xpos);
1326 cpl_vector_delete (model);
1328 cpl_free (bin_start);
1349 sinfo_illumcorr_create_bins (cpl_imagelist *sky,
1350 int llx,
int lly,
int urx,
int ury,
1358 double testarray3[15];
1359 double temp_double=0;
1360 int i=0, j=0, k=0,kk=0,nplanes=0;
1362 int norig = 0, nmerged = 0, ncont = 0, nline=0;
1373 double *spec_cont=NULL;
1374 double *spec_line=NULL;
1377 cpl_image *temp_image=NULL;
1379 nplanes = cpl_imagelist_get_size(sky);
1381 spec = (
double*) cpl_calloc(nplanes,
sizeof(
double));
1382 spec_line = (
double*) cpl_calloc(nplanes,
sizeof(
double));
1383 spec_cont = (
double*) cpl_calloc(nplanes,
sizeof(
double));
1386 pos = (
int*) cpl_calloc(nplanes,
sizeof(
int));
1387 flux = (
double*) cpl_calloc(nplanes,
sizeof(
double));
1388 x1 = (
int*) cpl_calloc(nplanes,
sizeof(
int));
1389 x2 = (
int*) cpl_calloc(nplanes,
sizeof(
int));
1390 x1b = (
int*) cpl_calloc(nplanes,
sizeof(
int));
1391 x2b = (
int*) cpl_calloc(nplanes,
sizeof(
int));
1393 for (i=z1; i<=z2; i++) {
1394 temp_image = cpl_imagelist_get(sky, i);
1395 spec[i] = sinfo_image_get_median_window (temp_image, llx, lly, urx, ury);
1397 for (i=z1+7; i<=z2-7; i++) {
1399 for (j=-7; j<=7; j++)
1400 if (!isnan(spec[i+j]))
1401 testarray3[k++] = spec[i+j];
1403 sinfo_tools_sort_double (&testarray3[0], k);
1404 spec_cont[i] = testarray3[1];
1407 spec_cont[i] = 0./0.;
1411 "original, continuum, line");
1412 for (i=z1; i<=z2; i++) {
1413 spec_line[i] = spec[i] - spec_cont[i];
1415 i,spec[i],spec_cont[i], spec_line[i]);
1422 sinfo_msg (
"Searching for peaks");
1423 temp_double = -10000.0;
1426 if (!isnan (spec_line[i])) {
1427 if (temp_double<spec_line[i]) {
1429 temp_double = spec_line[i];
1433 if (temp_i == i-1 && spec_line[temp_i]>min_flux) {
1435 for (j=-spec_bin/2; j<=spec_bin/2; j++)
1436 if (j+i>=0 && i+j<nplanes && isnan(spec[i+j])) {
1441 pos[norig] = temp_i;
1442 flux[norig] = temp_double;
1445 temp_double = -10000.0;
1446 while (spec_line[i]<spec_line[i-1])
1460 sinfo_msg (
"Merging emission features too close to each other");
1463 if (flux[i] > 0.0) {
1466 && (x1[j]-x2[i]) <=spec_bin
1477 nline = norig - nmerged;
1480 for (i=0; i<norig; i++)
1482 x1b[j] = x1[i] - spec_bin/2;
1483 x2b[j] = x2[i] + spec_bin/2;
1497 if (!isnan (spec[i])) {
1498 if (x1b[j]-i < spec_bin) {
1504 for (k=0; k<spec_bin; k++)
1505 if (spec[i+k]>min_flux)
1509 x2[ncont] = i+spec_bin-1;
1521 sinfo_msg (
"Number of bins centered on emission features:");
1522 sinfo_msg (
" %i - %i (merged) = %i", norig, nmerged, nline);
1523 sinfo_msg (
" %i continuum bins", ncont);
1525 s1 = (
int*)cpl_calloc(norig-nmerged+ncont,
sizeof(
int));
1526 s2 = (
int*)cpl_calloc(norig-nmerged+ncont,
sizeof(
int));
1535 while (k<norig-nmerged+ncont) {
1536 if (i<norig && j<ncont && x1b[i]<x1[j]) {
1542 else if (i<norig && j<ncont && x1b[i]>x1[j]) {
1548 else if (i == norig) {
1554 else if (j == ncont) {
1563 "the bins %i and %i", i,j);
1568 for (i=0; i<nline+ncont; i++)
1581 cpl_free (spec_line);
1582 cpl_free (spec_cont);
1584 return (nline+ncont);
1618 sinfo_juha_function1d_natural_spline(
1629 register int i, j, n;
1643 a = cpl_malloc(
sizeof(
double) * splLen * 9) ;
1653 for (i = 0; i < len; i++) {
1654 a[i] = (double)y[i];
1658 for (i = 0; i < end; i++) {
1659 h[i] = (double)x[i + 1] - (
double)x[i];
1667 for (n = 0, i = 1; i < end; i++, n++) {
1669 alpha[i] = 3.0 * ((a[i+1] / h[i]) - (a[i] / h[n]) - (a[i] / h[i]) +
1674 l[0] = l[end] = 1.0;
1675 mu[0] = mu[end] = 0.0;
1676 z[0] = z[end] = 0.0;
1677 c[0] = c[end] = 0.0;
1680 for (n = 0, i = 1; i < end; i++, n++) {
1682 l[i] = 2 * (h[i] + h[n]) - h[n] * mu[n];
1683 mu[i] = h[i] / l[i];
1684 z[i] = (alpha[i] - h[n] * z[n]) / l[i];
1686 for (n = end, j = end - 1; j >= 0; j--, n--) {
1688 c[j] = z[j] - mu[j] * c[n];
1689 b[j] = (a[n] - a[j]) / h[j] - h[j] * (c[n] + 2.0 * c[j]) / 3.0;
1690 d[j] = (c[n] - c[j]) / (3.0 * h[j]);
1694 for (j = 0; j < splLen; j++) {
1695 v = (double)splX[j];
1699 if ((v < (
double)x[0]) || (v > (
double)x[end])) {
1703 loc = sinfo_function1d_search_value(x, len, (
double)v, &found);
1708 v -= (double)x[loc];
1709 splY[j] = (float)( a[loc] + v * (b[loc] + v * (c[loc] + v * d[loc])));
1735 sinfo_function1d_search_value(
1749 while (high >= low) {
1750 middle = (high + low) / 2;
1751 if (key > x[middle]) {
1753 }
else if (key < x[middle]) {
1800 sinfo_juha_vector_filter_median_create(
1801 const cpl_vector * v,
1804 cpl_vector * filtered=NULL;
1809 size = cpl_vector_get_size(v);
1810 filtered = cpl_vector_new(size);
1812 row = cpl_malloc((2*hw+1) *
sizeof(
double));
1813 for (i=0; i<size; i++) {
1815 for (j=-hw; j<=hw; j++)
1816 if ( (i+j) >= 0 && (i+j) < size) {
1817 temp = cpl_vector_get (v, i+j);
1821 sinfo_tools_sort_double (row, k);
1827 cpl_vector_set (filtered, i, temp);
1833 #define CPL_PIX_STACK_SIZE 50
1846 static cpl_error_code sinfo_tools_sort_double(
1856 cpl_ensure(pix_arr, CPL_ERROR_NULL_INPUT, CPL_ERROR_NULL_INPUT) ;
1861 i_stack = malloc(CPL_PIX_STACK_SIZE *
sizeof(
double)) ;
1864 for (j=l+1 ; j<=ir ; j++) {
1866 for (i=j-1 ; i>=1 ; i--) {
1867 if (pix_arr[i-1] <= a)
break;
1868 pix_arr[i] = pix_arr[i-1];
1872 if (j_stack == 0)
break;
1873 ir = i_stack[j_stack-- -1];
1874 l = i_stack[j_stack-- -1];
1877 SINFO_DOUBLE_SWAP(pix_arr[k-1], pix_arr[l])
1878 if (pix_arr[l] > pix_arr[ir-1]) {
1879 SINFO_DOUBLE_SWAP(pix_arr[l], pix_arr[ir-1])
1881 if (pix_arr[l-1] > pix_arr[ir-1]) {
1882 SINFO_DOUBLE_SWAP(pix_arr[l-1], pix_arr[ir-1])
1884 if (pix_arr[l] > pix_arr[l-1]) {
1885 SINFO_DOUBLE_SWAP(pix_arr[l], pix_arr[l-1])
1891 do i++;
while (pix_arr[i-1] < a);
1892 do j--;
while (pix_arr[j-1] > a);
1894 SINFO_DOUBLE_SWAP(pix_arr[i-1], pix_arr[j-1]);
1896 pix_arr[l-1] = pix_arr[j-1];
1899 if (j_stack > CPL_PIX_STACK_SIZE) {
1902 return CPL_ERROR_ILLEGAL_INPUT ;
1904 if (ir-i+1 >= j-l) {
1905 i_stack[j_stack-1] = ir;
1906 i_stack[j_stack-2] = i;
1909 i_stack[j_stack-1] = j-1;
1910 i_stack[j_stack-2] = l;
1916 return CPL_ERROR_NONE ;
1920 sinfo_vector_filter_median_create(
1921 const cpl_vector * v,
1924 cpl_vector * filtered;
1930 size = cpl_vector_get_size(v);
1931 filtered = cpl_vector_new(size);
1934 row = cpl_vector_new((2*hw+1));
1935 for (i=0; i<size; i++) {
1937 for (j=-hw; j<=hw; j++)
1938 if ( (i+j) >= 0 && (i+j) < size) {
1939 temp = cpl_vector_get (v, i+j);
1940 cpl_vector_set(row,k,temp);
1945 cpl_vector_sort(row, +1);
1947 temp = cpl_vector_get(row,k/2);
1950 temp = cpl_vector_get(row,k/2-1);
1953 sinfo_msg(
"value = %g ", temp);
1954 cpl_vector_set (filtered, i, temp);
1956 cpl_vector_delete(row);
1964 sinfo_image_get_median_window (
const cpl_image *image,
1965 int llx,
int lly,
int urx,
int ury)
1969 double *array, median;
1972 window = cpl_image_extract (image, llx, lly, urx, ury);
1973 size = (urx-llx+1)*(ury-lly+1);
1974 data = cpl_image_get_data_float(window);
1976 array = (
double*)cpl_calloc ( size,
sizeof(
double));
1978 for (i=0; i<size; i++)
1979 if (!isnan(data[i]))
1980 array[j++] = data[i];
1983 sinfo_tools_sort_double (array, j);
1985 if (j == 0 || 2*j<size)
1988 median = array[j/2];
1990 median = array[j/2-1];
1992 cpl_image_delete (window);