1
0
Fork 0
sattools/src/reduce.c

1488 lines
32 KiB
C

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <ctype.h>
#include <wcslib/cel.h>
#include <cpgplot.h>
#include "qfits.h"
#define D2R M_PI/180.0
#define R2D 180.0/M_PI
#define LIM 256
struct image {
char filename[64];
int naxis1,naxis2,naxis3,nframes;
float *zavg,*zstd,*zmax,*znum,*zd,*zsig;
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,zmax;
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,tmin,tmax;
char nfd[32],pos[32];
int epoch,type;
char iod_line[80];
float x[3],y[3];
float ax[2],ay[2];
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 dec2s(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);
double gmst(double mjd);
double modulo(double x,double y);
// Find peak
float find_peak(float *z,int kx,int ky,int xmin,int xmax,int ymin,int ymax,float s,int mx,int my,float *x0,float *y0)
{
int i,j,k,l,i0,j0,k0,i1,j1,k1,nx,ny;
int imid,jmid,imax,jmax,flag;
float *d,*g,*w,*h;
float sg,sgg,sgn,den,s1,s2;
float hmax,havg,hstd;
float x,y;
printf("%d %d %d %d -> %d %d\n",xmin,xmax,ymin,ymax,kx,ky);
// Select image
if (xmin<0.0) xmin=0.0;
if (ymin<0.0) ymin=0.0;
if (xmax>=kx) xmax=kx;
if (ymax>=ky) ymax=ky;
nx=(int) (xmax-xmin);
ny=(int) (ymax-ymin);
d=(float *) malloc(sizeof(float)*nx*ny);
for (i=xmin,i0=0;i<xmax;i++,i0++) {
for (j=ymin,j0=0;j<ymax;j++,j0++) {
k=i+kx*j;
k0=i0+nx*j0;
d[k0]=z[k];
}
}
printf("%d %d %d %d -> %d %d\n",xmin,xmax,ymin,ymax,nx,ny);
// Make kernel
g=(float *) malloc(sizeof(float)*mx*my);
for (i=0,imid=mx/2,jmid=my/2,sg=0.0,sgg=0.0;i<mx;i++) {
x=((float) (i-imid))/s;
for (j=0;j<my;j++) {
y=((float) (j-jmid))/s;
k=i+mx*j;
g[k]=exp(-0.5*(x*x+y*y));
sg+=g[k];
sgg+=g[k]*g[k];
}
}
sgn=sg/(float) (mx*my);
den=sgg-sg*sg/(float) (mx*my);
// Compute weights
w=(float *) malloc(sizeof(float)*mx*my);
for (i=0;i<mx;i++) {
for (j=0;j<my;j++) {
k=i+mx*j;
w[k]=(g[k]-sgn)/den;
}
}
// Compute H array
h=(float *) malloc(sizeof(float)*nx*ny);
for (i=0;i<nx;i++) {
for (j=0;j<ny;j++) {
k=i+nx*j;
h[k]=0.0;
for (i0=0;i0<mx;i0++) {
for (j0=0;j0<my;j0++) {
k0=i0+mx*j0;
i1=i+i0-imid;
j1=j+j0-jmid;
// Keep in range
if (i1<0 || i1>=nx || j1<0 || j1>=ny)
continue;
k1=i1+nx*j1;
h[k]+=w[k0]*d[k1];
}
}
h[k]/=(float) (mx*my);
}
}
// Locate maximum
for (i=mx,flag=0;i<nx-mx;i++) {
for (j=my;j<ny-my;j++) {
k=i+nx*j;
if (flag==0) {
imax=i;
jmax=j;
hmax=h[k];
flag=1;
}
if (h[k]>hmax) {
imax=i;
jmax=j;
hmax=h[k];
}
}
}
// Compute mean value
for (i=mx,s1=0.0,s2=0.0;i<nx-mx;i++) {
for (j=my;j<ny-my;j++) {
k=i+nx*j;
s1+=h[k];
s2+=1.0;
}
}
havg=s1/s2;
// Standard deviation
for (i=mx,s1=0.0,s2=0.0;i<nx-mx;i++) {
for (j=my;j<ny-my;j++) {
k=i+nx*j;
s1+=(h[k]-havg)*(h[k]-havg);
s2+=1.0;
}
}
hstd=sqrt(s1/s2);
// Free
free(g);
free(w);
free(h);
free(d);
*x0=imax+xmin+0.5;
*y0=jmax+ymin+0.5;
return (hmax-havg)/hstd;
}
// 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 i,iframe,k;
double ra,de,rx,ry;
float dx,dy,dt;
double mjd,mjd1,dra;
char nfd[32],sra[15],sde[15];
float ax[2],ay[2];
// 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);
// Transform direction
for (i=0;i<2;i++) {
ax[i]=obs->ax[i];
ay[i]=obs->ay[i];
}
obs->ax[1]=(img.a[1]*ax[1]+img.a[2]*ay[1])/3600.0;
obs->ay[1]=(img.b[1]*ax[1]+img.b[2]*ay[1])/3600.0;
// 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);
obs->mjd=mjd;
// Correct for motion
mjd1=img.mjd+0.5*(double) img.exptime/86400.0;
dra=gmst(mjd)-gmst(mjd1);
ra+=dra;
// Get RA/Dec
dec2s(ra/15.0,sra,0);
dec2s(de,sde,1);
obs->ra=ra;
obs->de=de;
// 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;
double s1,s2;
double avg,std;
for (i=0,s1=0.0,s2=0.0,m=0;i<n;i++) {
if (mask[i]==1) {
s1+=z[i];
s2+=z[i]*z[i];
m++;
}
}
avg=s1/(float) m;
std=sqrt(s2/(float) m-avg*avg);
*zmin=(float) (avg-lcut*std);
*zmax=(float) (avg+hcut*std);
return;
}
void plot_selection(struct selection s)
{
int i;
float x,y,dx,dy;
cpgsci(7);
if (s.state==1) {
cpgpt1(s.x0,s.y0,17);
}
// if (s.state>1) {
// 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;i<img->naxis1;i++) {
for (j=0;j<img->naxis2;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 && y<s.w && img->zmax[k]>s.zmin) {
img->mask[k]=1;
} else {
img->mask[k]=0;
}
}
}
return;
}
void apply_mask_sigma(struct image *img,struct selection s)
{
int i,j,k;
float x,y,dx,dy;
for (i=0;i<img->naxis1;i++) {
for (j=0;j<img->naxis2;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 && y<s.w && img->zsig[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;i<img->naxis1;i++) {
for (j=0;j<img->naxis2;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 || r<rmin) {
rmin=r;
kmin=k;
flag=1;
}
}
}
// Mask pixel
img->mask[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;i<img.naxis1*img.naxis2;i++)
if (img.mask[i]==1)
n++;
// Allocate
t=(float *) malloc(sizeof(float)*n);
dt=(float *) malloc(sizeof(float)*n);
x=(float *) malloc(sizeof(float)*n);
y=(float *) malloc(sizeof(float)*n);
// Fill
for (i=0,l=0;i<img.naxis1;i++) {
for (j=0;j<img.naxis2;j++) {
k=i+img.naxis1*j;
if (img.mask[k]==1) {
x[l]=(float) i+0.5;
y[l]=(float) j+0.5;
t[l]=img.dt[(int) img.znum[k]];
l++;
}
}
}
// Find limits in time
for (i=0;i<n;i++) {
if (i==0) {
tmin=t[i];
tmax=t[i];
} else {
if (t[i]<tmin) tmin=t[i];
if (t[i]>tmax) tmax=t[i];
}
}
tmid=0.5*(tmin+tmax);
printf("Using points between %.3f and %.3f\n",tmin,tmax);
// Shift in time
for (i=0;i<n;i++)
dt[i]=t[i]-tmid;
// Fit x-pixel position
chi2x=linear_fit(dt,x,n,ax,sax);
// Fit x-pixel position
chi2y=linear_fit(dt,y,n,ay,say);
printf("x: %6.2f +- %.2f %7.3f +- %.3f %8.2f; %f pix/s\n",ax[0],sax[0],ax[1],sax[1],chi2x,ax[1]/img.nframes*img.exptime);
printf("y: %6.2f +- %.2f %7.3f +- %.3f %8.2f; %f pix/s\n",ay[0],say[0],ay[1],say[1],chi2y,ay[1]/img.nframes*img.exptime);
obs->x[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;
obs->tmin=tmin;
obs->tmax=tmax;
for (i=0;i<2;i++) {
obs->ax[i]=ax[i];
obs->ay[i]=ay[i];
}
// 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;
float w,pa,dt;
file=fopen("observations.txt","a");
fprintf(file,"%s\n",obs.iod_line);
fclose(file);
printf("Observation written\n");
dt=obs.tmax-obs.tmin;
w=sqrt(obs.ax[1]*obs.ax[1]+obs.ay[1]*obs.ay[1])/dt;
pa=atan2(obs.ay[1],obs.ax[1])*R2D;
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);
trk.x0=x0;
trk.y0=y0;
trk.x1=x1;
trk.y1=y1;
trk.satno=satno;
trk.texp=texp;
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;i<img->naxis1*img->naxis2;i++) {
z[i]=0.0;
wt[i]=0;
}
// Loop over frames
for (l=0;l<img->nframes;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;i<img->naxis1;i++) {
for (j=0;j<img->naxis2;j++) {
k=i+img->naxis1*j;
k0=i+di+img->naxis1*(j+dj);
if (i+di>0 && i+di<img->naxis1 && j+dj>0 && j+dj<img->naxis2) {
wt[k]+=1;
if (img->znum[k0]==l)
z[k]+=img->zmax[k0];
// else
// z[k]+=img->zavg[k0];
}
}
}
}
// Scale
for (i=0;i<img->naxis1*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,int cflag)
{
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 -1;
}
while (fgetline(file,line,LIM)>0) {
if (cflag==1 && 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;
float sigma,xa,ya;
FILE *file;
char filename[128];
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);
//cpgpap(7,0.75);
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=5.0;
s.zmax=20.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;i<img.naxis1*img.naxis2;i++) {
if (layer==2) z[i]=img.zmax[i]*img.mask[i];
if (layer==3) z[i]=img.znum[i]*img.mask[i];
if (layer==4) z[i]=img.zd[i]*img.mask[i];
if (layer==5) z[i]=img.zsig[i]*img.mask[i];
}
if (layer==0) compute_cuts(img.zavg,img.mask,img.naxis1*img.naxis2,&zmin,&zmax,lcut,hcut);
if (layer==1) compute_cuts(img.zstd,img.mask,img.naxis1*img.naxis2,&zmin,&zmax,lcut,hcut);
if (layer==2) compute_cuts(img.zmax,img.mask,img.naxis1*img.naxis2,&zmin,&zmax,lcut,hcut);
if (layer==4) compute_cuts(img.zd,img.mask,img.naxis1*img.naxis2,&zmin,&zmax,lcut,hcut);
if (layer==5) {
zmin=s.zmin;
zmax=s.zmax;
}
if (layer==0) cpgimag(img.zavg,img.naxis1,img.naxis2,1,img.naxis1,1,img.naxis2,zmin,zmax,tr);
if (layer==1) cpgimag(img.zstd,img.naxis1,img.naxis2,1,img.naxis1,1,img.naxis2,zmin,zmax,tr);
if (layer==2) cpgimag(z,img.naxis1,img.naxis2,1,img.naxis1,1,img.naxis2,zmin,zmax,tr);
if (layer==3) cpgimag(z,img.naxis1,img.naxis2,1,img.naxis1,1,img.naxis2,0.0,(float) img.nframes,tr);
if (layer==4) cpgimag(z,img.naxis1,img.naxis2,1,img.naxis1,1,img.naxis2,zmin,zmax,tr);
if (layer==5) cpgimag(z,img.naxis1,img.naxis2,1,img.naxis1,1,img.naxis2,zmin,zmax,tr);
cpgbox("BCTSNI",0.,0,"BCTSNI",0.,0);
// Plot fit
if (obs.state==1) {
cpgsci(4);
cpgpt1(obs.x[0],obs.y[0],4);
cpgmove(obs.x[1],obs.y[1]);
cpgdraw(obs.x[2],obs.y[2]);
cpgsci(1);
} else if (obs.state==2) {
cpgsci(4);
cpgpt1(obs.x[0],obs.y[0],4);
cpgsci(1);
}
// Plot selection
if (s.state!=0)
plot_selection(s);
// Plot track
if (trk.satno!=0) {
cpgsci(4);
cpgmove(trk.x0,trk.y0);
cpgdraw(trk.x1,trk.y1);
cpgpt1(frac*(trk.x1-trk.x0)+trk.x0,frac*(trk.y1-trk.y0)+trk.y0,4);
cpgsci(1);
}
format_iod_line(&obs);
cpgmtxt("T",1.0,0.5,0.5,obs.iod_line);
redraw=0;
}
// Get cursor
cpgcurs(&x,&y,&c);
// Log as bad and quit
if (c=='Q') {
sprintf(filename,"%s.bad",argv[1]);
file=fopen(filename,"w");
fclose(file);
break;
}
// Quit
if (c=='q')
break;
// End
if (c=='a') {
status=autotrack(argv[1],obs,&img,0);
if (status==1) {
obs.satno=trk.satno;
find_designation(obs.satno,obs.desig);
track(argv[1],obs,&img,frac);
x=frac*(trk.x1-trk.x0)+trk.x0;
y=frac*(trk.y1-trk.y0)+trk.y0;
width=100;
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;
sigma=find_peak(img.zd,img.naxis1,img.naxis2,(int) xmin,(int) xmax,(int) ymin,(int) ymax,2.0,11,11,&x,&y);
printf("%f %f %f\n",x,y,sigma);
if (sigma>5.0) {
reduce_point(&obs,img,frac*img.exptime,x,y);
obs.x[0]=x;
obs.y[0]=y;
obs.state=2;
}
redraw=1;
layer=4;
}
continue;
}
// Find peak
if (c=='p') {
sigma=find_peak(img.zd,img.naxis1,img.naxis2,(int) xmin,(int) xmax,(int) ymin,(int) ymax,2.0,11,11,&x,&y);
printf("%f %f %f\n",x,y,sigma);
reduce_point(&obs,img,frac*img.exptime,x,y);
obs.x[0]=x;
obs.y[0]=y;
obs.state=2;
redraw=1;
continue;
}
// Track
if (c=='t') {
printf("Provide satellite ID: ");
scanf("%d",&obs.satno);
find_designation(obs.satno,obs.desig);
track(argv[1],obs,&img,frac);
layer=4;
redraw=1;
}
if (c=='\t') {
status=autotrack(argv[1],obs,&img,1);
if (status==1) {
obs.satno=trk.satno;
find_designation(obs.satno,obs.desig);
track(argv[1],obs,&img,frac);
redraw=1;
layer=4;
}
}
// Write obs
if (c=='w') {
write_observation(obs);
continue;
}
// Reduce
if (c=='m') {
reduce_point(&obs,img,-1.0,x,y);
obs.x[0]=x;
obs.y[0]=y;
obs.state=2;
redraw=1;
continue;
}
// Change fraction
if (c=='e') {
if (frac>0.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_sigma(&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.01;
printf("%.4f\n",s.zmin);
apply_mask_sigma(&img,s);
redraw=1;
continue;
}
if (c=='-') {
s.zmin/=1.01;
printf("%.4f\n",s.zmin);
apply_mask_sigma(&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;
}
if (c=='h'){
printf("Reduce Satellite tracks. ");
printf("q Quit\n");
printf("TAB track and stack objects automatically (only classfd sats)\n");
printf("w write IOD observation to observations.txt\n");
printf("M/D measure stack and track position (also middle mouse button)\n");
printf("e change fraction (0.0 to start, 0.5 for medium, 1.0 for the end)\n");
printf("d provide NORAD satellite number\n");
printf("C toggle IOD observing conditions G-Good F-Fair P-Poor B-Bad T-Terrible E-Excellent\n");
printf("B toggle behavior of sat.: F-Flash I-Irregular R-Regular S-Steady X-Uspecified E-Extremely weak\n");
printf("s select start of satellite track\n");
printf("f select end of satellite track\n");
printf("F fit satellite track\n");
printf("+/= Increase level of masking pixels\n");
printf("- Lower level for masking pixels (This does not seem to work)\n");
printf("1 go to the mean pixel value FITS layer\n");
printf("2 go to the FITS standard deviation layer\n");
printf("3 go to the maximum pixel value FITS layer\n");
printf("4 go to the frame number of the maximum pixel value FITS layer\n");
printf("5 go to the stack and track layer (only after 't' or 'TAB')\n");
printf("v lower dynamic range\n");
printf("b increase dynamic range\n");
printf("c center on cursor\n");
printf("z zoom in at cursor\n");
printf("x zoom out at cursor\n");
printf("R/r reset to start\n");
printf("m measure position of pixel\n");
printf("t track & stack, give NORAD satellite number\n");
printf("E change fraction in tenths\n");
printf("X pixel mask (also with mouse scroll wheel)\n");
}
}
cpgend();
free(img.zavg);
free(img.zstd);
free(img.zmax);
free(img.znum);
free(img.zd);
free(img.zsig);
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;i<img.nframes;i++) {
sprintf(key,"DT%04d",i);
//strcpy(val,qfits_query_hdr(filename,key));
// sscanf(val+1,"%f",&img.dt[i]);
img.dt[i]=atof(qfits_query_hdr(filename,key));
}
// Allocate image memory
img.zavg=(float *) malloc(sizeof(float)*img.naxis1*img.naxis2);
img.zstd=(float *) malloc(sizeof(float)*img.naxis1*img.naxis2);
img.zmax=(float *) malloc(sizeof(float)*img.naxis1*img.naxis2);
img.znum=(float *) malloc(sizeof(float)*img.naxis1*img.naxis2);
img.zd=(float *) malloc(sizeof(float)*img.naxis1*img.naxis2);
img.mask=(int *) malloc(sizeof(int)*img.naxis1*img.naxis2);
img.zsig=(float *) malloc(sizeof(float)*img.naxis1*img.naxis2);
for (i=0;i<img.naxis1*img.naxis2;i++)
img.zd[i]=0.0;
// Set parameters
ql.xtnum=0;
ql.ptype=PTYPE_FLOAT;
ql.filename=filename;
// Loop over planes
for (k=0;k<img.naxis3;k++) {
ql.pnum=k;;
// Initialize load
if (qfitsloader_init(&ql) != 0)
printf("Error initializing data loading\n");
// Test load
if (qfits_loadpix(&ql) != 0)
printf("Error loading actual data\n");
// Fill z array
for (i=0,l=0;i<img.naxis1;i++) {
for (j=0;j<img.naxis2;j++) {
if (k==0) img.zavg[l]=ql.fbuf[l];
if (k==1) img.zstd[l]=ql.fbuf[l];
if (k==2) img.zmax[l]=ql.fbuf[l];
if (k==3) img.znum[l]=ql.fbuf[l];
if (k==4) img.zd[l]=ql.fbuf[l];
l++;
}
}
}
// Compute scaled
for (i=0;i<img.naxis1*img.naxis2;i++)
img.mask[i]=1;
// Compute sigma
for (i=0;i<img.naxis1*img.naxis2;i++)
img.zsig[i]=(img.zmax[i]-img.zavg[i])/img.zstd[i];
return img;
}
// Compute Julian Day from Date
double date2mjd(int year,int month,double day)
{
int a,b;
double jd;
if (month<3) {
year--;
month+=12;
}
a=floor(year/100.);
b=2.-a+floor(a/4.);
if (year<1582) b=0;
if (year==1582 && month<10) b=0;
if (year==1582 && month==10 && day<=4) b=0;
jd=floor(365.25*(year+4716))+floor(30.6001*(month+1))+day+b-1524.5;
return jd-2400000.5;
}
// nfd2mjd
double nfd2mjd(char *date)
{
int year,month,day,hour,min;
double mjd,dday;
float sec;
sscanf(date,"'%04d-%02d-%02dT%02d:%02d:%f'",&year,&month,&day,&hour,&min,&sec);
dday=day+hour/24.0+min/1440.0+sec/86400.0;
mjd=date2mjd(year,month,dday);
return mjd;
}
// Compute Date from Julian Day
void mjd2date(double mjd,char *date)
{
double f,jd,dday;
int z,alpha,a,b,c,d,e;
double year,month,day,hour,min;
double sec,x,fsec;
jd=mjd+2400000.5;
jd+=0.5;
z=floor(jd);
f=fmod(jd,1.);
if (z<2299161)
a=z;
else {
alpha=floor((z-1867216.25)/36524.25);
a=z+1+alpha-floor(alpha/4.);
}
b=a+1524;
c=floor((b-122.1)/365.25);
d=floor(365.25*c);
e=floor((b-d)/30.6001);
dday=b-d-floor(30.6001*e)+f;
if (e<14)
month=e-1;
else
month=e-13;
if (month>2)
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=floor(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 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=floor(1000.0*(min-floor(min)));
else
fmin=floor(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<n;i++) {
w=1.0;
sum+=w;
sumx+=x[i]*w;
sumy+=y[i]*w;
sumxx+=x[i]*x[i]*w;
sumxy+=x[i]*y[i]*w;
}
d=sum*sumxx-sumx*sumx;
// Parameters
a[0]=(sumxx*sumy-sumx*sumxy)/d;
a[1]=(sum*sumxy-sumx*sumy)/d;
// Uncertainties
sa[0]=sqrt(sumxx/d);
sa[1]=sqrt(sum/d);
// Chi squared
for (i=0,chi2=0.0;i<n;i++)
chi2+=pow(y[i]-a[0]-a[1]*x[i],2);
// Covariance
covar= -sumx/d;
// Correlation coefficient
r= -sumx/sqrt(sum*sumxx);
return chi2;
}
// 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;
}
// Return x modulo y [0,y)
double modulo(double x,double y)
{
x=fmod(x,y);
if (x<0.0) x+=y;
return x;
}
// Greenwich Mean Sidereal Time
double gmst(double mjd)
{
double t,gmst;
t=(mjd-51544.5)/36525.0;
gmst=modulo(280.46061837+360.98564736629*(mjd-51544.5)+t*t*(0.000387933-t/38710000),360.0);
return gmst;
}