diff options
Diffstat (limited to 'funtools/fitsy/tableheader.c')
-rw-r--r-- | funtools/fitsy/tableheader.c | 230 |
1 files changed, 230 insertions, 0 deletions
diff --git a/funtools/fitsy/tableheader.c b/funtools/fitsy/tableheader.c new file mode 100644 index 0000000..e7a48e4 --- /dev/null +++ b/funtools/fitsy/tableheader.c @@ -0,0 +1,230 @@ +#include <xos.h> +#include "fitsy.h" + +/* + * + * ft_tableheader -- read a string that details the structure + * of the event record and generate a fitsy table header + * + * The structure of the string is: + * + * [name]:[n][type]:[(lodim:)hidim] + * + * Data types follow standard conventions for FITS binary tables, but include + * two extra unsigned types ('U' and 'V'): + * + * B -- unsigned 8-bit char + * I -- signed 16-bit int + * J -- signed 32-bit int + * K -- signed 64-bit int + * E -- 32-bit float + * D -- 64-bit float + * U -- unsigned 16-bit int + * V -- unsigned 32-bit int + * + * An optional integer value n can be prefixed to the type to indicate + * that the element actually is an array of n values. + * + * Furthermore, image dimensions are attached to the event specification + * in order to tell FITS how to bin the events into an image. They + * follow the conventions for the FITS TLMIN, TLMAX, and TALEN + * keywords. If the low image dimension is not specified, it defaults to + * 1. Thus: + * + * RAWX:J:1:100 + * RAWX:J:100 + * + * both specify that the dimension of this column runs from 1 to 100. + * Note that it is required that all padding be specified in the record + * definition. + * + * + * For example, suppose a FITS binary table has the following set of column + * definitions: + * + * + * TTYPE1 = 'X ' / Label for field + * TFORM1 = '1I ' / Data type for field + * TLMIN1 = 1 / Min. axis value + * TLMAX1 = 10 / Max. axis value + * TTYPE2 = 'Y ' / Label for field + * TFORM2 = '1I ' / Data type for field + * TLMIN2 = 2 / Min. axis value + * TLMAX2 = 11 / Max. axis value + * TTYPE3 = 'PHA ' / Label for field + * TFORM3 = '1I ' / Data type for field + * TTYPE4 = 'PI ' / Label for field + * TFORM4 = '1J ' / Data type for field + * TTYPE5 = 'TIME ' / Label for field + * TFORM5 = '1D ' / Data type for field + * TTYPE6 = 'DX ' / Label for field + * TFORM6 = '1E ' / Data type for field + * TLMIN6 = 1 / Min. axis value + * TLMAX6 = 10 / Max. axis value + * TTYPE7 = 'DY ' / Label for field + * TFORM7 = '1E ' / Data type for field + * TLMIN7 = 3 / Min. axis value + * TLMAX7 = 12 / Max. axis value + * + * An raw event file containing these same data would have the event + * specification: + * + * X:I:10,Y:I:2:11,PHA:I,PI:J,TIME:D,DX:E:10,DY:E:3:12 + * + */ +FITSHead ft_tableheader(char *eventdef, int nev) +{ + FITSHead header; + char type[SZ_LINE]; + char name[SZ_LINE]; + char dim[SZ_LINE]; + char *neventdef = NULL; + char *nevdef; + char *d, *n, *s, *t, u[2]; + char **names, **types, **dims; + char *extname="EVENTS"; + int extver=1; + int cols, width, got; + int i, r; + int *lodims, *hidims, *widths; + + /* init the fitsy header */ + header = ft_headinit(NULL, 0); + + /* get rid of enclosing parens */ + if(*eventdef == '('){ + NewString(neventdef, eventdef+1); + i = strlen(neventdef); + if( neventdef[i-1] == ')' ) + neventdef[i-1] = '\0'; + } + else{ + NewString(neventdef, eventdef); + } + /* we only deal with upper case in FITS */ + for(nevdef=neventdef; *nevdef; nevdef++){ + if( islower((int)*nevdef) ) + *nevdef = toupper(*nevdef); + } + + /* first count the number of columns we have specified, + separated by ',' */ + for(s=neventdef, cols=1; *s; s++){ + if( *s == ',' ) + cols++; + } + + /* allocate string space for each column */ + names = (char **)calloc(cols, sizeof(char *)); + types = (char **)calloc(cols, sizeof(char *)); + dims = (char **)calloc(cols, sizeof(char *)); + lodims = (int *)calloc(cols, sizeof(int)); + hidims = (int *)calloc(cols, sizeof(int)); + widths = (int *)calloc(cols, sizeof(int)); + + /* process the string and gather up the information */ + for(s=neventdef, width=0, got=0; *s; ){ + /* get name */ + n=name; + *n = '\0'; + while( *s && (*s != ':') ) + *n++ = *s++; + *n = '\0'; + NewString(names[got], name); + /* skip delim */ + if( *s == ':' ) + s++; + if( *s == '\0' ) + break; + + /* get type, which might be preceded by a count */ + r = strtol(s, &t, 10); + if( s != t ) + s = t; + else + r = 1; + /* cast unsupported unsigned type, if necessary */ + u[0] = *s; + u[1] = '\0'; + snprintf(type, SZ_LINE, "%d%c", r, *u); + NewString(types[got], type); + width += ft_sizeof(*u)*r; + widths[got] = ft_sizeof(*u); + /* bump past type character */ + s++; + + /* get optional image dimension */ + if( *s == ':' ){ + /* skip past ':' */ + s++; + *dim = '\0'; + for( d=dim; *s && (*s != ',') && (*s != ':'); ) + *d++ = *s++; + *d = '\0'; + NewString(dims[got], dim); + if( *s == ':' ){ + lodims[got] = atoi(dims[got]); + s++; + *dim = '\0'; + for( d=dim; *s && (*s != ','); ) + *d++ = *s++; + *d = '\0'; + hidims[got] = atoi(dim); + } + else{ + lodims[got] = 0; + hidims[got] = atoi(dims[got])-1; + } + if( *s == ',' ) + s++; + } + else + dims[got] = NULL; + + /* bump past the comma */ + if( *s == ',' ) + s++; + /* done with another header value */ + got++; + } + + /* fake the header to a binary table */ + ft_headsets(header, "XTENSION", 0, "BINTABLE", "FITS BINARY TABLE", 1); + ft_headseti(header, "BITPIX", 0, 8, "Binary data", 1); + ft_headseti(header, "NAXIS", 0, 2, "Table is a matrix", 1); + ft_headseti(header, "NAXIS", 1, width, "Width of table in bytes", 1); + ft_headseti(header, "NAXIS", 2, nev, "Number of entries in table", 1); + ft_headseti(header, "PCOUNT", 0, 0, "Random parameter count", 1); + ft_headseti(header, "GCOUNT", 0, 1, "Group count", 1); + ft_headseti(header, "TFIELDS", 0, got, "Number of fields in each row", 1); + ft_headsets(header, "EXTNAME", 0, extname, "Table name", 1); + ft_headseti(header, "EXTVER", 0, extver, "Version number of table", 1); + /* info for each column */ + for(i=0; i<got; i++){ + ft_headsets(header, "TFORM", i+1, types[i], "Data type for field", 1); + ft_headsets(header, "TTYPE", i+1, names[i], "Label for field", 1); + if( dims[i] != NULL ){ + ft_headseti(header, "TLMIN", i+1, lodims[i], "Min. axis value", 1); + ft_headseti(header, "TLMAX", i+1, hidims[i], "Max. axis value", 1); + } + } + + /* now turn this into a table header */ + ft_syncdata(header); + + /* free up the column strings */ + for(i=0; i<cols; i++){ + if( names[i] ) free(names[i]); + if( types[i] ) free(types[i]); + if( dims[i] ) free(dims[i]); + } + if( names ) free(names); + if( types ) free(types); + if( dims ) free(dims); + if( lodims ) free(lodims); + if( hidims ) free(hidims); + if( widths ) free(widths); + if( neventdef ) free(neventdef); + + return header; +} |