Ejemplo n.º 1
0
/**
 * L1 solver.
 *
 * Usage: 
 * xsol = sopt_solver_l1_mex(y, xsol, ny, nx, nr, A, At, Psi, Psit, ...
 *   Weights, Analysis, ...
 *   ParamMaxIter, ParamGamma, ParamRelObj, ...
 *   ParamEpsilon, ParamRealOut, ParamRealMeas, ...
 *   ParamL1ProxMaxIter, ParamL1ProxRelObj, ParamL1ProxNu, ...
 *   ParamL1ProxTight, ParamL1ProxPositivity, ...
 *   ParamL2BallMaxIter, ParamL2BallTol, ParamL2BallNu, ...
 *   ParamL2BallTight, ParamL2BallPositivity, ...
 *   ParamL2BallReality);
 */
void mexFunction( int nlhs, mxArray *plhs[],
                  int nrhs, const mxArray *prhs[])
{

  int i, j, iin, iout;

  int y_is_complex;
  double *y_real = NULL, *y_imag = NULL;
  double *yr = NULL;
  complex double *yc = NULL;
  int y_m, y_n;

  int xsol_is_complex;
  double *xsol_real = NULL, *xsol_imag = NULL;
  double *xsolr = NULL;
  complex double *xsolc = NULL;
  int xsol_m, xsol_n;




  // Check number of arguments. 
  if (nrhs != 28) {
    mexErrMsgIdAndTxt("sopt_solver_l1_mex:InvalidInput:nrhs",
          "Require 28 inputs.");
  }
  if (nlhs != 1) {
    mexErrMsgIdAndTxt("sopt_solver_l1_mex:InvalidOutput:nlhs",
          "Require one output.");
  }

  // Parse y.
  iin = 0;
  y_m = mxGetM(prhs[iin]);
  y_n = mxGetN(prhs[iin]);  
  if (!mxIsDouble(prhs[iin]) || (y_m != 1 && y_n != 1))
    mexErrMsgIdAndTxt("sopt_solver_l1_mex:InvalidInput:y",
          "y must be double array.");
  y_real = mxGetPr(prhs[iin]);  
  y_is_complex = mxIsComplex(prhs[iin]);
  y_imag = y_is_complex ? mxGetPi(prhs[iin]) : NULL;
  if (!y_is_complex) {
    yr = (double*)malloc(y_m * y_n * sizeof(double));
    for(i=0; i<y_m; i++)
      for(j=0; j<y_n; j++)
        yr[i*y_n + j] = y_real[i*y_n + j];
  }
  else {
    yc = (complex double*)malloc(y_m * y_n * sizeof(complex double));
    for(i=0; i<y_m; i++)
      for(j=0; j<y_n; j++)
        yc[i*y_n + j] = y_real[i*y_n + j]        
          + I * (y_is_complex ? y_imag[i*y_n + j] : 0.0);
  }

  // Parse xsol.
  iin = 1;
  xsol_m = mxGetM(prhs[iin]);
  xsol_n = mxGetN(prhs[iin]);  
  if (!mxIsDouble(prhs[iin]) || (xsol_m != 1 && xsol_n != 1))
    mexErrMsgIdAndTxt("sopt_solver_l1_mex:InvalidInput:xsol",
          "xsol must be double array.");
  xsol_real = mxGetPr(prhs[iin]);  
  xsol_is_complex = mxIsComplex(prhs[iin]);
  xsol_imag = xsol_is_complex ? mxGetPi(prhs[iin]) : NULL;
  if (!xsol_is_complex) {
    xsolr = (double*)malloc(xsol_m * xsol_n * sizeof(double));
    for(i=0; i<xsol_m; i++)
      for(j=0; j<xsol_n; j++)
        xsolr[i*xsol_n + j] = xsol_real[i*xsol_n + j];
  }
  else {
    xsolc = (complex double*)malloc(xsol_m * xsol_n * sizeof(complex double));
    for(i=0; i<xsol_m; i++)
      for(j=0; j<xsol_n; j++)
        xsolc[i*xsol_n + j] = xsol_real[i*xsol_n + j]        
          + I * (xsol_is_complex ? xsol_imag[i*xsol_n + j] : 0.0);
  }



  // if (f_is_complex && reality)
  //   mexWarnMsgTxt("Running real transform but input appears to be complex (ignoring imaginary component).");
  // if (!f_is_complex && !reality)
  //   mexWarnMsgTxt("Running complex transform on real signal (set reality flag to improve performance).");


    double *xout;
    double *error;
    double *y0;
    double *y;
    double *noise;
    double *w;



    void *datam[1];
    void *datas[1];

    int flag;
    double sigma;
    double a;
    double mse;
    double snr;

    int Nx, Ny, Nr;
    int seedn=54;
    int seedmat;

    Nx=256*256;
    Ny=(int)(0.5*Nx);
    Nr=1*Nx;
    
    xout = (double*)malloc((Nx) * sizeof(double));
    SOPT_ERROR_MEM_ALLOC_CHECK(xout);
    error = (double*)malloc((Nx) * sizeof(double));
    SOPT_ERROR_MEM_ALLOC_CHECK(error);
    y = (double*)malloc((Ny) * sizeof(double));
    SOPT_ERROR_MEM_ALLOC_CHECK(y);
    y0 = (double*)malloc((Ny) * sizeof(double));
    SOPT_ERROR_MEM_ALLOC_CHECK(y0);
    noise = (double*)malloc((Ny) * sizeof(double));
    SOPT_ERROR_MEM_ALLOC_CHECK(noise);
    w = (double*)malloc((Nr) * sizeof(double));
    SOPT_ERROR_MEM_ALLOC_CHECK(w);

    //Measurement operator initialization
    //Structure for the measurement operator
    sopt_meas_usparam param1;
    param1.nmeas = Ny;
    param1.nx = Nx;
    param1.real_flag = 1;


    seedmat = 234;

    
    param1.perm = (int*)malloc( param1.nmeas * sizeof(int));
    SOPT_ERROR_MEM_ALLOC_CHECK(param1.perm);



    flag = sopt_ran_knuthshuffle(param1.perm, param1.nmeas, param1.nx, seedmat);
    //Check random permutation.
    if (flag!=0) {
        SOPT_ERROR_GENERIC("Could not generate the permutation");
    }

    //Data cast for the measurement operator
    datam[0] = (void*)&param1;
    
    //Measurement operator
    sopt_meas_urandsamp((void*)y0, (void*)yr, datam);
    
    //Noise realization
    //Input snr
    snr = 30.0;
    a = cblas_dnrm2(Ny, y0, 1)/sqrt(Ny);
    sigma = a*pow(10.0,-(snr/20.0));
    
    for (i=0; i < Ny; i++) {
        noise[i] = sigma*sopt_ran_gasdev2(seedn);
        y[i] = y0[i] + noise[i];
    }

    
    //Backprojected image
    sopt_meas_urandsampadj((void*)xsolr, (void*)y, datam);


//     sopt_prox_tvparam param2;
    sopt_prox_l2bparam param3;    
//     sopt_tv_param param4;


// //Structure for the TV prox
//     param2.verbose = 1;
//     param2.max_iter = 50;
//     param2.rel_obj = 0.0001;

    //Structure for the l2 ball prox
    param3.verbose = 1;
    param3.max_iter = 50;
    param3.tol = 0.001;
    param3.nu = 1;
    param3.tight = 1;
    param3.pos = 1;
    param3.real = 0;
    

//     //Structure for the TV solver    
//     param4.verbose = 2;
//     param4.max_iter = 200;
//     param4.gamma = 0.1;
//     param4.rel_obj = 0.0005;
//     param4.epsilon = sqrt(Ny + 2*sqrt(Ny))*sigma;
//     param4.real_out = 1;
//     param4.real_meas = 1;
//     param4.paramtv = param2;
//     param4.paraml2b = param3;

//     //Initial solution for TV reconstruction
//     for (i=0; i < Nx; i++) {
//         xsolr[i] = 0.0;
//     }

//     sopt_tv_solver((void*)xsolr, 256, 256,
//                    &sopt_meas_urandsamp,
//                    datam,
//                    &sopt_meas_urandsampadj,
//                    datam,
//                    (void*)y, Ny, param4);


    sopt_wavelet_type *dict_types;
    sopt_sara_param param5;
    sopt_prox_l1param param6;
    sopt_l1_param param7;
    

    param5.ndict = 1;
    param5.real = 1;

    dict_types = malloc(param5.ndict * sizeof(sopt_wavelet_type));
    SOPT_ERROR_MEM_ALLOC_CHECK(dict_types);


    dict_types[0] = SOPT_WAVELET_DB8;


    sopt_sara_initop(&param5, 256, 256, 4, dict_types);

    datas[0] = (void*)&param5;

    //Structure for the L1 prox
    param6.verbose = 1;
    param6.max_iter = 50;
    param6.rel_obj = 0.01;
    param6.nu = 1;
    param6.tight = 1;
    param6.pos = 0;
    
    //Structure for the L1 solver    
    param7.verbose = 2;
    param7.max_iter = 200;
    param7.gamma = 0.1;
    param7.rel_obj = 0.0005;
    param7.epsilon = sqrt(Ny + 2*sqrt(Ny))*sigma;
    param7.real_out = 1;
    param7.real_meas = 1;
    param7.paraml1 = param6;
    param7.paraml2b = param3;
    
   
    //Weights
    for (i=0; i < Nr; i++) {
        w[i] = 1.0;
    }

    //Initial solution for L1 recosntruction
    for (i=0; i < Nx; i++) {
        xsolr[i] = 0.0;
    }

    sopt_l1_solver((void*)xsolr, Nx,
                   &sopt_meas_urandsamp,
                   datam,
                   &sopt_meas_urandsampadj,
                   datam,
                   &sopt_sara_synthesisop,
                   datas,
                   &sopt_sara_analysisop,
                   datas,
                   Nr,
                   (void*)y, Ny, w, param7);









  // Copy xsol to output.  
  iout = 0;
  if (!xsol_is_complex) {
    plhs[iout] = mxCreateDoubleMatrix(xsol_m * xsol_n, 1, mxREAL);
    xsol_real = mxGetPr(plhs[iout]);    
    for(i=0; i<xsol_m; i++)
      for(j=0; j<xsol_n; j++)
        xsol_real[i*xsol_n + j] = xsolr[i*xsol_n + j];
  }
  else {
    plhs[iout] = mxCreateDoubleMatrix(xsol_m * xsol_n, 1, mxCOMPLEX);
    xsol_real = mxGetPr(plhs[iout]);
    xsol_imag = mxGetPi(plhs[iout]);
    for(i=0; i<xsol_m; i++)
      for(j=0; j<xsol_n; j++) {
        xsol_real[i*xsol_n + j] = creal(xsolc[i*xsol_n + j]);
        xsol_imag[i*xsol_n + j] = cimag(xsolc[i*xsol_n + j]);
      }
  }

  // Free memory. 
  if (!y_is_complex)
    free(yr);
  else
    free(yc);
  if (!xsol_is_complex)
    free(xsolr);
  else
    free(xsolc);







    free(xout);
    free(y);
    free(y0);
    free(noise);
    free(error);
    free(w);
    free(param1.perm);

    free(dict_types);
    sopt_sara_free(&param5);
    



}
Ejemplo n.º 2
0
int main(int argc, char *argv[]) {
  
    int dim1;
    int dim2;
    int Nx;
    int Ny;
    int Nr;
    int seedn=54;
    int seedmat;
    int flag;
    double sigma;
    double a;
    double mse;
    double snr;
    
    
    int i;

    clock_t start, stop;
    double t = 0.0;

    //Structures for the different operators
    
    sopt_meas_usparam param1;
    sopt_prox_tvparam param2;
    sopt_prox_l2bparam param3;
    sopt_tv_param param4;
    sopt_wavelet_type *dict_types;
    sopt_sara_param param5;
    sopt_prox_l1param param6;
    sopt_l1_param param7;
    

    void *datam[1];
    void *datas[1];
    
    
    double *xin;
    double *xout;
    double *error;
    double *y0;
    double *y;
    double *noise;
    double *w;
    

    double scale = 1.0/255.0, offset = 0.0;
    int fail = 0;

    printf("**********************\n");
    printf("Inpainting demo\n");
    printf("**********************\n");
  
    //Read input image
    fail = spot_image_tiff_read(&xin, &dim2, &dim1, "images/cameraman256.tiff", scale, offset);
    if(fail == 1)
      SOPT_ERROR_GENERIC("Error reading image");
    
    
    Nx=dim1*dim2;
    Ny=(int)(0.5*Nx);
    Nr=Nx;
    
    
    xout = (double*)malloc((Nx) * sizeof(double));
    SOPT_ERROR_MEM_ALLOC_CHECK(xout);
    error = (double*)malloc((Nx) * sizeof(double));
    SOPT_ERROR_MEM_ALLOC_CHECK(error);
    y = (double*)malloc((Ny) * sizeof(double));
    SOPT_ERROR_MEM_ALLOC_CHECK(y);
    y0 = (double*)malloc((Ny) * sizeof(double));
    SOPT_ERROR_MEM_ALLOC_CHECK(y0);
    noise = (double*)malloc((Ny) * sizeof(double));
    SOPT_ERROR_MEM_ALLOC_CHECK(noise);
    w = (double*)malloc((Nr) * sizeof(double));
    SOPT_ERROR_MEM_ALLOC_CHECK(w);


    //Measurement operator initialization
    //Structure for the measurement operator
    param1.nmeas = Ny;
    param1.nx = Nx;
    param1.real_flag = 1;


    seedmat = 234;

    param1.perm = (int*)malloc( param1.nmeas * sizeof(int));
    SOPT_ERROR_MEM_ALLOC_CHECK(param1.perm);
    
    flag = sopt_ran_knuthshuffle(param1.perm, param1.nmeas, param1.nx, seedmat);
    //Check random permutation.
    if (flag!=0) {
        SOPT_ERROR_GENERIC("Could not generate the permutation");
    }

    //Data cast for the measurement operator
    datam[0] = (void*)&param1;
    
    //Measurement operator
    sopt_meas_urandsamp((void*)y0, (void*)xin, datam);
    
    //Noise realization
    //Input snr
    snr = 30.0;
    a = cblas_dnrm2(Ny, y0, 1)/sqrt(Ny);
    sigma = a*pow(10.0,-(snr/20.0));
    
    for (i=0; i < Ny; i++) {
        noise[i] = sigma*sopt_ran_gasdev2(seedn);
        y[i] = y0[i] + noise[i];
    }

    
    //Backprojected image
    sopt_meas_urandsampadj((void*)xout, (void*)y, datam);

    //Write Dirty image
    fail = spot_image_tiff_write(xout, dim2, dim1, "images/cameraIP_Dirty.tiff", 1.0/scale, offset);
    if(fail == 1)
      SOPT_ERROR_GENERIC("Error writing image");

    //SNR
    for (i=0; i < Nx; i++) {
        error[i] = xout[i] - xin[i];
    }
    mse = cblas_dnrm2(Nx, error, 1);
    a = cblas_dnrm2(Nx, xin, 1);
    mse = 20.0*log10(a/mse);
    printf("Backprojected image SNR: %f dB\n\n", mse);

    
    printf("**********************\n");
    printf("TV reconstruction\n");
    printf("**********************\n");

    
    //Structure for the TV prox
    param2.verbose = 1;
    param2.max_iter = 50;
    param2.rel_obj = 0.0001;

    //Structure for the l2 ball prox
    param3.verbose = 1;
    param3.max_iter = 50;
    param3.tol = 0.001;
    param3.nu = 1;
    param3.tight = 1;
    param3.pos = 1;
    param3.real = 0;
    

    //Structure for the TV solver    
    param4.verbose = 2;
    param4.max_iter = 200;
    param4.gamma = 0.1;
    param4.rel_obj = 0.0005;
    param4.epsilon = sqrt(Ny + 2*sqrt(Ny))*sigma;
    param4.real_out = 1;
    param4.real_meas = 1;
    param4.paramtv = param2;
    param4.paraml2b = param3;

    //Initial solution for TV reconstruction
    for (i=0; i < Nx; i++) {
        xout[i] = 0.0;
    }

    assert((start = clock())!=-1);
    sopt_tv_solver((void*)xout, dim1, dim2,
                   &sopt_meas_urandsamp,
                   datam,
                   &sopt_meas_urandsampadj,
                   datam,
                   (void*)y, Ny, param4);
    stop = clock();
    t = (double) (stop-start)/CLOCKS_PER_SEC;
    
    printf("Time TV: %f \n\n", t); 

    //SNR
    for (i=0; i < Nx; i++) {
        error[i] = xout[i] - xin[i];
    }
    mse = cblas_dnrm2(Nx, error, 1);
    a = cblas_dnrm2(Nx, xin, 1);
    mse = 20.0*log10(a/mse);
    printf("SNR: %f dB\n\n", mse);

    fail = spot_image_tiff_write(xout, dim2, dim1, "images/cameraIP_TV.tiff", 1.0/scale, offset);
    if(fail == 1)
      SOPT_ERROR_GENERIC("Error writing image");

    printf("**********************************\n");
    printf("L1-Db8 reconstruction\n");
    printf("**********************************\n");

    //SARA structure initialization

    param5.ndict = 1;
    param5.real = 1;

    dict_types = malloc(param5.ndict * sizeof(sopt_wavelet_type));
    SOPT_ERROR_MEM_ALLOC_CHECK(dict_types);


    dict_types[0] = SOPT_WAVELET_DB8;


    sopt_sara_initop(&param5, dim1, dim2, 4, dict_types);

    datas[0] = (void*)&param5;

    //Structure for the L1 prox
    param6.verbose = 1;
    param6.max_iter = 50;
    param6.rel_obj = 0.01;
    param6.nu = 1;
    param6.tight = 1;
    param6.pos = 0;
    
    //Structure for the L1 solver    
    param7.verbose = 2;
    param7.max_iter = 200;
    param7.gamma = 0.1;
    param7.rel_obj = 0.0005;
    param7.epsilon = sqrt(Ny + 2*sqrt(Ny))*sigma;
    param7.real_out = 1;
    param7.real_meas = 1;
    param7.paraml1 = param6;
    param7.paraml2b = param3;
    
   
    //Weights
    for (i=0; i < Nr; i++) {
        w[i] = 1.0;
    }

    //Initial solution for L1 recosntruction
    for (i=0; i < Nx; i++) {
        xout[i] = 0.0;
    }

    #ifdef _OPENMP
        start = omp_get_wtime();
    #else
        assert((start = clock())!=-1);
    #endif
    sopt_l1_solver((void*)xout, Nx,
                   &sopt_meas_urandsamp,
                   datam,
                   &sopt_meas_urandsampadj,
                   datam,
                   &sopt_sara_synthesisop,
                   datas,
                   &sopt_sara_analysisop,
                   datas,
                   Nr,
                   (void*)y, Ny, w, param7);
    #ifdef _OPENMP
        stop = omp_get_wtime();
        t = stop - start;
    #else    
        stop = clock();
        t = (double) (stop-start)/CLOCKS_PER_SEC;
    #endif    

    printf("Time L1: %f \n\n", t); 

    //SNR
    for (i=0; i < Nx; i++) {
        error[i] = xout[i] - xin[i];
    }
    mse = cblas_dnrm2(Nx, error, 1);
    a = cblas_dnrm2(Nx, xin, 1);
    mse = 20.0*log10(a/mse);
    printf("SNR: %f dB\n\n", mse);

    //Write output image
    fail = spot_image_tiff_write(xout, dim2, dim1, "images/cameraIP_Db8.tiff", 1.0/scale, offset);
    if(fail == 1)
      SOPT_ERROR_GENERIC("Error writing image");

   

    


    
    free(xin);
    free(xout);
    free(y);
    free(y0);
    free(noise);
    free(error);
    free(w);
    free(param1.perm);
    free(dict_types);
    sopt_sara_free(&param5);
     
    return 0;
}
Ejemplo n.º 3
0
int main(int argc, char *argv[]) {

  

  int i, j, Nx, Ny, Nr, Nb;
  int seedn=54;
  double sigma;
  double a;
  double mse;
  double snr;
  double snr_out;
  double gamma=0.001;
  double aux1, aux2, aux3, aux4;
  complex double alpha;
  

  purify_image img, img_copy;
  purify_visibility_filetype filetype_vis;
  purify_image_filetype filetype_img;
  complex double *xinc;
  complex double *y0;
  complex double *y;
  complex double *noise;
  double *xout;
  double *w;
  double *error;
  complex double *xoutc;
  double *wdx;
  double *wdy;
  double *dummyr;
  complex double *dummyc;

  
  //parameters for the continuos Fourier Transform
  double *deconv;
  purify_sparsemat_row gmat;
  purify_visibility vis_test;
  purify_measurement_cparam param_m1;
  purify_measurement_cparam param_m2;
  complex double *fft_temp1;
  complex double *fft_temp2;
  void *datafwd[5];
  void *dataadj[5];
  fftw_plan planfwd;
  fftw_plan planadj;

  //Structures for sparsity operator
  sopt_wavelet_type *dict_types;
  sopt_wavelet_type *dict_types1;
  sopt_wavelet_type *dict_types2;
  sopt_sara_param param1;
  sopt_sara_param param2;
  sopt_sara_param param3;
  void *datas[1];
  void *datas1[1];
  void *datas2[1];

  //Structures for the opmization problems
  sopt_l1_sdmmparam param4;
  sopt_l1_rwparam param5;
  sopt_prox_tvparam param6;
  sopt_tv_sdmmparam param7;
  sopt_tv_rwparam param8;

  clock_t start, stop;
  double t = 0.0;
  double start1, stop1;
  int dimy, dimx;
  
  //Image dimension of the zero padded image
  //Dimensions should be power of 2
  dimx = 256;
  dimy = 256;

  //Define parameters
  filetype_vis = PURIFY_VISIBILITY_FILETYPE_PROFILE_VIS;
  filetype_img = PURIFY_IMAGE_FILETYPE_FITS;

  //Read coverage
  purify_visibility_readfile(&vis_test,
             "./data/images/Coverages/cont_sim4.vis",
             filetype_vis); 
  printf("Number of visibilities: %i \n\n", vis_test.nmeas);  

   

  // Input image.
  img.fov_x = 1.0 / 180.0 * PURIFY_PI;
  img.fov_y = 1.0 / 180.0 * PURIFY_PI;
  img.nx = 4;
  img.ny = 4;

  //Read input image
  purify_image_readfile(&img, "data/images/Einstein.fits", 1);
  printf("Image dimension: %i, %i \n\n", img.nx, img.ny); 
//  purify_image_writefile(&img, "data/test/Einstein_double.fits", filetype_img);

  param_m1.nmeas = vis_test.nmeas;
  param_m1.ny1 = dimy;
  param_m1.nx1 = dimx;
  param_m1.ofy = 2;
  param_m1.ofx = 2;
  param_m1.ky = 2;
  param_m1.kx = 2;

  param_m2.nmeas = vis_test.nmeas;
  param_m2.ny1 = dimy;
  param_m2.nx1 = dimx;
  param_m2.ofy = 2;
  param_m2.ofx = 2;
  param_m2.ky = 2;
  param_m2.kx = 2;

  Nb = 9;
  Nx=param_m2.ny1*param_m2.nx1;
  Nr=Nb*Nx;
  Ny=param_m2.nmeas;

  //Memory allocation for the different variables
  deconv = (double*)malloc((Nx) * sizeof(double));
  PURIFY_ERROR_MEM_ALLOC_CHECK(deconv);
  xinc = (complex double*)malloc((Nx) * sizeof(complex double));
  PURIFY_ERROR_MEM_ALLOC_CHECK(xinc);
  xout = (double*)malloc((Nx) * sizeof(double));
  PURIFY_ERROR_MEM_ALLOC_CHECK(xout);
  y = (complex double*)malloc((vis_test.nmeas) * sizeof(complex double));
  PURIFY_ERROR_MEM_ALLOC_CHECK(y);
  y0 = (complex double*)malloc((vis_test.nmeas) * sizeof(complex double));
  PURIFY_ERROR_MEM_ALLOC_CHECK(y0);
  noise = (complex double*)malloc((vis_test.nmeas) * sizeof(complex double));
  PURIFY_ERROR_MEM_ALLOC_CHECK(noise);
  w = (double*)malloc((Nr) * sizeof(double));
  PURIFY_ERROR_MEM_ALLOC_CHECK(w);
  error = (double*)malloc((Nx) * sizeof(double));
  PURIFY_ERROR_MEM_ALLOC_CHECK(error);
  xoutc = (complex double*)malloc((Nx) * sizeof(complex double));
  PURIFY_ERROR_MEM_ALLOC_CHECK(xoutc);

  wdx = (double*)malloc((Nx) * sizeof(double));
  PURIFY_ERROR_MEM_ALLOC_CHECK(wdx);
  wdy = (double*)malloc((Nx) * sizeof(double));
  PURIFY_ERROR_MEM_ALLOC_CHECK(wdy);

  dummyr = malloc(Nr * sizeof(double));
  PURIFY_ERROR_MEM_ALLOC_CHECK(dummyr);
  dummyc = malloc(Nr * sizeof(complex double));
  PURIFY_ERROR_MEM_ALLOC_CHECK(dummyc);

  for (i=0; i < Nx; i++){
    xinc[i] = 0.0 + 0.0*I;
  }

  for (i=0; i < img.nx; i++){
    for (j=0; j < img.ny; j++){
      xinc[i+j*param_m1.nx1] = img.pix[i+j*img.nx] + 0.0*I;
    }
  }
  
  //Initialize griding matrix
  assert((start = clock())!=-1);
  purify_measurement_init_cft(&gmat, deconv, vis_test.u, vis_test.v, &param_m1);
  stop = clock();
  t = (double) (stop-start)/CLOCKS_PER_SEC;
  printf("Time initalization: %f \n\n", t);

  for(i = 0; i < img.nx * img.ny; ++i){
    deconv[i] = 1.0;
  }
  
  //Memory allocation for the fft
  i = Nx*param_m1.ofy*param_m1.ofx;
  fft_temp1 = (complex double*)malloc((i) * sizeof(complex double));
  PURIFY_ERROR_MEM_ALLOC_CHECK(fft_temp1);
  fft_temp2 = (complex double*)malloc((i) * sizeof(complex double));
  PURIFY_ERROR_MEM_ALLOC_CHECK(fft_temp2);

  //FFT plan  
  planfwd = fftw_plan_dft_2d(param_m1.nx1*param_m1.ofx, param_m1.ny1*param_m1.ofy, 
              fft_temp1, fft_temp1, 
              FFTW_FORWARD, FFTW_MEASURE);

  planadj = fftw_plan_dft_2d(param_m1.nx1*param_m1.ofx, param_m1.ny1*param_m1.ofy, 
              fft_temp2, fft_temp2, 
              FFTW_BACKWARD, FFTW_MEASURE);


  datafwd[0] = (void*)&param_m1;
  datafwd[1] = (void*)deconv;
  datafwd[2] = (void*)&gmat;
  datafwd[3] = (void*)&planfwd;
  datafwd[4] = (void*)fft_temp1;

  dataadj[0] = (void*)&param_m2;
  dataadj[1] = (void*)deconv;
  dataadj[2] = (void*)&gmat;
  dataadj[3] = (void*)&planadj;
  dataadj[4] = (void*)fft_temp2;


  printf("FFT plan done \n\n");
  
  
  assert((start = clock())!=-1);
  purify_measurement_cftfwd((void*)y0, (void*)xinc, datafwd);
  stop = clock();
  t = (double) (stop-start)/CLOCKS_PER_SEC;
  printf("Time forward operator: %f \n\n", t);

  
  //Noise realization
  //Input snr
  snr = 30.0;
  a = cblas_dznrm2(Ny, (void*)y0, 1);
  sigma = a*pow(10.0,-(snr/20.0))/sqrt(Ny);

  FILE *fout = fopen("ein.uv", "w");
    
  for (i=0; i < Ny; i++) {
//      noise[i] = (sopt_ran_gasdev2(seedn) + sopt_ran_gasdev2(seedn)*I)*(sigma/sqrt(2));
      noise[i] = 0;
      y[i] = y0[i] + noise[i];

    fprintf(fout, "%14.5e%14.5e%14.5e%14.5e%14.5e%14.5e\n", 
            vis_test.u[i], vis_test.v[i], vis_test.w[i],
            creal(y[i]), cimag(y[i]), 1.0);
  }

  fclose(fout);

  //Rescaling the measurements

  aux4 = (double)Ny/(double)Nx;

  for (i=0; i < Ny; i++) {
    y[i] = y[i]/sqrt(aux4);
  }

  for (i=0; i < Nx; i++) {
    deconv[i] = deconv[i]/sqrt(aux4);
  }
  
  
  // Output image.
  img_copy.fov_x = 1.0 / 180.0 * PURIFY_PI;
  img_copy.fov_y = 1.0 / 180.0 * PURIFY_PI;
  img_copy.nx = param_m1.nx1;
  img_copy.ny = param_m1.ny1;

  for (i=0; i < Nx; i++){
    xoutc[i] = 0.0 + 0.0*I;
  }
  
  //Dirty image
  purify_measurement_cftadj((void*)xoutc, (void*)y, dataadj);

  for (i=0; i < Nx; i++) {
    xout[i] = creal(xoutc[i]);
  }

  aux1 = purify_utils_maxarray(xout, Nx);

  

   img_copy.pix = (double*)malloc((Nx) * sizeof(double));
  PURIFY_ERROR_MEM_ALLOC_CHECK(img_copy.pix);

  for (i=0; i < Nx; i++){
    img_copy.pix[i] = creal(xoutc[i]);
  }
  
  purify_image_writefile(&img_copy, "eindirty.fits", filetype_img);
  
  return 0;
  
  //SARA structure initialization

    param1.ndict = Nb;
    param1.real = 0;

    dict_types = malloc(param1.ndict * sizeof(sopt_wavelet_type));
    PURIFY_ERROR_MEM_ALLOC_CHECK(dict_types);


    dict_types[0] = SOPT_WAVELET_DB1;
    dict_types[1] = SOPT_WAVELET_DB2;
    dict_types[2] = SOPT_WAVELET_DB3;
    dict_types[3] = SOPT_WAVELET_DB4;
    dict_types[4] = SOPT_WAVELET_DB5;
    dict_types[5] = SOPT_WAVELET_DB6;
    dict_types[6] = SOPT_WAVELET_DB7;
    dict_types[7] = SOPT_WAVELET_DB8;
    dict_types[8] = SOPT_WAVELET_Dirac;
    

    sopt_sara_initop(&param1, param_m1.ny1, param_m1.nx1, 4, dict_types);

    datas[0] = (void*)&param1;

    //Db8 structure initialization

    param2.ndict = 1;
    param2.real = 0;

    dict_types1 = malloc(param2.ndict * sizeof(sopt_wavelet_type));
    PURIFY_ERROR_MEM_ALLOC_CHECK(dict_types1);

    dict_types1[0] = SOPT_WAVELET_DB8;
    
    sopt_sara_initop(&param2, param_m1.ny1, param_m1.nx1, 4, dict_types1);

  datas1[0] = (void*)&param2;

  //Dirac structure initialization

    param3.ndict = 1;
    param3.real = 0;

    dict_types2 = malloc(param3.ndict * sizeof(sopt_wavelet_type));
    PURIFY_ERROR_MEM_ALLOC_CHECK(dict_types2);

    dict_types2[0] = SOPT_WAVELET_Dirac;
    
    sopt_sara_initop(&param3, param_m1.ny1, param_m1.nx1, 4, dict_types2);

  datas2[0] = (void*)&param3;

  //Scaling constants in the diferent representation domains

  sopt_sara_analysisop((void*)dummyc, (void*)xoutc, datas);

  for (i=0; i < Nr; i++) {
    dummyr[i] = creal(dummyc[i]);
  }

  aux2 = purify_utils_maxarray(dummyr, Nr);

  sopt_sara_analysisop((void*)dummyc, (void*)xoutc, datas1);

  for (i=0; i < Nr; i++) {
    dummyr[i] = creal(dummyc[i]);
  }

  aux3 = purify_utils_maxarray(dummyr, Nx);

  


  // Output image.
  img_copy.fov_x = 1.0 / 180.0 * PURIFY_PI;
  img_copy.fov_y = 1.0 / 180.0 * PURIFY_PI;
  img_copy.nx = param_m1.nx1;
  img_copy.ny = param_m1.ny1;



  //Initial solution and weights
  for (i=0; i < Nx; i++) {
      xoutc[i] = 0.0 + 0.0*I;
      wdx[i] = 1.0;
      wdy[i] = 1.0;
  }
  for (i=0; i < Nr; i++){
    w[i] = 1.0;
  }
  //Copy true image in xout
  for (i=0; i < Nx; i++) {
    xout[i] = creal(xinc[i]);
  }



  printf("**********************\n");
  printf("BPSA reconstruction\n");
  printf("**********************\n");

  
    
  //Structure for the L1 solver      
  param4.verbose = 2;
  param4.max_iter = 300;
  param4.gamma = gamma*aux2;
  param4.rel_obj = 0.001;
  param4.epsilon = sqrt(Ny + 2*sqrt(Ny))*sigma/sqrt(aux4);
  param4.epsilon_tol = 0.01;
  param4.real_data = 0;
  param4.cg_max_iter = 100;
  param4.cg_tol = 0.000001;

  
  //Initial solution
  for (i=0; i < Nx; i++) {
      xoutc[i] = 0.0 + 0.0*I;
  }
 
  #ifdef _OPENMP 
    start1 = omp_get_wtime();
  #else
    assert((start = clock())!=-1);
  #endif
  sopt_l1_sdmm((void*)xoutc, Nx,
                   &purify_measurement_cftfwd,
                   datafwd,
                   &purify_measurement_cftadj,
                   dataadj,
                   &sopt_sara_synthesisop,
                   datas,
                   &sopt_sara_analysisop,
                   datas,
                   Nr,
                   (void*)y, Ny, w, param4);

  #ifdef _OPENMP 
    stop1 = omp_get_wtime();
    t = stop1 - start1;
  #else
    stop = clock();
    t = (double) (stop-start)/CLOCKS_PER_SEC;
  #endif

  printf("Time BPSA: %f \n\n", t); 

  
    //SNR
    for (i=0; i < Nx; i++) {
        error[i] = creal(xoutc[i])-xout[i];
    }
    mse = cblas_dnrm2(Nx, error, 1);
    a = cblas_dnrm2(Nx, xout, 1);
    snr_out = 20.0*log10(a/mse);
    printf("SNR: %f dB\n\n", snr_out);


    
  for (i=0; i < Nx; i++){
    img_copy.pix[i] = creal(xoutc[i]);
  }
  
  purify_image_writefile(&img_copy, "./data/test/einbpsa.fits", filetype_img);

  //Residual image

  purify_measurement_cftfwd((void*)y0, (void*)xoutc, datafwd);
  alpha = -1.0 +0.0*I;
  cblas_zaxpy(Ny, (void*)&alpha, y, 1, y0, 1);
  purify_measurement_cftadj((void*)xinc, (void*)y0, dataadj);

  for (i=0; i < Nx; i++){
    img_copy.pix[i] = creal(xinc[i]);
  }
  
  purify_image_writefile(&img_copy, "data/test/einbpsares.fits", filetype_img);
  
  //Error image
  for (i=0; i < Nx; i++){
    img_copy.pix[i] = error[i];
  }
  
  purify_image_writefile(&img_copy, "data/test/einbpsaerror.fits", filetype_img);
  


  printf("**********************\n");
  printf("SARA reconstruction\n");
  printf("**********************\n");

  

  //Structure for the RWL1 solver    
  param5.verbose = 2;
  param5.max_iter = 5;
  param5.rel_var = 0.001;
  param5.sigma = sigma*sqrt((double)Ny/(double)Nr);
  param5.init_sol = 1;

  
  #ifdef _OPENMP 
    start1 = omp_get_wtime();
  #else
    assert((start = clock())!=-1);
  #endif
  sopt_l1_rwsdmm((void*)xoutc, Nx,
                   &purify_measurement_cftfwd,
                   datafwd,
                   &purify_measurement_cftadj,
                   dataadj,
                   &sopt_sara_synthesisop,
                   datas,
                   &sopt_sara_analysisop,
                   datas,
                   Nr,
                   (void*)y, Ny, param4, param5);

  #ifdef _OPENMP 
    stop1 = omp_get_wtime();
    t = stop1 - start1;
  #else
    stop = clock();
    t = (double) (stop-start)/CLOCKS_PER_SEC;
  #endif

  printf("Time SARA: %f \n\n", t); 

  
    //SNR
    for (i=0; i < Nx; i++) {
        error[i] = creal(xoutc[i])-xout[i];
    }
    mse = cblas_dnrm2(Nx, error, 1);
    a = cblas_dnrm2(Nx, xout, 1);
    snr_out = 20.0*log10(a/mse);
    printf("SNR: %f dB\n\n", snr_out);

  for (i=0; i < Nx; i++){
    img_copy.pix[i] = creal(xoutc[i]);
  }
  
  purify_image_writefile(&img_copy, "data/test/einsara.fits", filetype_img);

  

   //Residual image

  purify_measurement_cftfwd((void*)y0, (void*)xoutc, datafwd);
  alpha = -1.0 +0.0*I;
  cblas_zaxpy(Ny, (void*)&alpha, y, 1, y0, 1);
  purify_measurement_cftadj((void*)xinc, (void*)y0, dataadj);

  for (i=0; i < Nx; i++){
    img_copy.pix[i] = creal(xinc[i]);
  }
  
  purify_image_writefile(&img_copy, "data/test/einsarares.fits", filetype_img);

  //Error image
  for (i=0; i < Nx; i++){
    img_copy.pix[i] = error[i];
  }
  
  purify_image_writefile(&img_copy, "data/test/einsaraerror.fits", filetype_img);

  
    printf("**********************\n");
    printf("TV reconstruction\n");
    printf("**********************\n");

    
    //Structure for the TV prox
    param6.verbose = 1;
    param6.max_iter = 50;
    param6.rel_obj = 0.0001;

    
    //Structure for the TV solver    
    param7.verbose = 2;
    param7.max_iter = 300;
    param7.gamma = gamma*aux1;
    param7.rel_obj = 0.001;
    param7.epsilon = sqrt(Ny + 2*sqrt(Ny))*sigma/sqrt(aux4);
    param7.epsilon_tol = 0.01;
    param7.real_data = 0;
    param7.cg_max_iter = 100;
    param7.cg_tol = 0.000001;
    param7.paramtv = param6;

    //Initial solution and weights
    for (i=0; i < Nx; i++) {
        xoutc[i] = 0.0 + 0.0*I;
        wdx[i] = 1.0;
        wdy[i] = 1.0;
    }

    
    assert((start = clock())!=-1);
    sopt_tv_sdmm((void*)xoutc, dimx, dimy,
                   &purify_measurement_cftfwd,
                   datafwd,
                   &purify_measurement_cftadj,
                   dataadj,
                   (void*)y, Ny, wdx, wdy, param7);
    stop = clock();
    t = (double) (stop-start)/CLOCKS_PER_SEC;
    
    printf("Time TV: %f \n\n", t); 

    
   //SNR
    for (i=0; i < Nx; i++) {
        error[i] = creal(xoutc[i])-xout[i];
    }
    mse = cblas_dnrm2(Nx, error, 1);
    a = cblas_dnrm2(Nx, xout, 1);
    snr_out = 20.0*log10(a/mse);
    printf("SNR: %f dB\n\n", snr_out);

  for (i=0; i < Nx; i++){
    img_copy.pix[i] = creal(xoutc[i]);
  }
  
  purify_image_writefile(&img_copy, "data/test/eintv.fits", filetype_img);

   //Residual image

  purify_measurement_cftfwd((void*)y0, (void*)xoutc, datafwd);
  alpha = -1.0 +0.0*I;
  cblas_zaxpy(Ny, (void*)&alpha, y, 1, y0, 1);
  purify_measurement_cftadj((void*)xinc, (void*)y0, dataadj);

  for (i=0; i < Nx; i++){
    img_copy.pix[i] = creal(xinc[i]);
  }
  
  purify_image_writefile(&img_copy, "data/test/eintvres.fits", filetype_img);

  //Error image
  for (i=0; i < Nx; i++){
    img_copy.pix[i] = error[i];
  }
  
  purify_image_writefile(&img_copy, "data/test/eintverror.fits", filetype_img);

  printf("**********************\n");
  printf("RWTV reconstruction\n");
  printf("**********************\n");

  

  //Structure for the RWTV solver    
  param8.verbose = 2;
  param8.max_iter = 5;
  param8.rel_var = 0.001;
  param8.sigma = sigma*sqrt(Ny/(2*Nx));
  param8.init_sol = 1;

  
  assert((start = clock())!=-1);
    sopt_tv_rwsdmm((void*)xoutc, dimx, dimy,
                   &purify_measurement_cftfwd,
                   datafwd,
                   &purify_measurement_cftadj,
                   dataadj,
                   (void*)y, Ny, param7, param8);
    stop = clock();
    t = (double) (stop-start)/CLOCKS_PER_SEC;

  printf("Time RWTV: %f \n\n", t); 

  

    //SNR
    for (i=0; i < Nx; i++) {
        error[i] = creal(xoutc[i])-xout[i];
    }
    mse = cblas_dnrm2(Nx, error, 1);
    a = cblas_dnrm2(Nx, xout, 1);
    snr_out = 20.0*log10(a/mse);
    printf("SNR: %f dB\n\n", snr_out);

  for (i=0; i < Nx; i++){
    img_copy.pix[i] = creal(xoutc[i]);
  }
  
  purify_image_writefile(&img_copy, "data/test/einrwtv.fits", filetype_img);

   //Residual image

  purify_measurement_cftfwd((void*)y0, (void*)xoutc, datafwd);
  alpha = -1.0 +0.0*I;
  cblas_zaxpy(Ny, (void*)&alpha, y, 1, y0, 1);
  purify_measurement_cftadj((void*)xinc, (void*)y0, dataadj);

  for (i=0; i < Nx; i++){
    img_copy.pix[i] = creal(xinc[i]);
  }
  
  purify_image_writefile(&img_copy, "data/test/einrwtvres.fits", filetype_img);

  //Error image
  for (i=0; i < Nx; i++){
    img_copy.pix[i] = error[i];
  }
  
  purify_image_writefile(&img_copy, "data/test/einrwtverror.fits", filetype_img);

  printf("**********************\n");
  printf("Db8 reconstruction\n");
  printf("**********************\n");

  //Initial solution
  for (i=0; i < Nx; i++) {
        xoutc[i] = 0.0 + 0.0*I;
  }
  
  param4.gamma = gamma*aux3;

  assert((start = clock())!=-1);
   sopt_l1_sdmm((void*)xoutc, Nx,
                   &purify_measurement_cftfwd,
                   datafwd,
                   &purify_measurement_cftadj,
                   dataadj,
                   &sopt_sara_synthesisop,
                   datas1,
                   &sopt_sara_analysisop,
                   datas1,
                   Nx,
                   (void*)y, Ny, w, param4);

  stop = clock();
  t = (double) (stop-start)/CLOCKS_PER_SEC;

  printf("Time BPDb8: %f \n\n", t); 

  //SNR
  for (i=0; i < Nx; i++) {
        error[i] = creal(xoutc[i])-xout[i];
    }
    mse = cblas_dnrm2(Nx, error, 1);
    a = cblas_dnrm2(Nx, xout, 1);
    snr_out = 20.0*log10(a/mse);
    printf("SNR: %f dB\n\n", snr_out);

  for (i=0; i < Nx; i++){
    img_copy.pix[i] = creal(xoutc[i]);
  }
  
  purify_image_writefile(&img_copy, "data/test/eindb8.fits", filetype_img);

   //Residual image

  purify_measurement_cftfwd((void*)y0, (void*)xoutc, datafwd);
  alpha = -1.0 +0.0*I;
  cblas_zaxpy(Ny, (void*)&alpha, y, 1, y0, 1);
  purify_measurement_cftadj((void*)xinc, (void*)y0, dataadj);

  for (i=0; i < Nx; i++){
    img_copy.pix[i] = creal(xinc[i]);
  }
  
  purify_image_writefile(&img_copy, "data/test/eindb8res.fits", filetype_img);

  //Error image
  for (i=0; i < Nx; i++){
    img_copy.pix[i] = error[i];
  }
  
  purify_image_writefile(&img_copy, "data/test/eindb8error.fits", filetype_img);

  printf("**********************\n");
  printf("RWBPDb8 reconstruction\n");
  printf("**********************\n");

  

  //Structure for the RWL1 solver    
  param5.verbose = 2;
  param5.max_iter = 5;
  param5.rel_var = 0.001;
  param5.sigma = sigma*sqrt((double)Ny/(double)Nx);
  param5.init_sol = 1;

  
  assert((start = clock())!=-1);
  sopt_l1_rwsdmm((void*)xoutc, Nx,
                   &purify_measurement_cftfwd,
                   datafwd,
                   &purify_measurement_cftadj,
                   dataadj,
                   &sopt_sara_synthesisop,
                   datas1,
                   &sopt_sara_analysisop,
                   datas1,
                   Nx,
                   (void*)y, Ny, param4, param5);

  stop = clock();
  t = (double) (stop-start)/CLOCKS_PER_SEC;

  printf("Time RWBPDb8: %f \n\n", t); 

  

    //SNR
    for (i=0; i < Nx; i++) {
        error[i] = creal(xoutc[i])-xout[i];
    }
    mse = cblas_dnrm2(Nx, error, 1);
    a = cblas_dnrm2(Nx, xout, 1);
    snr_out = 20.0*log10(a/mse);
    printf("SNR: %f dB\n\n", snr_out);

  for (i=0; i < Nx; i++){
    img_copy.pix[i] = creal(xoutc[i]);
  }
  
  purify_image_writefile(&img_copy, "data/test/einrwdb8.fits", filetype_img);

   //Residual image

  purify_measurement_cftfwd((void*)y0, (void*)xoutc, datafwd);
  alpha = -1.0 +0.0*I;
  cblas_zaxpy(Ny, (void*)&alpha, y, 1, y0, 1);
  purify_measurement_cftadj((void*)xinc, (void*)y0, dataadj);

  for (i=0; i < Nx; i++){
    img_copy.pix[i] = creal(xinc[i]);
  }
  
  purify_image_writefile(&img_copy, "data/test/einrwdb8res.fits", filetype_img);

  //Error image
  for (i=0; i < Nx; i++){
    img_copy.pix[i] = error[i];
  }
  
  purify_image_writefile(&img_copy, "data/test/einrwdb8error.fits", filetype_img);



  printf("**********************\n");
  printf("BP reconstruction\n");
  printf("**********************\n");

  param4.gamma = gamma*aux1;

  //Initial solution
  for (i=0; i < Nx; i++) {
      xoutc[i] = 0.0 + 0.0*I;
  }

  assert((start = clock())!=-1);
  sopt_l1_sdmm((void*)xoutc, Nx,
                   &purify_measurement_cftfwd,
                   datafwd,
                   &purify_measurement_cftadj,
                   dataadj,
                   &sopt_sara_synthesisop,
                   datas2,
                   &sopt_sara_analysisop,
                   datas2,
                   Nx,
                   (void*)y, Ny, w, param4); 

  stop = clock();
  t = (double) (stop-start)/CLOCKS_PER_SEC;

  printf("Time BP: %f \n\n", t); 

  //SNR
  for (i=0; i < Nx; i++) {
        error[i] = creal(xoutc[i])-xout[i];
    }
    mse = cblas_dnrm2(Nx, error, 1);
    a = cblas_dnrm2(Nx, xout, 1);
    snr_out = 20.0*log10(a/mse);
    printf("SNR: %f dB\n\n", snr_out);

  for (i=0; i < Nx; i++){
    img_copy.pix[i] = creal(xoutc[i]);
  }
  
  purify_image_writefile(&img_copy, "data/test/einbp.fits", filetype_img);

   //Residual image

  purify_measurement_cftfwd((void*)y0, (void*)xoutc, datafwd);
  alpha = -1.0 +0.0*I;
  cblas_zaxpy(Ny, (void*)&alpha, y, 1, y0, 1);
  purify_measurement_cftadj((void*)xinc, (void*)y0, dataadj);

  for (i=0; i < Nx; i++){
    img_copy.pix[i] = creal(xinc[i]);
  }
  
  purify_image_writefile(&img_copy, "data/test/einbpres.fits", filetype_img);

  //Error image
  for (i=0; i < Nx; i++){
    img_copy.pix[i] = error[i];
  }
  
  purify_image_writefile(&img_copy, "data/test/einbperror.fits", filetype_img);

  printf("**********************\n");
  printf("RWBP reconstruction\n");
  printf("**********************\n");

  

  //Structure for the RWL1 solver    
  param5.verbose = 2;
  param5.max_iter = 5;
  param5.rel_var = 0.001;
  param5.sigma = sigma*sqrt((double)Ny/(double)Nx);
  param5.init_sol = 1;

  
  assert((start = clock())!=-1);
  sopt_l1_rwsdmm((void*)xoutc, Nx,
                   &purify_measurement_cftfwd,
                   datafwd,
                   &purify_measurement_cftadj,
                   dataadj,
                   &sopt_sara_synthesisop,
                   datas2,
                   &sopt_sara_analysisop,
                   datas2,
                   Nx,
                   (void*)y, Ny, param4, param5);

  stop = clock();
  t = (double) (stop-start)/CLOCKS_PER_SEC;

  printf("Time RWBP: %f \n\n", t); 

  

    //SNR
    for (i=0; i < Nx; i++) {
        error[i] = creal(xoutc[i])-xout[i];
    }
    mse = cblas_dnrm2(Nx, error, 1);
    a = cblas_dnrm2(Nx, xout, 1);
    snr_out = 20.0*log10(a/mse);
    printf("SNR: %f dB\n\n", snr_out);

  for (i=0; i < Nx; i++){
    img_copy.pix[i] = creal(xoutc[i]);
  }
  
  purify_image_writefile(&img_copy, "data/test/einrwbp.fits", filetype_img);

   //Residual image

  purify_measurement_cftfwd((void*)y0, (void*)xoutc, datafwd);
  alpha = -1.0 +0.0*I;
  cblas_zaxpy(Ny, (void*)&alpha, y, 1, y0, 1);
  purify_measurement_cftadj((void*)xinc, (void*)y0, dataadj);

  for (i=0; i < Nx; i++){
    img_copy.pix[i] = creal(xinc[i]);
  }
  
  purify_image_writefile(&img_copy, "data/test/einrwbpres.fits", filetype_img);

  //Error image
  for (i=0; i < Nx; i++){
    img_copy.pix[i] = error[i];
  }
  
  purify_image_writefile(&img_copy, "data/test/einrwbperror.fits", filetype_img);


  
  
  //Free all memory
  purify_image_free(&img);
  purify_image_free(&img_copy);
  free(deconv);
  purify_visibility_free(&vis_test);
  free(y);
  free(xinc);
  free(xout);
  free(w);
  free(noise);
  free(y0);
  free(error);
  free(xoutc);
  free(wdx);
  free(wdy);

  sopt_sara_free(&param1);
  sopt_sara_free(&param2);
  sopt_sara_free(&param3);
  free(dict_types);
  free(dict_types1);
  free(dict_types2);

  free(fft_temp1);
  free(fft_temp2);
  fftw_destroy_plan(planfwd);
  fftw_destroy_plan(planadj);
  purify_sparsemat_freer(&gmat);

  free(dummyr);
  free(dummyc);


  return 0;

}