bool Camera_INDIClass::ReadFITS(usImage& img, bool takeSubframe, const wxRect& subframe) { int xsize, ysize; fitsfile *fptr; // FITS file pointer int status = 0; // CFITSIO status value MUST be initialized to zero! int hdutype, naxis; int nhdus=0; long fits_size[2]; long fpixel[3] = {1,1,1}; size_t bsize = static_cast<size_t>(cam_bp->bloblen); // load blob to CFITSIO if (fits_open_memfile(&fptr, "", READONLY, &(cam_bp->blob), &bsize, 0, NULL, &status) ) { pFrame->Alert(_("Unsupported type or read error loading FITS file")); return true; } if (fits_get_hdu_type(fptr, &hdutype, &status) || hdutype != IMAGE_HDU) { pFrame->Alert(_("FITS file is not of an image")); PHD_fits_close_file(fptr); return true; } // Get HDUs and size fits_get_img_dim(fptr, &naxis, &status); fits_get_img_size(fptr, 2, fits_size, &status); xsize = (int) fits_size[0]; ysize = (int) fits_size[1]; fits_get_num_hdus(fptr,&nhdus,&status); if ((nhdus != 1) || (naxis != 2)) { pFrame->Alert(_("Unsupported type or read error loading FITS file")); PHD_fits_close_file(fptr); return true; } if (takeSubframe) { if (img.Init(FullSize)) { pFrame->Alert(_("Memory allocation error")); PHD_fits_close_file(fptr); return true; } img.Clear(); img.Subframe = subframe; unsigned short *rawdata = new unsigned short[xsize*ysize]; if (fits_read_pix(fptr, TUSHORT, fpixel, xsize*ysize, NULL, rawdata, NULL, &status) ) { pFrame->Alert(_("Error reading data")); PHD_fits_close_file(fptr); return true; } int i = 0; for (int y = 0; y < subframe.height; y++) { unsigned short *dataptr = img.ImageData + (y + subframe.y) * img.Size.GetWidth() + subframe.x; memcpy(dataptr, &rawdata[i], subframe.width * sizeof(unsigned short)); i += subframe.width; } delete[] rawdata; } else { if (img.Init(xsize,ysize)) { pFrame->Alert(_("Memory allocation error")); PHD_fits_close_file(fptr); return true; } // Read image if (fits_read_pix(fptr, TUSHORT, fpixel, xsize*ysize, NULL, img.ImageData, NULL, &status) ) { pFrame->Alert(_("Error reading data")); PHD_fits_close_file(fptr); return true; } } PHD_fits_close_file(fptr); return false; }
oskar_Sky* oskar_sky_from_fits_file(int precision, const char* filename, double min_peak_fraction, double min_abs_val, const char* default_map_units, int override_units, double frequency_hz, double spectral_index, int* status) { double image_crval_deg[2], image_crpix[2]; double image_cellsize_deg = 0.0, image_freq_hz = 0.0; double beam_area_pixels = 0.0, pixel_area_sr = 0.0; char *reported_map_units = 0, ordering = 0, coordsys = 0; int naxis = 0, nside = 0; int image_size[2]; oskar_Sky* t = 0; oskar_Mem* data = 0; fitsfile* fptr; /* Determine whether this is a regular FITS image or HEALPix data. */ fits_open_file(&fptr, filename, READONLY, status); if (*status || !fptr) { *status = OSKAR_ERR_FILE_IO; return 0; } fits_get_img_dim(fptr, &naxis, status); fits_close_file(fptr, status); if (naxis == 0) { /* Try to load HEALPix data. */ data = oskar_mem_read_healpix_fits(filename, 0, &nside, &ordering, &coordsys, &reported_map_units, status); pixel_area_sr = (4.0 * M_PI) / oskar_mem_length(data); /* Check HEALPix ordering scheme. */ if (!*status && ordering != 'R') { *status = OSKAR_ERR_FILE_IO; fprintf(stderr, "HEALPix data is not in RING format.\n"); } } else { /* Try to load image pixels. */ data = oskar_mem_read_fits_image_plane(filename, 0, 0, 0, image_size, image_crval_deg, image_crpix, &image_cellsize_deg, 0, &image_freq_hz, &beam_area_pixels, &reported_map_units, status); pixel_area_sr = pow(image_cellsize_deg * M_PI / 180.0, 2.0); } /* Make sure pixels are in Jy. */ if (image_freq_hz == 0.0) image_freq_hz = frequency_hz; oskar_convert_brightness_to_jy(data, beam_area_pixels, pixel_area_sr, image_freq_hz, min_peak_fraction, min_abs_val, reported_map_units, default_map_units, override_units, status); free(reported_map_units); /* Convert the image into a sky model. */ if (naxis == 0) t = oskar_sky_from_healpix_ring(precision, data, image_freq_hz, spectral_index, nside, (coordsys == 'G'), status); else t = oskar_sky_from_image(precision, data, image_size, image_crval_deg, image_crpix, image_cellsize_deg, image_freq_hz, spectral_index, status); /* Free pixel data and return sky model. */ oskar_mem_free(data, status); return t; }
std::string read_image_3D(std::string pathname_3D, float *&array_2D_real, float *&array_2D_imag, int &naxis_2D, long *&naxes_2D) { TRACE_ENTER(); // open FITS image file in READONLY mode fitsfile *fptr; int status = 0; fits_open_image(&fptr, pathname_3D.c_str(), READONLY, &status); if (status != 0) { return FORMAT_STATUS(status); } // read number of HDUs in the file int nhdus = 0; fits_get_num_hdus(fptr, &nhdus, &status); if (status != 0) { return FORMAT_STATUS(status); } // we expect only one HDU in the file if (nhdus != 1) { std::ostringstream exit_oss; exit_oss << "nhdus is " << nhdus << ", not 1"; TRACE_ERROR(exit_oss.str()); return exit_oss.str(); } // read the type of the HDU int hdutype = 0; fits_movabs_hdu(fptr, nhdus, &hdutype, &status); if (status != 0) { return FORMAT_STATUS(status); } // we expect the HDU to be an image if (hdutype != IMAGE_HDU) { std::ostringstream exit_oss; exit_oss << "hdutype is " << hdutype << ", not IMAGE_HDU"; TRACE_ERROR(exit_oss.str()); return exit_oss.str(); } // read the type of data in the HDU int bitpix = 0; fits_get_img_type (fptr, &bitpix, &status); if (status != 0) { return FORMAT_STATUS(status); } // we expect the data to be floats if (bitpix != FLOAT_IMG) { std::ostringstream exit_oss; exit_oss << "bitpix is " << bitpix << ", not FLOAT_IMG"; TRACE_ERROR(exit_oss.str()); return exit_oss.str(); } // get the number of dimensions in the image int naxis_3D = 0; fits_get_img_dim (fptr, &naxis_3D, &status); if (status != 0) { return FORMAT_STATUS(status); } naxis_2D = naxis_3D-1; // we expect 3 dimensions in the image if (naxis_3D != 3) { std::ostringstream exit_oss; exit_oss << "naxis_3D is " << naxis_3D << ", not 3"; TRACE_ERROR(exit_oss.str()); return exit_oss.str(); } // get the size of each dimension in the image long *naxes_3D = new long[naxis_3D]; int maxdim = naxis_3D; fits_get_img_size(fptr, maxdim, naxes_3D, &status); if (status != 0) { return FORMAT_STATUS(status); } naxes_2D = new long[naxis_2D]; for (int i = 0; i < naxis_2D; i++) { naxes_2D[i] = naxes_3D[i]; } // we expect two sub-images in the third dimension if (naxes_3D[2] != 2) { std::ostringstream exit_oss; exit_oss << "naxes_2D[2] is " << naxes_2D[2] << ", not 2"; TRACE_ERROR (exit_oss.str()); return exit_oss.str(); } // fits_read_subset long *fpixel = new long[naxis_3D]; for (int i = 0; i < naxis_3D; i++) { fpixel[i] = 1; } long *lpixel = new long[naxis_3D]; for (int i = 0; i < naxis_3D; i++) { lpixel[i] = naxes_3D[i]; } long *inc = new long[naxis_3D]; for (int i = 0; i < naxis_3D; i++) { inc[i] = 1; } float nulval = 0; long nelements_2D = 1; for (int i = 0; i < naxis_2D; i++) { nelements_2D = nelements_2D*naxes_2D[i]; } int anynul = 0; // read array_2D_real array_2D_real = new float[nelements_2D]; fpixel[2] = 1; lpixel[2] = 1; fits_read_subset(fptr, TFLOAT, fpixel, lpixel, inc, &nulval, array_2D_real, &anynul, &status); // read array_2D_imag array_2D_imag = new float[nelements_2D]; fpixel[2] = 2; lpixel[2] = 2; fits_read_subset(fptr, TFLOAT, fpixel, lpixel, inc, &nulval, array_2D_imag, &anynul, &status); // free arrays delete [] inc; delete [] lpixel; delete [] fpixel; // test read result if (status != 0) { return FORMAT_STATUS(status); } // close the FITS image file fits_close_file(fptr, &status); if (status != 0) { return FORMAT_STATUS(status); } return "READ_OK"; }
std::string read_image(std::string pathname, float *&array, int &naxis, long *&naxes) { TRACE_ENTER(); // open FITS image file in READONLY mode fitsfile *fptr; int status = 0; fits_open_image(&fptr, pathname.c_str(), READONLY, &status); if (status != 0) { return FORMAT_STATUS(status); } // read number of HDUs in the file int nhdus = 0; fits_get_num_hdus(fptr, &nhdus, &status); if (status != 0) { return FORMAT_STATUS(status); } // we expect only one HDU in the file if (nhdus != 1) { std::ostringstream exit_oss; exit_oss << "nhdus is " << nhdus << ", not 1"; TRACE_ERROR(exit_oss.str()); return exit_oss.str(); } // read the type of the HDU int hdutype = 0; fits_movabs_hdu(fptr, nhdus, &hdutype, &status); if (status != 0) { return FORMAT_STATUS(status); } // we expect the HDU to be an image if (hdutype != IMAGE_HDU) { std::ostringstream exit_oss; exit_oss << "hdutype is " << hdutype << ", not IMAGE_HDU"; TRACE_ERROR(exit_oss.str()); return exit_oss.str(); } // read the type of data in the HDU int bitpix = 0; fits_get_img_type (fptr, &bitpix, &status); if (status != 0) { return FORMAT_STATUS(status); } // we expect the data to be floats if (bitpix != FLOAT_IMG) { std::ostringstream exit_oss; exit_oss << "bitpix is " << bitpix << ", not FLOAT_IMG"; TRACE_ERROR(exit_oss.str()); return exit_oss.str(); } // get the number of dimensions in the image naxis = 0; fits_get_img_dim (fptr, &naxis, &status); if (status != 0) { return FORMAT_STATUS(status); } // we expect 2 or 3 dimensions in the image if ((naxis < 2) || (naxis > 3)) { std::ostringstream exit_oss; exit_oss << "naxis is " << naxis << ", neither 2 nor 3"; TRACE_ERROR(exit_oss.str()); return exit_oss.str(); } // get the size of each dimension in the image naxes = new long[naxis]; int maxdim = naxis; fits_get_img_size(fptr, maxdim, naxes, &status); if (status != 0) { return FORMAT_STATUS(status); } // fits_read_subset long *fpixel = new long[naxis]; for (int i = 0; i < naxis; i++) { fpixel[i] = 1; } long *lpixel = new long[naxis]; for (int i = 0; i < naxis; i++) { lpixel[i] = naxes[i]; } long *inc = new long[naxis]; for (int i = 0; i < naxis; i++) { inc[i] = 1; } float nulval = 0; long nelements = 1; for (int i = 0; i < naxis; i++) { nelements = nelements * naxes[i]; } array = new float[nelements]; int anynul = 0; fits_read_subset(fptr, TFLOAT, fpixel, lpixel, inc, &nulval, array, &anynul, &status); delete [] inc; delete [] lpixel; delete [] fpixel; if (status != 0) { return FORMAT_STATUS(status); } // close the FITS image file fits_close_file(fptr, &status); if (status != 0) { return FORMAT_STATUS(status); } return "READ_OK"; }
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; }
// getImageToArray: extract a sub-section from an image HDU, return array void *getImageToArray(fitsfile *fptr, int *dims, double *cens, char *slice, int *odim1, int *odim2, int *bitpix, int *status){ int i, naxis; int xcen, ycen, dim1, dim2, type; int tstatus = 0; int doscale = 0; void *obuf; long totpix, totbytes; long naxes[IDIM], fpixel[IDIM], lpixel[IDIM], inc[IDIM]; double bscale = 1.0; double bzero = 0.0; char comment[81]; char *s, *tslice; int nslice, idx, iaxis0, iaxis1; int iaxes[2] = {0, 1}; int saxes[IDIM] = {0, 0, 0, 0}; // seed buffers for(i=0; i<IDIM; i++){ naxes[i] = 0; fpixel[i] = 1; lpixel[i] = 1; inc[i] = 1; } // get image dimensions and type fits_get_img_dim(fptr, &naxis, status); fits_get_img_size(fptr, min(IDIM,naxis), naxes, status); fits_get_img_type(fptr, bitpix, status); if( naxis < 2 ){ *status = BAD_DIMEN; return NULL; } // parse slice string into primary axes and slice axes if( slice && *slice ){ tslice = (char *)strdup(slice); for(s=(char *)strtok(tslice, " :,"), nslice=0, idx=0; (s != NULL) && (nslice < IDIM); s=(char *)strtok(NULL," :,"), nslice++){ if( !strcmp(s, "*") ){ if( idx < 2 ){ iaxes[idx++] = nslice; } } else { saxes[nslice] = atoi(s); if( (saxes[nslice] < 1) || (saxes[nslice] > naxes[nslice]) ){ *status = SEEK_ERROR; return NULL; } } } free(tslice); } // convenience variables for the primary axis indexes iaxis0 = iaxes[0]; iaxis1 = iaxes[1]; // get limits of extracted section if( dims && dims[0] && dims[1] ){ dim1 = min(dims[0], naxes[iaxis0]); dim2 = min(dims[1], naxes[iaxis1]); // read image section if( cens ){ xcen = cens[0]; ycen = cens[1]; } else { xcen = dim1/2; ycen = dim2/2; } fpixel[iaxis0] = (int)(xcen - (dim1+1)/2); fpixel[iaxis1] = (int)(ycen - (dim2+1)/2); lpixel[iaxis0] = (int)(xcen + (dim1/2)); lpixel[iaxis1] = (int)(ycen + (dim2/2)); } else { // read entire image fpixel[iaxis0] = 1; fpixel[iaxis1] = 1; lpixel[iaxis0] = naxes[iaxis0]; lpixel[iaxis1] = naxes[iaxis1]; } // stay within image limits fpixel[iaxis0] = max(fpixel[iaxis0], 1); fpixel[iaxis0] = min(fpixel[iaxis0], naxes[iaxis0]); lpixel[iaxis0] = max(lpixel[iaxis0], 1); lpixel[iaxis0] = min(lpixel[iaxis0], naxes[iaxis0]); fpixel[iaxis1] = max(fpixel[iaxis1], 1); fpixel[iaxis1] = min(fpixel[iaxis1], naxes[iaxis0]); lpixel[iaxis1] = max(lpixel[iaxis1], 1); lpixel[iaxis1] = min(lpixel[iaxis1], naxes[iaxis0]); // for sliced dimensions, set first and last pixel to the specified slice for(i=0; i<min(IDIM,naxis); i++){ if( saxes[i] ){ // 1 pixel slice in this dimension fpixel[i] = saxes[i]; lpixel[i] = saxes[i]; // stay within image limits fpixel[i] = max(fpixel[i], 1); fpixel[i] = min(fpixel[i], naxes[i]); lpixel[i] = max(lpixel[i], 1); lpixel[i] = min(lpixel[i], naxes[i]); } } // section dimensions *odim1 = lpixel[iaxis0] - fpixel[iaxis0] + 1; *odim2 = lpixel[iaxis1] - fpixel[iaxis1] + 1; totpix = *odim1 * *odim2; // make sure we have an image with valid dimensions size if( totpix <= 1 ){ *status = NEG_AXIS; return NULL; } // are we scaling? fits_read_key(fptr, TDOUBLE, "BSCALE", &bscale, comment, &tstatus); if( tstatus != VALUE_UNDEFINED ){ fits_read_key(fptr, TDOUBLE, "BZERO", &bzero, comment, &tstatus); } if( (bscale != 1.0) || (bzero != 0.0) ){ doscale = 1; } // allocate space for the pixel array switch(*bitpix){ case 8: if( doscale ){ // scaled data has to be float *bitpix = -32; type = TFLOAT; totbytes = totpix * sizeof(float); } else { type = TBYTE; totbytes = totpix * sizeof(char); } break; case 16: if( doscale ){ // scaled data has to be float *bitpix = -32; type = TFLOAT; totbytes = totpix * sizeof(float); } else { type = TSHORT; totbytes = totpix * sizeof(short); } break; case -16: if( doscale ){ // scaled data has to be float *bitpix = -32; type = TFLOAT; totbytes = totpix * sizeof(float); } else { type = TUSHORT; totbytes = totpix * sizeof(unsigned short); } break; case 32: if( doscale ){ // scaled data has to be float *bitpix = -32; type = TFLOAT; totbytes = totpix * sizeof(float); } else { type = TINT; totbytes = totpix * sizeof(int); } break; case 64: if( doscale ){ // scaled data has to be float *bitpix = -32; type = TFLOAT; totbytes = totpix * sizeof(float); } else { type = TLONGLONG; totbytes = totpix * sizeof(long long); } break; case -32: type = TFLOAT; totbytes = totpix * sizeof(float); break; case -64: type = TDOUBLE; totbytes = totpix * sizeof(double); break; default: return NULL; } #if EM // sanity check on memory limits if( totbytes > max_memory ){ *status = MEMORY_ALLOCATION; return NULL; } #endif // try to allocate that much memory if(!(obuf = (void *)malloc(totbytes))){ *status = MEMORY_ALLOCATION; return NULL; } /* read the image section */ fits_read_subset(fptr, type, fpixel, lpixel, inc, 0, obuf, 0, status); // return pixel buffer (and section dimensions) return obuf; }