#include #include #include #include #include #include #include "qfits.h" #include #include #define NMAX 8192 #define LIM 128 #define D2R M_PI/180.0 #define R2D 180.0/M_PI struct image { int naxis,naxis1,naxis2,nframes; float *zavg,*zstd,*zmax,*znum; double ra0,de0; float x0,y0; float a[2],b[2]; double mjd; float *dt; }; struct transformation { double mjd; double ra0,de0; float a[3],b[3]; float x0,y0; float xrms,yrms,rms; }; struct star { double ra,de; float pmra,pmde; float mag; }; struct catalog { int n; float x[NMAX],y[NMAX],imag[NMAX],fm[NMAX],fb[NMAX],bg[NMAX]; double ra[NMAX],de[NMAX],vmag[NMAX]; double rx[NMAX],ry[NMAX]; float xres[NMAX],yres[NMAX],res[NMAX]; int usage[NMAX]; }; struct image read_fits(char *filename); void forward(double ra0,double de0,double ra,double de,double *x,double *y); void reverse(double ra0,double de0,double x,double y,double *ra,double *de); double gmst(double mjd); double modulo(double x,double y); int fgetline(FILE *file,char *s,int lim); struct catalog match_catalogs(char *pixcat,char *astcat,struct transformation t,struct image img,float rmax,float mmin); void plot_astrometric_catalog(struct transformation t,struct image img,float mmin); void plot_pixel_catalog(char *filename); void lfit2d(float *x,float *y,float *z,int n,float *a); void add_fits_keywords(struct transformation t,char *filename); void modify_fits_keywords(struct transformation t,char *filename); void precess(double mjd0,double ra0,double de0,double mjd,double *ra,double *de); void plot_image(struct image img,struct transformation t,struct catalog c,char *filename,float mmin) { int i; float tr[]={-0.5,1.0,0.0,-0.5,0.0,1.0}; float heat_l[]={0.0,0.2,0.4,0.6,1.0}; float heat_r[]={0.0,0.5,1.0,1.0,1.0}; float heat_g[]={0.0,0.0,0.5,1.0,1.0}; float heat_b[]={0.0,0.0,0.0,0.3,1.0}; float zmin,zmax,zavg,zstd; for (i=0,zavg=0.0;i: FITS file to add/fit WCS to [required]\n"); printf("-r : FITS file with reference WCS [required]\n"); printf("-m : Magnitude cut-off in Tycho-2 catalog [optional; default %.1f]\n",mmin); printf("-R : Radius cut-off for matching [optional; default %.1f pix]\n",rmin); printf("-p Plot image and selected stars [optional]\n"); printf("-a Add WCS keywords to input file (instead of modify) [optional]\n"); printf("-t Track on a fixed RA/Dec (correct for field rotation)\n"); printf("-h Print this help\n"); return; } // Get reference transformation struct transformation reference(char *filename) { struct transformation t; t.mjd=atof(qfits_query_hdr(filename,"MJD-OBS")); t.ra0=atof(qfits_query_hdr(filename,"CRVAL1")); t.de0=atof(qfits_query_hdr(filename,"CRVAL2")); t.x0=atof(qfits_query_hdr(filename,"CRPIX1")); t.y0=atof(qfits_query_hdr(filename,"CRPIX2")); t.a[0]=0.0; t.a[1]=3600.0*atof(qfits_query_hdr(filename,"CD1_1")); t.a[2]=3600.0*atof(qfits_query_hdr(filename,"CD1_2")); t.b[0]=0.0; t.b[1]=3600.0*atof(qfits_query_hdr(filename,"CD2_1")); t.b[2]=3600.0*atof(qfits_query_hdr(filename,"CD2_2")); return t; } void rotate(float theta,float *x,float *y) { float ct,st; float x0,y0; ct=cos(theta*D2R); st=sin(theta*D2R); x0= *x; y0= *y; *x=ct*x0-st*y0; *y=st*x0+ct*y0; return; } int main(int argc,char *argv[]) { int i,j,k,l,m; struct transformation t; struct image img; char *fitsfile=NULL,*reffile=NULL,catfile[128],calfile[128]; FILE *outfile; struct catalog c; float mmin=10.0,rmin=10.0; double mjd0=51544.5,ra0,de0,ra1,de1; float q0,q1; float rmsmin; float x[NMAX],y[NMAX],rx[NMAX],ry[NMAX]; int arg=0,plot=0,add=0,track=0; char *env,starfile[128]; // Environment variables env=getenv("ST_DATADIR"); sprintf(starfile,"%s/data/tycho2.dat",env); // Decode options if (argc>1) { while ((arg=getopt(argc,argv,"f:r:m:R:hpnta"))!=-1) { switch (arg) { case 'f': fitsfile=optarg; break; case 'r': reffile=optarg; break; case 'm': mmin=atof(optarg); break; case 't': track=1; break; case 'R': rmin=atof(optarg); break; case 'p': plot=1; break; case 'a': add=1; break; case 'h': usage(mmin,rmin); return 0; default: usage(mmin,rmin); return 0; } } } else { usage(mmin,rmin); return 0; } // Check if minimum input is provided if (fitsfile==NULL || reffile==NULL) { usage(mmin,rmin); return 0; } // Check this is indeed a FITS file if (is_fits_file(fitsfile)!=1) { printf("%s is not a FITS file\n",fitsfile); return -1 ; } // Check this is indeed a FITS file if (is_fits_file(reffile)!=1) { printf("%s is not a FITS file\n",reffile); return -1 ; } // Read fits file img=read_fits(fitsfile); sprintf(catfile,"%s.cat",fitsfile); sprintf(calfile,"%s.cal",fitsfile); // Read reference transformation t=reference(reffile); // Correct astrometry for fixed or tracked setup if (track==0) { precess(mjd0,t.ra0,t.de0,t.mjd,&ra1,&de1); ra1=modulo(ra1+gmst(img.mjd)-gmst(t.mjd),360.0); precess(img.mjd,ra1,de1,mjd0,&t.ra0,&t.de0); } // Match catalog c=match_catalogs(catfile,starfile,t,img,rmin,mmin); // Plot if (plot==1) plot_image(img,t,c,catfile,mmin); // Do fit if (c.n>10) { for (l=0;l<10;l++) { for (j=0;j<5;j++) { // Transform for (i=0;i2*t.rms) c.usage[i]=0; } } } else { t.xrms=0.0; t.yrms=0.0; t.rms=0.0; } // Print results outfile=fopen(calfile,"w"); for (i=0;i 0 && (c=fgetc(file)) != EOF && c != '\n') s[i++] = c; if (c == '\n') s[i++] = c; s[i] = '\0'; return i; } // Match catalogs struct catalog match_catalogs(char *pixcat,char *astcat,struct transformation t,struct image img,float rmax,float mmin) { int i=0,imin,j,k,np; FILE *file; char line[LIM]; struct star s; double rx,ry,d,dx,dy; int usage[NMAX]; float xp[NMAX],yp[NMAX],mp[NMAX],x,y,fb[NMAX],fm[NMAX],bg[NMAX]; struct catalog c; float r,rmin; // Read pixel catalog file=fopen(pixcat,"r"); if (file==NULL) { printf("pixel catalog not found\n"); exit(-1); } while (fgetline(file,line,LIM)>0) { if (strstr(line,"#")!=NULL) continue; sscanf(line,"%f %f %f %f %f %f",&xp[i],&yp[i],&mp[i],&fb[i],&fm[i],&bg[i]); usage[i]=1; i++; } fclose(file); np=i; // Denominator d=t.a[1]*t.b[2]-t.a[2]*t.b[1]; // Read astrometric catalog file=fopen(astcat,"rb"); if (file==NULL) { printf("astrometric catalog not found\n"); exit(-1); } j=0; while (!feof(file)) { fread(&s,sizeof(struct star),1,file); if (s.mag>mmin) continue; r=acos(sin(t.de0*D2R)*sin(s.de*D2R)+cos(t.de0*D2R)*cos(s.de*D2R)*cos((t.ra0-s.ra)*D2R))*R2D; if (r>90.0) continue; forward(t.ra0,t.de0,s.ra,s.de,&rx,&ry); dx=rx-t.a[0]; dy=ry-t.b[0]; x=(t.b[2]*dx-t.a[2]*dy)/d+t.x0; y=(t.a[1]*dy-t.b[1]*dx)/d+t.y0; // On image if (x>0.0 && x0.0 && ymmin) continue; r=acos(sin(t.de0*D2R)*sin(s.de*D2R)+cos(t.de0*D2R)*cos(s.de*D2R)*cos((t.ra0-s.ra)*D2R))*R2D; if (r>90.0) continue; forward(t.ra0,t.de0,s.ra,s.de,&rx,&ry); x=(t.b[2]*rx-t.a[2]*ry)/d+t.x0; y=(t.a[1]*ry-t.b[1]*rx)/d+t.y0; if (x>0.0 && x0.0 && y0) { if (strstr(line,"#")!=NULL) continue; sscanf(line,"%f %f %f",&x,&y,&mag); cpgpt1(x,y,4); i++; } fclose(file); return; } // Linear 2D fit void lfit2d(float *x,float *y,float *z,int n,float *a) { int i,j,m; double chisq; gsl_matrix *X,*cov; gsl_vector *yy,*w,*c; X=gsl_matrix_alloc(n,3); yy=gsl_vector_alloc(n); w=gsl_vector_alloc(n); c=gsl_vector_alloc(3); cov=gsl_matrix_alloc(3,3); // Fill matrices for(i=0;i360.0) *ra-=360.0; return; }