aboutsummaryrefslogtreecommitdiff
path: root/vendor/voclient/voapps/voiminfo.c
blob: fe2baa8d21e34cd71f558b18fcae2b425958bd67 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
/*
 *  VOIMINFO -- Get the WCS information for a FITS image.
 *
 *    Usage:
 *		voiminfo [<otps>] image.fits
 *
 *  @file       voiminfo.c
 *  @author     Mike Fitzpatrick
 *  @date       11/03/12
 *
 *  @brief      Get the WCS information for a FITS image.
 */

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <math.h>

#include "votParse.h"			/* keep these in order!		*/
#include "voApps.h"
#include "fitsio.h"



#define	MAX_IMAGES	20480		/* max images to process	*/
#define SZ_RESBUF	819200

#define	OPT_ALL		0001
#define	OPT_BOX		0002
#define	OPT_CORNERS	0004
#define	OPT_EXTNS	0010
#define	OPT_FRAME	0020
#define	OPT_NAXES	0040


static int  do_return   = 0;		/* return result?		*/

/*  Global task declarations.  These should all be defined as 'static' to
 *  avoid namespace collisions.
 */
static int do_all	= 0;		/* print global values		*/
static int do_sex	= 0;		/* print sexagesimal values	*/

static int do_box	= 0;		/* print box coordinates	*/
static int do_corners	= 0;		/* print image corners		*/
static int do_extns	= 0;		/* print extension values	*/
static int do_info	= 0;		/* print image info		*/
static int do_naxis	= 0;		/* print NAXIS values		*/

static int debug	= 0;		/* debug flag			*/
static int verbose	= 1;		/* verbose flag			*/


/*  Task specific option declarations.  Task options are declared using the
 *  getopt_long(3) syntax.
 */
int  voiminfo (int argc, char **argv, size_t *len, void **result);

static Task  self       = {  "voiminfo",  voiminfo,  0,  0,  0  };
static char  *opts 	= "%:habcdvnseio:r";
static struct option long_opts[] = {
        { "test",         1, 0,   '%'},		/* --test is std	*/
        { "help",         2, 0,   'h'},		/* --help is std	*/
        { "return",       2, 0,   'r'},		/* --return is std	*/
        { "debug",        2, 0,   'd'},		/* debug flag 		*/
        { "verbose",      2, 0,   'v'},		/* verbose flag 	*/

        { "all",          2, 0,   'a'},		/* print global value	*/
        { "box",     	  2, 0,   'b'},		/* print box values 	*/
        { "corners",      2, 0,   'c'},		/* print image corner 	*/
        { "extns",        2, 0,   'e'},		/* print each extn	*/
        { "info",         2, 0,   'i'},		/* print image info	*/
        { "naxes",     	  2, 0,   'n'},		/* print NEXIS values 	*/
        { "output",       1, 0,   'o'},		/* output filename	*/
        { "sex",          2, 0,   's'},		/* sexagesimal values	*/
        { NULL,           0, 0,    0 }
};


/**
 *  Private procedures.
 */
static void  Usage (void);
static void  Tests (char *input);
static char *fmt (double pos, int is_ra);
static char *fmt_naxis (char *imname, ImInfo *im, int do_all);
static char *fmt_box (char *imname, ImInfo *im, int do_all);
static char *fmt_corners (char *imname, ImInfo *im, int do_all);

extern int   vos_getURL (char *url, char *name);



/**
 *  Application entry point.
 */
