1
0
Fork 0
sattools/qfits/saft/fitsort.c

419 lines
12 KiB
C

/*----------------------------------------------------------------------------*/
/**
@file fitsort.c
@author Nicolas Devillard
@date May 1st, 1996
@version $Revision: 1.4 $
@brief Sorts out FITS keywords
The input is a succession of FITS headers delivered through stdin by
'dfits'. On the command line, specify which keywords you wish to display, the
output contains for each file, the file name and the keyword values in
column format. Example:
dfits *.fits | fitsort BITPIX NAXIS NAXIS1 NAXIS2 NAXIS3
The output would be like:
File BITPIX NAXIS NAXIS1 NAXIS2 NAXIS3
image1.fits 32 2 256 256
image2.fits -32 3 128 128 40
Using 'fitsort -d ...' would prevent printing the first line (filename and
keyword names).
The output format is simple: values are separated by tabs, records by
linefeeds. When no value is present (no keyword in this header), only a tab
is printed out. Example:
file1.fits contains NAXIS1=100 NAXIS2=200
file2.fits contains NAXIS1=20
dfits file1.fits file2.fits | fitsort NAXIS2 NAXIS1
would litterally print out (\t stands for tab, \n for linefeed):
file1.fits\t200\t100\n
file2.fits\t\t20\n
*/
/*----------------------------------------------------------------------------*/
/*
$Id: fitsort.c,v 1.4 2005/07/04 14:21:31 yjung Exp $
$Author: yjung $
$Date: 2005/07/04 14:21:31 $
$Revision: 1.4 $
*/
/*-----------------------------------------------------------------------------
Include
-----------------------------------------------------------------------------*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
/*-----------------------------------------------------------------------------
Define
-----------------------------------------------------------------------------*/
#define MAX_STRING 128
#define MAX_KEY 512
#define FMT_STRING "%%-%ds\t"
/*-----------------------------------------------------------------------------
New types
-----------------------------------------------------------------------------*/
/* This holds a keyword value and a flag to indicate its presence */
typedef struct _KEYWORD_
{
char value[MAX_STRING];
int present;
} keyword;
/* Each detected file in input has such an associated structure */
typedef struct _RECORD_
{
char filename[MAX_STRING];
keyword listkw[MAX_KEY];
} record;
/*-----------------------------------------------------------------------------
Function prototypes
-----------------------------------------------------------------------------*/
static int isfilename (char *string);
static void getfilename (char *line, char *word);
static char *expand_hierarch_keyword (char *, char *);
static int isdetectedkeyword (char *line, char *keywords[], int nkeys);
static void getkeywordvalue (char *line, char *word);
/*-----------------------------------------------------------------------------
Main
-----------------------------------------------------------------------------*/
int
main (int argc, char *argv[])
{
char curline[MAX_STRING];
char word[MAX_STRING];
int i, j;
int nfiles;
record *allrecords;
int kwnum;
int len;
int max_width[MAX_KEY];
int max_filnam;
char fmt[8];
int flag;
int printnames;
int print_hdr;
if (argc < 2)
{
printf ("\n\nuse : %s [-d] KEY1 KEY2 ... KEYn\n", argv[0]);
printf ("Input data is received from stdin\n");
printf ("See man page for more details and examples\n\n");
return 0;
}
/* Initialize */
printnames = 0;
print_hdr = 1;
nfiles = 0;
allrecords = (record *) calloc (1, sizeof (record));
if (!strcmp (argv[1], "-d"))
{
print_hdr = 0;
argv++;
argc--;
}
argv++;
/* Uppercase all inputs */
for (i = 0; i < (argc - 1); i++)
{
j = 0;
while (argv[i][j] != 0)
{
argv[i][j] = toupper (argv[i][j]);
j++;
}
}
while (fgets (curline, MAX_STRING, stdin) != (char *) NULL)
{
flag = isfilename (curline);
if (flag == 1)
{
/* New file name is detected, get the new file name */
printnames = 1;
getfilename (curline, allrecords[nfiles].filename);
nfiles++;
/* Initialize a new record structure to store data for this file. */
allrecords =
(record *) realloc (allrecords, (nfiles + 1) * sizeof (record));
for (i = 0; i < MAX_KEY; i++)
allrecords[nfiles].listkw[i].present = 0;
}
else if (flag == 0)
{
/* Is not a file name, is it a searched keyword? */
if ((kwnum = isdetectedkeyword (curline, argv, argc - 1)) != -1)
{
/* Is there anything allocated yet to store this? */
if (nfiles > 0)
{
/* It has been detected as a searched keyword. */
/* Get its value, store it, present flag up */
getkeywordvalue (curline, word);
strcpy (allrecords[nfiles - 1].listkw[kwnum].value, word);
allrecords[nfiles - 1].listkw[kwnum].present++;
}
}
}
}
for (i = 0; i < argc - 1; i++)
max_width[i] = (int) strlen (argv[i]);
/* Record the maximum width for each column */
max_filnam = 0;
for (i = 0; i < nfiles; i++)
{
len = (int) strlen (allrecords[i].filename);
if (len > max_filnam)
max_filnam = len;
for (kwnum = 0; kwnum < argc - 1; kwnum++)
{
if (allrecords[i].listkw[kwnum].present)
{
len = (int) strlen (allrecords[i].listkw[kwnum].value);
}
else
{
len = 0;
}
if (len > max_width[kwnum])
max_width[kwnum] = len;
}
}
/* Print out header line */
if (print_hdr)
{
sprintf (fmt, FMT_STRING, max_filnam);
if (printnames)
printf (fmt, "FILE");
for (i = 0; i < argc - 1; i++)
{
sprintf (fmt, FMT_STRING, max_width[i]);
printf (fmt, argv[i]);
}
printf ("\n");
}
/* Now print out stored data */
if (nfiles < 1)
{
printf ("*** error: no input data corresponding to dfits output\n");
return -1;
}
for (i = 0; i < nfiles; i++)
{
if (printnames)
{
sprintf (fmt, FMT_STRING, max_filnam);
printf (fmt, allrecords[i].filename);
}
for (kwnum = 0; kwnum < argc - 1; kwnum++)
{
sprintf (fmt, FMT_STRING, max_width[kwnum]);
if (allrecords[i].listkw[kwnum].present)
printf (fmt, allrecords[i].listkw[kwnum].value);
else
printf (fmt, " ");
}
printf ("\n");
}
free (allrecords);
return 0;
}
/*-----------------------------------------------------------------------------
Functions code
-----------------------------------------------------------------------------*/
/*----------------------------------------------------------------------------*/
/**
@brief find out if an input line contains a file name or a FITS magic nb.
@param string dfits output line
@return int (see below)
Filename recognition is based on 'dfits' output. The function returns 1 if
the line contains a valid file name as produced by dfits, 2 if it is for an
extension, 0 otherwise.
*/
/*----------------------------------------------------------------------------*/
static int
isfilename (char *string)
{
if (!strncmp (string, "====>", 5))
return 1;
if (!strncmp (string, "===>", 4))
return 2;
return 0;
}
/*----------------------------------------------------------------------------*/
/**
@brief returns a file name from a dfits output line
@param line dfits output line
@param word file name
@return a file name from a dfits output line
This is dfits dependent.
*/
/*----------------------------------------------------------------------------*/
static void
getfilename (char *line, char *word)
{
/* get filename from a dfits output */
sscanf (line, "%*s %*s %s", word);
return;
}
/*----------------------------------------------------------------------------*/
/**
@brief detects a if a keyword is present in a FITS line
@param line FITS line
@param keywords set of keywords
@param nkeys number of kw in the set
@return keyword rank, -1 if unidentified
Feed this function a FITS line, a set of keywords in the *argv[] fashion
(*keywords[]). If the provided line appears to contain one of the keywords
registered in the list, the rank of the keyword in the list is returned,
otherwise, -1 is returned.
*/
/*----------------------------------------------------------------------------*/
static int
isdetectedkeyword (char *line, char *keywords[], int nkeys)
{
char kw[MAX_STRING];
char esokw[MAX_STRING];
int i;
/* The keyword is up to the equal character, with trailing blanks removed */
strcpy (kw, line);
strtok (kw, "=");
/* Now remove all trailing blanks (if any) */
i = (int) strlen (kw) - 1;
while (kw[i] == ' ')
i--;
kw[i + 1] = (char) 0;
/* Now compare what we got with what's available */
for (i = 0; i < nkeys; i++)
{
if (strstr (keywords[i], ".") != NULL)
{
/*
* keyword contains a dot, it is a hierarchical keyword that
* must be expanded. Pattern is:
* A.B.C... becomes HIERARCH ESO A B C ...
*/
expand_hierarch_keyword (keywords[i], esokw);
if (!strcmp (kw, esokw))
{
return i;
}
}
else if (!strcmp (kw, keywords[i]))
{
return i;
}
}
/* Keyword not found */
return -1;
}
/*----------------------------------------------------------------------------*/
/**
@brief Expand a HIERARCH keyword in format A.B.C to HIERARCH ESO A B C
@param dotkey Keyword
@param hierarchy HIERARCH
@return char *, pointer to second input string (modified)
*/
/*----------------------------------------------------------------------------*/
static char *
expand_hierarch_keyword (char *dotkey, char *hierarchy)
{
char *token;
char ws[MAX_STRING];
sprintf (hierarchy, "HIERARCH ESO");
strcpy (ws, dotkey);
token = strtok (ws, ".");
while (token != NULL)
{
strcat (hierarchy, " ");
strcat (hierarchy, token);
token = strtok (NULL, ".");
}
return hierarchy;
}
/*----------------------------------------------------------------------------*/
/**
@brief Get a keyword value within a FITS line
@param line FITS line to process
@param word char string to return result
@return void, result returned in word
No complex value is recognized
*/
/*----------------------------------------------------------------------------*/
static void
getkeywordvalue (char *line, char *word)
{
int c, w;
char tmp[MAX_STRING];
char *begin, *end;
int length;
int quote = 0;
int search = 1;
memset (tmp, (char) 0, MAX_STRING);
memset (word, (char) 0, MAX_STRING);
c = w = 0;
/* Parse the line till the equal '=' sign is found */
while (line[c] != '=')
c++;
c++;
/* Copy the line till the slash '/' sign or the end of data is found. */
while (search == 1)
{
if (c >= 80)
search = 0;
else if ((line[c] == '/') && (quote == 0))
search = 0;
if (line[c] == '\'')
quote = !quote;
tmp[w++] = line[c++];
}
/* NULL termination of the string */
tmp[--w] = (char) 0;
/* Return the keyword only : a diff is made between text fields and nbs. */
if ((begin = strchr (tmp, '\'')) != (char *) NULL)
{
/* A quote has been found: it is a string value */
begin++;
end = strrchr (tmp, '\'');
length = (int) strlen (begin) - (int) strlen (end);
strncpy (word, begin, length);
}
else
{
/* No quote, just get the value (only one, no complex supported) */
sscanf (tmp, "%s", word);
}
return;
}