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); }
static fitsfile* create_fits_file(const char* filename, int precision, int width, int height, int num_times, int num_channels, double centre_deg[2], double fov_deg[2], double start_time_mjd, double delta_time_sec, double start_freq_hz, double delta_freq_hz, int horizon_mode, const char* settings_log, size_t settings_log_length, int* status) { int imagetype; long naxes[4], naxes_dummy[4] = {1l, 1l, 1l, 1l}; double delta; const double deg2rad = M_PI / 180.0; const double rad2deg = 180.0 / M_PI; fitsfile* f = 0; const char* line; size_t length; if (*status) return 0; /* Create a new FITS file and write the image headers. */ if (oskar_file_exists(filename)) remove(filename); imagetype = (precision == OSKAR_DOUBLE ? DOUBLE_IMG : FLOAT_IMG); naxes[0] = width; naxes[1] = height; naxes[2] = num_channels; naxes[3] = num_times; fits_create_file(&f, filename, status); fits_create_img(f, imagetype, 4, naxes_dummy, status); fits_write_date(f, status); fits_write_key_str(f, "TELESCOP", "OSKAR " OSKAR_VERSION_STR, 0, status); /* Write axis headers. */ if (horizon_mode) { delta = oskar_convert_fov_to_cellsize(M_PI, width); write_axis(f, 1, "-----SIN", "Azimuthal angle", 0.0, -delta * rad2deg, (width + 1) / 2.0, status); delta = oskar_convert_fov_to_cellsize(M_PI, height); write_axis(f, 2, "-----SIN", "Elevation", 90.0, delta * rad2deg, (height + 1) / 2.0, status); } else { delta = oskar_convert_fov_to_cellsize(fov_deg[0] * deg2rad, width); write_axis(f, 1, "RA---SIN", "Right Ascension", centre_deg[0], -delta * rad2deg, (width + 1) / 2.0, status); delta = oskar_convert_fov_to_cellsize(fov_deg[1] * deg2rad, height); write_axis(f, 2, "DEC--SIN", "Declination", centre_deg[1], delta * rad2deg, (height + 1) / 2.0, status); } write_axis(f, 3, "FREQ", "Frequency", start_freq_hz, delta_freq_hz, 1.0, status); write_axis(f, 4, "UTC", "Time", start_time_mjd * 86400.0, delta_time_sec, 1.0, status); /* Write other headers. */ fits_write_key_str(f, "TIMESYS", "UTC", NULL, status); fits_write_key_str(f, "TIMEUNIT", "s", "Time axis units", status); fits_write_key_dbl(f, "MJD-OBS", start_time_mjd, 10, "Start time", status); if (!horizon_mode) { fits_write_key_dbl(f, "OBSRA", centre_deg[0], 10, "RA", status); fits_write_key_dbl(f, "OBSDEC", centre_deg[1], 10, "DEC", status); } /* Write the settings log up to this point as HISTORY comments. */ line = settings_log; length = settings_log_length; for (; settings_log_length > 0;) { const char* eol; fits_write_history(f, line, status); eol = (const char*) memchr(line, '\0', length); if (!eol) break; eol += 1; length -= (eol - line); line = eol; } /* Update header keywords with the correct axis lengths. * Needs to be done here because CFITSIO doesn't let us write only the * file header with the correct axis lengths to start with. This trick * allows us to create a small dummy image block to write only the headers, * and not waste effort moving a huge block of zeros within the file. */ fits_update_key_lng(f, "NAXIS1", naxes[0], 0, status); fits_update_key_lng(f, "NAXIS2", naxes[1], 0, status); fits_update_key_lng(f, "NAXIS3", naxes[2], 0, status); fits_update_key_lng(f, "NAXIS4", naxes[3], 0, status); return f; }
int addkey(char *outfile, char *keyword, char *keyvalue) { fitsfile *fptr; /* FITS file pointer, defined in fitsio.h */ char card[FLEN_CARD], newcard[FLEN_CARD], temp[FLEN_CARD]; char oldvalue[FLEN_VALUE], comment[FLEN_COMMENT]; int status = 0; /* CFITSIO status value MUST be initialized to zero! */ int keytype, i; if (!fits_open_file(&fptr, outfile, READWRITE, &status)) { #ifdef DEBUG if (fits_read_card(fptr, keyword, card, &status)) { printf("Keyword does not exist\n"); card[0] = '\0'; comment[0] = '\0'; status = 0; /* reset status after error */ } else { strcpy (temp, keyword); for (i=0; i<FLEN_CARD; i++) temp[i]=toupper(temp[i]); if ( strcmp("COMMENT", temp) && strcmp("HISTORY", temp) ) printf("%s\n",card); } #endif /* check if this is a protected keyword that must not be changed */ if (*card && fits_get_keyclass(card) == TYP_STRUC_KEY) { #ifdef DEBUG printf("Protected keyword cannot be modified.\n"); #endif } else { strcpy (temp, keyword); for (i=0; i<FLEN_CARD; i++) temp[i]=toupper(temp[i]); if ( !strcmp ("COMMENT", temp) ) { fits_write_comment ( fptr, keyvalue, &status ); #ifdef DEBUG printf ("New comment added.\n"); #endif } else if ( !strcmp ("HISTORY", temp) ) { fits_write_history ( fptr, keyvalue, &status ); #ifdef DEBUG printf ("New history added.\n"); #endif } else { /* get the comment string */ if (*card)fits_parse_value(card, oldvalue, comment, &status); /* construct template for new keyword */ strcpy(newcard, keyword); /* copy keyword name */ strcat(newcard, " = "); /* '=' value delimiter */ strcat(newcard, keyvalue); /* new value */ if (*comment) { strcat(newcard, " / "); /* comment delimiter */ strcat(newcard, comment); /* append the comment */ } /* reformat the keyword string to conform to FITS rules */ fits_parse_template(newcard, card, &keytype, &status); /* overwrite the keyword with the new value */ fits_update_card(fptr, keyword, card, &status); #ifdef DEBUG printf("Keyword has been changed to:\n"); printf("%s\n",card); #endif } } fits_close_file(fptr, &status); } /* open_file */ /* if error occured, print out error message */ if (status) fits_report_error(stderr, status); return(status); }
int HPXout(struct healpix *hpxdat) { /* Number of facets on a side of each layout. */ const int NFACET[] = {5, 4, 4}; /* Arrays that define the facet location and rotation for each recognised * layout. Bear in mind that these appear to be upside-down, i.e. the top * line contains facet numbers for the bottom row of the output image. * Facets numbered -1 are blank. */ /* Equatorial (diagonal) facet layout. */ const int FACETS[][5][5] = {{{ 6, 9, -1, -1, -1}, { 1, 5, 8, -1, -1}, {-1, 0, 4, 11, -1}, {-1, -1, 3, 7, 10}, {-1, -1, -1, 2, 6}}, /* North polar (X) facet layout. */ {{ 8, 4, 4, 11, -1}, { 5, 0, 3, 7, -1}, { 5, 1, 2, 7, -1}, { 9, 6, 6, 10, -1}, {-1, -1, -1, -1, -1}}, /* South polar (X) facet layout. */ {{ 1, 6, 6, 2, -1}, { 5, 9, 10, 7, -1}, { 5, 8, 11, 7, -1}, { 0, 4, 4, 3, -1}, {-1, -1, -1, -1, -1}}}; /* All facets of the equatorial layout are rotated by +45 degrees with * respect to the normal orientation, i.e. that with the equator running * horizontally. The rotation recorded for the polar facets is the number * of additional positive (anti-clockwise) 90 degree turns with respect to * the equatorial layout. */ /* Equatorial (diagonal), no facet rotation. */ const int FROTAT[][5][5] = {{{ 0, 0, 0, 0, 0}, { 0, 0, 0, 0, 0}, { 0, 0, 0, 0, 0}, { 0, 0, 0, 0, 0}, { 0, 0, 0, 0, 0}}, /* North polar (X) facet rotation. */ {{ 3, 3, 0, 0, 0}, { 3, 3, 0, 0, 0}, { 2, 2, 1, 1, 0}, { 2, 2, 1, 1, 0}, { 0, 0, 0, 0, 0}}, /* South polar (X) facet rotation. */ {{ 1, 1, 2, 2, 0}, { 1, 1, 2, 2, 0}, { 0, 0, 3, 3, 0}, { 0, 0, 3, 3, 0}, { 0, 0, 0, 0, 0}}}; /* Facet halving codes. 0: the facet is whole (or wholly blank), * 1: blanked bottom-right, 2: top-right, 3: top-left, 4: bottom-left. * Positive values mean that the diagonal is included, otherwise not. */ /* Equatorial (diagonal), no facet halving. */ const int FHALVE[][5][5] = {{{ 0, 0, 0, 0, 0}, { 0, 0, 0, 0, 0}, { 0, 0, 0, 0, 0}, { 0, 0, 0, 0, 0}, { 0, 0, 0, 0, 0}}, /* North polar (X) facet halving. */ {{ 0, 1, -4, 0, 0}, {-3, 0, 0, 2, 0}, { 4, 0, 0, -1, 0}, { 0, -2, 3, 0, 0}, { 0, 0, 0, 0, 0}}, /* South polar (X) facet halving. */ {{ 0, 1, -4, 0, 0}, {-3, 0, 0, 2, 0}, { 4, 0, 0, -1, 0}, { 0, -2, 3, 0, 0}, { 0, 0, 0, 0, 0}}}; char history[72]; int facet, halve, i1, i2, ifacet, j, jfacet, layout, nfacet, nside, rotn, status; long *healidx = 0x0, *healp, naxes[2]; float nulval = HEALPIX_NULLVAL, *row = 0x0, *rowp; LONGLONG fpixel, group, nelem; fitsfile *fptr; nside = hpxdat->nside; layout = hpxdat->layout; nfacet = NFACET[layout]; /* Create the output FITS file. */ status = 0; naxes[0] = nfacet * nside; naxes[1] = naxes[0]; if (fits_create_file(&fptr, hpxdat->outfile, &status)) goto fitserr; if (fits_create_img(fptr, FLOAT_IMG, 2, naxes, &status)) goto fitserr; /* Write WCS keyrecords. */ if ((status = HPXhdr(fptr, hpxdat))) goto fitserr; /* Allocate arrays. */ if ((healidx = malloc(nside * sizeof(long))) == NULL || (row = malloc(nside * sizeof(float))) == NULL) { perror("HPXcvt"); goto cleanup; } /* Loop vertically facet-by-facet. */ fpixel = 1; group = 0; nelem = nside; for (jfacet = 0; jfacet < nfacet; jfacet++) { /* Loop row-by-row. */ for (j = 0; j < nside; j++) { /* Loop horizontally facet-by-facet. */ for (ifacet = 0; ifacet < nfacet; ifacet++) { facet = FACETS[layout][jfacet][ifacet]; rotn = FROTAT[layout][jfacet][ifacet]; halve = FHALVE[layout][jfacet][ifacet]; /* Recentre longitude? */ if (hpxdat->quad && facet >= 0) { if (facet <= 3) { facet += hpxdat->quad; if (facet > 3) facet -= 4; } else if (facet <= 7) { facet += hpxdat->quad; if (facet > 7) facet -= 4; } else { facet += hpxdat->quad; if (facet > 11) facet -= 4; } } /* Write out the data. */ if (facet < 0) { /* A blank facet. */ if (fits_write_img_null(fptr, group, fpixel, nelem, &status)) { goto fitserr; } } else { if (hpxdat->ordering == 'N') { /* Get nested indices. */ status = NESTidx(nside, facet, rotn, j, healidx); } else { /* Get ring indices. */ status = RINGidx(nside, facet, rotn, j, healidx); } /* Gather data into the output vector. */ healp = healidx; for (rowp = row; rowp < row + nside; rowp++) { *rowp = hpxdat->data[*(healp++)]; } /* Apply blanking to halved facets. */ if (halve) { if (abs(halve) == 1) { /* Blank bottom-right. */ i1 = j; i2 = nside; if (halve > 0) i1++; } else if (abs(halve) == 2) { /* Blank top-right. */ i1 = nside - j; i2 = nside; if (halve < 0) i1--; } else if (abs(halve) == 3) { /* Blank top-left. */ i1 = 0; i2 = j; if (halve < 0) i2++; } else { /* Blank bottom-left. */ i1 = 0; i2 = nside - j; if (halve > 0) i2--; } for (rowp = row + i1; rowp < row + i2; rowp++) { *rowp = nulval; } } /* Write out this facet's contribution to this row of the map. */ if (fits_write_imgnull_flt(fptr, group, fpixel, nelem, row, nulval, &status)) { goto fitserr; } } fpixel += nelem; } } } /* Write history. */ sprintf(history, "Original input file: %s", hpxdat->infile); fits_write_history(fptr, history, &status); sprintf(history, " Original NSIDE: %d", hpxdat->nside); fits_write_history(fptr, history, &status); sprintf(history, " Original ordering: %s", (hpxdat->ordering == 'N') ? "NESTED" : "RING"); if (hpxdat->ordering == 'r') strcat(history, " (assumed)"); fits_write_history(fptr, history, &status); /* Clean up. */ fits_close_file(fptr, &status); status = 0; return 0; fitserr: fits_report_error(stderr, status); cleanup: if (healidx) free(healidx); if (row) free(row); return 1; }
int FITSImage::saveFITS( const QString &newFilename ) { int status=0; long fpixel[2], nelements; fitsfile *new_fptr; nelements = stats.dim[0] * stats.dim[1]; fpixel[0] = 1; fpixel[1] = 1; /* Create a new File, overwriting existing*/ if (fits_create_file(&new_fptr, newFilename.toAscii(), &status)) { fits_report_error(stderr, status); return status; } /* Copy ALL contents */ if (fits_copy_file(fptr, new_fptr, 1, 1, 1, &status)) { fits_report_error(stderr, status); return status; } /* close current file */ if (fits_close_file(fptr, &status)) { fits_report_error(stderr, status); return status; } if (tempFile) { QFile::remove(filename); tempFile = false; } filename = newFilename; fptr = new_fptr; /* Write Data */ if (fits_write_pix(fptr, TFLOAT, fpixel, nelements, image_buffer, &status)) { fits_report_error(stderr, status); return status; } /* Write keywords */ // Minimum if (fits_update_key(fptr, TDOUBLE, "DATAMIN", &(stats.min), "Minimum value", &status)) { fits_report_error(stderr, status); return status; } // Maximum if (fits_update_key(fptr, TDOUBLE, "DATAMAX", &(stats.max), "Maximum value", &status)) { fits_report_error(stderr, status); return status; } // ISO Date if (fits_write_date(fptr, &status)) { fits_report_error(stderr, status); return status; } QString history = QString("Modified by KStars on %1").arg(QDateTime::currentDateTime().toString("yyyy-MM-ddThh:mm:ss")); // History if (fits_write_history(fptr, history.toAscii(), &status)) { fits_report_error(stderr, status); 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); }