VIRCAM Pipeline  2.3.10
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) 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: 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 <casu_utils.h>
38 #include <casu_stats.h>
39 #include <casu_wcsutils.h>
40 
41 #include "vircam_mods.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, casu_fits *file, cpl_frameset *fset);
90 static void writewcs(casu_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,
104  const char *expkey,
105  cpl_propertylist *plist, char *msg);
106 static void dstrct_close(int nfiles);
107 static void normal(outstrct *o);
108 
111 /*---------------------------------------------------------------------------*/
165 /*---------------------------------------------------------------------------*/
166 
167 extern int vircam_mosaic(cpl_frameset *infiles, cpl_frameset *inconf,
168  int interp, int skyflag, float skywish_in,
169  const char *expkey, int conflim, casu_fits **out,
170  casu_fits **outc, int *status) {
171  cpl_size i,nimages,nconfs;
172  int nerrs,nhdu,j,nstart,nalloc,npts,*cdata,jj,ind1,ind,ii,sczpt;
173  cpl_frame *fr,*frc;
174  outstrct outstr;
175  dstrct *dd;
176  cpl_propertylist *plist1,*plist2;
177  char msg[BUFSIZ];
178  float *alldata,back,noise,skywish,zpt1,exp1,sky1,scalefac,ds,*data,distort;
179  double x,y;
180  cpl_image *im,*cim;
181  casu_fits *ref;
182  const char *fctid="vircam_mosaic";
183 
184  /* Inherited status */
185 
186  *out = NULL;
187  *outc = NULL;
188  if (*status != CASU_OK)
189  return(*status);
190 
191  /* Quick sanity check */
192 
193  nimages = cpl_frameset_get_size(infiles);
194  nconfs = cpl_frameset_get_size(inconf);
195  if (nimages <= 0) {
196  cpl_msg_error(fctid,"No images to combine");
197  FATAL_ERROR
198  }
199  if (nconfs != 1 && nconfs != nimages) {
200  cpl_msg_error(fctid,"Number of conf maps must be 1 or nimages");
201  FATAL_ERROR
202  }
203 
204  /* Get some space for the file descriptors */
205 
206  dstrct_init(nimages);
207 
208  /* Loop through the input files and make sure we can open them all.
209  Compare the data array sizes in each of the extensions to those in
210  the relevant confidence maps. */
211 
212  nerrs = 0;
213  for (i = 0; i < nimages; i++) {
214  dd = fileptrs + i;
215  fr = cpl_frameset_get_position(infiles,i);
216  dd->infile = fr;
217  if (nconfs == 1)
218  frc = cpl_frameset_get_position(inconf,0);
219  else
220  frc = cpl_frameset_get_position(inconf,i);
221  dd->conf = frc;
222 
223  /* Start by checking the number of extensions in each */
224 
225  if (cpl_frame_get_nextensions(fr) != cpl_frame_get_nextensions(frc)) {
226  cpl_msg_error(fctid,"Number of extensions in %s and %s must match",
227  cpl_frame_get_filename(fr),
228  cpl_frame_get_filename(frc));
229  nerrs++;
230  continue;
231  }
232 
233  /* Now loop through each extension. Load both the image and confidence
234  map headers and make sure the image dimensions match */
235 
236  nhdu = (int)cpl_frame_get_nextensions(fr);
237  dstrct_extn_init(dd,nhdu);
238  for (j = 1; j <= nhdu; j++) {
239  plist1 = cpl_propertylist_load(cpl_frame_get_filename(fr),j);
240  if (cpl_error_get_code() != 0) {
241  nerrs++;
242  cpl_msg_error(fctid,"Unable to get header from %s[%d]",
243  cpl_frame_get_filename(fr),j);
244  continue;
245  }
246  plist2 = cpl_propertylist_load(cpl_frame_get_filename(frc),j);
247  if (cpl_error_get_code() != 0) {
248  nerrs++;
249  cpl_msg_error(fctid,"Unable to get header from %s[%d]",
250  cpl_frame_get_filename(frc),j);
251  cpl_propertylist_delete(plist1);
252  continue;
253  }
254  if (cpl_propertylist_get_int(plist1,"NAXIS1") !=
255  cpl_propertylist_get_int(plist2,"NAXIS1") ||
256  cpl_propertylist_get_int(plist1,"NAXIS2") !=
257  cpl_propertylist_get_int(plist2,"NAXIS2")) {
258  nerrs++;
259  cpl_msg_error(fctid,"%s[%d] and %s[%d] image dimensions don't match",
260  cpl_frame_get_filename(fr),j,
261  cpl_frame_get_filename(frc),j);
262  cpl_propertylist_delete(plist1);
263  cpl_propertylist_delete(plist2);
264  continue;
265  }
266 
267  /* Get information from extension headers */
268 
269  if (dstrct_extn_fill_from_plist(dd,j,expkey,plist1,msg) != CASU_OK) {
270  nerrs++;
271  cpl_msg_error(fctid,"Error reading header in %s[%d] -- %s",
272  cpl_frame_get_filename(fr),j,msg);
273  cpl_propertylist_delete(plist1);
274  cpl_propertylist_delete(plist2);
275  continue;
276  }
277  cpl_propertylist_delete(plist1);
278  cpl_propertylist_delete(plist2);
279  }
280  }
281  if (nerrs != 0) {
282  cpl_msg_error(fctid,"%d fatal errors",nerrs);
283  FATAL_ERROR
284  }
285 
286  /* Loop through the files again and get some background stats */
287 
288  for (i = 0; i < nimages; i++) {
289  nstart = 0;
290  nalloc = 0;
291  dd = fileptrs + i;
292  alldata = NULL;
293  for (j = 1; j <= dd->nhdus; j++) {
294 
295  /* Get some space to hold all the data from all extensions */
296 
297  nstart = nalloc;
298  npts = (dd->nx_extn[j-1])*(dd->ny_extn[j-1]);
299  nalloc += npts;
300  alldata = cpl_realloc(alldata,nalloc*sizeof(float));
301 
302  /* Load the current image */
303 
304  im = cpl_image_load(cpl_frame_get_filename(dd->infile),
305  CPL_TYPE_FLOAT,0,j);
306  memmove(alldata+nstart,cpl_image_get_data_float(im),
307  npts*sizeof(float));
308 
309  /* Get the stats for the current image */
310 
311  casu_qmedsig(cpl_image_get_data_float(im),NULL,(long)npts,
312  3.0,3,-1000.0,65535.0,&back,&noise);
313  dd->sky_extn[j-1] = back;
314  cpl_image_delete(im);
315  }
316 
317  /* Get the global background for the whole file */
318 
319  casu_qmedsig(alldata,NULL,(long)nalloc,3.0,3,-1000.0,65535.0,
320  &back,&noise);
321  dd->global_sky = back;
322  dd->global_noise = noise;
323  freespace(alldata);
324  }
325 
326  /* Now adjust some of the background estimates depending on what's been
327  requested */
328 
329  if (skyflag == 2) {
330  skywish = 0.0;
331  for (i = 0; i < nimages; i++)
332  skywish += (fileptrs+i)->global_sky;
333  skywish /= (float)nimages;
334  } else if (skyflag == 1) {
335  skywish = skywish_in;
336  } else {
337  skywish = 0.0;
338  }
339  if (skyflag != 0) {
340  for (i = 0; i < nimages; i++)
341  (fileptrs+i)->global_sky = skywish;
342  }
343 
344  /* Check the magnitude zeropoints. If there are any zeros, then cancel
345  the whole idea of scaling by zeropoint */
346 
347  sczpt = 1;
348  for (i = 0; i < nimages; i++) {
349  dd = fileptrs + i;
350  for (j = 1; j <= dd->nhdus; j++) {
351  if (dd->magzpt_extn[j-1] == 0.0) {
352  sczpt = 0;
353  break;
354  }
355  }
356  if (! sczpt)
357  break;
358  }
359  if (! sczpt)
360  cpl_msg_warning(fctid,"Missing magnitude zeropoint -- no photometric scaling done");
361 
362  /* Finally work out scale factors and sky offsets */
363 
364  zpt1 = fileptrs->magzpt_extn[0];
365  exp1 = fileptrs->exptime;
366  sky1 = fileptrs->global_sky;
367  for (i = 0; i < nimages; i++) {
368  dd = fileptrs + i;
369  for (j = 1; j <= dd->nhdus; j++) {
370  scalefac = (exp1/dd->exptime);
371  if (sczpt)
372  scalefac *= pow(10.0,0.4*(zpt1-dd->magzpt_extn[j-1]));
373  ds = sky1 - scalefac*(dd->global_sky);
374  dd->scalefac[j-1] = scalefac;
375  dd->skydiff[j-1] = ds;
376  }
377  }
378 
379  /* Now work out the dimensions of the output image and create it */
380 
381  output_images((int)nimages,&outstr);
382 
383  /* Loop through each extension now and do the summation */
384 
385  for (i = 0; i < nimages; i++) {
386  dd = fileptrs + i;
387  for (j = 1; j <= dd->nhdus; j++) {
388  im = cpl_image_load(cpl_frame_get_filename(dd->infile),
389  CPL_TYPE_FLOAT,0,(cpl_size)j);
390  data = cpl_image_get_data_float(im);
391  cim = cpl_image_load(cpl_frame_get_filename(dd->conf),
392  CPL_TYPE_INT,0,(cpl_size)j);
393  cdata = cpl_image_get_data_int(cim);
394 
395  /* Modify the data array so that they are all on the same
396  system as the first image. Also take out astrometric
397  distortion */
398 
399  if (skyflag != 0) {
400  for (jj = 0; jj < dd->ny_extn[j-1]; jj++) {
401  ind1 = jj*(dd->nx_extn[j-1]);
402  y = (double)(jj + 1);
403  for (ii = 0; ii < dd->nx_extn[j-1]; ii++) {
404  ind = ind1 + ii;
405  x = (double)(ii + 1);
406  distort = distort_corr(x,y,dd->wcs_extn[j-1]);
407  data[ind] = (data[ind] - dd->sky_extn[j-1])*distort +
408  skywish;
409  }
410  }
411  }
412 
413  /* Now average it in */
414 
415  average(dd,j,data,cdata,&outstr,interp,conflim);
416  cpl_image_delete(im);
417  cpl_image_delete(cim);
418  }
419  }
420 
421  /* Normalise the output maps */
422 
423  normal(&outstr);
424 
425  /* Wrap the result */
426 
427  ref = casu_fits_load(fileptrs->infile,CPL_TYPE_FLOAT,1);
428  *out = casu_fits_wrap(outstr.outim,ref,NULL,NULL);
429  casu_fits_delete(ref);
430  ref = casu_fits_load(fileptrs->conf,CPL_TYPE_INT,1);
431  *outc = casu_fits_wrap(outstr.outcim,ref,NULL,NULL);
432  casu_fits_delete(ref);
433 
434  /* Write the WCS in both */
435 
436  writewcs(*out,outstr.outwcs);
437  writewcs(*outc,outstr.outwcs);
438 
439  /* Write the provenance */
440 
441  prov(interp,*out,infiles);
442  prov(interp,*outc,infiles);
443 
444  /* Add a DRIBBLE keyword */
445 
446  if (interp != 0) {
447  cpl_propertylist_update_string(casu_fits_get_ehu(*out),"DRIBBLE",
448  "bilinear");
449  cpl_propertylist_set_comment(casu_fits_get_ehu(*out),"DRIBBLE",
450  "Interpolation method");
451  }
452 
453  /* Tidy and exit */
454 
455  freespace(outstr.outwcs);
456  cpl_image_delete(outstr.work);
457  dstrct_close(nimages);
458  return(CASU_OK);
459 }
460 
463 /*---------------------------------------------------------------------------*/
482 /*---------------------------------------------------------------------------*/
483 
484 static void prov(int interp, casu_fits *file, cpl_frameset *fset) {
485  int nfset,ncard,i;
486  cpl_propertylist *ehu;
487  char value[81],key[9],comment[81];
488  const char *algorithm[] = {"Nearest-neighbour","Bi-linear interpolation"};
489 
490  /* Start by removing any pre-existing PROV keywords */
491 
492  ehu = casu_fits_get_ehu(file);
493  cpl_propertylist_erase_regexp(ehu,"PROV[0-9]+",0);
494 
495  /* Add the zeroth card */
496 
497  ncard = 0;
498  (void)snprintf(key,9,"PROV%04d",ncard);
499  (void)snprintf(value,81,"File formed from %s of",algorithm[interp]);
500  (void)snprintf(comment,81,"File combination algorithm");
501  cpl_propertylist_update_string(ehu,key,value);
502  cpl_propertylist_set_comment(ehu,key,comment);
503 
504  /* Now add a card for each input file */
505 
506  nfset = cpl_frameset_get_size(fset);
507  for (i = 0; i < nfset; i++) {
508  ncard++;
509  (void)snprintf(key,9,"PROV%04d",ncard);
510  (void)snprintf(value,81,"%s",
511  basename((char *)cpl_frame_get_filename(cpl_frameset_get_position(fset,i))));
512  (void)snprintf(comment,81,"Card # %d",ncard);
513  cpl_propertylist_update_string(ehu,key,value);
514  cpl_propertylist_set_comment(ehu,key,comment);
515  }
516 }
517 
518 /*---------------------------------------------------------------------------*/
536 /*---------------------------------------------------------------------------*/
537 
538 static void writewcs(casu_fits *fitsfile, mywcs *o) {
539  char key[16],sval[16],proj[4];
540  int i,j,n;
541  float val;
542  double dval;
543  cpl_propertylist *ehu;
544 
545  /* Get a convenient reference */
546 
547  ehu = casu_fits_get_ehu(fitsfile);
548  cpl_propertylist_update_int(ehu,"NAXIS1",
549  (int)cpl_image_get_size_x(casu_fits_get_image(fitsfile)));
550  cpl_propertylist_update_int(ehu,"NAXIS2",
551  (int)cpl_image_get_size_y(casu_fits_get_image(fitsfile)));
552 
553  /* Write out CTYPE */
554 
555  if (o->istan)
556  (void)strcpy(proj,"TAN");
557  else
558  (void)strcpy(proj,"ZPN");
559  for (i = 1; i <= 2; i++) {
560  (void)sprintf(key,"CTYPE%d",i);
561  if (i == 1)
562  (void)sprintf(sval,"RA---%s",proj);
563  else
564  (void)sprintf(sval,"DEC--%s",proj);
565  (void)cpl_propertylist_update_string(ehu,key,sval);
566  }
567 
568  /* CRVAL, CRPIX */
569 
570  for (i = 1; i <= 2; i++) {
571  (void)sprintf(key,"CRVAL%d",i);
572  dval = (o->crval[i-1])*DEGRAD;
573  cpl_propertylist_update_double(ehu,key,dval);
574  }
575  for (i = 1; i <= 2; i++) {
576  (void)sprintf(key,"CRPIX%d",i);
577  dval = (o->crpix[i-1]);
578  cpl_propertylist_update_double(ehu,key,dval);
579  }
580 
581  /* CD matrix */
582 
583  n = 0;
584  for (j = 1; j <= 2; j++) {
585  for (i = 1; i <= 2; i++) {
586  (void)sprintf(key,"CD%d_%d",j,i);
587  dval = (o->cd[n])*DEGRAD;
588  cpl_propertylist_update_double(ehu,key,dval);
589  n++;
590  }
591  }
592 
593  /* PV vector */
594 
595  if (! o->istan) {
596  val = (float)(o->pv21);
597  cpl_propertylist_update_float(ehu,"PV2_1",val);
598  val = (float)(o->pv23);
599  cpl_propertylist_update_float(ehu,"PV2_3",val);
600  val = (float)(o->pv25);
601  cpl_propertylist_update_float(ehu,"PV2_5",val);
602  } else {
603  if (cpl_propertylist_has(ehu,"PV2_1"))
604  cpl_propertylist_erase(ehu,"PV2_1");
605  if (cpl_propertylist_has(ehu,"PV2_3"))
606  cpl_propertylist_erase(ehu,"PV2_3");
607  if (cpl_propertylist_has(ehu,"PV2_5"))
608  cpl_propertylist_erase(ehu,"PV2_5");
609  }
610 }
611 
612 /*---------------------------------------------------------------------------*/
642 /*---------------------------------------------------------------------------*/
643 
644 static void average(dstrct *dd, int nextn, float *data, int *cdata,
645  outstrct *outstr, int interp, int conflim) {
646  int i,j,ind1,ind,outind,j_1,j_2,i_1,i_2,jj,ii,ind1o,indo,ixo,iyo;
647  float *odata,*work,wi,wj,scf,fcd,ds;
648  double x_in,y_in,x_out,y_out;
649 
650  /* Set up some convenience variables */
651 
652  odata = cpl_image_get_data_float(outstr->outim);
653  scf = dd->scalefac[nextn-1];
654  ds = dd->skydiff[nextn-1];
655 
656  /* Get some workspace for the sum of the confidence */
657 
658  work = cpl_image_get_data_float(outstr->work);
659 
660  /* Have separate loops for nearest neighbour and interpolation to
661  speed things up */
662 
663  if (interp == 0) {
664  for (j = 0; j < dd->ny_extn[nextn-1]; j++) {
665  ind1 = j*dd->nx_extn[nextn-1];
666  y_in = (double)(j+1);
667  for (i = 0; i < dd->nx_extn[nextn-1]; i++) {
668  ind = ind1 + i;
669  if (cdata[ind] <= conflim)
670  continue;
671  x_in = (double)(i+1);
672  outloc(dd->wcs_extn[nextn-1],x_in,y_in,outstr->outwcs,
673  &x_out,&y_out);
674  ixo = casu_nint(x_out);
675  iyo = casu_nint(y_out);
676  if (ixo < 1 || ixo > outstr->nxo || iyo < 1 ||
677  iyo > outstr->nyo)
678  continue;
679  outind = (iyo-1)*outstr->nxo + ixo - 1;
680  fcd = (float)cdata[ind];
681  odata[outind] += fcd*(data[ind]*scf + ds);
682  work[outind] += fcd;
683  }
684  }
685  } else {
686  for (j = 0; j < dd->ny_extn[nextn-1]; j++) {
687  ind1 = j*dd->nx_extn[nextn-1];
688  y_in = (double)(j+1);
689  for (i = 0; i < dd->nx_extn[nextn-1]; i++) {
690  ind = ind1 + i;
691  if (cdata[ind] <= conflim)
692  continue;
693  x_in = (double)(i+1);
694  outloc(dd->wcs_extn[nextn-1],x_in,y_in,outstr->outwcs,
695  &x_out,&y_out);
696  if (x_out < 1.0 || y_out < 1.0 || x_out >= outstr->nxo || y_out >= outstr->nyo) {
697 /* fprintf(stderr,"%d %d %g %g %g %g\n",i,j,x_in,y_in,x_out,y_out); */
698 
699 /* xytord(dd->wcs_extn,x_in,y_in,&x_out,&y_out); */
700 /* fprintf(stderr,"%g %g***\n",x_out,y_out); */
701 /* exit(1); */
702  continue;
703  }
704  j_1 = (int)y_out;
705  j_2 = j_1 + 1;
706  i_1 = (int)x_out;
707  i_2 = i_1 + 1;
708  fcd = (float)cdata[ind];
709  for (jj = j_1; jj <= j_2; jj++) {
710  wj = 1.0 - fabs(y_out - (double)jj);
711  ind1o = (jj - 1)*outstr->nxo;
712  for (ii = i_1; ii <= i_2; ii++) {
713  indo = ind1o + ii - 1;
714  wi = 1.0 - fabs(x_out - (double)ii);
715  odata[indo] += wi*wj*fcd*(scf*data[ind] + ds);
716  work[indo] += wi*wj*fcd;
717  }
718  }
719  }
720  }
721  }
722 }
723 
724 /*---------------------------------------------------------------------------*/
742 /*---------------------------------------------------------------------------*/
743 
744 static void output_images(int nimages, outstrct *outstr) {
745  double lowerleft[2],upperleft[2],lowerright[2],upperright[2];
746  double xout,yout,xmin,ymin,ra,dec;
747  float *data;
748  int i,*idata,j,nx,ny,ixo,iyo;
749  dstrct *dd;
750  mywcs *refwcs,*curwcs,*outwcs;
751 
752  /* Initialise the corners */
753 
754  lowerleft[0] = 1.0e8;
755  lowerleft[1] = 1.0e8;
756  upperleft[0] = 1.0e8;
757  upperleft[1] = -1.0e8;
758  lowerright[0] = -1.0e8;
759  lowerright[1] = 1.0e8;
760  upperright[0] = -1.0e8;
761  upperright[1] = -1.0e8;
762 
763  /* Loop for all images relative to the first one */
764 
765  refwcs = NULL;
766  for (i = 0; i < nimages; i++) {
767  dd = fileptrs + i;
768 
769  /* Open the image and loop for each hdu */
770 
771  for (j = 1; j <= dd->nhdus; j++) {
772  curwcs = dd->wcs_extn[j-1];
773  if (i == 0 && j == 1) {
774  refwcs = dupwcs(curwcs);
775  refwcs->istan = 1;
776  }
777  nx = dd->nx_extn[j-1];
778  ny = dd->ny_extn[j-1];
779  outloc(curwcs,(double)1.0,(double)1.0,refwcs,&xout,&yout);
780  lowerleft[0] = min(lowerleft[0],xout);
781  lowerleft[1] = min(lowerleft[1],yout);
782  outloc(curwcs,(double)1.0,(double)ny,refwcs,&xout,&yout);
783  upperleft[0] = min(upperleft[0],xout);
784  upperleft[1] = max(upperleft[1],yout);
785  outloc(curwcs,(double)nx,(double)1.0,refwcs,&xout,&yout);
786  lowerright[0] = max(lowerright[0],xout);
787  lowerright[1] = min(lowerright[1],yout);
788  outloc(curwcs,(double)nx,(double)ny,refwcs,&xout,&yout);
789  upperright[0] = max(upperright[0],xout);
790  upperright[1] = max(upperright[1],yout);
791  }
792  }
793 
794  /* Ok, what are the limits? */
795 
796  ixo = casu_nint(max(lowerright[0]-lowerleft[0],
797  upperright[0]-upperleft[0])) + 5;
798  iyo = casu_nint(max(upperright[1]-lowerright[1],
799  upperleft[1]-lowerleft[1])) + 5;
800  xmin = min(lowerleft[0],upperleft[0]);
801  ymin = min(lowerleft[1],lowerright[1]);
802  outstr->nxo = ixo;
803  outstr->nyo = iyo;
804 
805  /* Create the output images and work image. Make sure they are zeroed
806  because they're going to be used in summations */
807 
808  outstr->outim = cpl_image_new((cpl_size)ixo,(cpl_size)iyo,CPL_TYPE_FLOAT);
809  data = cpl_image_get_data_float(outstr->outim);
810  memset(data,0,ixo*iyo*sizeof(float));
811  outstr->work = cpl_image_new((cpl_size)ixo,(cpl_size)iyo,CPL_TYPE_FLOAT);
812  data = cpl_image_get_data_float(outstr->work);
813  memset(data,0,ixo*iyo*sizeof(float));
814  outstr->outcim = cpl_image_new((cpl_size)ixo,(cpl_size)iyo,CPL_TYPE_INT);
815  idata = cpl_image_get_data_int(outstr->outcim);
816  memset(idata,0,ixo*iyo*sizeof(int));
817 
818  /* Update the reference point for the WCS */
819 
820  outwcs = cpl_malloc(sizeof(mywcs));
821  outwcs->crpix[0] = refwcs->crpix[0] - xmin + 1.0;
822  outwcs->crpix[1] = refwcs->crpix[1] - ymin + 1.0;
823  outwcs->crval[0] = refwcs->crval[0];
824  outwcs->crval[1] = refwcs->crval[1];
825  for (i = 0; i < 4; i++)
826  outwcs->cd[i] = refwcs->cd[i];
827  outwcs->pv21 = 1.0;
828  outwcs->pv23 = -0.33333333333;
829  outwcs->pv25 = 0.0;
830  outwcs->nx = ixo;
831  outwcs->ny = iyo;
832  outwcs->istan = 1;
833  outwcs->tand = tan(outwcs->crval[1]);
834  outwcs->secd = 1.0/cos(outwcs->crval[1]);
835  outstr->outwcs = outwcs;
836 
837  /* Now see what the RA,Dec of the centre of the map is and shift the
838  reference point to that place */
839 
840  xout = 0.5*(double)ixo;
841  yout = 0.5*(double)iyo;
842  xytord(outwcs,xout,yout,&ra,&dec);
843  outwcs->crpix[0] = xout;
844  outwcs->crpix[1] = yout;
845  outwcs->crval[0] = ra/DEGRAD;
846  outwcs->crval[1] = dec/DEGRAD;
847  outwcs->tand = tan(outwcs->crval[1]);
848  outwcs->secd = 1.0/cos(outwcs->crval[1]);
849  freespace(refwcs);
850 }
851 
852 /*---------------------------------------------------------------------------*/
877 /*---------------------------------------------------------------------------*/
878 
879 static float distort_corr(double x, double y, mywcs *w) {
880  double xi,xn,r,rprime,drprime_bydr,dc,tanr;
881 
882  xi = (x - w->crpix[0])*(w->cd[0]) + (y - w->crpix[1])*(w->cd[1]);
883  xn = (x - w->crpix[0])*(w->cd[2]) + (y - w->crpix[1])*(w->cd[3]);
884  r = sqrt(xi*xi + xn*xn);
885  if (r == 0.0) {
886  dc = 1.0;
887  } else {
888  if (! w->istan) {
889  rprime = r*w->pv21 + pow(r,(double)3.0)*w->pv23 +
890  pow(r,(double)5.0)*w->pv25;
891  drprime_bydr = w->pv21 + 3.0*pow(r,(double)2.0)*w->pv23 +
892  5.0*pow(r,(double)4.0)*w->pv25;
893  tanr = tan(rprime);
894  dc = tanr*drprime_bydr*(1.0 + tanr*tanr)/r;
895  } else {
896  tanr = tan(r);
897  dc = (1.0 + tanr*tanr)*tanr/r;
898  }
899  }
900  return(dc);
901 }
902 
903 /*---------------------------------------------------------------------------*/
929 /*---------------------------------------------------------------------------*/
930 
931 static void outloc(mywcs *win, double xin, double yin, mywcs *wout,
932  double *xout, double *yout) {
933  double xt,yt,xi,eta,r,rfac,aa,tandec,denom,rp;
934  int i;
935 
936  /* Do the conversion. First to standard coordinates in the frame of
937  the input image */
938 
939  xt = xin - win->crpix[0];
940  yt = yin - win->crpix[1];
941  xi = win->cd[0]*xt + win->cd[1]*yt;
942  eta = win->cd[2]*xt + win->cd[3]*yt;
943  if (! win->istan) {
944  if (fabs(xt) < 1.0e-6 && fabs(yt) < 1.0e-6) {
945  rfac = 1.0;
946  } else {
947  rp = sqrt(xi*xi + eta*eta);
948  r = rp;
949  for (i = 0; i < 3; i++) {
950  rfac = win->pv21 + win->pv23*pow(r,2.0) + win->pv25*pow(r,4.0);
951  r = rp/rfac;
952  }
953  rfac = tan(r)/rp;
954  }
955  } else {
956  rfac = 1.0;
957  }
958  xi *= rfac;
959  eta *= rfac;
960  aa = atan(xi*win->secd/(1.0-eta*win->tand));
961  if (xi != 0.0)
962  tandec = (eta+win->tand)*sin(aa)/(xi*win->secd);
963  else
964  tandec = (eta+win->tand)/(1.0 - eta*win->tand);
965 
966  /* Now form standard coordinates in the frame of the output image */
967 
968  aa += (win->crval[0] - wout->crval[0]);
969  denom = wout->tand*tandec + cos(aa);
970  xi = wout->secd*sin(aa)/denom;
971  eta = (tandec - wout->tand*cos(aa))/denom;
972  if (! wout->istan) {
973  rp = sqrt(xi*xi + eta*eta);
974  r = atan(rp);
975  rfac = wout->pv21 + wout->pv23*pow(rp,2.0) + wout->pv25*pow(rp,4.0);
976  rfac *= r/rp;
977  } else {
978  rfac = 1.0;
979  }
980  xi *= rfac;
981  eta *= rfac;
982  denom = wout->cd[0]*wout->cd[3] - wout->cd[1]*wout->cd[2];
983  *xout = (xi*wout->cd[3] - eta*wout->cd[1])/denom + wout->crpix[0];
984  *yout = (eta*wout->cd[0] - xi*wout->cd[2])/denom + wout->crpix[1];
985 }
986 
987 /*---------------------------------------------------------------------------*/
1011 /*---------------------------------------------------------------------------*/
1012 
1013 static void xytord(mywcs *win, double xin, double yin, double *ra,
1014  double *dec) {
1015  double xt,yt,xi,eta,r,rfac,aa;
1016 
1017  xt = xin - win->crpix[0];
1018  yt = yin - win->crpix[1];
1019  xi = win->cd[0]*xt + win->cd[1]*yt;
1020  eta = win->cd[2]*xt + win->cd[3]*yt;
1021  r = sqrt(xi*xi + eta*eta);
1022  if (! win->istan) {
1023  rfac = win->pv21 + win->pv23*pow(r,2.0) + win->pv25*pow(r,4.0);
1024  r /= rfac;
1025  rfac = win->pv21 + win->pv23*pow(r,2.0) + win->pv25*pow(r,4.0);
1026  xi /= rfac;
1027  eta /= rfac;
1028  } else {
1029  if (r == 0.0)
1030  rfac = 1.0;
1031  else
1032  rfac = tan(r)/r;
1033  xi *= rfac;
1034  eta *= rfac;
1035  }
1036  aa = atan(xi*win->secd/(1.0-eta*win->tand));
1037  *ra = aa + win->crval[0];
1038  if (xi != 0.0) {
1039  *dec = atan((eta + win->tand)*sin(aa)/(xi*win->secd));
1040  } else {
1041  *dec = atan((eta + win->tand)/(1.0 - eta*win->tand));
1042  }
1043  if (*ra > 2.0*CPL_MATH_PI)
1044  *ra -= 2.0*CPL_MATH_PI;
1045  else if (*ra < 0.0)
1046  *ra += 2.0*CPL_MATH_PI;
1047  *ra *= DEGRAD;
1048  *dec *= DEGRAD;
1049 }
1050 
1051 /* static void rdtoxy(mywcs *win, double ra, double dec, double *x, double *y) { */
1052 /* double xi,eta,rra,ddec,denom,rp,rfac; */
1053 
1054 /* rra = ra/DEGRAD - win->crval[0]; */
1055 /* ddec = dec/DEGRAD; */
1056 /* denom = win->tand*tan(ddec) + cos(rra); */
1057 /* xi = win->secd*sin(rra)/denom; */
1058 /* eta = (tan(ddec) - win->tand*cos(rra))/denom; */
1059 /* rp = sqrt(xi*xi + eta*eta); */
1060 /* if (win->istan) { */
1061 /* if (rp == 0) */
1062 /* rfac = 1.0; */
1063 /* else */
1064 /* rfac = atan(rp)/rp; */
1065 /* } else { */
1066 /* rfac = win->pv21 + win->pv23*pow(rp,2.0) + win->pv25*pow(rp,4.0); */
1067 /* } */
1068 /* xi *= rfac; */
1069 /* eta *= rfac; */
1070 /* denom = win->cd[0]*win->cd[3] - win->cd[1]*win->cd[2]; */
1071 /* *x = (xi*win->cd[3] - eta*win->cd[1])/denom + win->crpix[0]; */
1072 /* *y = (eta*win->cd[0] - xi*win->cd[2])/denom + win->crpix[1]; */
1073 /* } */
1074 
1075 /*---------------------------------------------------------------------------*/
1092 /*---------------------------------------------------------------------------*/
1093 
1094 static mywcs *dupwcs(mywcs *in) {
1095  int i;
1096  mywcs *out;
1097 
1098  out = cpl_malloc(sizeof(mywcs));
1099  for (i = 0; i < 2; i++) {
1100  out->crval[i] = in->crval[i];
1101  out->crpix[i] = in->crpix[i];
1102  }
1103  for (i = 0; i < 4; i++)
1104  out->cd[i] = in->cd[i];
1105  out->secd = in->secd;
1106  out->tand = in->tand;
1107  out->pv21 = in->pv21;
1108  out->pv23 = in->pv23;
1109  out->pv25 = in->pv25;
1110  out->nx = in->nx;
1111  out->ny = in->ny;
1112  out->istan = in->istan;
1113  return(out);
1114 }
1115 
1116 /*---------------------------------------------------------------------------*/
1132 /*---------------------------------------------------------------------------*/
1133 
1134 static void dstrct_init(int nfiles) {
1135  int i;
1136  dstrct *dd;
1137 
1138  fileptrs = cpl_malloc(nfiles*sizeof(dstrct));
1139  for (i = 0; i < nfiles; i++) {
1140  dd = fileptrs + i;
1141  dd->infile = NULL;
1142  dd->conf = NULL;
1143  dd->global_sky = 0.0;
1144  dd->global_noise = 0.0;
1145  dd->tpa = 0.0;
1146  dd->tpd = 0.0;
1147  dd->exptime = 0.0;
1148  dd->nhdus = 0;
1149  dd->wcs_extn = NULL;
1150  dd->nx_extn = NULL;
1151  dd->ny_extn = NULL;
1152  dd->magzpt_extn = NULL;
1153  dd->sky_extn = NULL;
1154  dd->cur_extn = 0;
1155  dd->scalefac = NULL;
1156  dd->skydiff = NULL;
1157  }
1158 }
1159 
1160 /*---------------------------------------------------------------------------*/
1178 /*---------------------------------------------------------------------------*/
1179 
1180 static void dstrct_extn_init(dstrct *dd, int nhdu) {
1181  int i;
1182  dd->nhdus = nhdu;
1183  dd->wcs_extn = cpl_malloc(nhdu*sizeof(mywcs *));
1184  for (i = 0; i < nhdu; i++)
1185  dd->wcs_extn[i] = NULL;
1186  dd->nx_extn = cpl_malloc(nhdu*sizeof(int));
1187  dd->ny_extn = cpl_malloc(nhdu*sizeof(int));
1188  dd->magzpt_extn = cpl_malloc(nhdu*sizeof(float));
1189  dd->sky_extn = cpl_malloc(nhdu*sizeof(float));
1190  dd->scalefac = cpl_malloc(nhdu*sizeof(float));
1191  dd->skydiff = cpl_malloc(nhdu*sizeof(float));
1192 }
1193 
1194 /*---------------------------------------------------------------------------*/
1221 /*---------------------------------------------------------------------------*/
1222 
1223 static int dstrct_extn_fill_from_plist(dstrct *dd, int extnum,
1224  const char *expkey,
1225  cpl_propertylist *plist, char *msg) {
1226  mywcs *w;
1227  int i;
1228 
1229  /* Fill in some global parameters when reading the first header */
1230 
1231  if (extnum == 1) {
1232  if (cpl_propertylist_has(plist,"CRVAL1")) {
1233  dd->tpa = cpl_propertylist_get_double(plist,"CRVAL1");
1234  } else {
1235  (void)sprintf(msg,"Missing CRVAL1 in extension %d",extnum);
1236  return(CASU_FATAL);
1237  }
1238  if (cpl_propertylist_has(plist,"CRVAL2")) {
1239  dd->tpd = cpl_propertylist_get_double(plist,"CRVAL2");
1240  } else {
1241  (void)sprintf(msg,"Missing CRVAL2 in extension %d",extnum);
1242  return(CASU_FATAL);
1243  }
1244  if (cpl_propertylist_has(plist,expkey)) {
1245  dd->exptime = cpl_propertylist_get_float(plist,expkey);
1246  } else {
1247  (void)sprintf(msg,"Missing %s in extension %d",expkey,extnum);
1248  return(CASU_FATAL);
1249  }
1250  }
1251 
1252  /* Now some extension specific stuff. Start with the data array size
1253  and mag zeropoint */
1254 
1255  if (cpl_propertylist_has(plist,"NAXIS1")) {
1256  dd->nx_extn[extnum-1] = cpl_propertylist_get_int(plist,"NAXIS1");
1257  } else {
1258  (void)sprintf(msg,"Missing NAXIS1 in extension %d",extnum);
1259  return(CASU_FATAL);
1260  }
1261  if (cpl_propertylist_has(plist,"NAXIS2")) {
1262  dd->ny_extn[extnum-1] = cpl_propertylist_get_int(plist,"NAXIS2");
1263  } else {
1264  (void)sprintf(msg,"Missing NAXIS2 in extension %d",extnum);
1265  return(CASU_FATAL);
1266  }
1267  if (cpl_propertylist_has(plist,"ESO QC MAGZPT")) {
1268  dd->magzpt_extn[extnum-1] = cpl_propertylist_get_float(plist,
1269  "ESO QC MAGZPT");
1270  } else {
1271  (void)sprintf(msg,"Missing ESO QC MAGZPT in extension %d",extnum);
1272  return(CASU_FATAL);
1273  }
1274 
1275  /* Now for the wcs */
1276 
1277  w = cpl_malloc(sizeof(mywcs));
1278  if (strstr(cpl_propertylist_get_string(plist,"CTYPE1"),"TAN") == NULL)
1279  w->istan = 0;
1280  else
1281  w->istan = 1;
1282  w->crval[0] = cpl_propertylist_get_double(plist,"CRVAL1");
1283  w->crval[1] = cpl_propertylist_get_double(plist,"CRVAL2");
1284  w->crpix[0] = cpl_propertylist_get_double(plist,"CRPIX1");
1285  w->crpix[1] = cpl_propertylist_get_double(plist,"CRPIX2");
1286  w->cd[0] = cpl_propertylist_get_double(plist,"CD1_1");
1287  w->cd[1] = cpl_propertylist_get_double(plist,"CD1_2");
1288  w->cd[2] = cpl_propertylist_get_double(plist,"CD2_1");
1289  w->cd[3] = cpl_propertylist_get_double(plist,"CD2_2");
1290  if (! w->istan) {
1291  if (cpl_propertylist_has(plist,"PV2_1"))
1292  w->pv21 = cpl_propertylist_get_double(plist,"PV2_1");
1293  else
1294  w->pv21 = 1.0;
1295  if (cpl_propertylist_has(plist,"PV2_3"))
1296  w->pv23 = cpl_propertylist_get_double(plist,"PV2_3");
1297  else
1298  w->pv23 = -0.3333333333;
1299  if (cpl_propertylist_has(plist,"PV2_5"))
1300  w->pv25 = cpl_propertylist_get_double(plist,"PV2_5");
1301  else
1302  w->pv25 = 0.0;
1303  } else {
1304  w->pv21 = 1.0;
1305  w->pv23 = -0.33333333;
1306  w->pv25 = 0.0;
1307  }
1308  w->nx = dd->nx_extn[extnum-1];
1309  w->ny = dd->ny_extn[extnum-1];
1310 
1311  /* Change angles to radians */
1312 
1313  for (i = 0; i < 2; i++)
1314  w->crval[i] /= DEGRAD;
1315  for (i = 0; i < 4; i++)
1316  w->cd[i] /= DEGRAD;
1317 
1318  /* Add a couple of convenience values */
1319 
1320  w->tand = tan(w->crval[1]);
1321  w->secd = 1.0/cos(w->crval[1]);
1322 
1323  /* Now the store away WCS... */
1324 
1325  dd->wcs_extn[extnum-1] = w;
1326  return(CASU_OK);
1327 }
1328 
1329 /*---------------------------------------------------------------------------*/
1345 /*---------------------------------------------------------------------------*/
1346 
1347 static void dstrct_close(int nfiles) {
1348  int i,j;
1349  dstrct *dd;
1350 
1351  for (i = 0; i < nfiles; i++) {
1352  dd = fileptrs + i;
1353  if (dd->wcs_extn != NULL) {
1354  for (j = 0; j < dd->nhdus; j++)
1355  freespace(dd->wcs_extn[j]);
1356  freespace(dd->wcs_extn);
1357  }
1358  freespace(dd->nx_extn);
1359  freespace(dd->ny_extn);
1360  freespace(dd->magzpt_extn);
1361  freespace(dd->sky_extn);
1362  freespace(dd->scalefac);
1363  freespace(dd->skydiff);
1364  }
1365  freespace(fileptrs);
1366 }
1367 
1368 /*---------------------------------------------------------------------------*/
1384 /*---------------------------------------------------------------------------*/
1385 
1386 static void normal(outstrct *o) {
1387  int npo,i;
1388  float *odata,*work,renorm,val,junk;
1389  int *ocdata;
1390  unsigned char *bpm;
1391 
1392  /* Get some convenience variables */
1393 
1394  npo = o->nxo*o->nyo;
1395  odata = cpl_image_get_data_float(o->outim);
1396  work = cpl_image_get_data_float(o->work);
1397  ocdata = cpl_image_get_data_int(o->outcim);
1398  bpm = cpl_calloc(npo,sizeof(unsigned char));
1399 
1400  /* Normalise the output image */
1401 
1402  for (i = 0; i < npo; i++) {
1403  if (work[i] != 0.0) {
1404  odata[i] /= work[i];
1405  } else {
1406  bpm[i] = 1;
1407  }
1408  }
1409 
1410  /* Work out a mean background that you can use to fill in the blank spots */
1411 
1412  (void)casu_qmedsig(odata,bpm,(long)npo,3.0,3,-1000.0,65535.0,&val,&junk);
1413  for (i = 0; i < npo; i++)
1414  if (bpm[i])
1415  odata[i] = val;
1416 
1417  /* Now normalise the confidence map */
1418 
1419  (void)casu_qmedsig(work,bpm,(long)npo,3.0,3,-1000.0,65535.0,&val,&junk);
1420  renorm = 100.0/val;
1421  for (i = 0; i < npo; i++)
1422  ocdata[i] = max(0,min(1000,casu_nint(work[i]*renorm)));
1423  cpl_free(bpm);
1424 }
1425 
1426 
1427 /*
1428 
1429 $Log: not supported by cvs2svn $
1430 
1431 */
cpl_image * casu_fits_get_image(casu_fits *p)
Definition: casu_fits.c:436
casu_fits * casu_fits_load(cpl_frame *frame, cpl_type type, int nexten)
Definition: casu_fits.c:80
void casu_fits_delete(casu_fits *p)
Definition: casu_fits.c:364
casu_fits * casu_fits_wrap(cpl_image *im, casu_fits *model, cpl_propertylist *phu, cpl_propertylist *ehu)
Definition: casu_fits.c:883
cpl_propertylist * casu_fits_get_ehu(casu_fits *p)
Definition: casu_fits.c:576
void casu_qmedsig(float *data, unsigned char *bpm, long npts, float thresh, int niter, float lowv, float highv, float *median, float *sigma)
Definition: casu_stats.c:258
int vircam_mosaic(cpl_frameset *infiles, cpl_frameset *inconf, int interp, int skyflag, float skywish_in, const char *expkey, int conflim, casu_fits **out, casu_fits **outc, int *status)
Create a vircam mosaic.