int
voiminfo (int argc, char **argv, size_t *reslen, void **result)
{
    /*  These declarations are required for the VOApps param interface.
     */
    char **pargv, optval[SZ_FNAME], resbuf[SZ_RESBUF];
    char   imname[SZ_LINE];


    /*  These declarations are specific to the task.
     */
    char   *oname = NULL, *imlist[MAX_IMAGES], *nimlist[MAX_IMAGES];
    int     i, ch = 0, status = OK, pos = 0, nfiles = 0, narg = 0;;
    size_t  maxlen = SZ_RESBUF;
    FILE   *fd = (FILE *) NULL;
    ImInfo *im;


    /* Initialize result object	whether we return an object or not.
     */
    *reslen = 0;	
    *result = NULL;
    memset (imlist,  0, MAX_IMAGES);
    memset (nimlist, 0, MAX_IMAGES);


    /*  Parse the argument list.  The use of vo_paramInit() is required to
     *  rewrite the argv[] strings in a way vo_paramNext() can be used to
     *  parse them.  The programmatic interface allows "param=value" to
     *  be passed in, but the getopt_long() interface requires these to
     *  be written as "--param=value" so they are not confused with 
     *  positional parameters (i.e. any param w/out a leading '-').
     */
    pargv = vo_paramInit (argc, argv, opts, long_opts);
    while ((ch = vo_paramNext(opts,long_opts,argc,pargv,optval,&pos)) != 0) {
        if (ch > 0) {
	    /*  If the 'ch' value is > 0 we are parsing a single letter
	     *  flag as defined in the 'opts string.
	     */
	    switch (ch) {
	    case '%':  Tests (optval);			return (self.nfail);
	    case 'h':  Usage ();			return (OK);
	    case 'r':  do_return=1;	    	    	break;
	    case 'd':  debug++;				break;
	    case 'v':  verbose++;			break;

	    case 'a':  do_all++;			break;
	    case 'b':  do_box++;			break;
	    case 'c':  do_corners++;			break;
	    case 'e':  do_extns++;			break;
	    case 'i':  do_info++;			break;
	    case 's':  do_sex++;			break;
	    case 'n':  do_naxis++;			break;
	    case 'o':  oname = strdup (optval);		break;
	    default:
		fprintf (stderr, "Invalid option '%s'\n", optval);
		return (1);
	    }

        } else if (ch == PARG_ERR) {
            return (ERR);

	} else {
	    /*  This code processes the positional arguments.  The 'optval'
	     *  string contains the value but since this string is
	     *  overwritten w/ each arch we need to make a copy (and must
	     *  remember to free it later.
	     */
	    imlist[nfiles++] = strdup (optval);
	    narg++;
	}

	if (narg > MAX_IMAGES) {
            fprintf (stderr, "ERROR: Too many images to process\n");
            return (1);
	}
    }


    /*  Sanity checks.
     */
    if (imlist[0] == NULL || strcmp (imlist[0], "-") == 0) { 
	free (imlist[0]);
	imlist[0] = strdup ("stdin");  
	nfiles = 1;
    }
    if (do_all && strcasecmp (imlist[0], "stdin") == 0) {
	fprintf (stderr, "Error: Option not supported with standard input\n");
	return (ERR);
    }
    if (oname == NULL) oname = strdup ("stdout");
    if (strcmp (oname, "-") == 0) { free (oname), oname = strdup ("stdout"); }


    /*  Open the output file.
     */
    if (strcmp (oname, "stdout") != 0) {
	if ((fd = fopen (oname, "w+")) == (FILE *) NULL) {
	    fprintf (stderr, "Error: Cannot open output file '%s'\n", oname);
	    return (ERR);
	}
    } else
	fd = stdout;

    /* Default to printing all info if we're not given a specific option.
    if (!do_box && !do_corners && !do_info && !do_naxis)
	do_info = 1;
     */


    /**
     *  Main body of task
     */
    for (i=0; i < nfiles; i++) {

	memset (imname, 0, SZ_LINE);
	if (strncmp ("http://", imlist[i], 7) == 0) {
	    if (access ("/tmp/voiminfo.fits", F_OK) == 0)
		unlink ("/tmp/voiminfo.fits");
	    strcpy (imname, "/tmp/voiminfo.fits");
	    if (vos_getURL (imlist[i], imname) <= 0)
		continue;
	} else
	    strcpy (imname, imlist[i]);

	if ((im = vot_imageInfo (imname, do_all)) ) {
    	    memset (resbuf,  0, SZ_RESBUF);
	    if (do_info) {
                vot_printImageInfo (fd, im);
	    } else if (do_naxis) {
		strcpy (resbuf, fmt_naxis (imname, im, do_all));
	    } else if (do_box) {
		strcpy (resbuf, fmt_box (imname, im, do_all));
	    } else if (do_corners) {
		strcpy (resbuf, fmt_corners (imname, im, do_all));
	    } else {
                sprintf (resbuf, "%s\t%s\t%s\t%s\n", imlist[i], 
		    fmt (im->frame.cx,1), fmt (im->frame.cy,0), 
		    fmt (im->frame.radius,0));
	    }

	    if (do_return)
		vo_appendResultFromString (resbuf, reslen, result, &maxlen);
	    else
                fprintf (fd, "%s", resbuf);

            vot_freeImageInfo (im);

	    if (strncmp ("http://", imlist[i], 7) == 0)
	        unlink (imname);
	}
    }


    /*  Clean up.  Rememebr to free whatever pointers were created when
     *  parsing arguments.
     */
    for (i=0; i < MAX_IMAGES; i++) {
        if (imlist[i])  
	    free (imlist[i]);
        if (nimlist[i]) 
	    free (nimlist[i]);
	else
	    break;
    }
    if (oname) free (oname);
    if (fd != stdout)
	fclose (fd);

    vo_paramFree (argc, pargv);

    return (status);	/* status must be OK or ERR (i.e. 0 or 1)     	*/
}


