diff options
author | Joseph Hunkeler <jhunkeler@gmail.com> | 2015-07-08 20:46:52 -0400 |
---|---|---|
committer | Joseph Hunkeler <jhunkeler@gmail.com> | 2015-07-08 20:46:52 -0400 |
commit | fa080de7afc95aa1c19a6e6fc0e0708ced2eadc4 (patch) | |
tree | bdda434976bc09c864f2e4fa6f16ba1952b1e555 /vendor/voclient/voapps/vosloanspec.c | |
download | iraf-linux-fa080de7afc95aa1c19a6e6fc0e0708ced2eadc4.tar.gz |
Initial commit
Diffstat (limited to 'vendor/voclient/voapps/vosloanspec.c')
-rw-r--r-- | vendor/voclient/voapps/vosloanspec.c | 765 |
1 files changed, 765 insertions, 0 deletions
diff --git a/vendor/voclient/voapps/vosloanspec.c b/vendor/voclient/voapps/vosloanspec.c new file mode 100644 index 00000000..70fcfbe9 --- /dev/null +++ b/vendor/voclient/voapps/vosloanspec.c @@ -0,0 +1,765 @@ +/* + * VOTSLOANSPEC -- Query and access spectra from SDSS/BOSS + * + * Usage: + * vosloanspec [<opts>] <obj> | {<ra> <dec>} | {<ra> <dec> <radius>} + * + * where + * -%%,--test Run unit tests + * -h,--help This message + * -d,--debug Debug Flag + * -v,--verbose Verbose Flag + * -r,--return=<obj> Return object + * + * -P,--pos=<ra>,<dec> Set query position (dec degrees) + * -R,--release=<rel> Data release (dr8/dr9/current) (def=current) + * -s,--size=<radius> Set query radius (dec degrees) + * -t,--type=<type> Object type (all|galaxy|qso|star) + * -z,--redshift=<zrange> Select by redshift range string(s) + * + * -c,--count Return only count of results + * -m,--meta Print result position metadata + * -D,--delete Delete spectra after printing metadata + * -l,--limit=<N> Limit to top <N> results + * -u,--urls Get urls to spectra + * + * -S,--samp Broadcase urls to SAMP (as spectrum) + * -T,--table Broadcase urls as VOTable message + * -N,--num=<N> Number of download threads + * + * -f,--file=<file> Input file + * -b,--base=<file> Base filename + * -O,--output=<file> Output file + * -o,--object=<obj> Object name + * + * Interface based on API at: http://api.sdss3.org/index.html + * + * + * @file vosloanspec.c + * @author Mike Fitzpatrick + * @date 9/93/12 + * + * @brief Query and access spectra from SDSS/BOSS + */ + +#include <stdio.h> +#include <unistd.h> +#include <stdlib.h> +#include <string.h> +#include <stdarg.h> +#include <ctype.h> +#include <pthread.h> +#include <errno.h> +#include <sys/stat.h> + +#include "samp.h" +#include "VOClient.h" +#include "voApps.h" + + +#define SZ_RESBUF 8192 +#define SZ_URL 1024 + +#define MAX_THREADS 64 +#define DEF_THREADS 12 +#define MAX_DOWNLOADS 65537 + +#define NEXTARG(a) strdup(optval);argnum++; + + +static int verbose = FALSE; /* verbose flag */ +static int debug = FALSE; /* debug flag */ +static int count = FALSE; /* count results */ +static int urls = FALSE; /* get URLs to data? */ +static int asSpec = TRUE; /* SAMP as Spectrum (or Table)? */ +static int nthreads = DEF_THREADS; /* Number of downlaod threads */ +static int ndownloads = 0; /* Number of file downloads */ +static int specnum = 0; /* spectrum number */ + +static int have_infile = FALSE; /* have input file? */ +static int do_return = FALSE; /* return result? */ +static int do_samp = FALSE; /* broadcast SAMP result? */ +static int do_meta = FALSE; /* get spectrum metadata? */ +static int do_delete = FALSE; /* delete files after metadata? */ + +static char *pos = NULL; /* position string */ +static char *release = NULL; /* data release */ +static char *limit = NULL; /* limit results */ +static char *size = NULL; /* search radius */ +static char *type = NULL; /* spectrum type */ +static char *redshift = NULL; /* redshift range */ +static char *iname = NULL; /* input position name */ +static char *oname = NULL; /* output name */ +static char *object = NULL; /* object name */ +static char *basename = NULL; /* base filename */ + +static double ra = -999.9; /* RA query position */ +static double dec = -999.9; /* Dec query position */ +static double rad = 0.25; /* query size (deg) */ + +static char ra_str[SZ_FNAME]; +static char dec_str[SZ_FNAME]; +static char rad_str[SZ_FNAME]; + +#ifdef USE_RESBUF +static char *resbuf; /* result buffer */ +#endif + +char url[SZ_URL]; +char *query_base = "http://api.sdss3.org/spectrumQuery?"; +char *spec_base = "http://api.sdss3.org/spectrum?"; + + +typedef struct { + char url[SZ_URL]; /* access URL */ + char fname[SZ_URL]; /* local filename */ + int tnum; /* worker thread number */ +} Acref, *AcrefP; + +Acref aclist[MAX_DOWNLOADS]; /* access list */ + + +/* Task specific option declarations. + */ +int vosloanspec (int argc, char **argv, size_t *len, void **result); + +static Task self = { "vosloanspec", vosloanspec, 0, 0, 0 }; +static char *opts = "%hrvdDP:N:R:STs:t:z:cl:uf:o:bm"; +static struct option long_opts[] = { + { "test", 2, 0, '%'}, /* required */ + { "help", 2, 0, 'h'}, /* required */ + { "verbose", 2, 0, 'v'}, /* verbose flag */ + { "debug", 2, 0, 'd'}, /* debug flag */ + { "return", 1, 0, 'r'}, /* task return option */ + + { "pos", 1, 0, 'P'}, /* position param */ + { "release", 1, 0, 'R'}, /* data release */ + { "table", 2, 0, 'T'}, /* data release */ + { "size", 1, 0, 's'}, /* search radius */ + { "type", 1, 0, 't'}, /* spectra type */ + { "redshift", 1, 0, 'z'}, /* redshift range */ + + { "count", 2, 0, 'c'}, /* count results */ + { "meta", 2, 0, 'm'}, /* count results */ + { "limit", 1, 0, 'l'}, /* limit results */ + { "urls", 2, 0, 'u'}, /* get urls */ + { "samp", 2, 0, 'S'}, /* broadcast SAMP */ + { "num", 1, 0, 'N'}, /* num downloads */ + { "delete", 2, 0, 'D'}, /* num downloads */ + + { "file", 1, 0, 'f'}, /* input file */ + { "output", 1, 0, 'O'}, /* output file */ + { "object", 1, 0, 'o'}, /* object name */ + { "base", 1, 0, 'b'}, /* base filename */ + { NULL, 0, 0, 0 } +}; + + +static void Usage (void); +static void Tests (char *input); +static int vos_getCountValue (char *fname); +static int vos_sampInit (void); +static char *vos_getURLValues (char *fname); +static void vot_procAclist (void); +static void vot_procMeta (void); +static void *vot_getAclist (void *arg); + +extern int vos_getURL (); +extern int vot_atoi (char *v); +extern double vot_atof (char *v); +extern char *vot_mktemp (); + +extern int vosesame (int argc, char **argv, size_t *len, void **result); +extern char *vo_urlEncode (char *target); + + + +/** + * Application entry point. + */ +int +vosloanspec (int argc, char **argv, size_t *reslen, void **result) +{ + int apos, argnum = 0, status = OK; + FILE *fd = (FILE *) NULL; + char **pargv, optval[SZ_FNAME], ch, *urlList = NULL;; + char *tmp = vot_mktemp ("vosloan"); + + + /* Initialize. + */ + oname = NULL; + iname = NULL; + *reslen = 0; + *result = NULL; + + ra = -999.9; + dec = -999.9; + memset (ra_str, 0, SZ_FNAME); + memset (dec_str, 0, SZ_FNAME); + memset (rad_str, 0, SZ_FNAME); + memset (url, 0, SZ_URL); /* initialize the query URL */ + strcpy (url, query_base); + strcpy (rad_str, "900"); /* 0.25 deg default */ + + asSpec = TRUE; + do_samp = FALSE; + do_meta = FALSE; + do_delete = FALSE; + + pos = NULL; /* position string */ + release = NULL; /* data release */ + limit = NULL; /* limit results */ + size = NULL; /* search radius */ + type = NULL; /* spectrum type */ + redshift = NULL; /* redshift range */ + iname = NULL; /* input position name */ + oname = NULL; /* output name */ + object = NULL; /* object name */ + basename = NULL; /* base filename */ + + + /* Parse the argument list. + */ + pargv = vo_paramInit (argc, argv, opts, long_opts); + while ((ch = vo_paramNext (opts,long_opts,argc,pargv,optval,&apos)) != 0) { + argnum++; + if (ch > 0) { + switch (ch) { + case '%': Tests (NULL); return (self.nfail); + case 'h': Usage (); return (OK); + + case 'v': verbose++; break; + case 'd': debug++; break; + case 'r': do_return++; break; /* FIX */ + + case 'N': nthreads = vot_atoi (optval); argnum++; break; + case 'P': pos = NEXTARG (optval); break; + case 'R': release = NEXTARG (optval); break; + case 's': size = NEXTARG (optval); + sprintf (rad_str, "%g", (rad = vot_atof(size) * 3600.)); + break; + case 't': type = NEXTARG (optval); break; + case 'z': redshift = NEXTARG (optval); break; + + case 'c': count++; break; + case 'm': do_meta++; break; + case 'u': urls++; break; + case 'S': do_samp++; break; + case 'D': do_delete++; break; + case 'T': asSpec--; break; + case 'l': limit = NEXTARG (optval); break; + + case 'f': iname = NEXTARG (optval); /* NYI */ + have_infile++; + break; + case 'O': oname = NEXTARG (optval); break; + case 'o': object = NEXTARG (optval); + if (argv[argnum]) { + Sesame sr; + char *opts = "runid=voc.vosloanspec,use_cache=no"; + + if (voc_initVOClient (opts) != OK) { + fprintf (stderr,"ERROR: can't open VOClient\n"); + return (ERR); + } + sr = voc_nameResolver (vo_urlEncode (argv[argnum])); + if (sr == 0) { + fprintf (stderr,"ERROR: can't resolve '%s'\n", + argv[argnum]); + return (ERR); + } else { + sprintf (ra_str, "%f", + (ra=voc_resolverRA (sr))); + sprintf (dec_str, "%f", + (dec=voc_resolverDEC (sr))); + } + } + break; + case 'b': basename = NEXTARG (optval); break; + default: + fprintf (stderr, "Invalid option '%s'\n", optval); + return (1); + } + + } else if (ch == PARG_ERR) { + return (ERR); + + } else { + + switch (argc - argnum) { + case -1: /* obj */ + argnum--; + case 0: /* obj */ + argnum--; + case 1: /* obj */ + /* resolve object pos + */ + if (argv[argnum]) { + Sesame sr; + char *opts = "runid=voc.vosloanspec,use_cache=no"; + + if (voc_initVOClient (opts) != OK) { + fprintf (stderr, "ERROR: cannot open VOClient\n"); + return (ERR); + } + sr = voc_nameResolver (vo_urlEncode (argv[argnum])); + if (sr == 0) { + fprintf (stderr,"ERROR: can't resolve '%s'\n", + argv[argnum]); + return (ERR); + } + sprintf (ra_str, "%f", (ra = voc_resolverRA (sr))); + sprintf (dec_str, "%f", (dec = voc_resolverDEC (sr))); + } + break; + case 2: /* ra dec */ + ra = vot_atof (argv[argnum]); + dec = vot_atof (argv[argnum+1]); + strcpy (ra_str, argv[argnum]); + strcpy (dec_str, argv[argnum+1]); + break; + case 3: /* ra dec rad */ + ra = vot_atof (argv[argnum]); + dec = vot_atof (argv[argnum+1]); + rad = vot_atof (argv[argnum+2]); + strcpy (ra_str, argv[argnum]); + strcpy (dec_str, argv[argnum+1]); + strcpy (rad_str, argv[argnum+2]); + break; + } + break; + } + } + + if (debug) + fprintf (stderr, "ra = %f dec = %f rad = %f\n", ra, dec, rad); + + /* Sanity checks + */ + if (iname == NULL) iname = strdup ("stdin"); + if (oname == NULL) oname = strdup ("stdout"); + if (strcmp (iname, "-") == 0) { free (iname), iname = strdup ("stdin"); } + if (strcmp (oname, "-") == 0) { free (oname), oname = strdup ("stdout"); } + + if (rad > 36000) /* enforce max query size of 10 deg */ + rad = 36000; + + + /* Append parameters to the base URL based on the cmdline options. We + * parse the positions/sizes and deal with files below. + */ + if (limit) strcat (url, "&limit="), strcat (url, limit); + if (type) strcat (url, "&class="), strcat (url, type); + if (release) strcat (url, "&release="), strcat (url, release); + if (redshift) strcat (url, "&redshift="), strcat (url, redshift); + if (count) strcat (url, "&count"); + strcat (url, "&urls"); /* always get URLS */ + + if (ra != -999.9) + strcat (url, "&ra="), strcat (url, ra_str), strcat (url,"d");; + if (dec != -999.9) + strcat (url, "&dec="), strcat (url, dec_str); + strcat (url, "&radius="); strcat (url, rad_str); + + if (debug) + fprintf (stderr, "url[0] = %s\n", url); + + + /* Access the query URL, saving the result to the named filed. We'll + * process the options on the resulting file. + */ + if (vos_getURL (url, tmp) >= 0) { + if (count) { + printf ("%d\n", vos_getCountValue (tmp)); + + } else if (urls) { + printf ("%s", (urlList= vos_getURLValues (tmp))); + + } else { + char *url = NULL, *base = NULL, tok[SZ_URL], fname[SZ_FNAME]; + int sampH = vos_sampInit (); + + url = urlList = vos_getURLValues (tmp); + memset (tok, 0, SZ_URL); + base = (basename ? basename : "sdss"); + + if (do_samp) { + if (verbose) + fprintf (stderr, "Initializing SAMP ....\n"); + sampH = sampInit ("vosloanspec", "VOClient SDSS Task"); + } + + for (specnum=0; *url && sscanf (url, "%s", tok); specnum++) { + memset (fname, 0, SZ_FNAME); + sprintf (fname, "%s%04d.fits", base, specnum); + + if (do_samp) { + /* Broadcast URL as a SAMP message, either as a bintable + * or an ssa-generic spectrum. + */ + if (sampH) { + int stat = -1; + + if (verbose) + fprintf (stderr, "Loading '%s' ....\n", tok); + if (asSpec) { + stat = samp_specLoadSSAGeneric (sampH, "all", + tok, /* URL */ + 0, /* Map meta */ /* NYI */ + fname, /* spectrumId */ + fname); /* name */ + } else { + stat = samp_tableLoadFITS (sampH, "all", + tok, /* URL/file */ + fname, /* tblId */ + fname); /* name */ + } + } + + } else { + /* Download URL to a local file. + */ + aclist[specnum].tnum = ((nthreads == 1) ? 0 : + (specnum % nthreads)); + strcpy (aclist[specnum].url, tok); + strcpy (aclist[specnum].fname, fname); + ndownloads++; + } + + url += strlen (tok) + 1; + memset (tok, 0, SZ_URL); + } + + /* Process the access list (downloads) and metadata request. + */ + if (ndownloads) { + vot_procAclist (); + if (do_meta) + vot_procMeta (); + } + + if (do_samp && sampH) + sampClose (sampH); + } + } else + status = ERR; + + + /* Clean up. + */ + if (fd != stdout) + fclose (fd); + if (urlList) + free ((void *) urlList); + + if (pos) free (pos); + if (type) free (type); + if (size) free (size); + if (limit) free (limit); + if (iname) free (iname); + if (oname) free (oname); + if (object) free (object); + if (release) free (release); + if (redshift) free (redshift); + if (basename) free (basename); + + vo_paramFree (argc, pargv); + + return (status); +} + + +/** + * VOT_PROCACLIST -- Process the access list. + */ +static void +vot_procAclist (void) +{ + /* Spawn the worker threads. + */ + int rc = 0, tc = 0, status = 0, tnum[MAX_THREADS]; + pthread_attr_t attr; /* thread attributes */ + pthread_t thread[MAX_THREADS]; + + + /* Initialize the service processing thread attributes and run 'em. + */ + pthread_attr_init (&attr); + pthread_attr_setdetachstate (&attr, PTHREAD_CREATE_JOINABLE); + + for (tc=0; tc < nthreads; tc++) { + tnum[tc] = tc; + if ((rc = pthread_create (&thread[tc], &attr, vot_getAclist, + (void *)&tnum[tc]))) { + fprintf (stderr, "ERROR: pthread_create() fails, code=%d\n", + rc); + return; + } + } + + /* Free attribute and wait for the threads to complete. + */ + pthread_attr_destroy (&attr); + for (tc=0; tc < nthreads; tc++) { + if ((rc = pthread_join (thread[tc], (void **)&status)) ) { + if (rc != ESRCH) { + fprintf (stderr, + "ERROR: pthread_join() fails, code=%d status=%d\n", + rc, status); + return; + } + } + } + + if (verbose) + fprintf (stderr, "Downloaded %d files -- complete\n", ndownloads); +} + + +/** + * VOT_GETACLIST -- Download all the files for the specified thread. + */ +static void * +vot_getAclist (void *arg) +{ + register int i; + int threadNum = 0; + + + if (arg) { + threadNum = *(int *)arg; + + for (i=0; i < ndownloads; i++) { + if (aclist[i].tnum == threadNum) { + if (verbose) + fprintf (stderr, "%s -> %s\n", + aclist[i].fname, aclist[i].url); + vos_getURL (aclist[i].url, aclist[i].fname); + } + } + } + return ((void *) NULL); +} + + +/** + * VOT_PROCMETA -- Process the metadata request. + */ +static void +vot_procMeta (void) +{ + int i, fd, nread; + char rec[(4 * 2880)]; + + for (i=0; i < ndownloads; i++) { + if (access (aclist[i].fname, R_OK) == 0) { + if ((fd = open (aclist[i].fname, O_RDONLY)) >= 0) { + nread = read (fd, rec, (size_t) (4 * 2880)); + printf ("%s\t", aclist[i].fname); + printf ("%11.6f\t", atof (strstr (rec, "PLUG_RA") + 11)); + printf ("%12.6f\n", atof (strstr (rec, "PLUG_DEC") + 11)); + close (fd); + + if (do_delete) + unlink (aclist[i].fname); + } + } + } +} + + +/** + * VOS_GETCOUNTVALUE -- Get the value from a count request. + */ +static int +vos_getCountValue (char *fname) +{ + char buf[SZ_LINE], *line; + FILE *fd; + + if (fname && (fd = fopen (fname, "r"))) { + memset (buf, 0, SZ_LINE); + line = fgets (buf, SZ_LINE, fd); + fclose (fd); + unlink (fname); + + return (vot_atoi (line)); + } + return (-1); +} + + +/** + * VOS_GETURLVALUES -- Get the values from a URL request. + */ +static char * +vos_getURLValues (char *fname) +{ + char *ptr, *out, *ip, *op; + FILE *fd; + extern int vos_fileRead(); + + + if (fname && (fd = fopen (fname, "r"))) { + struct stat info; + size_t sz, nr; + + if (stat (fname, &info) < 0) /* read the whole file */ + return (NULL); + sz = info.st_size; + ptr = calloc (sz + 1, sizeof(char)); + out = calloc (sz + 1, sizeof(char)); + nr = vos_fileRead (fileno(fd), ptr, sz); + + /* Check for a service outage. + */ + if (strstr (ptr, "uWSGI Error")) { + if (ptr) free (ptr); + if (out) free (out); + return ( strdup ("SDSS Service not available\n") ); + } + + for (ip=ptr, op=out; *ip; ip++) { + if (*ip == '[') + ; + if (*ip == '"') { + ip++; + while (*ip != '"') /* copy token */ + *op++ = *ip++; + *op++ = '\n'; + while (*ip != '"') /* skip to next token */ + ip++; + } + } + + free ((void *) ptr); + fclose (fd); + unlink (fname); + + return (out); + } + + return (NULL); +} + + +/** + * VOS_SAMPINIT -- Initialize the SAMP interface connection. + */ +static int +vos_sampInit (void) +{ + int sampH = 0; + + + /* If there's no Hub running, don't bother .... + */ + if (!samp_hubRunning()) + return (0); + + /* Initialize the SAMP interface. + */ + sampH = sampInit ("vosloanspec", "VOClient SDSS Spectrum Task"); + if (samp_hubActive (sampH) == 0) + return (0); + + /* Force 'asynch' messaging. + */ + samp_setSyncMode (sampH); + + /* Load metadata. + */ + samp_Metadata (sampH, "author.name", "Mike Fitzpatrick, NOAO"); + samp_Metadata (sampH, "author.email", "fitz@noao.edu"); + samp_Metadata (sampH, "samp.description.html", + "http://iraf.noao.edu/voclient/vosamp.html"); + samp_Metadata (sampH, "samp.icon.url", + "http://iraf.noao.edu/voclient/vao_icon.gif"); + + /* Register with the Hub and begin messaging. + */ + sampStartup (sampH); + + + return (sampH); +} + + +/** + * USAGE -- Print task help summary. + */ +static void +Usage (void) +{ + fprintf (stderr, "\n Usage:\n\t" + "vosloanspec [<opts>] <obj> | {<ra> <dec>} | {<ra> <dec> <radius>}\n\n" + " where\n" + " -%%,--test Run unit tests\n" + " -h,--help This message\n" + " -v,--verbose Verbose Flag\n" + " -d,--debug Debug Flag\n" + " -r,--return=<obj> Return object\n" + "\n" + " -P,--pos=<ra>,<dec> Set query position (dec degrees)\n" + " -R,--release=<rel> Data release (dr8/dr9/def=current)\n" + " -s,--size=<radius> Set query radius (dec degrees)\n" + " -t,--type=<type> Object type (all|galaxy|qso|star)\n" + " -z,--redshift=<zrange> Select by redshift range string(s)\n" + "\n" + " -c,--count Return only count of results\n" + " -m,--meta Print result position metadata\n" + " -D,--delete Delete spectra after printing metadata\n" + " -l,--limit=<N> Limit to top <N> results\n" + " -u,--urls Get urls to spectra\n" + "\n" + " -S,--samp Broadcase urls to SAMP (as spectrum)\n" + " -T,--table Broadcase urls as VOTable message\n" + " -N,--num=<N> Number of download threads\n" + "\n" + " -f,--file=<file> Input file\n" + " -b,--base=<file> Base filename\n" + " -O,--output=<file> Output file\n" + " -o,--object=<obj> Object name\n" + "\n\n" + " Examples:\n\n" + " 1) Download all galaxy spectra w/in 0.1 deg of the Hubble UDF\n\n" + " %% vosloanspec -s 0.1 -t galaxy HUDF\n" + " %% vosloanspec --size=0.1 --type=galaxy HUDF\n" + "\n" + " 2) Get only the positions of the SDSS spectra around a point\n\n" + " %% vosloanspec -m -d m51\n" + " %% vosloanspec --meta --delete m51\n" + "\n" + " 3) Broadcast 5 spectra around 3c273 to SAMP-enabled apps\n\n" + " %% vosloanspec -l 5 --samp 3c273\t# as a spectrum msg\n" + " %% vosloanspec -l 5 --samp --table 3c273\t# as a table msg\n" + "\n" + " 4) Get all QSO spectra with a redshift > 0.3 (Note an upper range\n" + " must be specified for the redshift range for a valid query)\n\n" + " %% vosloanspec --redshift=0.3-1.0\n" + "\n\n" + ); +} + + +/** + * Tests -- Task unit tests. + */ +static void +Tests (char *input) +{ + Task *task = &self; + + vo_taskTest (task, "--help", NULL); + + vo_taskTest (task, "-s", "0.1", "-t", "galaxy", "HUDF", NULL); // Ex 1a + vo_taskTest (task, "--size=0.1", "--type=galaxy", "HUDF", NULL); // Ex 1b + vo_taskTest (task, "-m", "-D", "m51", NULL); // Ex 2a + vo_taskTest (task, "--meta", "--delete", "m51", NULL); // Ex 2b + vo_taskTest (task, "-l", "5", "--samp", "3c273", NULL); // Ex 3a + vo_taskTest (task, "-l", "5", "--samp", "--table", "3c273", NULL); // Ex 3b + vo_taskTest (task, "--redshift=0.3-1.0", NULL); // Ex 4 + + vo_taskTestReport (self); +} |