VIRCAM Pipeline 2.3.12
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
43typedef 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
57typedef 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
78typedef 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
87static dstrct *fileptrs = NULL;
88
89static void prov(int interp, casu_fits *file, cpl_frameset *fset);
90static void writewcs(casu_fits *fitsfile, mywcs *o);
91static void average(dstrct *dd, int nextn, float *data, int *cdata,
92 outstrct *outstr, int interp, int conflim);
93static void output_images(int nimages, outstrct *outstr);
94static mywcs *dupwcs(mywcs *in);
95static float distort_corr(double x, double y, mywcs *w);
96static void outloc(mywcs *win, double xin, double yin, mywcs *wout,
97 double *xout, double *yout);
98static 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); */
101static void dstrct_init(int nfiles);
102static void dstrct_extn_init(dstrct *dd, int nhdu);
103static int dstrct_extn_fill_from_plist(dstrct *dd, int extnum,
104 const char *expkey,
105 cpl_propertylist *plist, char *msg);
106static void dstrct_close(int nfiles);
107static void normal(outstrct *o);
108
111/*---------------------------------------------------------------------------*/
165/*---------------------------------------------------------------------------*/
166
167extern 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
484static 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
538static 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
644static 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
744static 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
879static 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
931static 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
1013static 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
1094static 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
1134static 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
1180static 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
1223static 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
1347static 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
1386static 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*/
casu_fits * casu_fits_wrap(cpl_image *im, casu_fits *model, cpl_propertylist *phu, cpl_propertylist *ehu)
Definition: casu_fits.c:883
cpl_image * casu_fits_get_image(casu_fits *p)
Definition: casu_fits.c:436
void casu_fits_delete(casu_fits *p)
Definition: casu_fits.c:364
cpl_propertylist * casu_fits_get_ehu(casu_fits *p)
Definition: casu_fits.c:576
casu_fits * casu_fits_load(cpl_frame *frame, cpl_type type, int nexten)
Definition: casu_fits.c:80
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.