void writefits(int im, inputPars *par, molData *m, image *img){ double bscale,bzero,epoch,lonpole,equinox,restfreq; double cdelt1,crpix1,crval1,cdelt2,crpix2,crval2; double cdelt3,crpix3,crval3,ru3; int velref; float *row; int px,py,ichan; fitsfile *fptr; int status = 0; int naxis=3, bitpix=-32; long naxes[3]; long int fpixels[3],lpixels[3]; char negfile[100]="! "; row = malloc(sizeof(*row)*img[im].pxls); naxes[0]=img[im].pxls; naxes[1]=img[im].pxls; if(img[im].doline==1) naxes[2]=img[im].nchan; else if(img[im].doline==0 && par->polarization) naxes[2]=3; else naxes[2]=1; fits_create_file(&fptr, img[im].filename, &status); if(status!=0){ if(!silent) warning("Overwriting existing fits file "); status=0; strcat(negfile,img[im].filename); fits_create_file(&fptr, negfile, &status); } /* Write FITS header */ fits_create_img(fptr, bitpix, naxis, naxes, &status); epoch =2.0e3; lonpole =1.8e2; equinox =2.0e3; restfreq=img[im].freq; velref =257; cdelt1 =-1.8e2*img[im].imgres/PI; crpix1 =(double) img[im].pxls/2+0.5; crval1 =0.0e0; cdelt2 =1.8e2*img[im].imgres/PI; crpix2 =(double) img[im].pxls/2+0.5; crval2 =0.0e0; cdelt3 =img[im].velres; crpix3 =(double) (img[im].nchan-1)/2.+1; crval3 =0.0e0; bscale =1.0e0; bzero =0.0e0; fits_write_key(fptr, TSTRING, "OBJECT ", &"LIMEMDL ", "", &status); fits_write_key(fptr, TDOUBLE, "EPOCH ", &epoch, "", &status); fits_write_key(fptr, TDOUBLE, "LONPOLE ", &lonpole, "", &status); fits_write_key(fptr, TDOUBLE, "EQUINOX ", &equinox, "", &status); fits_write_key(fptr, TSTRING, "SPECSYS ", &"LSRK ", "", &status); fits_write_key(fptr, TDOUBLE, "RESTFREQ", &restfreq, "", &status); fits_write_key(fptr, TINT, "VELREF ", &velref, "", &status); fits_write_key(fptr, TSTRING, "CTYPE1 ", &"RA---SIN", "", &status); fits_write_key(fptr, TDOUBLE, "CDELT1 ", &cdelt1, "", &status); fits_write_key(fptr, TDOUBLE, "CRPIX1 ", &crpix1, "", &status); fits_write_key(fptr, TDOUBLE, "CRVAL1 ", &crval1, "", &status); fits_write_key(fptr, TSTRING, "CUNIT1 ", &"DEG ", "", &status); fits_write_key(fptr, TSTRING, "CTYPE2 ", &"DEC--SIN", "", &status); fits_write_key(fptr, TDOUBLE, "CDELT2 ", &cdelt2, "", &status); fits_write_key(fptr, TDOUBLE, "CRPIX2 ", &crpix2, "", &status); fits_write_key(fptr, TDOUBLE, "CRVAL2 ", &crval2, "", &status); fits_write_key(fptr, TSTRING, "CUNIT2 ", &"DEG ", "", &status); fits_write_key(fptr, TSTRING, "CTYPE3 ", &"VELO-LSR", "", &status); fits_write_key(fptr, TDOUBLE, "CDELT3 ", &cdelt3, "", &status); fits_write_key(fptr, TDOUBLE, "CRPIX3 ", &crpix3, "", &status); fits_write_key(fptr, TDOUBLE, "CRVAL3 ", &crval3, "", &status); fits_write_key(fptr, TSTRING, "CUNIT3 ", &"M/S ", "", &status); fits_write_key(fptr, TDOUBLE, "BSCALE ", &bscale, "", &status); fits_write_key(fptr, TDOUBLE, "BZERO ", &bzero, "", &status); if(img[im].unit==0) fits_write_key(fptr, TSTRING, "BUNIT", &"K ", "", &status); if(img[im].unit==1) fits_write_key(fptr, TSTRING, "BUNIT", &"JY/PIXEL", "", &status); if(img[im].unit==2) fits_write_key(fptr, TSTRING, "BUNIT", &"WM2HZSR ", "", &status); if(img[im].unit==3) fits_write_key(fptr, TSTRING, "BUNIT", &"Lsun/PX ", "", &status); if(img[im].unit==3) fits_write_key(fptr, TSTRING, "BUNIT", &" ", "", &status); /* Write FITS data */ for(py=0;py<img[im].pxls;py++){ for(ichan=0;ichan<img[im].nchan;ichan++){ for(px=0;px<img[im].pxls;px++){ if(img[im].unit==0) row[px]=(float) img[im].pixel[px+py*img[im].pxls].intense[ichan]*(CLIGHT/img[im].freq)*(CLIGHT/img[im].freq)/2./KBOLTZ*m[0].norm; else if(img[im].unit==1) row[px]=(float) img[im].pixel[px+py*img[im].pxls].intense[ichan]*1e26*img[im].imgres*img[im].imgres*m[0].norm; else if(img[im].unit==2) row[px]=(float) img[im].pixel[px+py*img[im].pxls].intense[ichan]*m[0].norm; else if(img[im].unit==3) { ru3 = img[im].distance/1.975e13; row[px]=(float) img[im].pixel[px+py*img[im].pxls].intense[ichan]*4.*PI*ru3*ru3*img[im].freq*img[im].imgres*img[im].imgres*m[0].norm; } else if(img[im].unit==4) row[px]=(float) img[im].pixel[px+py*img[im].pxls].tau[ichan]; else { if(!silent) bail_out("Image unit number invalid"); exit(0); } if (fabs(row[px])<(float) eps) row[px]=(float)eps; } fpixels[0]=1; fpixels[1]=py+1; fpixels[2]=ichan+1; lpixels[0]=img[im].pxls; lpixels[1]=py+1; lpixels[2]=ichan+1; fits_write_subset(fptr, TFLOAT, fpixels, lpixels, row, &status); } } fits_close_file(fptr, &status); free(row); if(!silent) done(13); }
std::string write_image_3D(std::string pathname_3D, float *array_2D_real, float *array_2D_imag, std::string name_3D, int naxis_2D, long *naxes_2D) { // this function writes a float array to a FITS image file TRACE_ENTER(); // create new file fitsfile *fptr; int status = 0; fits_create_file(&fptr, pathname_3D.c_str(), &status); if (status != 0) { // cannot create the file // likely, the file already exists // try to open it, delete it and create it anew // try to open the file status = 0; fits_open_file(&fptr, pathname_3D.c_str(), READWRITE, &status); if (status != 0) { // cannot open the file, for some reason return FORMAT_STATUS(status); } // try to delete the file status = 0; fits_delete_file(fptr, &status); if (status != 0) { // cannot delete the file, for some reason return FORMAT_STATUS(status); } // try to create the file status = 0; fits_create_file(&fptr, pathname_3D.c_str(), &status); if (status != 0) { // cannot create the file, for some reason return FORMAT_STATUS(status); } } // create the primary array image int naxis_3D = naxis_2D+1; long *naxes_3D = new long [naxis_3D]; for (int i = 0; i < naxis_2D; i++) { naxes_3D[i] = naxes_2D[i]; } naxes_3D[naxis_3D-1] = 2; fits_create_img(fptr, FLOAT_IMG, naxis_3D, naxes_3D, &status); if (status != 0) { return FORMAT_STATUS(status); } // write a keyword fits_update_key(fptr, TFLOAT, name_3D.c_str(), array_2D_real, name_3D.c_str(), &status); if (status != 0) { return FORMAT_STATUS(status); } // write the array of floats to the image long *fpixel = new long [naxis_3D]; fpixel[0] = 1; fpixel[1] = 1; fpixel[2] = 1; long *lpixel = new long [naxis_3D]; lpixel[0] = naxes_2D[0]; lpixel[1] = naxes_2D[1]; lpixel[2] = 1; fits_write_subset(fptr, TFLOAT, fpixel, lpixel, (void*)array_2D_real, &status); if (status != 0) { return FORMAT_STATUS(status); } // write a keyword fits_update_key(fptr, TFLOAT, name_3D.c_str(), array_2D_imag, name_3D.c_str(), &status); if (status != 0) { return FORMAT_STATUS(status); } // write the array of floats to the image fpixel[0] = 1; fpixel[1] = 1; fpixel[2] = 2; lpixel[0] = naxes_2D[0]; lpixel[1] = naxes_2D[1]; lpixel[2] = 2; fits_write_subset(fptr, TFLOAT, fpixel, lpixel, (void*)array_2D_imag, &status); if (status != 0) { return FORMAT_STATUS(status); } // close the file fits_close_file(fptr, &status); if (status != 0) { return FORMAT_STATUS(status); } return "WRITE_OK"; }
int main(int argc, char *argv[]) { char opt, *framename, *listname, *outname, *e_outname, buffer[BUFSIZ]; int n, row, col, cX, cY, npatch, npxi, npxt, nprof; int flag_autoname, flag_verbose, status, bitmask[YAR][XAR]; long xsize, ysize, lowleft[DIM], upright[DIM], increment[DIM] = {1L, 1L}, framesize[DIM]; float mask_val, cutoff, framefragment[YAR][XAR]; struct star* patchstars; FILE *listfile; fitsfile *frame, *maskedframe; extern char *optarg; extern int opterr; framename = NULL; listname = NULL; outname = NULL; mask_val = DEFAULT_MASK; cutoff = DEFAULT_CUTOFF; flag_autoname = 1; flag_verbose = 0; opterr = 0; while ((opt=getopt(argc, argv, "f:l:o:m:c:v")) != -1) { switch (opt) { case 'f': framename = optarg; break; case 'l': listname = optarg; break; case 'o': flag_autoname = 0; outname = optarg; break; case 'm': mask_val = atof(optarg); break; case 'c': cutoff = atof(optarg); break; case 'v': flag_verbose = 1; break; default: usage(argv); } } /* check mandatory parameters: */ if (framename == NULL || listname == NULL) usage(argv); if (cutoff < 0.0) { fprintf(stderr, " WARNING: invalid cut-off value (%.1f ADU), using default (%.1f ADU)\n", cutoff, DEFAULT_CUTOFF); cutoff = DEFAULT_CUTOFF; } /* read ID and coordinates from any single-lined Daophot output, detect and skip the header if necessary: */ if ((listfile=fopen(listname, "r")) == NULL) { file_read_error(listname); } else { npatch = line_count(listfile); if (has_daophot_header(listfile) == 1) { npatch -= DAO_HEADER_SIZE; line_skip(listfile, DAO_HEADER_SIZE); } if (npatch <= 0) { fclose(listfile); fprintf(stderr, " couldn't read contents of '%s', exiting.\n\n", listname); exit(EXIT_FAILURE); } patchstars = calloc(npatch, sizeof(struct star)); if (patchstars == NULL) { fclose(listfile); memory_error(); } for (n=0; n < npatch; n++) { fgets(buffer, BUFSIZ, listfile); sscanf(buffer, "%d %lf %lf", &patchstars[n].num, &patchstars[n].X, &patchstars[n].Y); } fclose(listfile); } status = 0; fits_open_file(&frame, framename, READONLY, &status); if (status != 0) { free(patchstars); file_read_error(framename); } fits_get_img_size(frame, DIM, framesize, &status); fits_print_error(status); xsize = framesize[0]; ysize = framesize[1]; printf(" %s: %ld x %ld pixels\n", framename, xsize, ysize); printf(" %s: %d stars in the list\n", listname, npatch); printf(" mask value: %.1f ADU\n", mask_val); printf(" cut-off level: %.1f ADU\n", cutoff); if (flag_autoname == 1) { outname = expand_filename(framename, "-msk", 0, 0); if (outname == NULL) { free(patchstars); fits_close_file(frame, &status); memory_error(); } } printf(" output file: %s\n", outname); /* force cfitsio to overwrite already existing file (prepend ! to the filename) */ e_outname = prepend_bang(outname); if (e_outname == NULL) { free(patchstars); fits_close_file(frame, &status); memory_error(); } /* create output (masked) frame: */ fits_create_file(&maskedframe, e_outname, &status); fits_print_error(status); free(e_outname); if (flag_autoname == 1) /* only necessary if outname was created automatically */ free(outname); fits_copy_file(frame, maskedframe, 1, 1, 1, &status); fits_print_error(status); npxt = 0; nprof = 0; /* process the stars in the list: */ for (n=0; n < npatch; n++) { if (flag_verbose == 1) printf("\n star #%d:\n", patchstars[n].num); /* cfitsio doesn't understand fractional pixels, round the coordinates to nearest integer: */ cX = rint(patchstars[n].X); cY = rint(patchstars[n].Y); /* make sure center is in the picture, skip this star if it is not: */ if (cX < 1 || cY < 1 || cX > xsize || cY > ysize) { printf(" star #%d is outside the frame (%d,%d), skipping.\n", patchstars[n].num, cX, cY); continue; } /* * in fitsio pixel index runs from 1 to N, not from 0 to N-1. * consider XAR=21 (reading 10 pixels right and left from center), XSIZE=2044. * example 1: star with x=10. fitsio will reach and try to read pixel at x=0, ILLEGAL. * example 2: star with x=2034. fitsio will reach and try to read pixel at x=2044, LEGAL. * we have to use LESS OR EQUAL when checking lower and left boundary, * for upper and right boundary only using GREATER is fine */ else if (cX <= (XAR-1)/2 || cY <= (YAR-1)/2 || cX > xsize-(XAR-1)/2 || cY > ysize-(YAR-1)/2) { printf(" star #%d is too close to the edge or partially outside the frame (%d,%d), skipping.\n", patchstars[n].num, cX, cY); continue; } if (flag_verbose == 1) printf(" coordinates of star #%d center in current frame: (%d,%d)\n", patchstars[n].num, cX, cY); /* compute the coordinates of lower left and upper right pixel: */ lowleft[0] = cX - (XAR-1)/2; lowleft[1] = cY - (YAR-1)/2; upright[0] = cX + (XAR-1)/2; upright[1] = cY + (YAR-1)/2; /* load frame fragment with the star into table: */ fits_read_subset(frame, TFLOAT, lowleft, upright, increment, 0, framefragment, 0, &status); fits_print_error(status); /* initialise the bitmask with zeros: */ for (row=0; row < YAR; row++) for (col=0; col < XAR; col++) bitmask[row][col] = 0; /* detect holes and write to bitmask: */ for (row=YAR-1; row >= 0; row--) examine_row(framefragment, bitmask, row, cutoff); for (col=0; col < XAR; col++) examine_col(framefragment, bitmask, col, cutoff); npxi = apply_bitmask(framefragment, bitmask, mask_val); npxt += npxi; if (npxi > 0) ++nprof; if (flag_verbose == 1) { printf("\n"); print_bitmask(bitmask); printf("\n star %d: %d pixels masked\n", patchstars[n].num, npxi); } /* write the modified frame subsection to output frame: */ fits_write_subset(maskedframe, TFLOAT, lowleft, upright, framefragment, &status); fits_print_error(status); } printf(" %d pixels were masked in %d stars.\n", npxt, nprof); fits_close_file(frame, &status); fits_print_error(status); fits_close_file(maskedframe, &status); fits_print_error(status); free(patchstars); return 0; }
void write4Dfits(int im, int unit_index, configInfo *par, imageInfo *img){ /* Users have complained that downstream packages (produced by lazy coders >:8) will not deal with FITS cubes having less that 4 axes. Thus all LIME output images are now sent to the present function. */ const int numAxes=4; double bscale,bzero,epoch,lonpole,equinox,restfreq; int axesOrder[] = {0,1,2,3}; char ctype[numAxes][9],cunit[numAxes][9]; double crpix[numAxes],crval[numAxes]; float cdelt[numAxes]; double ru3,scale=1.0; int velref,unitI,i; float *row; int px,py,ichan; fitsfile *fptr; int status = 0; int naxis=numAxes, bitpix=-32; long naxes[numAxes]; long int fpixels[numAxes],lpixels[numAxes]; char negfile[100]="! ",message[STR_LEN_0]; unsigned long ppi; unitI = img[im].imgunits[unit_index]; row = malloc(sizeof(*row)*img[im].pxls); naxes[axesOrder[0]] = img[im].pxls; naxes[axesOrder[1]] = img[im].pxls; if(img[im].doline) naxes[axesOrder[2]] = img[im].nchan; else naxes[axesOrder[2]] = 1; /* In this case nchan can =3, the number of active Stokes parameters, if the dust is polarized. */ if(!img[im].doline && par->polarization) naxes[axesOrder[3]]=4; else naxes[axesOrder[3]]=1; fits_create_file(&fptr, img[im].filename, &status); if(status!=0){ if(!silent) warning("Overwriting existing fits file "); status=0; strcat(negfile,img[im].filename); fits_create_file(&fptr, negfile, &status); } /* Write FITS header */ fits_create_img(fptr, bitpix, naxis, naxes, &status); epoch =2.0e3; lonpole =1.8e2; equinox =2.0e3; restfreq=img[im].freq; velref =257; sprintf(ctype[axesOrder[0]], "RA---SIN"); cdelt[axesOrder[0]] = -1.8e2*(float)(img[im].imgres/M_PI); crpix[axesOrder[0]] = ((double)img[im].pxls)/2.0 + 0.5; crval[axesOrder[0]] = 0.0e0; sprintf(cunit[axesOrder[0]], "DEG "); sprintf(ctype[axesOrder[1]], "DEC--SIN"); cdelt[axesOrder[1]] = 1.8e2*(float)(img[im].imgres/M_PI); crpix[axesOrder[1]] = ((double)img[im].pxls)/2.0 + 0.5; crval[axesOrder[1]] = 0.0e0; sprintf(cunit[axesOrder[1]], "DEG "); sprintf(ctype[axesOrder[2]], "VELO-LSR"); if(img[im].doline) cdelt[axesOrder[2]] = (float)img[im].velres; else cdelt[axesOrder[2]] = 1.0; crpix[axesOrder[2]] = (double) (naxes[axesOrder[2]]-1)/2.+1; crval[axesOrder[2]] = 0.0e0; sprintf(cunit[axesOrder[2]], "M/S "); sprintf(ctype[axesOrder[3]], "STOKES "); cdelt[axesOrder[3]] = 1.0; crpix[axesOrder[3]] = (double) (naxes[axesOrder[3]]-1)/2.+1; crval[axesOrder[3]] = 1.0e0; sprintf(cunit[axesOrder[3]], " "); bscale =1.0e0; bzero =0.0e0; fits_write_key(fptr, TSTRING, "OBJECT ", &"LIMEMDL ", "", &status); fits_write_key(fptr, TDOUBLE, "EPOCH ", &epoch, "", &status); fits_write_key(fptr, TDOUBLE, "LONPOLE ", &lonpole, "", &status); fits_write_key(fptr, TDOUBLE, "EQUINOX ", &equinox, "", &status); fits_write_key(fptr, TSTRING, "SPECSYS ", &"LSRK ", "", &status); fits_write_key(fptr, TDOUBLE, "RESTFREQ", &restfreq, "", &status); fits_write_key(fptr, TINT, "VELREF ", &velref, "", &status); for(i=0;i<numAxes;i++) writeWCS(fptr, i, axesOrder, cdelt, crpix, crval, ctype, cunit); fits_write_key(fptr, TDOUBLE, "BSCALE ", &bscale, "", &status); fits_write_key(fptr, TDOUBLE, "BZERO ", &bzero, "", &status); if(unitI==0) fits_write_key(fptr, TSTRING, "BUNIT", &"K ", "", &status); if(unitI==1) fits_write_key(fptr, TSTRING, "BUNIT", &"JY/PIXEL", "", &status); if(unitI==2) fits_write_key(fptr, TSTRING, "BUNIT", &"WM2HZSR ", "", &status); if(unitI==3) fits_write_key(fptr, TSTRING, "BUNIT", &"Lsun/PX ", "", &status); if(unitI==4) fits_write_key(fptr, TSTRING, "BUNIT", &" ", "", &status); if( unitI==0) scale=0.5*(CLIGHT/img[im].freq)*(CLIGHT/img[im].freq)/KBOLTZ; else if(unitI==1) scale=1e26*img[im].imgres*img[im].imgres; else if(unitI==2) scale=1.0; else if(unitI==3) { ru3 = img[im].distance/1.975e13; scale=4.*M_PI*ru3*ru3*img[im].freq*img[im].imgres*img[im].imgres; } else if(unitI!=4) { if(!silent) bail_out("Image unit number invalid"); exit(0); } /* Write FITS data */ if(img[im].doline){ for(ichan=0;ichan<img[im].nchan;ichan++){ for(py=0;py<img[im].pxls;py++){ for(px=0;px<img[im].pxls;px++){ ppi = py*img[im].pxls + px; if(unitI>-1 && unitI<4) row[px]=(float) img[im].pixel[ppi].intense[ichan]*scale; else if(unitI==4) row[px]=(float) img[im].pixel[ppi].tau[ichan]; else { if(!silent) bail_out("Image unit number invalid"); exit(0); } if (fabs(row[px])<IMG_MIN_ALLOWED) row[px]=IMG_MIN_ALLOWED; } fpixels[axesOrder[0]] = 1; fpixels[axesOrder[1]] = py+1; fpixels[axesOrder[2]] = ichan+1; fpixels[axesOrder[3]] = 1; lpixels[axesOrder[0]] = img[im].pxls; lpixels[axesOrder[1]] = py+1; lpixels[axesOrder[2]] = ichan+1; lpixels[axesOrder[3]] = 1; fits_write_subset(fptr, TFLOAT, fpixels, lpixels, row, &status); } } }else{ for(ichan=0;ichan<img[im].nchan;ichan++){ for(py=0;py<img[im].pxls;py++){ for(px=0;px<img[im].pxls;px++){ ppi = py*img[im].pxls + px; if(unitI>-1 && unitI<4) row[px]=(float) img[im].pixel[ppi].intense[ichan]*scale; else if(unitI==4) row[px]=(float) img[im].pixel[ppi].tau[ichan]; else { if(!silent) bail_out("Image unit number invalid"); exit(0); } if (fabs(row[px])<IMG_MIN_ALLOWED) row[px]=IMG_MIN_ALLOWED; } fpixels[axesOrder[0]] = 1; fpixels[axesOrder[1]] = py+1; fpixels[axesOrder[3]] = ichan+1; fpixels[axesOrder[2]] = 1; lpixels[axesOrder[0]] = img[im].pxls; lpixels[axesOrder[1]] = py+1; lpixels[axesOrder[3]] = ichan+1; lpixels[axesOrder[2]] = 1; fits_write_subset(fptr, TFLOAT, fpixels, lpixels, row, &status); } } if(par->polarization){ /* ichan should have run from 0 to 2 in this case. Stokes I, Q and U but no V. Load zeros into the last pol channel: */ if(img[im].nchan!=3){ if(!silent){ sprintf(message, "%d pol channels found but %d expected.", img[im].nchan, 3); bail_out(message); } exit(1); } ichan = 3; for(px=0;px<img[im].pxls;px++) row[px] = IMG_MIN_ALLOWED; for(py=0;py<img[im].pxls;py++){ fpixels[axesOrder[0]] = 1; fpixels[axesOrder[1]] = py+1; fpixels[axesOrder[3]] = ichan+1; fpixels[axesOrder[2]] = 1; lpixels[axesOrder[0]] = img[im].pxls; lpixels[axesOrder[1]] = py+1; lpixels[axesOrder[3]] = ichan+1; lpixels[axesOrder[2]] = 1; fits_write_subset(fptr, TFLOAT, fpixels, lpixels, row, &status); } } } fits_close_file(fptr, &status); free(row); }