VIRCAM Pipeline 2.3.12
casu_sky.c
1/* $Id: casu_sky.c,v 1.2 2015/08/07 13:06:54 jim Exp $
2 *
3 * This file is part of the CASU Pipeline utilities
4 * Copyright (C) 2015 European Southern Observatory
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 */
20
21/*
22 * $Author: jim $
23 * $Date: 2015/08/07 13:06:54 $
24 * $Revision: 1.2 $
25 * $Name: $
26 */
27
28/* Includes */
29
30#ifdef HAVE_CONFIG_H
31#include <config.h>
32#endif
33
34#include <cpl.h>
35#include <math.h>
36#include <string.h>
37
38#include "casu_sky.h"
39#include "casu_mask.h"
40#include "catalogue/casu_fits.h"
41#include "casu_mods.h"
42#include "catalogue/casu_utils.h"
43#include "casu_stats.h"
44#include "catalogue/casu_wcsutils.h"
45
46static void casu_sky_mask_grow(cpl_image *dith, float rad);
47static float casu_sky_med(casu_fits *sky);
48static void casu_sky_joffs(casu_fits **inlist, int nfiles, float **xoffs,
49 float **yoffs);
50static void casu_sky_xytoxy(cpl_wcs *inwcs, cpl_wcs *outwcs,
51 cpl_matrix *inxy, cpl_matrix **outxy);
52
55/*---------------------------------------------------------------------------*/
108/*---------------------------------------------------------------------------*/
109
110extern int casu_pawsky_mask(casu_fits **inlist, casu_fits **invar, int nfiles,
111 casu_fits *conf, casu_mask *mask,
112 casu_fits **skyout, casu_fits **skyvar, int niter,
113 int ipix, float thresh, int nbsize, float smkern,
114 int *status) {
115 int i,nx,ny,nbad0,lastone,iter,npts,nbad_init,nbad,dbad;
116 int xx1,xx2,yy1,yy2,nfiles2,*confdata;
117 const char *fctid = "casu_pawsky_mask";
118 cpl_image *dith,*dithc,*skyim,*im,*newim,*outim,*outimv;
119 cpl_mask *cplmask,*dithmask,*newmask,*curmask;
120 casu_fits **list_ss,*dithf,*dithcf,**inlist2,**invar2;
121 unsigned char *inbpm,*rejmask,*rejplus;
122 float medsky,*xoffs,*yoffs,mindx,mindy,fbad;
123 cpl_propertylist *p,*drs;
124
125 /* Inherited status */
126
127 *skyout = NULL;
128 *skyvar = NULL;
129 if (*status != CASU_OK)
130 return(*status);
131
132 /* If there aren't any images, then get out of here */
133
134 if (nfiles == 0) {
135 cpl_msg_error(fctid,"Sky correction impossible. No science frames");
136 FATAL_ERROR
137 }
138
139 /* Check to see which files are good */
140
141 inlist2 = cpl_malloc(nfiles*sizeof(casu_fits *));
142 if (invar != NULL)
143 invar2 = cpl_malloc(nfiles*sizeof(casu_fits *));
144 else
145 invar2 = NULL;
146 nfiles2 = 0;
147 for (i = 0; i < nfiles; i++) {
148 if (casu_fits_get_status(inlist[i]) == CASU_OK) {
149 inlist2[nfiles2] = inlist[i];
150 if (invar != NULL)
151 invar2[nfiles2] = invar[i];
152 nfiles2++;
153 }
154 }
155
156 /* If no good images are present then wrap a dummy image and return it */
157
158 if (nfiles2 == 0) {
159 outim = casu_dummy_image(inlist[0]);
160 *skyout = casu_fits_wrap(outim,inlist[0],NULL,NULL);
162 casu_fits_set_status(*skyout,CASU_FATAL);
163 if (invar != NULL) {
164 outimv = casu_dummy_image(inlist[0]);
165 *skyvar = casu_fits_wrap(outimv,inlist[0],NULL,NULL);
167 } else {
168 *skyvar = NULL;
169 }
170 cpl_msg_warning(fctid,"No good images in input list");
171 freespace(inlist2);
172 freespace(invar2);
173 *status = CASU_WARN;
174 return(CASU_WARN);
175 }
176
177 /* Wrap the input mask into a cpl_mask structure and use it to set the
178 internal mask for each of the input images */
179
180 inbpm = casu_mask_get_data(mask);
181 nx = casu_mask_get_size_x(mask);
182 ny = casu_mask_get_size_y(mask);
183 cplmask = cpl_mask_wrap((cpl_size)nx,(cpl_size)ny,(cpl_binary *)inbpm);
184 for (i = 0; i < nfiles2; i++)
185 cpl_image_reject_from_mask(casu_fits_get_image(inlist2[i]),cplmask);
186 cpl_mask_unwrap(cplmask);
187
188 /* Do an initial sky combination */
189
190 casu_imcombine(inlist2,invar2,nfiles2,1,1,0,2.0,"EXPTIME",&outim,&outimv,
191 &rejmask,&rejplus,&drs,status);
192 *skyout = casu_fits_wrap(outim,inlist2[0],NULL,NULL);
193 if (invar != NULL)
194 *skyvar = casu_fits_wrap(outimv,invar2[0],NULL,NULL);
195 freespace(rejmask);
196 freespace(rejplus);
197 freepropertylist(drs);
198
199 /* Clean up any blank bits */
200
201 (void)casu_inpaint(*skyout,nbsize,status);
202
203 /* If this is the only iteration then get out of here now */
204
205 if (niter == 0)
206 return(*status);
207
208 /* Work out the median sky, ignoring the bad bits */
209
210 medsky = casu_sky_med(*skyout);
211
212 /* Get jitter offsets from wcs */
213
214 casu_sky_joffs(inlist2,nfiles2,&xoffs,&yoffs);
215 mindx = xoffs[0];
216 mindy = yoffs[0];
217 for (i = 1; i < nfiles2; i++) {
218 mindx = min(mindx,xoffs[i]);
219 mindy = min(mindy,yoffs[i]);
220 }
221
222 /* Do an initial subtraction */
223
224 list_ss = cpl_malloc(nfiles2*sizeof(casu_fits *));
225 skyim = casu_fits_get_image(*skyout);
226 for (i = 0; i < nfiles2; i++) {
227 im = casu_fits_get_image(inlist2[i]);
228 newim = cpl_image_subtract_create(im,skyim);
229 cpl_image_add_scalar(newim,(double)medsky);
230 list_ss[i] = casu_fits_wrap(newim,inlist2[i],NULL,NULL);
231 }
232 casu_fits_delete(*skyout);
233 if (invar != NULL)
234 casu_fits_delete(*skyvar);
235
236 /* Set up some counters and begin the iteration loop */
237
238 nbad0 = 0;
239 lastone = 0;
240 for (iter = 1; iter <= niter; iter++) {
241 if (lastone)
242 break;
243 lastone = (iter == niter);
244
245 /* Dither the sky subtracted input images */
246
247 (void)casu_imdither(list_ss,&conf,nfiles2,1,5.0,5.0,&p,"EXPTIME",&dith,
248 &dithc,status);
249 cpl_propertylist_delete(p);
250
251 /* How many dead pixels are there in the dithered image? */
252
253 confdata = cpl_image_get_data_int(dithc);
254 npts = (int)cpl_image_get_size_x(dithc)*(int)cpl_image_get_size_y(dithc);
255 nbad_init = 0;
256 for (i = 0; i < npts; i++)
257 if (confdata[i] == 0)
258 nbad_init++;
259
260 /* Get rid of the sky subtracted images */
261
262 for (i = 0; i < nfiles2; i++)
263 casu_fits_delete(list_ss[i]);
264
265 /* Wrap the result */
266
267 dithf = casu_fits_wrap(dith,inlist2[0],NULL,NULL);
268 dithcf = casu_fits_wrap(dithc,conf,NULL,NULL);
269
270 /* Now get an object mask from this dithered image */
271
272 (void)casu_opm(dithf,dithcf,ipix,thresh,nbsize,smkern,2,status);
273
274 /* How many flagged pixels are there, not counting the ones already
275 flagged in the confidence map */
276
277 nbad = (int)cpl_image_count_rejected((const cpl_image *)dith) -
278 nbad_init;
279 dbad = nbad - nbad0;
280 fbad = (iter > 1 ? (float)abs(dbad)/(float)nbad0 : 10000.0);
281 cpl_msg_info(fctid,
282 "Iteration: %" CPL_SIZE_FORMAT ", Nreject: %" CPL_SIZE_FORMAT " %" CPL_SIZE_FORMAT,
283 (cpl_size)iter,(cpl_size)nbad,(cpl_size)nbad0);
284 if (fbad < 0.025 || dbad < 0) {
285 lastone = 1;
286 } else {
287 nbad0 = nbad;
288 }
289
290 /* Allow the mask to grow before the next iteration */
291
292 casu_sky_mask_grow(dith,2);
293
294 /* Right, now decide which part of the mask belongs to each of the
295 input images and update the input mask. */
296
297 dithmask = cpl_image_get_bpm(dith);
298 for (i = 0; i < nfiles2; i++) {
299 xx1 = (int)(-mindx + xoffs[i] + 1.5);
300 xx2 = xx1 + nx - 1;
301 yy1 = (int)(-mindy + yoffs[i] + 1.5);
302 yy2 = yy1 + ny - 1;
303 newmask = cpl_mask_extract(dithmask,(cpl_size)xx1,(cpl_size)yy1,
304 (cpl_size)xx2,(cpl_size)yy2);
305 curmask = cpl_image_get_bpm(casu_fits_get_image(inlist2[i]));
306 cpl_mask_or(curmask,newmask);
307 cpl_mask_delete(newmask);
308 }
309
310 /* Delete the dither and its confidence map */
311
312 casu_fits_delete(dithf);
313 casu_fits_delete(dithcf);
314
315 /* Do a new sky combination using these new object masks */
316
317 casu_imcombine(inlist2,invar2,nfiles2,1,1,0,2.0,"EXPTIME",&outim,
318 &outimv,&rejmask,&rejplus,&drs,status);
319 *skyout = casu_fits_wrap(outim,inlist2[0],NULL,NULL);
320 if (invar != NULL)
321 *skyvar = casu_fits_wrap(outimv,invar2[0],NULL,NULL);
322 freespace(rejmask);
323 freespace(rejplus);
324 freepropertylist(drs);
325 p = casu_fits_get_ehu(*skyout);
326 cpl_propertylist_update_string(p,"ESO DRS SKYALGO","pawsky_mask");
327 cpl_propertylist_set_comment(p,"ESO DRS SKYALGO",
328 "Sky estimation algorithm");
329
330 /* Clean up any blank bits */
331
332 (void)casu_inpaint(*skyout,nbsize,status);
333
334 /* Do the sky subtraction again so long as this isn't
335 the last iteration */
336
337 if (! lastone) {
338 skyim = casu_fits_get_image(*skyout);
339 for (i = 0; i < nfiles2; i++) {
340 im = casu_fits_get_image(inlist2[i]);
341 newim = cpl_image_subtract_create(im,skyim);
342 cpl_image_add_scalar(newim,(double)medsky);
343 list_ss[i] = casu_fits_wrap(newim,inlist2[i],NULL,NULL);
344 }
345 casu_fits_delete(*skyout);
346 if (invar != NULL)
347 casu_fits_delete(*skyvar);
348 }
349 }
350
351 /* Free up some workspace that we've collected along the way */
352
353 freespace(xoffs);
354 freespace(yoffs);
355 freespace(list_ss);
356 freespace(inlist2);
357 freespace(invar2);
358 return(*status);
359}
360
361/*---------------------------------------------------------------------------*/
410/*---------------------------------------------------------------------------*/
411
412extern int casu_pawsky_mask_pre(casu_fits **inlist, casu_fits **invar,
413 int nfiles, casu_mask *mask,
414 casu_fits *objmask, int nbsize,
415 casu_fits **skyout, casu_fits **skyvar,
416 int *status) {
417 const char *fctid = "casu_pawsky_mask_pre";
418 unsigned char *inbpm,*rejplus,*rejmask;
419 int nx,ny,npts,ncoor,i,j,nx_objmask,ny_objmask,k,kk,ix,iy,ind,*opm;
420 int nfiles2;
421 cpl_mask *cplmask;
422 cpl_wcs *wcs_objmask,*wcs;
423 cpl_matrix *in_xy,*out_xy,*ddx,*ddx_out;
424 cpl_image *im,*outim,*outimv;
425 cpl_propertylist *drs,*p;
426 double *inxy_data,xx,yy,*ddx_data,shiftx,shifty;
427 casu_fits **inlist2,**invar2;
428
429 /* Inherited status */
430
431 *skyout = NULL;
432 *skyvar = NULL;
433 if (*status != CASU_OK)
434 return(*status);
435
436 /* If there aren't any images, then get out of here */
437
438 if (nfiles == 0) {
439 cpl_msg_error(fctid,"Sky correction impossible. No science frames");
440 FATAL_ERROR
441 }
442
443 /* Check to see which files are good */
444
445 inlist2 = cpl_malloc(nfiles*sizeof(casu_fits *));
446 if (invar != NULL)
447 invar2 = cpl_malloc(nfiles*sizeof(casu_fits *));
448 else
449 invar2 = NULL;
450 nfiles2 = 0;
451 for (i = 0; i < nfiles; i++) {
452 if (casu_fits_get_status(inlist[i]) == CASU_OK) {
453 inlist2[nfiles2] = inlist[i];
454 if (invar != NULL)
455 invar2[nfiles2] = invar[i];
456 nfiles2++;
457 }
458 }
459
460 /* If no good images are present then wrap a dummy image and return it */
461
462 if (nfiles2 == 0) {
463 outim = casu_dummy_image(inlist[0]);
464 *skyout = casu_fits_wrap(outim,inlist[0],NULL,NULL);
466 casu_fits_set_status(*skyout,CASU_FATAL);
467 if (invar != NULL) {
468 outimv = casu_dummy_image(inlist[0]);
469 *skyvar = casu_fits_wrap(outimv,invar[0],NULL,NULL);
471 } else {
472 *skyvar = NULL;
473 }
474 cpl_msg_warning(fctid,"No good images in input list");
475 freespace(inlist2);
476 *status = CASU_WARN;
477 return(CASU_WARN);
478 }
479
480 /* Wrap the input mask into a cpl_mask structure and use it to set the
481 internal mask for each of the input images */
482
483 inbpm = casu_mask_get_data(mask);
484 nx = casu_mask_get_size_x(mask);
485 ny = casu_mask_get_size_y(mask);
486 cplmask = cpl_mask_wrap((cpl_size)nx,(cpl_size)ny,(cpl_binary *)inbpm);
487 for (i = 0; i < nfiles2; i++)
488 cpl_image_reject_from_mask(casu_fits_get_image(inlist2[i]),cplmask);
489 cpl_mask_unwrap(cplmask);
490
491 /* Open the WCS of the object mask and get the pixel mask info */
492
493 wcs_objmask = cpl_wcs_new_from_propertylist(casu_fits_get_ehu(objmask));
494 opm = cpl_image_get_data(casu_fits_get_image(objmask));
495 nx_objmask = cpl_image_get_size_x(casu_fits_get_image(objmask));
496 ny_objmask = cpl_image_get_size_y(casu_fits_get_image(objmask));
497
498 /* Get some memory so that we can do a transformation between the coordinate
499 systems of the input frames and that of the object mask */
500
501 npts = nx*ny;
502 ncoor = 2;
503 in_xy = cpl_matrix_new((cpl_size)npts,(cpl_size)ncoor);
504
505 /* Initialise the data for the first x,y matrix */
506
507 inxy_data = cpl_matrix_get_data(in_xy);
508 k = 0;
509 for (j = 0; j < ny; j++) {
510 for (i = 0; i < nx; i++) {
511 inxy_data[k++] = (double)(i+1);
512 inxy_data[k++] = (double)(j+1);
513 }
514 }
515
516 /* Initialise data for an offset matrix */
517
518 ddx = cpl_matrix_new(1,2);
519 ddx_data = cpl_matrix_get_data(ddx);
520 ddx_data[0] = 1.0;
521 ddx_data[1] = 1.0;
522
523 /* Loop for each input file. Convert the xy matrix to an xy in the object
524 mask frame of reference for the first file. Then use the offsets between
525 the first image and the subsequent ones to define the location of
526 the object pixels in the following images */
527
528 for (k = 0; k < nfiles2; k++) {
529 wcs = cpl_wcs_new_from_propertylist(casu_fits_get_ehu(inlist2[k]));
530 im = casu_fits_get_image(inlist2[k]);
531 if (k == 0)
532 casu_sky_xytoxy(wcs,wcs_objmask,in_xy,&out_xy);
533 casu_sky_xytoxy(wcs,wcs_objmask,ddx,&ddx_out);
534 cpl_wcs_delete(wcs);
535 shiftx = cpl_matrix_get(out_xy,0,0) - cpl_matrix_get(ddx_out,0,0);
536 shifty = cpl_matrix_get(out_xy,0,1) - cpl_matrix_get(ddx_out,0,1);
537 kk = 0;
538 for (j = 0; j < ny; j++) {
539 for (i = 0; i < nx; i++) {
540 xx = cpl_matrix_get(out_xy,kk,0) - shiftx;
541 yy = cpl_matrix_get(out_xy,kk,1) - shifty;
542 kk++;
543 ix = casu_nint(xx);
544 iy = casu_nint(yy);
545 if (ix < 1 || ix > nx_objmask || iy < 1 || iy > ny_objmask)
546 continue;
547 ind = (iy-1)*nx_objmask + ix - 1;
548 if (opm[ind])
549 cpl_image_reject(im,i+1,j+1);
550 }
551 }
552 cpl_matrix_delete(ddx_out);
553 }
554 cpl_matrix_delete(in_xy);
555 cpl_matrix_delete(out_xy);
556 cpl_wcs_delete(wcs_objmask);
557
558 /* Do a sky combination */
559
560 casu_imcombine(inlist2,invar2,nfiles2,1,1,0,2.0,"EXPTIME",&outim,&outimv,
561 &rejmask,&rejplus,&drs,status);
562 *skyout = casu_fits_wrap(outim,inlist2[0],NULL,NULL);
563 if (invar != NULL)
564 *skyvar = casu_fits_wrap(outimv,invar2[0],NULL,NULL);
565 freespace(rejmask);
566 freespace(rejplus);
567 freepropertylist(drs);
568 freespace(inlist2);
569 p = casu_fits_get_ehu(*skyout);
570 cpl_propertylist_update_string(p,"ESO DRS SKYALGO","pawsky_mask_pre");
571 cpl_propertylist_set_comment(p,"ESO DRS SKYALGO",
572 "Sky estimation algorithm");
573 cpl_propertylist_update_string(p,"ESO DRS MASKUSED",
574 casu_fits_get_filename(objmask));
575 cpl_propertylist_set_comment(p,"ESO DRS MASKUSED",
576 "Object masked used to make sky");
577
578 /* Clean up any blank bits */
579
580 (void)casu_inpaint(*skyout,nbsize,status);
581
582 /* Get out of here */
583
584 return(*status);
585}
586
587/*---------------------------------------------------------------------------*/
641/*---------------------------------------------------------------------------*/
642
643extern int casu_simplesky_mask(casu_fits **inlist, casu_fits **invar,
644 int nfiles, casu_fits *conf, casu_mask *mask,
645 casu_fits **skyout, casu_fits **skyvar,
646 int niter, int ipix, float thresh, int nbsize,
647 float smkern, int *status) {
648 const char *fctid = "casu_simplesky_mask";
649 unsigned char *inbpm,*rejmask,*rejplus;
650 int nx,ny,i,ninit,nbad0,iter,nbad,nb,dbad,lastone,nfiles2;
651 cpl_mask *cplmask,*newmask,*oldmask;
652 cpl_image *outim,*skyim,*im,*outimv;
653 cpl_propertylist *drs,*p;
654 casu_fits *skysub_im,**inlist2,**invar2;
655 float fbad,medsky;
656
657 /* Inherited status */
658
659 *skyout = NULL;
660 *skyvar = NULL;
661 if (*status != CASU_OK)
662 return(*status);
663
664 /* If there aren't any images, then get out of here */
665
666 if (nfiles == 0) {
667 cpl_msg_error(fctid,"Sky correction impossible. No science frames");
668 FATAL_ERROR
669 }
670
671 /* Check to see which files are good */
672
673 inlist2 = cpl_malloc(nfiles*sizeof(casu_fits *));
674 if (invar != NULL)
675 invar2 = cpl_malloc(nfiles*sizeof(casu_fits*));
676 else
677 invar2 = NULL;
678 nfiles2 = 0;
679 for (i = 0; i < nfiles; i++) {
680 if (casu_fits_get_status(inlist[i]) == CASU_OK) {
681 inlist2[nfiles2] = inlist[i];
682 if (invar != NULL)
683 invar2[nfiles2] = invar[i];
684 nfiles2++;
685 }
686 }
687
688 /* If no good images are present then wrap a dummy image and return it */
689
690 if (nfiles2 == 0) {
691 outim = casu_dummy_image(inlist[0]);
692 *skyout = casu_fits_wrap(outim,inlist[0],NULL,NULL);
694 casu_fits_set_status(*skyout,CASU_FATAL);
695 if (invar != NULL) {
696 outimv = casu_dummy_image(inlist[0]);
697 *skyvar = casu_fits_wrap(outimv,inlist[0],NULL,NULL);
699 } else {
700 *skyvar = NULL;
701 }
702 cpl_msg_warning(fctid,"No good images in input list");
703 freespace(inlist2);
704 *status = CASU_WARN;
705 return(CASU_WARN);
706 }
707
708 /* Wrap the input mask into a cpl_mask structure and use it to set the
709 internal mask for each of the input images */
710
711 inbpm = casu_mask_get_data(mask);
712 nx = casu_mask_get_size_x(mask);
713 ny = casu_mask_get_size_y(mask);
714 cplmask = cpl_mask_wrap((cpl_size)nx,(cpl_size)ny,(cpl_binary *)inbpm);
715 for (i = 0; i < nfiles2; i++)
716 cpl_image_reject_from_mask(casu_fits_get_image(inlist2[i]),cplmask);
717 cpl_mask_unwrap(cplmask);
718 ninit = cpl_image_count_rejected((const cpl_image *)casu_fits_get_image(inlist2[0]));
719
720 /* Do an initial sky combination */
721
722 casu_imcombine(inlist2,invar2,nfiles2,1,1,0,2.0,"EXPTIME",&outim,&outimv,
723 &rejmask,&rejplus,&drs,status);
724 *skyout = casu_fits_wrap(outim,inlist2[0],NULL,NULL);
725 if (invar != NULL)
726 *skyvar = casu_fits_wrap(outimv,invar2[0],NULL,NULL);
727 freespace(rejmask);
728 freespace(rejplus);
729 freepropertylist(drs);
730
731 /* Clean up any blank bits */
732
733 (void)casu_inpaint(*skyout,nbsize,status);
734
735 /* If this is the only iteration then get out of here now */
736
737 if (niter == 0)
738 return(*status);
739
740 /* Begin the iteration loop */
741
742 nbad0 = 0;
743 for (iter = 1; iter <= niter; iter++) {
744
745 /* For each image, sky subtract using the latest sky. Then create
746 an object mask from the sky subtracted image and count the number
747 of bad pixels */
748
749 skyim = casu_fits_get_image(*skyout);
750 medsky = casu_sky_med(*skyout);
751 nbad = 0;
752 for (i = 0; i < nfiles2; i++) {
753 im = casu_fits_get_image(inlist2[i]);
754 outim = cpl_image_subtract_create(im,skyim);
755 cpl_image_add_scalar(outim,(double)medsky);
756 skysub_im = casu_fits_wrap(outim,inlist2[i],NULL,NULL);
757 *status = CASU_OK;
758 (void)casu_opm(skysub_im,conf,ipix,thresh,nbsize,smkern,2,
759 status);
760 nb = (int)cpl_image_count_rejected((const cpl_image *)outim) -
761 ninit;
762 nbad += nb;
763 newmask = cpl_image_get_bpm(outim);
764 oldmask = cpl_image_get_bpm(im);
765 cpl_mask_or(oldmask,newmask);
766 freefits(skysub_im);
767 }
768
769 /* Update report on the number of pixels rejected */
770
771 dbad = nbad - nbad0;
772 fbad = (iter > 1 ? (float)abs(dbad)/(float)nbad0 : 10000.0);
773 cpl_msg_info(fctid,
774 "Iteration: %" CPL_SIZE_FORMAT ", Nreject: %" CPL_SIZE_FORMAT " %" CPL_SIZE_FORMAT,
775 (cpl_size)iter,(cpl_size)nbad,(cpl_size)nbad0);
776
777 if (fbad < 0.025 || dbad < 0) {
778 lastone = 1;
779 } else {
780 nbad0 = nbad;
781 lastone = 0;
782 }
783
784 /* If this has converged or this is the last iteration, then
785 get out of here now. */
786
787 if (lastone || iter == niter) {
788 break;
789
790 /* Otherwise, delete the current sky and create a new one */
791
792 } else {
793 freefits(*skyout);
794 casu_imcombine(inlist2,invar2,nfiles2,1,1,0,2.0,"EXPTIME",&outim,
795 &outimv,&rejmask,&rejplus,&drs,status);
796 *skyout = casu_fits_wrap(outim,inlist2[0],NULL,NULL);
797 if (invar != NULL)
798 *skyvar = casu_fits_wrap(outimv,invar2[0],NULL,NULL);
799 (void)casu_inpaint(*skyout,nbsize,status);
800 freespace(rejmask);
801 freespace(rejplus);
802 freepropertylist(drs);
803 p = casu_fits_get_ehu(*skyout);
804 cpl_propertylist_update_string(p,"ESO DRS SKYALGO",
805 "simplesky_mask");
806 cpl_propertylist_set_comment(p,"ESO DRS SKYALGO",
807 "Sky estimation algorithm");
808 }
809 }
810 freespace(inlist2);
811 freespace(invar2);
812 return(*status);
813}
814
815/*---------------------------------------------------------------------------*/
833/*---------------------------------------------------------------------------*/
834
835static void casu_sky_mask_grow(cpl_image *dith, float rad) {
836 cpl_binary *inmap,*outmap;
837 int nx,ny,ir,i,j,indx,ixmin,ixmax,iymin,iymax,ii,jj,indx2;
838 float dx,dy,radius;
839
840 /* Get the input map */
841
842 inmap = cpl_mask_get_data(cpl_image_get_bpm(dith));
843 nx = (int)cpl_image_get_size_x(dith);
844 ny = (int)cpl_image_get_size_y(dith);
845
846 /* Get an output map of the same size. Copy the input map to it */
847
848 outmap = cpl_malloc(nx*ny*sizeof(*outmap));
849 memmove(outmap,inmap,nx*ny*sizeof(*inmap));
850
851 /* What is the minimum cell size that we need to consider given the
852 input radius */
853
854 ir = casu_nint(rad);
855
856 /* Right, loop through the input image. If the current input pixel is
857 not flagged, then move on to the next one. If it is, then look at
858 a cell around it. Find all the pixels in that cell that are within
859 the grow radius and flag them */
860
861 for (j = 0; j < ny; j++) {
862 for (i = 0; i < nx; i++) {
863 indx = j*nx + i;
864 if (inmap[indx] != 2)
865 continue;
866 ixmin = max(0,i-ir);
867 ixmax = min(nx-1,i+ir);
868 iymin = max(0,j-ir);
869 iymax = min(ny-1,j+ir);
870 for (jj = iymin; jj <= iymax; jj++) {
871 dy = (float)(jj - j);
872 for (ii = ixmin; ii <= ixmax; ii++) {
873 dx = (float)(ii - i);
874 radius = (float)sqrt(pow(dx,2.0) + pow(dy,2.0));
875 if (radius <= rad) {
876 indx2 = jj*nx + ii;
877 outmap[indx2] = 1;
878 }
879 }
880 }
881 }
882 }
883
884 /* Now move the result back into the input mask. Free up workspace
885 and get out of here */
886
887 memmove(inmap,outmap,nx*ny*sizeof(*inmap));
888 cpl_free(outmap);
889}
890
891/*---------------------------------------------------------------------------*/
909/*---------------------------------------------------------------------------*/
910
911static float casu_sky_med(casu_fits *sky) {
912 int npts;
913 float *data,med;
914 unsigned char *bpm;
915 cpl_image *skyim;
916
917 /* Get the size of the data array */
918
919 skyim = casu_fits_get_image(sky);
920 npts = (int)cpl_image_get_size_x(skyim)*(int)cpl_image_get_size_y(skyim);
921
922 /* Get the data */
923
924 data = cpl_image_get_data_float(skyim);
925 bpm = (unsigned char *)cpl_mask_get_data(cpl_image_get_bpm(skyim));
926
927 /* Get the median */
928
929 med = casu_med(data,bpm,(long)npts);
930 return(med);
931}
932
933/*---------------------------------------------------------------------------*/
955/*---------------------------------------------------------------------------*/
956
957static void casu_sky_joffs(casu_fits **inlist, int nfiles, float **xoffs,
958 float **yoffs) {
959 float xoff,yoff;
960 cpl_wcs *wcsref,*wcs;
961 int refset,i,status;
962 const double maxoffset = 12000;
963 casu_fits *ff;
964 const char *fctid = "casu_sky_joffs";
965
966 /* Get a bit of workspace to hold the offsets */
967
968 *xoffs = cpl_malloc(nfiles*sizeof(float));
969 *yoffs = cpl_malloc(nfiles*sizeof(float));
970
971 /* Work out the jitter offsets from the WCS. First loop for each image */
972
973 refset = 0;
974 wcsref = NULL;
975 for (i = 0; i < nfiles; i++) {
976 ff = inlist[i];
977 wcs = cpl_wcs_new_from_propertylist(casu_fits_get_ehu(ff));
978
979 /* If we can't get a WCS for this image, then signal that with
980 a warning */
981
982 if (wcs == NULL) {
983 cpl_msg_warning(fctid,"Unable to get WCS for %s",
985 (*xoffs)[i] = 0.0;
986 (*yoffs)[i] = 0.0;
987 casu_fits_set_error(ff,CASU_WARN);
988 continue;
989 }
990
991 /* Define the reference wcs pointer and set the first offset to zero */
992
993 if (! refset) {
994 (*xoffs)[0] = 0.0;
995 (*yoffs)[0] = 0.0;
996 refset = 1;
997 wcsref = wcs;
998 continue;
999 }
1000
1001 /* Work out the x,y offset */
1002
1003 status = CASU_OK;
1004 (void)casu_diffxywcs(wcs,wcsref,&xoff,&yoff,&status);
1005
1006 /* Did it work? If not the set a warning status for this file */
1007
1008 if (status != CASU_OK) {
1009 (*xoffs)[i] = 0.0;
1010 (*yoffs)[i] = 0.0;
1011 cpl_msg_warning(fctid,"Unable to WCS difference for %s",
1013 } else if (fabs((double)xoff) > maxoffset ||
1014 fabs((double)yoff) > maxoffset) {
1015 casu_fits_set_error(ff,CASU_FATAL);
1016 cpl_msg_error(fctid,"WCS offsets for %s are >%g: %g %g -- ignoring",
1017 casu_fits_get_filename(ff),maxoffset,xoff,yoff);
1018 } else {
1019 (*xoffs)[i] = xoff;
1020 (*yoffs)[i] = yoff;
1021 }
1022 cpl_wcs_delete(wcs);
1023 }
1024 if (wcsref != NULL)
1025 cpl_wcs_delete(wcsref);
1026
1027 /* Write the results to the headers */
1028
1029 for (i = 0; i < nfiles; i++) {
1030 ff = inlist[i];
1031 cpl_propertylist_update_double(casu_fits_get_ehu(ff),
1032 "ESO DRS XOFFDITHER",
1033 (double)(*xoffs)[i]);
1034 cpl_propertylist_update_double(casu_fits_get_ehu(ff),
1035 "ESO DRS YOFFDITHER",
1036 (double)(*yoffs)[i]);
1037 }
1038}
1039
1040/*---------------------------------------------------------------------------*/
1062/*---------------------------------------------------------------------------*/
1063
1064static void casu_sky_xytoxy(cpl_wcs *inwcs, cpl_wcs *outwcs,
1065 cpl_matrix *inxy, cpl_matrix **outxy) {
1066 cpl_matrix *radec;
1067 cpl_array *wstatus;
1068
1069 /* Convert the input xy data to RA/Dec */
1070
1071 cpl_wcs_convert(inwcs,inxy,&radec,&wstatus,CPL_WCS_PHYS2WORLD);
1072 cpl_array_delete(wstatus);
1073
1074 /* Now convert the RA/Dec to the xy coordinates of the second image */
1075
1076 cpl_wcs_convert(outwcs,radec,outxy,&wstatus,CPL_WCS_WORLD2PHYS);
1077 cpl_array_delete(wstatus);
1078 cpl_matrix_delete(radec);
1079}
1080
1083/*
1084
1085$Log: casu_sky.c,v $
1086Revision 1.2 2015/08/07 13:06:54 jim
1087Fixed copyright to ESO
1088
1089Revision 1.1.1.1 2015/06/12 10:44:32 jim
1090Initial import
1091
1092Revision 1.12 2015/04/30 12:07:43 jim
1093raised the maximum offset to be used in pawsky_mask
1094
1095Revision 1.11 2015/03/03 10:48:11 jim
1096Fixed some memory leaks
1097
1098Revision 1.10 2015/01/29 11:56:27 jim
1099modified comments
1100
1101Revision 1.9 2015/01/09 12:13:15 jim
1102*** empty log message ***
1103
1104Revision 1.8 2014/12/11 12:23:33 jim
1105new version
1106
1107Revision 1.7 2014/04/09 11:08:21 jim
1108Get rid of a couple of compiler moans
1109
1110Revision 1.6 2014/03/26 15:58:46 jim
1111Uses floating point confidence
1112
1113Revision 1.5 2013/11/27 10:35:27 jim
1114Fixed routines so that add the DRS SKYALGO header keyword
1115
1116Revision 1.4 2013/11/21 09:38:14 jim
1117detabbed
1118
1119Revision 1.3 2013-10-24 09:26:28 jim
1120traps for dummy input files and tries to remove them from the analysis
1121
1122Revision 1.2 2013-09-30 18:12:24 jim
1123Added casu_simplesky_mask
1124
1125Revision 1.1.1.1 2013-08-27 12:07:48 jim
1126Imported
1127
1128
1129*/
casu_fits * casu_fits_wrap(cpl_image *im, casu_fits *model, cpl_propertylist *phu, cpl_propertylist *ehu)
Definition: casu_fits.c:883
int casu_fits_get_status(casu_fits *p)
Definition: casu_fits.c:711
cpl_image * casu_fits_get_image(casu_fits *p)
Definition: casu_fits.c:436
void casu_fits_delete(casu_fits *p)
Definition: casu_fits.c:364
int casu_fits_set_error(casu_fits *p, int status)
Definition: casu_fits.c:747
char * casu_fits_get_filename(casu_fits *p)
Definition: casu_fits.c:646
void casu_fits_set_status(casu_fits *p, int status)
Definition: casu_fits.c:801
cpl_propertylist * casu_fits_get_ehu(casu_fits *p)
Definition: casu_fits.c:576
unsigned char * casu_mask_get_data(casu_mask *m)
Definition: casu_mask.c:544
int casu_mask_get_size_y(casu_mask *m)
Definition: casu_mask.c:498
int casu_mask_get_size_x(casu_mask *m)
Definition: casu_mask.c:475
int casu_imdither(casu_fits **inf, casu_fits **inconf, int nimages, int nconfs, float lthr, float hthr, cpl_propertylist **p, const char *expkey, cpl_image **out, cpl_image **outc, int *status)
Dither a set of jittered observations.
int casu_simplesky_mask(casu_fits **inlist, casu_fits **invar, int nfiles, casu_fits *conf, casu_mask *mask, casu_fits **skyout, casu_fits **skyvar, int niter, int ipix, float thresh, int nbsize, float smkern, int *status)
Work out a masked sky estimate from a jitter series with large offsets.
Definition: casu_sky.c:643
int casu_imcombine(casu_fits **fset, casu_fits **fsetv, int nfits, int combtype, int scaletype, int xrej, float thresh, const char *expkey, cpl_image **outimage, cpl_image **outvimage, unsigned char **rejmask, unsigned char **rejplus, cpl_propertylist **drs, int *status)
Stack images into a mean or median image with rejection.
int casu_pawsky_mask_pre(casu_fits **inlist, casu_fits **invar, int nfiles, casu_mask *mask, casu_fits *objmask, int nbsize, casu_fits **skyout, casu_fits **skyvar, int *status)
Work out a sky estimate from an input jitter series and a pre-existing object mask.
Definition: casu_sky.c:412
int casu_opm(casu_fits *infile, casu_fits *conf, int ipix, float threshold, int nbsize, float filtfwhm, int niter, int *status)
Generate an object mask from an input image.
Definition: casu_opm.c:90
int casu_inpaint(casu_fits *in, int nbsize, int *status)
Inpaint pixels or patches in a map.
Definition: casu_inpaint.c:83
int casu_pawsky_mask(casu_fits **inlist, casu_fits **invar, int nfiles, casu_fits *conf, casu_mask *mask, casu_fits **skyout, casu_fits **skyvar, int niter, int ipix, float thresh, int nbsize, float smkern, int *status)
Work out a masked sky estimate from an input jitter series.
Definition: casu_sky.c:110
float casu_med(float *data, unsigned char *bpm, long npts)
Definition: casu_stats.c:89
void casu_dummy_property(cpl_propertylist *p)
Set dummy property keyword.
Definition: casu_utils.c:445
cpl_image * casu_dummy_image(casu_fits *model)
Create a dummy image of zeros based on a model.
Definition: casu_utils.c:533
int casu_diffxywcs(cpl_wcs *wcs, cpl_wcs *wcsref, float *xoff, float *yoff, int *status)