VIRCAM Pipeline  1.3.3
vircam_sky.c
1 /* $Id: vircam_sky.c,v 1.10 2013-10-15 16:51:47 jim Exp $
2  *
3  * This file is part of the VIRCAM Pipeline
4  * Copyright (C) 2008 Cambridge Astronomy Survey Unit
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: 2013-10-15 16:51:47 $
24  * $Revision: 1.10 $
25  * $Name: not supported by cvs2svn $
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 "vircam_sky.h"
39 #include "vircam_mask.h"
40 #include "vircam_fits.h"
41 #include "vircam_mods.h"
42 #include "vircam_utils.h"
43 #include "vircam_stats.h"
44 #include "vircam_wcsutils.h"
45 #include "vircam_pfits.h"
46 
47 typedef struct {
48  vir_fits **in;
49  int n;
50  int nalloc;
51  int status;
52  vir_fits *xsky;
53 } xsky_struct;
54 
55 static void vircam_sky_mask_grow(cpl_image *dith, float rad);
56 static float vircam_sky_med(vir_fits *sky);
57 static void vircam_sky_joffs(vir_fits **inlist, int nfiles, float **xoffs,
58  float **yoffs);
59 static void vircam_sky_xytoxy(cpl_wcs *inwcs, cpl_wcs *outwcs,
60  cpl_matrix *inxy, cpl_matrix **outxy);
61 
64 /*---------------------------------------------------------------------------*/
109 /*---------------------------------------------------------------------------*/
110 
111 extern int vircam_pawsky_mask(vir_fits **inlist, int nfiles, vir_fits *conf,
112  vir_mask *mask, vir_fits **skyout, int niter,
113  int ipix, float thresh, int nbsize, float smkern,
114  int *status) {
115  int i,nx,ny,nbad0,lastone,iter,*confdata,npts,nbad_init,nbad,dbad;
116  int xx1,xx2,yy1,yy2;
117  const char *fctid = "vircam_pawsky_mask";
118  cpl_image *dith,*dithc,*skyim,*im,*newim,*outim;
119  cpl_mask *cplmask,*dithmask,*newmask,*curmask;
120  vir_fits **list_ss,*dithf,*dithcf;
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  if (*status != VIR_OK)
129  return(*status);
130 
131  /* If there aren't any images, then get out of here */
132 
133  if (nfiles == 0) {
134  cpl_msg_error(fctid,"Sky correction impossible. No science frames");
135  return(VIR_FATAL);
136  }
137 
138  /* Wrap the input mask into a cpl_mask structure and use it to set the
139  internal mask for each of the input images */
140 
141  inbpm = vircam_mask_get_data(mask);
142  nx = vircam_mask_get_size_x(mask);
143  ny = vircam_mask_get_size_y(mask);
144  cplmask = cpl_mask_wrap((cpl_size)nx,(cpl_size)ny,(cpl_binary *)inbpm);
145  for (i = 0; i < nfiles; i++)
146  cpl_image_reject_from_mask(vircam_fits_get_image(inlist[i]),cplmask);
147  cpl_mask_unwrap(cplmask);
148 
149  /* Do an initial sky combination */
150 
151  vircam_imcombine(inlist,nfiles,1,1,0,2.0,&outim,&rejmask,
152  &rejplus,&drs,status);
153  *skyout = vircam_fits_wrap(outim,inlist[0],NULL,NULL);
154  freespace(rejmask);
155  freespace(rejplus);
156  freepropertylist(drs);
157 
158  /* Clean up any blank bits */
159 
160  (void)vircam_inpaint(*skyout,nbsize,status);
161 
162  /* If this is the only iteration then get out of here now */
163 
164  if (niter == 0)
165  return(*status);
166 
167  /* Work out the median sky, ignoring the bad bits */
168 
169  medsky = vircam_sky_med(*skyout);
170 
171  /* Get jitter offsets from wcs */
172 
173  vircam_sky_joffs(inlist,nfiles,&xoffs,&yoffs);
174  mindx = xoffs[0];
175  mindy = yoffs[0];
176  for (i = 1; i < nfiles; i++) {
177  mindx = min(mindx,xoffs[i]);
178  mindy = min(mindy,yoffs[i]);
179  }
180 
181  /* Do an initial subtraction */
182 
183  list_ss = cpl_malloc(nfiles*sizeof(vir_fits *));
184  skyim = vircam_fits_get_image(*skyout);
185  for (i = 0; i < nfiles; i++) {
186  im = vircam_fits_get_image(inlist[i]);
187  newim = cpl_image_subtract_create(im,skyim);
188  cpl_image_add_scalar(newim,(double)medsky);
189  list_ss[i] = vircam_fits_wrap(newim,inlist[i],NULL,NULL);
190  }
191  vircam_fits_delete(*skyout);
192 
193  /* Set up some counters and begin the iteration loop */
194 
195  nbad0 = 0;
196  lastone = 0;
197  for (iter = 1; iter <= niter; iter++) {
198  if (lastone)
199  break;
200  lastone = (iter == niter);
201 
202  /* Dither the sky subtracted input images */
203 
204  (void)vircam_imdither(list_ss,&conf,nfiles,1,5.0,5.0,&p,&dith,
205  &dithc,status);
206  cpl_propertylist_delete(p);
207 
208  /* How many dead pixels are there in the dithered image? */
209 
210  confdata = cpl_image_get_data_int(dithc);
211  npts = (int)cpl_image_get_size_x(dithc)*(int)cpl_image_get_size_y(dithc);
212  nbad_init = 0;
213  for (i = 0; i < npts; i++)
214  if (confdata[i] == 0)
215  nbad_init++;
216 
217  /* Get rid of the sky subtracted images */
218 
219  for (i = 0; i < nfiles; i++)
220  vircam_fits_delete(list_ss[i]);
221 
222  /* Wrap the result */
223 
224  dithf = vircam_fits_wrap(dith,inlist[0],NULL,NULL);
225  dithcf = vircam_fits_wrap(dithc,conf,NULL,NULL);
226 
227  /* Now get an object mask from this dithered image */
228 
229  (void)vircam_opm(dithf,dithcf,ipix,thresh,nbsize,smkern,niter,status);
230 
231  /* How many flagged pixels are there, not counting the ones already
232  flagged in the confidence map */
233 
234  nbad = (int)cpl_image_count_rejected((const cpl_image *)dith) -
235  nbad_init;
236  dbad = nbad - nbad0;
237  fbad = (iter > 1 ? (float)abs(dbad)/(float)nbad0 : 10000.0);
238  cpl_msg_info(fctid,
239  "Iteration: %" CPL_SIZE_FORMAT ", Nreject: %" CPL_SIZE_FORMAT " %" CPL_SIZE_FORMAT,
240  (cpl_size)iter,(cpl_size)nbad,(cpl_size)nbad0);
241  if (fbad < 0.025 || dbad < 0) {
242  lastone = 1;
243  } else {
244  nbad0 = nbad;
245  }
246 
247  /* Allow the mask to grow before the next iteration */
248 
249  vircam_sky_mask_grow(dith,2);
250 
251  /* Right, now decide which part of the mask belongs to each of the
252  input images and update the input mask. */
253 
254  dithmask = cpl_image_get_bpm(dith);
255  for (i = 0; i < nfiles; i++) {
256  xx1 = (int)(-mindx + xoffs[i] + 1.5);
257  xx2 = xx1 + nx - 1;
258  yy1 = (int)(-mindy + yoffs[i] + 1.5);
259  yy2 = yy1 + ny - 1;
260  newmask = cpl_mask_extract(dithmask,(cpl_size)xx1,(cpl_size)yy1,
261  (cpl_size)xx2,(cpl_size)yy2);
262  curmask = cpl_image_get_bpm(vircam_fits_get_image(inlist[i]));
263  cpl_mask_or(curmask,newmask);
264  cpl_mask_delete(newmask);
265  }
266 
267  /* Delete the dither and its confidence map */
268 
269  vircam_fits_delete(dithf);
270  vircam_fits_delete(dithcf);
271 
272  /* Do a new sky combination using these new object masks */
273 
274  vircam_imcombine(inlist,nfiles,1,1,0,2.0,&outim,&rejmask,
275  &rejplus,&drs,status);
276  *skyout = vircam_fits_wrap(outim,inlist[0],NULL,NULL);
277  freespace(rejmask);
278  freespace(rejplus);
279  freepropertylist(drs);
280 
281  /* Clean up any blank bits */
282 
283  (void)vircam_inpaint(*skyout,nbsize,status);
284 
285  /* Do the sky subtraction again so long as this isn't
286  the last iteration */
287 
288  if (! lastone) {
289  skyim = vircam_fits_get_image(*skyout);
290  for (i = 0; i < nfiles; i++) {
291  im = vircam_fits_get_image(inlist[i]);
292  newim = cpl_image_subtract_create(im,skyim);
293  cpl_image_add_scalar(newim,(double)medsky);
294  list_ss[i] = vircam_fits_wrap(newim,inlist[i],NULL,NULL);
295  }
296  vircam_fits_delete(*skyout);
297  }
298  }
299 
300  /* Free up some workspace that we've collected along the way */
301 
302  freespace(xoffs);
303  freespace(yoffs);
304  freespace(list_ss);
305  return(*status);
306 }
307 
308 /*---------------------------------------------------------------------------*/
353 /*---------------------------------------------------------------------------*/
354 
355 extern int vircam_pawsky_mask_pre(vir_fits **inlist, int nfiles, vir_fits *conf,
356  vir_mask *mask, vir_fits *objmask,
357  int nbsize, vir_fits **skyout, int *status) {
358  const char *fctid = "vircam_pawsky_mask_pre";
359  unsigned char *inbpm,*rejplus,*rejmask;
360  int nx,ny,npts,ncoor,i,j,nx_objmask,ny_objmask,k,kk,ix,iy,ind,*opm;
361  cpl_mask *cplmask;
362  cpl_wcs *wcs_objmask,*wcs;
363  cpl_matrix *in_xy,*out_xy,*ddx,*ddx_out;
364  cpl_image *im,*outim;
365  cpl_propertylist *drs;
366  double *inxy_data,xx,yy,*ddx_data,shiftx,shifty;
367 
368  /* Inherited status */
369 
370  *skyout = NULL;
371  if (*status != VIR_OK)
372  return(*status);
373 
374  /* If there aren't any images, then get out of here */
375 
376  if (nfiles == 0) {
377  cpl_msg_error(fctid,"Sky correction impossible. No science frames");
378  return(VIR_FATAL);
379  }
380 
381  /* Wrap the input mask into a cpl_mask structure and use it to set the
382  internal mask for each of the input images */
383 
384  inbpm = vircam_mask_get_data(mask);
385  nx = vircam_mask_get_size_x(mask);
386  ny = vircam_mask_get_size_y(mask);
387  cplmask = cpl_mask_wrap((cpl_size)nx,(cpl_size)ny,(cpl_binary *)inbpm);
388  for (i = 0; i < nfiles; i++)
389  cpl_image_reject_from_mask(vircam_fits_get_image(inlist[i]),cplmask);
390  cpl_mask_unwrap(cplmask);
391 
392  /* Open the WCS of the object mask and get the pixel mask info */
393 
394  wcs_objmask = cpl_wcs_new_from_propertylist(vircam_fits_get_ehu(objmask));
395  opm = cpl_image_get_data(vircam_fits_get_image(objmask));
396  nx_objmask = cpl_image_get_size_x(vircam_fits_get_image(objmask));
397  ny_objmask = cpl_image_get_size_y(vircam_fits_get_image(objmask));
398 
399  /* Get some memory so that we can do a transformation between the coordinate
400  systems of the input frames and that of the object mask */
401 
402  npts = nx*ny;
403  ncoor = 2;
404  in_xy = cpl_matrix_new((cpl_size)npts,(cpl_size)ncoor);
405 
406  /* Initialise the data for the first x,y matrix */
407 
408  inxy_data = cpl_matrix_get_data(in_xy);
409  k = 0;
410  for (j = 0; j < ny; j++) {
411  for (i = 0; i < nx; i++) {
412  inxy_data[k++] = (double)(i+1);
413  inxy_data[k++] = (double)(j+1);
414  }
415  }
416 
417  /* Initialise data for an offset matrix */
418 
419  ddx = cpl_matrix_new(1,2);
420  ddx_data = cpl_matrix_get_data(ddx);
421  ddx_data[0] = 1.0;
422  ddx_data[1] = 1.0;
423 
424  /* Loop for each input file. Convert the xy matrix to an xy in the object
425  mask frame of reference for the first file. Then use the offsets between
426  the first image and the subsequent ones to define the location of
427  the object pixels in the following images */
428 
429  for (k = 0; k < nfiles; k++) {
430  wcs = cpl_wcs_new_from_propertylist(vircam_fits_get_ehu(inlist[k]));
431  im = vircam_fits_get_image(inlist[k]);
432  if (k == 0)
433  vircam_sky_xytoxy(wcs,wcs_objmask,in_xy,&out_xy);
434  vircam_sky_xytoxy(wcs,wcs_objmask,ddx,&ddx_out);
435  cpl_wcs_delete(wcs);
436  shiftx = cpl_matrix_get(out_xy,0,0) - cpl_matrix_get(ddx_out,0,0);
437  shifty = cpl_matrix_get(out_xy,0,1) - cpl_matrix_get(ddx_out,0,1);
438  kk = 0;
439  for (j = 0; j < ny; j++) {
440  for (i = 0; i < nx; i++) {
441  xx = cpl_matrix_get(out_xy,kk,0) - shiftx;
442  yy = cpl_matrix_get(out_xy,kk,1) - shifty;
443  kk++;
444  ix = vircam_nint(xx);
445  iy = vircam_nint(yy);
446  if (ix < 1 || ix > nx_objmask || iy < 1 || iy > ny_objmask)
447  continue;
448  ind = (iy-1)*nx_objmask + ix - 1;
449  if (opm[ind])
450  cpl_image_reject(im,i+1,j+1);
451  }
452  }
453  cpl_matrix_delete(ddx_out);
454  }
455  cpl_matrix_delete(in_xy);
456  cpl_matrix_delete(out_xy);
457  cpl_wcs_delete(wcs_objmask);
458 
459  /* Do an initial sky combination */
460 
461  vircam_imcombine(inlist,nfiles,1,1,0,2.0,&outim,&rejmask,
462  &rejplus,&drs,status);
463  *skyout = vircam_fits_wrap(outim,inlist[0],NULL,NULL);
464  freespace(rejmask);
465  freespace(rejplus);
466  freepropertylist(drs);
467 
468  /* Clean up any blank bits */
469 
470  (void)vircam_inpaint(*skyout,nbsize,status);
471 
472  /* Get out of here */
473 
474  return(*status);
475 }
476 
477 /*---------------------------------------------------------------------------*/
510 /*---------------------------------------------------------------------------*/
511 
512 extern int vircam_tilesky(vir_fits **inlist, int nfiles, vir_mask *mask,
513  vir_fits **skyout, int *status) {
514  int i,njit,nx,ny,ji,ns,npts;
515  unsigned char *inbpm,*rejmask,*rejplus;
516  cpl_mask *cplmask;
517  xsky_struct *xskys;
518  cpl_propertylist *drs;
519  cpl_image *outim;
520  vir_fits **xsky_fits;
521  const char *fctid = "vircam_tilesky";
522 
523  /* Inherited status */
524 
525  *skyout = NULL;
526  if (*status != VIR_OK)
527  return(*status);
528 
529  /* If there aren't any images, then get out of here */
530 
531  if (nfiles == 0) {
532  cpl_msg_error(fctid,"Sky correction impossible. No science frames");
533  return(VIR_FATAL);
534  }
535 
536  /* Wrap the input mask into a cpl_mask structure and use it to set the
537  internal mask for each of the input images */
538 
539  inbpm = vircam_mask_get_data(mask);
540  nx = vircam_mask_get_size_x(mask);
541  ny = vircam_mask_get_size_y(mask);
542  npts = nx*ny;
543  cplmask = cpl_mask_wrap((cpl_size)nx,(cpl_size)ny,(cpl_binary *)inbpm);
544  for (i = 0; i < nfiles; i++)
545  cpl_image_reject_from_mask(vircam_fits_get_image(inlist[i]),cplmask);
546  cpl_mask_unwrap(cplmask);
547 
548  /* For each file, do a quickie background analysis and reject high
549  pixels */
550 
551  /* test = cpl_malloc(nx*ny*sizeof(float)); */
552  /* for (i = 0; i < nfiles; i++) { */
553  /* vircam_backmap(inlist[i],mask,64,&outim,&skymed); */
554  /* odata = cpl_image_get_data_float(outim); */
555  /* idata = cpl_image_get_data_float(vircam_fits_get_image(inlist[i])); */
556  /* for (j = 0; j < npts; j++) */
557  /* test[j] = idata[j] - odata[j]; */
558  /* vircam_qmedsig(test,inbpm,(long)npts,3.0,2,-65535.0,65535.0,&skymed, */
559  /* &skysig); */
560  /* immask = cpl_mask_get_data(cpl_image_get_bpm(vircam_fits_get_image(inlist[i]))); */
561  /* for (j = 0; j < npts; j++) */
562  /* if (test[j] > (skymed + 1.5*skysig)) */
563  /* immask[j] = 1; */
564  /* cpl_image_delete(outim); */
565  /* } */
566  /* freespace(test); */
567 
568  /* How many jitter steps are there? */
569 
570  (void)vircam_pfits_get_njsteps(vircam_fits_get_phu(inlist[0]),&njit);
571 
572  /* Allocate some workspce */
573 
574  xskys = cpl_malloc(njit*sizeof(xsky_struct));
575  for (i = 0; i < njit; i++) {
576  xskys[i].n = 0;
577  xskys[i].in = cpl_malloc(8*sizeof(vir_fits *));
578  xskys[i].nalloc = 8;
579  xskys[i].xsky = NULL;
580  xskys[i].status = VIR_OK;
581  }
582  xsky_fits = cpl_malloc(njit*sizeof(vir_fits *));
583 
584  /* Now loop through all the files and put them into the relevant
585  structure depending upon where they are in the jitter pattern.
586  NB: We don't have to check on the status of the individual
587  frames because only good frames should have been passed in by
588  the calling routine. */
589 
590  for (i = 0; i < nfiles; i++) {
591  (void)vircam_pfits_get_jitteri(vircam_fits_get_phu(inlist[i]),&ji);
592  ji--;
593  if (xskys[ji].n == xskys[ji].nalloc) {
594  xskys[ji].in = cpl_realloc(xskys[ji].in,
595  (xskys[ji].nalloc+8)*sizeof(vir_fits *));
596  xskys[ji].nalloc += 8;
597  }
598  xskys[ji].in[xskys[ji].n] = inlist[i];
599  xskys[ji].n += 1;
600  }
601 
602  /* Now loop through each of these groups and form a sky file with
603  rejection */
604 
605  ns = 0;
606  for (i = 0; i < njit; i++) {
607  *status = VIR_OK;
608  if (xskys[i].n == 0) {
609  xskys[i].xsky = NULL;
610  continue;
611  } else if (xskys[i].n == 1) {
612  xskys[i].xsky = NULL;
613  xsky_fits[ns++] = xskys[i].in[0];
614  continue;
615  }
616  outim = NULL;
617  (void)vircam_imcombine(xskys[i].in,xskys[i].n,1,1,0,1.0,&outim,&rejmask,
618  &rejplus,&drs,status);
619  freespace(rejmask);
620  freespace(rejplus);
621  freepropertylist(drs);
622  if (*status == VIR_OK) {
623  xskys[i].xsky = vircam_fits_wrap(outim,xskys[i].in[0],NULL,NULL);
624  xsky_fits[ns++] = xskys[i].xsky;
625  } else {
626  freeimage(outim);
627  }
628  }
629 
630  /* Now combine all the intermediate skies to form the final sky */
631 
632  if (ns != 0) {
633  outim = NULL;
634  (void)vircam_imcombine(xsky_fits,ns,1,1,0,1.0,&outim,&rejmask,&rejplus,
635  &drs,status);
636  freespace(rejmask);
637  freespace(rejplus);
638  freepropertylist(drs);
639  if (*status == VIR_OK) {
640  *skyout = vircam_fits_wrap(outim,inlist[0],NULL,NULL);
641  (void)vircam_inpaint(*skyout,64,status);
642  } else {
643  freeimage(outim);
644  *skyout = NULL;
645  }
646  } else {
647  *skyout = NULL;
648  }
649 
650  /* Tidy and exit */
651 
652  freespace(xsky_fits);
653  for (i = 0; i < njit; i++) {
654  freespace(xskys[i].in);
655  freefits(xskys[i].xsky);
656  }
657  freespace(xskys);
658  return(*status);
659 }
660 
661 
662 /*---------------------------------------------------------------------------*/
680 /*---------------------------------------------------------------------------*/
681 
682 static void vircam_sky_mask_grow(cpl_image *dith, float rad) {
683  cpl_binary *inmap,*outmap;
684  int nx,ny,ir,i,j,indx,ixmin,ixmax,iymin,iymax,ii,jj,indx2;
685  float dx,dy,radius;
686 
687  /* Get the input map */
688 
689  inmap = cpl_mask_get_data(cpl_image_get_bpm(dith));
690  nx = (int)cpl_image_get_size_x(dith);
691  ny = (int)cpl_image_get_size_y(dith);
692 
693  /* Get an output map of the same size. Copy the input map to it */
694 
695  outmap = cpl_malloc(nx*ny*sizeof(*outmap));
696  memmove(outmap,inmap,nx*ny*sizeof(*inmap));
697 
698  /* What is the minimum cell size that we need to consider given the
699  input radius */
700 
701  ir = vircam_nint(rad);
702 
703  /* Right, loop through the input image. If the current input pixel is
704  not flagged, then move on to the next one. If it is, then look at
705  a cell around it. Find all the pixels in that cell that are within
706  the grow radius and flag them */
707 
708  for (j = 0; j < ny; j++) {
709  for (i = 0; i < nx; i++) {
710  indx = j*nx + i;
711  if (! inmap[indx])
712  continue;
713  ixmin = max(0,i-ir);
714  ixmax = min(nx-1,i+ir);
715  iymin = max(0,j-ir);
716  iymax = min(ny-1,j+ir);
717  for (jj = iymin; jj <= iymax; jj++) {
718  dy = (float)(jj - j);
719  for (ii = ixmin; ii <= ixmax; ii++) {
720  dx = (float)(ii - i);
721  radius = (float)sqrt(pow(dx,2.0) + pow(dy,2.0));
722  if (radius <= rad) {
723  indx2 = jj*nx + ii;
724  outmap[indx2] = 1;
725  }
726  }
727  }
728  }
729  }
730 
731  /* Now move the result back into the input mask. Free up workspace
732  and get out of here */
733 
734  memmove(inmap,outmap,nx*ny*sizeof(*inmap));
735  cpl_free(outmap);
736 }
737 
738 /*---------------------------------------------------------------------------*/
756 /*---------------------------------------------------------------------------*/
757 
758 static float vircam_sky_med(vir_fits *sky) {
759  int npts;
760  float *data,med;
761  unsigned char *bpm;
762  cpl_image *skyim;
763 
764  /* Get the size of the data array */
765 
766  skyim = vircam_fits_get_image(sky);
767  npts = (int)cpl_image_get_size_x(skyim)*(int)cpl_image_get_size_y(skyim);
768 
769  /* Get the data */
770 
771  data = cpl_image_get_data_float(skyim);
772  bpm = (unsigned char *)cpl_mask_get_data(cpl_image_get_bpm(skyim));
773 
774  /* Get the median */
775 
776  med = vircam_med(data,bpm,(long)npts);
777  return(med);
778 }
779 
780 
781 /*---------------------------------------------------------------------------*/
803 /*---------------------------------------------------------------------------*/
804 
805 static void vircam_sky_joffs(vir_fits **inlist, int nfiles, float **xoffs,
806  float **yoffs) {
807  float xoff,yoff;
808  cpl_wcs *wcsref,*wcs;
809  int refset,i,status;
810  const double maxoffset = 2048;
811  vir_fits *ff;
812  const char *fctid = "vircam_sky_joffs";
813 
814  /* Get a bit of workspace to hold the offsets */
815 
816  *xoffs = cpl_malloc(nfiles*sizeof(float));
817  *yoffs = cpl_malloc(nfiles*sizeof(float));
818 
819  /* Work out the jitter offsets from the WCS. First loop for each image */
820 
821  refset = 0;
822  wcsref = NULL;
823  for (i = 0; i < nfiles; i++) {
824  ff = inlist[i];
825  wcs = cpl_wcs_new_from_propertylist(vircam_fits_get_ehu(ff));
826 
827  /* If we can't get a WCS for this image, then signal that with
828  a warning */
829 
830  if (wcs == NULL) {
831  cpl_msg_warning(fctid,"Unable to get WCS for %s",
833  (*xoffs)[i] = 0.0;
834  (*yoffs)[i] = 0.0;
835  vircam_fits_set_error(ff,VIR_WARN);
836  continue;
837  }
838 
839  /* Define the reference wcs pointer and set the first offset to zero */
840 
841  if (! refset) {
842  (*xoffs)[0] = 0.0;
843  (*yoffs)[0] = 0.0;
844  refset = 1;
845  wcsref = wcs;
846  continue;
847  }
848 
849  /* Work out the x,y offset */
850 
851  status = VIR_OK;
852  (void)vircam_diffxywcs(wcs,wcsref,&xoff,&yoff,&status);
853 
854  /* Did it work? If not the set a warning status for this file */
855 
856  if (status != VIR_OK) {
857  (*xoffs)[i] = 0.0;
858  (*yoffs)[i] = 0.0;
859  cpl_msg_warning(fctid,"Unable to WCS difference for %s",
861  } else if (fabs((double)xoff) > maxoffset ||
862  fabs((double)yoff) > maxoffset) {
863  vircam_fits_set_error(ff,VIR_FATAL);
864  cpl_msg_error(fctid,"WCS offsets for %s are >%g: %g %g -- ignoring",
865  vircam_fits_get_filename(ff),maxoffset,xoff,yoff);
866  } else {
867  (*xoffs)[i] = xoff;
868  (*yoffs)[i] = yoff;
869  }
870  cpl_wcs_delete(wcs);
871  }
872  if (wcsref != NULL)
873  cpl_wcs_delete(wcsref);
874 
875  /* Write the results to the headers */
876 
877  for (i = 0; i < nfiles; i++) {
878  ff = inlist[i];
879  cpl_propertylist_update_double(vircam_fits_get_ehu(ff),
880  "ESO DRS XOFFDITHER",
881  (double)(*xoffs)[i]);
882  cpl_propertylist_update_double(vircam_fits_get_ehu(ff),
883  "ESO DRS YOFFDITHER",
884  (double)(*yoffs)[i]);
885  }
886 }
887 
888 static void vircam_sky_xytoxy(cpl_wcs *inwcs, cpl_wcs *outwcs,
889  cpl_matrix *inxy, cpl_matrix **outxy) {
890  cpl_matrix *radec;
891  cpl_array *wstatus;
892 
893  /* Convert the input xy data to RA/Dec */
894 
895  cpl_wcs_convert(inwcs,inxy,&radec,&wstatus,CPL_WCS_PHYS2WORLD);
896  cpl_array_delete(wstatus);
897 
898  /* Now convert the RA/Dec to the xy coordinates of the second image */
899 
900  cpl_wcs_convert(outwcs,radec,outxy,&wstatus,CPL_WCS_WORLD2PHYS);
901  cpl_array_delete(wstatus);
902  cpl_matrix_delete(radec);
903 }
904 
907 /*
908 
909 $Log: not supported by cvs2svn $
910 Revision 1.9 2012/01/27 12:25:10 jim
911 Fixed some casts
912 
913 Revision 1.8 2012/01/15 17:40:09 jim
914 Minor modifications to take into accout the changes in cpl API for v6
915 
916 Revision 1.7 2010/06/30 12:42:00 jim
917 A few fixes to stop compiler compaints
918 
919 Revision 1.6 2009/02/23 10:46:26 jim
920 Modified tilesky to try and get rid of some of the low level glow around
921 bright and extended objects
922 
923 Revision 1.5 2009/02/20 11:01:13 jim
924 Added vircam_tilesky. Commented out vircam_skycombine as it's not being
925 used at present and it's generating a compiler error. May delete it
926 completely later
927 
928 Revision 1.4 2008/11/25 06:23:09 jim
929 Added some routine prologues
930 
931 Revision 1.3 2008/11/21 10:12:36 jim
932 Fixed typo
933 
934 Revision 1.2 2008/10/24 10:57:19 jim
935 Fixed bug in pawsky_mask so that the bad pixels in the confidence map are
936 folded into the object mask
937 
938 Revision 1.1 2008/10/13 08:13:21 jim
939 New entry
940 
941 */