/**
 *  USAGE -- Print task help summary.
 */
static void
Usage (void)
{
    fprintf (stderr, "\n  Usage:\n\t"
        "voiminfo [<opts>] votable.xml\n\n"
        "  where\n"
        "       -%%,--test		run unit tests\n"
        "       -h,--help		this message\n"
	"\n"
        "	-a,--all   		print all extns\n"
        "	-i,--info     		print image info\n"
        "	-b,--box     		print box values\n"
        "	-c,--corners   		print image corners\n"
        "	-n,--naxes     		print NAXIS values\n"
        "	-o,--output    		output filename\n"
        "	-s,--sex       		sexagesimal values\n"
	"\n"
        "       -o,--output=<file>	output file\n"
	"\n"
	"\n"
 	"  Examples:\n\n"
	"    1) Print the size of each image extension in an MEF file:\n\n"
	"	    %% voiminfo -n mef.fits\n"
	"\n"
	"    2) Print the LL and UR positions of an image as sexigesimal:\n\n"
	"	    %% voiminfo -b -s image.fits\n"
	"\n"
	"    3) Print the corner positions of an image as decimal degrees:\n\n"
	"	    %% voiminfo -c image.fits\n"
	"\n"
	"    4) Print the box values for an entire mosaic MEF file:\n\n"
	"	    %% voiminfo -b mef.fits\n"
	"\n"
    );
}


/**
 *  Tests -- Task unit tests.
 */
static void
Tests (char *input)
{
    Task  *task = &self;
    char  *mef = "data/mef.fits";
    char  *sif = "data/sif.fits";
    char  *opts[] = { "-a", "-i", "-b", "-c", "-n", "-s", NULL };
    register int i;


    vo_taskTest (task, "--help", NULL);

    if (access (input, F_OK) == 0) {
        vo_taskTest (task, "-n", input, NULL);				// Ex 1
        vo_taskTest (task, "-b", "-s", input, NULL);			// Ex 2
        vo_taskTest (task, "-c", input, NULL);				// Ex 3
        vo_taskTest (task, "-b", input, NULL);				// Ex 4
    } else 
	fprintf (stderr, "Warning: input file '%s' not found...\n", input);

    if (access (sif, F_OK) == 0)
	for (i=0; opts[i]; i++)
	    vo_taskTest (task, opts[i], sif, NULL);

    if (access (mef, F_OK) == 0)
	for (i=0; opts[i]; i++)
	    vo_taskTest (task, opts[i], mef, NULL);

    vo_taskTestReport (self);
}



/***************************************************************************/
/****  			    Private Procedures				****/
/***************************************************************************/

/**
 *  FMT -- Output formatter.
 */
static char *
fmt (double pos, int is_ra)
{
    static char strbuf[10][SZ_LINE];
    static int  bufnum = 0;


    bufnum = (bufnum + 1) % 10;
    memset (strbuf[bufnum], 0, SZ_LINE);

    pos = (pos < 0.0 ? -pos : pos);

    if (do_sex) {
        int   d, m;
        float s, frac;
        char  sign = (pos < 0.0 ? '-' : ' ');

        pos = (is_ra ? (pos / 15.0) : pos);
        d = (int) pos;
        frac = (pos - d);
        m = frac * 60.0;
        s = ((frac * 60.0) - m) * 60.0;

        sprintf (strbuf[bufnum], "%c%02d:%02d:%04.1f", sign, d, m, s);

    } else
        sprintf (strbuf[bufnum], "%f", pos);

    return (strbuf[bufnum]);
}


