void WMAPSource::addToMetadata( fitsfile *ffits, int &iStatus ) { QString str; int iResult; int keysexist; int morekeys; iResult = fits_get_hdrspace( ffits, &keysexist, &morekeys, &iStatus ); if( iResult == 0 ) { QString strTable; KstObjectTag tableTag( strTable, tag( ) ); char keyname[FLEN_KEYWORD]; char value[FLEN_VALUE]; char comment[FLEN_COMMENT]; int keynum; for( keynum=1; keynum<=keysexist; ++keynum ) { iResult = fits_read_keyn( ffits, keynum, keyname, value, comment, &iStatus ); if( iResult == 0 ) { KstString *metaString; KstObjectTag newTag( keyname, tag( ) ); str.sprintf( "%s %s", value, comment ); metaString = new KstString( newTag, this, str ); _metaData.insert( keyname, metaString ); } } } }
int copy_history(fitsfile *infptr, fitsfile *outfptr, char *infile) { int status = 0; int i, nkeys; char card[81]; /* Position files at main HDU */ fits_movabs_hdu(outfptr, 1, NULL, &status); fits_movabs_hdu(infptr, 1, NULL, &status); /* Find the number of cards in the input header */ fits_get_hdrspace(infptr, &nkeys, NULL, &status); /* Write an optional separator in the output history */ if (infile != NULL) { sprintf(card, "History from file %.40s:", infile); fits_write_history(outfptr, "-------------------------------------------------------------------", &status); fits_write_history(outfptr, card, &status); } /* Read all the input cards and copy those that are HISTORY */ for (i = 0; i < nkeys; i++) { fits_read_record(infptr, i+1, card, &status); if (strncmp(card, "HISTORY", 7) == 0) fits_write_record(outfptr, card, &status); } return status; }
bool LFIIOSource::initFile( ) { KstObject::UpdateType updateType; bool bRetVal = false; int iResult = 0; _numFrames = 0; // // read the metadata // if( !_filename.isNull( ) && !_filename.isEmpty( ) ) { QString str; fitsfile* ffits; int iStatus = 0; if( _first ) { iResult = fits_open_table( &ffits, _filename.toAscii( ), READONLY, &iStatus ); if( iResult == 0 ) { int keysexist; int morekeys; iResult = fits_get_hdrspace( ffits, &keysexist, &morekeys, &iStatus ); if( iResult == 0 ) { char keyname[FLEN_KEYWORD]; char value[FLEN_VALUE]; char comment[FLEN_COMMENT]; int keynum; for( keynum=1; keynum <= keysexist; ++keynum ) { iResult = fits_read_keyn( ffits, keynum, keyname, value, comment, &iStatus ); if( iResult == 0 ) { KstString *metaString; str.sprintf( "%s %s", value, comment ); metaString = new KstString( KstObjectTag( keyname, tag() ), this, str ); _metaData.insert( keyname, *metaString ); } } _first = false; } } } } updateType = update( ); if( updateType == KstObject::UPDATE ) { bRetVal = true; } return bRetVal; }
int FitsFile::GetKeywordCount() { int status = 0, keysexist; fits_get_hdrspace(_fptr, &keysexist, NULL, &status); CheckStatus(status); return keysexist; }
int main(int argc, char *argv[]) { fitsfile *fitsFilePtr; char card[FLEN_CARD]; int status, numKey, numHDU, curKey, curHDU, hduType; status = 0; /* Must initialize status before use */ if(argc < 2) { printf("ERROR\n"); exit(11); } /* Open the fits file */ fits_open_file(&fitsFilePtr, argv[1], READONLY, &status); reportAndExitOnFITSerror(status); /* Get the number of HDUs -- usually only one */ fits_get_num_hdus(fitsFilePtr, &numHDU, &status); reportAndExitOnFITSerror(status); printf("Number of headers in file: %d\n", numHDU); /* Get the current HDU number. This first one is '1', not '0'. */ fits_get_hdu_num(fitsFilePtr, &curHDU); reportAndExitOnFITSerror(status); printf("Working on header number: %d\n", curHDU); fits_get_hdu_type(fitsFilePtr, &hduType, &status); reportAndExitOnFITSerror(status); switch(hduType) { case IMAGE_HDU : printf("HDU Type: IMAGE\n"); break; case ASCII_TBL : printf("HDU Type: ASCII Table\n"); break; case BINARY_TBL: printf("HDU Type: Binary Table\n"); break; default : printf("HDU Type: UNKNOWN\n"); break; } /* Get the size (number of keys) of the header space */ fits_get_hdrspace(fitsFilePtr, &numKey, NULL, &status); reportAndExitOnFITSerror(status); printf("Number of keys in current HDU: %d\n", numKey); /* One can traverse all the lines like this: */ for(curKey = 1; curKey <= numKey; curKey++) { /* read the current keyword */ fits_read_record(fitsFilePtr, curKey, card, &status); reportAndExitOnFITSerror(status); printf("%5d: %s\n", curKey, card); } printf("END\n\n"); /* We are done. Close the file. */ fits_close_file(fitsFilePtr, &status); reportAndExitOnFITSerror(status); /* If we get here, everything worked! */ return 0; }
int c_tbpsta (IRAFPointer tp, int param) { /* Get the value of a parameter describing the table. arguments: IRAFPointer tp i: table descriptor int param i: code specifying the parameter to be gotten: TBL_NROWS: number of rows in the table TBL_NCOLS: number of columns in the table TBL_WHTYPE: which type of table (TBL_TYPE_FITS) TBL_NPAR: number of keywords in the header function value o: value of parameter */ TableDescr *tbl_descr; int value; char *errmsg; int status = 0; tbl_descr = (TableDescr *)tp; switch (param) { case TBL_NROWS: value = tbl_descr->nrows; break; case TBL_NCOLS: value = tbl_descr->ncols; break; case TBL_WHTYPE: /* type is FITS */ value = TBL_TYPE_FITS; break; case TBL_NPAR: /* number of keywords */ /* fits_get_hdrspace = ffghsp */ fits_get_hdrspace (tbl_descr->fptr, &value, NULL, &status); break; default: errmsg = (char *)calloc (SZ_ERRMESS+1, sizeof(char)); sprintf (errmsg, "c_tbpsta: Parameter code %d not recognized.", param); setError (ERR_PARAMETER_UNKNOWN, errmsg); free (errmsg); value = 0; break; } return value; }
/** * Function: get_fits_header * Returns the header of extension hdunum from a fits file filename * * Parameters: * @param filename The name of the FITS file * @param hdunum the number of the HDU to access * * Returns: * @return a pointer to a newly allocated string containing the entire header */ char * get_fits_header (char filename[], int hdunum) { fitsfile *input; int f_status = 0, hdutype; int nkeys, i; char card[FLEN_CARD]; char *header, *p; // Open the file for creating/appending fits_open_file (&input, filename, READONLY, &f_status); if (f_status) { ffrprt (stderr, f_status); aXe_message (aXe_M_FATAL, __FILE__, __LINE__, "get_fits_header: Could not open" " file:", filename); } fits_movabs_hdu (input, hdunum, &hdutype, &f_status); if (f_status) { ffrprt (stderr, f_status); aXe_message (aXe_M_FATAL, __FILE__, __LINE__, "get_fits_header: " "Could not read extention %d from file: %s", hdunum, filename); } fits_get_hdrspace (input, &nkeys, NULL, &f_status); /* get # of keywords */ header = (char *) malloc ((nkeys + 1) * FLEN_CARD * sizeof (char)); p = header; for (i = 0; i < nkeys; i++) { /* Read and print each keywords */ if (fits_read_record (input, i + 1, card, &f_status)) break; sprintf(p,"%-80s", card); p = p + 80; } /* Add END keyword */ sprintf (card, "END"); sprintf(p,"%-80s", card); return header; }
void FitsReader::readHistory() { int status = 0; int npos, moreKeys; fits_get_hdrspace(_fitsPtr, &npos, &moreKeys, &status); checkStatus(status, _filename); char keyCard[256]; for(int pos=1; pos<=npos; ++pos) { fits_read_record(_fitsPtr, pos, keyCard, &status); keyCard[7] = 0; if(std::string("HISTORY") == keyCard) { _history.push_back(&keyCard[8]); } } }
int appendheader ( char *outfile, char *infile ) { fitsfile *infptr, *outfptr; /* FITS file pointer, defined in fitsio.h */ char card[FLEN_CARD]; /* Standard string lengths defined in fitsio.h */ int status = 0; /* CFITSIO status value MUST be initialized to zero! */ int nkeys, ii; char keyword[FLEN_KEYWORD], keyvalue[FLEN_VALUE], keycomment[FLEN_COMMENT]; char temp[FLEN_KEYWORD]; strcpy(temp,"COMMENT"); if (!fits_open_file(&infptr, infile, READONLY, &status)) { if (!fits_open_file(&outfptr, outfile, READWRITE, &status)) { fits_get_hdrspace(infptr, &nkeys, NULL, &status); /* get # of keywords */ for (ii = 1; ii <= nkeys; ii++) { /* Read and write each keywords */ if (fits_read_record(infptr, ii, card, &status))break; fits_read_keyn(infptr, ii, keyword, keyvalue, keycomment, &status); /* check if this is a protected keyword that must not be changed */ if (*card && fits_get_keyclass(card) == TYP_STRUC_KEY) printf("%s - Protected keyword cannot be modified.\n", keyword); else { if (!strcmp(temp, keyword)) { /* do not overwrite COMMENTs */ fits_write_record(outfptr, card, &status); } else { fits_update_card(outfptr, keyword, card, &status); } printf("Writing - %s\n", card); } } fits_close_file(outfptr, &status); } if (status == END_OF_FILE) status = 0; /* Reset after normal error */ fits_close_file(infptr, &status); } }
int showkey(char *filename, char *keyword) { /* function showkey displays keyword and value if keyword is COMMENT or HISTORY, it displays all respective lines. */ fitsfile *fptr; /* FITS file pointer, defined in fitsio.h */ char card[FLEN_CARD]; int status = 0, nkeys, i; /* CFITSIO status value MUST be initialized to zero! */ if (!fits_open_file(&fptr, filename, READONLY, &status)) { for (i=0; i<FLEN_CARD; i++) keyword[i]=toupper(keyword[i]); if ( !strcmp(keyword, "COMMENT") || !strcmp(keyword, "HISTORY")) { fits_get_hdrspace(fptr, &nkeys, NULL, &status); /* get # of keywords */ for (i = 1; i <= nkeys; i++) { /* Read and print each keywords */ if (fits_read_record(fptr, i, card, &status)) break; if ( !strncmp(card, keyword, 7) ) printf("%s\n", card); } } else { if (fits_read_card(fptr, keyword, card, &status)) { printf("Keyword does not exist\n"); status = 0; /* reset status after error */ } else printf("%s\n",card); } fits_close_file(fptr, &status); } /* open_file */ /* if error occured, print out error message */ if (status) fits_report_error(stderr, status); return(status); }
int main(int argc, char *argv[]) { (void)argc; fitsfile *fptr; char card[FLEN_CARD]; int status = 0, nkeys, ii; /* MUST initialize status */ fits_open_file(&fptr, argv[1], READONLY, &status); fits_get_hdrspace(fptr, &nkeys, NULL, &status); for (ii = 1; ii <= nkeys; ii++) { fits_read_record(fptr, ii, card, &status); /* read keyword */ printf("%s\n", card); } printf("END\n\n"); /* terminate listing with END */ fits_close_file(fptr, &status); if (status) /* print any error messages */ fits_report_error(stderr, status); return(status); }
int fits_print_header(fitsfile* fptr, int* status) { /* get # of keywords */ int nkeys = 0; fits_get_hdrspace(fptr, &nkeys, 0, status); if (*status && nkeys == 0) return *status; /* Standard string lengths defined in fitsio.h */ static char card[FLEN_CARD]; int i; /* Read and print each keywords */ for (i=1; i<=nkeys; i++) { if (fits_read_record(fptr, i, card, status)) break; printf("%s\n", card); } /* terminate listing with END */ printf("END\n"); fits_print_error(*status); return *status; }
void loadPrimaryHeader(fitsfile *fp,dSet *data) { int status=0; int nkey=-1; int morekeys=-1; int i; char keyname[128],val[128],comment[128]; fits_get_hdrspace(fp,&nkey,&morekeys,&status); data->pheaderSet = 1; data->phead.nhead = nkey; // Allocate memory data->phead.keyname = (char **)malloc(sizeof(char *)*nkey); data->phead.val = (char **)malloc(sizeof(char *)*nkey); data->phead.comment = (char **)malloc(sizeof(char *)*nkey); for (i=0;i<nkey;i++) { data->phead.keyname[i] = (char *)malloc(sizeof(char)*128); data->phead.val[i] = (char *)malloc(sizeof(char)*128); data->phead.comment[i] = (char *)malloc(sizeof(char)*128); } data->pheaderSet=1; // Complete allocating memory for (i=1;i<=nkey;i++) { fits_read_keyn(fp,i+1,data->phead.keyname[i-1],data->phead.val[i-1],data->phead.comment[i-1],&status); if (strcmp(data->phead.keyname[i-1],"OBSFREQ")==0) sscanf(data->phead.val[i-1],"%f",&(data->phead.freq)); else if (strcmp(data->phead.keyname[i-1],"STT_IMJD")==0) sscanf(data->phead.val[i-1],"%d",&(data->phead.imjd)); else if (strcmp(data->phead.keyname[i-1],"STT_SMJD")==0) sscanf(data->phead.val[i-1],"%f",&(data->phead.smjd)); else if (strcmp(data->phead.keyname[i-1],"STT_OFFS")==0) sscanf(data->phead.val[i-1],"%f",&(data->phead.stt_offs)); else if (strcmp(data->phead.keyname[i-1],"OBSBW")==0) sscanf(data->phead.val[i-1],"%f",&(data->phead.bw)); } // Read specific parameters fits_read_key(fp,TSTRING,"OBS_MODE",data->phead.obsMode,NULL,&status); fits_read_key(fp,TSTRING,"SRC_NAME",data->phead.source,NULL,&status); if (status) { fits_report_error(stderr,status); exit(1); } // Now load information from the subintegration table fits_movnam_hdu(fp,BINARY_TBL,"SUBINT",1,&status); if (status) { printf("No subintegration table\n"); data->subintTable=0; status=0; } else { data->subintTable=1; fits_read_key(fp,TINT,"NAXIS2",&(data->phead.nsub),NULL,&status); if (status) { printf("Reading naxis2\n"); fits_report_error(stderr,status); exit(1); } fits_read_key(fp,TINT,"NCHAN",&(data->phead.nchan),NULL,&status); if (status) { printf("Reading nchan\n"); fits_report_error(stderr,status); exit(1); } fits_read_key(fp,TFLOAT,"ZERO_OFF",&(data->phead.zeroOff),NULL,&status); if (status) { printf("Reading zero_off\n"); fits_report_error(stderr,status); data->phead.zeroOff = 0; status=0; } fits_read_key(fp,TINT,"NBITS",&(data->phead.nbits),NULL,&status); if (status) { printf("Reading nbits\n"); fits_report_error(stderr,status); exit(1); } fits_read_key(fp,TINT,"NPOL",&(data->phead.npol),NULL,&status); if (status) { printf("Reading npol\n"); fits_report_error(stderr,status); exit(1); } fits_read_key(fp,TINT,"NSBLK",&(data->phead.nsblk),NULL,&status); if (status) { printf("Reading nsblk\n"); fits_report_error(stderr,status); exit(1); } fits_read_key(fp,TINT,"NBIN",&(data->phead.nbin),NULL,&status); if (status) { printf("Reading nbin\n"); fits_report_error(stderr,status); exit(1); } // printf("nbin = %d (%d)\n",data->phead.nbin,status); fits_read_key(fp,TFLOAT,"CHAN_BW",&(data->phead.chanbw),NULL,&status); if (data->phead.chanbw < 0 && data->phead.bw > 0) data->phead.bw*=-1; fits_read_key(fp,TFLOAT,"TBIN",&(data->phead.tsamp),NULL,&status); } fits_movnam_hdu(fp,BINARY_TBL,"PSRPARAM",1,&status); if (status) { printf("No PSRPARM table\n"); data->psrparamTable=0; status=0; } else { int len,i,colnum; char **line,str1[1024],str2[1024]; data->psrparamTable=1; char nval[128]="UNKNOWN"; int anynul=0; float tt; fits_read_key(fp,TINT,"NAXIS2",&len,NULL,&status); fits_get_colnum(fp,CASEINSEN,"PARAM",&colnum,&status); if (status) { printf("Unable to find data in the psrparam table in FITS file\n"); exit(1); } line = (char **)malloc(sizeof(char *)); line[0] = (char *)malloc(sizeof(char)*1024); for (i=0;i<len;i++) { fits_read_col_str(fp,colnum,i+1,1,1,nval,line,&anynul,&status); if (sscanf(line[0],"%s %s",str1,str2)==2) { if (strcasecmp(str1,"DM")==0) sscanf(str2,"%f",&(data->phead.dm)); if (strcasecmp(str1,"F0")==0) { sscanf(str2,"%f",&tt); data->phead.period = 1.0/tt; } } // printf("Read: %s\n",line[0]); } // printf("Lenght = %d\n",len); free(line[0]); free(line); } }
int main(int argc, char *argv[]) { fitsfile *infptr, *outfptr; /* FITS file pointers defined in fitsio.h */ int status = 0, ii = 1, iteration = 0, single = 0, hdupos; int hdutype, bitpix, bytepix, naxis = 0, nkeys, datatype = 0, anynul; long naxes[9] = {1, 1, 1, 1, 1, 1, 1, 1, 1}; long first, totpix = 0, npix; double *array, bscale = 1.0, bzero = 0.0, nulval = 0.; char card[81]; if (argc != 3) { printf("\n"); printf("Usage: imcopy inputImage outputImage[compress]\n"); printf("\n"); printf("Copy an input image to an output image, optionally compressing\n"); printf("or uncompressing the image in the process. If the [compress]\n"); printf("qualifier is appended to the output file name then the input image\n"); printf("will be compressed using the tile-compressed format. In this format,\n"); printf("the image is divided into rectangular tiles and each tile of pixels\n"); printf("is compressed and stored in a variable-length row of a binary table.\n"); printf("If the [compress] qualifier is omitted, and the input image is\n"); printf("in tile-compressed format, then the output image will be uncompressed.\n"); printf("\n"); printf("If an extension name or number is appended to the input file name, \n"); printf("enclosed in square brackets, then only that single extension will be\n"); printf("copied to the output file. Otherwise, every extension in the input file\n"); printf("will be processed in turn and copied to the output file.\n"); printf("\n"); printf("Examples:\n"); printf("\n"); printf("1) imcopy image.fit 'cimage.fit[compress]'\n"); printf("\n"); printf(" This compresses the input image using the default parameters, i.e.,\n"); printf(" using the Rice compression algorithm and using row by row tiles.\n"); printf("\n"); printf("2) imcopy cimage.fit image2.fit\n"); printf("\n"); printf(" This uncompress the image created in the first example.\n"); printf(" image2.fit should be identical to image.fit if the image\n"); printf(" has an integer datatype. There will be small differences\n"); printf(" in the pixel values if it is a floating point image.\n"); printf("\n"); printf("3) imcopy image.fit 'cimage.fit[compress GZIP 100,100;4]'\n"); printf("\n"); printf(" This compresses the input image using the following parameters:\n"); printf(" GZIP compression algorithm;\n"); printf(" 100 X 100 pixel compression tiles;\n"); printf(" noise_bits = 4 (only used with floating point images)\n"); printf("\n"); printf("The full syntax of the compression qualifier is:\n"); printf(" [compress ALGORITHM TDIM1,TDIM2,...; NOISE_BITS]\n"); printf("where the allowed ALGORITHM values are Rice, GZIP, PLIO, \n"); printf("and TDIMn is the size of the compression tile in each dimension,\n"); printf("and NOISE_BITS = 1, 2, 3, or 4 and controls the amount of noise\n"); printf("suppression when compressing floating point images. \n"); printf("\n"); printf("Note that it may be necessary to enclose the file names\n"); printf("in single quote characters on the Unix command line.\n"); return(0); } /* Open the input file and create output file */ fits_open_file(&infptr, argv[1], READONLY, &status); fits_create_file(&outfptr, argv[2], &status); if (status != 0) { fits_report_error(stderr, status); return(status); } fits_get_hdu_num(infptr, &hdupos); /* Get the current HDU position */ /* Copy only a single HDU if a specific extension was given */ if (hdupos != 1 || strchr(argv[1], '[')) single = 1; for (; !status; hdupos++) /* Main loop through each extension */ { fits_get_hdu_type(infptr, &hdutype, &status); if (hdutype == IMAGE_HDU) { /* get image dimensions and total number of pixels in image */ for (ii = 0; ii < 9; ii++) naxes[ii] = 1; fits_get_img_param(infptr, 9, &bitpix, &naxis, naxes, &status); totpix = naxes[0] * naxes[1] * naxes[2] * naxes[3] * naxes[4] * naxes[5] * naxes[6] * naxes[7] * naxes[8]; } if (hdutype != IMAGE_HDU || naxis == 0 || totpix == 0) { /* just copy tables and null images */ fits_copy_hdu(infptr, outfptr, 0, &status); } else { /* Explicitly create new image, to support compression */ fits_create_img(outfptr, bitpix, naxis, naxes, &status); if (status) { fits_report_error(stderr, status); return(status); } /* copy all the user keywords (not the structural keywords) */ fits_get_hdrspace(infptr, &nkeys, NULL, &status); for (ii = 1; ii <= nkeys; ii++) { fits_read_record(infptr, ii, card, &status); if (fits_get_keyclass(card) > TYP_CMPRS_KEY) fits_write_record(outfptr, card, &status); } switch(bitpix) { case BYTE_IMG: datatype = TBYTE; break; case SHORT_IMG: datatype = TSHORT; break; case LONG_IMG: datatype = TINT; break; case FLOAT_IMG: datatype = TFLOAT; break; case DOUBLE_IMG: datatype = TDOUBLE; break; } bytepix = abs(bitpix) / 8; npix = totpix; iteration = 0; /* try to allocate memory for the entire image */ /* use double type to force memory alignment */ array = (double *) calloc(npix, bytepix); /* if allocation failed, divide size by 2 and try again */ while (!array && iteration < 10) { iteration++; npix = npix / 2; array = (double *) calloc(npix, bytepix); } if (!array) { printf("Memory allocation error\n"); return(0); } /* turn off any scaling so that we copy the raw pixel values */ fits_set_bscale(infptr, bscale, bzero, &status); fits_set_bscale(outfptr, bscale, bzero, &status); first = 1; while (totpix > 0 && !status) { /* read all or part of image then write it back to the output file */ fits_read_img(infptr, datatype, first, npix, &nulval, array, &anynul, &status); fits_write_img(outfptr, datatype, first, npix, array, &status); totpix = totpix - npix; first = first + npix; } free(array); } if (single) break; /* quit if only copying a single HDU */ fits_movrel_hdu(infptr, 1, NULL, &status); /* try to move to next HDU */ } if (status == END_OF_FILE) status = 0; /* Reset after normal error */ fits_close_file(outfptr, &status); fits_close_file(infptr, &status); /* if error occurred, print out error message */ if (status) fits_report_error(stderr, status); return(status); }
/*--------------------------------------------------------------------------*/ int ffhist(fitsfile **fptr, /* IO - pointer to table with X and Y cols; */ /* on output, points to histogram image */ char *outfile, /* I - name for the output histogram file */ int imagetype, /* I - datatype for image: TINT, TSHORT, etc */ int naxis, /* I - number of axes in the histogram image */ char colname[4][FLEN_VALUE], /* I - column names */ double *minin, /* I - minimum histogram value, for each axis */ double *maxin, /* I - maximum histogram value, for each axis */ double *binsizein, /* I - bin size along each axis */ char minname[4][FLEN_VALUE], /* I - optional keywords for min */ char maxname[4][FLEN_VALUE], /* I - optional keywords for max */ char binname[4][FLEN_VALUE], /* I - optional keywords for binsize */ double weightin, /* I - binning weighting factor */ char wtcol[FLEN_VALUE], /* I - optional keyword or col for weight*/ int recip, /* I - use reciprocal of the weight? */ char *selectrow, /* I - optional array (length = no. of */ /* rows in the table). If the element is true */ /* then the corresponding row of the table will*/ /* be included in the histogram, otherwise the */ /* row will be skipped. Ingnored if *selectrow*/ /* is equal to NULL. */ int *status) { int ii, datatype, repeat, imin, imax, ibin, bitpix, tstatus, use_datamax = 0; long haxes[4]; fitsfile *histptr; char errmsg[FLEN_ERRMSG], keyname[FLEN_KEYWORD], card[FLEN_CARD]; tcolumn *colptr; iteratorCol imagepars[1]; int n_cols = 1, nkeys; long offset = 0; long n_per_loop = -1; /* force whole array to be passed at one time */ histType histData; /* Structure holding histogram info for iterator */ float amin[4], amax[4], binsize[4], maxbin[4]; float datamin = FLOATNULLVALUE, datamax = FLOATNULLVALUE; char svalue[FLEN_VALUE]; double dvalue; char cpref[4][FLEN_VALUE]; char *cptr; if (*status > 0) return(*status); if (naxis > 4) { ffpmsg("histogram has more than 4 dimensions"); return(*status = BAD_DIMEN); } /* reset position to the correct HDU if necessary */ if ((*fptr)->HDUposition != ((*fptr)->Fptr)->curhdu) ffmahd(*fptr, ((*fptr)->HDUposition) + 1, NULL, status); histData.tblptr = *fptr; histData.himagetype = imagetype; histData.haxis = naxis; histData.rowselector = selectrow; if (imagetype == TBYTE) bitpix = BYTE_IMG; else if (imagetype == TSHORT) bitpix = SHORT_IMG; else if (imagetype == TINT) bitpix = LONG_IMG; else if (imagetype == TFLOAT) bitpix = FLOAT_IMG; else if (imagetype == TDOUBLE) bitpix = DOUBLE_IMG; else return(*status = BAD_DATATYPE); /* The CPREF keyword, if it exists, gives the preferred columns. */ /* Otherwise, assume "X", "Y", "Z", and "T" */ tstatus = 0; ffgky(*fptr, TSTRING, "CPREF", cpref[0], NULL, &tstatus); if (!tstatus) { /* Preferred column names are given; separate them */ cptr = cpref[0]; /* the first preferred axis... */ while (*cptr != ',' && *cptr != '\0') cptr++; if (*cptr != '\0') { *cptr = '\0'; cptr++; while (*cptr == ' ') cptr++; strcpy(cpref[1], cptr); cptr = cpref[1]; /* the second preferred axis... */ while (*cptr != ',' && *cptr != '\0') cptr++; if (*cptr != '\0') { *cptr = '\0'; cptr++; while (*cptr == ' ') cptr++; strcpy(cpref[2], cptr); cptr = cpref[2]; /* the third preferred axis... */ while (*cptr != ',' && *cptr != '\0') cptr++; if (*cptr != '\0') { *cptr = '\0'; cptr++; while (*cptr == ' ') cptr++; strcpy(cpref[3], cptr); } } } } for (ii = 0; ii < naxis; ii++) { /* get the min, max, and binsize values from keywords, if specified */ if (*minname[ii]) { if (ffgky(*fptr, TDOUBLE, minname[ii], &minin[ii], NULL, status) ) { ffpmsg("error reading histogramming minimum keyword"); ffpmsg(minname[ii]); return(*status); } } if (*maxname[ii]) { if (ffgky(*fptr, TDOUBLE, maxname[ii], &maxin[ii], NULL, status) ) { ffpmsg("error reading histogramming maximum keyword"); ffpmsg(maxname[ii]); return(*status); } } if (*binname[ii]) { if (ffgky(*fptr, TDOUBLE, binname[ii], &binsizein[ii], NULL, status) ) { ffpmsg("error reading histogramming binsize keyword"); ffpmsg(binname[ii]); return(*status); } } if (binsizein[ii] == 0.) { ffpmsg("error: histogram binsize = 0"); return(*status = ZERO_SCALE); } if (*colname[ii] == '\0') { strcpy(colname[ii], cpref[ii]); /* try using the preferred column */ if (*colname[ii] == '\0') { if (ii == 0) strcpy(colname[ii], "X"); else if (ii == 1) strcpy(colname[ii], "Y"); else if (ii == 2) strcpy(colname[ii], "Z"); else if (ii == 3) strcpy(colname[ii], "T"); } } /* get the column number in the table */ if (ffgcno(*fptr, CASEINSEN, colname[ii], histData.hcolnum+ii, status) > 0) { strcpy(errmsg, "column for histogram axis doesn't exist: "); strcat(errmsg, colname[ii]); ffpmsg(errmsg); return(*status); } colptr = ((*fptr)->Fptr)->tableptr; colptr += (histData.hcolnum[ii] - 1); repeat = (int) colptr->trepeat; /* vector repeat factor of the column */ if (repeat > 1) { strcpy(errmsg, "Can't bin a vector column: "); strcat(errmsg, colname[ii]); ffpmsg(errmsg); return(*status = BAD_DATATYPE); } /* get the datatype of the column */ fits_get_coltype(*fptr, histData.hcolnum[ii], &datatype, NULL, NULL, status); if (datatype < 0 || datatype == TSTRING) { strcpy(errmsg, "Inappropriate datatype; can't bin this column: "); strcat(errmsg, colname[ii]); ffpmsg(errmsg); return(*status = BAD_DATATYPE); } /* use TLMINn and TLMAXn keyword values if min and max were not given */ /* else use actual data min and max if TLMINn and TLMAXn don't exist */ if (minin[ii] == DOUBLENULLVALUE) { ffkeyn("TLMIN", histData.hcolnum[ii], keyname, status); if (ffgky(*fptr, TFLOAT, keyname, amin+ii, NULL, status) > 0) { /* use actual data minimum value for the histogram minimum */ *status = 0; if (fits_get_col_minmax(*fptr, histData.hcolnum[ii], amin+ii, &datamax, status) > 0) { strcpy(errmsg, "Error calculating datamin and datamax for column: "); strcat(errmsg, colname[ii]); ffpmsg(errmsg); return(*status); } } } else { amin[ii] = (float) minin[ii]; } if (maxin[ii] == DOUBLENULLVALUE) { ffkeyn("TLMAX", histData.hcolnum[ii], keyname, status); if (ffgky(*fptr, TFLOAT, keyname, &amax[ii], NULL, status) > 0) { *status = 0; if(datamax != FLOATNULLVALUE) /* already computed max value */ { amax[ii] = datamax; } else { /* use actual data maximum value for the histogram maximum */ if (fits_get_col_minmax(*fptr, histData.hcolnum[ii], &datamin, &amax[ii], status) > 0) { strcpy(errmsg, "Error calculating datamin and datamax for column: "); strcat(errmsg, colname[ii]); ffpmsg(errmsg); return(*status); } } } use_datamax = 1; /* flag that the max was determined by the data values */ /* and not specifically set by the calling program */ } else { amax[ii] = (float) maxin[ii]; } /* use TDBINn keyword or else 1 if bin size is not given */ if (binsizein[ii] == DOUBLENULLVALUE) { tstatus = 0; ffkeyn("TDBIN", histData.hcolnum[ii], keyname, &tstatus); if (ffgky(*fptr, TDOUBLE, keyname, binsizein + ii, NULL, &tstatus) > 0) { /* make at least 10 bins */ binsizein[ii] = (amax[ii] - amin[ii]) / 10. ; if (binsizein[ii] > 1.) binsizein[ii] = 1.; /* use default bin size */ } } if ( (amin[ii] > amax[ii] && binsizein[ii] > 0. ) || (amin[ii] < amax[ii] && binsizein[ii] < 0. ) ) binsize[ii] = (float) -binsizein[ii]; /* reverse the sign of binsize */ else binsize[ii] = (float) binsizein[ii]; /* binsize has the correct sign */ ibin = (int) binsize[ii]; imin = (int) amin[ii]; imax = (int) amax[ii]; /* Determine the range and number of bins in the histogram. This */ /* depends on whether the input columns are integer or floats, so */ /* treat each case separately. */ if (datatype <= TLONG && (float) imin == amin[ii] && (float) imax == amax[ii] && (float) ibin == binsize[ii] ) { /* This is an integer column and integer limits were entered. */ /* Shift the lower and upper histogramming limits by 0.5, so that */ /* the values fall in the center of the bin, not on the edge. */ haxes[ii] = (imax - imin) / ibin + 1; /* last bin may only */ /* be partially full */ maxbin[ii] = (float) (haxes[ii] + 1.); /* add 1. instead of .5 to avoid roundoff */ if (amin[ii] < amax[ii]) { amin[ii] = (float) (amin[ii] - 0.5); amax[ii] = (float) (amax[ii] + 0.5); } else { amin[ii] = (float) (amin[ii] + 0.5); amax[ii] = (float) (amax[ii] - 0.5); } } else if (use_datamax) { /* Either the column datatype and/or the limits are floating point, */ /* and the histogram limits are being defined by the min and max */ /* values of the array. Add 1 to the number of histogram bins to */ /* make sure that pixels that are equal to the maximum or are */ /* in the last partial bin are included. */ maxbin[ii] = (amax[ii] - amin[ii]) / binsize[ii]; haxes[ii] = (long) (maxbin[ii] + 1); } else { /* float datatype column and/or limits, and the maximum value to */ /* include in the histogram is specified by the calling program. */ /* The lower limit is inclusive, but upper limit is exclusive */ maxbin[ii] = (amax[ii] - amin[ii]) / binsize[ii]; haxes[ii] = (long) maxbin[ii]; if (amin[ii] < amax[ii]) { if (amin[ii] + (haxes[ii] * binsize[ii]) < amax[ii]) haxes[ii]++; /* need to include another partial bin */ } else { if (amin[ii] + (haxes[ii] * binsize[ii]) > amax[ii]) haxes[ii]++; /* need to include another partial bin */ } } } /* get the histogramming weighting factor */ if (*wtcol) { /* first, look for a keyword with the weight value */ if (ffgky(*fptr, TFLOAT, wtcol, &histData.weight, NULL, status) ) { /* not a keyword, so look for column with this name */ *status = 0; /* get the column number in the table */ if (ffgcno(*fptr, CASEINSEN, wtcol, &histData.wtcolnum, status) > 0) { ffpmsg( "keyword or column for histogram weights doesn't exist: "); ffpmsg(wtcol); return(*status); } histData.weight = FLOATNULLVALUE; } } else histData.weight = (float) weightin; if (histData.weight <= 0. && histData.weight != FLOATNULLVALUE) { ffpmsg("Illegal histogramming weighting factor <= 0."); return(*status = URL_PARSE_ERROR); } if (recip && histData.weight != FLOATNULLVALUE) /* take reciprocal of weight */ histData.weight = (float) (1.0 / histData.weight); histData.wtrecip = recip; /* size of histogram is now known, so create temp output file */ if (ffinit(&histptr, outfile, status) > 0) { ffpmsg("failed to create temp output file for histogram"); return(*status); } if (ffcrim(histptr, bitpix, histData.haxis, haxes, status) > 0) { ffpmsg("failed to create primary array histogram in temp file"); ffclos(histptr, status); return(*status); } /* copy all non-structural keywords from the table to the image */ fits_get_hdrspace(*fptr, &nkeys, NULL, status); for (ii = 1; ii <= nkeys; ii++) { fits_read_record(*fptr, ii, card, status); if (fits_get_keyclass(card) >= 120) fits_write_record(histptr, card, status); } /* Set global variables with histogram parameter values. */ /* Use separate scalar variables rather than arrays because */ /* it is more efficient when computing the histogram. */ histData.amin1 = amin[0]; histData.maxbin1 = maxbin[0]; histData.binsize1 = binsize[0]; histData.haxis1 = haxes[0]; if (histData.haxis > 1) { histData.amin2 = amin[1]; histData.maxbin2 = maxbin[1]; histData.binsize2 = binsize[1]; histData.haxis2 = haxes[1]; if (histData.haxis > 2) { histData.amin3 = amin[2]; histData.maxbin3 = maxbin[2]; histData.binsize3 = binsize[2]; histData.haxis3 = haxes[2]; if (histData.haxis > 3) { histData.amin4 = amin[3]; histData.maxbin4 = maxbin[3]; histData.binsize4 = binsize[3]; histData.haxis4 = haxes[3]; } } } /* define parameters of image for the iterator function */ fits_iter_set_file(imagepars, histptr); /* pointer to image */ fits_iter_set_datatype(imagepars, imagetype); /* image datatype */ fits_iter_set_iotype(imagepars, OutputCol); /* image is output */ /* call the iterator function to write out the histogram image */ if (fits_iterate_data(n_cols, imagepars, offset, n_per_loop, ffwritehisto, (void*)&histData, status) ) return(*status); /* write the World Coordinate System (WCS) keywords */ /* create default values if WCS keywords are not present in the table */ for (ii = 0; ii < histData.haxis; ii++) { /* CTYPEn */ tstatus = 0; ffkeyn("TCTYP", histData.hcolnum[ii], keyname, &tstatus); ffgky(*fptr, TSTRING, keyname, svalue, NULL, &tstatus); if (tstatus) { /* just use column name as the type */ tstatus = 0; ffkeyn("TTYPE", histData.hcolnum[ii], keyname, &tstatus); ffgky(*fptr, TSTRING, keyname, svalue, NULL, &tstatus); } if (!tstatus) { ffkeyn("CTYPE", ii + 1, keyname, &tstatus); ffpky(histptr, TSTRING, keyname, svalue, "Coordinate Type", &tstatus); } else tstatus = 0; /* CUNITn */ ffkeyn("TCUNI", histData.hcolnum[ii], keyname, &tstatus); ffgky(*fptr, TSTRING, keyname, svalue, NULL, &tstatus); if (tstatus) { /* use the column units */ tstatus = 0; ffkeyn("TUNIT", histData.hcolnum[ii], keyname, &tstatus); ffgky(*fptr, TSTRING, keyname, svalue, NULL, &tstatus); } if (!tstatus) { ffkeyn("CUNIT", ii + 1, keyname, &tstatus); ffpky(histptr, TSTRING, keyname, svalue, "Coordinate Units", &tstatus); } else tstatus = 0; /* CRPIXn - Reference Pixel */ ffkeyn("TCRPX", histData.hcolnum[ii], keyname, &tstatus); ffgky(*fptr, TDOUBLE, keyname, &dvalue, NULL, &tstatus); if (tstatus) { dvalue = 1.0; /* choose first pixel in new image as ref. pix. */ tstatus = 0; } else { /* calculate locate of the ref. pix. in the new image */ dvalue = (dvalue - amin[ii]) / binsize[ii] + .5; } ffkeyn("CRPIX", ii + 1, keyname, &tstatus); ffpky(histptr, TDOUBLE, keyname, &dvalue, "Reference Pixel", &tstatus); /* CRVALn - Value at the location of the reference pixel */ ffkeyn("TCRVL", histData.hcolnum[ii], keyname, &tstatus); ffgky(*fptr, TDOUBLE, keyname, &dvalue, NULL, &tstatus); if (tstatus) { /* calculate value at ref. pix. location (at center of 1st pixel) */ dvalue = amin[ii] + binsize[ii]/2.; tstatus = 0; } ffkeyn("CRVAL", ii + 1, keyname, &tstatus); ffpky(histptr, TDOUBLE, keyname, &dvalue, "Reference Value", &tstatus); /* CDELTn - unit size of pixels */ ffkeyn("TCDLT", histData.hcolnum[ii], keyname, &tstatus); ffgky(*fptr, TDOUBLE, keyname, &dvalue, NULL, &tstatus); if (tstatus) { dvalue = 1.0; /* use default pixel size */ tstatus = 0; } dvalue = dvalue * binsize[ii]; ffkeyn("CDELT", ii + 1, keyname, &tstatus); ffpky(histptr, TDOUBLE, keyname, &dvalue, "Pixel size", &tstatus); /* CROTAn - Rotation angle (degrees CCW) */ /* There should only be a CROTA2 keyword, and only for 2+ D images */ if (ii == 1) { ffkeyn("TCROT", histData.hcolnum[ii], keyname, &tstatus); ffgky(*fptr, TDOUBLE, keyname, &dvalue, NULL, &tstatus); if (!tstatus && dvalue != 0.) /* only write keyword if angle != 0 */ { ffkeyn("CROTA", ii + 1, keyname, &tstatus); ffpky(histptr, TDOUBLE, keyname, &dvalue, "Rotation angle", &tstatus); } else { /* didn't find CROTA for the 2nd axis, so look for one */ /* on the first axis */ tstatus = 0; ffkeyn("TCROT", histData.hcolnum[0], keyname, &tstatus); ffgky(*fptr, TDOUBLE, keyname, &dvalue, NULL, &tstatus); if (!tstatus && dvalue != 0.) /* only write keyword if angle != 0 */ { dvalue *= -1.; /* negate the value, because mirror image */ ffkeyn("CROTA", ii + 1, keyname, &tstatus); ffpky(histptr, TDOUBLE, keyname, &dvalue, "Rotation angle", &tstatus); } } } } /* convert any TPn_k keywords to PCi_j; the value remains unchanged */ /* also convert any TCn_k to CDi_j; the value is modified by n binning size */ /* This is a bit of a kludge, and only works for 2D WCS */ if (histData.haxis == 2) { /* PC1_1 */ tstatus = 0; ffkeyn("TP", histData.hcolnum[0], card, &tstatus); strcat(card,"_"); ffkeyn(card, histData.hcolnum[0], keyname, &tstatus); ffgky(*fptr, TDOUBLE, keyname, &dvalue, card, &tstatus); if (!tstatus) ffpky(histptr, TDOUBLE, "PC1_1", &dvalue, card, &tstatus); tstatus = 0; keyname[1] = 'C'; ffgky(*fptr, TDOUBLE, keyname, &dvalue, card, &tstatus); if (!tstatus) { dvalue *= binsize[0]; ffpky(histptr, TDOUBLE, "CD1_1", &dvalue, card, &tstatus); } /* PC1_2 */ tstatus = 0; ffkeyn("TP", histData.hcolnum[0], card, &tstatus); strcat(card,"_"); ffkeyn(card, histData.hcolnum[1], keyname, &tstatus); ffgky(*fptr, TDOUBLE, keyname, &dvalue, card, &tstatus); if (!tstatus) ffpky(histptr, TDOUBLE, "PC1_2", &dvalue, card, &tstatus); tstatus = 0; keyname[1] = 'C'; ffgky(*fptr, TDOUBLE, keyname, &dvalue, card, &tstatus); if (!tstatus) { dvalue *= binsize[0]; ffpky(histptr, TDOUBLE, "CD1_2", &dvalue, card, &tstatus); } /* PC2_1 */ tstatus = 0; ffkeyn("TP", histData.hcolnum[1], card, &tstatus); strcat(card,"_"); ffkeyn(card, histData.hcolnum[0], keyname, &tstatus); ffgky(*fptr, TDOUBLE, keyname, &dvalue, card, &tstatus); if (!tstatus) ffpky(histptr, TDOUBLE, "PC2_1", &dvalue, card, &tstatus); tstatus = 0; keyname[1] = 'C'; ffgky(*fptr, TDOUBLE, keyname, &dvalue, card, &tstatus); if (!tstatus) { dvalue *= binsize[1]; ffpky(histptr, TDOUBLE, "CD2_1", &dvalue, card, &tstatus); } /* PC2_2 */ tstatus = 0; ffkeyn("TP", histData.hcolnum[1], card, &tstatus); strcat(card,"_"); ffkeyn(card, histData.hcolnum[1], keyname, &tstatus); ffgky(*fptr, TDOUBLE, keyname, &dvalue, card, &tstatus); if (!tstatus) ffpky(histptr, TDOUBLE, "PC2_2", &dvalue, card, &tstatus); tstatus = 0; keyname[1] = 'C'; ffgky(*fptr, TDOUBLE, keyname, &dvalue, card, &tstatus); if (!tstatus) { dvalue *= binsize[1]; ffpky(histptr, TDOUBLE, "CD2_2", &dvalue, card, &tstatus); } } /* finally, close the original file and return ptr to the new image */ ffclos(*fptr, status); *fptr = histptr; return(*status); }
int checkHdr(char *infile, int hdrflag, int hdu) { int i, len, ncard, morekeys; int status = 0; char *keyword; char *value; char fitskeyword[80]; char fitsvalue [80]; char fitscomment[80]; char tmpstr [80]; char *end; char line [1024]; char pline [1024]; char *ptr1; char *ptr2; FILE *fp; fitsfile *infptr; static int maxhdr; if(!mHeader) { mHeader = malloc(MAXHDR); maxhdr = MAXHDR; } havePLTRAH = 0; haveSIMPLE = 0; haveBITPIX = 0; haveNAXIS = 0; haveNAXIS1 = 0; haveNAXIS2 = 0; haveCTYPE1 = 0; haveCTYPE2 = 0; haveCRPIX1 = 0; haveCRPIX2 = 0; haveCDELT1 = 0; haveCDELT2 = 0; haveCD1_1 = 0; haveCD1_2 = 0; haveCD2_1 = 0; haveCD2_2 = 0; haveCRVAL1 = 0; haveCRVAL2 = 0; haveBSCALE = 0; haveBZERO = 0; haveBLANK = 0; haveEPOCH = 0; haveEQUINOX = 0; /****************************************/ /* Initialize the WCS transform library */ /* and find the pixel location of the */ /* sky coordinate specified */ /****************************************/ errorCount = 0; if(hdrCheck_outfile) { fout = fopen(hdrCheck_outfile, "w+"); if(fout == (FILE *)NULL) { fprintf(fstatus, "[struct stat=\"ERROR\", msg=\"Cannot open output file %s.\"]\n", hdrCheck_outfile); fflush(fstatus); exit(1); } } strcpy(mHeader, ""); if(fits_open_file(&infptr, infile, READONLY, &status) == 0) { if(CHdebug) { printf("\nFITS file\n"); fflush(stdout); } if(hdrflag == HDR) { fprintf(fstatus, "[struct stat=\"ERROR\", msg=\"FITS file (%s) cannot be used as a header template\"]\n", infile); fflush(fstatus); exit(1); } if(hdu > 0) { if(fits_movabs_hdu(infptr, hdu+1, NULL, &status)) FITSerror(status); } if(fits_get_hdrspace (infptr, &ncard, &morekeys, &status)) FITSerror(status); if(ncard > 1000) mHeader = realloc(mHeader, ncard * 80 + 1024); if(CHdebug) { printf("ncard = %d\n", ncard); fflush(stdout); } for (i=1; i<=ncard; i++) { if(fits_read_keyn (infptr, i, fitskeyword, fitsvalue, fitscomment, &status)) FITSerror(status); if(fitsvalue[0] == '\'') { strcpy(tmpstr, fitsvalue+1); if(tmpstr[strlen(tmpstr)-1] == '\'') tmpstr[strlen(tmpstr)-1] = '\0'; } else strcpy(tmpstr, fitsvalue); fitsCheck(fitskeyword, tmpstr); sprintf(line, "%-8s= %20s", fitskeyword, fitsvalue); if(strncmp(line, "COMMENT", 7) != 0) strAdd(mHeader, line); } strAdd(mHeader, "END"); if(fits_close_file(infptr, &status)) FITSerror(status); } else { if(CHdebug) { printf("\nTemplate file\n"); fflush(stdout); } if(hdrflag == FITS) { fp = fopen(infile, "r"); if(fp == (FILE *)NULL) { fprintf(fstatus, "[struct stat=\"ERROR\", msg=\"File %s not found.\"]\n", infile); fflush(fstatus); exit(1); } fclose(fp); fprintf(fstatus, "[struct stat=\"ERROR\", msg=\"File (%s) is not a FITS image\"]\n", infile); fflush(fstatus); exit(1); } fp = fopen(infile, "r"); if(fp == (FILE *)NULL) { fprintf(fstatus, "[struct stat=\"ERROR\", msg=\"File %s not found.\"]\n", infile); fflush(fstatus); exit(1); } while(1) { if(fgets(line, 1024, fp) == (char *)NULL) break; if(line[(int)strlen(line)-1] == '\n') line[(int)strlen(line)-1] = '\0'; if(line[(int)strlen(line)-1] == '\r') line[(int)strlen(line)-1] = '\0'; strcpy(pline, line); if((int)strlen(line) > 80) { fprintf(fstatus, "[struct stat=\"ERROR\", msg=\"FITS header lines cannot be greater than 80 characters.\"]\n"); fflush(fstatus); exit(1); } len = (int)strlen(pline); keyword = pline; while(*keyword == ' ' && keyword < pline+len) ++keyword; end = keyword; while(*end != ' ' && *end != '=' && end < pline+len) ++end; value = end; while((*value == '=' || *value == ' ' || *value == '\'') && value < pline+len) ++value; *end = '\0'; end = value; if(*end == '\'') ++end; while(*end != ' ' && *end != '\'' && end < pline+len) ++end; *end = '\0'; fitsCheck(keyword, value); strAdd(mHeader, line); if((int)strlen(mHeader) + 160 > maxhdr) { maxhdr += MAXHDR; mHeader = realloc(mHeader, maxhdr); } } fclose(fp); } /********************************************************/ /* */ /* Check to see if we have the minimum FITS header info */ /* */ /********************************************************/ if(!haveBITPIX) errorOutput("No BITPIX keyword in FITS header"); if(!haveNAXIS) errorOutput("No NAXIS keyword in FITS header"); if(!haveNAXIS1) errorOutput("No NAXIS1 keyword in FITS header"); if(!haveNAXIS2) errorOutput("No NAXIS2 keyword in FITS header"); if(havePLTRAH) { /* If we have this parameter, we'll assume this is a DSS header */ /* the WCS checking routine should be able to verify if it isn't */ free(mHeader); maxhdr = 0; mHeader = (char *)NULL; return(0); } if(!haveCTYPE1) errorOutput("No CTYPE1 keyword in FITS header"); if(!haveCTYPE2) errorOutput("No CTYPE2 keyword in FITS header"); if(!haveCRPIX1) errorOutput("No CRPIX1 keyword in FITS header"); if(!haveCRPIX2) errorOutput("No CRPIX2 keyword in FITS header"); if(!haveCRVAL1) errorOutput("No CRVAL1 keyword in FITS header"); if(!haveCRVAL2) errorOutput("No CRVAL2 keyword in FITS header"); if(!haveCD1_1 && !haveCD1_2 && !haveCD2_1 && !haveCD2_2) { if(!haveCDELT1) errorOutput("No CDELT1 keyword (or incomplete CD matrix) in FITS header"); else if(!haveCDELT2) errorOutput("No CDELT2 keyword (or incomplete CD matrix) in FITS header"); } if(strlen(ctype1) < 8) errorOutput("CTYPE1 must be at least 8 characters"); if(strlen(ctype2) < 8) errorOutput("CTYPE2 must be at least 8 characters"); ptr1 = ctype1; while(*ptr1 != '-' && *ptr1 != '\0') ++ptr1; while(*ptr1 == '-' && *ptr1 != '\0') ++ptr1; ptr2 = ctype2; while(*ptr2 != '-' && *ptr2 != '\0') ++ptr2; while(*ptr2 == '-' && *ptr2 != '\0') ++ptr2; if(strlen(ptr1) == 0 || strlen(ptr2) == 0) errorOutput("Invalid CTYPE1 or CTYPE2 projection information"); if(strcmp(ptr1, ptr2) != 0) errorOutput("CTYPE1, CTYPE2 projection information mismatch"); if(hdrStringent) { if(strlen(ptr1) != 3) errorOutput("Invalid CTYPE1 projection information"); if(strlen(ptr2) != 3) errorOutput("Invalid CTYPE2 projection information"); } /****************************************/ /* Initialize the WCS transform library */ /* and find the pixel location of the */ /* sky coordinate specified */ /****************************************/ /* if(CHdebug) { printf("header = \n%s\n", mHeader); fflush(stdout); } */ hdrCheck_wcs = wcsinit(mHeader); checkWCS(hdrCheck_wcs, 0); if(errorCount > 0) { fprintf(fstatus, "[struct stat=\"ERROR\", msg=\"%d Errors\"]\n", errorCount); fflush(fstatus); exit(1); } return(0); }
std::vector<ImportDescriptor*> FitsImporter::getImportDescriptors(const std::string& fname) { std::string filename = fname; std::vector<std::vector<std::string> >& errors = mErrors[fname]; std::vector<std::vector<std::string> >& warnings = mWarnings[fname]; errors.clear(); warnings.clear(); int status=0; std::vector<ImportDescriptor*> descriptors; FitsFileResource pFile(filename); if (!pFile.isValid()) { errors.resize(1); errors[0].push_back(pFile.getStatus()); RETURN_DESCRIPTORS; } int hduCnt = 0; int specificHdu = 0; int hdu = 1; if (!splitFilename(filename, hduCnt, specificHdu, hdu, pFile, errors, warnings)) { RETURN_DESCRIPTORS; } errors.resize(hduCnt+1); warnings.resize(hduCnt+1); for(; hdu <= hduCnt; ++hdu) { std::string datasetName = filename + "[" + StringUtilities::toDisplayString(hdu) + "]"; int hduType; CHECK_FITS(fits_movabs_hdu(pFile, hdu, &hduType, &status), hdu, false, continue); ImportDescriptorResource pImportDescriptor(static_cast<ImportDescriptor*>(NULL)); FactoryResource<DynamicObject> pMetadata; VERIFYRV(pMetadata.get() != NULL, descriptors); { // scope std::vector<std::string> comments; char pCard[81]; char pValue[81]; char pComment[81]; int nkeys = 0; CHECK_FITS(fits_get_hdrspace(pFile, &nkeys, NULL, &status), hdu, true, ;); for(int keyidx = 1; keyidx <= nkeys; ++keyidx) { CHECK_FITS(fits_read_keyn(pFile, keyidx, pCard, pValue, pComment, &status), hdu, true, continue); std::string name = StringUtilities::stripWhitespace(std::string(pCard)); std::string val = StringUtilities::stripWhitespace(std::string(pValue)); std::string comment = StringUtilities::stripWhitespace(std::string(pComment)); if (!val.empty()) { pMetadata->setAttributeByPath("FITS/" + name, val); } else if (!comment.empty()) { comments.push_back(comment); } } if (!comments.empty()) { // ideally, this would add a multi-line string but Opticks doesn't display this properly // pMetadata->setAttributeByPath("FITS/COMMENT", StringUtilities::join(comments, "\n")); for(unsigned int idx = 0; idx < comments.size(); ++idx) { pMetadata->setAttributeByPath("FITS/COMMENT/" + StringUtilities::toDisplayString(idx), comments[idx]); } } } switch(hduType) { case IMAGE_HDU: { pImportDescriptor = ImportDescriptorResource(datasetName, TypeConverter::toString<RasterElement>()); VERIFYRV(pImportDescriptor.get() != NULL, descriptors); EncodingType fileEncoding; InterleaveFormatType interleave(BSQ); unsigned int rows=0; unsigned int cols=0; unsigned int bands=1; int bitpix; int naxis; long axes[3]; CHECK_FITS(fits_get_img_param(pFile, 3, &bitpix, &naxis, axes, &status), hdu, false, continue); switch(bitpix) { case BYTE_IMG: fileEncoding = INT1UBYTE; break; case SHORT_IMG: fileEncoding = INT2SBYTES; break; case LONG_IMG: fileEncoding = INT4SBYTES; break; case FLOAT_IMG: fileEncoding = FLT4BYTES; break; case DOUBLE_IMG: fileEncoding = FLT8BYTES; break; default: warnings[hdu].push_back("Unsupported BITPIX value " + StringUtilities::toDisplayString(bitpix) + "."); continue; } EncodingType dataEncoding = checkForOverflow(fileEncoding, pMetadata.get(), hdu, errors, warnings); if (naxis == 1) { // 1-D data is a signature pImportDescriptor = ImportDescriptorResource(datasetName, TypeConverter::toString<Signature>()); pMetadata->setAttributeByPath(METADATA_SIG_ENCODING, dataEncoding); pMetadata->setAttributeByPath(METADATA_SIG_LENGTH, axes[0]); RasterUtilities::generateAndSetFileDescriptor(pImportDescriptor->getDataDescriptor(), filename, StringUtilities::toDisplayString(hdu), BIG_ENDIAN_ORDER); // add units SignatureDataDescriptor* pSigDd = dynamic_cast<SignatureDataDescriptor*>(pImportDescriptor->getDataDescriptor()); if (pSigDd != NULL) { FactoryResource<Units> pUnits; pUnits->setUnitName("Custom"); pUnits->setUnitType(CUSTOM_UNIT); pSigDd->setUnits("Reflectance", pUnits.get()); } break; // leave switch() } else if (naxis == 2) { cols = axes[0]; rows = axes[1]; } else if (naxis == 3) { cols = axes[0]; rows = axes[1]; bands = axes[2]; } else { errors[hdu].push_back(StringUtilities::toDisplayString(naxis) + " axis data not supported."); } RasterDataDescriptor* pDataDesc = RasterUtilities::generateRasterDataDescriptor( datasetName, NULL, rows, cols, bands, interleave, dataEncoding, IN_MEMORY); pImportDescriptor->setDataDescriptor(pDataDesc); if (specificHdu == 0 && hdu == 1 && naxis == 2 && (axes[0] <= 5 || axes[1] <= 5)) { // use 5 as this is a good top end for the number of astronomical band pass filters // in general usage. this is not in a spec anywhere and is derived from various sample // FITS files for different astronomical instruments. // // There's a good chance this is really a spectrum. (0th HDU) // We'll create an import descriptor for the spectrum version of this // And disable the raster descriptor by default pImportDescriptor->setImported(false); ImportDescriptorResource pSigDesc(datasetName, TypeConverter::toString<SignatureLibrary>()); DynamicObject* pSigMetadata = pSigDesc->getDataDescriptor()->getMetadata(); pSigMetadata->merge(pMetadata.get()); std::vector<double> centerWavelengths; unsigned int cnt = (axes[0] <= 5) ? axes[1] : axes[0]; double startVal = StringUtilities::fromDisplayString<double>( dv_cast<std::string>(pMetadata->getAttributeByPath("FITS/MINWAVE"), "0.0")); double endVal = StringUtilities::fromDisplayString<double>( dv_cast<std::string>(pMetadata->getAttributeByPath("FITS/MAXWAVE"), "0.0")); double incr = (endVal == 0.0) ? 1.0 : ((endVal - startVal) / static_cast<double>(cnt)); centerWavelengths.reserve(cnt); for (unsigned int idx = 0; idx < cnt; idx++) { centerWavelengths.push_back(startVal + (idx * incr)); } pSigMetadata->setAttributeByPath(CENTER_WAVELENGTHS_METADATA_PATH, centerWavelengths); // Units std::string unitsName = dv_cast<std::string>(pMetadata->getAttributeByPath("FITS/BUNIT"), std::string()); if (!unitsName.empty()) { FactoryResource<Units> units; units->setUnitName(unitsName); units->setUnitType(RADIANCE); SignatureDataDescriptor* pSigDd = dynamic_cast<SignatureDataDescriptor*>(pSigDesc->getDataDescriptor()); if (pSigDd != NULL) { pSigDd->setUnits("Reflectance", units.get()); } } RasterUtilities::generateAndSetFileDescriptor(pSigDesc->getDataDescriptor(), filename, StringUtilities::toDisplayString(hdu), BIG_ENDIAN_ORDER); // If units are not available, set custom units into the data descriptor so that the user can // modify them - this must occur after the call to RasterUtilities::generateAndSetFileDescriptor() // so that the file descriptor will still display no defined units if (unitsName.empty()) { FactoryResource<Units> units; units->setUnitName("Custom"); units->setUnitType(CUSTOM_UNIT); SignatureDataDescriptor* pSigDd = dynamic_cast<SignatureDataDescriptor*>(pSigDesc->getDataDescriptor()); if (pSigDd != NULL) { pSigDd->setUnits("Reflectance", units.get()); } } descriptors.push_back(pSigDesc.release()); } RasterFileDescriptor* pFileDescriptor = dynamic_cast<RasterFileDescriptor*>( RasterUtilities::generateAndSetFileDescriptor(pDataDesc, filename, StringUtilities::toDisplayString(hdu), BIG_ENDIAN_ORDER)); if (pFileDescriptor != NULL) { unsigned int bitsPerElement = RasterUtilities::bytesInEncoding(fileEncoding) * 8; pFileDescriptor->setBitsPerElement(bitsPerElement); } break; // leave switch() } case ASCII_TBL: case BINARY_TBL: warnings[hdu].push_back("Tables not supported. [HDU " + StringUtilities::toDisplayString(hdu) + "]"); continue; default: warnings[hdu].push_back("HDU " + StringUtilities::toDisplayString(hdu) + " is an unknown type."); continue; } pImportDescriptor->getDataDescriptor()->setMetadata(pMetadata.release()); pImportDescriptor->setImported(errors[hdu].empty()); descriptors.push_back(pImportDescriptor.release()); }
int main(int argc, char *argv[]) { fitsfile *fptr; /* FITS file pointer, defined in fitsio.h */ char card[FLEN_CARD]; /* Standard string lengths defined in fitsio.h */ int status = 0; /* CFITSIO status value MUST be initialized to zero! */ int single = 0, hdupos = 0, nkeys = 0, ii = 0; int printhelp = (argc == 2 && (strcmp(argv[1], "-h") == 0 || strcmp(argv[1], "--help") == 0)); if (printhelp || argc != 2) { fprintf(stderr, "Usage: %s filename[ext] \n", argv[0]); fprintf(stderr, "\n"); fprintf(stderr, "List the FITS header keywords in a single extension, or, if \n"); fprintf(stderr, "ext is not given, list the keywords in all the extensions. \n"); fprintf(stderr, "\n"); fprintf(stderr, "Examples: \n"); fprintf(stderr, " %s file.fits - list every header in the file \n", argv[0]); fprintf(stderr, " %s file.fits[0] - list primary array header \n", argv[0]); fprintf(stderr, " %s file.fits[2] - list header of 2nd extension \n", argv[0]); fprintf(stderr, " %s file.fits+2 - same as above \n", argv[0]); fprintf(stderr, " %s file.fits[GTI] - list header of GTI extension\n", argv[0]); fprintf(stderr, "\n"); fprintf(stderr, "Note that it may be necessary to enclose the input file\n"); fprintf(stderr, "name in single quote characters on the Unix command line.\n"); return (0); } #if defined(PAGER) && defined(HAVE_POPEN) && defined(HAVE_PCLOSE) FILE *fout = popen(PAGER, "w"); if (fout == NULL) { fprintf(stderr, "Could not execute '%s'\n", PAGER); return (1); } #else FILE *fout = stdout; #endif if (!fits_open_file(&fptr, argv[1], READONLY, &status)) { fits_get_hdu_num(fptr, &hdupos); /* Get the current HDU position */ /* List only a single header if a specific extension was given */ if (hdupos != 1 || strchr(argv[1], '[')) { single = 1; } for (; !status; hdupos++) { /* Main loop through each extension */ fits_get_hdrspace(fptr, &nkeys, NULL, &status); /* get # of keywords */ fprintf(fout, "Header listing for HDU #%d:\n", hdupos); for (ii = 1; ii <= nkeys; ii++) { /* Read and print each keywords */ if (fits_read_record(fptr, ii, card, &status)) { break; } fprintf(fout, "%s\n", card); } fprintf(fout, "END\n\n"); /* terminate listing with END */ if (single) { break; /* quit if only listing a single header */ } fits_movrel_hdu(fptr, 1, NULL, &status); /* try to move to next HDU */ } if (status == END_OF_FILE) { status = 0; /* Reset after normal error */ } fits_close_file(fptr, &status); } #if defined(PAGER) && defined(HAVE_POPEN) && defined(HAVE_PCLOSE) pclose(fout); #endif if (status) { fits_report_error(stderr, status); /* print any error message */ } return (status); }
/* copy image section from input to putput, with binning */ int copyImageSection(fitsfile *ifptr, fitsfile *ofptr, int *dims, double *cens, int bin, char *slice, int *status) { void *buf; char card[FLEN_CARD]; char tbuf[SZ_LINE]; int numkeys, nkey, bitpix, dtype; int start[2]; int end[2]; int naxis = 2; long nelements; long naxes[2]; long fpixel[2] = {1,1}; buf = getImageToArray(ifptr, dims, cens, bin, slice, start, end, &bitpix, status); if( !buf || *status ){ fits_get_errstatus(*status, tbuf); fprintf(stderr, "ERROR: could not create section for output image: %s\n", tbuf); return *status; } /* get image size and total number of elements */ naxes[0] = (int)((end[0] - start[0] + 1) / bin); naxes[1] = (int)((end[1] - start[1] + 1) / bin); nelements = naxes[0] * naxes[1]; /* convert bitpix to cfitio data type */ switch(bitpix){ case 8: dtype = TBYTE; break; case 16: dtype = TSHORT; break; case -16: dtype = TUSHORT; break; case 32: dtype = TINT; break; case 64: dtype = TLONGLONG; break; case -32: dtype = TFLOAT; break; case -64: dtype = TDOUBLE; break; default: fprintf(stderr, "ERROR: unknown data type for image section\n"); return -1; } /* this code is modeled after cfitsio/cfileio.c/fits_copy_image_section() */ fits_create_img(ofptr, bitpix, naxis, naxes, status); /* copy all other non-structural keywords from the input to output file */ fits_get_hdrspace(ifptr, &numkeys, NULL, status); for(nkey=4; nkey<=numkeys; nkey++) { fits_read_record(ifptr, nkey, card, status); if (fits_get_keyclass(card) > TYP_CMPRS_KEY){ /* write the record to the output file */ fits_write_record(ofptr, card, status); } } if( *status > 0 ){ fprintf(stderr, "ERROR: can't copy header from input image to output section"); return(*status); } /* write image to FITS file */ fits_write_pix(ofptr, dtype, fpixel, nelements, buf, status); /* update LTM/TLV values in header */ updateLTM(ifptr, ofptr, (int)((end[0] + start[0]) / 2), (int)((end[1] + start[1]) / 2), (int)(end[0] - start[0] + 1), (int)(end[1] - start[1] + 1), bin, 1); /* free up space */ if( buf ){ free(buf); } /* return status */ return *status; }
int main(int argc, char **argv) { int c, i, j, got, args, jsonlen, istart; int odim1, odim2, blen, pad; int idim1=0, idim2=0, bitpix=0, ncard=0; int verbose=0; size_t totbytes, dlen; char tbuf[SZ_LINE]; char *buf=NULL; char *jsonheader=NULL; char *iname=NULL, *oname=NULL; FILE *ofp=NULL; Optinfo optinfo; #if HAVE_CFITSIO int status = 0; int n; int hdutype; int maxcard, morekeys; int dims[2] = {0, 0}; int block = 1; void *dbuf; double d1, d2, d3, d4; double cens[2] = {0.0, 0.0}; char *s; char *filter=NULL; char *evtlist = DEF_EVTLIST; char card[81]; char s1[BUFLEN], s2[BUFLEN], s3[BUFLEN], s4[BUFLEN]; fitsfile *fptr=NULL, *ofptr=NULL; #elif HAVE_FUNTOOLS char *s=NULL; int dtype; Fun ifun=NULL, tfun=NULL; #endif /* we want the args in the same order in which they arrived, and gnu getopt sometimes changes things without this */ putenv("POSIXLY_CORRECT=true"); /* process switch arguments */ while ((c = getopt(argc, argv, "b:e:f:s:v")) != -1){ switch(c){ case 'b': #if HAVE_CFITSIO block = atoi(optarg); #else fprintf(stderr, "warning: -b switch only for cfitsio (ignoring)\n"); #endif break; case 'e': #if HAVE_CFITSIO evtlist = optarg; #else fprintf(stderr, "warning: -e switch only for cfitsio (ignoring)\n"); #endif break; case 'f': #if HAVE_CFITSIO filter = optarg; #else fprintf(stderr, "warning: -f switch only for cfitsio (ignoring)\n"); #endif break; case 's': #if HAVE_CFITSIO s = strdup(optarg); if( strlen(s) > BUFLEN ) s[BUFLEN-1] = '\0'; if( sscanf(s, "%[0-9.*] @ %[-0-9.*] , %[0-9.*] @ %[-0-9.*]%n", s1, s2, s3, s4, &n) == 4){ dims[0] = atof(s1); cens[0] = atof(s2); dims[1] = atof(s3); cens[1] = atof(s4); } else if(sscanf(s, "%[-0-9.*] : %[-0-9.*] , %[-0-9.*] : %[-0-9.*]%n", s1, s2, s3, s4, &n) == 4){ d1 = atof(s1); d2 = atof(s2); d3 = atof(s3); d4 = atof(s4); dims[0] = d2 - d1 + 1; cens[0] = dims[0] / 2; dims[1] = d4 - d3 + 1; cens[1] = dims[1] / 2; } else { fprintf(stderr, "warning: unknown arg for -s switch (ignoring)\n"); } if( s ) free(s); #else fprintf(stderr, "warning: -s switch only for cfitsio (ignoring)\n"); #endif break; case 'v': verbose++; break; } } /* check for required arguments */ args = argc - optind; if( args < 2 ){ fprintf(stderr, "usage: %s iname oname\n", argv[0]); exit(1); } iname = argv[optind++]; oname = argv[optind++]; /* optional info */ if( !(optinfo = (Optinfo)calloc(sizeof(OptinfoRec), 1)) ){ fprintf(stderr, "ERROR: can't allocate optional info rec\n"); exit(1); } /* open the input FITS file */ #if HAVE_CFITSIO fptr = openFITSFile(iname, evtlist, &hdutype, &status); errchk(status); #elif HAVE_FUNTOOLS if( !(ifun = FunOpen(iname, "r", NULL)) ){ fprintf(stderr, "ERROR could not open input FITS file: %s (%s)\n", iname, strerror(errno)); exit(1); } #endif /* save the input filename in the png file */ optinfo->fitsname = iname; /* open the output PGN file */ if( !strcmp(oname, "-") || !strcmp(oname, "stdout") ){ ofp = stdout; } else if( !(ofp = fopen(oname, "w")) ){ fprintf(stderr, "ERROR: could not create output PNG file: %s (%s)\n", oname, strerror(errno)); exit(1); } #if HAVE_CFITSIO switch(hdutype){ case IMAGE_HDU: // get image array dbuf = getImageToArray(fptr, NULL, NULL, &idim1, &idim2, &bitpix, &status); errchk(status); fits_get_hdrspace(fptr, &maxcard, &morekeys, &status); errchk(status); ofptr = fptr; break; default: ofptr = filterTableToImage(fptr, filter, NULL, dims, cens, block, &status); errchk(status); // get image array dbuf = getImageToArray(ofptr, NULL, NULL, &idim1, &idim2, &bitpix, &status); errchk(status); // get number of keys fits_get_hdrspace(ofptr, &maxcard, &morekeys, &status); errchk(status); break; } #elif HAVE_FUNTOOLS /* copy the input fits header into a FITS image header */ if( !(tfun = (Fun)calloc(1, sizeof(FunRec))) ){ fprintf(stderr, "ERROR: could not create tfun struct\n"); exit(1); } _FunCopy2ImageHeader(ifun, tfun); /* and save for storage in the png file */ optinfo->fitsheader = (char *)tfun->header->cards; /* get image parameters. its safe to do this before calling image get so long as we don't change bitpix before that call */ FunInfoGet(ifun, FUN_SECT_BITPIX, &bitpix, FUN_SECT_DIM1, &idim1, FUN_SECT_DIM2, &idim2, 0); #endif /* convert FITS header into a json string */ snprintf(tbuf, SZ_LINE-1, "{\"js9Protocol\": %s, ", JS9_PROTOCOL); scat(tbuf, &jsonheader); snprintf(tbuf, SZ_LINE-1, "\"js9Endian\": \"%s\", ", JS9_ENDIAN); scat(tbuf, &jsonheader); snprintf(tbuf, SZ_LINE-1, "\"cardstr\": \""); scat(tbuf, &jsonheader); // concat header cards into a single string #if HAVE_CFITSIO while( ++ncard <= maxcard ){ fits_read_record(ofptr, ncard, card, &status); errchk(status); // change " to ' for(i=0; i<80; i++){ if( card[i] == '"' ){ card[i] = '\''; } } snprintf(tbuf, SZ_LINE-1, "%-80s", card); scat(tbuf, &jsonheader); } #elif HAVE_FUNTOOLS while( (s = FunParamGets(tfun, NULL, ++ncard, NULL, &dtype)) ){ for(i=0; i<80; i++){ if( s[i] == '"' ){ s[i] = '\''; } } scat(s, &jsonheader); if( s ) free(s); } #endif // end with the number of cards snprintf(tbuf, SZ_LINE-1, "\", \"ncard\": %d}", ncard); scat(tbuf, &jsonheader); /* we want the image buffer to start on an 8-byte boundary, so make jsonheader + null byte end on one */ pad = 8 - (strlen(jsonheader) % 8) - 1; for(i=0; i<pad; i++){ strcat(jsonheader, " "); } /* get final length of json header */ jsonlen = strlen(jsonheader); /* total length of the header + null + image we are storing */ blen = ABS(bitpix/8); dlen = (size_t)idim1 * (size_t)idim2 * blen; totbytes = jsonlen + 1 + dlen; /* all of this should now fit into the png image */ /* somewhat arbitrarily, we use idim1 for odim1, and adjust odim2 to fit */ odim1 = idim1; odim2 = (int)(((totbytes + odim1 - 1) / odim1) + (COLOR_CHANNELS-1)) / COLOR_CHANNELS; /* allocate buf to hold json header + null byte + RGB image */ if( !(buf=calloc(COLOR_CHANNELS, odim1 * odim2)) ){ fprintf(stderr, "ERROR: can't allocate image buf\n"); exit(1); } /* move the json header into the output buffer */ memmove(buf, jsonheader, jsonlen); /* add a null byte to signify end of json header */ buf[jsonlen] = '\0'; /* offset into image buffer where image starts, past header and null byte */ istart = jsonlen + 1; /* debug output */ if( verbose ){ fprintf(stderr, "idim=%d,%d (bitpix=%d jsonlen=%d istart=%d endian=%s) [%ld] -> odim=%d,%d [%d]\n", idim1, idim2, bitpix, jsonlen, istart, JS9_ENDIAN, totbytes, odim1, odim2, odim1 * odim2 * COLOR_CHANNELS); } #if HAVE_CFITSIO /* move the json header into the output buffer */ memmove(&buf[istart], dbuf, dlen); #elif HAVE_FUNTOOLS /* extract and bin the data section into an image buffer */ if( !FunImageGet(ifun, &buf[istart], NULL) ){ fprintf(stderr, "ERROR: could not FunImageGet: %s\n", iname); exit(1); } #endif /* debugging output to check against javascript input */ if( verbose > 1 ){ fprintf(stderr, "jsonheader: %s\n", jsonheader); for(j=0; j<idim2; j++){ fprintf(stderr, "data #%d: ", j); for(i=0; i<idim1; i++){ switch(bitpix){ case 8: fprintf(stderr, "%d ", *(unsigned char *)(buf + istart + ((j * idim1) + i) * blen)); break; case 16: fprintf(stderr, "%d ", *(short *)(buf + istart + ((j * idim1) + i) * blen)); break; case -16: fprintf(stderr, "%d ", *(unsigned short *)(buf + istart + ((j * idim1) + i) * blen)); break; case 32: fprintf(stderr, "%d ", *(int *)(buf + istart + ((j * idim1) + i) * blen)); break; case -32: fprintf(stderr, "%.3f ", *(float *)(buf + istart + ((j * idim1) + i) * blen)); break; case -64: fprintf(stderr, "%.3f ", *(double *)(buf + istart + ((j * idim1) + i) * blen)); break; } } fprintf(stderr, "\n"); } fprintf(stderr, "\n"); } /* might have to swap to preferred endian for png creation */ if( (!strncmp(JS9_ENDIAN, "l", 1) && is_bigendian()) || (!strncmp(JS9_ENDIAN, "b", 1) && !is_bigendian()) ){ swap_data(&buf[istart], idim1 * idim2, bitpix/8); } /* write the PNG file */ got = writePNG(ofp, buf, odim1, odim2, optinfo); /* free up space */ if( buf ) free(buf); if( optinfo ) free(optinfo); if( jsonheader ) free(jsonheader); /* close files */ #if HAVE_CFITSIO status = 0; if( ofptr && (ofptr != fptr) ) closeFITSFile(ofptr, &status); if( fptr ) closeFITSFile(fptr, &status); if( dbuf ) free(dbuf); #elif HAVE_FUNTOOLS if( ifun ) FunClose(ifun); if( tfun ){ FunClose(tfun); free(tfun); } #endif if( ofp) fclose(ofp); /* return the news */ return got; }
static int vips_fits_get_header( VipsFits *fits, VipsImage *out ) { int status; int bitpix; int width, height, bands, format, type; int keysexist; int i; status = 0; if( fits_get_img_paramll( fits->fptr, 10, &bitpix, &fits->naxis, fits->naxes, &status ) ) { vips_fits_error( status ); return( -1 ); } #ifdef VIPS_DEBUG VIPS_DEBUG_MSG( "naxis = %d\n", fits->naxis ); for( i = 0; i < fits->naxis; i++ ) VIPS_DEBUG_MSG( "%d) %lld\n", i, fits->naxes[i] ); #endif /*VIPS_DEBUG*/ height = 1; bands = 1; switch( fits->naxis ) { /* If you add more dimensions here, adjust data read below. See also * the definition of MAX_DIMENSIONS above. */ case 10: case 9: case 8: case 7: case 6: case 5: case 4: for( i = fits->naxis; i > 3; i-- ) if( fits->naxes[i - 1] != 1 ) { vips_error( "fits", "%s", _( "dimensions above 3 " "must be size 1" ) ); return( -1 ); } case 3: bands = fits->naxes[2]; case 2: height = fits->naxes[1]; case 1: width = fits->naxes[0]; break; default: vips_error( "fits", _( "bad number of axis %d" ), fits->naxis ); return( -1 ); } /* Are we in one-band mode? */ if( fits->band_select != -1 ) bands = 1; /* Get image format. We want the 'raw' format of the image, our caller * can convert using the meta info if they want. */ for( i = 0; i < VIPS_NUMBER( fits2vips_formats ); i++ ) if( fits2vips_formats[i][0] == bitpix ) break; if( i == VIPS_NUMBER( fits2vips_formats ) ) { vips_error( "fits", _( "unsupported bitpix %d\n" ), bitpix ); return( -1 ); } format = fits2vips_formats[i][1]; fits->datatype = fits2vips_formats[i][2]; if( bands == 1 ) { if( format == VIPS_FORMAT_USHORT ) type = VIPS_INTERPRETATION_GREY16; else type = VIPS_INTERPRETATION_B_W; } else if( bands == 3 ) { if( format == VIPS_FORMAT_USHORT ) type = VIPS_INTERPRETATION_RGB16; else type = VIPS_INTERPRETATION_RGB; } else type = VIPS_INTERPRETATION_MULTIBAND; vips_image_pipelinev( out, VIPS_DEMAND_STYLE_SMALLTILE, NULL ); vips_image_init_fields( out, width, height, bands, format, VIPS_CODING_NONE, type, 1.0, 1.0 ); /* Read all keys into meta. */ if( fits_get_hdrspace( fits->fptr, &keysexist, NULL, &status ) ) { vips_fits_error( status ); return( -1 ); } for( i = 0; i < keysexist; i++ ) { char record[81]; char vipsname[100]; if( fits_read_record( fits->fptr, i + 1, record, &status ) ) { vips_fits_error( status ); return( -1 ); } VIPS_DEBUG_MSG( "fits2vips: setting meta on vips image:\n" ); VIPS_DEBUG_MSG( " record == \"%s\"\n", record ); /* FITS lets keys repeat. For example, HISTORY appears many * times, each time with a fresh line of history attached. We * have to include the key index in the vips name we assign. */ vips_snprintf( vipsname, 100, "fits-%d", i ); vips_image_set_string( out, vipsname, record ); } return( 0 ); }
int read_kpvt( char *input_file_name, char *aux_file, int verbose_flag, int minmax_flag) { int status = 0; /* * If the Compiler macro FITS is not defined, that means the makefile * determined that libcfitsio.a was not available. Instead of shutting down * the entire converter Lets just disable any read routines thatt depend on * the FITS library * */ #ifdef FITS extern int linear_minmax_search(float *, int, float *, float *); fitsfile *fits_filePtr; char header_buffer[FLEN_CARD ]; float operand1; int i, j; int number_of_fits_header_keys; int number_of_fits_hdus; int hdu_type; int bit_pix; long naxes[10]; int maxdim = 10; long fpixel[10]; float missing_val = 256*256*256; int anynul; float net_flux_2d_static[180][360]; float net_flux_2d_static_flat[64800]; float total_flux_2d_static[180][360]; float total_flux_2d_static_flat[64800]; float weights_2d_static[180][360]; float weights_2d_static_flat[64800]; /** open fits file **/ fits_open_file( &fits_filePtr, input_file_name, READONLY, &status); /** get number_of_fits_header_keys **/ fits_get_hdrspace(fits_filePtr, &number_of_fits_header_keys, NULL, &status); /** get the number of hdu's in the current file **/ fits_get_num_hdus(fits_filePtr, &number_of_fits_hdus, &status); printf("FITS File: %s has %d hdu's\n", input_file_name, number_of_fits_hdus); /** for every hdu **/ for (i=0; i<number_of_fits_hdus; i++) { /** select hdu by number **/ fits_movabs_hdu(fits_filePtr, number_of_fits_hdus, &hdu_type, &status); /** there are three type of hdu's * IMAGE_HDU * ACSII_TBL * BINARY_TBL * ********************************/ if (hdu_type == IMAGE_HDU) { printf("Current HDU Type is IMAGE\n"); /*** get general info about the current image file ***/ fits_get_img_param( fits_filePtr, maxdim, &bit_pix, &naxis, naxes, &status); printf("bitpix = %d\nnaxis = %d\n", bit_pix, naxis); if (DEBUG_FLAG) { for (i = 0; i<naxis; i++) printf("naxis[%d] = %ld\n", i, naxes[i]); } naxis1 = naxes[0]; naxis2 = naxes[1]; number_of_elements = naxis1 * naxis2; /** dynamically allocate space for the image grid **/ carrington_longitiude = malloc(naxis1 * sizeof(float)); carrington_sine_latitude = malloc(naxis2 * sizeof(float)); /** dynamically allocate space for the flat variable arrays **/ net_flux = malloc(number_of_elements * sizeof(float)); total_flux = malloc(number_of_elements * sizeof(float)); weights = malloc(number_of_elements * sizeof(float)); /** manually insert sequential grid values from 1 - naxes[*] **/ operand1 = 2.0 / naxis2; if (DEBUG_FLAG) { printf( "\n\n\n\n\n\nWTF: operand1 = %f\nnaxis2 = %d\n", operand1, naxis2); } for (i=0; i < naxis2; i++) { /** convert to sine latidude **/ /* carrington_sine_latitude[i] = i+1; */ carrington_sine_latitude[i] = (-1.0) + (operand1 * ( (i + 1 ) - .5 ) ); if (DEBUG_FLAG) printf("%d deg = %f\n", i+1, carrington_sine_latitude[i]); } for (i=0; i < naxis1; i++) { carrington_longitiude[i] = i+1; if (DEBUG_FLAG) printf("%d deg = %f deg\n", i+1, carrington_longitiude[i]); } /** print position values **/ for (i=0; i<naxis2; i+=30) { for (j=0; j<naxis1; j+=30) { if (DEBUG_FLAG) { printf( "position[%f][%f]\n", carrington_sine_latitude[i], carrington_longitiude[j]); } } } /** print c_lon values **/ for (i=0; i<naxis1; i++) { if( DEBUG_FLAG ) printf("c_lon[%d] = %f ", i, carrington_longitiude[i]); } /** print c_sine_lat values **/ for (i=0; i<naxis2; i++) { if( DEBUG_FLAG ) printf("c_sine_lat[%d] = %f ", i, carrington_sine_latitude[i]); } /** dynamically allocate memory for the three image slices that we * expect - we must reverse the majority since the fits api expects * array[column][row] **/ net_flux_2d = malloc(naxis1 * sizeof(float *)); for (i=0; i< naxis1; i++) { net_flux_2d[i] = malloc(naxis2 * sizeof(float)); } total_flux_2d = malloc(naxis2 * sizeof(float *)); for (i=0; i< naxis2; i++) { total_flux_2d[i] = malloc(naxis1 * sizeof(float)); } weights_2d = malloc(naxis2 * sizeof(float *)); for (i=0; i< naxis2; i++) { weights_2d[i] = malloc(naxis1 * sizeof(float)); } /*** read in the image data ***/ /** this is the starting point for the read - slice one - net flux **/ fpixel[0] = fpixel[1] = fpixel[2]= 1; if( DEBUG_FLAG ) printf( "\nfpixel[0] = %ld\nfpixel[1] = %ld\nfpixel[2] = %ld\nnumber_of_elements = %ld\n\n", fpixel[0], fpixel[1], fpixel[2], number_of_elements); /* fits_read_pix( fits_filePtr, TFLOAT, fpixel, number_of_elements, &missing_val, *net_flux_2d, &anynul, &status ); */ fits_read_pix( fits_filePtr, TFLOAT, fpixel, number_of_elements, &missing_val, net_flux_2d_static, &anynul, &status); /** this is the starting point for the read - slice two - total flux */ fpixel[2] = 2; if( DEBUG_FLAG ) printf( "fpixel[0] = %ld\nfpixel[1] = %ld\nfpixel[2] = %ld\nnumber_of_elements = %ld\n\n", fpixel[0], fpixel[1], fpixel[2], number_of_elements); /* * fits_read_pix( fits_filePtr, TFLOAT, fpixel, number_of_elements, * &missing_val, *total_flux_2d, &anynul, &status ); * */ fits_read_pix( fits_filePtr, TFLOAT, fpixel, number_of_elements, &missing_val, total_flux_2d_static, &anynul, &status); /** this is the starting point for the read - slice three - weights **/ fpixel[2] = 3; if( DEBUG_FLAG )printf( "fpixel[0] = %ld\nfpixel[1] = %ld\nfpixel[2] = %ld\nnumber_of_elements = %ld\n\n", fpixel[0], fpixel[1], fpixel[2], number_of_elements); /* * fits_read_pix( fits_filePtr, TFLOAT, fpixel, number_of_elements, * &missing_val, *weights_2d, &anynul, &status ); * */ fits_read_pix( fits_filePtr, TFLOAT, fpixel, number_of_elements, &missing_val, weights_2d_static, &anynul, &status); /** flatten out arrays **/ for (i=0; i<naxis2; i++) { for (j=0; j<naxis1; j++) { /* net_flux[ i * naxis1 + j] = net_flux_2d_static[i][j]; total_flux[ i * naxis1 + j] = total_flux_2d[i][j]; weights[ i * naxis1 + j] = weights_2d[i][j]; */ net_flux[ i * naxis1 + j] = net_flux_2d_static[i][j]; total_flux[ i * naxis1 + j] = total_flux_2d_static[i][j]; weights[ i * naxis1 + j] = weights_2d_static[i][j]; } } /*** DEBUG PRINT OUT OF VALUES ***/ /* for( i=0;i<naxis2;i+=20) { for( j=0;j<naxis1;j+=20) { printf( "net_flux[%d][%d] = %f\n", i,j, net_flux[i * naxis1 + j] ); printf( "net_flux_2d[%d][%d] = %f\n", i,j, net_flux_2d[i][j] ); printf( "net_flux_2d_static[%d][%d] = %f\n", i,j, net_flux_2d_static[i][j] ); printf( "net_flux_2d_static_flat[%d][%d] = %f\n", i,j, net_flux_2d_static_flat[i * naxis1 + j] ); printf( "total_flux[%d][%d] = %f\n", i,j, total_flux[i * naxis1 + j] ); printf( "total_flux_2d[%d][%d] = %f\n", i,j, total_flux_2d[i][j] ); printf( "weights[%d][%d] = %f\n", i,j, weights[i * naxis1 + j] ); printf( "weights_2d[%d][%d] = %f\n\n", i,j, weights_2d[i][j] ); } } */ } else if (hdu_type == ASCII_TBL) { printf("Current HDU Type is ACSII TABLE\n"); } else if (hdu_type == BINARY_TBL) { printf("Current HDU Type is BINARY TABLE\n"); } /*** get the header info for the current hdu ***/ for (i = 0; i < number_of_fits_header_keys; i++) { fits_read_record(fits_filePtr, i, header_buffer, &status); printf("%s\n", header_buffer); } } /** close fits file **/ fits_close_file(fits_filePtr, &status); if (status) { fits_report_error( stderr, status); } /* * calcluate actual min/max values for each ariable unless -nominmax flag was * specified * */ /** add more error handling for each linear_minmax_search function call **/ /*** if -nominmax option was NOT specified ***/ if ( !minmax_flag) { if (verbose_flag) { printf("\ncalculating actual minimum & maximum values for each variable ...\n"); } if (verbose_flag) { printf("%-25s%-25s%-25s\n", "", "min", "max"); } linear_minmax_search( carrington_longitiude, naxis1, &carrington_longitiude_actual_min, &carrington_longitiude_actual_max); if (verbose_flag) { printf( "%-25s%-25g%-25g\n", "c_lon", carrington_longitiude_actual_min, carrington_longitiude_actual_max); } linear_minmax_search( carrington_sine_latitude, naxis2, &carrington_sine_latitude_actual_min, &carrington_sine_latitude_actual_max); if (verbose_flag) { printf( "%-25s%-25g%-25g\n", "c_sine_lat", carrington_sine_latitude_actual_min, carrington_sine_latitude_actual_max); } linear_minmax_search( net_flux, number_of_elements, &net_flux_actual_min, &net_flux_actual_max); if (verbose_flag) { printf( "%-25s%-25g%-25g\n", "net_flux", net_flux_actual_min, net_flux_actual_max); } linear_minmax_search( total_flux, number_of_elements, &total_flux_actual_min, &total_flux_actual_max); if (verbose_flag) { printf( "%-25s%-25g%-25g\n", "total_flux", total_flux_actual_min, total_flux_actual_max); } linear_minmax_search( weights, number_of_elements, &weights_actual_min, &weights_actual_max); if (verbose_flag) { printf( "%-25s%-25g%-25g\n", "weights", weights_actual_min, weights_actual_max); } } #endif #ifndef FITS printf("\n\n!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n"); printf("!! WARNING: from %s line [%d]. Conversion Software was not compiled and linked with netCDF libraries ( libcfitsio.a ). No .fts FITS files will be ingested... \n", __FILE__, __LINE__ ); return EXIT_FAILURE; #endif return status; }
int fits_execute_template(fitsfile *ff, char *ngp_template, int *status) { int r, exit_flg, first_extension, i, my_hn, tmp0, keys_exist, more_keys, used_ver; char grnm[NGP_MAX_STRING], used_name[NGP_MAX_STRING]; long luv; if (NULL == status) return(NGP_NUL_PTR); if (NGP_OK != *status) return(*status); if ((NULL == ff) || (NULL == ngp_template)) { *status = NGP_NUL_PTR; return(*status); } ngp_inclevel = 0; /* initialize things, not all should be zero */ ngp_grplevel = 0; master_grp_idx = 1; exit_flg = 0; ngp_master_dir[0] = 0; /* this should be before 1st call to ngp_include_file */ first_extension = 1; /* we need to create PHDU */ if (NGP_OK != (r = ngp_delete_extver_tab())) { *status = r; return(r); } fits_get_hdu_num(ff, &my_hn); /* our HDU position */ if (my_hn <= 1) /* check whether we really need to create PHDU */ { fits_movabs_hdu(ff, 1, &tmp0, status); fits_get_hdrspace(ff, &keys_exist, &more_keys, status); fits_movabs_hdu(ff, my_hn, &tmp0, status); if (NGP_OK != *status) return(*status); /* error here means file is corrupted */ if (keys_exist > 0) first_extension = 0; /* if keywords exist assume PHDU already exist */ } else { first_extension = 0; /* PHDU (followed by 1+ extensions) exist */ for (i = 2; i<= my_hn; i++) { *status = NGP_OK; fits_movabs_hdu(ff, 1, &tmp0, status); if (NGP_OK != *status) break; fits_read_key(ff, TSTRING, "EXTNAME", used_name, NULL, status); if (NGP_OK != *status) continue; fits_read_key(ff, TLONG, "EXTVER", &luv, NULL, status); used_ver = luv; /* bugfix - 22-Jan-99, BO - nonalignment of OSF/Alpha */ if (VALUE_UNDEFINED == *status) { used_ver = 1; *status = NGP_OK; } if (NGP_OK == *status) *status = ngp_set_extver(used_name, used_ver); } fits_movabs_hdu(ff, my_hn, &tmp0, status); } if (NGP_OK != *status) return(*status); if (NGP_OK != (*status = ngp_include_file(ngp_template))) return(*status); for (i = strlen(ngp_template) - 1; i >= 0; i--) /* strlen is > 0, otherwise fopen failed */ { #ifdef MSDOS if ('\\' == ngp_template[i]) break; #else if ('/' == ngp_template[i]) break; #endif } i++; if (i > (NGP_MAX_FNAME - 1)) i = NGP_MAX_FNAME - 1; if (i > 0) { memcpy(ngp_master_dir, ngp_template, i); ngp_master_dir[i] = 0; } for (;;) { if (NGP_OK != (r = ngp_read_line(1))) break; /* EOF always means error here */ switch (ngp_keyidx) { case NGP_TOKEN_SIMPLE: if (0 == first_extension) /* simple only allowed in first HDU */ { r = NGP_TOKEN_NOT_EXPECT; break; } if (NGP_OK != (r = ngp_unread_line())) break; r = ngp_read_xtension(ff, 0, NGP_XTENSION_SIMPLE | NGP_XTENSION_FIRST); first_extension = 0; break; case NGP_TOKEN_XTENSION: if (NGP_OK != (r = ngp_unread_line())) break; r = ngp_read_xtension(ff, 0, (first_extension ? NGP_XTENSION_FIRST : 0)); first_extension = 0; break; case NGP_TOKEN_GROUP: if (NGP_TTYPE_STRING == ngp_linkey.type) { strncpy(grnm, ngp_linkey.value.s, NGP_MAX_STRING); } else { sprintf(grnm, "DEFAULT_GROUP_%d", master_grp_idx++); } grnm[NGP_MAX_STRING - 1] = 0; r = ngp_read_group(ff, grnm, 0); first_extension = 0; break; case NGP_TOKEN_EOF: exit_flg = 1; break; default: r = NGP_TOKEN_NOT_EXPECT; break; } if (exit_flg || (NGP_OK != r)) break; } /* all top level HDUs up to faulty one are left intact in case of i/o error. It is up to the caller to call fits_close_file or fits_delete_file when this function returns error. */ ngp_free_line(); /* deallocate last line (if any) */ ngp_free_prevline(); /* deallocate cached line (if any) */ ngp_delete_extver_tab(); /* delete extver table (if present), error ignored */ *status = r; return(r); }
static GwyContainer* fits_load(const gchar *filename, G_GNUC_UNUSED GwyRunType mode, GError **error) { GwyContainer *container = NULL; fitsfile *fptr = NULL; GwyDataField *field = NULL, *mask; gint status = 0; /* Must be initialised to zero! */ gint hdutype, naxis, anynull, nkeys, k; glong res[3]; /* First index is the fast looping one. */ char strvalue[FLEN_VALUE]; gchar *invalid = NULL; gdouble real, off; if (fits_open_image(&fptr, filename, READONLY, &status)) { err_FITS(error, status); return NULL; } if (fits_get_hdu_type(fptr, &hdutype, &status)) { err_FITS(error, status); goto fail; } gwy_debug("hdutype %d", hdutype); if (hdutype != IMAGE_HDU) { g_set_error(error, GWY_MODULE_FILE_ERROR, GWY_MODULE_FILE_ERROR_DATA, _("Only two-dimensional images are supported.")); goto fail; } if (fits_get_img_dim(fptr, &naxis, &status)) { err_FITS(error, status); goto fail; } gwy_debug("naxis %d", naxis); if (naxis != 2 && naxis != 3) { g_set_error(error, GWY_MODULE_FILE_ERROR, GWY_MODULE_FILE_ERROR_DATA, _("Only two-dimensional images are supported.")); goto fail; } if (fits_get_img_size(fptr, naxis, res, &status)) { err_FITS(error, status); goto fail; } if (naxis == 3 && res[2] != 1) { g_set_error(error, GWY_MODULE_FILE_ERROR, GWY_MODULE_FILE_ERROR_DATA, _("Only two-dimensional images are supported.")); goto fail; } gwy_debug("xres %ld, yres %ld", res[0], res[1]); if (err_DIMENSION(error, res[0]) || err_DIMENSION(error, res[1])) goto fail; field = gwy_data_field_new(res[0], res[1], res[0], res[1], FALSE); invalid = g_new(gchar, res[0]*res[1]); if (fits_read_imgnull(fptr, TDOUBLE, 1, res[0]*res[1], field->data, invalid, &anynull, &status)) { err_FITS(error, status); goto fail; } container = gwy_container_new(); gwy_container_set_object_by_name(container, "/0/data", field); /* Failures here are non-fatal. We already have an image. */ if (fits_get_hdrspace(fptr, &nkeys, NULL, &status)) { g_warning("Cannot get the first hdrspace."); goto fail; } if (!fits_read_key(fptr, TSTRING, "BUINT ", strvalue, NULL, &status)) { gint power10; gwy_debug("BUINT = <%s>", strvalue); gwy_si_unit_set_from_string_parse(gwy_data_field_get_si_unit_z(field), strvalue, &power10); if (power10) gwy_data_field_multiply(field, pow10(power10)); } status = 0; if (get_real_and_offset(fptr, 1, res[0], &real, &off)) { if (real < 0.0) { off += real; real = -real; gwy_data_field_invert(field, FALSE, TRUE, FALSE); } gwy_data_field_set_xreal(field, real); gwy_data_field_set_xoffset(field, off); } if (get_real_and_offset(fptr, 2, res[1], &real, &off)) { if (real < 0.0) { off += real; real = -real; gwy_data_field_invert(field, TRUE, FALSE, FALSE); } gwy_data_field_set_yreal(field, real); gwy_data_field_set_yoffset(field, off); } /* Create a mask of invalid data. */ for (k = 0; k < field->xres*field->yres; k++) { if (invalid[k]) field->data[k] = NAN; } if ((mask = gwy_app_channel_mask_of_nans(field, TRUE))) { gwy_container_set_object_by_name(container, "/0/mask", mask); g_object_unref(mask); } fail: fits_close_file(fptr, &status); gwy_object_unref(field); g_free(invalid); return container; }