/* fitsfield.c *%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% * * Part of: The LDAC Tools * * Author: E.BERTIN, DeNIS/LDAC * * Contents: Functions related to the management of fields. * * Last modify: 25/04/97 * *%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% */ #include #include #include #include "fitscat_defs.h" #include "fitscat.h" /****** read_field ************************************************************* PROTO int read_field(tabstruct *tab, char **keynames, keystruct **keys, int nkeys, int field, tabstruct *ftab) PURPOSE Read several columns from a FITS binary table for only one field. INPUT pointer to the OBJECTS table, pointer to an array of char *, pointer to an array of keystruct * (memory must have been allocated), number of keys to read, the field to be read, pointer to the FIELDS table. OUTPUT The number of objects read. NOTES The array of pointers pointed by keys is filled with pointers to the relevant keys (a NULL means NO key with such name was found). A NULL keys pointer can be given (no info returned of course). A NULL keynames pointer means read ALL keys belonging to the table. A NULL FIELDS table pointer means sequential access to the OBJECTS table (much slower). Obviously, the FIELD_NUMBER key is required in the table to be read. AUTHOR E. Bertin (IAP & Leiden observatory) E.R. Deul (Leiden Observatory) VERSION 25/04/97 28/08/97 Extended read_field() warning message to print field nr ***/ int read_field(tabstruct *tab, char **keynames, keystruct **keys, int nkeys, int field, tabstruct *ftab) { #define DEFAULT_NUMBER 2048 /* default number of objects */ /* to use when allocating memory */ catstruct *cat; keystruct *key, *fkey, *fposkey, **ckeys; char *buf, *ptr, *fptr; int rfield, ok; int i,j,k,n, larray,narray,nfields, nb, kflag = 0, size; #ifdef BSWAP int esize; #endif /*!! It is not necessarily the original table */ tab = tab->key->tab; cat = tab->cat; /* We are expecting a 2D binary-table, and nothing else*/ if ((tab->naxis != 2) || (tab->bitpix!=8) || (tab->tfields == 0) || strncmp(tab->xtension, "BINTABLE", 8)) error(EXIT_FAILURE, "*Error*: No binary table in ", cat->filename); if ((tab->naxis != 2) || (tab->bitpix!=8) || (tab->tfields == 0) || strncmp(tab->xtension, "BINTABLE", 8)) error(EXIT_FAILURE, "*Error*: No binary table in ", cat->filename); /* Size and number of lines in the binary table*/ larray = tab->naxisn[0]; nfields= tab->tfields; narray = tab->naxisn[1]; /* Check if field is not too large*/ if (ftab && (field>ftab->naxisn[1] || field<1)) error(EXIT_FAILURE, "*Error*: field not found in ", cat->filename); if (!keynames) nkeys = tab->nkey; /* Allocate memory to store the list of keys to be read */ if (!keys) { QMALLOC(keys, keystruct *, nkeys); kflag = 1; } if (!(fposkey = name_to_key(tab, "FIELD_POS"))) { if (!(fposkey = name_to_key(tab, "FIELD_NUMBER"))) { error(EXIT_FAILURE, "*Error*: No Field number in ", cat->filename); } } /* Get information from the FIELDS table if possible and if necessary*/ fkey = name_to_key(ftab, "OBJECT_COUNT"); if (fkey == NULL || fkey->ptr == NULL) { if ((key=read_key(ftab, "OBJECT_COUNT")) == NULL) { if ((key=read_key(ftab, "OBJECT_NUMBER")) == NULL) { error(EXIT_FAILURE,"*Error*: No OBJECT_COUNT in ", cat->filename); } } } else { key = fkey; } if (ftab) nb = narray = ((int *)key->ptr)[field-1]; else nb = DEFAULT_NUMBER; /* Some value to start with */ /*allocate memory for the arrays*/ ckeys = keys; if (keynames) for (i=nkeys; i--;) { if ((key = name_to_key(tab, *(keynames++)))) { QMALLOC(key->ptr, char, key->nbytes*nb); *(ckeys++) = key; } else *(ckeys++) = NULL; } else { key = tab->key; for (i=nkeys; i--;) { QMALLOC(key->ptr, char, key->nbytes*nb); *(ckeys++) = key; key = key->nextkey; } } /*allocate memory for the buffer where we put one line of data*/ QMALLOC(buf, char, larray); /*Positioning to the first element*/ open_cat(cat, READ_ONLY); /*Get information from the FIELDS table if possible*/ if (ftab) { fkey = name_to_key(ftab, "OBJECT_POS"); key = (fkey && fkey->ptr) ? fkey : read_key(ftab, "OBJECT_POS"); QFSEEK(cat->file, tab->bodypos+((((int *)key->ptr)[field-1])-1)*larray, SEEK_SET, cat->filename) } else QFSEEK(cat->file, tab->bodypos , SEEK_SET, cat->filename); /*read line by line*/ n = 0; for (i=narray; i--;) { QFREAD(buf, larray, cat->file, cat->filename); /*--Check that current line corresponds to the right field*/ /* * Allow for short and long int FIELD_POS types */ if (fposkey->ttype == T_LONG) { memcpy(&rfield,buf+fposkey->pos,sizeof(LONG)); #ifdef BSWAP swapbytes(&rfield, sizeof(LONG), 1); #endif ok = (field == *((LONG *)&rfield)); } else { memcpy(&rfield,buf+fposkey->pos,sizeof(short)); #ifdef BSWAP swapbytes(&rfield, sizeof(short), 1); #endif ok = (field == *((short *)&rfield)); } if (ok) { /*---- Check if there's still enough memory*/ if (n>=nb) { nb *= 2; /* Geometric progression; can be put to a */ /* milder progression if necessary */ ckeys = keys; for (j=nkeys; j--;) if ((key = *(ckeys++))) QREALLOC(key->ptr, char, key->nbytes*nb); } ckeys = keys; for (k=nkeys; k--;) if ((key = *(ckeys++))) { fptr = buf+key->pos; ptr = (char *)key->ptr+n*(size=key->nbytes); #ifdef BSWAP esize = t_size[key->ttype]; swapbytes(fptr, esize, size/esize); #endif for (j=size; j--;) *(ptr++) = *(fptr++); } n++; } } /* Finally, only keep what is needed*/ ckeys = keys; if (!n) { char mess[80]; sprintf(&mess[0],"No element read in field %d of ",field); warning(mess, cat->filename); ckeys = keys; for (i=nkeys; i--;) if ((key = *(ckeys++))) QFREE(key->ptr); } else { for (i=nkeys; i--;) if ((key = *(ckeys++))) QREALLOC(key->ptr, char, key->nbytes*n); } free(buf); if (kflag) free(keys); return n; }