int main_pics(int argc, char* argv[]) { // Initialize default parameters struct sense_conf conf = sense_defaults; bool use_gpu = false; bool randshift = true; unsigned int maxiter = 30; float step = -1.; // Start time count double start_time = timestamp(); // Read input options struct nufft_conf_s nuconf = nufft_conf_defaults; nuconf.toeplitz = false; float restrict_fov = -1.; const char* pat_file = NULL; const char* traj_file = NULL; bool scale_im = false; bool eigen = false; float scaling = 0.; unsigned int llr_blk = 8; const char* image_truth_file = NULL; bool im_truth = false; const char* image_start_file = NULL; bool warm_start = false; bool hogwild = false; bool fast = false; float admm_rho = iter_admm_defaults.rho; unsigned int admm_maxitercg = iter_admm_defaults.maxitercg; struct opt_reg_s ropts; ropts.r = 0; ropts.algo = CG; ropts.lambda = -1.; const struct opt_s opts[] = { { 'l', true, opt_reg, &ropts, "1/-l2\t\ttoggle l1-wavelet or l2 regularization." }, OPT_FLOAT('r', &ropts.lambda, "lambda", "regularization parameter"), { 'R', true, opt_reg, &ropts, " <T>:A:B:C\tgeneralized regularization options (-Rh for help)" }, OPT_SET('c', &conf.rvc, "real-value constraint"), OPT_FLOAT('s', &step, "step", "iteration stepsize"), OPT_UINT('i', &maxiter, "iter", "max. number of iterations"), OPT_STRING('t', &traj_file, "file", "k-space trajectory"), OPT_CLEAR('n', &randshift, "disable random wavelet cycle spinning"), OPT_SET('g', &use_gpu, "use GPU"), OPT_STRING('p', &pat_file, "file", "pattern or weights"), OPT_SELECT('I', enum algo_t, &ropts.algo, IST, "(select IST)"), OPT_UINT('b', &llr_blk, "blk", "Lowrank block size"), OPT_SET('e', &eigen, "Scale stepsize based on max. eigenvalue"), OPT_SET('H', &hogwild, "(hogwild)"), OPT_SET('F', &fast, "(fast)"), OPT_STRING('T', &image_truth_file, "file", "(truth file)"), OPT_STRING('W', &image_start_file, "<img>", "Warm start with <img>"), OPT_INT('d', &debug_level, "level", "Debug level"), OPT_INT('O', &conf.rwiter, "rwiter", "(reweighting)"), OPT_FLOAT('o', &conf.gamma, "gamma", "(reweighting)"), OPT_FLOAT('u', &admm_rho, "rho", "ADMM rho"), OPT_UINT('C', &admm_maxitercg, "iter", "ADMM max. CG iterations"), OPT_FLOAT('q', &conf.cclambda, "cclambda", "(cclambda)"), OPT_FLOAT('f', &restrict_fov, "rfov", "restrict FOV"), OPT_SELECT('m', enum algo_t, &ropts.algo, ADMM, "Select ADMM"), OPT_FLOAT('w', &scaling, "val", "scaling"), OPT_SET('S', &scale_im, "Re-scale the image after reconstruction"), }; cmdline(&argc, argv, 3, 3, usage_str, help_str, ARRAY_SIZE(opts), opts); if (NULL != image_truth_file) im_truth = true; if (NULL != image_start_file) warm_start = true; long max_dims[DIMS]; long map_dims[DIMS]; long pat_dims[DIMS]; long img_dims[DIMS]; long coilim_dims[DIMS]; long ksp_dims[DIMS]; long traj_dims[DIMS]; // load kspace and maps and get dimensions complex float* kspace = load_cfl(argv[1], DIMS, ksp_dims); complex float* maps = load_cfl(argv[2], DIMS, map_dims); complex float* traj = NULL; if (NULL != traj_file) traj = load_cfl(traj_file, DIMS, traj_dims); md_copy_dims(DIMS, max_dims, ksp_dims); md_copy_dims(5, max_dims, map_dims); md_select_dims(DIMS, ~COIL_FLAG, img_dims, max_dims); md_select_dims(DIMS, ~MAPS_FLAG, coilim_dims, max_dims); if (!md_check_compat(DIMS, ~(MD_BIT(MAPS_DIM)|FFT_FLAGS), img_dims, map_dims)) error("Dimensions of image and sensitivities do not match!\n"); assert(1 == ksp_dims[MAPS_DIM]); (use_gpu ? num_init_gpu : num_init)(); // print options if (use_gpu) debug_printf(DP_INFO, "GPU reconstruction\n"); if (map_dims[MAPS_DIM] > 1) debug_printf(DP_INFO, "%ld maps.\nESPIRiT reconstruction.\n", map_dims[MAPS_DIM]); if (hogwild) debug_printf(DP_INFO, "Hogwild stepsize\n"); if (im_truth) debug_printf(DP_INFO, "Compare to truth\n"); // initialize sampling pattern complex float* pattern = NULL; if (NULL != pat_file) { pattern = load_cfl(pat_file, DIMS, pat_dims); assert(md_check_compat(DIMS, COIL_FLAG, ksp_dims, pat_dims)); } else { md_select_dims(DIMS, ~COIL_FLAG, pat_dims, ksp_dims); pattern = md_alloc(DIMS, pat_dims, CFL_SIZE); estimate_pattern(DIMS, ksp_dims, COIL_DIM, pattern, kspace); } if ((NULL != traj_file) && (NULL == pat_file)) { md_free(pattern); pattern = NULL; nuconf.toeplitz = true; } else { // print some statistics long T = md_calc_size(DIMS, pat_dims); long samples = (long)pow(md_znorm(DIMS, pat_dims, pattern), 2.); debug_printf(DP_INFO, "Size: %ld Samples: %ld Acc: %.2f\n", T, samples, (float)T / (float)samples); } if (NULL == traj_file) { fftmod(DIMS, ksp_dims, FFT_FLAGS, kspace, kspace); fftmod(DIMS, map_dims, FFT_FLAGS, maps, maps); } // apply fov mask to sensitivities if (-1. != restrict_fov) { float restrict_dims[DIMS] = { [0 ... DIMS - 1] = 1. }; restrict_dims[0] = restrict_fov; restrict_dims[1] = restrict_fov; restrict_dims[2] = restrict_fov; apply_mask(DIMS, map_dims, maps, restrict_dims); }
/** * * NUFFT operator initialization * * @param N - number of dimensions * @param ksp_dims - kspace dimension * @param cim_dims - coil images dimension * @param traj - trajectory * @param conf - configuration options * @param use_gpu - use gpu boolean * */ struct linop_s* nufft_create(unsigned int N, const long ksp_dims[N], const long cim_dims[N], const long traj_dims[N], const complex float* traj, const complex float* weights, struct nufft_conf_s conf, bool use_gpu) { struct nufft_data* data = (struct nufft_data*)xmalloc(sizeof(struct nufft_data)); data->N = N; data->use_gpu = use_gpu; data->traj = traj; data->conf = conf; data->width = 3.; data->beta = calc_beta(2., data->width); // get dims assert(md_check_compat(N - 3, 0, ksp_dims + 3, cim_dims + 3)); unsigned int ND = N + 3; data->ksp_dims = xmalloc(ND * sizeof(long)); data->cim_dims = xmalloc(ND * sizeof(long)); data->cml_dims = xmalloc(ND * sizeof(long)); data->img_dims = xmalloc(ND * sizeof(long)); data->trj_dims = xmalloc(ND * sizeof(long)); data->lph_dims = xmalloc(ND * sizeof(long)); data->psf_dims = xmalloc(ND * sizeof(long)); data->wgh_dims = xmalloc(ND * sizeof(long)); data->ksp_strs = xmalloc(ND * sizeof(long)); data->cim_strs = xmalloc(ND * sizeof(long)); data->cml_strs = xmalloc(ND * sizeof(long)); data->img_strs = xmalloc(ND * sizeof(long)); data->trj_strs = xmalloc(ND * sizeof(long)); data->lph_strs = xmalloc(ND * sizeof(long)); data->psf_strs = xmalloc(ND * sizeof(long)); data->wgh_strs = xmalloc(ND * sizeof(long)); md_singleton_dims(ND, data->cim_dims); md_singleton_dims(ND, data->ksp_dims); md_copy_dims(N, data->cim_dims, cim_dims); md_copy_dims(N, data->ksp_dims, ksp_dims); md_select_dims(ND, FFT_FLAGS, data->img_dims, data->cim_dims); assert(3 == traj_dims[0]); assert(traj_dims[1] == ksp_dims[1]); assert(traj_dims[2] == ksp_dims[2]); assert(md_check_compat(N - 3, ~0, traj_dims + 3, ksp_dims + 3)); assert(md_check_bounds(N - 3, ~0, traj_dims + 3, ksp_dims + 3)); md_singleton_dims(ND, data->trj_dims); md_copy_dims(N, data->trj_dims, traj_dims); // get strides md_calc_strides(ND, data->cim_strs, data->cim_dims, CFL_SIZE); md_calc_strides(ND, data->img_strs, data->img_dims, CFL_SIZE); md_calc_strides(ND, data->trj_strs, data->trj_dims, CFL_SIZE); md_calc_strides(ND, data->ksp_strs, data->ksp_dims, CFL_SIZE); data->weights = NULL; if (NULL != weights) { md_singleton_dims(ND, data->wgh_dims); md_select_dims(N, ~MD_BIT(0), data->wgh_dims, data->trj_dims); md_calc_strides(ND, data->wgh_strs, data->wgh_dims, CFL_SIZE); complex float* tmp = md_alloc(ND, data->wgh_dims, CFL_SIZE); md_copy(ND, data->wgh_dims, tmp, weights, CFL_SIZE); data->weights = tmp; } complex float* roll = md_alloc(ND, data->img_dims, CFL_SIZE); rolloff_correction(2., data->width, data->beta, data->img_dims, roll); data->roll = roll; complex float* linphase = compute_linphases(N, data->lph_dims, data->img_dims); md_calc_strides(ND, data->lph_strs, data->lph_dims, CFL_SIZE); if (!conf.toeplitz) md_zmul2(ND, data->lph_dims, data->lph_strs, linphase, data->lph_strs, linphase, data->img_strs, data->roll); fftmod(ND, data->lph_dims, FFT_FLAGS, linphase, linphase); fftscale(ND, data->lph_dims, FFT_FLAGS, linphase, linphase); // md_zsmul(ND, data->lph_dims, linphase, linphase, 1. / (float)(data->trj_dims[1] * data->trj_dims[2])); complex float* fftm = md_alloc(ND, data->img_dims, CFL_SIZE); md_zfill(ND, data->img_dims, fftm, 1.); fftmod(ND, data->img_dims, FFT_FLAGS, fftm, fftm); data->fftmod = fftm; data->linphase = linphase; data->psf = NULL; if (conf.toeplitz) { #if 0 md_copy_dims(ND, data->psf_dims, data->lph_dims); #else md_copy_dims(3, data->psf_dims, data->lph_dims); md_copy_dims(ND - 3, data->psf_dims + 3, data->trj_dims + 3); data->psf_dims[N] = data->lph_dims[N]; #endif md_calc_strides(ND, data->psf_strs, data->psf_dims, CFL_SIZE); data->psf = compute_psf2(N, data->psf_dims, data->trj_dims, data->traj, data->weights); } md_copy_dims(ND, data->cml_dims, data->cim_dims); data->cml_dims[N + 0] = data->lph_dims[N + 0]; md_calc_strides(ND, data->cml_strs, data->cml_dims, CFL_SIZE); data->cm2_dims = xmalloc(ND * sizeof(long)); // ! md_copy_dims(ND, data->cm2_dims, data->cim_dims); for (int i = 0; i < 3; i++) data->cm2_dims[i] = (1 == cim_dims[i]) ? 1 : (2 * cim_dims[i]); data->grid = md_alloc(ND, data->cml_dims, CFL_SIZE); data->fft_op = linop_fft_create(ND, data->cml_dims, FFT_FLAGS, use_gpu); return linop_create(N, ksp_dims, N, cim_dims, data, nufft_apply, nufft_apply_adjoint, nufft_apply_normal, NULL, nufft_free_data); }
/** * Efficiently chain two matrix linops by multiplying the actual matrices together. * Stores a copy of the new matrix. * Returns: C = B A * * @param a first matrix (applied to input) * @param b second matrix (applied to output of first matrix) */ struct linop_s* linop_matrix_chain(const struct linop_s* a, const struct linop_s* b) { const struct operator_matrix_s* a_data = CAST_DOWN(operator_matrix_s, linop_get_data(a)); const struct operator_matrix_s* b_data = CAST_DOWN(operator_matrix_s, linop_get_data(b)); // check compatibility assert(linop_codomain(a)->N == linop_domain(b)->N); assert(md_check_compat(linop_codomain(a)->N, 0u, linop_codomain(a)->dims, linop_domain(b)->dims)); unsigned int D = linop_domain(a)->N; unsigned long outB_flags = md_nontriv_dims(D, linop_codomain(b)->dims); unsigned long inB_flags = md_nontriv_dims(D, linop_domain(b)->dims); unsigned long delB_flags = inB_flags & ~outB_flags; unsigned int N = a_data->N; assert(N == 2 * D); long in_dims[N]; md_copy_dims(N, in_dims, a_data->in_dims); long matA_dims[N]; md_copy_dims(N, matA_dims, a_data->mat_dims); long matB_dims[N]; md_copy_dims(N, matB_dims, b_data->mat_dims); long out_dims[N]; md_copy_dims(N, out_dims, b_data->out_dims); for (unsigned int i = 0; i < D; i++) { if (MD_IS_SET(delB_flags, i)) { matA_dims[2 * i + 0] = a_data->mat_dims[2 * i + 1]; matA_dims[2 * i + 1] = a_data->mat_dims[2 * i + 0]; in_dims[2 * i + 0] = a_data->in_dims[2 * i + 1]; in_dims[2 * i + 1] = a_data->in_dims[2 * i + 0]; } } long matrix_dims[N]; md_singleton_dims(N, matrix_dims); unsigned long iflags = md_nontriv_dims(N, in_dims); unsigned long oflags = md_nontriv_dims(N, out_dims); unsigned long flags = iflags | oflags; // we combine a and b and sum over dims not in input or output md_max_dims(N, flags, matrix_dims, matA_dims, matB_dims); debug_printf(DP_DEBUG1, "tensor chain: %ld x %ld -> %ld\n", md_calc_size(N, matA_dims), md_calc_size(N, matB_dims), md_calc_size(N, matrix_dims)); complex float* matrix = md_alloc(N, matrix_dims, CFL_SIZE); debug_print_dims(DP_DEBUG2, N, matrix_dims); debug_print_dims(DP_DEBUG2, N, in_dims); debug_print_dims(DP_DEBUG2, N, matA_dims); debug_print_dims(DP_DEBUG2, N, matB_dims); debug_print_dims(DP_DEBUG2, N, out_dims); md_ztenmul(N, matrix_dims, matrix, matA_dims, a_data->mat, matB_dims, b_data->mat); // priv2 takes our doubled dimensions struct operator_matrix_s* data = linop_matrix_priv2(N, out_dims, in_dims, matrix_dims, matrix); /* although we internally use different dimensions we define the * correct interface */ struct linop_s* c = linop_create(linop_codomain(b)->N, linop_codomain(b)->dims, linop_domain(a)->N, linop_domain(a)->dims, CAST_UP(data), linop_matrix_apply, linop_matrix_apply_adjoint, linop_matrix_apply_normal, NULL, linop_matrix_del); md_free(matrix); return c; }
int main_nufft(int argc, char* argv[]) { bool adjoint = false; bool inverse = false; bool use_gpu = false; bool precond = false; bool dft = false; struct nufft_conf_s conf = nufft_conf_defaults; struct iter_conjgrad_conf cgconf = iter_conjgrad_defaults; long coilim_vec[3] = { 0 }; float lambda = 0.; const struct opt_s opts[] = { OPT_SET('a', &adjoint, "adjoint"), OPT_SET('i', &inverse, "inverse"), OPT_VEC3('d', &coilim_vec, "x:y:z", "dimensions"), OPT_VEC3('D', &coilim_vec, "", "()"), OPT_SET('t', &conf.toeplitz, "Toeplitz embedding for inverse NUFFT"), OPT_SET('c', &precond, "Preconditioning for inverse NUFFT"), OPT_FLOAT('l', &lambda, "lambda", "l2 regularization"), OPT_UINT('m', &cgconf.maxiter, "", "()"), OPT_SET('s', &dft, "DFT"), }; cmdline(&argc, argv, 3, 3, usage_str, help_str, ARRAY_SIZE(opts), opts); long coilim_dims[DIMS] = { 0 }; md_copy_dims(3, coilim_dims, coilim_vec); // Read trajectory long traj_dims[DIMS]; complex float* traj = load_cfl(argv[1], DIMS, traj_dims); assert(3 == traj_dims[0]); num_init(); if (inverse || adjoint) { long ksp_dims[DIMS]; const complex float* ksp = load_cfl(argv[2], DIMS, ksp_dims); assert(1 == ksp_dims[0]); assert(md_check_compat(DIMS, ~(PHS1_FLAG|PHS2_FLAG), ksp_dims, traj_dims)); md_copy_dims(DIMS - 3, coilim_dims + 3, ksp_dims + 3); if (0 == md_calc_size(DIMS, coilim_dims)) { estimate_im_dims(DIMS, coilim_dims, traj_dims, traj); debug_printf(DP_INFO, "Est. image size: %ld %ld %ld\n", coilim_dims[0], coilim_dims[1], coilim_dims[2]); } complex float* img = create_cfl(argv[3], DIMS, coilim_dims); md_clear(DIMS, coilim_dims, img, CFL_SIZE); const struct linop_s* nufft_op; if (!dft) nufft_op = nufft_create(DIMS, ksp_dims, coilim_dims, traj_dims, traj, NULL, conf, use_gpu); else nufft_op = nudft_create(DIMS, FFT_FLAGS, ksp_dims, coilim_dims, traj_dims, traj); if (inverse) { const struct operator_s* precond_op = NULL; if (conf.toeplitz && precond) precond_op = nufft_precond_create(nufft_op); lsqr(DIMS, &(struct lsqr_conf){ lambda }, iter_conjgrad, CAST_UP(&cgconf), nufft_op, NULL, coilim_dims, img, ksp_dims, ksp, precond_op); if (conf.toeplitz && precond) operator_free(precond_op); } else {
void iwt2(unsigned int N, unsigned int flags, const long shifts[N], const long odims[N], const long ostr[N], complex float* out, const long idims[N], const long istr[N], const complex float* in, const long minsize[N], const long flen, const float filter[2][2][flen]) { assert(wavelet_check_dims(N, flags, odims, minsize)); if (0 == flags) { // note: recursion does *not* end here assert(md_check_compat(N, 0u, odims, idims)); md_copy2(N, idims, ostr, out, istr, in, CFL_SIZE); return; } // check input dimensions long idims2[N]; wavelet_coeffs2(N, flags, idims2, odims, minsize, flen); assert(md_check_compat(N, 0u, idims2, idims)); long wdims2[2 * N]; wavelet_dims(N, flags, wdims2, odims, flen); // only consider transform dims... long dims1[N]; md_select_dims(N, flags, dims1, odims); long wdims[2 * N]; wavelet_dims(N, flags, wdims, dims1, flen); long level_coeffs = md_calc_size(2 * N, wdims); // ... which get embedded in dimension b unsigned int b = ffs(flags) - 1; long istr2[2 * N]; md_calc_strides(2 * N, istr2, wdims, istr[b]); // merge with original strides for (unsigned int i = 0; i < N; i++) if (!MD_IS_SET(flags, i)) istr2[i] = istr[i]; assert(idims[b] >= level_coeffs); long offset = (idims[b] - level_coeffs) * (istr[b] / CFL_SIZE); long bands = md_calc_size(N, wdims + N); long coeffs = md_calc_size(N, wdims + 0); // subtract coefficients in high band idims2[b] -= (bands - 1) * coeffs; assert(idims2[b] > 0); debug_printf(DP_DEBUG4, "ifwt2: flags:%d lcoeffs:%ld coeffs:%ld (space:%ld) bands:%ld str:%ld off:%ld\n", flags, level_coeffs, coeffs, idims2[b], bands, istr[b], offset / ostr[b]); // fix me we need temp storage complex float* tmp = md_alloc_sameplace(2 * N, wdims2, CFL_SIZE, out); long tstr[2 * N]; md_calc_strides(2 * N, tstr, wdims2, CFL_SIZE); md_copy2(2 * N, wdims2, tstr, tmp, istr2, in + offset, CFL_SIZE); long shifts0[N]; for (unsigned int i = 0; i < N; i++) shifts0[i] = 0; unsigned int flags2 = wavelet_filter_flags(N, flags, wdims, minsize); assert((0 == offset) == (0u == flags2)); if (0u != flags2) { long idims3[N]; wavelet_coeffs2(N, flags2, idims3, wdims2, minsize, flen); long istr3[N]; embed(N, flags, istr3, idims3, istr); iwt2(N, flags2, shifts0, wdims2, tstr, tmp, idims3, istr3, in, minsize, flen, filter); } iwtN(N, flags, shifts, odims, ostr, out, tstr, tmp, flen, filter); md_free(tmp); }
int main_nufft(int argc, char* argv[]) { int c; bool adjoint = false; bool inverse = false; bool use_gpu = false; bool sizeinit = false; struct nufft_conf_s conf = nufft_conf_defaults; struct iter_conjgrad_conf cgconf = iter_conjgrad_defaults; long coilim_dims[DIMS]; md_singleton_dims(DIMS, coilim_dims); float lambda = 0.; while (-1 != (c = getopt(argc, argv, "d:m:l:aiht"))) { switch (c) { case 'i': inverse = true; break; case 'a': adjoint = true; break; case 'd': sscanf(optarg, "%ld:%ld:%ld", &coilim_dims[0], &coilim_dims[1], &coilim_dims[2]); sizeinit = true; break; case 'm': cgconf.maxiter = atoi(optarg); break; case 'l': lambda = atof(optarg); break; case 't': conf.toeplitz = true; break; case 'h': usage(argv[0], stdout); help(); exit(0); default: usage(argv[0], stderr); exit(1); } } if (argc - optind != 3) { usage(argv[0], stderr); exit(1); } // Read trajectory long traj_dims[DIMS]; complex float* traj = load_cfl(argv[optind + 0], DIMS, traj_dims); assert(3 == traj_dims[0]); num_init(); if (inverse || adjoint) { long ksp_dims[DIMS]; const complex float* ksp = load_cfl(argv[optind + 1], DIMS, ksp_dims); assert(1 == ksp_dims[0]); assert(md_check_compat(DIMS, ~(PHS1_FLAG|PHS2_FLAG), ksp_dims, traj_dims)); md_copy_dims(DIMS - 3, coilim_dims + 3, ksp_dims + 3); if (!sizeinit) { estimate_im_dims(DIMS, coilim_dims, traj_dims, traj); debug_printf(DP_INFO, "Est. image size: %ld %ld %ld\n", coilim_dims[0], coilim_dims[1], coilim_dims[2]); } complex float* img = create_cfl(argv[optind + 2], DIMS, coilim_dims); md_clear(DIMS, coilim_dims, img, CFL_SIZE); const struct linop_s* nufft_op = nufft_create(DIMS, ksp_dims, coilim_dims, traj_dims, traj, NULL, conf, use_gpu); if (inverse) { lsqr(DIMS, &(struct lsqr_conf){ lambda }, iter_conjgrad, &cgconf, nufft_op, NULL, coilim_dims, img, ksp_dims, ksp); } else {
int main_rsense(int argc, char* argv[]) { bool usegpu = false; int maps = 2; int ctrsh = 0.; bool sec = false; bool scale_im = false; const char* pat_file = NULL; struct sense_conf sconf = sense_defaults; struct grecon_conf conf = { NULL, &sconf, false, false, false, true, 30, 0.95, 0. }; int c; while (-1 != (c = getopt(argc, argv, "l:r:s:i:p:Sgh"))) { switch(c) { case 'r': conf.lambda = atof(optarg); break; case 's': conf.step = atof(optarg); break; case 'i': conf.maxiter = atoi(optarg); break; case 'l': if (1 == atoi(optarg)) conf.l1wav = true; else if (2 == atoi(optarg)) conf.l1wav = false; else { usage(argv[0], stderr); exit(1); } break; case 'S': scale_im = true; break; case 'h': usage(argv[0], stdout); help(); exit(0); case 'g': usegpu = true; break; case 'p': pat_file = strdup(optarg); break; default: usage(argv[0], stderr); exit(1); } } if (argc - optind != 3) { usage(argv[0], stderr); exit(1); } int N = DIMS; long dims[N]; long img_dims[N]; long ksp_dims[N]; long sens_dims[N]; complex float* kspace_data = load_cfl(argv[optind + 0], N, ksp_dims); complex float* sens_maps = load_cfl(argv[optind + 1], N, sens_dims); assert(1 == ksp_dims[MAPS_DIM]); md_copy_dims(N, dims, ksp_dims); if (!sec) { dims[MAPS_DIM] = sens_dims[MAPS_DIM]; } else { assert(maps <= ksp_dims[COIL_DIM]); dims[MAPS_DIM] = maps; } for (int i = 0; i < 4; i++) { // sizes2[4] may be > 1 if (ksp_dims[i] != dims[i]) { fprintf(stderr, "Dimensions of kspace and sensitivities do not match!\n"); exit(1); } } complex float* pattern = NULL; long pat_dims[DIMS]; if (NULL != pat_file) { pattern = load_cfl(pat_file, DIMS, pat_dims); assert(md_check_compat(DIMS, COIL_FLAG, ksp_dims, pat_dims)); } debug_printf(DP_INFO, "%ld map(s)\n", dims[MAPS_DIM]); if (conf.l1wav) debug_printf(DP_INFO, "l1-wavelet regularization\n"); md_select_dims(N, ~COIL_FLAG, img_dims, dims); (usegpu ? num_init_gpu : num_init)(); // float scaling = estimate_scaling(ksp_dims, sens_maps, kspace_data); float scaling = estimate_scaling(ksp_dims, NULL, kspace_data); debug_printf(DP_INFO, "Scaling: %f\n", scaling); if (0. != scaling) md_zsmul(N, ksp_dims, kspace_data, kspace_data, 1. / scaling); debug_printf(DP_INFO, "Readout FFT..\n"); ifftuc(N, ksp_dims, READ_FLAG, kspace_data, kspace_data); debug_printf(DP_INFO, "Done.\n"); complex float* image = create_cfl(argv[optind + 2], N, img_dims); debug_printf(DP_INFO, "Reconstruction...\n"); struct ecalib_conf calib; if (sec) { calib = ecalib_defaults; calib.crop = ctrsh; conf.calib = &calib; } rgrecon(&conf, dims, image, sens_dims, sens_maps, pat_dims, pattern, kspace_data, usegpu); if (scale_im) md_zsmul(DIMS, img_dims, image, image, scaling); debug_printf(DP_INFO, "Done.\n"); unmap_cfl(N, img_dims, image); unmap_cfl(N, ksp_dims, kspace_data); unmap_cfl(N, sens_dims, sens_maps); exit(0); }