#include #include #include #include #include "cel.h" #include "cpgplot.h" #include "qfits.h" #define D2R M_PI/180.0 #define R2D 180.0/M_PI #define LIM 128 struct image { char filename[64]; int naxis1,naxis2,naxis3,nframes; float *zavg,*zstd,*zmax,*znum,*zd; int *mask; char nfd[32]; double ra0,de0; float x0,y0; float a[3],b[3],xrms,yrms; double mjd; float *dt,exptime; int cospar; }; struct selection { int state,fit; float x0,y0,x1,y1; float w,zmin; float a,ca,sa,r; float tmid,tmin,tmax,ax[2],sax[2],ay[2],say[2],chi2x,chi2y; }; struct observation { int satno,cospar; char desig[16],conditions,behavior; double mjd,ra,de; float terr,perr,tmid; char nfd[32],pos[32]; int epoch,type; char iod_line[80]; float x[3],y[3]; int state; }; struct track { float x0,y0,x1,y1,texp; int satno; } trk; int iobject=0; 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 nfd2mjd(char *date); double date2mjd(int year,int month,double day); void mjd2date(double mjd,char *date); void dec2sex(double x,char *s,int type); float linear_fit(float x[],float y[],int n,float a[],float sa[]); int fgetline(FILE *file,char *s,int lim); // MJD to DOY double mjd2doy(double mjd,int *yr) { int year,month,k=2; int day; double doy; char nfd[32]; mjd2date(mjd,nfd); sscanf(nfd,"%04d",&year); sscanf(nfd+4,"%02d",&month); sscanf(nfd+6,"%02d",&day); if (year%4==0 && year%400!=0) k=1; doy=floor(275.0*month/9.0)-k*floor((month+9.0)/12.0)+day-30; *yr=year; return doy; } // Reduce point void reduce_point(struct observation *obs,struct image img,float tmid,float x,float y) { int iframe,k; double ra,de,rx,ry; float dx,dy,dt; double mjd; char nfd[32],sra[15],sde[15]; // Transform position dx=x-img.x0; dy=y-img.y0; rx=img.a[0]+img.a[1]*dx+img.a[2]*dy; ry=img.b[0]+img.b[1]*dx+img.b[2]*dy; reverse(img.ra0,img.de0,rx,ry,&ra,&de); dec2sex(ra/15.0,sra,0); dec2sex(de,sde,1); // Get time k=(int) x + img.naxis1*(int) y; iframe=(int) img.znum[k]; if (tmid<0.0) dt=img.dt[iframe]; else dt=tmid; mjd=nfd2mjd(img.nfd)+(double) dt/86400.0; mjd2date(mjd,nfd); // Copy strcpy(obs->nfd,nfd); sprintf(obs->pos,"%s%s",sra,sde); return; } void compute_cuts(float *z,int *mask,int n,float *zmin,float *zmax,float lcut,float hcut) { int i,m; float s1,s2; float avg,std; for (i=0,s1=0.0,s2=0.0,m=0;i1) { // cpgmove(s.x0,s.y0); // cpgdraw(s.x1,s.y1); // } if (s.state==2) { for (i=0;i<5;i++) { if (i==0 || i==4) { dx=-s.w; dy=-s.w; } else if (i==1) { dx=-s.w; dy=s.w; } else if (i==2) { dx=s.w; dy=s.w; } else if (i==3) { dx=s.w; dy=-s.w; } dx=0.0; if (i<2 || i==4) { x=s.ca*dx-s.sa*dy+s.x0; y=s.sa*dx+s.ca*dy+s.y0; } else { x=s.ca*dx-s.sa*dy+s.x1; y=s.sa*dx+s.ca*dy+s.y1; } if (i==0) cpgmove(x,y); else cpgdraw(x,y); } } cpgsci(1); return; } void apply_mask(struct image *img,struct selection s) { int i,j,k; float x,y,dx,dy; for (i=0;inaxis1;i++) { for (j=0;jnaxis2;j++) { k=i+img->naxis1*j; if (img->mask[k]==0) continue; dx=(float) i-s.x0; dy=(float) j-s.y0; x=s.ca*dx+s.sa*dy; y=-s.sa*dx+s.ca*dy; if (x>=0.0 && x<=s.r && y>-s.w && yzmax[k]>s.zmin) { img->mask[k]=1; } else { img->mask[k]=0; } } } return; } void mask_pixel(struct image *img,float x,float y) { int i,j,k,kmin,i0,j0,flag; float r,rmin; i0=(int) x; j0=(int) y; // Find nearest pixel for (i=0,flag=0;inaxis1;i++) { for (j=0;jnaxis2;j++) { k=i+img->naxis1*j; r=sqrt(pow(i-i0,2)+pow(j-j0,2)); if (img->mask[k]==0) continue; if (flag==0 || rmask[kmin]=0; return; } void fit(struct observation *obs,struct image img) { int i,j,k,l,n; float *t,*dt,*x,*y; float tmin,tmax,tmid; float chi2x,chi2y,ax[2],sax[2],ay[2],say[2]; // Count number of points for (i=0,n=0;itmax) tmax=t[i]; } } tmid=0.5*(tmin+tmax); printf("Using points between %.3f and %.3f\n",tmin,tmax); // Shift in time for (i=0;ix[0]=ax[0]; obs->y[0]=ay[0]; obs->x[1]=ax[0]+ax[1]*(tmin-tmid); obs->y[1]=ay[0]+ay[1]*(tmin-tmid); obs->x[2]=ax[0]+ax[1]*(tmax-tmid); obs->y[2]=ay[0]+ay[1]*(tmax-tmid); obs->state=1; // Reduce point reduce_point(obs,img,tmid,ax[0],ay[0]); // Free free(t); free(dt); free(x); free(y); return; } void format_iod_line(struct observation *obs) { int mt,xt,mp,xp; char string[10]; // Time format sprintf(string,"%7.1e",obs->terr); mt=string[0]-'0'; xt=atoi(string+4)+8; // Position format if (obs->type==2) { sprintf(string,"%7.1e",obs->perr); mp=string[0]-'0'; xp=atoi(string+4)+8; } else { printf("Position format not implemented!\n"); } sprintf(obs->iod_line,"%05d %c%c %-6s %04d %c %-17s %d%d %d%d %-14s %d%d %c", obs->satno, obs->desig[0],obs->desig[1], obs->desig+2, obs->cospar, obs->conditions, obs->nfd, mt,xt, obs->type,obs->epoch, obs->pos, mp,xp, obs->behavior); return; } void find_designation(int satno0,char *desig0) { FILE *file; int satno; char desig[16]; char *env,filename[128]; // Environment variables env=getenv("ST_DATADIR"); sprintf(filename,"%s/data/desig.txt",env); file=fopen(filename,"r"); if (file==NULL) { fprintf(stderr,"Designation file not found!\n"); exit(0); } while (!feof(file)) { fscanf(file,"%d %s",&satno,desig); if (satno==satno0) { strcpy(desig0,desig); break; } } fclose(file); return; } void write_observation(struct observation obs) { FILE *file; file=fopen("observations.txt","a"); fprintf(file,"%s\n",obs.iod_line); fclose(file); printf("Observation written\n"); return; } void track(char *fileroot,struct observation obs,struct image *img,float frac) { FILE *file; char line[LIM],filename[LIM]; int flag=0,satno; float x0,y0,x1,y1,texp; int i,j,k,l,k0; int di,dj; float *z; int *wt; float dxdn,dydn,dx,dy; sprintf(filename,"%s.id",fileroot); // Open ID file file=fopen(filename,"r"); if (file==NULL) { fprintf(stderr,"ID file %s not found\n",filename); return; } while (fgetline(file,line,LIM)>0) { sscanf(line,"%s %f %f %f %f %f %d",filename,&x0,&y0,&x1,&y1,&texp,&satno); if (satno==obs.satno) break; } fclose(file); if (satno!=obs.satno) { fprintf(stderr,"Object %d not found\n",obs.satno); return; } dxdn=(x1-x0)/(float) img->nframes; dydn=(y1-y0)/(float) img->nframes; // Allocate z=(float *) malloc(sizeof(float)*img->naxis1*img->naxis2); wt=(int *) malloc(sizeof(int)*img->naxis1*img->naxis2); // Set to zero for (i=0;inaxis1*img->naxis2;i++) { z[i]=0.0; wt[i]=0; } // Loop over frames for (l=0;lnframes;l++) { // Offset dx=dxdn*(l-frac*img->nframes); dy=dydn*(l-frac*img->nframes); // Integer offset di=(int) floor(dx+0.5); dj=(int) floor(dy+0.5); // Set for (i=0;inaxis1;i++) { for (j=0;jnaxis2;j++) { k=i+img->naxis1*j; k0=i+di+img->naxis1*(j+dj); if (i+di>0 && i+dinaxis1 && j+dj>0 && j+djnaxis2) { wt[k]+=1; if (img->znum[k0]==l) z[k]+=img->zmax[k0]; // else // z[k]+=img->zavg[k0]; } } } } // Scale for (i=0;inaxis1*img->naxis2;i++) { if (wt[i]>0) img->zd[i]=z[i]/(float) wt[i]; else img->zd[i]=z[i]; } img->naxis3=5; free(z); free(wt); return; } int autotrack(char *fileroot,struct observation obs,struct image *img) { FILE *file; char line[LIM],filename[LIM]; int flag=0,satno,satno0=0,i=0,n; float x0,y0,x1,y1,texp; int status=0; sprintf(filename,"%s.id",fileroot); // Open ID file file=fopen(filename,"r"); if (file==NULL) { fprintf(stderr,"ID file %s not found\n",filename); return; } while (fgetline(file,line,LIM)>0) { if (strstr(line,"classfd")==NULL) continue; sscanf(line,"%s %f %f %f %f %f %d",filename,&trk.x0,&trk.y0,&trk.x1,&trk.y1,&trk.texp,&trk.satno); if (i==iobject) { status=1; break; } i++; } fclose(file); iobject++; return status; } int main(int argc,char *argv[]) { int i,j,k,l; int iconditions=0,ibehavior=0; struct image img; 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 x,y,frac=0.5; char c; float xmin,xmax,ymin,ymax,zmin,zmax,*z; float width; int redraw=1,layer=2,status; float lcut=4,hcut=6; struct selection s; struct observation obs; char conditions[]="EGFPBT",behavior[]="EFIRSX"; char text[128]; double doy,mjd; int year; char *env; env=getenv("ST_COSPAR"); // Default observation obs.satno=99999; strcpy(obs.desig,"99999U"); obs.cospar=atoi(env); obs.conditions='G'; strcpy(obs.nfd,"YYYYMMDDHHMMSSsss"); obs.terr=0.1; strcpy(obs.pos,"HHMMmmm+DDMMmm"); strcpy(obs.iod_line,""); obs.perr=0.3; obs.epoch=5; obs.type=2; obs.behavior='S'; obs.state=0; // Set track trk.satno=0; // Read image img=read_fits(argv[1]); // Allocate z=(float *) malloc(sizeof(float)*img.naxis1*img.naxis2); // Get fake designation mjd=nfd2mjd(img.nfd); doy=mjd2doy(mjd,&year); sprintf(obs.desig,"%02d%03.0lfA",year-2000,doy+500); cpgopen("/xs"); cpgpap(0.,1.0); cpgask(0); cpgsch(0.8); // Default limits xmin=0.0; xmax=(float) img.naxis1; ymin=0.0; ymax=(float) img.naxis2; width=img.naxis1; // Default selection s.state=0; s.w=10; s.zmin=0; s.fit=0; // Set cospas obs.cospar=img.cospar; for (;;) { if (redraw==1) { cpgeras(); cpgsvp(0.1,0.95,0.1,0.95); cpgwnad(xmin,xmax,ymin,ymax); cpglab("x (pix)","y (pix)"," "); cpgsfs(2); cpgctab (heat_l,heat_r,heat_g,heat_b,5,1.0,0.5); sprintf(text,"UT Date: %.23s COSPAR ID: %04d",img.nfd+1,img.cospar); cpgmtxt("T",6.0,0.0,0.0,text); sprintf(text,"R.A.: %10.5f (%4.1f'') Decl.: %10.5f (%4.1f'')",img.ra0,img.xrms,img.de0,img.yrms); cpgmtxt("T",4.8,0.0,0.0,text); sprintf(text,"FoV: %.2f\\(2218)x%.2f\\(2218) Scale: %.2f''x%.2f'' pix\\u-1\\d",img.naxis1*sqrt(img.a[1]*img.a[1]+img.b[1]*img.b[1])/3600.0,img.naxis2*sqrt(img.a[2]*img.a[2]+img.b[2]*img.b[2])/3600.0,sqrt(img.a[1]*img.a[1]+img.b[1]*img.b[1]),sqrt(img.a[2]*img.a[2]+img.b[2]*img.b[2])); cpgmtxt("T",3.6,0.0,0.0,text); // Apply mask for (i=0;i0.49 && frac<0.51) frac=1.0; else if (frac>0.51) frac=0.0; else if (frac<0.49) frac=0.5; printf("Fraction: %.1f\n",frac); iobject=0; } // Change fraction if (c=='E') { frac+=0.1; if (frac>1.0) frac=0.0; printf("Fraction: %.1f\n",frac); iobject=0; } // Reduce if (c=='M' || c=='D') { reduce_point(&obs,img,frac*img.exptime,x,y); obs.x[0]=x; obs.y[0]=y; obs.state=2; redraw=1; continue; } // Get designation if (c=='d') { printf("Provide satellite number: "); scanf("%d",&obs.satno); find_designation(obs.satno,obs.desig); redraw=1; continue; } // Toggle condition if (c=='C') { iconditions++; if (iconditions>strlen(conditions)-1) iconditions=0; obs.conditions=conditions[iconditions]; redraw=1; continue; } // Toggle behavior if (c=='B') { ibehavior++; if (ibehavior>strlen(behavior)-1) ibehavior=0; obs.behavior=behavior[ibehavior]; redraw=1; continue; } // Reread if (c=='R') { img=read_fits(argv[1]); redraw=1; continue; } // Start if (c=='s' && s.state==0) { s.x0=x; s.y0=y; s.state=1; redraw=1; continue; } // Fit if (c=='F') { fit(&obs,img); redraw=1; continue; } // End if (c=='f' && s.state==1) { s.x1=x; s.y1=y; s.a=atan2(s.y1-s.y0,s.x1-s.x0); s.ca=cos(s.a); s.sa=sin(s.a); s.r=sqrt(pow(s.x0-s.x1,2)+pow(s.y0-s.y1,2)); s.state=2; apply_mask(&img,s); s.zmin=zmin; redraw=1; continue; } // Mask pixel if (c=='X' && s.state!=0) { mask_pixel(&img,x,y); apply_mask(&img,s); redraw=1; continue; } // Change level if (c=='+' || c=='=') { s.zmin+=1.0; apply_mask(&img,s); redraw=1; continue; } if (c=='-') { s.zmin-=1.0; apply_mask(&img,s); redraw=1; continue; } // Mean if (isdigit(c)) { layer=c-'0'-1; redraw=1; continue; } // Adjust cuts if (c=='v') { lcut*=2; hcut*=2; redraw=1; continue; } if (c=='b') { lcut/=2; hcut/=2; if (lcut<0.5) lcut=0.5; if (hcut<0.75) hcut=0.75; redraw=1; continue; } // Center if (c=='c') { xmin=x-0.5*width; xmax=x+0.5*width; ymin=y-0.5*width*img.naxis2/img.naxis1; ymax=y+0.5*width*img.naxis2/img.naxis1; redraw=1; continue; } // Zoom if (c=='z') { width/=2; xmin=x-0.5*width; xmax=x+0.5*width; ymin=y-0.5*width*img.naxis2/img.naxis1; ymax=y+0.5*width*img.naxis2/img.naxis1; redraw=1; continue; } // Unzoom if (c=='x') { width*=2; xmin=x-0.5*width; xmax=x+0.5*width; ymin=y-0.5*width*img.naxis2/img.naxis1; ymax=y+0.5*width*img.naxis2/img.naxis1; redraw=1; continue; } // Reset if (c=='r') { xmin=0.0; xmax=(float) img.naxis1; ymin=0.0; ymax=(float) img.naxis2; width=img.naxis1; lcut=4.0; hcut=6.0; s.state=0; s.fit=0; obs.state=0; redraw=1; continue; } } cpgend(); free(img.zavg); free(img.zstd); free(img.zmax); free(img.znum); free(img.zd); return 0; } // Read fits image struct image read_fits(char *filename) { int i,j,k,l,m; qfitsloader ql; char key[FITS_LINESZ+1]; char val[FITS_LINESZ+1]; struct image img; // Copy filename strcpy(img.filename,filename); // Image size img.naxis1=atoi(qfits_query_hdr(filename,"NAXIS1")); img.naxis2=atoi(qfits_query_hdr(filename,"NAXIS2")); img.naxis3=atoi(qfits_query_hdr(filename,"NAXIS3")); img.nframes=atoi(qfits_query_hdr(filename,"NFRAMES")); // MJD img.mjd=(double) atof(qfits_query_hdr(filename,"MJD-OBS")); strcpy(img.nfd,qfits_query_hdr(filename,"DATE-OBS")); img.exptime=atof(qfits_query_hdr(filename,"EXPTIME")); // COSPAR ID img.cospar=atoi(qfits_query_hdr(filename,"COSPAR")); // Transformation img.mjd=atof(qfits_query_hdr(filename,"MJD-OBS")); img.ra0=atof(qfits_query_hdr(filename,"CRVAL1")); img.de0=atof(qfits_query_hdr(filename,"CRVAL2")); img.x0=atof(qfits_query_hdr(filename,"CRPIX1")); img.y0=atof(qfits_query_hdr(filename,"CRPIX2")); img.a[0]=0.0; img.a[1]=3600.0*atof(qfits_query_hdr(filename,"CD1_1")); img.a[2]=3600.0*atof(qfits_query_hdr(filename,"CD1_2")); img.b[0]=0.0; img.b[1]=3600.0*atof(qfits_query_hdr(filename,"CD2_1")); img.b[2]=3600.0*atof(qfits_query_hdr(filename,"CD2_2")); img.xrms=3600.0*atof(qfits_query_hdr(filename,"CRRES1")); img.yrms=3600.0*atof(qfits_query_hdr(filename,"CRRES2")); // Timestamps img.dt=(float *) malloc(sizeof(float)*img.nframes); for (i=0;i2) year=c-4716; else year=c-4715; day=(int) floor(dday); x=24.0*(dday-day); x=3600.*fabs(x); sec=fmod(x,60.); x=(x-sec)/60.; min=fmod(x,60.); x=(x-min)/60.; hour=x; fsec=1000.0*(sec-floor(sec)); sprintf(date,"%04d%02d%02d%02d%02d%02.0f%03.0f",(int) year,(int) month,(int) day,(int) hour,(int) min,floor(sec),fsec); return; } // Convert Decimal into Sexagesimal void dec2sex(double x,char *s,int type) { int i; double sec,deg,min,fmin; char sign; sign=(x<0 ? '-' : '+'); x=60.*fabs(x); min=fmod(x,60.); x=(x-min)/60.; // deg=fmod(x,60.); deg=x; if (type==0) fmin=1000.0*(min-floor(min)); else fmin=100.0*(min-floor(min)); if (type==0) sprintf(s,"%02.0f%02.0f%03.0f",deg,floor(min),fmin); else sprintf(s,"%c%02.0f%02.0f%02.0f",sign,deg,floor(min),fmin); return; } // Linear least squares fit float linear_fit(float x[],float y[],int n,float a[],float sa[]) { int i; float sum,sumx,sumy,sumxx,sumxy; float w,d,chi2,covar,r; // Compute sums sum=sumx=sumy=sumxx=sumxy=0.; for (i=0;i 0 && (c=fgetc(file)) != EOF && c != '\n') s[i++] = c; if (c == '\t') c=' '; if (c == '\n') s[i++] = c; s[i] = '\0'; return i; }