Advertisement
Guest User

jediconvolve.c

a guest
Jan 13th, 2020
364
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 11.40 KB | None | 0 0
  1.  
  2.  * Compile     : gcc -Wall -O3 -o jediconvolve jediconvolve.c -lm -lcfitsio -lfftw3f
  3.  *
  4.  * Run         : ./jediconvolve out1/trial0_HST.fits psf/psf0.fits jedisim_out/out0/convolved/
  5.  *                executable    fitsfile_to_convolve convolving_psf   empty_folder_to_write_6_bands
  6.  
  7.  
  8.  */
  9.  
  10. #include <stdio.h>
  11. #include <string.h>
  12. #include <math.h>
  13. #include "fitsio.h"
  14. #include <fftw3.h>
  15.  
  16. #define BANDHEIGHT 2048
  17.  
  18. char *help[] = {
  19.     "Convolves an image with a specified PSF with a fourier-space convolution. The convolution is carried out in bands so that it can be performed on very large images.",
  20.     "usage: jediconvolve input_file PSF_file output_file",
  21.     "Arguments: input_file - FITS file to convolve",
  22.     "           PSF_file - the PSF with which to convolve",
  23.     "           output_folder - output folder for images",
  24.     0};
  25.  
  26. int main(int argc, char *argv[]){
  27.     //declare variables
  28.     char infile[1024], psffile[1024], outfolder[1024];
  29.  
  30.     //fits variables
  31.     fitsfile    *infptr, *psffptr, *outfptr;    //fits pointers for the input, psf, and output files
  32.     int         status = 0, naxis = 0;          //cfitsio status counter & image dimensionality
  33.     long int    inaxes[2], bnaxes[2], pnaxes[2], onaxes[2];    //dimensions of input image, band, PSF, and output image
  34.     long int    fpixel[2] = {1,1}, bpixel[2] = {1,1};//cfitsio first/last pixel to read in/out
  35.     long int    lpixel[2];
  36.     long int    inc[2] = {1,1};
  37.     float       *bimage, *pimage, *pimage2, *oimage; //arrays for the input, psf, resized psf, and  output images
  38.     int         num_bands, band;    //number of bands, and counter for the current band
  39.     long int    row, col;           //counters
  40.  
  41.     //print help
  42.     if(argc != 4){
  43.         int line;
  44.         for(line = 0; help[line] !=0; line++)
  45.             fprintf(stderr, "%s\n", help[line]);
  46.         exit(1);
  47.     }
  48.  
  49.     //parse command line input
  50.     sscanf(argv[1], "%s", infile);
  51.     sscanf(argv[2], "%s", psffile);
  52.     sscanf(argv[3], "%s", outfolder);
  53.  
  54.     //open input image
  55.     //fprintf(stdout,"Getting size of the input image.\n");
  56.     fits_open_file(&infptr, infile, READONLY, &status);
  57.     fits_get_img_dim(infptr, &naxis, &status);
  58.     fits_get_img_size(infptr, 2, inaxes, &status);
  59.     if(status){
  60.         fits_report_error(stderr,status);
  61.         exit(1);
  62.     }
  63.     //fprintf(stdout,"Input image has size: (%li, %li).\n", inaxes[0], inaxes[1]);
  64.  
  65.     //read in the PSF image
  66.     //fprintf(stdout,"Reading in PSF.\n");
  67.     fits_open_file(&psffptr, psffile, READONLY, &status);
  68.     fits_get_img_dim(psffptr, &naxis, &status);
  69.     fits_get_img_size(psffptr, 2, pnaxes, &status);
  70.     if(status){
  71.         fits_report_error(stderr, status);
  72.         exit(1);
  73.     }
  74.  
  75.     //allocate enough memory for the PSF
  76.     pimage = (float *) calloc (pnaxes[0]*pnaxes[1], sizeof(float));
  77.     if (pimage == NULL){
  78.         fprintf(stderr, "Error allocating memory for psf.\n");
  79.         exit(1);
  80.     }
  81.  
  82.     //read the PSF pixels
  83.     if(fits_read_pix(psffptr, TFLOAT, fpixel, pnaxes[0]*pnaxes[1], NULL, pimage, NULL, &status)){
  84.         fprintf(stderr, "Can't read in image.\n");
  85.         fits_report_error(stderr, status);
  86.         exit(1);
  87.     }
  88.     fits_close_file(psffptr, &status);
  89.     if(status){
  90.         fprintf(stderr, "Error reading PSF file.\n");
  91.         fits_report_error(stderr, status);
  92.         exit(1);
  93.     }
  94.  
  95.  
  96.     //the bnaxes array specifies the dimension of one band of the input image
  97.     bnaxes[0] = inaxes[0];
  98.     bnaxes[1] = BANDHEIGHT;
  99.  
  100.     //the onaxes array specifies the dimension of one band of the output image
  101.     //we need to put a border the size of the PSF around the band
  102.     onaxes[0] = inaxes[0]+2*pnaxes[0];
  103.     onaxes[1] = BANDHEIGHT+2*pnaxes[1];
  104.     //fprintf(stdout,"Band shape: (%li, %li).\n",bnaxes[0],bnaxes[1]);
  105.     //fprintf(stdout,"Output image shape: (%li, %li).\n", onaxes[0],onaxes[1]);
  106.     num_bands = inaxes[1]/bnaxes[1];
  107.  
  108.     //the last pixel we want to read in for the first band
  109.     lpixel[0] = inaxes[0];
  110.     lpixel[1] = BANDHEIGHT;
  111.  
  112.     //fprintf(stdout,"Resizing and wrapping PSF.\n");
  113.     pimage2 = (float *) calloc(onaxes[0]*onaxes[1], sizeof(float));
  114.     if(pimage2 == NULL){
  115.         fprintf(stderr, "Error: could not allocate memory for PSF image 2.\n");
  116.         exit(1);
  117.     }
  118.  
  119.     //make PSF with the center pixel of the PSF at (0,0) and wrap around to the other sides
  120.     //also change to row-major order
  121.     for(row = 0; row < pnaxes[0]; row++){
  122.         for(col = 0; col < pnaxes[1]; col++){
  123.             //place in the new PSF array
  124.             int new_row = (row - pnaxes[0]/2 + onaxes[0]) % onaxes[0];
  125.             int new_col = (col - pnaxes[1]/2 + onaxes[1]) % onaxes[1];
  126.             pimage2[new_row*onaxes[1]+new_col] = pimage[col*pnaxes[0]+row];
  127.         }
  128.     }
  129.     //we don't need the old PSF array, so throw it away to save some memory
  130.     free(pimage);
  131.  
  132.  
  133.     //allocate memory to read in the one band
  134.     bimage = (float *) calloc(bnaxes[0]*bnaxes[1], sizeof(float));
  135.     if(bimage == NULL){
  136.         fprintf(stderr, "Error allocating memory for band.\n");
  137.         exit(1);
  138.     }
  139.  
  140.     //allocate memory so there's a place to put one band
  141.     oimage = (float *) calloc(onaxes[0]*onaxes[1], sizeof(float));
  142.     if(oimage == NULL){
  143.         fprintf(stderr, "Error allocating memory for output image.\n");
  144.         exit(1);
  145.     }
  146.  
  147.  
  148.     //arrays for the input and output images in row-major order for FFTW3
  149.     float *IMG, *OUT;
  150.     IMG = (float *) calloc(onaxes[0]*onaxes[1], sizeof(float));
  151.     if(IMG == NULL){
  152.         fprintf(stderr,"Error allocating memory for FFTW3 input image.\n");
  153.         exit(1);
  154.     }
  155.     OUT = (float *) calloc(onaxes[0]*onaxes[1], sizeof(float));
  156.     if(OUT == NULL){
  157.         fprintf(stderr,"Error allocating memory for FFTW3 input image.\n");
  158.         exit(1);
  159.     }
  160.  
  161.  
  162.  
  163.  
  164.     //fprintf(stdout,"Setting up FFT.\n");
  165.     float   scale = 1.0/(onaxes[0]*onaxes[1]); //scaling factor for convolution
  166.  
  167.     //make arrays for the transformed input, PSF, and output images
  168.     fftwf_complex *FIMG, *FPSF, *FOUT;
  169.  
  170.     //make FFTW3 plans for transforming them
  171.     fftwf_plan pIMG, pPSF, pinv;
  172.  
  173.     //since this is a real-to-complex fourier transform, we don't need one complex number
  174.     //for every pixel in the input array, but only about half that many
  175.     long int    fcol = (onaxes[1]/2)+1;
  176.  
  177.     //allocate memory for the transformed images.
  178.     //I think FFTW3 will give an error message if they can't be allocated
  179.     //I'm also pretty sure that they shouldn't be de-allocated, because the FFTW3
  180.     //plan depends on where exactly in memory they're stored
  181.     FIMG = (fftwf_complex *) fftwf_malloc(onaxes[0]*fcol*sizeof(fftwf_complex));
  182.     FPSF = (fftwf_complex *) fftwf_malloc(onaxes[0]*fcol*sizeof(fftwf_complex));
  183.     FOUT = (fftwf_complex *) fftwf_malloc(onaxes[0]*fcol*sizeof(fftwf_complex));
  184.  
  185.     //make the FFTW3 plans
  186.     pIMG = fftwf_plan_dft_r2c_2d(onaxes[0], onaxes[1], IMG, FIMG, FFTW_ESTIMATE);
  187.     pPSF = fftwf_plan_dft_r2c_2d(onaxes[0], onaxes[1], pimage2, FPSF, FFTW_ESTIMATE);
  188.     pinv = fftwf_plan_dft_c2r_2d(onaxes[0], onaxes[1], FOUT, OUT, FFTW_ESTIMATE);
  189.  
  190.     //transform the PSF because it's transform is the same for all bands
  191.     //fprintf(stdout,"Taking the FFT of the PSF.\n");
  192.     fftwf_execute(pPSF);
  193.  
  194.     //we don't need the un-transformed PSF array anymore, so save some memory and get rid of it
  195.     free(pimage2);
  196.  
  197.     //loop over all the bands
  198.     for(band = 0; band < num_bands; band++){
  199.  
  200.         fprintf(stdout,"Band %i/%i: reading in image. Size: %.1fMB.\n", band+1, num_bands, (float) bnaxes[0]*bnaxes[1]*sizeof(float)/(1000*1000));
  201.  
  202.         //read in the band
  203.         //fprintf(stdout,"first: (%li, %li)\tlast:(%li, %li).\n", bpixel[0], bpixel[1], lpixel[0], lpixel[1]);
  204.         fits_read_subset(infptr, TFLOAT, bpixel, lpixel, inc, NULL, bimage, NULL, &status);
  205.         if(status){
  206.             fprintf(stderr, "Error: can't read in band %i/%i of the input image.\n",band, num_bands);
  207.             fits_report_error(stderr, status);
  208.             exit(1);
  209.         }
  210.  
  211.         //put image into row-major order
  212.         //fprintf(stdout,"Band %i/%i: transposing input to row-major order.\n",band+1,num_bands);
  213.         for(row = 0; row < bnaxes[0]; row++){
  214.             for(col = 0; col < bnaxes[1]; col++){
  215.                 long int col_m_index = row+col*bnaxes[0];
  216.                 long int row_m_index = (pnaxes[1] + col)+(row+pnaxes[0])*onaxes[1];
  217.                 IMG[row_m_index] = bimage[col_m_index];
  218.             }
  219.         }
  220.  
  221.         //transform the band
  222.         //fprintf(stdout,"Band %i/%i: taking FFT. \n", band+1, num_bands);
  223.         fftwf_execute(pIMG);
  224.  
  225.         //perform convolution by multiplying in fourier space
  226.         //fprintf(stdout,"Band %i/%i: convolving.\n",band+1,num_bands);
  227.         for(row = 0; row < onaxes[0]; row++){
  228.             for(col = 0; col < fcol; col++){
  229.                 long int index = row*fcol + col; //the row-major index
  230.                 //do complex multiplication and get the scale right
  231.                 FOUT[index][0] = scale*(FIMG[index][0] * FPSF[index][0] - FIMG[index][1] * FPSF[index][1]);
  232.                 FOUT[index][1] = scale*(FIMG[index][0] * FPSF[index][1] + FIMG[index][1] * FPSF[index][0]);
  233.             }
  234.         }
  235.  
  236.         //transform back
  237.         //fprintf(stdout,"Band %i/%i: taking inverse FFT.\n", band+1,num_bands);
  238.         fftwf_execute(pinv);
  239.  
  240.         //fprintf(stdout,"Band %i/%i: transposing back to column-major order.\n",band+1,num_bands);
  241.  
  242.         //put the output into column-major order
  243.         for(row = 0; row < onaxes[0]; row++){
  244.             for(col = 0; col < onaxes[1]; col++){
  245.                 long int col_m_index = row+col*onaxes[0];
  246.                 long int row_m_index = col+row*onaxes[1];
  247.                 oimage[col_m_index] = OUT[row_m_index];
  248.             }
  249.         }
  250.  
  251.         //write out the band to memory, each band as a separate file
  252.         //fprintf(stdout,"Band %i/%i: writing convolved band.\n",band+1,num_bands);
  253.         char outfile[1024];
  254.         char out1[1024];
  255.         strcpy(out1,"!");
  256.         sprintf(outfile,"%sconvolved_band_%i.fits",outfolder, band);
  257.         strcat(out1,outfile);
  258.         long int xembed = bpixel[0]-pnaxes[0]-1;
  259.         long int yembed = bpixel[1]-pnaxes[1]-1;
  260.         fits_create_file(&outfptr, out1, &status);
  261.         fits_create_img(outfptr, FLOAT_IMG, naxis, onaxes, &status);
  262.  
  263.         //keep track of where this band belongs so we can use jedipaste to recombine them
  264.         fits_update_key(outfptr, TLONG, "XEMBED", &xembed , "x pixel in target image to embed lower left pixel.", &status);
  265.         fits_update_key(outfptr, TLONG, "YEMBED", &yembed , "y pixel in target image to embed lower left pixel.", &status);
  266.         fits_write_pix(outfptr, TFLOAT, fpixel, onaxes[0]*onaxes[1], oimage, &status);
  267.         fits_close_file(outfptr, &status);
  268.  
  269.         //make sure nothing went wrong
  270.         if(status){
  271.             fprintf(stderr, "Error writing out band image.\n");
  272.             fits_report_error(stderr, status);
  273.             exit(1);
  274.         }
  275.  
  276.         //step up to the next band for CFITSIO
  277.         bpixel[1] += BANDHEIGHT;
  278.         lpixel[1] += BANDHEIGHT;
  279.     }
  280.  
  281.     //clean up
  282.     //fprintf(stdout,"Cleaning up.\n");
  283.  
  284.     fftwf_destroy_plan(pIMG);
  285.     fftwf_destroy_plan(pPSF);
  286.     fftwf_destroy_plan(pinv);
  287.  
  288.     fftwf_free(FIMG);
  289.     fftwf_free(FPSF);
  290.     fftwf_free(FOUT);
  291.  
  292.     return 0;
  293. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement