VIRCAM Pipeline  1.3.3
vircam_tilesky_minus.c
1 /* $Id: vircam_tilesky_minus.c,v 1.1 2013-10-15 16:30:07 jim Exp $
2  *
3  * This file is part of the VIRCAM Pipeline
4  * Copyright (C) 2013 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:30:07 $
24  * $Revision: 1.1 $
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_dfs.h"
46 #include "vircam_pfits.h"
47 
48 typedef struct {
49  int pawposition;
50  int nimages;
51  vir_fits **infiles;
52  float **datas;
53  unsigned char **masks;
54  float *master_xsky;
55  unsigned char *master_xsky_bpm;
56  float **xsky_variant;
57  unsigned char **xsky_variant_bpm;
58  float *zeros;
59  float *dx;
60  float *dy;
61 } jpos;
62 static void combine_master(int nfiles, int stat, int npts, float **datas,
63  unsigned char **masks, float **skyout,
64  unsigned char **skyout_bpm);
65 static void combine_variant(int stat, int npts, jpos *jp, int skipme);
66 static void combine_final(int nxskys, int stat, int npts, float **xskys,
67  unsigned char **xsky_masks, float *data,
68  float *master_sky, unsigned char *master_bpm);
69 static void masksky_zeros(jpos *jp, int njit, int npts);
70 static void domed(float *buf, int n, float *val);
71 static jpos *jpos_init(int njit);
72 static void jpos_alloc(vir_fits **infiles, int nfiles, int pawpos, jpos *jp);
73 static void jpos_free(jpos *jp, int njit);
74 
75 /********************/
76 
77 /* extern int vircam_tilesky_minus(vir_fits **infiles, vir_fits *conf, */
78 /* vir_fits *mask, int nfiles, int nconfs, */
79 /* vir_fits **skyout, int *status); */
80 /* int main () { */
81 /* char *infiles[54] = { */
82 /* "v20120819_00534.fit", */
83 /* "v20120819_00535.fit", */
84 /* "v20120819_00536.fit", */
85 /* "v20120819_00537.fit", */
86 /* "v20120819_00538.fit", */
87 /* "v20120819_00539.fit", */
88 /* "v20120819_00540.fit", */
89 /* "v20120819_00541.fit", */
90 /* "v20120819_00542.fit", */
91 /* "v20120819_00543.fit", */
92 /* "v20120819_00544.fit", */
93 /* "v20120819_00545.fit", */
94 /* "v20120819_00546.fit", */
95 /* "v20120819_00547.fit", */
96 /* "v20120819_00548.fit", */
97 /* "v20120819_00549.fit", */
98 /* "v20120819_00550.fit", */
99 /* "v20120819_00551.fit", */
100 /* "v20120819_00552.fit", */
101 /* "v20120819_00553.fit", */
102 /* "v20120819_00554.fit", */
103 /* "v20120819_00555.fit", */
104 /* "v20120819_00556.fit", */
105 /* "v20120819_00557.fit", */
106 /* "v20120819_00558.fit", */
107 /* "v20120819_00559.fit", */
108 /* "v20120819_00560.fit", */
109 /* "v20120819_00561.fit", */
110 /* "v20120819_00562.fit", */
111 /* "v20120819_00563.fit", */
112 /* "v20120819_00564.fit", */
113 /* "v20120819_00565.fit", */
114 /* "v20120819_00566.fit", */
115 /* "v20120819_00567.fit", */
116 /* "v20120819_00568.fit", */
117 /* "v20120819_00569.fit", */
118 /* "v20120819_00570.fit", */
119 /* "v20120819_00571.fit", */
120 /* "v20120819_00572.fit", */
121 /* "v20120819_00573.fit", */
122 /* "v20120819_00574.fit", */
123 /* "v20120819_00575.fit", */
124 /* "v20120819_00576.fit", */
125 /* "v20120819_00577.fit", */
126 /* "v20120819_00578.fit", */
127 /* "v20120819_00579.fit", */
128 /* "v20120819_00580.fit", */
129 /* "v20120819_00581.fit", */
130 /* "v20120819_00582.fit", */
131 /* "v20120819_00583.fit", */
132 /* "v20120819_00584.fit", */
133 /* "v20120819_00585.fit", */
134 /* "v20120819_00586.fit", */
135 /* "v20120819_00587.fit"}; */
136 /* char *conf = "Z_conf.fit",fname[BUFSIZ]; */
137 /* char *maskfits = "es1.fit"; */
138 /* vir_fits **infits,*inconf,*skyout,*inmask; */
139 /* int nfiles=54,nconfs=1,status,i,j,retval; */
140 /* cpl_init(CPL_INIT_DEFAULT); */
141 /* cpl_frameset *infrmset; */
142 /* cpl_frame *conffrm,*frm,*maskfrm; */
143 
144 /* status = VIR_OK; */
145 
146 /* /\* Load up the input images into a framelist *\/ */
147 
148 /* infrmset = cpl_frameset_new(); */
149 /* for (i = 0; i < 54; i++) { */
150 /* frm = cpl_frame_new(); */
151 /* cpl_frame_set_filename(frm,infiles[i]); */
152 /* cpl_frame_set_tag(frm,VIRCAM_SCI_OBJECT_RAW); */
153 /* cpl_frameset_insert(infrmset,frm); */
154 /* } */
155 /* conffrm = cpl_frame_new(); */
156 /* cpl_frame_set_filename(conffrm,conf); */
157 /* maskfrm = cpl_frame_new(); */
158 /* cpl_frame_set_filename(maskfrm,maskfits); */
159 /* /\* inmask = vircam_fits_load(maskfrm,CPL_TYPE_INT,1); *\/ */
160 /* inmask = NULL; */
161 /* for (i = 1; i <= 1; i++) { */
162 /* fprintf(stderr,"Doing extn %d\n",i); */
163 /* infits = vircam_fits_load_list(infrmset,CPL_TYPE_FLOAT,i); */
164 /* inconf = vircam_fits_load(conffrm,CPL_TYPE_INT,i); */
165 /* retval = vircam_tilesky_minus(infits,inconf,inmask,54,1,&skyout, */
166 /* &status); */
167 /* for (j = 0; j < 54; j++) { */
168 /* (void)sprintf(fname,"new_%s",infiles[j]); */
169 /* if (i == 1) */
170 /* cpl_image_save(NULL,fname,CPL_TYPE_UCHAR, */
171 /* vircam_fits_get_phu(infits[j]),CPL_IO_DEFAULT); */
172 /* cpl_image_save(vircam_fits_get_image(infits[j]),fname, */
173 /* CPL_TYPE_FLOAT, */
174 /* vircam_fits_get_ehu(infits[j]), */
175 /* CPL_IO_EXTEND); */
176 /* } */
177 /* if (i == 1) */
178 /* cpl_image_save(NULL,"testsky.fit",CPL_TYPE_UCHAR, */
179 /* vircam_fits_get_phu(skyout),CPL_IO_DEFAULT); */
180 /* cpl_image_save(vircam_fits_get_image(skyout),"testsky.fit", */
181 /* CPL_TYPE_FLOAT, */
182 /* vircam_fits_get_ehu(skyout), */
183 /* CPL_IO_EXTEND); */
184 /* freefitslist(infits,54); */
185 /* freefits(inconf); */
186 /* freefits(skyout); */
187 /* } */
188 /* cpl_frameset_delete(infrmset); */
189 /* cpl_frame_delete(conffrm); */
190 /* freefits(inmask); */
191 /* cpl_end(); */
192 /* } */
193 
194 
195 /**********************/
196 extern int vircam_tilesky_minus(vir_fits **infiles, vir_fits *conf,
197  vir_fits *objmaskfits, int nfiles, int nconfs,
198  vir_fits **skyout, int *status) {
199  int i,nx_mask,ny_mask,ind,j,nx,ny,kind,njit,*confdata,jx,jy,ix,iy,k;
200  int npts,*opm;
201  jpos *jp=NULL;
202  cpl_wcs *wcsmask,*wcsimg;
203  cpl_image *im,*skyim;
204  cpl_propertylist *plist;
205  unsigned char **xsky_masks,*master_sky_lev2_bpm;
206  double *xin,*yin,*xout,*yout,*dx,*dy,ddx,ddy;
207  float **xskys,*master_sky_lev2,val,sig;
208  const char *fctid = "vircam_tilesky_minus";
209 
210  /* Inherited status */
211 
212  *skyout = NULL;
213  if (*status != VIR_OK)
214  return(*status);
215 
216  /* If there aren't any images, then get out of here */
217 
218  if (nfiles == 0) {
219  cpl_msg_error(fctid,"Sky correction impossible. No science frames");
220  return(VIR_FATAL);
221  }
222 
223  /* Initialise the jpos structure. There is one for each jitter position.
224  Each jitter position has a maximum number of observations which is
225  the number of jitter sequences. This is nominally 6, but will
226  sometimes be 3 if we are observing in stripes or something else
227  if the tile is incomplete. */
228 
229  (void)vircam_pfits_get_njsteps(vircam_fits_get_phu(infiles[0]),&njit);
230  jp = jpos_init(njit);
231  for (i = 1; i <= njit; i++)
232  jpos_alloc(infiles,nfiles,i,jp+i-1);
233  nx = cpl_image_get_size_x(vircam_fits_get_image(infiles[0]));
234  ny = cpl_image_get_size_y(vircam_fits_get_image(infiles[0]));
235  npts = nx*ny;
236 
237  /* Get the wcs descriptor for the mask (if it exists) */
238 
239  if (objmaskfits != NULL) {
240  nx_mask = cpl_image_get_size_x(vircam_fits_get_image(objmaskfits));
241  ny_mask = cpl_image_get_size_y(vircam_fits_get_image(objmaskfits));
242  wcsmask = cpl_wcs_new_from_propertylist(vircam_fits_get_ehu(objmaskfits));
243  opm = cpl_image_get_data_int(vircam_fits_get_image(objmaskfits));
244 
245  /* We need this space so that we can work out which part of the
246  input mask is relevant for each input image */
247 
248  xin = cpl_malloc(npts*sizeof(double));
249  yin = cpl_malloc(npts*sizeof(double));
250  xout = cpl_malloc(npts*sizeof(double));
251  yout = cpl_malloc(npts*sizeof(double));
252  dx = cpl_malloc(nfiles*sizeof(double));
253  dy = cpl_malloc(nfiles*sizeof(double));
254 
255  /* Initialise the input xy arrays */
256 
257  ind = 0;
258  for (j = 0; j < ny; j++) {
259  for (i = 0; i < nx; i++) {
260  xin[ind] = (double)(i+1);
261  yin[ind++] = (double)(j+1);
262  }
263  }
264 
265  /* Define an output grid for the first image and then offsets for
266  the subsequent images */
267 
268  ddx = 1.0;
269  ddy = 1.0;
270  for (i = 0; i < nfiles; i++) {
271  wcsimg = cpl_wcs_new_from_propertylist(vircam_fits_get_ehu(infiles[i]));
272  if (i == 0)
273  vircam_xytoxy_list(wcsimg,wcsmask,npts,xin,yin,xout,yout);
274  vircam_xytoxy_list(wcsimg,wcsmask,1,&ddx,&ddy,dx+i,dy+i);
275  dx[i] -= xout[0];
276  dy[i] -= yout[0];
277  cpl_wcs_delete(wcsimg);
278  }
279  cpl_wcs_delete(wcsmask);
280  }
281 
282  /* Loop for each file and get a reference for the data array. Get
283  some space for a mask that will cover both the zeroed pixels in the
284  confidence maps and any object mask that might be used */
285 
286  for (j = 0; j < njit; j++) {
287  for (i = 0; i < jp[j].nimages; i++) {
288  im = vircam_fits_get_image(jp[j].infiles[i]);
289  jp[j].datas[i] = cpl_image_get_data_float(im);
290  jp[j].masks[i] = cpl_calloc(npts,sizeof(unsigned char));
291  if (i == 0 && j == 0)
292  confdata = cpl_image_get_data_int(vircam_fits_get_image(conf));
293 
294  /* Now loop for each pixel. If the confidence map is zero here then
295  mark this as a bad pixel. If not, then look at the master mask
296  and see which is its closest pixel to the current one. NB: the
297  -0.5 in the index is a combination of +0.5 to do a nint and a -1
298  to take account of the fact that arrays start from index zero. */
299 
300  for (jy = 0; jy < ny; jy++) {
301  for (jx = 0; jx < nx; jx++) {
302  ind = jy*nx + jx;
303  if (confdata[ind] == 0) {
304  jp[j].masks[i][ind] = 1;
305  } else if (objmaskfits != NULL) {
306  kind = (int)(yout[ind] + dy[i] - 0.5)*nx_mask +
307  (int)(xout[ind] + dx[i] - 0.5);
308  jp[j].masks[i][ind] = opm[kind];
309  }
310  }
311  }
312  }
313  }
314 
315  /* Do an intermediate tidy */
316 
317  if (objmaskfits != NULL) {
318  freespace(xin);
319  freespace(yin);
320  freespace(xout);
321  freespace(yout);
322  freespace(dx);
323  freespace(dy);
324  }
325 
326  /* Offset the DC level for all images together */
327 
328  masksky_zeros(jp,njit,npts);
329 
330  /* Now loop through all the positions again and form the xskys and
331  all their variants. The 'master' is an xsky that is formed from
332  all the images. The variant xskys are formed from all but one
333  of the input images (removing one image from the list each time). */
334 
335  for (i = 0; i < njit; i++) {
336 
337  /* Form the master xsky for this position */
338 
339  combine_master(jp[i].nimages,0,npts,jp[i].datas,jp[i].masks,
340  &(jp[i].master_xsky),&(jp[i].master_xsky_bpm));
341 
342  /* Form the variant xskys for this position */
343 
344  for (j = 0; j < jp[i].nimages; j++)
345  combine_variant(0,npts,jp+i,j);
346  }
347 
348  /* Form master level 2 sky */
349 
350  xskys = cpl_malloc(njit*sizeof(float *));
351  xsky_masks = cpl_malloc(njit*sizeof(unsigned char *));
352  for (i = 0; i < njit; i++) {
353  xskys[i] = jp[i].master_xsky;
354  xsky_masks[i] = jp[i].master_xsky_bpm;
355  }
356  combine_master(njit,0,npts,xskys,xsky_masks,&master_sky_lev2,
357  &master_sky_lev2_bpm);
358 
359  /* Wrap the sky and reject the pixels that had no sky contribution */
360 
361  skyim = cpl_image_wrap_float(nx,ny,master_sky_lev2);
362  for (i = 0; i < npts; i++) {
363  iy = i/nx + 1;
364  ix = i - (iy-1)*nx + 1;
365  if (master_sky_lev2_bpm[i])
366  cpl_image_reject(skyim,(cpl_size)ix,(cpl_size)iy);
367  }
368  *skyout = vircam_fits_wrap(skyim,infiles[0],NULL,NULL);
369  plist = vircam_fits_get_ehu(*skyout);
370  if (objmaskfits != NULL) {
371  cpl_propertylist_update_string(plist,"ESO DRS MASKUSED",
372  vircam_fits_get_filename(objmaskfits));
373  cpl_propertylist_set_comment(plist,"ESO DRS MASKUSED",
374  "Object masked used to make sky");
375  }
376  cpl_propertylist_update_string(plist,"ESO DRS SKYALGO","tilesky_minus");
377  cpl_propertylist_set_comment(plist,"ESO DRS SKYALGO",
378  "Sky estimation algorithm");
379  vircam_prov(plist,infiles,nfiles);
380 
381  /* Fill in the bits with no sky contribution */
382 
383  vircam_inpaint(*skyout,64,status);
384 
385  /* OK, now loop through each of the jitter positions again and
386  form the variant level 2 sky and subtract it off the data frames */
387 
388  for (j = 0; j < njit; j++) {
389  for (i = 0; i < njit; i++) {
390  xskys[i] = jp[i].master_xsky;
391  xsky_masks[i] = jp[i].master_xsky_bpm;
392  }
393  for (i = 0; i < jp[j].nimages; i++) {
394  xskys[j] = jp[j].xsky_variant[i];
395  xsky_masks[j] = jp[j].xsky_variant_bpm[i];
396  combine_final(njit,0,npts,xskys,xsky_masks,jp[j].datas[i],
397  master_sky_lev2,master_sky_lev2_bpm);
398 
399  /* Readjust the DC to be what it was before sky subtraction */
400 
401  vircam_qmedsig(jp[j].datas[i],jp[j].masks[i],(long)npts,3.0,1,
402  -1000.0,65535.0,&val,&sig);
403  val = jp[j].zeros[i] - val;
404  for (k = 0; k < npts; k++)
405  jp[j].datas[i][k] += val;
406  }
407  }
408 
409  /* Tidy up */
410 
411  freespace(xskys);
412  freespace(xsky_masks);
413  freespace(master_sky_lev2_bpm);
414  jpos_free(jp,njit);
415  return(VIR_OK);
416 }
417 
418 static void combine_master(int nfiles, int stat, int npts, float **datas,
419  unsigned char **masks, float **skyout,
420  unsigned char **skyout_bpm) {
421  int i,j,n;
422  float *buf;
423 
424  /* Get workspace for output arrays */
425 
426  *skyout = cpl_malloc(npts*sizeof(float));
427  *skyout_bpm = cpl_malloc(npts*sizeof(unsigned char));
428  buf = cpl_malloc(nfiles*sizeof(float));
429 
430  /* Loop now for each input pixel and form the median */
431 
432  for (j = 0; j < npts; j++) {
433  n = 0;
434  for (i = 0; i < nfiles; i++) {
435  if (masks[i][j] == 0)
436  buf[n++] = datas[i][j];
437  }
438  if (n == 0) {
439  (*skyout)[j] = 0.0;
440  (*skyout_bpm)[j] = 1;
441  } else {
442  if (stat == 0)
443  domed(buf,n,(*skyout)+j);
444  else
445  (*skyout)[j] = vircam_mean(buf,NULL,n);
446  (*skyout_bpm)[j] = 0;
447  }
448  }
449 
450  /* Free some workspace and get out of here */
451 
452  freespace(buf);
453  return;
454 }
455 
456 static void combine_variant(int stat, int npts, jpos *jp, int skipme) {
457  int i,j,n,nfiles;
458  float *buf,**datas,*skyout,*master_sky;
459  unsigned char **masks,*skyout_bpm,*master_sky_bpm;
460 
461  /* Create some shortcuts */
462 
463  datas = jp->datas;
464  masks = jp->masks;
465  master_sky = jp->master_xsky;
466  master_sky_bpm = jp->master_xsky_bpm;
467  nfiles = jp->nimages;
468 
469  /* Get workspace for output arrays */
470 
471  skyout = cpl_malloc(npts*sizeof(float));
472  jp->xsky_variant[skipme] = skyout;
473  skyout_bpm = cpl_malloc(npts*sizeof(unsigned char));
474  jp->xsky_variant_bpm[skipme] = skyout_bpm;
475  buf = cpl_malloc(nfiles*sizeof(float));
476 
477  /* If there is only one file in this group then just replace the
478  variant with the master and get out of here */
479 
480  if (nfiles == 1) {
481  memmove(skyout,jp->master_xsky,npts*sizeof(float));
482  memmove(skyout_bpm,jp->master_xsky_bpm,npts*sizeof(unsigned char));
483  freespace(buf);
484  return;
485  }
486 
487  /* Loop now for each input pixel and form the median */
488 
489  for (j = 0; j < npts; j++) {
490  n = 0;
491 
492  /* If the current pixel was masked out in the skipped image, then
493  there isn't any point in recalculating the mean value again */
494 
495  if (masks[skipme][j]) {
496  skyout[j] = master_sky[j];
497  skyout_bpm[j] = master_sky_bpm[j];
498  continue;
499  }
500 
501  /* Recalculate */
502 
503  for (i = 0; i < nfiles; i++) {
504  if (masks[i][j] == 0 && i != skipme)
505  buf[n++] = datas[i][j];
506  }
507  if (n == 0) {
508  skyout[j] = 0.0;
509  skyout_bpm[j] = 1;
510  } else {
511  if (stat == 0)
512  domed(buf,n,skyout+j);
513  else
514  skyout[j] = vircam_mean(buf,NULL,n);
515  skyout_bpm[j] = 0;
516  }
517  }
518 
519  /* Free some workspace and get out of here */
520 
521  freespace(buf);
522  return;
523 }
524 
525 static void combine_final(int nxskys, int stat, int npts, float **xskys,
526  unsigned char **xsky_masks, float *data,
527  float *master_sky, unsigned char *master_bpm) {
528  int i,j,n;
529  float *buf,val;
530 
531  /* Get some memory */
532 
533  buf = cpl_malloc(nxskys*sizeof(float));
534 
535  /* Loop now for each input pixel */
536 
537  for (j = 0; j < npts; j++) {
538 
539  /* If the master bpm is flagged, then this is an interpolated point
540  and there's no reason to recalculate */
541 
542  if (master_bpm[j]) {
543  val = master_sky[j];
544  } else {
545 
546  /* Loop for each file. If the current pixel in the current file
547  was flagged, then the sky for that pixel will be the same as
548  the general sky we did before. If not, then remove that file's
549  pixel and recalculate the sky */
550 
551  n = 0;
552  for (i = 0; i < nxskys; i++) {
553  if (xsky_masks[i][j] != 0)
554  continue;
555  buf[n++] = xskys[i][j];
556  }
557  if (n == 0) {
558  val = master_sky[j];
559  } else {
560  if (stat == 0)
561  domed(buf,n,&val);
562  else
563  val = vircam_mean(buf,NULL,n);
564  }
565  }
566 
567  /* Now correct this pixel in the input image */
568 
569  data[j] -= val;
570  }
571 
572  /* Free some workspace and get out of here */
573 
574  freespace(buf);
575  return;
576 }
577 
578 
579 static jpos *jpos_init(int njit) {
580  jpos *jp;
581  int i;
582 
583  jp = cpl_malloc(njit*sizeof(jpos));
584  for (i = 0; i < njit; i++) {
585  jp[i].pawposition = i + 1;
586  jp[i].nimages = 0;
587  jp[i].infiles = NULL;
588  jp[i].datas = NULL;
589  jp[i].masks = NULL;
590  jp[i].master_xsky = NULL;
591  jp[i].master_xsky_bpm = NULL;
592  jp[i].xsky_variant = NULL;
593  jp[i].xsky_variant_bpm = NULL;
594  jp[i].zeros = NULL;
595  jp[i].dx = NULL;
596  jp[i].dy = NULL;
597  }
598  return(jp);
599 }
600 
601 static void jpos_alloc(vir_fits **infiles, int nfiles, int pawpos, jpos *jp) {
602  int i,ji;
603 
604  /* First the paw position */
605 
606  jp->pawposition = pawpos;
607 
608  /* Now loop through the files and find which ones are at this position */
609 
610  jp->nimages = 0;
611  jp->infiles = cpl_malloc(6*sizeof(vir_fits *));
612  for (i = 0; i < nfiles; i++) {
613  (void)vircam_pfits_get_jitteri(vircam_fits_get_phu(infiles[i]),&ji);
614  if (ji != pawpos)
615  continue;
616  jp->infiles[jp->nimages] = infiles[i];
617  jp->nimages += 1;
618  }
619  jp->infiles = cpl_realloc(jp->infiles,jp->nimages*sizeof(vir_fits *));
620 
621  /* Right, safely through all the hard bits. Finish allocating memory */
622 
623  jp->datas = cpl_calloc(jp->nimages,sizeof(float *));
624  jp->masks = cpl_calloc(jp->nimages,sizeof(unsigned char *));
625  jp->master_xsky = NULL;
626  jp->master_xsky_bpm = NULL;
627  jp->xsky_variant = cpl_calloc(jp->nimages,sizeof(float *));
628  jp->xsky_variant_bpm = cpl_calloc(jp->nimages,sizeof(unsigned char *));
629  jp->zeros = cpl_calloc(jp->nimages,sizeof(float));
630  jp->dx = cpl_calloc(jp->nimages,sizeof(float));
631  jp->dy = cpl_calloc(jp->nimages,sizeof(float));
632 }
633 
634 static void jpos_free(jpos *jp, int njit) {
635  int i,j;
636 
637  for (i = 0; i < njit; i++) {
638  freespace(jp[i].infiles);
639  freespace(jp[i].master_xsky);
640  freespace(jp[i].master_xsky_bpm);
641  freespace(jp[i].zeros);
642  for (j = 0; j < jp[i].nimages; j++) {
643  freespace(jp[i].masks[j]);
644  freespace(jp[i].xsky_variant[j]);
645  freespace(jp[i].xsky_variant_bpm[j]);
646  }
647  freespace(jp[i].datas);
648  freespace(jp[i].masks);
649  freespace(jp[i].xsky_variant);
650  freespace(jp[i].xsky_variant_bpm);
651  freespace(jp[i].dx);
652  freespace(jp[i].dy);
653  }
654  freespace(jp);
655 }
656 
657 static void masksky_zeros(jpos *jp, int njit, int npts) {
658  int i,j,k,nf;
659  float sig,medval,off,*zeros;
660 
661  /* How many files total are there? */
662 
663  nf = 0;
664  for (j = 0; j < njit; j++)
665  nf += jp[j].nimages;
666 
667  /* Get some workspace */
668 
669  zeros = cpl_malloc(nf*sizeof(float));
670 
671  /* Loop for each input image and get the background median */
672 
673  nf = 0;
674  for (j = 0; j < njit; j++) {
675  for (i = 0; i < jp[j].nimages; i++) {
676  vircam_qmedsig(jp[j].datas[i],jp[j].masks[i],(long)npts,3.0,1,
677  -1000.0,65535.0,zeros+nf,&sig);
678  jp[j].zeros[i] = zeros[nf];
679  nf++;
680  }
681  }
682 
683  /* Get the median value of the array */
684 
685  medval = vircam_med(zeros,NULL,nf);
686 
687  /* Now work out the offset for each image */
688 
689  for (j = 0; j < njit; j++) {
690  for (i = 0; i < jp[j].nimages; i++) {
691  off = medval - jp[j].zeros[i];
692  for (k = 0; k < npts; k++)
693  jp[j].datas[i][k] += off;
694  }
695  }
696  freespace(zeros);
697 }
698 
699 static void domed(float *buf, int n, float *val) {
700  int is_even,n2;
701 
702  is_even = ! (n & 1);
703  vircam_sort(&buf,n,1);
704  n2 = n/2;
705  if (is_even) {
706  *val = 0.5*(buf[n2-1] + buf[n2]);
707  } else {
708  if (n <= 5)
709  *val = buf[n2];
710  else
711  *val = 0.5*buf[n2] + 0.25*(buf[n2-1] + buf[n2+1]);
712  }
713 }
714 
715 /*
716 
717 $Log: not supported by cvs2svn $
718 
719 */