static void * vips_fits_write_meta( VipsImage *image, const char *field, GValue *value, void *a ) { VipsFits *fits = (VipsFits *) a; int status; const char *value_str; status = 0; /* We want fields which start "fits-". */ if( !vips_isprefix( "fits-", field ) ) return( NULL ); /* The value should be a refstring, since we wrote it in fits2vips * above ^^. */ value_str = vips_value_get_ref_string( value, NULL ); VIPS_DEBUG_MSG( "vips_fits_write_meta: setting meta on fits image:\n" ); VIPS_DEBUG_MSG( " value == \"%s\"\n", value_str ); if( fits_write_record( fits->fptr, value_str, &status ) ) { vips_fits_error( status ); return( a ); } return( NULL ); }
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; }
int ngp_keyword_all_write(NGP_HDU *ngph, fitsfile *ffp, int mode) { int i, r, ib; char buf[200]; long l; if (NULL == ngph) return(NGP_NUL_PTR); if (NULL == ffp) return(NGP_NUL_PTR); r = NGP_OK; for (i=0; i<ngph->tokcnt; i++) { if ((NGP_REALLY_ALL & mode) || (NGP_OK == ngp_keyword_is_write(&(ngph->tok[i])))) { switch (ngph->tok[i].type) { case NGP_TTYPE_BOOL: ib = ngph->tok[i].value.b; fits_write_key(ffp, TLOGICAL, ngph->tok[i].name, &ib, ngph->tok[i].comment, &r); break; case NGP_TTYPE_STRING: fits_write_key_longstr(ffp, ngph->tok[i].name, ngph->tok[i].value.s, ngph->tok[i].comment, &r); break; case NGP_TTYPE_INT: l = ngph->tok[i].value.i; /* bugfix - 22-Jan-99, BO - nonalignment of OSF/Alpha */ fits_write_key(ffp, TLONG, ngph->tok[i].name, &l, ngph->tok[i].comment, &r); break; case NGP_TTYPE_REAL: fits_write_key(ffp, TDOUBLE, ngph->tok[i].name, &(ngph->tok[i].value.d), ngph->tok[i].comment, &r); break; case NGP_TTYPE_COMPLEX: fits_write_key(ffp, TDBLCOMPLEX, ngph->tok[i].name, &(ngph->tok[i].value.c), ngph->tok[i].comment, &r); break; case NGP_TTYPE_NULL: fits_write_key_null(ffp, ngph->tok[i].name, ngph->tok[i].comment, &r); break; case NGP_TTYPE_RAW: if (0 == strcmp("HISTORY", ngph->tok[i].name)) { fits_write_history(ffp, ngph->tok[i].comment, &r); break; } if (0 == strcmp("COMMENT", ngph->tok[i].name)) { fits_write_comment(ffp, ngph->tok[i].comment, &r); break; } sprintf(buf, "%-8.8s%s", ngph->tok[i].name, ngph->tok[i].comment); fits_write_record(ffp, buf, &r); break; } if (r) return(r); } } fits_set_hdustruc(ffp, &r); /* resync cfitsio */ return(r); }
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 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 create_input() { const double TWOPI = 2.0 * 3.14159265358979323846; /* These must match wcstab.keyrec. */ const char infile[] = "test/wcstab.keyrec"; const long NAXIS1 = 256; const long NAXIS2 = 128; const long NAXIS3 = 4; const char *ttype1[3] = {"CelCoords", "RAIndex", "DecIndex"}; const char *tform1[3] = {"5600E", "70E", "40E"}; const char *tunit1[3] = {"deg", "", ""}; const char *ttype2[4] = {"WaveIndex", "WaveCoord", "TimeIndex", "TimeCoord"}; const char *tform2[4] = {"8E", "8D", "8E", "8D"}; const char *tunit2[4] = {"", "m", "", "a"}; /* The remaining parameters may be chosen at will. */ float refval[] = {150.0f, -30.0f}; float span[] = {5.0f, (5.0f*K2)/K1}; float sigma[] = {0.10f, 0.05f}; double wcoord[] = {0.21106114, 0.21076437, 2.0e-6, 2.2e-6, 500.0e-9, 650.0e-9, 1.24e-9, 2.48e-9}; double windex[] = {0.5, 1.5, 1.5, 2.5, 2.5, 3.5, 3.5, 4.5}; double tcoord[] = {1997.84512, 1997.84631, 1993.28451, 1993.28456, 2001.59234, 2001.59239, 2002.18265, 2002.18301}; double tindex[] = {0.0, 1.0, 1.0, 2.0, 2.0, 3.0, 3.0, 4.0}; char keyrec[84]; int i, status; long dummy, firstelem, k1, k2, p1, p2, p3; float array[2*K1*K2], *fp, image[256]; double s, t, x1, x2, z, z1, z2; FILE *stream; fitsfile *fptr; /* Look for the input header keyrecords. */ if ((stream = fopen(infile+5, "r")) == 0x0) { if ((stream = fopen(infile, "r")) == 0x0) { printf("ERROR opening %s\n", infile); return 1; } } /* Create the FITS output file, deleting any pre-existing file. */ status = 0; fits_create_file(&fptr, "!wcstab.fits", &status); /* Convert header keyrecords to FITS. */ while (fgets(keyrec, 82, stream) != NULL) { /* Ignore meta-comments (copyright information, etc.). */ if (keyrec[0] == '#') continue; /* Strip off the newline. */ i = strlen(keyrec) - 1; if (keyrec[i] == '\n') keyrec[i] = '\0'; fits_write_record(fptr, keyrec, &status); } fclose(stream); /* Create and write some phoney image data. */ firstelem = 1; for (p3 = 0; p3 < NAXIS3; p3++) { for (p2 = 0; p2 < NAXIS2; p2++) { fp = image; s = (p3 + 1) * cos(0.2 * p2); t = cos(0.8*p2); for (p1 = 0; p1 < NAXIS1; p1++) { /* Do not adjust your set! */ *(fp++) = sin(0.1*(p1+p2) + s) * cos(0.4*p1) * t; } fits_write_img_flt(fptr, 0L, firstelem, NAXIS1, image, &status); firstelem += NAXIS1; } } /* Add the first binary table extension. */ fits_create_tbl(fptr, BINARY_TBL, 1L, 3L, (char **)ttype1, (char **)tform1, (char **)tunit1, NULL, &status); /* Write EXTNAME and EXTVER near the top, after TFIELDS. */ fits_read_key_lng(fptr, "TFIELDS", &dummy, NULL, &status); fits_insert_key_str(fptr, "EXTNAME", "WCS-TABLE", "WCS Coordinate lookup table", &status); fits_insert_key_lng(fptr, "EXTVER", 1L, "Table number 1", &status); /* Write the TDIM1 keyrecord after TFORM1. */ fits_read_key_str(fptr, "TFORM1", keyrec, NULL, &status); sprintf(keyrec, "(2,%ld,%ld)", K1, K2); fits_insert_key_str(fptr, "TDIM1", keyrec, "Dimensions of 3-D array", &status); /* Plate carrée projection with a bit of noise for the sake of realism. */ fp = array; for (k2 = 0; k2 < K2; k2++) { for (k1 = 0; k1 < K1; k1++) { /* Box-Muller transformation: uniform -> normal distribution. */ x1 = lcprng(); x2 = lcprng(); if (x1 == 0.0) x1 = 1.0; z = sqrt(-2.0 * log(x1)); x2 *= TWOPI; z1 = z * cos(x2); z2 = z * sin(x2); *(fp++) = refval[0] + span[0] * (k1/(K1-1.0) - 0.5) + z1 * sigma[0]; *(fp++) = refval[1] + span[1] * (k2/(K2-1.0) - 0.5) + z2 * sigma[1]; } } fits_write_col_flt(fptr, 1, 1L, 1L, 2*K1*K2, array, &status); fp = array; for (k1 = 0; k1 < K1; k1++) { *(fp++) = 4.0f * k1; } fits_write_col_flt(fptr, 2, 1L, 1L, K1, array, &status); fp = array; for (k2 = 0; k2 < K2; k2++) { *(fp++) = 4.0f * k2; } fits_write_col_flt(fptr, 3, 1L, 1L, K2, array, &status); /* Add the second binary table extension. */ if (fits_create_tbl(fptr, BINARY_TBL, 1L, 4L, (char **)ttype2, (char **)tform2, (char **)tunit2, NULL, &status)) { fits_report_error(stderr, status); return 1; } /* Write EXTNAME and EXTVER near the top, after TFIELDS. */ fits_read_key_lng(fptr, "TFIELDS", &dummy, NULL, &status); fits_insert_key_str(fptr, "EXTNAME", "WCS-TABLE", "WCS Coordinate lookup table", &status); fits_insert_key_lng(fptr, "EXTVER", 2L, "Table number 2", &status); /* Write the TDIM2 keyrecord after TFORM2. */ fits_read_key_str(fptr, "TFORM2", keyrec, NULL, &status); fits_insert_key_str(fptr, "TDIM2", "(1,8)", "Dimensions of 2-D array", &status); /* Write the TDIM4 keyrecord after TFORM4. */ fits_read_key_str(fptr, "TFORM4", keyrec, NULL, &status); fits_insert_key_str(fptr, "TDIM4", "(1,8)", "Dimensions of 2-D array", &status); fits_write_col_dbl(fptr, 1, 1L, 1L, 8L, windex, &status); fits_write_col_dbl(fptr, 2, 1L, 1L, 8L, wcoord, &status); fits_write_col_dbl(fptr, 3, 1L, 1L, 8L, tindex, &status); fits_write_col_dbl(fptr, 4, 1L, 1L, 8L, tcoord, &status); fits_close_file(fptr, &status); if (status) { fits_report_error(stderr, status); return 1; } return 0; }
int HPXhdr(fitsfile *fptr, struct healpix *hpxdat) { char comment[64], cval[16], *ctype1, *ctype2, *descr1, *descr2, *pcode; int status; float cos45, crpix1, crpix2, crval1, crval2, lonpole; double cdelt1, cdelt2; status = 0; fits_update_key_log(fptr, "EXTEND", 0, "No FITS extensions are present", &status); fits_write_date(fptr, &status); /* Set pixel transformation parameters. */ if (hpxdat->layout == 0) { crpix1 = (5 * hpxdat->nside + 1) / 2.0f; } else { crpix1 = (4 * hpxdat->nside + 1) / 2.0f; } crpix2 = crpix1; fits_write_key(fptr, TFLOAT, "CRPIX1", &crpix1, "Coordinate reference pixel", &status); fits_write_key(fptr, TFLOAT, "CRPIX2", &crpix2, "Coordinate reference pixel", &status); cos45 = (float)sqrt(2.0) / 2.0f; if (hpxdat->layout == 0) { fits_write_key_flt(fptr, "PC1_1", cos45, -8, "Transformation matrix element", &status); fits_write_key_flt(fptr, "PC1_2", cos45, -8, "Transformation matrix element", &status); fits_write_key_flt(fptr, "PC2_1", -cos45, -8, "Transformation matrix element", &status); fits_write_key_flt(fptr, "PC2_2", cos45, -8, "Transformation matrix element", &status); } cdelt1 = -90.0 / hpxdat->nside / sqrt(2.0); cdelt2 = -cdelt1; fits_write_key_dbl(fptr, "CDELT1", cdelt1, -8, "[deg] Coordinate increment", &status); fits_write_key_dbl(fptr, "CDELT2", cdelt2, -8, "[deg] Coordinate increment", &status); /* Celestial transformation parameters. */ if (hpxdat->layout == 0) { pcode = "HPX"; } else { pcode = "XPH"; } if (hpxdat->crdsys == 'G') { /* Galactic. */ ctype1 = "GLON"; ctype2 = "GLAT"; descr1 = "Galactic longitude"; descr2 = "Galactic latitude"; } else if (hpxdat->crdsys == 'E') { /* Ecliptic, who-knows-what. */ ctype1 = "ELON"; ctype2 = "ELAT"; descr1 = "Ecliptic longitude"; descr2 = "Ecliptic latitude"; } else if (hpxdat->crdsys == 'Q') { /* Equatorial, who-knows-what. */ ctype1 = "RA--"; ctype2 = "DEC-"; descr1 = "Right ascension"; descr2 = "Declination"; } else { /* Unknown. */ ctype1 = "XLON"; ctype2 = "XLAT"; descr1 = "Longitude"; descr2 = " Latitude"; } sprintf(cval, "%s-%s", ctype1, pcode); sprintf(comment, "%s in an %s projection", descr1, pcode); fits_write_key_str(fptr, "CTYPE1", cval, comment, &status); sprintf(cval, "%s-%s", ctype2, pcode); sprintf(comment, "%s in an %s projection", descr2, pcode); fits_write_key_str(fptr, "CTYPE2", cval, comment, &status); crval1 = 0.0f + 90.0f * hpxdat->quad; if (hpxdat->layout == 0) { crval2 = 0.0f; } else if (hpxdat->layout == 1) { crval1 += 180.0f; crval2 = 90.0f; } else { crval1 += 180.0f; crval2 = -90.0f; } if (360.0f < crval1) crval1 -= 360.0f; sprintf(comment, "[deg] %s at the reference point", descr1); fits_write_key(fptr, TFLOAT, "CRVAL1", &crval1, comment, &status); sprintf(comment, "[deg] %s at the reference point", descr2); fits_write_key(fptr, TFLOAT, "CRVAL2", &crval2, comment, &status); if (hpxdat->layout) { lonpole = 180.0f; sprintf(comment, "[deg] Native longitude of the celestial pole"); fits_write_key(fptr, TFLOAT, "LONPOLE", &lonpole, comment, &status); } if (hpxdat->layout == 0) { fits_write_key_lng(fptr, "PV2_1", (LONGLONG)4, "HPX H parameter (longitude)", &status); fits_write_key_lng(fptr, "PV2_2", (LONGLONG)3, "HPX K parameter (latitude)", &status); } /* Commentary. */ fits_write_record(fptr, " ", &status); if (hpxdat->layout == 0) { fits_write_comment(fptr, "Celestial map with FITS-standard HPX coordinate system generated by", &status); } else { fits_write_comment(fptr, "Celestial map with XPH coordinate system (polar HPX) generated by", &status); } fits_write_comment(fptr, "'HPXcvt' which reorganises HEALPix data without interpolation as", &status); fits_write_comment(fptr, "described in \"Mapping on the HEALPix grid\" by Mark Calabretta and", &status); fits_write_comment(fptr, "Boud Roukema. See http://www.atnf.csiro.au/people/Mark.Calabretta", &status); 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 ngp_keyword_all_write(NGP_HDU *ngph, fitsfile *ffp, int mode) { int i, r, ib; char buf[200]; long l; if (NULL == ngph) return(NGP_NUL_PTR); if (NULL == ffp) return(NGP_NUL_PTR); r = NGP_OK; for (i=0; i<ngph->tokcnt; i++) { r = ngp_keyword_is_write(&(ngph->tok[i])); if ((NGP_REALLY_ALL & mode) || (NGP_OK == r)) { switch (ngph->tok[i].type) { case NGP_TTYPE_BOOL: ib = ngph->tok[i].value.b; fits_write_key(ffp, TLOGICAL, ngph->tok[i].name, &ib, ngph->tok[i].comment, &r); break; case NGP_TTYPE_STRING: fits_write_key_longstr(ffp, ngph->tok[i].name, ngph->tok[i].value.s, ngph->tok[i].comment, &r); break; case NGP_TTYPE_INT: l = ngph->tok[i].value.i; /* bugfix - 22-Jan-99, BO - nonalignment of OSF/Alpha */ fits_write_key(ffp, TLONG, ngph->tok[i].name, &l, ngph->tok[i].comment, &r); break; case NGP_TTYPE_REAL: fits_write_key(ffp, TDOUBLE, ngph->tok[i].name, &(ngph->tok[i].value.d), ngph->tok[i].comment, &r); break; case NGP_TTYPE_COMPLEX: fits_write_key(ffp, TDBLCOMPLEX, ngph->tok[i].name, &(ngph->tok[i].value.c), ngph->tok[i].comment, &r); break; case NGP_TTYPE_NULL: fits_write_key_null(ffp, ngph->tok[i].name, ngph->tok[i].comment, &r); break; case NGP_TTYPE_RAW: if (0 == strcmp("HISTORY", ngph->tok[i].name)) { fits_write_history(ffp, ngph->tok[i].comment, &r); break; } if (0 == strcmp("COMMENT", ngph->tok[i].name)) { fits_write_comment(ffp, ngph->tok[i].comment, &r); break; } sprintf(buf, "%-8.8s%s", ngph->tok[i].name, ngph->tok[i].comment); fits_write_record(ffp, buf, &r); break; } } else if (NGP_BAD_ARG == r) /* enhancement 10 dec 2003, James Peachey: template comments replace defaults */ { r = NGP_OK; /* update comments of special keywords like TFORM */ if (ngph->tok[i].comment && *ngph->tok[i].comment) /* do not update with a blank comment */ { fits_modify_comment(ffp, ngph->tok[i].name, ngph->tok[i].comment, &r); } } else /* other problem, typically a blank token */ { r = NGP_OK; /* skip this token, but continue */ } if (r) return(r); } fits_set_hdustruc(ffp, &r); /* resync cfitsio */ return(r); }
/*--------------------------------------------------------------------------*/ 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); }