/* * fitscat.c * * Low-level functions for handling FITS images and tables. * *%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% * * This file part of: AstrOmatic FITS/LDAC library * * Copyright: (C) 1995-2012 Emmanuel Bertin -- IAP/CNRS/UPMC * * License: GNU General Public License * * AstrOmatic software is free software: you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation, either version 3 of the * License, or (at your option) any later version. * AstrOmatic software is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with AstrOmatic software. * If not, see . * * Last modified: 29/08/2012 * *%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include #include #include #include #include #include #include "fitscat_defs.h" #include "fitscat.h" /****** about_cat ************************************************************** PROTO int about_cat(catstruct *cat, FILE *stream) PURPOSE Print some info about a catalog. INPUT Catalog structure, output stream. OUTPUT RETURN_OK if everything went as expected, RETURN_ERROR otherwise. AUTHOR E. Bertin (IAP & Leiden observatory) VERSION 19/03/2002 ***/ int about_cat(catstruct *cat, FILE *stream) { tabstruct *tab; int i; fprintf(stream,"\n"); /*General info about the catalog itself*/ fprintf(stream, "------------------Catalog information----------------\n"); fprintf(stream, "Filename:..............%s\n", cat->filename); fprintf(stream, "Number of segments:....%d\n", cat->ntab); fprintf(stream,"\n"); /*Now for each table*/ tab = cat->tab; for (i=0; intab; i++) { fprintf(stream, "****** Table #%d\n", i+1); fprintf(stream, " Extension type:.........%s\n", tab->xtension[0]? tab->xtension: "(Primary HDU)"); fprintf(stream, " Extension name:.........%s\n", tab->extname); if (tab->naxis) { fprintf(stream, " Number of dimensions:...%d\n", tab->naxis); fprintf(stream, " Number of elements:.....%d\n", tab->naxisn[1]); if (tab->tfields) fprintf(stream, " Number of data fields...%d\n", tab->tfields); fprintf(stream, " Body size:..............%ld bytes\n", (unsigned long)tab->tabsize); } fprintf(stream,"\n"); while (!(tab=tab->nexttab)->nseg); } fprintf(stream,"\n"); return RETURN_OK; } /****** addhistoryto_cat ******************************************************* PROTO int addhistoryto_cat(catstruct *cat, char *str) PURPOSE Add a HISTORY line to a FITS catalog. INPUT A pointer to catalog structure, and the character string to insert. OUTPUT RETURN_OK if everything went as expected, RETURN_ERROR otherwise. NOTES The pointer to the primary header might be reallocated if necessary. AUTHOR E. Bertin (IAP & Leiden observatory) VERSION 25/09/2004 ***/ int addhistoryto_cat(catstruct *cat, char *str) { time_t thetime; char str2[82]; tabstruct *tab; int n, headpos; tab = cat->tab; n = tab->headnblock; headpos = fitsfind(tab->headbuf, "END "); if (headpos >= n*(FBSIZE/80) - 1) { QREALLOC(tab->headbuf, char, (n+1)*FBSIZE); memset(&tab->headbuf[n*FBSIZE], ' ', FBSIZE); tab->headnblock++; } if (time(&thetime)==-1) warning("No time available for history",""); if (!strftime(str2, 16, "%d/%m/%Y %H:%M", localtime(&thetime))) error(EXIT_FAILURE, "*Internal Error*: Time/date string too long in ", "addhistoryto_cat()"); sprintf(str2, "%s %.65s", str2, str); fitsadd(tab->headbuf, "HISTORY ", str2); return RETURN_OK; } /****** close_cat ************************************************************** PROTO int close_cat(catstruct *cat) PURPOSE Close a FITS catalog. INPUT catalog structure. OUTPUT RETURN_OK if everything went as expected, RETURN_ERROR otherwise. NOTES the file structure member is set to NULL; AUTHOR E. Bertin (IAP & Leiden observatory) VERSION 22/06/2001 ***/ int close_cat(catstruct *cat) { if (cat->file && fclose(cat->file)) { cat->file = NULL; return RETURN_ERROR; } cat->file = NULL; return RETURN_OK; } #ifdef HAVE_CFITSIO int close_cfitsio(catstruct *cat) { if (cat->tab->infptr) { int status = 0; fits_close_file(cat->tab->infptr, &status); if (status != 0) { fits_report_error(stderr, status); printf("ERROR could not close FITS file with cfitsio: %s\n", cat->filename); } else { //printf("SUCCESS CFITSIO CLOSE\n\n"); cat->tab->infptr == NULL; } } //printf("NO CFITSIO FILE TO CLOSE\n"); } #endif /****** free_cat *************************************************************** PROTO void free_cat(catstruct **cat, int ncat) PURPOSE Free all structures allocated for one or several FITS catalog. INPUT Pointer to a catalog structure, Number of catalogs. OUTPUT -. NOTES Unallocated pointers should have been put to NULL. AUTHOR E. Bertin (IAP & Leiden observatory) VERSION 05/12/2009 ***/ void free_cat(catstruct **cat, int ncat) { catstruct **thecat; int i; /*--free memory allocated within each catalog */ thecat = cat; for (i=ncat; i--;) { if ((*thecat)->file) close_cat(*thecat); remove_tabs(*thecat); free(*(thecat++)); } return; } /****** inherit_cat ************************************************************ PROTO int inherit_cat(catstruct *catin, catstruct *catout) PURPOSE Copy the primary table, and all other informations from one catalog to another, except those related to the associated file itself (filename, etc...), INPUT A pointer to both catalog structures. OUTPUT RETURN_OK if at least one table was copied, RETURN_ERROR otherwise. NOTES The output catalog should be ``cleaned'' before call. AUTHOR E. Bertin (IAP & Leiden observatory) VERSION 13/06/2002 ***/ int inherit_cat(catstruct *catin, catstruct *catout) { tabstruct *tabin, *tabout, *prevtabout; int j; catout->ntab = 1; tabin = catin->tab; /*copy only one table: well it could be simpler, but let's stay general!*/ prevtabout = NULL; for (j=tabin->nseg; j--;) { QCALLOC(tabout, tabstruct, 1); *tabout = *tabin; if (tabin->naxis) QMEMCPY(tabin->naxisn, tabout->naxisn, int, (size_t)tabin->naxis); if (tabin->headbuf) QMEMCPY(tabin->headbuf, tabout->headbuf, char, tabin->headnblock*FBSIZE); if (tabin->bodybuf) QMEMCPY(tabin->bodybuf, tabout->bodybuf, char, (size_t)tabin->tabsize); if (prevtabout) { tabout->prevtab = prevtabout; prevtabout->nexttab = tabout; } else { catout->tab = tabout; } prevtabout = tabout; tabin = tabin->nexttab; } if (prevtabout) { prevtabout->nexttab = catout->tab; catout->tab->prevtab = prevtabout; } else return RETURN_ERROR; return RETURN_OK; } /****** init_cat *************************************************************** PROTO int init_cat(catstruct *cat) PURPOSE Initialize a catalog, "cleaning" any content if present and adding the primary header "table". INPUT A pointer to the catalog structure. OUTPUT RETURN_OK if everything went as expected, RETURN_ERROR otherwise. NOTES The output catalog should be ``cleaned'' before call. AUTHOR E. Bertin (IAP & Leiden observatory) VERSION 28/05/2001 ***/ int init_cat(catstruct *cat) { static char bintabtemplate[][80] = { "SIMPLE = T / This is a FITS file", "BITPIX = 8 / ", "NAXIS = 0 / ", "EXTEND = T / This file may contain FITS extensions", "END "}; tabstruct *tab; char *buf; int i; /* Initialize the primary header itself */ QCALLOC(tab, tabstruct, 1); tab->naxis = 0; tab->bitpix = 8; tab->bytepix = 1; tab->pcount = 0; tab->gcount = 1; tab->seg = 1; tab->nseg = 1; /* Provide a new header*/ QCALLOC(tab->headbuf, char, FBSIZE); memcpy(tab->headbuf, bintabtemplate, sizeof(bintabtemplate)); for (buf = tab->headbuf, i=0; iheadnblock = 1; /* Clean catalog and add the table to it */ remove_tabs(cat); cat->tab = tab->prevtab = tab->nexttab = tab; cat->ntab = 1; return RETURN_OK; } /****** map_cat **************************************************************** PROTO int map_cat(catstruct *cat) PURPOSE Explores the whole FITS file and gets information for each of the FITS tables it contains. INPUT catalog structure. OUTPUT RETURN_OK if at least one table was found, RETURN_ERROR otherwise. NOTES Memory space for the array of fits structures is reallocated. AUTHOR E. Bertin (IAP & Leiden observatory) VERSION 14/12/2002 ***/ int map_cat(catstruct *cat) { int ntab; tabstruct *tab, *prevtab; /*scan through the file until we reach the end*/ prevtab = NULL; QCALLOC(tab, tabstruct, 1); tab->cat = cat; QFTELL(cat->file, tab->headpos, cat->filename); #ifdef HAVE_CFITSIO // CFITSIO fitsfile *infptr; int status, hdutype, hdunum; status = 0; fits_open_file(&infptr, cat->filename, READONLY, &status); if (status != 0) { fits_report_error(stderr, status); printf("ERROR could not open FITS file with cfitsio: %s\n", cat->filename); } hdunum = 1; #endif for (ntab=0; !get_head(tab); ntab++) { readbasic_head(tab); readbintabparam_head(tab); QFTELL(cat->file, tab->bodypos, cat->filename); tab->nseg = tab->seg = 1; #ifdef HAVE_CFITSIO tab->hdunum = hdunum; tab->infptr = infptr; status = 0; fits_movabs_hdu(tab->infptr, tab->hdunum, &hdutype, &status); if (status != 0) printf("ERROR could not move to hdu %d in file %s\n", tab->hdunum, cat->filename); //tab->tabsize = infptr->Fptr->rowlength; //printf("TABSIZE = %ld\n", tab->tabsize); #endif if (tab->tabsize) { #ifdef HAVE_CFITSIO // IMPORTANT: moving to start of next header using fseek and cfitsio position rather than table size, as done previously fseek(cat->file, infptr->Fptr->headstart[hdunum], SEEK_SET); #else // this is how it was done previously QFSEEK(cat->file, PADTOTAL(tab->tabsize), SEEK_CUR, cat->filename); #endif } if (prevtab) { tab->prevtab = prevtab; prevtab->nexttab = tab; } else cat->tab = tab; prevtab = tab; QCALLOC(tab, tabstruct, 1); tab->cat = cat; QFTELL(cat->file, tab->headpos, cat->filename); #ifdef HAVE_CFITSIO hdunum++; #endif } cat->ntab = ntab; free(tab); if (prevtab) { prevtab->nexttab = cat->tab; cat->tab->prevtab = prevtab; } else return RETURN_ERROR; /*rewind to the beginning*/ /* QFSEEK(cat->file, 0, SEEK_SET, cat->filename); */ return RETURN_OK; } /****** new_cat **************************************************************** PROTO catstruct *new_cat(int ncat) PURPOSE Initialize a structure for a FITS catalog. INPUT Number of catalogs. OUTPUT A pointer to the catalog array. NOTES All fields are initialized to 0. AUTHOR E. Bertin (IAP & Leiden observatory) VERSION 20/03/96 ***/ catstruct *new_cat(int ncat) { catstruct *cat; QCALLOC(cat, catstruct, ncat); cat->access_type = WRITE_ONLY; return cat; } /****** open_cat *************************************************************** PROTO int open_cat(catstruct *cat, access_type_t at) PURPOSE Open a FITS catalog with name filename. INPUT catalog structure, access type (can be WRITE_ONLY or READ_ONLY). OUTPUT RETURN_OK if the cat is found, RETURN_ERROR otherwise. NOTES If the file was already opened by this catalog, nothing is done. AUTHOR E. Bertin (IAP & Leiden observatory) VERSION 29/08/2012 ***/ int open_cat(catstruct *cat, access_type_t at) { if (cat->access_type == READ_ONLY && at == WRITE_ONLY) error(EXIT_FAILURE, "*Internal Error*: Trying to write to the " "READ_ONLY catalog ", cat->filename); if (!cat->file) { if ((cat->file = fopen(cat->filename, at==WRITE_ONLY?"wb":"rb")) == NULL) return RETURN_ERROR; cat->access_type = at; } return RETURN_OK; }