VIRCAM Pipeline  1.3.4
vircam_mosaic.c
1 /* $Id: vircam_mosaic.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 #include <math.h>
34 #include <string.h>
35 #include <libgen.h>
36 #include <cpl.h>
37 #include "vircam_mods.h"
38 #include "vircam_utils.h"
39 #include "vircam_fits.h"
40 #include "vircam_stats.h"
41 #include "vircam_wcsutils.h"
42 
43 typedef struct {
44  double crval[2];
45  double crpix[2];
46  double cd[4];
47  double secd;
48  double tand;
49  double pv21;
50  double pv23;
51  double pv25;
52  int nx;
53  int ny;
54  int istan;
55 } mywcs;
56 
57 typedef struct {
58  cpl_frame *infile;
59  cpl_frame *conf;
60  float global_sky;
61  float global_noise;
62  double tpa;
63  double tpd;
64  float exptime;
65 
66  int nhdus;
67  mywcs **wcs_extn;
68  int *nx_extn;
69  int *ny_extn;
70  float *magzpt_extn;
71 
72  int cur_extn;
73  float *sky_extn;
74  float *scalefac;
75  float *skydiff;
76 } dstrct;
77 
78 typedef struct {
79  cpl_image *outim;
80  cpl_image *outcim;
81  int nxo;
82  int nyo;
83  mywcs *outwcs;
84  cpl_image *work;
85 } outstrct;
86 
87 static dstrct *fileptrs = NULL;
88 
89 static void prov(int interp, vir_fits *file, cpl_frameset *fset);
90 static void writewcs(vir_fits *fitsfile, mywcs *o);
91 static void average(dstrct *dd, int nextn, float *data, int *cdata,
92  outstrct *outstr, int interp, int conflim);
93 static void output_images(int nimages, outstrct *outstr);
94 static mywcs *dupwcs(mywcs *in);
95 static float distort_corr(double x, double y, mywcs *w);
96 static void outloc(mywcs *win, double xin, double yin, mywcs *wout,
97  double *xout, double *yout);
98 static void xytord(mywcs *win, double xin, double yin, double *ra,
99  double *dec);
100 static void rdtoxy(mywcs *win, double ra, double dec, double *x, double *y);
101 static void dstrct_init(int nfiles);
102 static void dstrct_extn_init(dstrct *dd, int nhdu);
103 static int dstrct_extn_fill_from_plist(dstrct *dd, int extnum, char *expkey,
104  cpl_propertylist *plist, char *msg);
105 static void dstrct_close(int nfiles);
106 static void normal(outstrct *o);
107 
108 
109 extern int vircam_mosaic(cpl_frameset *infiles, cpl_frameset *inconf,
110  int interp, int skyflag, float skywish_in,
111  char *expkey, int conflim, vir_fits **out,
112  vir_fits **outc, int *status) {
113  cpl_size i,nimages,nconfs;
114  int nerrs,nhdu,j,nstart,nalloc,npts,*cdata,jj,ind1,ind,ii;
115  cpl_frame *fr,*frc;
116  outstrct outstr;
117  dstrct *dd;
118  cpl_propertylist *plist1,*plist2;
119  char msg[BUFSIZ];
120  float *alldata,back,noise,skywish,zpt1,exp1,sky1,scalefac,ds,*data,distort;
121  double x,y;
122  cpl_image *im,*cim;
123  vir_fits *ref;
124  const char *fctid="vircam_mosaic";
125 
126  /* Inherited status */
127 
128  *out = NULL;
129  *outc = NULL;
130  if (*status != VIR_OK)
131  return(*status);
132 
133  /* Quick sanity check */
134 
135  nimages = cpl_frameset_get_size(infiles);
136  nconfs = cpl_frameset_get_size(inconf);
137  if (nimages <= 0) {
138  cpl_msg_error(fctid,"No images to combine");
139  FATAL_ERROR
140  }
141  if (nconfs != 1 && nconfs != nimages) {
142  cpl_msg_error(fctid,"Number of conf maps must be 1 or nimages");
143  FATAL_ERROR
144  }
145 
146  /* Get some space for the file descriptors */
147 
148  dstrct_init(nimages);
149 
150  /* Loop through the input files and make sure we can open them all.
151  Compare the data array sizes in each of the extensions to those in
152  the relevant confidence maps. */
153 
154  nerrs = 0;
155  for (i = 0; i < nimages; i++) {
156  dd = fileptrs + i;
157  fr = cpl_frameset_get_frame(infiles,i);
158  dd->infile = fr;
159  if (nconfs == 1)
160  frc = cpl_frameset_get_frame(inconf,0);
161  else
162  frc = cpl_frameset_get_frame(inconf,i);
163  dd->conf = frc;
164 
165  /* Start by checking the number of extensions in each */
166 
167  if (cpl_frame_get_nextensions(fr) != cpl_frame_get_nextensions(frc)) {
168  cpl_msg_error(fctid,"Number of extensions in %s and %s must match",
169  cpl_frame_get_filename(fr),
170  cpl_frame_get_filename(frc));
171  nerrs++;
172  continue;
173  }
174 
175  /* Now loop through each extension. Load both the image and confidence
176  map headers and make sure the image dimensions match */
177 
178  nhdu = (int)cpl_frame_get_nextensions(fr);
179  dstrct_extn_init(dd,nhdu);
180  for (j = 1; j <= nhdu; j++) {
181  plist1 = cpl_propertylist_load(cpl_frame_get_filename(fr),j);
182  if (cpl_error_get_code() != 0) {
183  nerrs++;
184  cpl_msg_error(fctid,"Unable to get header from %s[%d]",
185  cpl_frame_get_filename(fr),j);
186  continue;
187  }
188  plist2 = cpl_propertylist_load(cpl_frame_get_filename(frc),j);
189  if (cpl_error_get_code() != 0) {
190  nerrs++;
191  cpl_msg_error(fctid,"Unable to get header from %s[%d]",
192  cpl_frame_get_filename(frc),j);
193  cpl_propertylist_delete(plist1);
194  continue;
195  }
196  if (cpl_propertylist_get_int(plist1,"NAXIS1") !=
197  cpl_propertylist_get_int(plist2,"NAXIS1") ||
198  cpl_propertylist_get_int(plist1,"NAXIS2") !=
199  cpl_propertylist_get_int(plist2,"NAXIS2")) {
200  nerrs++;
201  cpl_msg_error(fctid,"%s[%d] and %s[%d] image dimensions don't match",
202  cpl_frame_get_filename(fr),j,
203  cpl_frame_get_filename(frc),j);
204  cpl_propertylist_delete(plist1);
205  cpl_propertylist_delete(plist2);
206  continue;
207  }
208 
209  /* Get information from extension headers */
210 
211  if (dstrct_extn_fill_from_plist(dd,j,expkey,plist1,msg) != VIR_OK) {
212  nerrs++;
213  cpl_msg_error(fctid,"Error reading header in %s[%d] -- %s",
214  cpl_frame_get_filename(fr),j,msg);
215  cpl_propertylist_delete(plist1);
216  cpl_propertylist_delete(plist2);
217  continue;
218  }
219  cpl_propertylist_delete(plist1);
220  cpl_propertylist_delete(plist2);
221  }
222  }
223  if (nerrs != 0) {
224  cpl_msg_error(fctid,"%d fatal errors",nerrs);
225  FATAL_ERROR
226  }
227 
228  /* Loop through the files again and get some background stats */
229 
230  for (i = 0; i < nimages; i++) {
231  nstart = 0;
232  nalloc = 0;
233  dd = fileptrs + i;
234  alldata = NULL;
235  for (j = 1; j <= dd->nhdus; j++) {
236 
237  /* Get some space to hold all the data from all extensions */
238 
239  nstart = nalloc;
240  npts = (dd->nx_extn[j-1])*(dd->ny_extn[j-1]);
241  nalloc += npts;
242  alldata = cpl_realloc(alldata,nalloc*sizeof(float));
243 
244  /* Load the current image */
245 
246  im = cpl_image_load(cpl_frame_get_filename(dd->infile),
247  CPL_TYPE_FLOAT,0,j);
248  memmove(alldata+nstart,cpl_image_get_data_float(im),
249  npts*sizeof(float));
250 
251  /* Get the stats for the current image */
252 
253  vircam_qmedsig(cpl_image_get_data_float(im),NULL,(long)npts,
254  3.0,3,-1000.0,65535.0,&back,&noise);
255  dd->sky_extn[j-1] = back;
256  cpl_image_delete(im);
257  }
258 
259  /* Get the global background for the whole file */
260 
261  vircam_qmedsig(alldata,NULL,(long)nalloc,3.0,3,-1000.0,65535.0,
262  &back,&noise);
263  dd->global_sky = back;
264  dd->global_noise = noise;
265  freespace(alldata);
266  }
267 
268  /* Now adjust some of the background estimates depending on what's been
269  requested */
270 
271  if (skyflag == 2) {
272  skywish = 0.0;
273  for (i = 0; i < nimages; i++)
274  skywish += (fileptrs+i)->global_sky;
275  skywish /= (float)nimages;
276  } else if (skyflag == 1) {
277  skywish = skywish_in;
278  } else {
279  skywish = 0.0;
280  }
281  if (skyflag != 0) {
282  for (i = 0; i < nimages; i++)
283  (fileptrs+i)->global_sky = skywish;
284  }
285 
286  /* Finally work out scale factors and sky offsets */
287 
288  zpt1 = fileptrs->magzpt_extn[0];
289  exp1 = fileptrs->exptime;
290  sky1 = fileptrs->global_sky;
291  for (i = 0; i < nimages; i++) {
292  dd = fileptrs + i;
293  for (j = 1; j <= dd->nhdus; j++) {
294  scalefac = (exp1/dd->exptime)*pow(10.0,0.4*(zpt1-dd->magzpt_extn[j-1]));
295  ds = sky1 - scalefac*(dd->global_sky);
296  dd->scalefac[j-1] = scalefac;
297  dd->skydiff[j-1] = ds;
298  }
299  }
300 
301  /* Now work out the dimensions of the output image and create it */
302 
303  output_images((int)nimages,&outstr);
304 
305  /* Loop through each extension now and do the summation */
306 
307  for (i = 0; i < nimages; i++) {
308  dd = fileptrs + i;
309  for (j = 1; j <= dd->nhdus; j++) {
310  im = cpl_image_load(cpl_frame_get_filename(dd->infile),
311  CPL_TYPE_FLOAT,0,(cpl_size)j);
312  data = cpl_image_get_data_float(im);
313  cim = cpl_image_load(cpl_frame_get_filename(dd->conf),
314  CPL_TYPE_INT,0,(cpl_size)j);
315  cdata = cpl_image_get_data_int(cim);
316 
317  /* Modify the data array so that they are all on the same
318  system as the first image. Also take out astrometric
319  distortion */
320 
321  if (skyflag != 0) {
322  for (jj = 0; jj < dd->ny_extn[j-1]; jj++) {
323  ind1 = jj*(dd->nx_extn[j-1]);
324  y = (double)(jj + 1);
325  for (ii = 0; ii < dd->nx_extn[j-1]; ii++) {
326  ind = ind1 + ii;
327  x = (double)(ii + 1);
328  distort = distort_corr(x,y,dd->wcs_extn[j-1]);
329  data[ind] = (data[ind] - dd->sky_extn[j-1])*distort +
330  skywish;
331  }
332  }
333  }
334 
335  /* Now average it in */
336 
337  average(dd,j,data,cdata,&outstr,interp,conflim);
338  cpl_image_delete(im);
339  cpl_image_delete(cim);
340  }
341  }
342 
343  /* Normalise the output maps */
344 
345  normal(&outstr);
346 
347  /* Wrap the result */
348 
349  ref = vircam_fits_load(fileptrs->infile,CPL_TYPE_FLOAT,1);
350  *out = vircam_fits_wrap(outstr.outim,ref,NULL,NULL);
351  vircam_fits_delete(ref);
352  ref = vircam_fits_load(fileptrs->conf,CPL_TYPE_INT,1);
353  *outc = vircam_fits_wrap(outstr.outcim,ref,NULL,NULL);
354  vircam_fits_delete(ref);
355 
356  /* Write the WCS in both */
357 
358  writewcs(*out,outstr.outwcs);
359  writewcs(*outc,outstr.outwcs);
360 
361  /* Write the provenance */
362 
363  prov(interp,*out,infiles);
364  prov(interp,*outc,infiles);
365 
366  /* Add a DRIBBLE keyword */
367 
368  if (interp != 0) {
369  cpl_propertylist_update_string(vircam_fits_get_ehu(*out),"DRIBBLE",
370  "bilinear");
371  cpl_propertylist_set_comment(vircam_fits_get_ehu(*out),"DRIBBLE",
372  "Interpolation method");
373  }
374 
375  /* Tidy and exit */
376 
377  freespace(outstr.outwcs);
378  cpl_image_delete(outstr.work);
379  dstrct_close(nimages);
380  return(VIR_OK);
381 }
382 
383 static void prov(int interp, vir_fits *file, cpl_frameset *fset) {
384  int nfset,ncard,i;
385  cpl_propertylist *ehu;
386  char value[81],key[9],comment[81];
387  const char *algorithm[] = {"Nearest-neighbour","Bi-linear interpolation"};
388 
389  /* Start by removing any pre-existing PROV keywords */
390 
391  ehu = vircam_fits_get_ehu(file);
392  cpl_propertylist_erase_regexp(ehu,"PROV*",0);
393 
394  /* Add the zeroth card */
395 
396  ncard = 0;
397  (void)snprintf(key,9,"PROV%04d",ncard);
398  (void)snprintf(value,81,"File formed from %s of",algorithm[interp]);
399  (void)snprintf(comment,81,"File combination algorithm");
400  cpl_propertylist_update_string(ehu,key,value);
401  cpl_propertylist_set_comment(ehu,key,comment);
402 
403  /* Now add a card for each input file */
404 
405  nfset = cpl_frameset_get_size(fset);
406  for (i = 0; i < nfset; i++) {
407  ncard++;
408  (void)snprintf(key,9,"PROV%04d",ncard);
409  (void)snprintf(value,81,"%s",
410  basename((char *)cpl_frame_get_filename(cpl_frameset_get_frame(fset,i))));
411  (void)snprintf(comment,81,"Card # %d",ncard);
412  cpl_propertylist_update_string(ehu,key,value);
413  cpl_propertylist_set_comment(ehu,key,comment);
414  }
415 }
416 
417 static void writewcs(vir_fits *fitsfile, mywcs *o) {
418  char key[16],sval[16],proj[4];
419  int status,i,j,n;
420  float val;
421  double dval;
422  cpl_propertylist *ehu;
423 
424  /* Get a convenient reference */
425 
426  ehu = vircam_fits_get_ehu(fitsfile);
427 
428  /* Write out CTYPE */
429 
430  if (o->istan)
431  (void)strcpy(proj,"TAN");
432  else
433  (void)strcpy(proj,"ZPN");
434  status = 0;
435  for (i = 1; i <= 2; i++) {
436  (void)sprintf(key,"CTYPE%d",i);
437  if (i == 1)
438  (void)sprintf(sval,"RA---%s",proj);
439  else
440  (void)sprintf(sval,"DEC--%s",proj);
441  (void)cpl_propertylist_update_string(ehu,key,sval);
442  }
443 
444  /* CRVAL, CRPIX */
445 
446  for (i = 1; i <= 2; i++) {
447  (void)sprintf(key,"CRVAL%d",i);
448  dval = (o->crval[i-1])*DEGRAD;
449  cpl_propertylist_update_double(ehu,key,dval);
450  }
451  for (i = 1; i <= 2; i++) {
452  (void)sprintf(key,"CRPIX%d",i);
453  dval = (o->crpix[i-1]);
454  cpl_propertylist_update_double(ehu,key,dval);
455  }
456 
457  /* CD matrix */
458 
459  n = 0;
460  for (j = 1; j <= 2; j++) {
461  for (i = 1; i <= 2; i++) {
462  (void)sprintf(key,"CD%d_%d",j,i);
463  dval = (o->cd[n])*DEGRAD;
464  cpl_propertylist_update_double(ehu,key,dval);
465  n++;
466  }
467  }
468 
469  /* PV vector */
470 
471  if (! o->istan) {
472  val = (float)(o->pv21);
473  cpl_propertylist_update_float(ehu,"PV2_1",val);
474  val = (float)(o->pv23);
475  cpl_propertylist_update_float(ehu,"PV2_3",val);
476  val = (float)(o->pv25);
477  cpl_propertylist_update_float(ehu,"PV2_5",val);
478  } else {
479  if (cpl_propertylist_has(ehu,"PV2_1"))
480  cpl_propertylist_erase(ehu,"PV2_1");
481  if (cpl_propertylist_has(ehu,"PV2_3"))
482  cpl_propertylist_erase(ehu,"PV2_3");
483  if (cpl_propertylist_has(ehu,"PV2_5"))
484  cpl_propertylist_erase(ehu,"PV2_5");
485  }
486 }
487 
488 static void average(dstrct *dd, int nextn, float *data, int *cdata,
489  outstrct *outstr, int interp, int conflim) {
490  int i,j,ind1,ind,outind,j_1,j_2,i_1,i_2,jj,ii,ind1o,indo,ixo,iyo;
491  float *odata,*work,wi,wj,scf,fcd,ds;
492  double x_in,y_in,x_out,y_out;
493 
494  /* Set up some convenience variables */
495 
496  odata = cpl_image_get_data_float(outstr->outim);
497  scf = dd->scalefac[nextn-1];
498  ds = dd->skydiff[nextn-1];
499 
500  /* Get some workspace for the sum of the confidence */
501 
502  work = cpl_image_get_data_float(outstr->work);
503 
504  /* Have separate loops for nearest neighbour and interpolation to
505  speed things up */
506 
507  if (interp == 0) {
508  for (j = 0; j < dd->ny_extn[nextn-1]; j++) {
509  ind1 = j*dd->nx_extn[nextn-1];
510  y_in = (double)(j+1);
511  for (i = 0; i < dd->nx_extn[nextn-1]; i++) {
512  ind = ind1 + i;
513  if (cdata[ind] <= conflim)
514  continue;
515  x_in = (double)(i+1);
516  outloc(dd->wcs_extn[nextn-1],x_in,y_in,outstr->outwcs,
517  &x_out,&y_out);
518  ixo = vircam_nint(x_out);
519  iyo = vircam_nint(y_out);
520  if (ixo < 1 || ixo > outstr->nxo || iyo < 1 ||
521  iyo > outstr->nyo)
522  continue;
523  outind = (iyo-1)*outstr->nxo + ixo - 1;
524  fcd = (float)cdata[ind];
525  odata[outind] += fcd*(data[ind]*scf + ds);
526  work[outind] += fcd;
527  }
528  }
529  } else {
530  for (j = 0; j < dd->ny_extn[nextn-1]; j++) {
531  ind1 = j*dd->nx_extn[nextn-1];
532  y_in = (double)(j+1);
533  for (i = 0; i < dd->nx_extn[nextn-1]; i++) {
534  ind = ind1 + i;
535  if (cdata[ind] <= conflim)
536  continue;
537  x_in = (double)(i+1);
538  outloc(dd->wcs_extn[nextn-1],x_in,y_in,outstr->outwcs,
539  &x_out,&y_out);
540  if (x_out < 1.0 || y_out < 1.0 || x_out >= outstr->nxo || y_out >= outstr->nyo) {
541 /* fprintf(stderr,"%d %d %g %g %g %g\n",i,j,x_in,y_in,x_out,y_out); */
542 
543 /* xytord(dd->wcs_extn,x_in,y_in,&x_out,&y_out); */
544 /* fprintf(stderr,"%g %g***\n",x_out,y_out); */
545 /* exit(1); */
546  continue;
547  }
548  j_1 = (int)y_out;
549  j_2 = j_1 + 1;
550  i_1 = (int)x_out;
551  i_2 = i_1 + 1;
552  fcd = (float)cdata[ind];
553  for (jj = j_1; jj <= j_2; jj++) {
554  wj = 1.0 - fabs(y_out - (double)jj);
555  ind1o = (jj - 1)*outstr->nxo;
556  for (ii = i_1; ii <= i_2; ii++) {
557  indo = ind1o + ii - 1;
558  wi = 1.0 - fabs(x_out - (double)ii);
559  odata[indo] += wi*wj*fcd*(scf*data[ind] + ds);
560  work[indo] += wi*wj*fcd;
561  }
562  }
563  }
564  }
565  }
566 }
567 
568 static void output_images(int nimages, outstrct *outstr) {
569  double lowerleft[2],upperleft[2],lowerright[2],upperright[2];
570  double xout,yout,xmin,ymin,ra,dec;
571  float *data;
572  int i,*idata,j,nx,ny,ixo,iyo;
573  dstrct *dd;
574  mywcs *refwcs,*curwcs,*outwcs;
575 
576  /* Initialise the corners */
577 
578  lowerleft[0] = 1.0e8;
579  lowerleft[1] = 1.0e8;
580  upperleft[0] = 1.0e8;
581  upperleft[1] = -1.0e8;
582  lowerright[0] = -1.0e8;
583  lowerright[1] = 1.0e8;
584  upperright[0] = -1.0e8;
585  upperright[1] = -1.0e8;
586 
587  /* Loop for all images relative to the first one */
588 
589  refwcs = NULL;
590  for (i = 0; i < nimages; i++) {
591  dd = fileptrs + i;
592 
593  /* Open the image and loop for each hdu */
594 
595  for (j = 1; j <= dd->nhdus; j++) {
596  curwcs = dd->wcs_extn[j-1];
597  if (i == 0 && j == 1) {
598  refwcs = dupwcs(curwcs);
599  refwcs->istan = 1;
600  }
601  nx = dd->nx_extn[j-1];
602  ny = dd->ny_extn[j-1];
603  outloc(curwcs,(double)1.0,(double)1.0,refwcs,&xout,&yout);
604  lowerleft[0] = min(lowerleft[0],xout);
605  lowerleft[1] = min(lowerleft[1],yout);
606  outloc(curwcs,(double)1.0,(double)ny,refwcs,&xout,&yout);
607  upperleft[0] = min(upperleft[0],xout);
608  upperleft[1] = max(upperleft[1],yout);
609  outloc(curwcs,(double)nx,(double)1.0,refwcs,&xout,&yout);
610  lowerright[0] = max(lowerright[0],xout);
611  lowerright[1] = min(lowerright[1],yout);
612  outloc(curwcs,(double)nx,(double)ny,refwcs,&xout,&yout);
613  upperright[0] = max(upperright[0],xout);
614  upperright[1] = max(upperright[1],yout);
615  }
616  }
617 
618  /* Ok, what are the limits? */
619 
620  ixo = vircam_nint(max(lowerright[0]-lowerleft[0],
621  upperright[0]-upperleft[0])) + 5;
622  iyo = vircam_nint(max(upperright[1]-lowerright[1],
623  upperleft[1]-lowerleft[1])) + 5;
624  xmin = min(lowerleft[0],upperleft[0]);
625  ymin = min(lowerleft[1],lowerright[1]);
626  outstr->nxo = ixo;
627  outstr->nyo = iyo;
628 
629  /* Create the output images and work image. Make sure they are zeroed
630  because they're going to be used in summations */
631 
632  outstr->outim = cpl_image_new((cpl_size)ixo,(cpl_size)iyo,CPL_TYPE_FLOAT);
633  data = cpl_image_get_data_float(outstr->outim);
634  memset(data,0,ixo*iyo*sizeof(float));
635  outstr->work = cpl_image_new((cpl_size)ixo,(cpl_size)iyo,CPL_TYPE_FLOAT);
636  data = cpl_image_get_data_float(outstr->work);
637  memset(data,0,ixo*iyo*sizeof(float));
638  outstr->outcim = cpl_image_new((cpl_size)ixo,(cpl_size)iyo,CPL_TYPE_INT);
639  idata = cpl_image_get_data_int(outstr->outcim);
640  memset(idata,0,ixo*iyo*sizeof(int));
641 
642  /* Update the reference point for the WCS */
643 
644  outwcs = cpl_malloc(sizeof(mywcs));
645  outwcs->crpix[0] = refwcs->crpix[0] - xmin + 1.0;
646  outwcs->crpix[1] = refwcs->crpix[1] - ymin + 1.0;
647  outwcs->crval[0] = refwcs->crval[0];
648  outwcs->crval[1] = refwcs->crval[1];
649  for (i = 0; i < 4; i++)
650  outwcs->cd[i] = refwcs->cd[i];
651  outwcs->pv21 = 1.0;
652  outwcs->pv23 = -0.33333333333;
653  outwcs->pv25 = 0.0;
654  outwcs->nx = ixo;
655  outwcs->ny = iyo;
656  outwcs->istan = 1;
657  outwcs->tand = tan(outwcs->crval[1]);
658  outwcs->secd = 1.0/cos(outwcs->crval[1]);
659  outstr->outwcs = outwcs;
660 
661  /* Now see what the RA,Dec of the centre of the map is and shift the
662  reference point to that place */
663 
664  xout = 0.5*(double)ixo;
665  yout = 0.5*(double)iyo;
666  xytord(outwcs,xout,yout,&ra,&dec);
667  outwcs->crpix[0] = xout;
668  outwcs->crpix[1] = yout;
669  outwcs->crval[0] = ra/DEGRAD;
670  outwcs->crval[1] = dec/DEGRAD;
671  outwcs->tand = tan(outwcs->crval[1]);
672  outwcs->secd = 1.0/cos(outwcs->crval[1]);
673  freespace(refwcs);
674 }
675 
676 static float distort_corr(double x, double y, mywcs *w) {
677  double xi,xn,r,rprime,drprime_bydr,dc,tanr;
678 
679  xi = (x - w->crpix[0])*(w->cd[0]) + (y - w->crpix[1])*(w->cd[1]);
680  xn = (x - w->crpix[0])*(w->cd[2]) + (y - w->crpix[1])*(w->cd[3]);
681  r = sqrt(xi*xi + xn*xn);
682  if (r == 0.0) {
683  dc = 1.0;
684  } else {
685  if (! w->istan) {
686  rprime = r*w->pv21 + pow(r,(double)3.0)*w->pv23 +
687  pow(r,(double)5.0)*w->pv25;
688  drprime_bydr = w->pv21 + 3.0*pow(r,(double)2.0)*w->pv23 +
689  5.0*pow(r,(double)4.0)*w->pv25;
690  tanr = tan(rprime);
691  dc = tanr*drprime_bydr*(1.0 + tanr*tanr)/r;
692  } else {
693  tanr = tan(r);
694  dc = (1.0 + tanr*tanr)*tanr/r;
695  }
696  }
697  return(dc);
698 }
699 
700 static void outloc(mywcs *win, double xin, double yin, mywcs *wout,
701  double *xout, double *yout) {
702  double xt,yt,xi,eta,r,rfac,aa,tandec,denom,rp;
703  int i;
704 
705  /* Do the conversion. First to standard coordinates in the frame of
706  the input image */
707 
708  xt = xin - win->crpix[0];
709  yt = yin - win->crpix[1];
710  xi = win->cd[0]*xt + win->cd[1]*yt;
711  eta = win->cd[2]*xt + win->cd[3]*yt;
712  if (! win->istan) {
713  if (fabs(xt) < 1.0e-6 && fabs(yt) < 1.0e-6) {
714  rfac = 1.0;
715  } else {
716  rp = sqrt(xi*xi + eta*eta);
717  r = rp;
718  for (i = 0; i < 3; i++) {
719  rfac = win->pv21 + win->pv23*pow(r,2.0) + win->pv25*pow(r,4.0);
720  r = rp/rfac;
721  }
722  rfac = tan(r)/rp;
723  }
724  } else {
725  rfac = 1.0;
726  }
727  xi *= rfac;
728  eta *= rfac;
729  aa = atan(xi*win->secd/(1.0-eta*win->tand));
730  if (xi != 0.0)
731  tandec = (eta+win->tand)*sin(aa)/(xi*win->secd);
732  else
733  tandec = (eta+win->tand)/(1.0 - eta*win->tand);
734 
735  /* Now form standard coordinates in the frame of the output image */
736 
737  aa += (win->crval[0] - wout->crval[0]);
738  denom = wout->tand*tandec + cos(aa);
739  xi = wout->secd*sin(aa)/denom;
740  eta = (tandec - wout->tand*cos(aa))/denom;
741  if (! wout->istan) {
742  rp = sqrt(xi*xi + eta*eta);
743  r = atan(rp);
744  rfac = wout->pv21 + wout->pv23*pow(rp,2.0) + wout->pv25*pow(rp,4.0);
745  rfac *= r/rp;
746  } else {
747  rfac = 1.0;
748  }
749  xi *= rfac;
750  eta *= rfac;
751  denom = wout->cd[0]*wout->cd[3] - wout->cd[1]*wout->cd[2];
752  *xout = (xi*wout->cd[3] - eta*wout->cd[1])/denom + wout->crpix[0];
753  *yout = (eta*wout->cd[0] - xi*wout->cd[2])/denom + wout->crpix[1];
754 }
755 
756 static void xytord(mywcs *win, double xin, double yin, double *ra,
757  double *dec) {
758  double xt,yt,xi,eta,r,rfac,aa;
759 
760  xt = xin - win->crpix[0];
761  yt = yin - win->crpix[1];
762  xi = win->cd[0]*xt + win->cd[1]*yt;
763  eta = win->cd[2]*xt + win->cd[3]*yt;
764  r = sqrt(xi*xi + eta*eta);
765  if (! win->istan) {
766  rfac = win->pv21 + win->pv23*pow(r,2.0) + win->pv25*pow(r,4.0);
767  r /= rfac;
768  rfac = win->pv21 + win->pv23*pow(r,2.0) + win->pv25*pow(r,4.0);
769  xi /= rfac;
770  eta /= rfac;
771  } else {
772  if (r == 0.0)
773  rfac = 1.0;
774  else
775  rfac = tan(r)/r;
776  xi *= rfac;
777  eta *= rfac;
778  }
779  aa = atan(xi*win->secd/(1.0-eta*win->tand));
780  *ra = aa + win->crval[0];
781  if (xi != 0.0) {
782  *dec = atan((eta + win->tand)*sin(aa)/(xi*win->secd));
783  } else {
784  *dec = atan((eta + win->tand)/(1.0 - eta*win->tand));
785  }
786  if (*ra > 2.0*CPL_MATH_PI)
787  *ra -= 2.0*CPL_MATH_PI;
788  else if (*ra < 0.0)
789  *ra += 2.0*CPL_MATH_PI;
790  *ra *= DEGRAD;
791  *dec *= DEGRAD;
792 }
793 
794 static void rdtoxy(mywcs *win, double ra, double dec, double *x, double *y) {
795  double xi,eta,rra,ddec,denom,rp,rfac;
796 
797  rra = ra/DEGRAD - win->crval[0];
798  ddec = dec/DEGRAD;
799  denom = win->tand*tan(ddec) + cos(rra);
800  xi = win->secd*sin(rra)/denom;
801  eta = (tan(ddec) - win->tand*cos(rra))/denom;
802  rp = sqrt(xi*xi + eta*eta);
803  if (win->istan) {
804  if (rp == 0)
805  rfac = 1.0;
806  else
807  rfac = atan(rp)/rp;
808  } else {
809  rfac = win->pv21 + win->pv23*pow(rp,2.0) + win->pv25*pow(rp,4.0);
810  }
811  xi *= rfac;
812  eta *= rfac;
813  denom = win->cd[0]*win->cd[3] - win->cd[1]*win->cd[2];
814  *x = (xi*win->cd[3] - eta*win->cd[1])/denom + win->crpix[0];
815  *y = (eta*win->cd[0] - xi*win->cd[2])/denom + win->crpix[1];
816 }
817 
818 static mywcs *dupwcs(mywcs *in) {
819  int i;
820  mywcs *out;
821 
822  out = cpl_malloc(sizeof(mywcs));
823  for (i = 0; i < 2; i++) {
824  out->crval[i] = in->crval[i];
825  out->crpix[i] = in->crpix[i];
826  }
827  for (i = 0; i < 4; i++)
828  out->cd[i] = in->cd[i];
829  out->secd = in->secd;
830  out->tand = in->tand;
831  out->pv21 = in->pv21;
832  out->pv23 = in->pv23;
833  out->pv25 = in->pv25;
834  out->nx = in->nx;
835  out->ny = in->ny;
836  out->istan = in->istan;
837  return(out);
838 }
839 
840 static void dstrct_init(int nfiles) {
841  int i;
842  dstrct *dd;
843 
844  fileptrs = cpl_malloc(nfiles*sizeof(dstrct));
845  for (i = 0; i < nfiles; i++) {
846  dd = fileptrs + i;
847  dd->infile = NULL;
848  dd->conf = NULL;
849  dd->global_sky = 0.0;
850  dd->global_noise = 0.0;
851  dd->tpa = 0.0;
852  dd->tpd = 0.0;
853  dd->exptime = 0.0;
854  dd->nhdus = 0;
855  dd->wcs_extn = NULL;
856  dd->nx_extn = NULL;
857  dd->ny_extn = NULL;
858  dd->magzpt_extn = NULL;
859  dd->sky_extn = NULL;
860  dd->cur_extn = 0;
861  dd->scalefac = NULL;
862  dd->skydiff = NULL;
863  }
864 }
865 
866 static void dstrct_extn_init(dstrct *dd, int nhdu) {
867  int i;
868  dd->nhdus = nhdu;
869  dd->wcs_extn = cpl_malloc(nhdu*sizeof(mywcs *));
870  for (i = 0; i < nhdu; i++)
871  dd->wcs_extn[i] = NULL;
872  dd->nx_extn = cpl_malloc(nhdu*sizeof(int));
873  dd->ny_extn = cpl_malloc(nhdu*sizeof(int));
874  dd->magzpt_extn = cpl_malloc(nhdu*sizeof(float));
875  dd->sky_extn = cpl_malloc(nhdu*sizeof(float));
876  dd->scalefac = cpl_malloc(nhdu*sizeof(float));
877  dd->skydiff = cpl_malloc(nhdu*sizeof(float));
878 }
879 
880 static int dstrct_extn_fill_from_plist(dstrct *dd, int extnum, char *expkey,
881  cpl_propertylist *plist, char *msg) {
882  mywcs *w;
883  int i;
884 
885  /* Fill in some global parameters when reading the first header */
886 
887  if (extnum == 1) {
888  if (cpl_propertylist_has(plist,"CRVAL1")) {
889  dd->tpa = cpl_propertylist_get_double(plist,"CRVAL1");
890  } else {
891  (void)sprintf(msg,"Missing CRVAL1 in extension %d",extnum);
892  return(VIR_FATAL);
893  }
894  if (cpl_propertylist_has(plist,"CRVAL2")) {
895  dd->tpd = cpl_propertylist_get_double(plist,"CRVAL2");
896  } else {
897  (void)sprintf(msg,"Missing CRVAL2 in extension %d",extnum);
898  return(VIR_FATAL);
899  }
900  if (cpl_propertylist_has(plist,expkey)) {
901  dd->exptime = cpl_propertylist_get_float(plist,expkey);
902  } else {
903  (void)sprintf(msg,"Missing %s in extension %d",expkey,extnum);
904  return(VIR_FATAL);
905  }
906  }
907 
908  /* Now some extension specific stuff. Start with the data array size
909  and mag zeropoint */
910 
911  if (cpl_propertylist_has(plist,"NAXIS1")) {
912  dd->nx_extn[extnum-1] = cpl_propertylist_get_int(plist,"NAXIS1");
913  } else {
914  (void)sprintf(msg,"Missing NAXIS1 in extension %d",extnum);
915  return(VIR_FATAL);
916  }
917  if (cpl_propertylist_has(plist,"NAXIS2")) {
918  dd->ny_extn[extnum-1] = cpl_propertylist_get_int(plist,"NAXIS2");
919  } else {
920  (void)sprintf(msg,"Missing NAXIS2 in extension %d",extnum);
921  return(VIR_FATAL);
922  }
923  if (cpl_propertylist_has(plist,"ESO QC MAGZPT")) {
924  dd->magzpt_extn[extnum-1] = cpl_propertylist_get_float(plist,
925  "ESO QC MAGZPT");
926  } else {
927  (void)sprintf(msg,"Missing ESO QC MAGZPT in extension %d",extnum);
928  return(VIR_FATAL);
929  }
930 
931  /* Now for the wcs */
932 
933  w = cpl_malloc(sizeof(mywcs));
934  if (strstr(cpl_propertylist_get_string(plist,"CTYPE1"),"TAN") == NULL)
935  w->istan = 0;
936  else
937  w->istan = 1;
938  w->crval[0] = cpl_propertylist_get_double(plist,"CRVAL1");
939  w->crval[1] = cpl_propertylist_get_double(plist,"CRVAL2");
940  w->crpix[0] = cpl_propertylist_get_double(plist,"CRPIX1");
941  w->crpix[1] = cpl_propertylist_get_double(plist,"CRPIX2");
942  w->cd[0] = cpl_propertylist_get_double(plist,"CD1_1");
943  w->cd[1] = cpl_propertylist_get_double(plist,"CD1_2");
944  w->cd[2] = cpl_propertylist_get_double(plist,"CD2_1");
945  w->cd[3] = cpl_propertylist_get_double(plist,"CD2_2");
946  if (! w->istan) {
947  if (cpl_propertylist_has(plist,"PV2_1"))
948  w->pv21 = cpl_propertylist_get_double(plist,"PV2_1");
949  else
950  w->pv21 = 1.0;
951  if (cpl_propertylist_has(plist,"PV2_3"))
952  w->pv23 = cpl_propertylist_get_double(plist,"PV2_3");
953  else
954  w->pv23 = -0.3333333333;
955  if (cpl_propertylist_has(plist,"PV2_5"))
956  w->pv25 = cpl_propertylist_get_double(plist,"PV2_5");
957  else
958  w->pv25 = 0.0;
959  } else {
960  w->pv21 = 1.0;
961  w->pv23 = -0.33333333;
962  w->pv25 = 0.0;
963  }
964  w->nx = dd->nx_extn[extnum-1];
965  w->ny = dd->ny_extn[extnum-1];
966 
967  /* Change angles to radians */
968 
969  for (i = 0; i < 2; i++)
970  w->crval[i] /= DEGRAD;
971  for (i = 0; i < 4; i++)
972  w->cd[i] /= DEGRAD;
973 
974  /* Add a couple of convenience values */
975 
976  w->tand = tan(w->crval[1]);
977  w->secd = 1.0/cos(w->crval[1]);
978 
979  /* Now the store away WCS... */
980 
981  dd->wcs_extn[extnum-1] = w;
982  return(VIR_OK);
983 }
984 
985 static void dstrct_close(int nfiles) {
986  int i,j;
987  dstrct *dd;
988 
989  for (i = 0; i < nfiles; i++) {
990  dd = fileptrs + i;
991  if (dd->wcs_extn != NULL) {
992  for (j = 0; j < dd->nhdus; j++)
993  freespace(dd->wcs_extn[j]);
994  freespace(dd->wcs_extn);
995  }
996  freespace(dd->nx_extn);
997  freespace(dd->ny_extn);
998  freespace(dd->magzpt_extn);
999  freespace(dd->sky_extn);
1000  freespace(dd->scalefac);
1001  freespace(dd->skydiff);
1002  }
1003  freespace(fileptrs);
1004 }
1005 
1006 static void normal(outstrct *o) {
1007  int npo,i;
1008  float *odata,*work,renorm,val,junk;
1009  int *ocdata;
1010 
1011  /* Get some convenience variables */
1012 
1013  npo = o->nxo*o->nyo;
1014  odata = cpl_image_get_data_float(o->outim);
1015  work = cpl_image_get_data_float(o->work);
1016  ocdata = cpl_image_get_data_int(o->outcim);
1017 
1018  /* Normalise the output image */
1019 
1020  for (i = 0; i < npo; i++)
1021  if (work[i] != 0.0)
1022  odata[i] /= work[i];
1023 
1024  /* Work out a mean background that you can use to fill in the blank spots */
1025 
1026  (void)vircam_qmedsig(odata,NULL,(long)npo,3.0,3,-1000.0,65535.0,&val,&junk);
1027  for (i = 0; i < npo; i++)
1028  if (work[i] == 0.0)
1029  odata[i] = val;
1030 
1031  /* Now normalise the confidence map */
1032 
1033  (void)vircam_qmedsig(work,NULL,(long)npo,3.0,3,-1000.0,65535.0,&val,&junk);
1034  renorm = 100.0/val;
1035  for (i = 0; i < npo; i++)
1036  ocdata[i] = max(0,min(1000,vircam_nint(work[i]*renorm)));
1037 
1038 }
1039 
1040 /*
1041 
1042 $Log: not supported by cvs2svn $
1043 
1044 */
void vircam_qmedsig(float *data, unsigned char *bpm, long npts, float thresh, int niter, float lowv, float highv, float *median, float *sigma)
Definition: vircam_stats.c:542
vir_fits * vircam_fits_wrap(cpl_image *im, vir_fits *model, cpl_propertylist *phu, cpl_propertylist *ehu)
Definition: vircam_fits.c:725
void vircam_fits_delete(vir_fits *p)
Definition: vircam_fits.c:277
vir_fits * vircam_fits_load(cpl_frame *frame, cpl_type type, int nexten)
Definition: vircam_fits.c:80
cpl_propertylist * vircam_fits_get_ehu(vir_fits *p)
Definition: vircam_fits.c:457