#include #include #include #include #include "qfits.h" #include #include #include #include #define LIM 192 #define NMAX 256 #define D2R M_PI/180.0 #define R2D 180.0/M_PI struct fourframe { char filename[64]; int naxis1,naxis2,naxis3,nframes; float *zavg,*zstd,*zmax,*znum,*ztrk,*zsig; int *mask; double ra0,de0; float x0,y0; float a[3],b[3],xrms,yrms; double mjd; float *dt,exptime; char nfd[32]; int cospar; }; struct observation { int satno,cospar; char desig[16],conditions,behavior,catalog[32],comment[LIM]; 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],t[3],dxdt,dydt,drdt; int state; }; struct point { float x,y,t; int flag; }; struct fourframe 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); // Linear least squares fit float linear_fit(float x[],float y[],float w[],int n,float a[],float sa[]) { int i; float sum,sumx,sumy,sumxx,sumxy; float d,chi2,covar,r; // Compute sums sum=sumx=sumy=sumxx=sumxy=0.; 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; } // 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; } // Convert Decimal into Sexagesimal void dec2s(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; } // Reduce point void reduce_point(struct observation *obs,struct fourframe 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); dec2s(ra/15.0,sra,0); dec2s(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 fit(struct observation *obs,struct fourframe ff,struct point *p,int np,int flag) { int i,j,k,l,n,m; float *t,*dt,*x,*y,*w; float tmin,tmax,tmid; float chi2x,chi2y,ax[2],sax[2],ay[2],say[2]; float dx,dy,dr,rmsx,rmsy; // Count number of points for (i=0,n=0;itmax) tmax=t[i]; } } tmid=0.5*(tmin+tmax); // Shift in time for (i=0;ix[0]=ax[0]; obs->y[0]=ay[0]; obs->t[0]=tmid; obs->x[1]=ax[0]+ax[1]*(tmin-tmid); obs->y[1]=ay[0]+ay[1]*(tmin-tmid); obs->t[1]=tmin; obs->x[2]=ax[0]+ax[1]*(tmax-tmid); obs->y[2]=ay[0]+ay[1]*(tmax-tmid); obs->t[2]=tmax; obs->state=1; obs->dxdt=(obs->x[2]-obs->x[1])/(obs->t[2]-obs->t[1]); obs->dydt=(obs->y[2]-obs->y[1])/(obs->t[2]-obs->t[1]); obs->drdt=sqrt(obs->dxdt*obs->dxdt+obs->dydt*obs->dydt); // Reduce point reduce_point(obs,ff,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; } // Read a line of maximum length int lim from file FILE into string s int fgetline(FILE *file,char *s,int lim) { int c,i=0; while (--lim > 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; } 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 identify_observation(struct observation *obs,char *fileroot,float drmin,float amin) { FILE *file; float x0,y0,x1,y1,x,y,texp; double mjd; int satno,flag=0,i; char nfd[32],filename[LIM],line[LIM],catalog[LIM]; float dx,dy,dr,dxdt,dydt,drdt,angle,dp; // Open ID file sprintf(filename,"%s.id",fileroot); 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 %s",nfd,&x0,&y0,&x1,&y1,&texp,&satno,catalog); // Predicted pixel rates dxdt=(x1-x0)/texp; dydt=(y1-y0)/texp; drdt=sqrt(dxdt*dxdt+dydt*dydt); x=x0+dxdt*obs->t[0]; y=y0+dydt*obs->t[0]; // Compare dx=x-obs->x[0]; dy=y-obs->y[0]; dr=sqrt(dx*dx+dy*dy); dp=(dxdt*obs->dxdt+dydt*obs->dydt)/(obs->drdt*drdt); if (dp<=1.0) angle=acos(dp)*R2D; else angle=0.0; // Identify if (drsatno=satno; if (strstr(catalog,"classfd.tle")!=NULL) strcpy(obs->catalog,"classfd"); if (strstr(catalog,"inttles.tle")!=NULL) strcpy(obs->catalog,"classfd"); else if (strstr(catalog,"catalog.tle")!=NULL) strcpy(obs->catalog,"catalog"); } } fclose(file); return; } void write_observation(struct observation obs) { FILE *file; char filename[LIM]; sprintf(filename,"%s.dat",obs.catalog); file=fopen(filename,"a"); fprintf(file,"%s\n%s\n",obs.comment,obs.iod_line); fclose(file); return; } void overlay_predictions(char *fitsfile,struct fourframe ff) { float x0,y0,x1,y1,texp; int satno,isch; char filename[LIM],line[LIM],nfd[32],catalog[LIM],text[8]; FILE *file; float t,x,y; cpgqci(&isch); sprintf(filename,"%s.id",fitsfile); // 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 %s",nfd,&x0,&y0,&x1,&y1,&texp,&satno,catalog); if (strstr(catalog,"classfd")!=NULL) cpgsci(4); else if (strstr(catalog,"catalog")!=NULL) cpgsci(0); else if (strstr(catalog,"inttles")!=NULL) cpgsci(3); else if (strstr(catalog,"jsc")!=NULL) cpgsci(5); cpgpt1(x0,y0,17); cpgmove(x0,y0); cpgdraw(x1,y1); // plot text cpgsch(0.65); sprintf(text," %05d",satno); for (t=0.0;t<1.0;t+=0.1) { x=x0+(x1-x0)*t; y=y0+(y1-y0)*t; if (x>0.0 && y>0.0 && xnsel) zsel[ix+nx*iy]++; } } free(c); return; } // RANSAC line finding void ransac(struct point *p,int np,float drmin) { int i=0,j,k,l,m,n,mmax; const gsl_rng_type *T; gsl_rng * r; int i0,i1,i0max,i1max; float ax,bx,ay,by; float dx,dy,dr; // Set up randomizer gsl_rng_env_setup(); T=gsl_rng_default; r=gsl_rng_alloc(T); // Loop over number of lines for (i=1;i<=4;i++) { // Number of iterations for (l=0,mmax=0;l<10000;l++) { // Get random end points for (;;) { i0=(int) (np*gsl_rng_uniform(r)); if (p[i0].flag==0) break; } for (;;) { i1=(int) (np*gsl_rng_uniform(r)); if (p[i1].flag==0) break; } // Linear model ax=(p[i1].x-p[i0].x)/(p[i1].t-p[i0].t); bx=p[i0].x-ax*p[i0].t; ay=(p[i1].y-p[i0].y)/(p[i1].t-p[i0].t); by=p[i0].y-ay*p[i0].t; // Find matches for (k=0,m=0;kmmax) { mmax=m; i0max=i0; i1max=i1; } } // Linear model ax=(p[i1max].x-p[i0max].x)/(p[i1max].t-p[i0max].t); bx=p[i0max].x-ax*p[i0max].t; ay=(p[i1max].y-p[i0max].y)/(p[i1max].t-p[i0max].t); by=p[i0max].y-ay*p[i0max].t; // Find matches for (k=0;k1) { while ((arg=getopt(argc,argv,"f:s:R:r:a:pn:"))!=-1) { switch(arg) { case 'f': fitsfile=optarg; break; case 'p': plot=1; break; case 's': sigma=atof(optarg); break; case 'R': drmin=atof(optarg); break; case 'r': rmin=atof(optarg); break; case 'n': mmin=atoi(optarg); break; default: return 0; break; } } } else { return 0; } printf("# Processing %s\n",fitsfile); // Read ff=read_fits(fitsfile); // Fill mask if (ff.naxis1==720 && ff.naxis2==576) { for (i=0;iff.naxis1-12 || j>ff.naxis2-1 || j<1) ff.mask[k]=0; } } } // Allocate accumulation array zsel=(int *) malloc(sizeof(int)*ff.naxis1*ff.naxis2); for (i=0;i0) np++; // Skip if no points if (np==0) return 0; // Skip if too many points if (np>0.1*ff.naxis1*ff.naxis2) return 0; // Allocate points p=(struct point *) malloc(sizeof(struct point)*np); // Fill for (i=0,l=0;i0) { p[l].x=(float) i; p[l].y=(float) j; p[l].t=ff.dt[(int) ff.znum[k]]; p[l].flag=0; l++; } } } // Random Sample Consensus line finding ransac(p,np,drmin); // Fit lines for (l=1;l<=4;l++) { // Default observation env=getenv("ST_COSPAR"); obs.satno=99999; strcpy(obs.catalog,"unidentified"); 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=' '; obs.state=0; // Count points for (i=0,m=0;i