/*** File libwcs/tabread.c *** September 21, 2001 *** By Doug Mink, dmink@cfa.harvard.edu *** Harvard-Smithsonian Center for Astrophysics */ /* int tabread() Read tab table stars in specified region * int tabrnum() Read tab table stars with specified numbers * int tabxyread() Read x, y, and magnitude from tab table star list * int tabrkey() Read single keyword from specified tab table stars * struct StarCat tabcatopen() Open tab table catalog, return number of entries * struct TabTable *tabopen() Open tab table, returning number of entries * char *tabline() Get tab table entry for one line * double tabgetra() Return double right ascension in degrees * double tabgetdec() Return double declination in degrees * double tabgetr8() Return 8-byte floating point number from tab table line * int tabgeti4() Return 4-byte integer from tab table line * int tabgetk() Return character entry from tab table line for column * int tabgetc() Return n'th character entry from tab table line * int tabhgetr8() Return 8-byte floating point keyword value from header * int tabhgeti4() Return 4-byte integer keyword value from header * int tabhgetc() Return character keyword value from header * int tabparse() Make a table of column headings * int tabcol() Search a table of column headings for a particlar entry * int tabsize() Return length of file in bytes * int istab() Return 1 if first line of file contains a tab, else 0 */ #include #include #include #include #include #include #include "wcs.h" #include "wcscat.h" #define ABS(a) ((a) < 0 ? (-(a)) : (a)) static int tabhgetr8(); static int tabhgeti4(); static int tabhgetc(); static int tabcont(); static int tabsize(); static int nndec = 0; static char *taberr; static struct Tokens startok; char *gettaberr () { return (taberr); } int gettabndec() { return (nndec); } static char *kwo = NULL; /* Keyword returned by tabread(), tabrnum() */ void settabkey (keyword0) char *keyword0; { kwo = keyword0; return; } /* TABREAD -- Read tab table stars in specified region */ int tabread (tabcatname,distsort,cra,cdec,dra,ddec,drad, sysout,eqout,epout,mag1,mag2,sortmag,nstarmax,starcat, tnum,tra,tdec,tpra,tpdec,tmag,tpeak,tkey,nlog) char *tabcatname; /* Name of reference star catalog file */ int distsort; /* 1 to sort stars by distance from center */ double cra; /* Search center J2000 right ascension in degrees */ double cdec; /* Search center J2000 declination in degrees */ double dra; /* Search half width in right ascension in degrees */ double ddec; /* Search half-width in declination in degrees */ double drad; /* Limiting separation in degrees (ignore if 0) */ int sysout; /* Search coordinate system */ double eqout; /* Search coordinate equinox */ double epout; /* Proper motion epoch (0.0 for no proper motion) */ double mag1,mag2; /* Limiting magnitudes (none if equal) */ int sortmag; /* Magnitude by which to sort (1 to nmag) */ int nstarmax; /* Maximum number of stars to be returned */ struct StarCat **starcat; /* Star catalog data structure */ double *tnum; /* Array of UJ numbers (returned) */ double *tra; /* Array of right ascensions (returned) */ double *tdec; /* Array of declinations (returned) */ double *tpra; /* Array of right ascension proper motions (returned) */ double *tpdec; /* Array of declination proper motions (returned) */ double **tmag; /* 2-D Array of magnitudes (returned) */ int *tpeak; /* Array of peak counts (returned) */ char **tkey; /* Array of additional keyword values */ int nlog; { double ra1,ra2; /* Limiting right ascensions of region in degrees */ double dec1,dec2; /* Limiting declinations of region in degrees */ double dist = 0.0; /* Distance from search center in degrees */ double faintmag=0.0; /* Faintest magnitude */ double maxdist=0.0; /* Largest distance */ int faintstar=0; /* Faintest star */ int farstar=0; /* Most distant star */ double *tdist; /* Array of distances to stars */ int sysref; /* Catalog coordinate system */ double eqref; /* Catalog equinox */ double epref; /* Catalog epoch */ double magt; char cstr[32]; struct Star *star; struct StarCat *sc; /* Star catalog data structure */ int wrap; int jstar; int magsort; int nstar; char *objname; int lname; int imag; double ra,dec, rapm, decpm; double mag, parallax, rv; double num; int peak, i; int istar, nstars, lstar; int verbose; sc = *starcat; if (nlog > 0) verbose = 1; else verbose = 0; SearchLim (cra,cdec,dra,ddec,sysout,&ra1,&ra2,&dec1,&dec2,verbose); /* If RA range includes zero, split it in two */ wrap = 0; if (ra1 > ra2) wrap = 1; else wrap = 0; /* mag1 is always the smallest magnitude limit */ if (mag2 < mag1) { mag = mag2; mag2 = mag1; mag1 = mag; } /* Logging interval */ nstar = 0; tdist = (double *) calloc (nstarmax, sizeof (double)); lstar = sizeof (struct Star); star = (struct Star *) calloc (1, lstar); if (sc == NULL) sc = tabcatopen (tabcatname, NULL, 0); *starcat = sc; if (sc == NULL || sc->nstars <= 0) { if (taberr != NULL) fprintf (stderr,"%s\n", taberr); fprintf (stderr,"TABREAD: Cannot read catalog %s\n", tabcatname); free (star); sc = NULL; return (0); } nstars = sc->nstars; jstar = 0; if (sortmag > 0 && sortmag <= sc->nmag) magsort = sortmag - 1; else magsort = 0; /* Set catalog coordinate system */ if (sc->equinox != 0.0) eqref = sc->equinox; else eqref = eqout; if (sc->epoch != 0.0) epref = sc->epoch; else epref = epout; if (sc->coorsys) sysref = sc->coorsys; else sysref = sysout; wcscstr (cstr, sysout, eqout, epout); /* Loop through catalog */ for (istar = 1; istar <= nstars; istar++) { /* Read position of next star */ if (tabstar (istar, sc, star, verbose)) { if (verbose) fprintf (stderr,"TABREAD: Cannot read star %d\n", istar); break; } /* Set coordinate system for this star */ sysref = star->coorsys; eqref = star->equinox; epref = star->epoch; /* Extract selected fields */ num = star->num; ra = star->ra; dec = star->dec; rapm = star->rapm; decpm = star->decpm; parallax = star->parallax; rv = star->radvel; if (sc->entpx || sc->entrv) wcsconv (sysref, sysout, eqref, eqout, epref, epout, &ra, &dec, &rapm, &decpm, ¶llax, &rv); else if (sc->mprop == 1) wcsconp (sysref, sysout, eqref, eqout, epref, epout, &ra, &dec, &rapm, &decpm); else wcscon (sysref, sysout, eqref, eqout, &ra, &dec, epout); if (sc->sptype) peak = (1000 * (int) star->isp[0]) + (int)star->isp[1]; else peak = star->peak; if (drad > 0 || distsort) dist = wcsdist (cra,cdec,ra,dec); else dist = 0.0; /* Set magnitude for faint star rejection */ magt = star->xmag[magsort]; if (magt == 99.90 && sc->nmag > 1) magt = star->xmag[0]; if (magt == 99.90 && sc->nmag > 1) magt = star->xmag[1]; if (magt == 99.90 && sc->nmag > 2) magt = star->xmag[2]; if (magt == 99.90 && sc->nmag > 3) magt = star->xmag[3]; if (magt > 100.0) magt = magt - 100.0; /* Check magnitude and position limits */ if ((mag1 == mag2 || (magt >= mag1 && magt <= mag2)) && ((wrap && (ra >= ra1 || ra <= ra2)) || (!wrap && (ra >= ra1 && ra <= ra2))) && ((drad > 0.0 && dist < drad) || (drad == 0.0 && dec >= dec1 && dec <= dec2))) { /* Save star position and magnitude in table */ if (nstar < nstarmax) { tnum[nstar] = num; tra[nstar] = ra; tdec[nstar] = dec; if (sc->mprop == 1) { tpra[nstar] = rapm; tpdec[nstar] = decpm; } for (imag = 0; imag < sc->nmag; imag++) { if (tmag[imag] != NULL) tmag[imag][nstar] = star->xmag[imag]; } if (tpeak) tpeak[nstar] = peak; tdist[nstar] = dist; lname = strlen (star->objname); if (lname > 0) { objname = (char *)calloc (lname+1, 1); strcpy (objname, star->objname); tkey[nstar] = objname; } if (dist > maxdist) { maxdist = dist; farstar = nstar; } if (magt > faintmag) { faintmag = magt; faintstar = nstar; } } /* If radial search & too many stars, replace furthest star */ else if (distsort) { if (dist < maxdist) { tnum[farstar] = num; tra[farstar] = ra; tdec[farstar] = dec; if (sc->mprop == 1) { tpra[farstar] = rapm; tpdec[farstar] = decpm; } for (imag = 0; imag < sc->nmag; imag++) { if (tmag[imag] != NULL) tmag[imag][farstar] = star->xmag[imag]; } tpeak[farstar] = peak; tdist[farstar] = dist; lname = strlen (star->objname); if (lname > 0) { objname = (char *)calloc (lname+1, 1); strcpy (objname, star->objname); tkey[farstar] = objname; } /* Find new farthest star */ maxdist = 0.0; for (i = 0; i < nstarmax; i++) { if (tdist[i] > maxdist) { maxdist = tdist[i]; farstar = i; } } } } /* Otherwise if too many stars, replace faintest star */ else if (magt < faintmag) { tnum[faintstar] = num; tra[faintstar] = ra; tdec[faintstar] = dec; if (sc->mprop == 1) { tpra[faintstar] = rapm; tpdec[faintstar] = decpm; } for (imag = 0; imag < sc->nmag; imag++) { if (tmag[imag] != NULL) tmag[imag][faintstar] = star->xmag[imag]; } tpeak[faintstar] = peak; tdist[faintstar] = dist; lname = strlen (star->objname); if (lname > 0) { objname = (char *)calloc (lname+1, 1); strcpy (objname, star->objname); tkey[faintstar] = objname; } faintmag = 0.0; /* Find new faintest star */ for (i = 0; i < nstarmax; i++) { magt = tmag[magsort][i]; magt = tmag[magsort][i]; if (magt == 99.90 && sc->nmag > 1) magt = tmag[0][i]; if (magt == 99.90 && sc->nmag > 1) magt = tmag[0][i]; if (magt == 99.90 && sc->nmag > 2) magt = tmag[2][i]; if (magt == 99.90 && sc->nmag > 3) magt = tmag[3][i]; if (magt > 100.0) magt = magt - 100.0; if (magt > faintmag) { faintmag = magt; faintstar = i; } } } nstar++; jstar++; if (nlog == 1) fprintf (stderr,"TABREAD: %11.6f: %9.5f %9.5f %s %5.2f %d \n", num,ra,dec,cstr,magt,peak); /* End of accepted star processing */ } /* Log operation */ if (nlog > 0 && istar%nlog == 0) fprintf (stderr,"TABREAD: %5d / %5d / %5d sources catalog %s\r", jstar,istar,nstars,tabcatname); /* End of star loop */ } /* Summarize search */ if (nlog > 0) { fprintf (stderr,"TABREAD: Catalog %s : %d / %d / %d found\n",tabcatname, jstar,istar,nstars); if (nstar > nstarmax) fprintf (stderr,"TABREAD: %d stars found; only %d returned\n", nstar,nstarmax); } free ((char *)tdist); return (nstar); } /* TABRNUM -- Read tab table stars with specified numbers */ int tabrnum (tabcatname, nnum, sysout, eqout, epout, starcat, tnum,tra,tdec,tpra,tpdec,tmag,tpeak,tkey,nlog) char *tabcatname; /* Name of reference star catalog file */ int nnum; /* Number of stars to look for */ int sysout; /* Search coordinate system */ double eqout; /* Search coordinate equinox */ double epout; /* Proper motion epoch (0.0 for no proper motion) */ struct StarCat **starcat; /* Star catalog data structure */ double *tnum; /* Array of star numbers to look for */ double *tra; /* Array of right ascensions (returned) */ double *tdec; /* Array of declinations (returned) */ double *tpra; /* Array of right ascension proper motions (returned) */ double *tpdec; /* Array of declination proper motions (returned) */ double **tmag; /* 2-D array of magnitudes (returned) */ int *tpeak; /* Array of peak counts (returned) */ char **tkey; /* Array of additional keyword values */ int nlog; { int jnum; int nstar; double ra,dec, rapm, decpm; double mag, parallax, rv; double num; int peak; int istar, nstars; int imag; char *line; int sysref; /* Catalog coordinate system */ double eqref; /* Catalog equinox */ double epref; /* Catalog epoch */ char cstr[32]; char str[32]; char *objname; int lname, lstar; int ireg, inum; struct TabTable *startab; struct StarCat *sc; struct Star *star; line = 0; nstar = 0; nndec = 0; /* Allocate catalog entry buffer */ lstar = sizeof (struct Star); star = (struct Star *) calloc (1, lstar); /* Open star catalog */ sc = *starcat; if (sc == NULL) sc = tabcatopen (tabcatname, NULL, 0); *starcat = sc; if (sc == NULL || sc->nstars <= 0) { if (taberr != NULL) fprintf (stderr,"%s\n", taberr); fprintf (stderr,"TABRNUM: Cannot read catalog %s\n", tabcatname); free (star); return (0); } startab = sc->startab; nstars = sc->nstars; /* Set catalog coordinate system */ if (sc->equinox != 0.0) eqref = sc->equinox; else eqref = eqout; if (sc->epoch != 0.0) epref = sc->epoch; else epref = epout; if (sc->coorsys) sysref = sc->coorsys; else sysref = sysout; wcscstr (cstr, sysout, eqout, epout); star->num = 0.0; /* Loop through star list */ line = startab->tabdata; for (jnum = 0; jnum < nnum; jnum++) { /* Loop through catalog to star */ for (istar = 1; istar <= nstars; istar++) { if ((line = gettabline (startab, istar)) == NULL) { if (nlog) fprintf (stderr,"TABRNUM: Cannot read star %d\n", istar); break; } /* Check ID number first */ (void) setoken (&startok, line, "tab"); if (!strcmp (sc->isfil,"gsc-server")) { if (tabgetc (&startok, sc->entid, str, 24)) num = 0.0; else { num = atof (str+3) * 0.00001; ireg = (int) num; inum = (int) (((num - (double)ireg) * 100000.0) + 0.5); num = (double) ireg + 0.0001 * (double) inum; } } else num = tabgetr8 (&startok,sc->entid); if (num == 0.0) num = (double) istar; if (num == tnum[jnum]) break; } /* If star has been found in table, read rest of entry */ if (num == tnum[jnum]) { sc->istar = startab->iline; if (tabstar (istar, sc, star, nlog)) fprintf (stderr,"TABRNUM: Cannot read star %d\n", istar); /* If star entry has been read successfully */ else { /* Set coordinate system for this star */ sysref = star->coorsys; eqref = star->equinox; /* Extract selected fields */ num = star->num; ra = star->ra; dec = star->dec; rapm = star->rapm; decpm = star->decpm; parallax = star->parallax; rv = star->radvel; if (sc->entrv > 0) star->xmag[sc->nmag-1] = rv; if (sc->entpx || sc->entrv) wcsconv (sysref, sysout, eqref, eqout, epref, epout, &ra, &dec, &rapm, &decpm, ¶llax, &rv); else if (sc->mprop == 1) wcsconp (sysref, sysout, eqref, eqout, epref, epout, &ra, &dec, &rapm, &decpm); else wcscon (sysref, sysout, eqref, eqout, &ra, &dec, epout); mag = star->xmag[0]; if (sc->sptype) peak = (1000 * (int) star->isp[0]) + (int)star->isp[1]; else peak = star->peak; /* Save star position and magnitude in table */ tnum[jnum] = num; tra[jnum] = ra; tdec[jnum] = dec; if (sc->mprop == 1) { tpra[jnum] = rapm; tpdec[jnum] = decpm; } for (imag = 0; imag < sc->nmag; imag++) { if (tmag[imag] != NULL) tmag[imag][nstar] = star->xmag[imag]; } tpeak[jnum] = peak; lname = strlen (star->objname); if (lname > 0) { objname = (char *)calloc (lname+1, 1); strcpy (objname, star->objname); tkey[nstar] = objname; } nstar++; if (nlog == 1) fprintf (stderr,"TABRNUM: %11.6f: %9.5f %9.5f %s %5.2f %d \n", num,ra,dec,cstr,mag,peak); /* End of accepted star processing */ } } /* Log operation */ if (nlog > 0 && jnum%nlog == 0) fprintf (stderr,"TABRNUM: %5d / %5d / %5d sources catalog %s\r", nstar,jnum,nstars,tabcatname); /* End of star loop */ } /* Summarize search */ if (nlog > 0) fprintf (stderr,"TABRNUM: Catalog %s : %d / %d found\n", tabcatname,nstar,nstars); return (nstar); } /* TABXYREAD -- Read X, Y, and magnitude of tab table stars */ int tabxyread (tabcatname, xa, ya, ba, pa, nlog) char *tabcatname; /* Name of reference star catalog file */ double **xa; /* Array of x coordinates (returned) */ double **ya; /* Array of y coordinates (returned) */ double **ba; /* Array of magnitudes (returned) */ int **pa; /* Array of fluxes (returned) */ int nlog; { double xi, yi, magi, flux; char *line; int istar, nstars; int verbose; struct TabTable *startab; int entx, enty, entmag; /* Open tab table file */ nndec = 0; startab = tabopen (tabcatname, 0); if (startab == NULL || startab->nlines <= 0) { fprintf (stderr,"TABXYREAD: Cannot read catalog %s\n", tabcatname); return (0); } /* Find columns for X, Y, and magnitude */ if (!(entx = tabcol (startab, "X"))) entx = tabcol (startab, "x"); if (!(enty = tabcol (startab, "Y"))) enty = tabcol (startab, "y"); if (!(entmag = tabcol (startab, "MAG"))) entmag = tabcol (startab, "mag"); /* Allocate vectors for x, y, magnitude, and flux */ nstars = startab->nlines; *xa = (double *) realloc(*xa, nstars*sizeof(double)); if (*xa == NULL) { fprintf (stderr,"TABXYREAD: Cannot allocate memory for x\n"); return (0); } *ya = (double *) realloc(*ya, nstars*sizeof(double)); if (*ya == NULL) { fprintf (stderr,"TABXYREAD: Cannot allocate memory for y\n"); return (0); } *ba = (double *) realloc(*ba, nstars*sizeof(double)); if (*ba == NULL) { fprintf (stderr,"TABXYREAD: Cannot allocate memory for mag\n"); return (0); } *pa = (int *) realloc(*pa, nstars*sizeof(int)); if (*pa == NULL) { fprintf (stderr,"TABXYREAD: Cannot allocate memory for flux\n"); return (0); } /* Loop through catalog */ for (istar = 0; istar < nstars; istar++) { /* Read line for next star */ if ((line = gettabline (startab, istar)) == NULL) { fprintf (stderr,"TABXYREAD: Cannot read star %d\n", istar); break; } /* Extract x, y, and magnitude */ (void) setoken (&startok, line, "tab"); xi = tabgetr8 (&startok, entx); yi = tabgetr8 (&startok, enty); magi = tabgetr8 (&startok, entmag); (*xa)[istar] = xi; (*ya)[istar] = yi; (*ba)[istar] = magi; flux = pow (10.0, (-magi / 2.5)); (*pa)[istar] = (int) flux; if (nlog == 1) fprintf (stderr,"DAOREAD: %6d/%6d: %9.5f %9.5f %6.2f %15.4f\n", istar,nstars,xi,yi,magi,flux); /* Log operation */ if (nlog > 1 && istar%nlog == 0) fprintf (stderr,"TABXYREAD: %5d / %5d sources catalog %s\r", istar,nstars,tabcatname); /* End of star loop */ } /* Summarize search */ if (nlog > 0) fprintf (stderr,"TABXYREAD: Catalog %s : %d / %d found\n",tabcatname, istar,nstars); /* Free table */ tabclose (startab); if (istar < nstars-1) return (istar + 1); else return (nstars); } #define TABMAX 64 /* TABRKEY -- Read single keyword from tab table stars with specified numbers */ int tabrkey (tabcatname, starcat, nnum, tnum, keyword, tval) char *tabcatname; /* Name of reference star catalog file */ struct StarCat **starcat; /* Star catalog data structure */ int nnum; /* Number of stars to look for */ double *tnum; /* Array of star numbers to look for */ char *keyword; /* Keyword for which to return values */ char **tval; /* Returned values for specified keyword */ { int jnum, lval; int nstar; int istar, nstars; double num; char *line; char *tvalue; char value[TABMAX]; struct TabTable *startab; struct StarCat *sc; /* Star catalog data structure */ nstar = 0; /* Open star catalog */ sc = *starcat; if (sc == NULL) sc = tabcatopen (tabcatname, NULL, 0); *starcat = sc; if (sc == NULL || sc->nstars <= 0) { if (taberr != NULL) fprintf (stderr,"%s\n", taberr); fprintf (stderr,"TABRKEY: Cannot read catalog %s\n", tabcatname); return (0); } startab = sc->startab; if (startab == NULL || startab->nlines <= 0) { fprintf (stderr,"TABRKEY: Cannot read catalog %s\n", tabcatname); return (0); } /* Loop through star list */ nstars = startab->nlines; for (jnum = 0; jnum < nnum; jnum++) { /* Loop through catalog to star */ for (istar = 1; istar <= nstars; istar++) { if ((line = gettabline (startab, istar)) == NULL) { fprintf (stderr,"TABRKEY: Cannot read star %d\n", istar); num = 0.0; break; } /* Check ID number */ (void) setoken (&startok, line, "tab"); if ((num = tabgetr8 (&startok,line,sc->entid)) == 0.0) num = (double) istar; if (num == tnum[jnum]) break; } /* If star has been found in table */ if (num == tnum[jnum]) { nstar++; /* Extract selected field */ (void) tabgetk (startab, &startok, keyword, value, TABMAX); lval = strlen (value); if (lval > 0) { tvalue = (char *) calloc (1, lval+1); strcpy (tvalue, value); } else tvalue = NULL; tval[jnum] = tvalue; } } return (nstars); } static char newline = 10; static char tab = 9; /* TABCATOPEN -- Open tab table catalog, returning number of entries */ struct StarCat * tabcatopen (tabpath, tabtable, nbbuff) char *tabpath; /* Tab table catalog file pathname */ struct TabTable *tabtable; int nbbuff; /* Number of bytes in buffer; 0=read whole file */ { char cstr[32]; char *tabname; struct TabTable *startab; struct StarCat *sc; int i, lnum, ndec, istar, nbsc; char *line; double dnum; /* Open the tab table file */ if (tabtable != NULL) startab = tabtable; else if ((startab = tabopen (tabpath, nbbuff)) == NULL) return (NULL); /* Allocate catalog data structure */ nbsc = sizeof (struct StarCat); sc = (struct StarCat *) calloc (1, nbsc); sc->startab = startab; /* Save name of catalog */ tabname = strrchr (tabpath, '/'); if (tabname) tabname = tabname + 1; else tabname = tabpath; if (strlen (tabname) < 24) strcpy (sc->isfil, tabname); else { strncpy (sc->isfil, tabname, 23); sc->isfil[23] = (char) 0; } /* Find column and name of object identifier */ sc->entid = -1; sc->keyid[0] = (char) 0; if ((sc->entid = tabcol (startab, "ID"))) strcpy (sc->keyid, "ID"); else if ((sc->entid = tabcol (startab, "id"))) strcpy (sc->keyid, "id"); else if ((sc->entid = tabcont (startab, "_id"))) { i = sc->entid - 1; strncpy (sc->keyid, startab->colname[i], startab->lcol[i]); } else if ((sc->entid = tabcont (startab, "ID"))) { i = sc->entid - 1; strncpy (sc->keyid, startab->colname[i], startab->lcol[i]); } else if ((sc->entid = tabcont (startab, "name"))) { i = sc->entid - 1; strncpy (sc->keyid, startab->colname[i], startab->lcol[i]); } sc->nndec = nndec; /* Find column and name of object right ascension */ sc->entra = -1; sc->keyra[0] = (char) 0; if ((sc->entra = tabcol (startab, "RA"))) strcpy (sc->keyra, "RA"); else if ((sc->entra = tabcol (startab, "ra"))) strcpy (sc->keyra, "ra"); else if ((sc->entra = tabcol (startab, "Ra"))) strcpy (sc->keyra, "ra"); else if ((sc->entra = tabcont (startab, "ra"))) { i = sc->entra - 1; strncpy (sc->keyra, startab->colname[i], startab->lcol[i]); } /* Find column and name of object declination */ sc->entdec = -1; sc->keydec[0] = (char) 0; if ((sc->entdec = tabcol (startab, "DEC"))) strcpy (sc->keydec, "DEC"); else if ((sc->entdec = tabcol (startab, "dec"))) strcpy (sc->keydec, "dec"); else if ((sc->entdec = tabcol (startab, "Dec"))) strcpy (sc->keydec, "dec"); else if ((sc->entdec = tabcont (startab, "dec"))) { i = sc->entdec; strncpy (sc->keydec, startab->colname[i], startab->lcol[i]); } /* Find column and name of object first magnitude */ sc->entmag1 = -1; sc->keymag1[0] = (char) 0; if ((sc->entmag1 = tabcol (startab, "MAG"))) strcpy (sc->keymag1, "mag"); else if ((sc->entmag1 = tabcol (startab, "mag"))) strcpy (sc->keymag1, "mag"); else if ((sc->entmag1 = tabcol (startab, "magv"))) strcpy (sc->keymag1, "magv"); else if ((sc->entmag1 = tabcol (startab, "magr"))) strcpy (sc->keymag1, "magr"); else if ((sc->entmag1 = tabcol (startab, "magj"))) strcpy (sc->keymag1, "magj"); else if ((sc->entmag1 = tabcol (startab, "Fmag"))) strcpy (sc->keymag1, "Fmag"); else if ((sc->entmag1 = tabcont (startab, "mag"))) { i = sc->entmag1 - 1; strncpy (sc->keymag1, startab->colname[i], startab->lcol[i]); } /* Find column and name of object second magnitude */ sc->entmag2 = -1; sc->keymag2[0] = (char) 0; if ((sc->entmag2 = tabcol (startab, "magb"))) strcpy (sc->keymag2, "magb"); else if ((sc->entmag2 = tabcol (startab, "magr"))) strcpy (sc->keymag2, "magr"); else if ((sc->entmag2 = tabcol (startab, "magh"))) strcpy (sc->keymag2, "magh"); else if ((sc->entmag2 = tabcol (startab, "Jmag"))) strcpy (sc->keymag2, "Jmag"); /* Find column and name of object third magnitude */ sc->entmag3 = -1; sc->keymag3[0] = (char) 0; if ((sc->entmag3 = tabcol (startab, "magk"))) strcpy (sc->keymag3, "magk"); else if ((sc->entmag3 = tabcol (startab, "Vmag"))) strcpy (sc->keymag3, "Vmag"); /* Find column and name of object third magnitude */ sc->entmag4 = -1; sc->keymag4[0] = (char) 0; if ((sc->entmag4 = tabcol (startab, "Nmag"))) strcpy (sc->keymag4, "Nmag"); /* Set number of magnitudes */ if (sc->entmag1 && sc->entmag2 && sc->entmag3 && sc->entmag4) sc->nmag = 4; else if (sc->entmag1 && sc->entmag2 && sc->entmag3) sc->nmag = 3; else if (sc->entmag1 && sc->entmag2) sc->nmag = 2; else if (sc->entmag1) sc->nmag = 1; else sc->nmag = 0; /* Find column and name of object right ascension proper motion */ sc->entrpm = -1; sc->keyrpm[0] = (char) 0; if ((sc->entrpm = tabcol (startab, "ura"))) strcpy (sc->keyrpm, "ura"); else if ((sc->entrpm = tabcol (startab, "rapm"))) strcpy (sc->keyrpm, "rapm"); else if ((sc->entrpm = tabcol (startab, "ux"))) strcpy (sc->keyrpm, "ux"); /* Find column and name of object declination proper motion */ sc->entdpm = -1; sc->keydpm[0] = (char) 0; if ((sc->entdpm = tabcol (startab, "udec"))) strcpy (sc->keydpm, "udec"); else if ((sc->entdpm = tabcol (startab, "decpm"))) strcpy (sc->keydpm, "decpm"); else if ((sc->entdpm = tabcol (startab, "uy"))) strcpy (sc->keydpm, "uy"); /* Find units for RA proper motion */ sc->mprop = 0; cstr[0] = 0; if (!tabhgetc (startab,"RPMUNIT", cstr)) { if (!tabhgetc (startab,"rpmunit", cstr)) { if (!tabhgetc (startab,"pmunit", cstr)) tabhgetc (startab,"pmunit", cstr); } } if (strlen (cstr) > 0) { sc->mprop = 1; if (!strcmp (cstr, "mas/yr") || !strcmp (cstr, "mas/year")) sc->rpmunit = PM_MASYR; else if (!strcmp (cstr, "ms/yr") || !strcmp (cstr, "millisec/year")) sc->rpmunit = PM_MTSYR; else if (!strcmp (cstr, "arcsec/yr") || !strcmp (cstr, "arcsec/year")) sc->rpmunit = PM_ARCSECYR; else if (!strcmp (cstr, "arcsec/cen") || !strcmp (cstr, "arcsec/century")) sc->rpmunit = PM_ARCSECCEN; else if (!strcmp (cstr, "rad/yr") || !strcmp (cstr, "rad/year")) sc->rpmunit = PM_RADYR; else if (!strcmp (cstr, "sec/yr") || !strcmp (cstr, "sec/year")) sc->rpmunit = PM_TSECYR; else if (!strcmp (cstr, "tsec/yr") || !strcmp (cstr, "tsec/year")) sc->rpmunit = PM_TSECYR; else if (!strcmp (cstr, "tsec/cen") || !strcmp (cstr, "tsec/century")) sc->rpmunit = PM_TSECCEN; else sc->rpmunit = PM_DEGYR; } else if (sc->entrpm > 0) sc->rpmunit = PM_TSECCEN; /* Find units for Dec proper motion */ cstr[0] = 0; if (!tabhgetc (startab,"DPMUNIT", cstr)) { if (!tabhgetc (startab,"dpmunit", cstr)) { if (!tabhgetc (startab,"pmunit", cstr)) tabhgetc (startab,"pmunit", cstr); } } if (strlen (cstr) > 0) { sc->mprop = 1; if (!strcmp (cstr, "mas/yr") || !strcmp (cstr, "mas/year")) sc->dpmunit = PM_MASYR; else if (!strcmp (cstr, "sec/yr") || !strcmp (cstr, "sec/year")) sc->dpmunit = PM_ARCSECYR; else if (!strcmp (cstr, "tsec/yr") || !strcmp (cstr, "tsec/year")) sc->dpmunit = PM_ARCSECYR; else if (!strcmp (cstr, "arcsec/cen") || !strcmp (cstr, "arcsec/century")) sc->dpmunit = PM_ARCSECCEN; else if (!strcmp (cstr, "arcsec/yr") || !strcmp (cstr, "arcsec/year")) sc->dpmunit = PM_ARCSECYR; else if (!strcmp (cstr, "rad/yr") || !strcmp (cstr, "rad/year")) sc->dpmunit = PM_RADYR; else sc->dpmunit = PM_DEGYR; } else if (sc->entdpm > 0) sc->dpmunit = PM_ARCSECCEN; /* Find column for parallax */ sc->entpx = 0; sc->entpx = tabcol (startab, "px"); /* Find column for parallax error */ sc->entpxe = 0; sc->entpxe = tabcol (startab, "pxerr"); /* Find column for radial velocity */ sc->entrv = 0; sc->keyrv[0] = (char) 0; if ((sc->entrv = tabcol (startab, "rv"))) strcpy (sc->keyrv, "rv"); else if ((sc->entrv = tabcol (startab, "cz"))) strcpy (sc->keyrv, "cz"); if (sc->entrv > 0 && sc->nmag < 2) { if (sc->nmag == 0) strcpy (sc->keymag1, sc->keyrv); else strcpy (sc->keymag2, sc->keyrv); sc->nmag = sc->nmag + 1; } /* Find column and name of object peak or plate number */ sc->entpeak = -1; sc->keypeak[0] = (char) 0; if ((sc->entpeak = tabcol (startab, "PEAK"))) strcpy (sc->keypeak, "PEAK"); else if ((sc->entpeak = tabcol (startab, "peak"))) strcpy (sc->keypeak, "peak"); else if ((sc->entpeak = tabcol (startab, "plate"))) { strcpy (sc->keypeak, "plate"); sc->plate = 1; } else if ((sc->entpeak = tabcol (startab, "field"))) { strcpy (sc->keypeak, "field"); sc->plate = 1; } /* Find column and name of object spectral type */ sc->enttype = 0; sc->keytype[0] = (char) 0; if ((sc->enttype = tabcol (startab, "TYPE"))) strcpy (sc->keytype, "TYPE"); else if ((sc->enttype = tabcol (startab, "type"))) strcpy (sc->keytype, "type"); else if ((sc->enttype = tabcol (startab, "SpT"))) strcpy (sc->keytype, "spt"); else if ((sc->enttype = tabcol (startab, "spt"))) strcpy (sc->keytype, "spt"); else if ((sc->enttype = tabcont (startab, "typ"))) { i = sc->enttype - 1; strncpy (sc->keytype, startab->colname[i], startab->lcol[i]); } if (sc->enttype > 0) sc->sptype = 1; sc->entadd = -1; sc->keyadd[0] = (char) 0; if (kwo != NULL) sc->entadd = tabcol (startab, kwo); /* Set catalog coordinate system */ sc->coorsys = 0; sc->equinox = 0.0; sc->epoch = 0.0; if (tabhgetc (startab,"RADECSYS", cstr)) { sc->coorsys = wcscsys (cstr); if (!tabhgetr8 (startab,"EQUINOX", &sc->equinox)) sc->equinox = wcsceq (cstr); if (!tabhgetr8 (startab,"EPOCH",&sc->epoch)) sc->epoch = sc->equinox; } if (tabhgetc (startab,"radecsys", cstr)) { sc->coorsys = wcscsys (cstr); if (!tabhgetr8 (startab,"equinox", &sc->equinox)) sc->equinox = wcsceq (cstr); if (!tabhgetr8 (startab,"epoch",&sc->epoch)) sc->epoch = sc->equinox; } else if (tabhgetr8 (startab,"EQUINOX", &sc->equinox)) { if (!tabhgetr8 (startab,"EPOCH",&sc->epoch)) sc->epoch = sc->equinox; if (sc->equinox == 1950.0) sc->coorsys = WCS_B1950; else sc->coorsys = WCS_J2000; } else if (tabhgetr8 (startab,"equinox", &sc->equinox)) { if (!tabhgetr8 (startab,"epoch",&sc->epoch)) sc->epoch = sc->equinox; if (sc->equinox == 1950.0) sc->coorsys = WCS_B1950; else sc->coorsys = WCS_J2000; } else if (tabhgetr8 (startab,"EPOCH", &sc->epoch)) { sc->equinox = sc->epoch; if (sc->equinox == 1950.0) sc->coorsys = WCS_B1950; else sc->coorsys = WCS_J2000; } else if (tabhgetr8 (startab,"epoch", &sc->epoch)) { sc->equinox = sc->epoch; if (sc->equinox == 1950.0) sc->coorsys = WCS_B1950; else sc->coorsys = WCS_J2000; } /* Set other stuff */ sc->rasorted = 0; sc->nstars = startab->nlines; if (sc->entid) sc->stnum = 1; else sc->stnum = 0; /* Find out if ID is number, and if so, how many decimal places it has */ if (sc->entid) { istar = 1; if ((line = gettabline (startab, istar)) == NULL) { fprintf (stderr,"TABCATOPEN: Cannot read first star\n"); tabcatclose (sc); return (NULL); } if (setoken (&startok, line, "tab") < 2) { fprintf (stderr,"TABCATOPEN: First star has too few columns\n"); tabcatclose (sc); return (NULL); } tabgetc (&startok, sc->entid, cstr, 32); /* Find length of identifier */ sc->nnfld = strlen (cstr); /* Find number of decimal places in identifier */ if (tabhgeti4 (startab, "ndec", &nndec)) { sc->nndec = nndec; if (!isnum (cstr)) sc->stnum = -nndec; } else if (isnum (cstr)) { dnum = tabgetr8 (&startok,sc->entid); sprintf (cstr,"%.0f", (dnum * 100000000.0) + 0.1); lnum = strlen (cstr); for (i = 0; i < 8; i++) { if (cstr[lnum-i-1] != '0') { ndec = 8 - i; if (ndec > nndec) { nndec = ndec; sc->nndec = nndec; } break; } } sc->nndec = nndec; } else { sc->stnum = -strlen (cstr); sc->nndec = nndec; } } sc->refcat = TABCAT; return (sc); } /* TABCATCLOSE -- Close tab table catalog and free associated data structures */ void tabcatclose (sc) struct StarCat *sc; { tabclose (sc->startab); free (sc); return; } /* TABSTAR -- Get tab table catalog entry for one star; return 0 if successful, else -1 */ int tabstar (istar, sc, st, verbose) int istar; /* Star sequence number in tab table catalog */ struct StarCat *sc; /* Star catalog data structure */ struct Star *st; /* Star data structure, updated on return */ int verbose; /* 1 to print error messages */ { struct TabTable *startab = sc->startab; char *line; char *uscore; char cnum[32]; char *cn; int ndec, i; int lnum, ireg, inum; if ((line = gettabline (startab, istar)) == NULL) { if (verbose) fprintf (stderr,"TABSTAR: Cannot read star %d\n", istar); return (-1); } /* Parse line for rapid field extraction */ if (setoken (&startok, line, "tab") < 2) { fprintf (stderr,"TABSTAR: Star %d entry too short\n", istar); return (-1); } /* Extract ID */ st->objname[0] = (char) 0; if (sc->entid) { tabgetc (&startok, sc->entid, cnum, 32); if (!strcmp (sc->isfil,"usnoa-server")) { if ((uscore = strchr (cnum, '_')) != NULL) *uscore = '.'; cn = cnum + 1; } else if (!strcmp (sc->isfil,"gsc-server")) cn = cnum + 3; else cn = cnum; if (isnum (cn) || isnum (cn+1)) { if (isnum(cnum)) st->num = atof (cn); else { if (cnum[0] == 'S') st->num = -atof (cn+1); else st->num = atof (cn+1); } if (!strcmp (sc->isfil,"gsc-server")) { ireg = atoi (cn) / 100000; inum = atoi (cn) % 100000; st->num = (double) ireg + 0.0001 * (double) inum; } /* Find field length of identifier */ sc->nnfld = strlen (cn); /* Find number of decimal places in identifier */ if (strchr (cn,'.') == NULL) { nndec = 0; sc->nndec = nndec; } else { sprintf (cn,"%.0f", (st->num * 100000000.0) + 0.1); lnum = strlen (cnum); for (i = 0; i < 8; i++) { if (cn[lnum-i-1] != '0') { ndec = 8 - i; if (ndec > nndec) { nndec = ndec; sc->nndec = nndec; } break; } } } } else { strcpy (st->objname, cnum); st->num = st->num + 1.0; } } else { st->num = (double) istar; nndec = 0; sc->nndec = nndec; } /* Right ascension */ st->ra = tabgetra (&startok, sc->entra); /* Declination */ st->dec = tabgetdec (&startok, sc->entdec); /* Magnitudes */ st->xmag[0] = tabgetr8 (&startok, sc->entmag1); if (sc->entmag2) st->xmag[1] = tabgetr8 (&startok, sc->entmag2); else st->xmag[1] = 0.0; if (sc->entmag3) st->xmag[2] = tabgetr8 (&startok, sc->entmag3); else st->xmag[2] = 0.0; if (sc->entmag4) st->xmag[3] = tabgetr8 (&startok, sc->entmag4); else st->xmag[3] = 0.0; /* Right ascension proper motion */ st->rapm = tabgetr8 (&startok, sc->entrpm); if (sc->rpmunit == PM_MASYR) st->rapm = st->rapm / 3600000.0; else if (sc->rpmunit == PM_MTSYR) st->rapm = st->rapm / 240000.0; else if (sc->rpmunit == PM_ARCSECYR) st->rapm = st->rapm / 3600.0; else if (sc->rpmunit == PM_ARCSECCEN) st->rapm = st->rapm / 360000.0; else if (sc->rpmunit == PM_TSECYR) st->rapm = st->rapm / 240.0; else if (sc->rpmunit == PM_TSECCEN) st->rapm = st->rapm / 24000.0; else if (sc->rpmunit == PM_RADYR) st->rapm = raddeg (st->rapm); else st->rapm = 0.0; /* Declination proper motion */ st->decpm = tabgetr8 (&startok, sc->entdpm); if (sc->dpmunit == PM_MASYR) st->decpm = st->decpm / 3600000.0; else if (sc->dpmunit == PM_ARCSECYR) st->decpm = st->decpm / 3600.0; else if (sc->dpmunit == PM_ARCSECCEN) st->decpm = st->decpm / 360000.0; else if (sc->dpmunit == PM_RADYR) st->decpm = raddeg (st->decpm); else st->decpm = 0.0; /* Parallax */ if (sc->entpx) st->parallax = tabgetr8 (&startok, sc->entpx); else st->parallax = 0.0; /* Radial velocity */ if (sc->entrv) st->radvel = tabgetr8 (&startok, sc->entrv); else st->radvel = 0.0; /* Peak counts */ if (sc->entpeak > 0) st->peak = tabgeti4 (&startok, sc->entpeak); else st->peak = 0; /* Spectral type */ if (sc->enttype > 0) tabgetc (&startok, sc->enttype, st->isp, 24); /* Extract selected field */ if (kwo != NULL) (void) tabgetk (startab, &startok, kwo, st->objname, 32); st->coorsys = sc->coorsys; st->equinox = sc->equinox; st->epoch = sc->epoch; return (0); } /* TABOPEN -- Open tab table file, returning number of entries */ struct TabTable * tabopen (tabfile, nbbuff) char *tabfile; /* Tab table catalog file name */ int nbbuff; /* Number of bytes in buffer; 0=read whole file */ { FILE *fcat; int nr, lfile, lfname, lfa, lname, lline; char *tabnew, *tabline, *lastline; char *tabcomma, *nextline; char *thisname, *tabname; int thistab, itab, nchar, nbtab; int formfeed = (char) 12; struct TabTable *tabtable; tabcomma = NULL; if (taberr != NULL) { free (taberr); taberr = NULL; } tabname = NULL; if (!strcmp (tabfile, "stdin")) { lfile = 100000; fcat = stdin; } else { /* Separate table name from file name, if necessary */ if ((tabcomma = strchr (tabfile, ',')) != NULL) { tabname = (char *) calloc (1,64); strcpy (tabname, tabcomma+1); *tabcomma = (char) 0; } /* Find length of tab table catalog */ lfile = tabsize (tabfile); if (nbbuff > 1 && nbbuff < lfile) lfile = nbbuff; else if (nbbuff == 1 && lfile > 10000) lfile = 10000; if (lfile < 1) { taberr = (char *) calloc (64 + strlen (tabfile), 1); sprintf (taberr,"TABOPEN: Tab table file %s has no entries", tabfile); if (tabcomma != NULL) *tabcomma = ','; return (NULL); } /* Open tab table catalog */ if (!(fcat = fopen (tabfile, "r"))) { taberr = (char *) calloc (64 + strlen (tabfile), 1); sprintf (taberr,"TABOPEN: Tab table file %s cannot be read", tabfile); if (tabcomma != NULL) *tabcomma = ','; return (NULL); } } /* Allocate tab table structure */ nbtab = sizeof(struct TabTable); if ((tabtable=(struct TabTable *) calloc(1,nbtab)) == NULL){ taberr = (char *) calloc (64 + strlen (tabfile), 1); sprintf (taberr,"TABOPEN: cannot allocate Tab Table structure for %s", tabfile); if (tabcomma != NULL) *tabcomma = ','; return (NULL); } tabtable->tabname = tabname; /* Allocate space in structure for filename and save it */ lname = strlen (tabfile) + 2; if ((tabtable->filename = (char *)calloc (1, lname)) == NULL) { taberr = (char *) calloc (64 + strlen (tabfile), 1); sprintf (taberr,"TABOPEN: cannot allocate filename %s in structure", tabfile); (void) fclose (fcat); tabclose (tabtable); if (tabcomma != NULL) *tabcomma = ','; return (NULL); } strcpy (tabtable->filename, tabfile); /* Allocate buffer to hold entire catalog (or buffer length) and read it */ if ((tabtable->tabbuff = (char *) calloc (1, lfile+2)) == NULL) { taberr = (char *) calloc (64 + strlen (tabfile), 1); sprintf (taberr,"TABOPEN: cannot allocate buffer for tab table %s", tabfile); (void) fclose (fcat); tabclose (tabtable); if (tabcomma != NULL) *tabcomma = ','; return (NULL); } else { nr = fread (tabtable->tabbuff, 1, lfile, fcat); if (fcat != stdin && nr < lfile) { fprintf (stderr,"TABOPEN: read only %d / %d bytes of file %s\n", nr, lfile, tabfile); (void) fclose (fcat); tabclose (tabtable); if (tabcomma != NULL) *tabcomma = ','; return (NULL); } tabtable->tabbuff[lfile] = (char) 0; /* Check for named table within a file */ if (tabname != NULL) { if (isnum (tabname)) { itab = atoi (tabname); thisname = tabtable->tabbuff; thistab = 1; if (itab > 1) { while (thistab < itab && thisname != NULL) { thisname = strchr (thisname, formfeed); if (thisname != NULL) thisname++; thistab++; } } if (thisname == NULL) { fprintf (stderr, "GETTAB: There are < %d tables in %s\n", itab, tabfile); return (NULL); } while (*thisname==' ' || *thisname==newline || *thisname==formfeed || *thisname==(char)13) thisname++; tabline = strchr (thisname, newline); if (tabline != NULL) { nchar = tabline - thisname; if (strchr (thisname, tab) > tabline) strncpy (tabtable->tabname, thisname, nchar); } } else { lname = strlen (tabname); thisname = tabtable->tabbuff; while (*thisname != NULL) { while (*thisname==' ' || *thisname==newline || *thisname==formfeed || *thisname==(char)13) thisname++; if (!strncmp (tabname, thisname, lname)) break; else thisname = strchr (thisname, formfeed); } } if (thisname == NULL) { fprintf (stderr, "TABOPEN: table %s in file %s not found\n", tabname, tabfile); if (tabcomma != NULL) *tabcomma = ','; return (NULL); } else tabtable->tabheader = strchr (thisname, newline) + 1; } else tabtable->tabheader = tabtable->tabbuff; tabline = tabtable->tabheader; lastline = NULL; while (*tabline!='-' && tabline!=NULL && tabline < tabtable->tabbuff+lfile) { lastline = tabline; if ((tabline = strchr (lastline,newline)) != NULL) tabline++; else break; } if (tabline == NULL || *tabline != '-') { taberr = (char *) calloc (64 + strlen (tabfile), 1); sprintf (taberr,"TABOPEN: No - line in tab table %s",tabfile); (void) fclose (fcat); tabclose (tabtable); if (tabcomma != NULL) *tabcomma = ','; return (NULL); } tabtable->tabhead = lastline; tabtable->tabdata = strchr (tabline, newline) + 1; /* Extract positions of keywords we will want to use */ if (!tabparse (tabtable)) { fprintf (stderr,"TABOPEN: No columns in tab table %s\n",tabfile); (void) fclose (fcat); tabclose (tabtable); if (tabcomma != NULL) *tabcomma = ','; return (NULL); } /* Enumerate entries in tab table catalog by counting newlines */ if (nbbuff > 0) tabtable->nlines = 10000000; else { tabnew = tabtable->tabdata; tabtable->nlines = 0; while ((tabnew = strchr (tabnew, newline)) != NULL) { tabnew = tabnew + 1; tabtable->nlines = tabtable->nlines + 1; if (*tabnew == formfeed) break; } } } /* Set up line buffer, and put first line in it */ if (nbbuff > 0) { tabtable->lhead = tabtable->tabdata - tabtable->tabheader; tabtable->tcat = fcat; nextline = strchr (tabtable->tabdata, newline) + 1; tabtable->lline = (nextline - tabtable->tabdata) * 2; tabtable->tabline = (char *) calloc (tabtable->lline, 1); fseek (tabtable->tcat, (long) tabtable->lhead, SEEK_SET); fgets (tabtable->tabline, tabtable->lline, tabtable->tcat); lline = strlen (tabtable->tabline); if (tabtable->tabline[lline-1] < 32) tabtable->tabline[lline-1] = (char) 0; tabtable->tabdata = tabtable->tabline; } /* Close catalog file if not reading one line at a time */ else { tabtable->lhead = 0; (void) fclose (fcat); tabtable->tcat = NULL; } tabtable->tabline = tabtable->tabdata; tabtable->iline = 1; if (tabcomma != NULL) *tabcomma = ','; return (tabtable); } void tabclose (tabtable) struct TabTable *tabtable; { if (tabtable != NULL) { if (tabtable->filename != NULL) free (tabtable->filename); if (tabtable->tabname != NULL) free (tabtable->tabname); if (tabtable->tabbuff != NULL) free (tabtable->tabbuff); if (tabtable->colname != NULL) free (tabtable->colname); if (tabtable->lcol != NULL) free (tabtable->lcol); if (tabtable->lcfld != NULL) free (tabtable->lcfld); if (tabtable->tcat != NULL) fclose (tabtable->tcat); free (tabtable); } return; } /* TABLINE -- Get tab table entry for one line; return NULL if unsuccessful */ char * gettabline (tabtable, iline) struct TabTable *tabtable; /* Tab table structure */ int iline; /* Line sequence number in tab table */ { char *nextline = tabtable->tabline; char *next; int lline, i; /* Return NULL if tab table has not been opened */ if (tabtable == NULL) return (NULL); /* Read one line at a time if file is still open */ if (tabtable->tcat != NULL) { /* Return current line from buffer */ if (iline == tabtable->iline) return (tabtable->tabline); /* Read next line from file */ if (iline < 1 || iline > tabtable->iline) { for (i = tabtable->iline; i < iline; i++) { next = fgets (tabtable->tabline, tabtable->lline, tabtable->tcat); if (next == NULL || *next == EOF) return (NULL); tabtable->iline++; } lline = strlen (tabtable->tabline); if (lline < 2) return (NULL); if (tabtable->tabline[lline-1] < 32) tabtable->tabline[lline-1] = (char) 0; } else if (iline < tabtable->iline) { fseek (tabtable->tcat, (long) tabtable->lhead, SEEK_SET); tabtable->iline = 0; for (i = tabtable->iline; i < iline; i++) { fgets (tabtable->tabline, tabtable->lline, tabtable->tcat); tabtable->iline++; } lline = strlen (tabtable->tabline); if (tabtable->tabline[lline-1] < 32) tabtable->tabline[lline-1] = (char) 0; } return (tabtable->tabline); } /* Return NULL if trying to read past last line */ if (iline > tabtable->nlines) { fprintf (stderr, "TABLINE: line %d is not in table\n",iline); return (NULL); } /* If iline is 0 or less, just read next line from table */ else if (iline < 1 && nextline) { tabtable->iline++; if (tabtable->iline > tabtable->nlines) { fprintf (stderr, "TABLINE: line %d is not in table\n",iline); return (NULL); } nextline = strchr (nextline, newline) + 1; } /* If iline is before current line, read from start of file */ else if (iline < tabtable->iline) { tabtable->iline = 1; tabtable->tabline = tabtable->tabdata; while (tabtable->iline < iline) { tabtable->tabline = strchr (tabtable->tabline, newline) + 1; tabtable->iline ++; } } /* If iline is after current line, read forward */ else if (iline > tabtable->iline) { while (tabtable->iline < iline) { tabtable->tabline = strchr (tabtable->tabline, newline) + 1; tabtable->iline ++; } } return (tabtable->tabline); } /* TABGETRA -- returns double right ascension in degrees */ double tabgetra (tabtok, ientry) struct Tokens *tabtok; /* Line token structure */ int ientry; /* sequence of entry on line */ { char str[24]; if (tabgetc (tabtok, ientry, str, 24)) return (0.0); else return (str2ra (str)); } /* TABGETDEC -- returns double declination in degrees */ double tabgetdec (tabtok, ientry) struct Tokens *tabtok; /* Line token structure */ int ientry; /* sequence of entry on line */ { char str[24]; if (tabgetc (tabtok, ientry, str, 24)) return (0.0); else return (str2dec (str)); } /* TABGETR8 -- returns 8-byte floating point number from tab table line */ double tabgetr8 (tabtok, ientry) struct Tokens *tabtok; /* Line token structure */ int ientry; /* sequence of entry on line */ { char str[24]; if (tabgetc (tabtok, ientry, str, 24)) return (0.0); else if (isnum (str)) return (atof (str)); else return (0.0); } /* TABGETI4 -- returns a 4-byte integer from tab table line */ int tabgeti4 (tabtok, ientry) struct Tokens *tabtok; /* Line token structure */ int ientry; /* sequence of entry on line */ { char str[24]; if (tabgetc (tabtok, ientry, str, 24)) return (0); else if (isnum (str)) return ((int) atof (str)); else return (0); } /* TABGETK -- returns a character entry from tab table line for named column */ int tabgetk (tabtable, tabtok, keyword, string, maxchar) struct TabTable *tabtable; /* Tab table structure */ struct Tokens *tabtok; /* Line token structure */ char *keyword; /* column header of desired value */ char *string; /* character string (returned) */ int maxchar; /* Maximum number of characters in returned string */ { int ntok; int ientry = tabcol (tabtable, keyword); return (tabgetc (tabtok, ientry, string, maxchar)); } /* TABGETC -- returns n'th entry from tab table line as character string */ int tabgetc (tabtok, ientry, string, maxchar) struct Tokens *tabtok; /* Line token structure */ int ientry; /* Sequence of entry on line (1-ncol) */ char *string; /* Character string (returned) */ int maxchar; /* Maximum number of characters in returned string */ { if (getoken (tabtok, ientry, string, maxchar)) return (0); else return (-1); } /* TABHGETR8 -- read an 8-byte floating point number from a tab table header */ static int tabhgetr8 (tabtable, keyword, result) struct TabTable *tabtable; /* Tab table structure */ char *keyword; /* sequence of entry on line */ double *result; { char value[24]; if (tabhgetc (tabtable, keyword, value)) { *result = atof (value); return (1); } else return (0); } /* TABHGETI4 -- read a 4-byte integer from a tab table header */ static int tabhgeti4 (tabtable, keyword, result) struct TabTable *tabtable; /* Tab table structure */ char *keyword; /* sequence of entry on line */ int *result; { char value[24]; if (tabhgetc (tabtable, keyword, value)) { *result = (int) atof (value); return (1); } else return (0); } /* TABHGETC -- read a string from a tab table header */ static int tabhgetc (tabtable, keyword, result) struct TabTable *tabtable; /* Tab table structure */ char *keyword; /* sequence of entry on line */ char *result; { char *str0, *str1, *line, *head, keylow[24], keyup[24]; int ncstr, lkey, i; head = tabtable->tabbuff; str0 = 0; /* Make all-upper-case and all-lower-case versions of keyword */ lkey = strlen (keyword); for (i = 0; i < lkey; i++) { if (keyword[i] > 96 && keyword[i] < 123) keyup[i] = keyword[i] - 32; else keyup[i] = keyword[i]; if (keyword[i] > 64 && keyword[i] < 91) keylow[i] = keyword[i] + 32; else keylow[i] = keyword[i]; } /* Find keyword or all-upper-case or all-lower-case version in header */ while (head < tabtable->tabhead) { line = strsrch (head, keyword); if (line == NULL) line = strsrch (head, keylow); if (line == NULL) line = strsrch (head, keyup); if (line == NULL) break; if (line == tabtable->tabbuff || line[-1] == newline) { str0 = strchr (line, tab) + 1; str1 = strchr (line, newline); break; } else head = line + 1; } /* Return value as a character string and 1 if found */ if (str0) { ncstr = str1 - str0; strncpy (result, str0, ncstr); result[ncstr] = (char)0; return (1); } else return (0); } /* TABPARSE -- Make a table of column headings */ int tabparse (tabtable) struct TabTable *tabtable; /* Tab table structure */ { char *colhead; /* Column heading first character */ char *endcol; /* Column heading last character */ char *headlast; char *hyphens; char *hyphlast; char *nextab; int i, icol, ientry; int nbytes, nba; /* Return if no column names in header */ headlast = strchr (tabtable->tabhead, newline); if (headlast == tabtable->tabhead) return (0); /* Count columns in table header */ tabtable->ncols = 1; for (colhead = tabtable->tabhead; colhead < headlast; colhead++) { if (*colhead == tab) tabtable->ncols++; } /* Tabulate column names */ nbytes = tabtable->ncols * sizeof (char *); nba = nbytes / 64; if (nbytes > nba * 64) nba = (nba + 1) * 64; else nba = nba * 64; tabtable->colname = (char **)calloc (tabtable->ncols, sizeof (char *)); tabtable->lcol = (int *) calloc (tabtable->ncols, sizeof (int)); colhead = tabtable->tabhead; for (icol = 0; icol < tabtable->ncols; icol++) { nextab = strchr (colhead, tab); if (nextab < headlast) endcol = nextab - 1; else endcol = headlast - 1; while (*endcol == ' ') endcol = endcol - 1; tabtable->lcol[icol] = (int) (endcol - colhead) + 1; tabtable->colname[icol] = colhead; colhead = nextab + 1; if (colhead > headlast) break; } /* Tabulate field widths */ hyphens = headlast + 1; hyphlast = strchr (hyphens, newline); if (hyphlast == hyphens) return (0); tabtable->lcfld = (int *) calloc (tabtable->ncols, sizeof (int)); colhead = hyphens; for (icol = 0; icol < tabtable->ncols; icol++) { if ((nextab = strchr (colhead, tab)) == NULL) endcol = hyphlast - 1; else endcol = nextab - 1; tabtable->lcfld[icol] = (int) (endcol - colhead) + 1; if (nextab != NULL) colhead = nextab + 1; else break; } return (tabtable->ncols); } /* Search table of column headings for a particlar entry (case-dependent) */ int tabcol (tabtable, keyword) struct TabTable *tabtable; /* Tab table structure */ char *keyword; /* Column heading to find */ { int i, lkey, lcol; lkey = strlen (keyword); for (i = 0; i < tabtable->ncols; i++) { lcol = tabtable->lcol[i]; if (lcol == lkey && !strncasecmp (keyword, tabtable->colname[i], lcol)) { return (i + 1); } } return (0); } /* Search table of column headings for first with string (case-dependent) */ static int tabcont (tabtable, keyword) struct TabTable *tabtable; /* Tab table structure */ char *keyword; /* Part of column heading to find */ { int i; for (i = 0; i < tabtable->ncols; i++) { if (strnsrch (tabtable->colname[i], keyword, tabtable->lcol[i])) { return (i + 1); } } return (0); } /* TABSIZE -- return size of file in bytes */ static int tabsize (filename) char *filename; /* Name of file for which to find size */ { FILE *diskfile; long filesize; /* Open file */ if ((diskfile = fopen (filename, "r")) == NULL) return (-1); /* Move to end of the file */ if (fseek (diskfile, 0, 2) == 0) /* Position is the size of the file */ filesize = ftell (diskfile); else filesize = -1; fclose (diskfile); return (filesize); } /* ISTAB -- Return 1 if tab table file, else 0 */ int istab (filename) char *filename; /* Name of file to check */ { struct TabTable *tabtable; /* First check file extension */ if (strsrch (filename, ".tab")) return (1); /* If no .tab file extension, try opening the file */ else { if ((tabtable = tabopen (filename, 1000)) != NULL) { tabclose (tabtable); return (1); } else return (0); } } /* Jul 18 1996 New subroutines * Aug 6 1996 Remove unused variables after lint * Aug 8 1996 Fix bugs in entry reading and logging * Oct 15 1996 Add comparison when testing an assignment * Nov 5 1996 Drop unnecessary static declarations * Nov 13 1996 Return no more than maximum star number * Nov 13 1996 Write all error messages to stderr with subroutine names * Nov 15 1996 Implement search radius; change input arguments * Nov 19 1996 Allow lower case column headings * Dec 18 1996 Add UJCRNUM to read specified catalog entries * Dec 18 1996 Keep closest stars, not brightest, if searching within radius * * Mar 20 1997 Clean up code in TABRNUM * May 7 1997 Set entry number to zero if column not found * May 29 1997 Add TABPARSE and TABCOL to more easily extract specific columns * May 29 1997 Add TABCLOSE to free memory from outside this file * Jun 4 1997 Set ID to sequence number in table if no ID/id entry present * * Jun 2 1998 Fix bug parsing last column of header * Jun 24 1998 Add string lengths to ra2str() and dec2str() calls * Sep 16 1998 Use limiting radius correctly * Sep 22 1998 Convert to output coordinate system * Oct 15 1998 Add tabsize() and istab() * Oct 21 1998 Add tabrkey() to read values of keyword for list of stars * Oct 29 1998 Correctly assign numbers when too many stars are found * Oct 30 1998 Fix istab() to check only first line of file * Dec 8 1998 Do not declare tabsize() static * Jan 20 1999 Add tabcatopen() and keep table info in structure, not global * Jan 25 1999 Add lcfld to structure to keep track of field widths * Jan 29 1999 Add current line number and pointer to table structure * Feb 2 1999 Allow for equinox other than 2000.0 in tab table header * Feb 2 1999 Add tabhgetc() to read char string values from tab table header * Feb 17 1999 Increase maximum line in istab() from 80 to 1024 * Mar 2 1999 Fix bugs calling tabhgetx() * Mar 2 1999 Rewrite tabhgetx() to use tabhgetc() for all header reading * May 28 1999 Add tabcatopen() and tabstar() and use them * Jun 3 1999 Fix bug so header parameters are read correctly * Jun 16 1999 Use SearchLim() * Aug 16 1999 Fix bug to fix failure to search across 0:00 RA * Aug 25 1999 Return real number of stars from tabread() * Sep 10 1999 Fix bug setting equinox and coordinate system in tabcatopen() * Sep 10 1999 Set additional keyword selection with subroutine * Sep 13 1999 Fix comment for tabstar() * Sep 16 1999 Fix bug which didn't always return closest stars * Sep 16 1999 Add distsort argument so brightest stars in circle works, too * Oct 21 1999 Clean up code after lint * Oct 25 1999 Fix subroutine declaration inconsistency * Oct 25 1999 Replace malloc() calls with calloc() * Oct 29 1999 Add tabxyread() for image catalogs * Nov 23 1999 Improve error checking on Starbase tables; istab() opens file * Nov 30 1999 Fix bugs found when compiling under SunOS 4.1.3 * * Jan 4 2000 Always close file and print error message on tabopen() failures * Jan 6 2000 If "id" not found, try heading with "_id" to catch scat output * Jan 10 2000 Add second magnitude; save column headers in catalog structure * Feb 10 2000 Implement proper motion in source catalogs * Feb 10 2000 Accept first mag-containing column as first magnitude * Feb 10 2000 Clean up id reading: no. decimals, non-numeric id * Feb 14 2000 Save table opening errors in string * Feb 16 2000 Lengthen short calloc() lengths * Feb 16 2000 Pad tabbuff with 2 nulls so end can be found * Mar 10 2000 Return proper motions from tabread() and tabrnum() * Mar 13 2000 Do not free tabtable structure if it is null * Mar 27 2000 Clean up code after lint * May 26 2000 Add ability to read named tables in a multi-table file * Jun 26 2000 Add coordinate system to SearchLim() arguments * Jul 5 2000 Check for additional column heading variations * Jul 10 2000 Deal with number of decimal places and name/number in tabcatopen() * Jul 12 2000 Add star catalog data structure to tabread() argument list * Jul 13 2000 Use nndec header parameter to optionally set decimal places * Jul 25 2000 Pass star catalog address of data structure address * Aug 3 2000 Skip first character of ID if rest is number * Aug 3 2000 If no decimal point in numeric ID, set ndec to zero * Sep 27 2000 Use first column with name if no id column is found * Oct 26 2000 Add proper motion in seconds and arcseconds per century * Oct 31 2000 Add proper motion in milliseconds of time per year * Nov 22 2000 Add tabtable argument to tabcatopen() for URL search returns * Nov 28 2000 Add starcat as argument to tabrnum() as well as tabread() * Nov 29 2000 Do not set tmagb if it is null; set type if present * Nov 30 2000 Add spectral type as possible column * Dec 1 2000 Add field as synonym for plate * Dec 18 2000 Clean up after lint * Dec 29 2000 Clean up after lint * * May 29 2001 Save length of identifier in catalog structure * May 30 2001 Rewrite to deal with up to 3 magnitudes * Jun 11 2001 Add one-line-at-a-time catalog reading from tabcatopen() * Jun 14 2001 In tabopen(), use actual file size if less than buffer size * Jun 14 2001 In tabcol() make sure lengths are equal, too * Jun 18 2001 Fix bug finding of length of token string extracted * Jun 19 2001 Use setoken() to parse each catalog line * Jun 20 2001 Add fourth magnitude for GSC II * Jun 25 2001 Check fgets() return in gettabline() * Jun 25 2001 Print star read errors only in verbose mode * Jun 28 2001 If no proper motion unit is set, set proper motion to 0.0 * Jun 28 2001 If first magnitude is 99.90, sort by second magnitude * Jun 28 2001 Up default line limit from 1 million to 10 million * Jul 2 2001 Fix order of 3rd and 4th magnitudes * Jul 20 2001 Return magnitude as well as flux from tabxyread() * Aug 8 2001 Return radial velocity as additional magnitude * Aug 17 2001 Fix bug reading radial velocity * Aug 21 2001 Check numbers using isnum() in tabgetr8() and tabgeti4() * Aug 21 2001 Add starcat to tabrkey() argument list * Aug 21 2001 Read object name into tkey if it is present * Sep 11 2001 Allow an arbitrary number of magnitudes * Sep 11 2001 Add sort magnitude argument to tabread() * Sep 19 2001 Drop fitshead.h; it is in wcs.h * Sep 20 2001 Clean up pointers for Alpha and Linux; drop tabgetpm() * Sep 20 2001 Change _ to . in ESO server USNO-A2.0 numbers * Sep 21 2001 Rearrange ESO server GSC numbers */