diff --git a/README2.md b/README2.md new file mode 100644 index 0000000..8e5dac5 --- /dev/null +++ b/README2.md @@ -0,0 +1,48 @@ +Satellite Tracking Toolkit +========= + +Sattools is a collection of tools to facilitate Photographic and Video satellite tracking. + +Install notes +------------- +* Clone locally the code repository +* Install common dependencies + * gfortran + * gcc + * libpng-dev + * libx11-dev + * libjpeg-dev + * libexif-dev +* Build & install required libraries + * qfits-5.2.0: ftp://ftp.eso.org/pub/qfits/qfits-5.2.0.tar.gz + * pgplot-5.2.2: http://www.astro.caltech.edu/~tjp/pgplot/ + * gsl-1.15: ftp://ftp.gnu.org/gnu/gsl/gsl-1.15.tar.gz + * wcslib-2.9: http://www.epta.eu.org/~bassa/wcslib-2.9.tar +* Run `make` on the sattools folder + +* Helper scripts install_dependencies.sh and install_sattools.sh are available at scripts directory. + You can try run these scripts to install or use them as install guide. + Note that install_dependencies.sh needs to be run with admin privileges (sudo ./install_dependencies.sh). + +* If you re-run install_sattools.sh you should previously rmdir sattools directory or otherwise souces + will not be fetched even if they are not present at that dir + +Run notes +--------- +* You will need to set the following environment variables to run sattools. + These vars are set with default values after running install_sattolls.sh. + `ST_COSPAR` COSPAR number + `ST_DATADIR` path to sattools directory + `ST_TLEDIR` path to TLE directory + `ST_OBSDIR` path to observations directory +* If you have multiple capture devices you will need to add a /etc/udev/rules.d/99-server.rules file to add symlinks and use them to + address a particular camera. Sattools will automatically select the camera that is scheduled for each observation. + You may use a command such as 'udevadm info -a -n /dev/video0' to get your capture device attributes and + use that to create the rules file. + A sample rules file is available as guide in data/ + Note that symlinks to the rules file do not work, the rules file must be modified to suit your needs + and copied to /etc/udev/rules.d/ +* You should install NTP support on the system and configure time/date to automatically + sinchronize to time servers. +* Modify stget.sh for your space-track.org login and password (--post-data='identity=login&password=password') + diff --git a/data/99-server.rules b/data/99-server.rules new file mode 100644 index 0000000..7569b1c --- /dev/null +++ b/data/99-server.rules @@ -0,0 +1,2 @@ +KERNEL=="video[0-9]*", ATTR{name}=="Laptop_Integrated_Webcam_1.3M", SYMLINK+="video-Webcam" +KERNEL=="video[0-9]*", ATTR{name}=="AV TO USB2.0", SYMLINK+="video-S25H" diff --git a/data/cameras.txt b/data/cameras.txt index 1b6fc5b..095afe4 100644 --- a/data/cameras.txt +++ b/data/cameras.txt @@ -1,5 +1,5 @@ # List of available cameras -# Camera mnemonic (Camera/Optics), field width, field height, horiz resolution (neg.to mirror), vert resolution (neg.to mirror), mount type (AltAz/Eq/XY/Fixed), video device +# Camera mnemonic (Camera/Optics), field width, field height, horiz resolution (neg.to mirror), vert resolution (neg.to mirror), mount type (AltAz/Eq/XY/Fixed), video device , Azimuth (for fixed, south is zero), Altitude (for fixed) W50H 7.21 5.31 -720 576 AltAz /dev/video1 W28H 13.10 7.97 D85V 9.97 14.96 diff --git a/data/sites.txt b/data/sites.txt index 1dc9444..41d39a9 100644 --- a/data/sites.txt +++ b/data/sites.txt @@ -66,4 +66,4 @@ 9003 CP -24.6272 -70.4047 2638 Cerro Paranal 9004 LP 28.7622 -17.8775 2396 Isaac Newton 9999 GR 47.348 5.5151 100 Graves -0531 FM -34.8961 -56.1227 30 Fernando Mederos +0899 FM -34.8961 -56.1227 30 Fernando Mederos diff --git a/plotfits.c b/plotfits.c index 7a9b576..45de2c6 100644 --- a/plotfits.c +++ b/plotfits.c @@ -7,11 +7,26 @@ #include "qfits.h" #include #include +#include #define LIM 256 #define D2R M_PI/180.0 #define R2D 180.0/M_PI #define NMAX 4096 +#define MAXPOINTERR 200 // Maximum pointing error (pixels) + // Algorithm will not choose reference stars closer than this amount to any edge (in pixels) + // because matching star may fall outside astrometric field. + // This should change to arcseconds in the future and be used to widen + // the astrometric catalog so that it's scale is grater than that of the imaged catalog just enough + // to be sure it includes all imaged stars even at the worst pointing error. +#define MAXROT 15*D2R // Maximum expected rotation error (radians) +#define MAXSCALERR 1.05 // Expected image to astrometric map scaling error +#define DISTMATCHTOL 6 // Distance tolerance in pixels between matching stars after aplying scale and rotation +#define MAXMAGERR 3 // Expected magnitude error between imaged stars and corresponding astometric catalog stars +#define MAGMATCHTOL 0.75 // Relative magnitude between matching stars tolerance +#define DEFMATCHVALRATIO 0.35 // Default ratio of imaged stars that must fit into astrometric catalog after applying matching transformation (can be adjusted at runtime) +#define AUTOMAGLIM 1 // Automatically set astrometric catalog magnitude limit +#define DEBUG 0 struct star { double ra,de; @@ -50,6 +65,8 @@ double gmst(double mjd); double modulo(double x,double y); void precess(double mjd0,double ra0,double de0,double mjd,double *ra,double *de); double sex2dec(char *s); +float matchvalratio=DEFMATCHVALRATIO; + // Read astrometric catalog struct catalog read_astrometric_catalog(char *filename,float mmin,float sx,float sy,float angle) @@ -65,7 +82,7 @@ struct catalog read_astrometric_catalog(char *filename,float mmin,float sx,float file=fopen(filename,"rb"); if (file==NULL) { - fprintf(stderr,"%s not found!\n",filename); + fprintf(stdout,"%s not found!\n",filename); exit(0); } while (!feof(file)) { @@ -211,12 +228,12 @@ int match_catalogs(struct catalog *cat,struct catalog *ast,float rmax) for (i=0,n=0;in;i++) { for (j=0,flag=0;jn;j++) { if (ast->select[j]!=0) - continue; + continue; r=sqrt(pow(cat->x[i]-ast->x[j],2)+pow(cat->y[i]-ast->y[j],2)); if (flag==0 || r0 + fprintf(stdout,"Try different match.\n"); +#endif + } + else{ + // Either no match was found or this is the first time the routine is launched so + // we calculate reference triangle parameters... + // size=(img.naxis2-error)/2; + size=(img.naxis2-error)/3; + // Compute magnitude average + mave=0; + mmax=0; + mmin=10; + for (i=0;in;i++) { + r=cat->mag[i]; + if(r > mmax) + mmax=r; + if(r < mmin) + mmin=r; + mave+=r; + } + mave/=cat->n; + #if DEBUG>2 + fprintf(stdout,"Image height: %d, Expected error: %f, Ref.Tria.Size: %f\n",img.naxis2,error,size); + #endif + + if(size<0){ + fprintf(stdout,"Warning: Pointing inaccuracy too high\n"); + size=10; + } + #if DEBUG>0 + fprintf(stdout,"Stars in imaged catalog: %d, stars in astrometric catalog: %d.\n", cat->n, ast->n); + fprintf(stdout,"MMin:%2.1f,MMax:%2.1f,MAve.:%2.1f \n",mmin,mmax,mave); + #endif + + triast[0]=0; + triast[1]=0; + triast[2]=0; +#if DEBUG>2 + fprintf(stdout,"Try different triangle. Size: %f\n",size); +#endif + } + + + *nselect=0; + nmatch=0; + // search for candidate triangles satisfying size minimum and stars magnitude, later we can fall back to smaller size if no suitable triangle + // is found +// while((*nselect<3) && (size > 10)){ + while((nmatch<3) && (size > 10)){ +// *nselect=0; + +#if DEBUG>1 + fprintf(stdout,"Looking for triangles with min size %4.0f\n",size); +#endif + // Search candidate for 1st star + + for(s1=tricat[0];(nmatch<3) && (s1 <= cat->n);s1++){ + // discard if outside high magnitude range + r=cat->mag[s1]; + if(r > mave){ +#if DEBUG>2 + fprintf(stdout,"Star %d discarded for high magnitude.\n",s1); +#endif + continue; + } + // discard if too close to any edge + if((cat->x[s1] < error/2) || (cat->x[s1] > (img.naxis1-error/2))){ +#if DEBUG>2 + fprintf(stdout,"Star %d discarded for close to edge.\n",s1); +#endif + continue; + } + if((cat->y[s1] < error/2) || (cat->y[s1] > (img.naxis2-error/2))){ +#if DEBUG>2 + fprintf(stdout,"Star %d discarded for close to edge.\n",s1); +#endif + continue; + } + // s1 is viable candidate for 1st star +#if DEBUG>1 + fprintf(stdout,"Candidate star 1: %d, magnitude: %.1f \n",s1,r); +#endif + tricat[0]=s1; + *nselect=1; + +#if DEBUG>1 + fprintf(stdout,"Looking for 2nd star of triangle.\n"); +#endif + // Search candidate for 2nd star + for(s2=tricat[1];(nmatch<3) && (s2 <= cat->n);s2++){ + // discard candidate if outside magnitude range + r=cat->mag[s2]; + if(r > mave){ +#if DEBUG>2 + fprintf(stdout,"Star %d discarded for high magnitude.\n",s2); +#endif + continue; + } + // discard if too close to any edge + if((cat->x[s2] < error/2) || (cat->x[s2] > (img.naxis1-error/2))){ +#if DEBUG>2 + fprintf(stdout,"Star %d discarded for close to edge.\n",s2); +#endif + continue; + } + if((cat->y[s2] < error/2) || (cat->y[s2] > (img.naxis2-error/2))){ +#if DEBUG>2 + fprintf(stdout,"Star %d discarded for close to edge.\n",s2); +#endif + continue; + } + // discard if too close to star 1 + r=sqrt(pow(cat->x[s2]-cat->x[s1],2)+pow(cat->y[s2]-cat->y[s1],2)); + if(r < size){ +#if DEBUG>2 + fprintf(stdout,"Star %d discarded for close to 1st star.\n",s2); +#endif + continue; + } + // s2 is viable candidate for 2nd star +#if DEBUG>1 + fprintf(stdout,"Candidate star 2: %d, magnitude: %.1f, distance to star 1: %.1f \n",s2,cat->mag[s2],r); +#endif + tricat[1]=s2; + *nselect=2; + +#if DEBUG>1 + fprintf(stdout,"Looking for 3rd star of triangle.\n"); +#endif + // Search candidate for 3rd star beginning from the last candidate found + for(s3=tricat[2];(nmatch<3) && (s3 <= cat->n);s3++){ + // discard candidate if outside magnitude range + r=cat->mag[s3]; + if(r > mave){ +#if DEBUG>2 + fprintf(stdout,"Star %d discarded for high magnitude.\n",s3); +#endif + continue; + } + // discard if too close to any edge + if((cat->x[s3] < error/2) || (cat->x[s3] > (img.naxis1-error/2))){ +#if DEBUG>2 + fprintf(stdout,"Star %d discarded for close to edge.\n",s3); +#endif + continue; + } + if((cat->y[s3] < error/2) || (cat->y[s3] > (img.naxis2-error/2))){ +#if DEBUG>2 + fprintf(stdout,"Star %d discarded for close to edge.\n",s3); +#endif + continue; + } + // discard if too close to star 1 + r=sqrt(pow(cat->x[s3]-cat->x[s1],2)+pow(cat->y[s3]-cat->y[s1],2)); + if(r < size){ +#if DEBUG>2 + fprintf(stdout,"Star %d discarded for close to 1st star.\n",s3); +#endif + continue; + } + // discard if too close to star 2 + r=sqrt(pow(cat->x[s3]-cat->x[s2],2)+pow(cat->y[s3]-cat->y[s2],2)); + if(r < size){ +#if DEBUG>2 + fprintf(stdout,"Star %d discarded for close to 2nd star.\n",s3); +#endif + continue; + } + // s3 is viable candidate for 3rd star +#if DEBUG>1 + fprintf(stdout,"Candidate star 3: %d, magnitude: %.1f, distance to star 2: %.1f \n",s3,cat->mag[s3],r); +#endif + +#if DEBUG>1 + fprintf(stdout,"\n"); + fprintf(stdout,"Reference triangle: %d, %d, %d\n",s1,s2,s3); + fprintf(stdout,"Magnitudes: %f, %f, %f\n",cat->mag[s1],cat->mag[s2],cat->mag[s3]); +#endif + tricat[2]=s3; + *nselect=3; + + // ************************************************************ + // Calibration triangle candidate found! + // now look for matching triangle in astrometric catalog... + // ************************************************************ + + // at this point we have got 3 reference stars forming suitable triangle, will look for matching triangle in astrometric catalog + // will search by testing relative magnitude and relative distance between suspect matching stars + // a scale tolerance is given as a ratio for distances (triangle size) and is assumed as affecting the whole image, + // this tolerance could be high. + // Also a magnitude tolerance is defined as an absolute value, this should not be too high (1..2 magnitudes) + // + // relative distance between stars of astrometric catalog should closely match relative distances between stars of imaged catalog + // a tolerance for this match is given also as a ratio and should be low + // also magnitude difference between stars of matching triangle should closely match magn diff between stars of imaged + // reference triangle, tolerance for this magnitude match should not be high (0.5 magn or so) + + + nmatch=0; + // Search for candidate 1st match star + for(m1=triast[0];((nmatch<3) && (m1<=ast->n));m1++){ + // discard if outside magnitude tolerance + // this tolerance includes magnitude extraction tolerance on sextractor tool + r=fabs(cat->mag[s1] - ast->mag[m1]); + if(r > MAXMAGERR){ +#if DEBUG>2 + fprintf(stdout,"Match 1st star %d discarded for mag. difference.\n",m1); +#endif + continue; + } + r=ast->mag[m1]; + // m1 is viable candidate for match to 1st reference star +#if DEBUG>1 + fprintf(stdout,"Candidate match star 1: %d, magnitude: %.1f \n",m1,r); +#endif + triast[0]=m1; + nmatch=1; + // Calculate some values that will be repeatedly used during match check loop + mag12=cat->mag[s2] - cat->mag[s1]; + dis12=sqrt(pow(cat->x[s2]-cat->x[s1],2)+pow(cat->y[s2]-cat->y[s1],2)); + ang12=atan((cat->y[s2]-cat->y[s1]) / (cat->x[s2]-cat->x[s1])); + if((cat->x[s2]-cat->x[s1]) < 0){ + if(ang12 >= 0) ang12 -= M_PI; + else ang12 += M_PI; + } + // Search candidate for 2nd star + for(m2=triast[1];(nmatch<3) && (m2<=ast->n);m2++){ + // magn difference between ref stars 1 and 2 should be very close to magn diff between matching stars 1 and 2 + // discard if difference is outside match tolerance + if(fabs(mag12 - (ast->mag[m2] - ast->mag[m1])) > MAGMATCHTOL){ +#if DEBUG>2 + fprintf(stdout,"Match 2nd star %d discarded for mag. match tolerance.\n",m2); +#endif + continue; + } + // distance between ref stars 1 and 2 should resemble distance from matching stars 1 and star 2 allowing for + // scale tolerance + d=sqrt(pow(ast->x[m2]-ast->x[m1],2)+pow(ast->y[m2]-ast->y[m1],2)) / dis12; + // discard if distance between m2 and m1 is too far from distance between s2 and s1 + if((d > MAXSCALERR) || (1/d > MAXSCALERR)){ +#if DEBUG>2 + fprintf(stdout,"Match 2nd star %d discarded for distance to 1st match star error.\n",m2); +#endif + continue; + } + // keep scale to later check for coherence with third matching star + // this scale was obtained from distance ratio between ref stars 1 & 2 and match stars 1 & 2 + matchscale=d; +#if DEBUG>1 + fprintf(stdout,"Triangle size match scale: %f.2.\n",matchscale); +#endif + // check angle + d2=atan((ast->y[m2]-ast->y[m1]) / (ast->x[m2]-ast->x[m1])); + if((ast->x[m2]-ast->x[m1]) < 0){ + if(d2 >= 0) d2 -= M_PI; + else d2 += M_PI; + } + if(fabs(d2 - ang12) > MAXROT){ +#if DEBUG>2 + fprintf(stdout,"Match 2nd star %d discarded for rotation error.\n",m2); +#endif + continue; + } + // keep rotation for later checks + // this rotation was obtained from angle between ref stars 1 & 2 and match stars 1 & 2 + matchrot=d2-d; + // m2 is viable candidate for match to 2nd star + r=ast->mag[m2]; +#if DEBUG>1 + fprintf(stdout,"Candidate match star 2: %d, magnitude: %.1f \n",m2,r); +#endif +#if DEBUG>2 + fprintf(stdout,"Angle star 1 to star 2: %f \n",d); + d2=atan((ast->y[m2]-ast->y[m1]) / (ast->x[m2]-ast->x[m1])); + fprintf(stdout,"Angle match 1 to match 2: %f \n",d2); + d=fabs(d - d2); + fprintf(stdout,"Angle error %f \n",d); +#endif + triast[1]=m2; + nmatch=2; + // calculate values that will be used repeatedly + mag13=cat->mag[s3] - cat->mag[s1]; + mag23=cat->mag[s3] - cat->mag[s2]; + cenX=(cat->x[s1] + cat->x[s2] + cat->x[s3]) / 3; + cenY=(cat->y[s1] + cat->y[s2] + cat->y[s3]) / 3; + dis13=matchscale * sqrt(pow(cat->x[s3]-cat->x[s1],2)+pow(cat->y[s3]-cat->y[s1],2)); + dis23=matchscale * sqrt(pow(cat->x[s3]-cat->x[s2],2)+pow(cat->y[s3]-cat->y[s2],2)); + ang13=atan((cat->y[s3]-cat->y[s1]) / (cat->x[s3]-cat->x[s1])); + if((cat->x[s3]-cat->x[s1]) < 0){ + if(ang13 >= 0) ang13 -= M_PI; + else ang13 += M_PI; + } + // Search candidate for 3rd star + for(m3=triast[2];(nmatch<3) && (m3<=ast->n);m3++){ + // discard if magn difference is outside match tolerance + if(fabs(mag13 - (ast->mag[m3] - ast->mag[m1])) > MAGMATCHTOL){ +#if DEBUG>2 + fprintf(stdout,"Match 3rd star %d discarded for mag. match tolerance.\n",m3); +#endif + continue; + } + if(fabs(mag23 - (ast->mag[m3] - ast->mag[m2])) > MAGMATCHTOL){ +#if DEBUG>2 + fprintf(stdout,"Match 3rd star %d discarded for mag. match tolerance.\n",m3); +#endif + continue; + } + + // discard this star if matching triangle center is too far from reference triangle center + // check pointing error along X axis + d=(ast->x[m1] + ast->x[m2] + ast->x[m3]) / 3; + if((d2=fabs(d - cenX)) > error){ +#if DEBUG>2 + fprintf(stdout,"Match 3rd star %d discarded for excesive X pointing error: %f.\n",m3,d2); +#endif + continue; + } + // check pointing error along Y axis + d=(ast->y[m1] + ast->y[m2] + ast->y[m3]) / 3; + if((d2=fabs(d - cenY)) > error){ +#if DEBUG>2 + fprintf(stdout,"Match 3rd star %d discarded for excesive Y pointing error: %f.\n",m3,d2); +#endif + continue; + } + + // scale was fixed when found 2nd match candidate, no different scale error is allowed for 3rd matching star + // discard if distance between m3 and m1 is not very similar to distance between s3 and s1 + d=sqrt(pow(ast->x[m3]-ast->x[m1],2)+pow(ast->y[m3]-ast->y[m1],2)); + if(fabs(d - dis13) > DISTMATCHTOL){ +#if DEBUG>2 + fprintf(stdout,"Match 3rd star %d discarded for distance to 1st match star error: %f against %f.\n",m3,r,d); +#endif + continue; + } + // discard if distance between m3 and m2 is not very similar to distance between s3 and s2 + if(fabs(sqrt(pow(ast->x[m3]-ast->x[m2],2)+pow(ast->y[m3]-ast->y[m2],2)) - dis23) > DISTMATCHTOL){ +#if DEBUG>2 + fprintf(stdout,"Match 3rd star %d discarded for distance to 2nd match star error.\n",m3); +#endif + continue; + } + // check angle + d2=atan((ast->y[m3]-ast->y[m1]) / (ast->x[m3]-ast->x[m1])); + if((ast->x[m3]-ast->x[m1]) < 0){ + if(d2 >= 0) d2 -= M_PI; + else d2 += M_PI; + } + if(fabs(d2 - ang13) > MAXROT){ +#if DEBUG>2 + fprintf(stdout,"Match 3rd star %d discarded for rotation error.\n",m3); +#endif + continue; + } + // m3 is viable candidate for match to 3rd star + r=ast->mag[m3]; +#if DEBUG>1 + fprintf(stdout,"Match found with 3rd match star: %d, magnitude: %.1f \n",m3,r); +#endif +#if DEBUG>0 + fprintf(stdout,"Reference triangle: %d, %d, %d\n",s1,s2,s3); + fprintf(stdout,"Match found with stars: %d, %d, %d\n",m1,m2,m3); +#endif + triast[2]=m3; + + // ************************************************************************************************************ + // At this point a viable candidate triangle is found to match the selected reference triangle + // will try to validate this candidate by calculating the tranformation between the ref triangle and this candidate + // We will need to calculate scale, rotation and traslation + + end_t=clock(); +#if DEBUG>1 + fprintf(stdout,"\n"); + fprintf(stdout,"Match triangle found: %d,%d,%d\n",m1,m2,m3); + fprintf(stdout,"Magnitudes: %f, %f, %f\n",ast->mag[m1],ast->mag[m2],ast->mag[m3]); + fprintf(stdout,"Reference triangle: %d, %d, %d\n",s1,s2,s3); + fprintf(stdout,"Magnitudes: %f, %f, %f\n",cat->mag[s1],cat->mag[s2],cat->mag[s3]); + + d=(float)(end_t - start_t)/CLOCKS_PER_SEC; + fprintf(stdout,"Seconds elapsed: %f\n",d); +#endif + start_t=clock(); + + // Scale transformation calculation + // scaling from ref 1-2 to match 1-2 was previously calculated in matchscale, now we average with + // ref 2-3 to match 2-3 and ref 3-1 to match 3-1 + r=sqrt(pow(cat->x[s3]-cat->x[s2],2)+pow(cat->y[s3]-cat->y[s2],2)); + d=sqrt(pow(ast->x[m3]-ast->x[m2],2)+pow(ast->y[m3]-ast->y[m2],2)) / r; + matchscale += d; + r=sqrt(pow(cat->x[s1]-cat->x[s3],2)+pow(cat->y[s1]-cat->y[s3],2)); + d=sqrt(pow(ast->x[m1]-ast->x[m3],2)+pow(ast->y[m1]-ast->y[m3],2)) / r; + matchscale += d; + matchscale /= 3; + + // Rotation calculation + // matchrot was obtained from angle between ref stars 1-2 and match stars 1-2 + // now average with angle ref 2-3 to match 2-3 and angle ref 3-1 to match 3-1 + d2=atan((ast->y[m2]-ast->y[m1]) / (ast->x[m2]-ast->x[m1])); + if((ast->x[m2]-ast->x[m1]) < 0){ + if(d2 >= 0) d2 -= M_PI; + else d2 += M_PI; + } + matchrot = d2-ang12; + d=atan((cat->y[s3]-cat->y[s2]) / (cat->x[s3]-cat->x[s2])); + if((cat->x[s3]-cat->x[s2]) < 0){ + if(d >= 0) d -= M_PI; + else d += M_PI; + } + d2=atan((ast->y[m3]-ast->y[m2]) / (ast->x[m3]-ast->x[m2])); + if((ast->x[m3]-ast->x[m2]) < 0){ + if(d2 >= 0) d2 -= M_PI; + else d2 += M_PI; + } + matchrot += d2-d; + d=atan((cat->y[s1]-cat->y[s3]) / (cat->x[s1]-cat->x[s3])); + if((cat->x[s1]-cat->x[s3]) < 0){ + if(d >= 0) d -= M_PI; + else d += M_PI; + } + d2=atan((ast->y[m1]-ast->y[m3]) / (ast->x[m1]-ast->x[m3])); + if((ast->x[m1]-ast->x[m3]) < 0){ + if(d2 >= 0) d2 -= M_PI; + else d2 += M_PI; + } + matchrot += d2-d; + matchrot /= 3; + + // traslation calculation + // we apply averaged matchscale and matchrotation to reference stars and then + // average reference1 to match1 vector, ref2 to match2 vector and ref3 to match3 vector + r=sqrt(pow(cat->x[s1],2)+pow(cat->y[s1],2)); + d=atan(cat->y[s1] / cat->x[s1]); + r *= matchscale; + d += matchrot; + matchXtras = ast->x[m1] - r*cos(d); + matchYtras = ast->y[m1] - r*sin(d); + r=sqrt(pow(cat->x[s2],2)+pow(cat->y[s2],2)); + d=atan(cat->y[s2] / cat->x[s2]); + r *= matchscale; + d += matchrot; + matchXtras += ast->x[m2] - r*cos(d); + matchYtras += ast->y[m2] - r*sin(d); + r=sqrt(pow(cat->x[s3],2)+pow(cat->y[s3],2)); + d=atan(cat->y[s3] / cat->x[s3]); + r *= matchscale; + d += matchrot; + matchXtras += ast->x[m3] - r*cos(d); + matchYtras += ast->y[m3] - r*sin(d); + matchXtras /= 3; + matchYtras /= 3; + +#if DEBUG>1 + fprintf(stdout,"Transformation:\nScale: %f\nRotation: %f\nXTraslat: %f\nYTraslat: %f\n",matchscale,matchrot,matchXtras,matchYtras); +#endif + + // At this point we've determined the transformation function to convert our reference triangle in the image + // to a matching triangle in the astrometric catalog + // Now it's time to check if this tranformation effectively maps our imaged stars catalog into the astrometric catalog + // For this we apply the tranformation to every bright star in the imaged catalog and accumulate success count when + // a matching star is found in the astrometric catalog. This count is later used for validation. + n=0; + n2=0; +// d2=(mmin+mave)/2; +// d2=(mmax+mave)/2; + d2=mave; + for(i=0;i<=cat->n;i++){ + // skip faint stars from the match check + if(cat->mag[i] > d2) continue; + r=sqrt(pow(cat->x[i],2)+pow(cat->y[i],2)); + d=atan(cat->y[i] / cat->x[i]); + r *= matchscale; + d += matchrot; + x=r*cos(d) + matchXtras; + y=r*sin(d) + matchYtras; + n2++; // this star counts as a checked star + for(j=0;j<=ast->n;j++){ + // skip also faint stars from map + if(ast->mag[j] > (d2 + MAXMAGERR)) continue; + if((fabs(ast->x[j] - x) < DISTMATCHTOL) && (fabs(ast->y[j] - y) < DISTMATCHTOL)){ + n++; + break; + } + } + } + if(n < n2*matchvalratio){ +#if DEBUG>0 + fprintf(stdout,"Match discarded for insufficient match number: %d out of %d checked stars\n",n,n2); +#endif +// if(m1==101 && m2==80 && m3==87){ +// end_t=clock(); +// fprintf(stdout,"Special match triangle was discarded, halting...\n"); +// nmatch=3; +// } + + continue; + } + fprintf(stdout,"Match count: %d out of %d checked stars\n",n,n2); + nmatch=3; + } + // if no match found next try will search again for all possible 3rd match stars + if(nmatch<3) triast[2]=0; + } + // if no match found next try will search again for all possible 2nd match stars + if(nmatch<3) triast[1]=0; + } + if(nmatch<3){ + triast[0]=0; + // if no match was found for this ref triangle continue looking for ref triangles + // next try with following 3rd star + *nselect=2; +#if DEBUG>1 + fprintf(stdout,"No match found for this triangle\n"); +#endif + } + } + // if no triangle selected we will try next 2nd star and try again all possible 3rd stars + if(nmatch<3){ + tricat[2]=0; + *nselect=1; +#if DEBUG>2 + fprintf(stdout,"Try next 3rd star.\n"); +#endif + } + } + // if no triangle selected we will try next 1st star and try again all possible 2nd stars + if(nmatch<3){ + tricat[1]=0; + *nselect=0; +#if DEBUG>2 + fprintf(stdout,"Try next 2nd star.\n"); +#endif + } + } + // at this point either found 3 candidate stars or already tried all candidate stars without success + // if loop continues will look for smaller triangles, accept higher magnitude stars and + // accept lower match ratio for next iteration + if(nmatch<3){ + size/=1.25; + mave+=0.25; + // relax match constraint + matchvalratio/=1.25; + tricat[0]=0; +#if DEBUG>0 + fprintf(stdout,"Catalog completely parsed with no suitable reference triangle found. Decrasing minimum size, increase max magnitude for next search.\n"); +#endif + } + } + // if we could not find suitable triplet erase triange in catalog tricat[] + if(nmatch<3){ + tricat[0]=0; + tricat[1]=0; + tricat[2]=0; +#if DEBUG>0 + fprintf(stdout,"Did not find any suitable reference triangle.\n"); +#endif + } + return; +} + + int main(int argc,char *argv[]) { int i; @@ -298,6 +907,7 @@ int main(int argc,char *argv[]) int nx,ny; FILE *file; char *env,starfile[128]; + int tricat[3],triast[3],n; // Environment variables env=getenv("ST_DATADIR"); @@ -324,7 +934,7 @@ int main(int argc,char *argv[]) } else { file=fopen("position.txt","r"); if (file==NULL) { - fprintf(stderr,"No position file found\n"); + fprintf(stdout,"No position file found\n"); return 0; } fscanf(file,"%s %s",sra,sde); @@ -344,17 +954,17 @@ int main(int argc,char *argv[]) if (file==NULL) { sx=-36.15; sy=33.22; - fprintf(stderr,"No camera file found, using default pixel scale values %3.2f %3.2f\n",sx,sy); + fprintf(stdout,"No camera file found, using default pixel scale values %3.2f %3.2f\n",sx,sy); } else{ // Obtain FOV and image resolution from camera file - fscanf(file,"%s %f %f %d %d %s",cam,&fw,&fh,&nx,&ny,mount); + fscanf(file,"%s %f %f %d %d %s",cam,&fh,&fw,&nx,&ny,mount); fclose(file); sx=fw/nx*3600; sy=fh/ny*3600; // Check scheduled camera resolution against FITS image file resolution if((abs(nx)!=img.naxis1) || (abs(ny)!=img.naxis2)){ - fprintf(stderr,"Warning: scheduled camera resolution %dx%d does not match image resolution %dx%d",nx,ny,img.naxis1,img.naxis2); + fprintf(stdout,"Warning: scheduled camera resolution %dx%d does not match image resolution %dx%d\n",nx,ny,img.naxis1,img.naxis2); } } @@ -365,6 +975,20 @@ int main(int argc,char *argv[]) // Read catalogs cat=read_pixel_catalog(filename); ast=read_astrometric_catalog(starfile,mag,sx,sy,-q); + + // Adjust magnitude limit if configured for so + if (AUTOMAGLIM){ + while (ast.n > cat.n){ + mag -= 0.5; + ast=read_astrometric_catalog(starfile,mag,sx,sy,-q); + } + while (ast.n < cat.n){ + mag += 0.25; + ast=read_astrometric_catalog(starfile,mag,sx,sy,-q); + } + fprintf(stdout,"Astrometric map magnitude limit: %2.2f\n",mag); + fprintf(stdout,"Stars in map: %d, extracted imaged stars: %d\n",ast.n,cat.n); + } // Open PGPlot server cpgopen("/xs"); @@ -395,26 +1019,65 @@ int main(int argc,char *argv[]) cpgctab (heat_l,heat_r,heat_g,heat_b,5,1.0,0.5); cpgimag(img.z,img.naxis1,img.naxis2,1,img.naxis1,1,img.naxis2,img.zmin,img.zmax,tr); cpgbox("BCTSNI",0.,0,"BCTSNI",0.,0); - + + + // Plot triangle of calibration stars + if(nselect>=2){ + // imaged catalog + cpgmove(cat.x[tricat[0]],cat.y[tricat[0]]); +#if DEBUG>1 + fprintf(stdout,"\nRef.triangle: "); + fprintf(stdout,"%d, ",tricat[0]); +#endif + for(i=1;(i<3 && i1 + fprintf(stdout,"%d, ",tricat[i]); +#endif + } + cpgdraw(cat.x[tricat[0]],cat.y[tricat[0]]); + // astrometric catalog + if(triast[2]>0){ + cpgmove(ast.x[triast[0]],ast.y[triast[0]]); +#if DEBUG>1 + fprintf(stdout,"\nMatch triangle: "); + fprintf(stdout,"%d, ",triast[0]); +#endif + for(i=1;(i<3 && i1 + fprintf(stdout,"%d, ",triast[i]); +#endif + } + cpgdraw(ast.x[triast[0]],ast.y[triast[0]]); + } + } + fflush(stdout); + // Plot catalogs if (plotstars==1) { - cpgsci(3); - for (i=0;i=3) { fit_transformation(cat,ast,nselect); ast=reread_astrometric_catalog(starfile,mag+1); + for (i=0;i=3) && (triast[2] > 0)){ + // erase prior selection first + for (i=0;i=3) { + tricat[0]=0; + triast[0]=0; + tricat[1]=0; + triast[1]=0; + tricat[2]=0; + triast[2]=-1; + nselect=0; + redraw=1; + } + // Plot identified stars if (c=='p') { if (plotstars==1) - plotstars=0; + plotstars=0; else if (plotstars==0) - plotstars=1; + plotstars=1; redraw=1; } // Match catalogs if (c=='m') { - nselect=match_catalogs(&cat,&ast,10.0); + match_catalogs(&cat,&ast,10.0); redraw=1; } @@ -493,7 +1240,7 @@ int main(int argc,char *argv[]) } // Zoom - if (c=='z' || c=='+' || c=='=') { + if (c=='z') { width/=1.25; xmin=x-0.5*width; xmax=x+0.5*width; @@ -504,7 +1251,7 @@ int main(int argc,char *argv[]) } // Unzoom - if (c=='x' || c=='-') { + if (c=='x') { width*=1.25; xmin=x-0.5*width; xmax=x+0.5*width; @@ -514,21 +1261,46 @@ int main(int argc,char *argv[]) continue; } + // More astrometric map stars + if (c=='+' || c=='=') { + mag += 0.25; + fprintf(stdout,"Astrometric map magnitude limit: %2.2f\n",mag); + ast=read_astrometric_catalog(starfile,mag,sx,sy,-q); + fprintf(stdout,"Stars in map: %d, extracted imaged stars: %d\n",ast.n,cat.n); + redraw=1; + continue; + } + + // Less astrometric map stars + if (c=='-') { + mag -= 0.25; + fprintf(stdout,"Astrometric map magnitude limit: %2.2f\n",mag); + ast=read_astrometric_catalog(starfile,mag,sx,sy,-q); + fprintf(stdout,"Stars in map: %d, extracted imaged stars: %d\n",ast.n,cat.n); + redraw=1; + continue; + } + // Help if (c=='h') { - printf("Calibrates astrometry. Initially requires manual matching of at least three stars. Use 'a' to select star on the image, then 'b' to select star from the catalog, then 'f' to fit"); + printf("Calibrates astrometry.\nRequires matching of at least three stars. Use 'i' repeatedly for automatic selection of matching sets or 'a' to manually select a star from the image and 'b' to select the corresponding star from the catalog (tree sets needed). Then use 'f' to check fit, 'R' to start again.\nFinish with 'm' to match stars and 'q' writes calibration output\n"); printf("q Quit\n"); printf("a Select star on image\n"); printf("b Select star from catalog\n"); + printf("i Autoselect calibration stars from catalog\n"); + printf("I Reset calibration stars selection\n"); + printf("S Save calibration params. to cal.dat\n"); printf("c Center image on pixel\n"); printf("f Fit calibration\n"); printf("m Match stars using current calibration\n"); - printf("z/+ Zoom in on cursor\n"); - printf("x/- Zoom out on cursor\n"); + printf("z/x Zoom in/out on cursor\n"); + printf("+/- Increase/decrease astrometric map stars\n"); printf("p Plot sextractor catalog\n"); printf("r Reset zoom\n"); - + printf("R Reset fit\n"); } + redraw=1; + continue; } cpgend(); @@ -731,7 +1503,7 @@ struct catalog read_pixel_catalog(char *filename) // Read catalog file=fopen(filename,"r"); if (file==NULL) { - fprintf(stderr,"%s not found!\n",filename); + fprintf(stdout,"%s not found!\n",filename); exit(0); } while (fgetline(file,line,LIM)>0) { diff --git a/pnmenc.patch b/pnmenc.patch new file mode 100644 index 0000000..d6d4e38 --- /dev/null +++ b/pnmenc.patch @@ -0,0 +1,34 @@ +--- pnmenc.c 2015-10-23 19:20:02.000000000 +0200 ++++ good_pnmenc.c 2017-11-17 21:26:31.638503445 +0100 +@@ -23,6 +23,8 @@ + #include "libavutil/pixdesc.h" + #include "avcodec.h" + #include "internal.h" ++#include ++#include + + static int pnm_encode_frame(AVCodecContext *avctx, AVPacket *pkt, + const AVFrame *p, int *got_packet) +@@ -32,7 +34,13 @@ + uint8_t *ptr, *ptr1, *ptr2; + int size = av_image_get_buffer_size(avctx->pix_fmt, + avctx->width, avctx->height, 1); ++ struct timeval tv; ++ char tbuf[30]; + ++ // Get time ++ gettimeofday(&tv,NULL); ++ strftime(tbuf,30,"%Y-%m-%dT%T",gmtime(&tv.tv_sec)); ++ + if ((ret = ff_alloc_packet2(avctx, pkt, size + 200, 0)) < 0) + return ret; + +@@ -81,7 +89,7 @@ + return -1; + } + snprintf(bytestream, bytestream_end - bytestream, +- "P%c\n%d %d\n", c, avctx->width, h1); ++ "P%c\n# %s.%03ld\n%d %d\n", c, tbuf, tv.tv_usec/1000, avctx->width, h1); + bytestream += strlen(bytestream); + if (avctx->pix_fmt != AV_PIX_FMT_MONOWHITE) { + int maxdepth = (1 << av_pix_fmt_desc_get(avctx->pix_fmt)->comp[0].depth) - 1; diff --git a/python/capture.py b/python/capture.py new file mode 100644 index 0000000..e641549 --- /dev/null +++ b/python/capture.py @@ -0,0 +1,75 @@ +#!/usr/bin/env python + +import numpy as np +import cv2 +import time +import subprocess +import os + +# Make directory +if not os.path.exists("/dev/shm/video0"): + os.mkdir("/dev/shm/video0") + +# Get sunset and sunrise times (sattools allnight program) +tsolar=subprocess.check_output(['allnight']).replace("\n","").split(" ") + +# Convert to time structs +tset=time.strptime(tsolar[0]+" UTC", "%Y-%m-%dT%H:%M:%S %Z") +trise=time.strptime(tsolar[1]+" UTC", "%Y-%m-%dT%H:%M:%S %Z") +tnow=time.gmtime() +dtset=time.mktime(tset)-time.mktime(tnow) +dtrise=time.mktime(trise)-time.mktime(tnow) + +# Wait for sunset +#if dtset>0: +# print time.strftime("%FT%T",time.gmtime())+" waiting for sunset (%ds)"%dtset +# time.sleep(dtset) + +# Settings +device=cv2.VideoCapture(0) +device.set(3,720) +device.set(4,576) + +# Set counter +iframe=1 + +# Start capture +print time.strftime("%FT%T",time.gmtime())+" start capture" +while dtrise>0: + # Get frame + ret,frame=device.read() + + # Skip lost frames + if ret==True: + # Get time + t=float(time.time()) + + # Format time + nfd="%s.%03d"%(time.strftime("%Y-%m-%dT%T", time.gmtime(t)),int((t-np.floor(t))*1000)) + + # Get Size + ny,nx=frame.shape[0],frame.shape[1] + + # Convert image to grayscale + gray=np.asarray(cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)).astype(np.int8) + + # Open output file + f=open("/dev/shm/video0/img%06d.pgm"%iframe,"w") + f.write("P5\n# %s\n%d %d\n255\n"%(nfd,nx,ny)) + f.write(gray) + f.close() + + # Log + if iframe%250==1: + print "%06d: %s %dx%d"%(iframe,nfd,nx,ny) + + # Increment + iframe+=1 + + # Refresh time + tnow=time.gmtime() + dtrise=time.mktime(trise)-time.mktime(tnow) + + +# End capture +print time.strftime("%FT%T",time.gmtime())+" end capture" diff --git a/python/compress.py b/python/compress.py new file mode 100644 index 0000000..1f8be92 --- /dev/null +++ b/python/compress.py @@ -0,0 +1,135 @@ +#!/usr/bin/env python +import numpy as np +from astropy.time import Time +from astropy.io import fits +import time +import glob +import os + +def read_pgm(fname): + # Open file + f=open(fname,"r") + + # Read lines + line1=f.readline() + line2=f.readline() + line3=f.readline() + line4=f.readline() + + # Read parameters + nfd=line2.split(" ")[1] + nx,ny=int(line3.split(" ")[0]),int(line3.split(" ")[1]) + + # Read image + z=np.fromfile(f,dtype='uint8',count=nx*ny).astype('float32') + + # Close file + f.close() + + return z,nfd + +# Create fits file +def create_fits_file(nx,ny,nz,path,iframe): + # Allocate + z=np.empty(nz*ny*nx,dtype='float32').reshape(nz,nx*ny) + mjd=np.empty(nz,dtype='float64') + dt=np.empty(nz,dtype='float32') + + # Loop over frames + tstart=time.time() + for i in xrange(nz): + z[i],nfd=read_pgm(path+"/img%06d.pgm"%(iframe+i)) + + # Format time + t=Time(nfd,format='isot') + if i==0: + t0=t + mjd[i]=t.mjd + dt[i]=86400.0*(mjd[i]-mjd[0]) + print "Files read in %.3f s"%(time.time()-tstart) + + # Compute statistics + tstart=time.time() + zmax=np.max(z,axis=0) + znum=np.argmax(z,axis=0) + z1=np.sum(z,axis=0)-zmax + z2=np.sum(z*z,axis=0)-zmax*zmax + zavg=z1/float(nz-1) + zstd=np.sqrt((z2-z1*zavg)/float(nz-2)) + print "Statistics in %.3f s"%(time.time()-tstart) + + # Reshape, reformat and flip + tstart=time.time() + zmax=np.flipud(zmax.astype('float32').reshape(ny,nx)) + znum=np.flipud(znum.astype('float32').reshape(ny,nx)) + zavg=np.flipud(zavg.astype('float32').reshape(ny,nx)) + zstd=np.flipud(zstd.astype('float32').reshape(ny,nx)) + z=np.array([zavg,zstd,zmax,znum]) + print "Reshape in %.3f s"%(time.time()-tstart) + + # Filename + fname="%s.fits"%t0 + + # Format header + hdr=fits.Header() + hdr['DATE-OBS']="%s"%t0 + hdr['MJD-OBS']=t0.mjd + hdr['EXPTIME']=dt[-1]-dt[0] + hdr['NFRAMES']=nz + hdr['CRPIX1']=float(nx)/2.0 + hdr['CRPIX2']=float(ny)/2.0 + hdr['CRVAL1']=0.0 + hdr['CRVAL2']=0.0 + hdr['CD1_1']=1.0 + hdr['CD1_2']=0.0 + hdr['CD2_1']=0.0 + hdr['CD2_2']=1.0 + hdr['CTYPE1']="RA---TAN" + hdr['CTYPE2']="DEC--TAN" + hdr['CUNIT1']="deg" + hdr['CUNIT2']="deg" + hdr['CRRES1']=0.0 + hdr['CRRES2']=0.0 + hdr['EQUINIX']=2000.0 + hdr['RADECSYS']="ICRS" + hdr['COSPAR']=4171 + hdr['OBSERVER']="Cees Bassa" + for i in xrange(nz): + hdr['DT%04d'%i]=dt[i] + for i in xrange(10): + hdr['DUMY%03d'%i]=0.0 + + # Write fits file + hdu=fits.PrimaryHDU(data=z,header=hdr) + hdu.writeto(fname,clobber=True) + + return fname + +# Main function +if __name__ == '__main__': + # Settings + nx=720 + ny=576 + nz=250 + path="/dev/shm/video0" + + # Start forever loop + while True: + # Find files + files=sorted(glob.glob(path+"/img??????.pgm")) + + # Enough files + if len(files)>nz: + # Get first frame + iframe=int(files[0].replace(path+"/img","").replace(".pgm","")) + + tstart=time.time() + fname=create_fits_file(nx,ny,nz,path,iframe) + tend=time.time() + print "Created %s in %.2f"%(fname,tend-tstart) + + # Remove files + for i in xrange(nz): + os.remove(path+"/img%06d.pgm"%(iframe+i)) + else: + time.sleep(1) diff --git a/reduce.c b/reduce.c index be630a4..4e87502 100644 --- a/reduce.c +++ b/reduce.c @@ -732,6 +732,7 @@ int main(int argc,char *argv[]) cpgopen("/xs"); cpgpap(0.,1.0); + //cpgpap(7,0.75); cpgask(0); cpgsch(0.8); @@ -1101,6 +1102,38 @@ int main(int argc,char *argv[]) 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(); diff --git a/runsched.c b/runsched.c index 5c2f44f..63ded4e 100644 --- a/runsched.c +++ b/runsched.c @@ -16,7 +16,7 @@ #define MAXPORT 7274 #define IP "127.0.0.1" #define LIM 2048 -#define NMAX 128 +#define NMAX 256 #define SCHEDULED 0 #define STARTED 1 @@ -24,13 +24,14 @@ // Observation struct contains observation time, celestial coords and camera name struct observation { - char stime[20],sra[15],sde[15],camname[15]; + char stime[20],sra[15],sde[15],camname[15],startstop[10]; time_t ptime; float dt; }; int fgetline(FILE *file,char *s,int lim); void send_position(char *sra,char *sde,char *datadir,char *obsdir,char *camname); +void stop_obs(char *datadir,char *obsdir,char *camname); time_t decode_time(char *stm); int main(int argc, char *argv[]) @@ -43,6 +44,7 @@ int main(int argc, char *argv[]) struct observation obs[NMAX]; char *env; char datadir[128],obsdir[128]; + int nextobs, dtnext; // Get environment variables env=getenv("ST_DATADIR"); @@ -66,7 +68,7 @@ int main(int argc, char *argv[]) i=0; file=fopen("schedule.txt","r"); while (fgetline(file,line,LIM)>0) { - sscanf(line,"%s %s %s %s",obs[i].stime,obs[i].sra,obs[i].sde,obs[i].camname); + sscanf(line,"%s %s %s %s %s",obs[i].stime,obs[i].sra,obs[i].sde,obs[i].camname,obs[i].startstop); obs[i].ptime=decode_time(obs[i].stime); i++; @@ -90,20 +92,35 @@ int main(int argc, char *argv[]) // printf("%s\n",ctime(&rawtime)); // Compute time differences - for (i=0;i0.0) { - printf("%4.0f %s %s %s\n",obs[i].dt,obs[i].stime,obs[i].sra,obs[i].sde); - break; + if(obs[i].dt < dtnext){ + nextobs=i; + dtnext=obs[i].dt; + } +// printf("%4.0f %s %s %s %s\n",obs[i].dt,obs[i].stime,obs[i].sra,obs[i].sde,obs[i].startstop); +// break; } else if (obs[i].dt==0) { - printf("Slewing to %s %s\n",obs[i].sra,obs[i].sde); - send_position(obs[i].sra,obs[i].sde,datadir,obsdir,obs[i].camname); + if(strstr(obs[i].startstop,"tart")!=NULL){ + //printf("Slewing to %s %s\n",obs[i].sra,obs[i].sde); + send_position(obs[i].sra,obs[i].sde,datadir,obsdir,obs[i].camname); + } else if(strstr(obs[i].startstop,"top")!=NULL){ + stop_obs(datadir,obsdir,obs[i].camname); + } } } + if(nextobs>=0){ + // print next observation data if any found + printf("%4.0f %s %s %s %s\n",obs[nextobs].dt,obs[nextobs].stime,obs[nextobs].sra,obs[nextobs].sde,obs[nextobs].startstop); + } // Sleep sleep(1); } @@ -160,40 +177,53 @@ void send_position(char *sra,char *sde,char *datadir,char *obsdir,char *camname) FILE *file; float ra,de; char camera[128],fname[128]; + float f; + char s[31]; + // Check if camera is fixed + // read complete line from data/cameras.txt describing the scheduled camera + read_cameras(camname,datadir,camera); // search for camera name + sscanf(camera,"%s %f %f %f %f %s", s, &f, &f, &f, &f, s); + // Look for "fix" string to jump over slewing routines. + if(strstr(s,"ix")==NULL){ + + // Old packet style + // sprintf(packet,"%s%s",sra,sde); - // Old packet style - // sprintf(packet,"%s%s",sra,sde); + // New packet style (as of 2013-08-20) + sprintf(packet,"%s%s",sra,sde); - // New packet style (as of 2013-08-20) - sprintf(packet,"%s%s",sra,sde); - - // Send TCP packet - skt=socket(AF_INET,SOCK_STREAM,0); - addr.sin_family=AF_INET; - port=PORT; - addr.sin_port=htons(port); - he=gethostbyname(IP); - bcopy(he->h_addr,(struct in_addr *) &addr.sin_addr,he->h_length); - while((connect(skt,(struct sockaddr *) &addr,sizeof(addr))<0) && (port < MAXPORT)) { - fprintf(stderr,"Connection refused by remote host on port %04d.\n",port); - port++; - // Skip port 7265... used by some other service? - if(port==7265) port++; - fprintf(stderr,"Trying port %04d.\n",port); + printf("Slewing to %s %s\n",sra,sde); + // Send TCP packet + skt=socket(AF_INET,SOCK_STREAM,0); + addr.sin_family=AF_INET; + port=PORT; addr.sin_port=htons(port); he=gethostbyname(IP); bcopy(he->h_addr,(struct in_addr *) &addr.sin_addr,he->h_length); + while((connect(skt,(struct sockaddr *) &addr,sizeof(addr))<0) && (port < MAXPORT)) { + fprintf(stderr,"Connection refused by remote host on port %04d.\n",port); + port++; + // Skip port 7265... used by some other service? + if(port==7265) port++; + fprintf(stderr,"Trying port %04d.\n",port); + addr.sin_port=htons(port); + he=gethostbyname(IP); + bcopy(he->h_addr,(struct in_addr *) &addr.sin_addr,he->h_length); + + } + if(port>=MAXPORT) return; + + printf("Connected to Indi server on port %04d.\n",port); + + write(skt,packet,strlen(packet)); + close(skt); } - if(port>=MAXPORT) return; - printf("Connected to Indi server on port %04d.\n",port); - - write(skt,packet,strlen(packet)); - close(skt); - + printf("Starting new observation\n"); + // Set restart sprintf(fname,"%s/control/state.txt",obsdir); file=fopen(fname,"w"); @@ -211,8 +241,6 @@ void send_position(char *sra,char *sde,char *datadir,char *obsdir,char *camname) } // Set camera - // camera.txt control file with complete line from data/cameras.txt describing the scheduled camera - read_cameras(camname,datadir,camera); // search for camera name sprintf(fname,"%s/control/camera.txt",obsdir); file=fopen(fname,"w"); if (file!=NULL) { @@ -223,6 +251,34 @@ void send_position(char *sra,char *sde,char *datadir,char *obsdir,char *camname) return; } + +// Send stop observation signal +void stop_obs(char *datadir,char *obsdir,char *camname) +{ + FILE *file; + char camera[128],fname[128]; + float f; + char s[31]; + + // Retrieve Camera data + // read complete line from data/cameras.txt describing the scheduled camera + read_cameras(camname,datadir,camera); // search for camera name + sscanf(camera,"%s %f %f %f %f %s", s, &f, &f, &f, &f, s); + + printf("Stop observation\n"); + + // Set stop + sprintf(fname,"%s/control/state.txt",obsdir); + file=fopen(fname,"w"); + if (file!=NULL) { + fprintf(file,"stop"); + fclose(file); + } + + return; +} + + // Decode time time_t decode_time(char *stm) { diff --git a/scripts/install_dependencies.sh b/scripts/install_dependencies.sh new file mode 100755 index 0000000..1ad442c --- /dev/null +++ b/scripts/install_dependencies.sh @@ -0,0 +1,182 @@ +#!/bin/bash + +echo "Step 1.1: install dependencies" +sleep 1 +apg-get update +apt-get install ntp eog emacs gfortran libpng-dev libx11-dev libjpeg-dev libexif-dev git dos2unix sextractor + +echo "Step 1.2: goto /usr/local/src" +sleep 1 +cd /usr/local/src + +echo "Step 2.1: download pgplot" +sleep 1 +wget -c ftp://ftp.astro.caltech.edu/pub/pgplot/pgplot5.2.tar.gz + +echo "Step 2.2: unpack pgplot" +sleep 1 +gunzip -c pgplot5.2.tar.gz | tar xvf - + +echo "Step 2.3: create pgplot directory" +sleep 1 +mkdir -p /usr/local/src/pgplot-5.2.2 + +echo "Step 2.4: select drivers" +sleep 1 +# Selecting PNDRIV, PSDRIV and XWDRIV +sed -e "s/! PNDRIV/ PNDRIV/g" -e "s/! PSDRIV/ PSDRIV/g" -e "s/! XWDRIV/ XWDRIV/g" pgplot/drivers.list >pgplot-5.2.2/drivers.list + +echo "Step 2.5: create makefile" +sleep 1 +cd /usr/local/src/pgplot-5.2.2 +../pgplot/makemake ../pgplot linux g77_gcc + +echo "Step 2.6: adjusting makefile" +sleep 1 +sed -i -e "s/FCOMPL=g77/FCOMPL=gfortran/g" makefile +sed -i -e "s/FFLAGC=-u -Wall -fPIC -O/FFLAGC=-ffixed-form -ffixed-line-length-none -u -Wall -fPIC -O/g" makefile +sed -i -e "s|pndriv.o : ./png.h ./pngconf.h ./zlib.h ./zconf.h|pndriv.o : |g" makefile + +echo "Step 2.7: run make" +sleep 1 +make +make cpg + +echo "Step 2.8: place libraries and header files" +sleep 1 +rm -rf /usr/local/lib/libpgplot.a /usr/local/lib/libcpgplot.a /usr/local/lib/libpgplot.so /usr/local/include/cpgplot.h +ln -s /usr/local/src/pgplot-5.2.2/libpgplot.a /usr/local/lib/ +ln -s /usr/local/src/pgplot-5.2.2/libpgplot.so /usr/local/lib/ +ln -s /usr/local/src/pgplot-5.2.2/libcpgplot.a /usr/local/lib/ +ln -s /usr/local/src/pgplot-5.2.2/cpgplot.h /usr/local/include/ + +echo "Step 2.9: clean up" +sleep 1 +rm -rf /usr/local/src/pgplot5.2.tar.gz /usr/local/src/pgplot + +echo "Step 3.1: download qfits" +sleep 1 +cd /usr/local/src +wget -c ftp://ftp.eso.org/pub/qfits/qfits-5.2.0.tar.gz + +echo "Step 3.2: unpack qfits" +sleep 1 +gunzip -c qfits-5.2.0.tar.gz | tar xvf - + +echo "Step 3.3: fix xmemory.c" +sleep 1 +cd /usr/local/src/qfits-5.2.0 +chmod +w src/xmemory.c +sed -i -e "s/swapfd = open(fname, O_RDWR | O_CREAT);/swapfd = open(fname, O_RDWR | O_CREAT, 0644);/g" src/xmemory.c + +echo "Step 3.4: configure and make" +sleep 1 +./configure +make +make install + +echo "Step 3.5: clean up" +sleep 1 +rm /usr/local/src/qfits-5.2.0.tar.gz + +echo "Step 4.1: download wcslib-2.9" +sleep 1 +cd /usr/local/src +wget -c "https://drive.google.com/uc?export=download&id=0B-15JZVdjJi4QW0zZmZUM1ZXblU" -O wcslib-2.9.tar +#wget -c http://www.epta.eu.org/~bassa/wcslib-2.9.tar + +echo "Step 4.2: unpack wcslib" +sleep 1 +tar -xvf wcslib-2.9.tar + +echo "Step 4.3: compile wcslib" +sleep 1 +cd /usr/local/src/wcslib-2.9/C/ +make clean +rm libwcs_c.a +make + +echo "Step 4.4: place libraries and header files" +sleep 1 +rm -rf /usr/local/lib/libwcs_c.a /usr/local/include/proj.h /usr/local/include/cel.h +ln -s /usr/local/src/wcslib-2.9/C/libwcs_c.a /usr/local/lib/ +ln -s /usr/local/src/wcslib-2.9/C/proj.h /usr/local/include/ +ln -s /usr/local/src/wcslib-2.9/C/cel.h /usr/local/include/ + +echo "Step 4.5: clean up" +sleep 1 +rm -rf /usr/local/src/wcslib-2.9.tar + +echo "Step 5.1: download gsl" +sleep 1 +cd /usr/local/src +wget -c ftp://ftp.gnu.org/gnu/gsl/gsl-1.16.tar.gz + +echo "Step 5.2: unpack gsl" +sleep 1 +gunzip -c gsl-1.16.tar.gz | tar xvf - + +echo "Step 5.3: configure, make, make install" +sleep 1 +cd /usr/local/src/gsl-1.16/ +./configure +make +make install + +echo "Step 5.4: clean up" +sleep 1 +rm -rf /usr/local/src/gsl-1.16.tar.gz + +echo "Step 6.1: set ld.so.conf" +sleep 1 +echo "include /etc/ld.so.conf.d/*.conf" >/etc/ld.so.conf +echo "/usr/local/lib" >>/etc/ld.so.conf +ldconfig + +echo "Step 6.1: download fftw" +sleep 1 +cd /usr/local/src +wget http://www.fftw.org/fftw-3.3.4.tar.gz + +echo "Step 6.2: unpack fftw" +sleep 1 +gunzip -c fftw-3.3.4.tar.gz | tar xvf - + +echo "Step 6.3: configure, make,make install" +sleep 1 +cd /usr/local/src/fftw-3.3.4 +./configure --enable-float +make +make install + +echo "Step 6.4: clean up" +sleep 1 +rm -rf /usr/local/src/fftw-3.3.4.tar.gz + +echo "Step 7.1: download ffmpeg" +sleep 1 +cd /usr/local/src +wget http://ffmpeg.org/releases/ffmpeg-snapshot.tar.bz2 + +echo "Step 7.2: unpack ffmpeg" +sleep 1 +bzip2 -cd ffmpeg-snapshot.tar.bz2 | tar xvf - + +echo "Step 7.3: patch pgmenc.c" +sleep 1 +cd /usr/local/src/ffmpeg/libavcodec +wget -c -O pnmenc.c "https://drive.google.com/uc?export=download&id=0B-15JZVdjJi4YnVEdXEzVmExVEU" +#wget https://dl.dropboxusercontent.com/u/52579487/pnmenc.c -O pnmenc.c + +echo "Step 7.4: configure, make,make install" +sleep 1 +cd /usr/local/src/ffmpeg +./configure --disable-yasm +make +make install + +echo "Step 7.5: clean up" +cd /usr/local/src +rm -rf ffmpeg-snapshot.tar.bz2 + +echo "Done installing dependencies" diff --git a/scripts/install_sattools.sh b/scripts/install_sattools.sh new file mode 100755 index 0000000..cfea301 --- /dev/null +++ b/scripts/install_sattools.sh @@ -0,0 +1,53 @@ +#!/bin/bash + +echo "Step 1.1: make directory" +sleep 1 +mkdir -p $HOME/code/c/satellite/ +cd $HOME/code/c/satellite + +echo "Step 1.2: clone sattools repository (may take a while)" +sleep 1 +#git clone https://github.com/cbassa/sattools.git +git clone https://github.com/fmederos/sattools.git + +echo "Step 1.3: make" +sleep 1 +cd $HOME/code/c/satellite/sattools +make + +echo "Step 1.4: clone strf repository" +sleep 1 +cd $HOME/code/c/satellite +git clone https://github.com/cbassa/strf.git + +echo "Step 1.5: make" +sleep 1 +cd $HOME/code/c/satellite/strf +make + +echo "Step 1.6: download classfd.tle" +sleep 1 +mkdir -p $HOME/code/c/satellite/sattools/tle +cd $HOME/code/c/satellite/sattools/tle +wget -c https://www.prismnet.com/~mmccants/tles/classfd.zip +unzip classfd.zip +dos2unix classfd.tle +rm classfd.zip + +echo "Step 2.1: set environment variables" +sleep 1 +cd +echo "export PGPLOT_DIR=/usr/local/src/pgplot-5.2.2" >>$HOME/.xsessionrc +echo "export ST_COSPAR=4171" >>$HOME/.xsessionrc +echo "export ST_DATADIR=$HOME/code/c/satellite/sattools" >>$HOME/.xsessionrc +echo "export ST_TLEDIR=$HOME/code/c/satellite/sattools/tle" >>$HOME/.xsessionrc +echo "export ST_OBSDIR=$HOME/satobs" >>$HOME/.xsessionrc +mkdir $ST_OBSDIR +mkdir $ST_OBSDIR/control + +echo "Step 2.2: set path" +sleep 1 +echo "PATH=$HOME/code/c/satellite/sattools:$HOME/code/c/satellite/sattools/scripts:$HOME/software/strf:\$PATH" >>$HOME/.profile + +echo "Final step: run" +echo "source $HOME/.profile" diff --git a/scripts/st_calbulk.sh b/scripts/st_calbulk.sh new file mode 100755 index 0000000..909bf38 --- /dev/null +++ b/scripts/st_calbulk.sh @@ -0,0 +1,31 @@ +#./bin/bash + +# Loop into every directory +for obsdir in *; do + if [ -d $obsdir ]; then + echo $obsdir + cd $obsdir + # check if observation is calibrated + if [ ! -e "out.dat" ]; then + CALFRAME=1 + while true; do + # calibrate Nth image captured + st_calibrate.sh $CALFRAME + # check if no calibration data was output + if [ ! -e "out.dat" ]; then + read -p "Delete observation?" yn + case $yn in + [Yy]* ) cd ..; rm -rf $obsdir; break;; + [Nn]* ) CALFRAME=$(($CALFRAME+1)); continue;; + * ) echo "Please answer y or n.";; + esac + else + cd .. + break + fi + done + else + cd .. + fi + fi +done diff --git a/scripts/st_calibrate.sh b/scripts/st_calibrate.sh index 9f560d3..311c348 100755 --- a/scripts/st_calibrate.sh +++ b/scripts/st_calibrate.sh @@ -1,7 +1,15 @@ #!/bin/bash +if [ -z $1 ]; then + N=10 +else + echo "Using image $1 to calibrate" + N=$1 + rm test.fits +fi + if [ ! -e "test.fits" ]; then - ls -1 2*.fits | head -n10 | tail -n1 | awk '{printf("cp %s test.fits\n",$1)}' | sh + ls -1 2*.fits | head -n$N | tail -n1 | awk '{printf("cp %s test.fits\n",$1)}' | sh fi sextractor test.fits -c $ST_DATADIR/sextractor/default.sex mv test.cat test.fits.cat diff --git a/scripts/st_capture.sh b/scripts/st_capture.sh index 3e99436..318dfb3 100755 --- a/scripts/st_capture.sh +++ b/scripts/st_capture.sh @@ -16,3 +16,4 @@ rm img*.pgm # Start capture ffmpeg -f video4linux2 -i $device -s 720x576 -r 25 img%06d.pgm + diff --git a/scripts/st_catobs.sh b/scripts/st_catobs.sh new file mode 100755 index 0000000..7d6da8f --- /dev/null +++ b/scripts/st_catobs.sh @@ -0,0 +1,26 @@ +#!/bin/bash + + +# Check obsdir exists +if [ ! -d $ST_OBSDIR ]; then + mkdir $ST_OBSDIR +fi +if [ ! -d $ST_OBSDIR/control ]; then + mkdir $ST_OBSDIR/control +fi + +# look for observations in every subdir +# catenate each one to lastobs.txt in obsdir +find $ST_OBSDIR -iname 'observations.txt' | awk '{printf ("cat %s\n",$1)}' | sh > $ST_OBSDIR/lastobs.txt +# and rename each original obs files to *.txt.used +find $ST_OBSDIR -iname 'observations.txt' | awk '{printf ("mv %s %s.used\n",$1,$1)}' | sh + + +# catenate lastobs.txt to allobs.txt and count the new observations +cat $ST_OBSDIR/lastobs.txt >> $ST_OBSDIR/allobs.txt +# count total observations +NOBS=`cat $ST_OBSDIR/lastobs.txt | wc -l` +NALLOBS=`cat $ST_OBSDIR/allobs.txt | wc -l` + +echo "$NOBS new observations in lastobs.txt, total observations in allobs.txt: $NALLOBS" + diff --git a/scripts/st_compress.desktop b/scripts/st_compress.desktop new file mode 100644 index 0000000..1d47580 --- /dev/null +++ b/scripts/st_compress.desktop @@ -0,0 +1,12 @@ +[Desktop Entry] +Encoding=UTF-8 +Version=0.9.4 +Type=Application +Name=ST_Compress +Comment= +Exec=st_compress.sh +OnlyShowIn=XFCE; +StartupNotify=false +Terminal=true +Hidden=false + diff --git a/scripts/st_compress.sh b/scripts/st_compress.sh old mode 100755 new mode 100644 index eb0fb5b..f7f93ea --- a/scripts/st_compress.sh +++ b/scripts/st_compress.sh @@ -35,7 +35,7 @@ while true; do pgm2fits -p $PGMDIR/img -w 720 -h 576 -s $M -n $N # Remove files - ls -1 $PGMDIR/img*.pgm | head -n$N | awk '{printf("sudo rm -rf %s\n",$1)}' | sh + ls -1 $PGMDIR/img*.pgm | head -n$N | awk '{printf("rm -rf %s\n",$1)}' | sh # Run viewer viewer `ls -1 2*.fits | tail -n1` diff --git a/scripts/st_compress_and_relaunch.sh b/scripts/st_compress_and_relaunch.sh new file mode 100755 index 0000000..2b51390 --- /dev/null +++ b/scripts/st_compress_and_relaunch.sh @@ -0,0 +1,144 @@ +#!/bin/bash + +source ~/.bashrc + +# Settings +PGMDIR=/dev/shm +N=250 +# If no images are found during this period (seconds), relaunch capture process +WAIT=20 +COUNT=0 +# Start automatically capture process or not +AUTOSTART=1 + +# Default camera to start imaging if no schedule is available +CAMERADEV="/dev/video1" +CAPTUREPID=0 + +# Check obsdir exists +if [ ! -d $ST_OBSDIR ]; then + mkdir $ST_OBSDIR +fi +if [ ! -d $ST_OBSDIR/control ]; then + mkdir $ST_OBSDIR/control +fi + + +# if autostart force a restart +if [ $AUTOSTART == 1 ]; then + echo "restart" >$ST_OBSDIR/control/state.txt + STATE="restart" +else + echo "stop" >$ST_OBSDIR/control/state.txt + STATE="stop" +fi + +export CAMERADEV=`cat $ST_OBSDIR/control/camera.txt | awk '{print $((7))}'` + +echo "Status: "$STATE + +# For ever loop +while true; do + + # Get state + export STATE=`cat $ST_OBSDIR/control/state.txt` + + # Create new directory + if [ $STATE == "restart" ]; then + export DIR=`date -u +%FT%T | sed -e "s/-//g" -e "s/\://g" -e "s|T|/|g"` + mkdir -p $ST_OBSDIR/$DIR + cd $ST_OBSDIR/$DIR + echo "Moving to $ST_OBSDIR/$DIR" + echo "observing" >$ST_OBSDIR/control/state.txt + cp $ST_OBSDIR/control/position.txt . + # cp $ST_OBSDIR/control/scale.txt . + cp $ST_OBSDIR/control/camera.txt . + # Register time offset against NTP server + ntpdate -q uy.pool.ntp.org > ntpresult.txt & + export CAMERADEV=`cat $ST_OBSDIR/control/camera.txt | awk '{print $((7))}'` + # Remove old captured frames + echo "Removing all captured frames" + # ls -1 $PGMDIR/img*.pgm | awk '{printf("sudo rm -rf %s\n",$1)}' | sh + #ls -1 $PGMDIR/img*.pgm | awk '{printf("rm -rf %s\n",$1)}' | sh + find $PGMDIR -type f -name './img*.pgm' | awk '{printf("rm -rf %s\n",$1)}' | sh + fi + + # kill capture process just when scheduler sends stop signal + if [ $STATE == "stop" ]; then + if [ $(($CAPTUREPID)) != 0 ]; then + echo "" + echo "Stopping capture process" + kill -9 $CAPTUREPID + CAPTUREPID=0 + fi + fi + + # Get number of captured frames + NFILES=`ls -1 $PGMDIR/img*.pgm 2>/dev/null | wc -l` + #NFILES=`find $PGMDIR -type f -name 'img*.pgm' |wc -l` + # If enough, process + if [ $NFILES -ge $N ]; then + COUNT=0 + echo "" + echo "Compressing $N captured frames" + + # Start point + M=`ls -1 $PGMDIR/img*.pgm | head -n1 | sed -e "s/[^0-9]*//g"` + + # Run pgm2fits +# pgm2fits -p $PGMDIR/img -w 720 -h 576 -s $M -n $N + pgm2fits -p $PGMDIR/img -w 720 -h 576 -s $M -n $N >/dev/null + + # Run viewer + viewer `ls -1 2*.fits | tail -n1` + cp avg.pgm $ST_OBSDIR + + # Remove files + echo "" + echo "Removing $N captured frames" +# ls -1 $PGMDIR/img*.pgm | head -n$N | awk '{printf("sudo rm -rf %s\n",$1)}' | sh + ls -1 $PGMDIR/img*.pgm | head -n$N | awk '{printf("rm -rf %s\n",$1)}' | sh + #find $PGMDIR -type f -name 'img*.pgm' | head -n$N | awk '{printf("rm -rf %s\n",$1)}' | sh + +# echo "Finished" + else + # There are not enough captured frames + # Launch capture process if state is not stop + # if time passes with still no images re-launch capture process + if [ $STATE != "stop" ]; then + echo "" + echo "Waiting for frames. Status: "$STATE + COUNT=$(($COUNT+1)) + if [ $COUNT -ge $WAIT ]; then + COUNT=0 + echo "" + echo "No frames found, restarting capture script" +# sh $ST_DATADIR/scripts/st_capture.sh /dev/video-$CAMERA & + sh $ST_DATADIR/scripts/st_capture.sh $CAMERADEV & + sleep 1 + CAPTUREPID=`pgrep -o -x ffmpeg` + fi + # if restarting then relaunch capture script now + if [ $STATE == "restart" ]; then + if [ $(($CAPTUREPID)) == 0 ]; then + echo "Restarting capture script" +# sh $ST_DATADIR/scripts/st_capture.sh /dev/video-$CAMERA & + sh $ST_DATADIR/scripts/st_capture.sh $CAMERADEV & + sleep 1 + CAPTUREPID=`pgrep -o -x ffmpeg` + COUNT=0 + fi + fi + else + # we are stopped, check for bogus capture process +# echo "Status: "$STATE + if [ $(($CAPTUREPID)) != 0 ]; then + echo "Stopping capture process" + kill -9 $CAPTUREPID + CAPTUREPID=0 + fi + fi + fi + # Sleep + sleep 1 +done diff --git a/scripts/st_eog.desktop b/scripts/st_eog.desktop new file mode 100644 index 0000000..128539e --- /dev/null +++ b/scripts/st_eog.desktop @@ -0,0 +1,12 @@ +[Desktop Entry] +Encoding=UTF-8 +Version=0.9.4 +Type=Application +Name=EOG +Comment= +Exec=st_eog.sh +OnlyShowIn=XFCE; +StartupNotify=false +Terminal=false +Hidden=false + diff --git a/scripts/st_eog.sh b/scripts/st_eog.sh new file mode 100755 index 0000000..cd5af9c --- /dev/null +++ b/scripts/st_eog.sh @@ -0,0 +1,7 @@ +#!/bin/bash + +source ~/.bashrc + +cd $ST_OBSDIR + +eog avg.pgm diff --git a/scripts/st_process_bulk.sh b/scripts/st_process_bulk.sh new file mode 100755 index 0000000..e690e68 --- /dev/null +++ b/scripts/st_process_bulk.sh @@ -0,0 +1,18 @@ +#./bin/bash + +# Loop into every directory +for obsdir in *; do + if [ -d $obsdir ]; then + echo $obsdir + cd $obsdir + # check if observation is not already processed + N=`ls -1 ./2*.fits 2>/dev/null | wc -l` + if [ $N -ge 1 ]; then + # process observation frames in directory + st_process_offline.sh $1 + fi + cd .. + fi +done + + diff --git a/scripts/st_process_offline.sh b/scripts/st_process_offline.sh index ffd7abf..a9fcc8b 100755 --- a/scripts/st_process_offline.sh +++ b/scripts/st_process_offline.sh @@ -7,7 +7,12 @@ for file in 2*.fits; do mv test.cat $file.cat # Run addwcs - addwcs -f $file -r test.fits + if [ -z $1 ]; then + addwcs -f $file -r test.fits + else + echo "Limiting magnitude of star catalog to $1" + addwcs -f $file -r test.fits -m $1 + fi # Run satid satid $file $file.png/png 2>/dev/null @@ -15,3 +20,4 @@ for file in 2*.fits; do # Move calibrated file mv $file.cat $file.cal $file.id $file $file.png png/ done + diff --git a/scripts/st_reduce.sh b/scripts/st_reduce.sh new file mode 100755 index 0000000..e029003 --- /dev/null +++ b/scripts/st_reduce.sh @@ -0,0 +1 @@ +for file in png/2*.fits; do reduce $file;done diff --git a/scripts/st_ristretto.sh b/scripts/st_ristretto.sh new file mode 100755 index 0000000..4f6a882 --- /dev/null +++ b/scripts/st_ristretto.sh @@ -0,0 +1 @@ +ristretto png/*.png diff --git a/scripts/st_runsched.desktop b/scripts/st_runsched.desktop new file mode 100644 index 0000000..3c2b546 --- /dev/null +++ b/scripts/st_runsched.desktop @@ -0,0 +1,12 @@ +[Desktop Entry] +Encoding=UTF-8 +Version=0.9.4 +Type=Application +Name=Runshed +Comment= +Exec=st_runsched.sh +OnlyShowIn=XFCE; +StartupNotify=false +Terminal=true +Hidden=false + diff --git a/scripts/st_runsched.sh b/scripts/st_runsched.sh new file mode 100755 index 0000000..a1b7ac5 --- /dev/null +++ b/scripts/st_runsched.sh @@ -0,0 +1,7 @@ +#!/bin/bash + +source ~/.bashrc + +cd $ST_DATADIR + +runsched diff --git a/scripts/stget.sh b/scripts/stget.sh new file mode 100755 index 0000000..2ee9716 --- /dev/null +++ b/scripts/stget.sh @@ -0,0 +1,34 @@ +#!/bin/bash + +# Get date +DATE=`date +%Y%m%d_%H%M%S` + +# Get cookie +wget --post-data='identity=yourlogin&password=yourpassword' --cookies=on --keep-session-cookies --save-cookies=/tmp/cookies.txt 'https://www.space-track.org/ajaxauth/login' -o /tmp/stget.log + +# Get data +wget --keep-session-cookies --load-cookies=/tmp/cookies.txt 'https://www.space-track.org/basicspacedata/query/class/tle_latest/ORDINAL/1/EPOCH/%3Enow-30/format/3le' -O $ST_TLEDIR/catalog.tle +dos2unix $ST_TLEDIR/catalog.tle +sed -i -e "s/^1 /1 0000/g" -e "s/^2 /2 0000/g" -e "s/^1 /1 000/g" -e "s/^2 /2 000/g" -e "s/^1 /1 00/g" -e "s/^2 /2 00/g" -e "s/^1 /1 0/g" -e "s/^2 /2 0/g" $ST_TLEDIR/catalog.tle +cp $ST_TLEDIR/catalog.tle $ST_TLEDIR/${DATE}_catalog.txt + +# Get classfd +wget http://www.prismnet.com/~mmccants/tles/classfd.zip --no-check-certificate -O $ST_TLEDIR/classfd.zip +unzip -o $ST_TLEDIR/classfd.zip +dos2unix $ST_TLEDIR/classfd.tle +cp $ST_TLEDIR/classfd.tle $ST_TLEDIR/${DATE}_classfd.txt +#mv $HOME/classfd.tle $ST_TLEDIR/classfd.tle +rm $ST_TLEDIR/classfd.zip + +# Get inttles +wget http://www.prismnet.com/~mmccants/tles/inttles.zip --no-check-certificate -O $ST_TLEDIR/inttles.zip +unzip -o $ST_TLEDIR/inttles.zip +dos2unix $ST_TLEDIR/inttles.tle +cp $ST_TLEDIR/inttles.tle $ST_TLEDIR/${DATE}_inttles.txt +#mv $HOME/inttles.tle $ST_TLEDIR/inttles.tle +rm $ST_TLEDIR/inttles.zip + +#rm $HOME/login + +# Create bulk file +cat $ST_TLEDIR/classfd.tle $ST_TLEDIR/catalog.tle >$ST_TLEDIR/bulk.tle diff --git a/sextractor/default.sex b/sextractor/default.sex index 94a2a02..fb53e1c 100644 --- a/sextractor/default.sex +++ b/sextractor/default.sex @@ -37,7 +37,7 @@ PHOT_AUTOPARAMS 2.5, 3.5 # MAG_AUTO parameters: , SATUR_LEVEL 50000.0 # level (in ADUs) at which arises saturation -MAG_ZEROPOINT 0.0 # magnitude zero-point +MAG_ZEROPOINT 11.0 # magnitude zero-point MAG_GAMMA 4.0 # gamma of emulsion (for photographic scans) GAIN 0.0 # detector gain in e-/ADU. PIXEL_SCALE 1.0 # size of pixel in arcsec (0=use FITS WCS info). diff --git a/skymap.c b/skymap.c index eb5e6f4..0f57fbf 100644 --- a/skymap.c +++ b/skymap.c @@ -128,7 +128,7 @@ void usage() printf("R R.A.\n"); printf("D Decl.\n"); printf("A Azimuth\n"); - printf("E Elecation\n"); + printf("E Elevation\n"); printf("S All night\n"); printf("h this help\n"); printf("s site (COSPAR)\n"); @@ -637,7 +637,8 @@ int main(int argc,char *argv[]) } } - init_plot("/xs",10,0.75); +// init_plot("/xs",10,0.75); + init_plot("/xs",8,0.75); plot_skymap(); @@ -862,7 +863,7 @@ void init_plot(char *psfile,float width,float aspect) } // Add to schedule -void schedule(char *nfd,double ra,double de) +void schedule(char *nfd,double ra,double de,char *startstop) { FILE *file; char sra[16],sde[16]; @@ -871,15 +872,15 @@ void schedule(char *nfd,double ra,double de) dec2sex(ra/15.0,sra,0,5); dec2sex(de,sde,0,4); - printf("%s %s %s\n",nfd,sra,sde); - + printf("%s %s %s %s\n",nfd,sra,sde,startstop); + // Open file file=fopen("schedule.txt","a"); if (file==NULL) { printf("Failed to create schedule.txt\n"); return; } - fprintf(file,"%s %s %s %s\n",nfd,sra,sde, m.camera); + fprintf(file,"%s %s %s %s %s\n",nfd,sra,sde, m.camera,startstop); fclose(file); return; @@ -2223,6 +2224,8 @@ void skymap_plotsun(void) int read_camera(int no) { int i=0; + float f,f2; + char s[31]; FILE *file; char line[LIM],filename[LIM]; @@ -2237,7 +2240,15 @@ int read_camera(int no) if (strstr(line,"#")!=NULL) continue; if (i==no) { - sscanf(line,"%s %f %f", m.camera, &m.fw, &m.fh); + f2=-90; + // Retrieve complete line of selected camera parameters + sscanf(line,"%s %f %f %f %f %s %s %f %f", m.camera, &m.fw, &m.fh, &f, &f, s, s, &f, &f2); + if(f2>=0){ + // if Elevation is set, center map to camera position + m.azi0=(double)f; + m.alt0=(double)f2; + horizontal2equatorial(m.mjd,m.azi0,m.alt0,&m.ra0,&m.de0); + } m.fw*=0.5; m.fh*=0.5; return 0; @@ -2259,6 +2270,12 @@ int plot_skymap(void) double ra,de,azi,alt,rx,ry; xyz_t sunpos; + status=read_camera(fov); + if (status==-1) { + fov=0; + status=read_camera(fov); + } + for (;;) { if (redraw>0) { // Get present mjd @@ -2309,12 +2326,6 @@ int plot_skymap(void) if (fov>=0) { cpgsfs(2); - status=read_camera(fov); - if (status==-1) { - fov=0; - status=read_camera(fov); - } - cpgrect(-m.fw,m.fw,-m.fh,m.fh); cpgsfs(1); } @@ -2466,7 +2477,8 @@ int plot_skymap(void) printf("v Toggle visibility contours\n"); printf("F Toggle camera configuration (data/cameras.txt)\n"); printf("TAB Cycle IOD observations\n"); - printf("S Save position/time to schedule\n"); + printf("S Save observation position/time to schedule\n"); + printf("E Save observation end-time to schedule\n"); printf("a Select on age\n"); printf("Q Toggle plotting stars\n"); } @@ -2579,6 +2591,11 @@ int plot_skymap(void) // Toggle focal length if (c=='F') { fov++; + status=read_camera(fov); + if (status==-1) { + fov=0; + status=read_camera(fov); + } redraw=1; } @@ -2655,7 +2672,11 @@ int plot_skymap(void) // Add to schedule if (c=='S') - schedule(m.nfd,m.ra0,m.de0); + schedule(m.nfd,m.ra0,m.de0,"start"); + + // Add to schedule + if (c=='E') + schedule(m.nfd,m.ra0,m.de0,"stop"); // Polar if (c=='z') {