/**
 *  FMT_NAXIS -- Print the size of pixels of an image.
 */
static char *
fmt_naxis (char *imname, ImInfo *im, int do_all)
{
    static char line[SZ_RESBUF];

    memset (line, 0, SZ_RESBUF);
    if (im->nextend && !do_all) {
	register int i = 0;
	char buf[SZ_RESBUF];

	for (i=0; i < im->nextend; i++) {
	    memset (buf, 0, SZ_RESBUF);
            if (im->frame.naxis == 3)
                sprintf (buf, "%s[%d]\t%d %d %d\n", imname, i,
	            im->extns[i].naxes[0], 
		    im->extns[i].naxes[1],
		    im->extns[i].naxes[2]);
            else
                sprintf (buf, "%s[%d]\t%d %d\n", imname, i,
	            im->extns[i].naxes[0], im->extns[i].naxes[1]);
	    strcat (line, buf);
	}

    } else {
        if (im->frame.naxis == 3)
            sprintf (line, "%s\t%d %d %d\n", imname,
	        im->frame.naxes[0], im->frame.naxes[1], im->frame.naxes[2]);
        else
            sprintf (line, "%s\t%d %d\n", imname,
	        im->frame.naxes[0], im->frame.naxes[1]);
    }

    return (line);
}


/**
 *  FMT_BOX -- Print the corners of a box and rotation angle.
 */
static char *
fmt_box (char *imname, ImInfo *im, int do_all)
{
    static char line[SZ_RESBUF];

    memset (line, 0, SZ_RESBUF);
    if (im->nextend && !do_all) {
	register int i = 0;
	char buf[SZ_RESBUF];

	for (i=0; i < im->nextend; i++) {
	    memset (buf, 0, SZ_RESBUF);
            sprintf (buf, "%s[%d]\t%s %s\t%s %s\t%s\n", imname, i,
	        fmt (im->extns[i].lx,1), fmt (im->extns[i].ly,0), 
	        fmt (im->extns[i].ux,1), fmt (im->extns[i].uy,0), 
	        fmt (im->extns[i].rotang,0));
	    strcat (line, buf);
	}

    } else {
        sprintf (line, "%s\t%s %s\t%s %s\t%s\n", imname, 
	    fmt (im->frame.lx,1), fmt (im->frame.ly,0), 
	    fmt (im->frame.ux,1), fmt (im->frame.uy,0), 
	    fmt (im->frame.rotang,0));
    }

    return (line);
}


/**
 *  FMT_CORNERS -- Print the explicit corners of an image footprint.
 */
static char *
fmt_corners (char *imname, ImInfo *im, int do_all)
{
    static char line[SZ_RESBUF];

    memset (line, 0, SZ_RESBUF);
    if (im->nextend && !do_all) {
	register int i = 0;
	char buf[SZ_RESBUF];

	for (i=0; i < im->nextend; i++) {
	    memset (buf, 0, SZ_RESBUF);

            sprintf (buf, "%s\t%s %s\t%s %s\t%s %s\t%s %s\n", imname, 
	        fmt (im->extns[0].xc[0],1), fmt (im->extns[0].yc[0],0),
	        fmt (im->extns[0].xc[1],1), fmt (im->extns[0].yc[1],0),
	        fmt (im->extns[0].xc[2],1), fmt (im->extns[0].yc[2],0),
	        fmt (im->extns[0].xc[3],1), fmt (im->extns[0].yc[3],0));
	    strcat (line, buf);
	}

    } else {
        sprintf (line, "%s\t%s %s\t%s %s\t%s %s\t%s %s\n", imname, 
	    fmt (im->frame.xc[0],1), fmt (im->frame.yc[0],0),
	    fmt (im->frame.xc[1],1), fmt (im->frame.yc[1],0),
	    fmt (im->frame.xc[2],1), fmt (im->frame.yc[2],0),
	    fmt (im->frame.xc[3],1), fmt (im->frame.yc[3],0));
    }
    return (line);
}