void direct_calib(const long dims[5], complex float* sens, const long caldims[5], const complex float* data) { complex float* tmp = md_alloc(5, caldims, CFL_SIZE); assert(1 == caldims[4]); assert(1 == dims[4]); md_copy(5, caldims, tmp, data, CFL_SIZE); // apply Kaiser-Bessel Window beta=4 for (int z = 0; z < caldims[2]; z++) for (int y = 0; y < caldims[1]; y++) for (int x = 0; x < caldims[0]; x++) for (int c = 0; c < caldims[3]; c++) tmp[((c * caldims[2] + z) * caldims[1] + y) * caldims[0] + x] *= kaiser(4., caldims[2], z) * kaiser(4., caldims[1], y) * kaiser(4., caldims[0], x); md_resize_center(5, dims, sens, caldims, tmp, CFL_SIZE); ifftc(5, dims, 7, sens, sens); long dims1[5]; md_select_dims(5, ~MD_BIT(COIL_DIM), dims1, dims); complex float* img = md_alloc(5, dims1, CFL_SIZE); md_zrss(5, dims, COIL_FLAG, img, sens); #if 1 long T = md_calc_size(5, dims1); for (int i = 0; i < T; i++) for (int j = 0; j < dims[COIL_DIM]; j++) sens[j * T + i] *= (cabs(img[i]) == 0.) ? 0. : (1. / cabs(img[i])); #endif md_free(img); }
static void sense_reco(struct sense_data* data, complex float* imgs, const complex float* kspace) { complex float* adj = md_alloc(DIMS, data->imgs_dims, CFL_SIZE); md_clear(DIMS, data->imgs_dims, imgs, CFL_SIZE); sense_adjoint(data, adj, kspace); long size = md_calc_size(DIMS, data->imgs_dims); conjgrad(100, data->alpha, 1.E-3, 2 * size, data, &cpu_iter_ops, sense_normal, (float*)imgs, (const float*)adj, NULL, NULL, NULL); md_free(adj); }
int main_mip(int argc, char* argv[argc]) { bool mIP = false; const struct opt_s opts[] = { OPT_SET('m', &mIP, "minimum" ), }; cmdline(&argc, argv, 3, 3, usage_str, help_str, ARRAY_SIZE(opts), opts); unsigned int flags = atoi(argv[1]); long idims[DIMS]; complex float* in = load_cfl(argv[2], DIMS, idims); long odims[DIMS]; md_select_dims(DIMS, ~flags, odims, idims); complex float* out = create_cfl(argv[3], DIMS, odims); complex float* tmp = md_alloc(DIMS, idims, CFL_SIZE); md_zabs(DIMS, idims, tmp, in); long istr[DIMS]; long ostr[DIMS]; md_calc_strides(DIMS, istr, idims, CFL_SIZE); md_calc_strides(DIMS, ostr, odims, CFL_SIZE); md_clear(DIMS, odims, out, CFL_SIZE); md_max2(DIMS, idims, ostr, (float*)out, ostr, (const float*)out, istr, (const float*)tmp); if (mIP) { // need result of max in output md_min2(DIMS, idims, ostr, (float*)out, ostr, (const float*)out, istr, (const float*)tmp); } md_free(tmp); unmap_cfl(DIMS, idims, in); unmap_cfl(DIMS, odims, out); exit(0); }
void md_gaussian_rand(unsigned int D, const long dims[D], complex float* dst) { #ifdef USE_CUDA if (cuda_ondevice(dst)) { complex float* tmp = md_alloc(D, dims, sizeof(complex float)); md_gaussian_rand(D, dims, tmp); md_copy(D, dims, dst, tmp, sizeof(complex float)); md_free(tmp); return; } #endif //#pragma omp parallel for for (long i = 0; i < md_calc_size(D, dims); i++) dst[i] = (float)gaussian_rand(); }
static void nufft_apply_normal(const void* _data, complex float* dst, const complex float* src) { const struct nufft_data* data = _data; if (data->conf.toeplitz) { toeplitz_mult(data, dst, src); } else { complex float* tmp_ksp = md_alloc(data->N + 3, data->ksp_dims, CFL_SIZE); nufft_apply((const void*)data, tmp_ksp, src); nufft_apply_adjoint((const void*)data, dst, tmp_ksp); md_free(tmp_ksp); } }
static complex float* compute_linphases(unsigned int N, long lph_dims[N + 3], const long img_dims[N + 3]) { float shifts[8][3]; int s = 0; for(int i = 0; i < 8; i++) { bool skip = false; for(int j = 0; j < 3; j++) { shifts[s][j] = 0.; if (MD_IS_SET(i, j)) { skip = skip || (1 == img_dims[j]); shifts[s][j] = -0.5; } } if (!skip) s++; } unsigned int ND = N + 3; md_select_dims(ND, FFT_FLAGS, lph_dims, img_dims); lph_dims[N + 0] = s; complex float* linphase = md_alloc(ND, lph_dims, CFL_SIZE); for(int i = 0; i < s; i++) { float shifts2[ND]; for (unsigned int j = 0; j < ND; j++) shifts2[j] = 0.; shifts2[0] = shifts[i][0]; shifts2[1] = shifts[i][1]; shifts2[2] = shifts[i][2]; linear_phase(ND, img_dims, shifts2, linphase + i * md_calc_size(ND, img_dims)); } return linphase; }
void sum_apply_normal(const void* _data, complex float* dst, const complex float* src) { struct sum_data* data = (struct sum_data*)_data; if (NULL == data->tmp) { #ifdef USE_CUDA data->tmp = (data->use_gpu ? md_alloc_gpu : md_alloc)(DIMS, data->img_dims, CFL_SIZE); #else data->tmp = md_alloc(DIMS, data->img_dims, CFL_SIZE); #endif } sum_apply(_data, data->tmp, src); sum_apply_adjoint( _data, dst, data->tmp); }
static bool test_md_zavg_flags(unsigned int D, const long idims[D], unsigned int flags, const complex float* in, const complex float* out_ref, bool wavg) { long odims[D]; md_select_dims(D, ~flags, odims, idims); complex float* out = md_alloc(D, odims, CFL_SIZE); (wavg ? md_zwavg : md_zavg)(D, idims, flags, out, in); float err = md_znrmse(D, odims, out_ref, out); md_free(out); UT_ASSERT(err < UT_TOL); return true; }
void overlapandadd(int N, const long dims[N], const long blk[N], complex float* dst, complex float* src1, const long dim2[N], complex float* src2) { long ndims[2 * N]; long L[2 * N]; long ndim2[2 * N]; long ndim3[2 * N]; for (int i = 0; i < N; i++) { assert(0 == dims[i] % blk[i]); assert(dim2[i] <= blk[i]); ndims[i * 2 + 1] = dims[i] / blk[i]; ndims[i * 2 + 0] = blk[i]; L[i * 2 + 1] = dims[i] / blk[i]; L[i * 2 + 0] = blk[i] + dim2[i] - 1; ndim2[i * 2 + 1] = 1; ndim2[i * 2 + 0] = dim2[i]; ndim3[i * 2 + 1] = dims[i] / blk[i] + 1; ndim3[i * 2 + 0] = blk[i]; } complex float* tmp = md_alloc(2 * N, L, CFL_SIZE); // conv_causal_extend(2 * N, L, tmp, ndims, src1, ndim2, src2); conv(2 * N, ~0, CONV_EXTENDED, CONV_CAUSAL, L, tmp, ndims, src1, ndim2, src2); // [------++++|||||||| //long str1[2 * N]; long str2[2 * N]; long str3[2 * N]; //md_calc_strides(2 * N, str1, ndims, 8); md_calc_strides(2 * N, str2, L, 8); md_calc_strides(2 * N, str3, ndim3, 8); md_clear(2 * N, ndim3, dst, CFL_SIZE); md_zadd2(2 * N, L, str3, dst, str3, dst, str2, tmp); md_free(tmp); }
void overlapandsave(int N, const long dims[N], const long blk[N], complex float* dst, complex float* src1, const long dim2[N], complex float* src2) { // [------++++ // [------ long ndims[2 * N]; long L[2 * N]; long ndim2[2 * N]; long ndim3[2 * N]; for (int i = 0; i < N; i++) { assert(0 == dims[i] % blk[i]); assert(dim2[i] <= blk[i]); ndims[i * 2 + 1] = dims[i] / blk[i]; ndims[i * 2 + 0] = blk[i]; L[i * 2 + 1] = dims[i] / blk[i]; L[i * 2 + 0] = blk[i] + dim2[i] - 1; ndim2[i * 2 + 1] = 1; ndim2[i * 2 + 0] = dim2[i]; ndim3[i * 2 + 1] = dims[i] / blk[i] - 0; ndim3[i * 2 + 0] = blk[i]; } complex float* tmp = md_alloc(2 * N, L, CFL_SIZE); long str1[2 * N]; long str2[2 * N]; long str3[2 * N]; md_calc_strides(2 * N, str1, ndims, 8); md_calc_strides(2 * N, str2, L, 8); md_calc_strides(2 * N, str3, ndim3, 8); md_clear(2 * N, L, tmp, 8); md_copy2(2 * N, ndim3, str2, tmp, str1, src1, 8); conv(2 * N, ~0, CONV_VALID, CONV_CAUSAL, ndims, dst, L, tmp, ndim2, src2); md_free(tmp); }
void caltwo(const struct ecalib_conf* conf, const long out_dims[DIMS], complex float* out_data, complex float* emaps, const long in_dims[4], complex float* in_data, const long msk_dims[3], const bool* msk) { long xx = out_dims[0]; long yy = out_dims[1]; long zz = out_dims[2]; long xh = in_dims[0]; long yh = in_dims[1]; long zh = in_dims[2]; long channels = out_dims[3]; long cosize = channels * (channels + 1) / 2; assert(DIMS >= 5); assert(1 == md_calc_size(DIMS - 5, out_dims + 5)); assert(in_dims[3] == cosize); long cov_dims[4] = { xh, yh, zh, cosize }; long covbig_dims[4] = { xx, yy, zz, cosize }; assert(((xx == 1) && (xh == 1)) || (xx >= xh)); assert(((yy == 1) && (yh == 1)) || (yy >= yh)); assert(((zz == 1) && (zh == 1)) || (zz >= zh)); assert((1 == xh) || (0 == xh % 2)); assert((1 == yh) || (0 == yh % 2)); assert((1 == zh) || (0 == zh % 2)); complex float* imgcov2 = md_alloc(4, covbig_dims, CFL_SIZE); debug_printf(DP_DEBUG1, "Resize...\n"); sinc_zeropad(4, covbig_dims, imgcov2, cov_dims, in_data); debug_printf(DP_DEBUG1, "Point-wise eigen-decomposition...\n"); eigenmaps(out_dims, out_data, emaps, imgcov2, msk_dims, msk, conf->orthiter, conf->usegpu); md_free(imgcov2); }
int main_itsense(int argc, char* argv[]) { mini_cmdline(argc, argv, 5, usage_str, help_str); struct sense_data data; data.alpha = atof(argv[1]); complex float* kspace = load_cfl(argv[3], DIMS, data.data_dims); data.sens = load_cfl(argv[2], DIMS, data.sens_dims); data.pattern = load_cfl(argv[4], DIMS, data.mask_dims); // 1 2 4 8 md_select_dims(DIMS, ~COIL_FLAG, data.imgs_dims, data.sens_dims); assert(check_dimensions(&data)); complex float* image = create_cfl(argv[5], DIMS, data.imgs_dims); md_calc_strides(DIMS, data.sens_strs, data.sens_dims, CFL_SIZE); md_calc_strides(DIMS, data.imgs_strs, data.imgs_dims, CFL_SIZE); md_calc_strides(DIMS, data.data_strs, data.data_dims, CFL_SIZE); md_calc_strides(DIMS, data.mask_strs, data.mask_dims, CFL_SIZE); data.tmp = md_alloc(DIMS, data.data_dims, CFL_SIZE); num_init(); sense_reco(&data, image, kspace); unmap_cfl(DIMS, data.imgs_dims, image); unmap_cfl(DIMS, data.mask_dims, data.pattern); unmap_cfl(DIMS, data.sens_dims, data.sens); unmap_cfl(DIMS, data.data_dims, data.sens); md_free(data.tmp); exit(0); }
static void perturb(const long dims[2], complex float* vecs, float amt) { complex float* noise = md_alloc(2, dims, CFL_SIZE); md_gaussian_rand(2, dims, noise); for (long j = 0; j < dims[1]; j++) { float nrm = md_znorm(1, dims, noise + j * dims[0]); complex float val = amt / nrm; md_zsmul(1, dims, noise + j * dims[0], noise + j * dims[0], val); } md_zadd(2, dims, vecs, vecs, noise); for (long j = 0; j < dims[1]; j++) { float nrm = md_znorm(1, dims, vecs + j * dims[0]); complex float val = 1 / nrm; md_zsmul(1, dims, vecs + j * dims[0], vecs + j * dims[0], val); } md_free(noise); }
static struct ufft_data* ufft_create_data(const long ksp_dims[DIMS], const long pat_dims[DIMS], const complex float* pat, unsigned int flags, bool use_gpu) { PTR_ALLOC(struct ufft_data, data); data->flags = flags; data->use_gpu = use_gpu; md_copy_dims(DIMS, data->pat_dims, pat_dims); md_copy_dims(DIMS, data->ksp_dims, ksp_dims); md_calc_strides(DIMS, data->pat_strs, pat_dims, CFL_SIZE); md_calc_strides(DIMS, data->ksp_strs, ksp_dims, CFL_SIZE); #ifdef USE_CUDA data->pat = (use_gpu ? md_alloc_gpu : md_alloc)(DIMS, data->pat_dims, CFL_SIZE); #else data->pat = md_alloc(DIMS, data->pat_dims, CFL_SIZE); #endif md_copy(DIMS, data->pat_dims, data->pat, pat, CFL_SIZE); data->fft_op = linop_fftc_create(DIMS, ksp_dims, flags, use_gpu); return data; }
static bool test_md_swap(void) { enum { N = 4 }; long dims[N] = { 10, 10, 10, 10 }; complex float* a = md_alloc(N, dims, sizeof(complex float)); complex float* b = md_alloc(N, dims, sizeof(complex float)); complex float* c = md_alloc(N, dims, sizeof(complex float)); md_gaussian_rand(N, dims, a); md_gaussian_rand(N, dims, b); md_gaussian_rand(N, dims, c); complex float* d = md_alloc(N, dims, sizeof(complex float)); complex float* e = md_alloc(N, dims, sizeof(complex float)); complex float* f = md_alloc(N, dims, sizeof(complex float)); md_copy(N, dims, d, a, sizeof(complex float)); md_copy(N, dims, e, b, sizeof(complex float)); md_copy(N, dims, f, c, sizeof(complex float)); md_circular_swap(3, N, dims, (void*[]){ a, b, c }, sizeof(complex float));
void walsh(const long bsize[3], const long dims[DIMS], complex float* sens, const long caldims[DIMS], const complex float* data) { assert(1 == caldims[MAPS_DIM]); assert(1 == dims[MAPS_DIM]); int channels = caldims[COIL_DIM]; int cosize = channels * (channels + 1) / 2; assert(dims[COIL_DIM] == cosize); long dims1[DIMS]; md_copy_dims(DIMS, dims1, dims); dims1[COIL_DIM] = channels; long kdims[4]; kdims[0] = MIN(bsize[0], dims[0]); kdims[1] = MIN(bsize[1], dims[1]); kdims[2] = MIN(bsize[2], dims[2]); md_resize_center(DIMS, dims1, sens, caldims, data, CFL_SIZE); ifftc(DIMS, dims1, FFT_FLAGS, sens, sens); long odims[DIMS]; md_copy_dims(DIMS, odims, dims1); for (int i = 0; i < 3; i++) odims[i] = dims[i] + kdims[i] - 1; complex float* tmp = md_alloc(DIMS, odims, CFL_SIZE); #if 0 md_resizec(DIMS, odims, tmp, dims1, sens, CFL_SIZE); #else long cen[DIMS] = { 0 }; for (int i = 0; i < 3; i++) cen[i] = (odims[i] - dims[i] + 1) / 2; complex float* tmp1 = md_alloc(DIMS, odims, CFL_SIZE); md_circ_ext(DIMS, odims, tmp1, dims1, sens, CFL_SIZE); // md_resize(DIMS, odims, tmp1, dims1, sens, CFL_SIZE); md_circ_shift(DIMS, odims, cen, tmp, tmp1, CFL_SIZE); md_free(tmp1); #endif long calmat_dims[2]; complex float* cm = calibration_matrix(calmat_dims, kdims, odims, tmp); md_free(tmp); int xh = dims[0]; int yh = dims[1]; int zh = dims[2]; int pixels = calmat_dims[1] / channels; #pragma omp parallel for for (int k = 0; k < zh; k++) { complex float in[channels][pixels]; complex float cov[cosize]; for (int j = 0; j < yh; j++) { for (int i = 0; i < xh; i++) { for (int c = 0; c < channels; c++) for (int p = 0; p < pixels; p++) in[c][p] = cm[((((c * pixels + p) * zh) + k) * yh + j) * xh + i]; gram_matrix2(channels, cov, pixels, in); for (int l = 0; l < cosize; l++) sens[(((l * zh) + k) * yh + j) * xh + i] = cov[l]; } } } }
int main_nlinv(int argc, char* argv[]) { int iter = 8; float l1 = -1.; bool waterfat = false; bool rvc = false; bool normalize = true; float restrict_fov = -1.; float csh[3] = { 0., 0., 0. }; bool usegpu = false; const char* psf = NULL; const struct opt_s opts[] = { { 'l', true, opt_float, &l1, NULL }, { 'i', true, opt_int, &iter, NULL }, { 'c', false, opt_set, &rvc, NULL }, { 'N', false, opt_clear, &normalize, NULL }, { 'f', true, opt_float, &restrict_fov, NULL }, { 'p', true, opt_string, &psf, NULL }, { 'g', false, opt_set, &usegpu, NULL }, }; cmdline(&argc, argv, 2, 3, usage_str, help_str, ARRAY_SIZE(opts), opts); num_init(); assert(iter > 0); long ksp_dims[DIMS]; complex float* kspace_data = load_cfl(argv[1], DIMS, ksp_dims); long dims[DIMS]; md_copy_dims(DIMS, dims, ksp_dims); if (waterfat) dims[CSHIFT_DIM] = 2; long img_dims[DIMS]; md_select_dims(DIMS, FFT_FLAGS|CSHIFT_FLAG, img_dims, dims); long img_strs[DIMS]; md_calc_strides(DIMS, img_strs, img_dims, CFL_SIZE); complex float* image = create_cfl(argv[2], DIMS, img_dims); long msk_dims[DIMS]; md_select_dims(DIMS, FFT_FLAGS, msk_dims, dims); long msk_strs[DIMS]; md_calc_strides(DIMS, msk_strs, msk_dims, CFL_SIZE); complex float* mask; complex float* norm = md_alloc(DIMS, msk_dims, CFL_SIZE); complex float* sens; if (4 == argc) { sens = create_cfl(argv[3], DIMS, ksp_dims); } else { sens = md_alloc(DIMS, ksp_dims, CFL_SIZE); } complex float* pattern = NULL; long pat_dims[DIMS]; if (NULL != psf) { pattern = load_cfl(psf, DIMS, pat_dims); // FIXME: check compatibility } else { pattern = md_alloc(DIMS, img_dims, CFL_SIZE); estimate_pattern(DIMS, ksp_dims, COIL_DIM, pattern, kspace_data); } if (waterfat) { size_t size = md_calc_size(DIMS, msk_dims); md_copy(DIMS, msk_dims, pattern + size, pattern, CFL_SIZE); long shift_dims[DIMS]; md_select_dims(DIMS, FFT_FLAGS, shift_dims, msk_dims); long shift_strs[DIMS]; md_calc_strides(DIMS, shift_strs, shift_dims, CFL_SIZE); complex float* shift = md_alloc(DIMS, shift_dims, CFL_SIZE); unsigned int X = shift_dims[READ_DIM]; unsigned int Y = shift_dims[PHS1_DIM]; unsigned int Z = shift_dims[PHS2_DIM]; for (unsigned int x = 0; x < X; x++) for (unsigned int y = 0; y < Y; y++) for (unsigned int z = 0; z < Z; z++) shift[(z * Z + y) * Y + x] = cexp(2.i * M_PI * ((csh[0] * x) / X + (csh[1] * y) / Y + (csh[2] * z) / Z)); md_zmul2(DIMS, msk_dims, msk_strs, pattern + size, msk_strs, pattern + size, shift_strs, shift); md_free(shift); } #if 0 float scaling = 1. / estimate_scaling(ksp_dims, NULL, kspace_data); #else float scaling = 100. / md_znorm(DIMS, ksp_dims, kspace_data); #endif debug_printf(DP_INFO, "Scaling: %f\n", scaling); md_zsmul(DIMS, ksp_dims, kspace_data, kspace_data, scaling); if (-1. == restrict_fov) { mask = md_alloc(DIMS, msk_dims, CFL_SIZE); md_zfill(DIMS, msk_dims, mask, 1.); } else { float restrict_dims[DIMS] = { [0 ... DIMS - 1] = 1. }; restrict_dims[0] = restrict_fov; restrict_dims[1] = restrict_fov; restrict_dims[2] = restrict_fov; mask = compute_mask(DIMS, msk_dims, restrict_dims); } #ifdef USE_CUDA if (usegpu) { complex float* kspace_gpu = md_alloc_gpu(DIMS, ksp_dims, CFL_SIZE); md_copy(DIMS, ksp_dims, kspace_gpu, kspace_data, CFL_SIZE); noir_recon(dims, iter, l1, image, NULL, pattern, mask, kspace_gpu, rvc, usegpu); md_free(kspace_gpu); md_zfill(DIMS, ksp_dims, sens, 1.); } else #endif noir_recon(dims, iter, l1, image, sens, pattern, mask, kspace_data, rvc, usegpu); if (normalize) { md_zrss(DIMS, ksp_dims, COIL_FLAG, norm, sens); md_zmul2(DIMS, img_dims, img_strs, image, img_strs, image, msk_strs, norm); } if (4 == argc) { long strs[DIMS]; md_calc_strides(DIMS, strs, ksp_dims, CFL_SIZE); if (norm) md_zdiv2(DIMS, ksp_dims, strs, sens, strs, sens, img_strs, norm); fftmod(DIMS, ksp_dims, FFT_FLAGS, sens, sens); unmap_cfl(DIMS, ksp_dims, sens); } else { md_free(sens); } md_free(norm); md_free(mask); if (NULL != psf) unmap_cfl(DIMS, pat_dims, pattern); else md_free(pattern); unmap_cfl(DIMS, img_dims, image); unmap_cfl(DIMS, ksp_dims, kspace_data); exit(0); }
int main_ecalib(int argc, char* argv[]) { long calsize[3] = { 24, 24, 24 }; int maps = 2; bool one = false; bool calcen = false; bool print_svals = false; struct ecalib_conf conf = ecalib_defaults; const struct opt_s opts[] = { OPT_FLOAT('t', &conf.threshold, "threshold", "This determined the size of the null-space."), OPT_FLOAT('c', &conf.crop, "crop_value", "Crop the sensitivities if the eigenvalue is smaller than {crop_value}."), OPT_VEC3('k', &conf.kdims, "ksize", "kernel size"), OPT_VEC3('K', &conf.kdims, "", "()"), OPT_VEC3('r', &calsize, "cal_size", "Limits the size of the calibration region."), OPT_VEC3('R', &calsize, "", "()"), OPT_INT('m', &maps, "maps", "Number of maps to compute."), OPT_SET('S', &conf.softcrop, "create maps with smooth transitions (Soft-SENSE)."), OPT_SET('W', &conf.weighting, "soft-weighting of the singular vectors."), OPT_SET('I', &conf.intensity, "intensity correction"), OPT_SET('1', &one, "perform only first part of the calibration"), OPT_CLEAR('P', &conf.rotphase, "Do not rotate the phase with respect to the first principal component"), OPT_CLEAR('O', &conf.orthiter, "()"), OPT_FLOAT('b', &conf.perturb, "", "()"), OPT_SET('V', &print_svals, "()"), OPT_SET('C', &calcen, "()"), OPT_SET('g', &conf.usegpu, "()"), OPT_FLOAT('p', &conf.percentsv, "", "()"), OPT_INT('n', &conf.numsv, "", "()"), OPT_FLOAT('v', &conf.var, "variance", "Variance of noise in data."), OPT_SET('a', &conf.automate, "Automatically pick thresholds."), OPT_INT('d', &debug_level, "level", "Debug level"), }; cmdline(&argc, argv, 2, 3, usage_str, help_str, ARRAY_SIZE(opts), opts); if (-1. != conf.percentsv) conf.threshold = -1.; if (-1 != conf.numsv) conf.threshold = -1.; if (conf.automate) { conf.crop = -1.; conf.weighting = true; } if (conf.weighting) { conf.numsv = -1.; conf.threshold = 0; conf.percentsv = -1.; conf.orthiter = false; } int N = DIMS; long ksp_dims[N]; complex float* in_data = load_cfl(argv[1], N, ksp_dims); // assert((kdims[0] < calsize_ro) && (kdims[1] < calsize_ro) && (kdims[2] < calsize_ro)); // assert((ksp_dims[0] == 1) || (calsize_ro < ksp_dims[0])); if (1 != ksp_dims[MAPS_DIM]) error("MAPS dimension is not of size one.\n"); long cal_dims[N]; complex float* cal_data = NULL; if (!calcen) { #ifdef USE_CC_EXTRACT_CALIB cal_data = cc_extract_calib(cal_dims, calsize, ksp_dims, in_data); #else cal_data = extract_calib(cal_dims, calsize, ksp_dims, in_data, false); #endif } else { for (int i = 0; i < 3; i++) cal_dims[i] = (calsize[i] < ksp_dims[i]) ? calsize[i] : ksp_dims[i]; for (int i = 3; i < N; i++) cal_dims[i] = ksp_dims[i]; cal_data = md_alloc(5, cal_dims, CFL_SIZE); md_resize_center(5, cal_dims, cal_data, ksp_dims, in_data, CFL_SIZE); } for (int i = 0; i < 3; i++) if (1 == ksp_dims[i]) conf.kdims[i] = 1; long channels = cal_dims[3]; unsigned int K = conf.kdims[0] * conf.kdims[1] * conf.kdims[2] * channels; float svals[K]; for (unsigned int i = 0; i < 3; i++) if ((1 == cal_dims[i]) && (1 != ksp_dims[i])) error("Calibration region not found!\n"); // To reproduce old results turn off rotation of phase. // conf.rotphase = false; // FIXME: we should scale the data (conf.usegpu ? num_init_gpu : num_init)(); if ((conf.var < 0) && (conf.weighting || (conf.crop < 0))) conf.var = estvar_calreg(conf.kdims, cal_dims, cal_data); if (one) { #if 0 long maps = out_dims[4]; assert(caldims[3] == out_dims[3]); assert(maps <= channels); #endif long cov_dims[4]; calone_dims(&conf, cov_dims, channels); complex float* imgcov = md_alloc(4, cov_dims, CFL_SIZE); calone(&conf, cov_dims, imgcov, K, svals, cal_dims, cal_data); complex float* out = create_cfl(argv[2], 4, cov_dims); md_copy(4, cov_dims, out, imgcov, CFL_SIZE); unmap_cfl(4, cov_dims, out); // caltwo(crthr, out_dims, out_data, emaps, cov_dims, imgcov, NULL, NULL); md_free(imgcov); } else { long out_dims[N]; long map_dims[N]; for (int i = 0; i < N; i++) { out_dims[i] = 1; map_dims[i] = 1; if ((i < 3) && (1 < conf.kdims[i])) { out_dims[i] = ksp_dims[i]; map_dims[i] = ksp_dims[i]; } } assert(maps <= ksp_dims[COIL_DIM]); out_dims[COIL_DIM] = ksp_dims[COIL_DIM]; out_dims[MAPS_DIM] = maps; map_dims[COIL_DIM] = 1; map_dims[MAPS_DIM] = maps; const char* emaps_file = NULL; if (4 == argc) emaps_file = argv[3]; complex float* out_data = create_cfl(argv[2], N, out_dims); complex float* emaps = (emaps_file ? create_cfl : anon_cfl)(emaps_file, N, map_dims); calib(&conf, out_dims, out_data, emaps, K, svals, cal_dims, cal_data); unmap_cfl(N, out_dims, out_data); unmap_cfl(N, map_dims, emaps); } if (print_svals) { for (unsigned int i = 0; i < K; i++) printf("SVALS %d %f\n", i, svals[i]); } printf("Done.\n"); unmap_cfl(N, ksp_dims, in_data); md_free(cal_data); return 0; }
int main_nufft(int argc, char* argv[]) { int c; bool adjoint = false; bool inverse = false; bool toeplitz = false; bool precond = false; bool use_gpu = false; bool two = false; bool calib = false; bool sizeinit = false; bool stoch = false; long coilim_dims[DIMS]; md_singleton_dims(DIMS, coilim_dims); int maxiter = 50; float lambda = 0.00; const char* pat_str = NULL; while (-1 != (c = getopt(argc, argv, "d:m:l:p:aihCto:w:2:c:S"))) { switch (c) { case '2': two = true; break; case 'i': inverse = true; break; case 'a': adjoint = true; break; case 'C': precond = true; break; case 'S': stoch = true; break; case 'c': calib = true; inverse = true; case 'd': sscanf(optarg, "%ld:%ld:%ld", &coilim_dims[0], &coilim_dims[1], &coilim_dims[2]); sizeinit = true; break; case 'm': maxiter = atoi(optarg); break; case 'p': pat_str = strdup(optarg); break; case 'l': lambda = atof(optarg); break; case 't': 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[2]; complex float* traj = load_cfl(argv[optind + 0], 2, traj_dims); assert(3 == traj_dims[0]); if (!sizeinit) estimate_im_dims(coilim_dims, traj_dims, traj); num_init(); // Load pattern / density compensation (if any) complex float* pat = NULL; long pat_dims[2]; if (pat_str) { pat = load_cfl(pat_str, 2, pat_dims); assert(pat_dims[0] == 1); assert(pat_dims[1] == traj_dims[1]); } if (inverse || adjoint) { long ksp_dims[DIMS]; const complex float* ksp = load_cfl(argv[optind + 1], DIMS, ksp_dims); coilim_dims[COIL_DIM] = ksp_dims[COIL_DIM]; long out_dims[DIMS]; if (calib) { md_singleton_dims(DIMS, out_dims); estimate_im_dims(out_dims, traj_dims, traj); out_dims[COIL_DIM] = ksp_dims[COIL_DIM]; } else { md_copy_dims(DIMS, out_dims, coilim_dims); } complex float* out = create_cfl(argv[optind + 2], DIMS, out_dims); complex float* img = out; if (calib) img = md_alloc(DIMS, coilim_dims, CFL_SIZE); md_clear(DIMS, coilim_dims, img, CFL_SIZE); struct iter_conjgrad_conf cgconf = iter_conjgrad_defaults; cgconf.maxiter = maxiter; cgconf.l2lambda = 0.; cgconf.tol = 0; const struct linop_s* nufft_op; // Get nufft_op if (two) #ifdef BERKELEY_SVN nufft_op = nufft2_create(ksp_dims, coilim_dims, traj, pat, toeplitz, precond, &cgconf, use_gpu); #else assert(!two); #endif else
int g_process_math_string(__g_handle hdl, char *string, pmda mdm, pmda chain, int *ret, void **p_ret, uint32_t flags, uint32_t int_flags) { g_setjmp(0, "g_process_math_string", NULL, NULL); char *ptr = string, *left, oper = 0x0; size_t i; size_t sin_len = strlen(string); if (sin_len == 0) { return 0; } //g_del_char(string, string_p, 0x20); int f_ret = 0; while (ptr[0]) { if (ptr[0] == 0x0 || ptr[0] == 0x23 || ptr[0] == 0x7D || ptr[0] == 0x29 || ptr[0] == 0x3A) { if (ptr[0] == 0x29) { if (!(int_flags & F_PROC_MATH_STR_INB)) { f_ret = 0; goto f_end; } else { *p_ret = ptr; } } else { /*if ((int_flags & F_PROC_MATH_STR_INB)) { return 12; }*/ } break; } while (ptr[0] == 0x20) { ptr++; } if (ptr[0] == 0x28) { if (ptr[1] == 0x29) { break; } pmda object = (pmda) md_alloc(chain, sizeof(mda)); if (NULL == object) { f_ret = -1; goto f_end; } md_init(object, 8); char *pms_ret = ""; ptr++; int r = g_process_math_string(hdl, ptr, object, chain, ret, (void*) &pms_ret, flags, int_flags | F_PROC_MATH_STR_INB); if (0 != r) { ERROR( "g_process_math_string (F_PROC_MATH_STR_INB): FAILED: [%d]: %s\n", r, pms_ret); md_free(object); f_ret = r; goto f_end; } else { __g_math math_c = (__g_math ) m_find_last_dtype(chain, chain->pos); __g_math math = (__g_math ) md_alloc(mdm, sizeof(_g_math)); if (NULL == math) { f_ret = 16; goto f_end; } if (NULL == math_c) { f_ret = 17; goto f_end; } math->next = object; math->flags |= F_MATH_NITEM; pms_ret++; ptr = pms_ret; math->flags |= (math_c->flags & F_MATH_TYPES); __g_math math_p = (__g_math ) m_find_prev_dtype(mdm, (p_md_obj) mdm->pos); math->_m_p = g_get_math_m_p(math, math_p); if (!(is_ascii_arith_bin_oper(ptr[0]))) { if (NULL == math_c->_m_p) { f_ret = 21; goto f_end; } math->op_t = m_get_op_proc(ptr[0], math_c); if ( NULL == math->op_t) { f_ret = 22; goto f_end; } //math->_m_p = math_c->_m_p; } math->vb = math_c->vb; math->l_off = math_c->l_off; if (ptr[0] == 0x0 || ptr[0] == 0x23 || ptr[0] == 0x7D || ptr[0] == 0x3A || ptr[0] == 0x29) { continue; } ptr++; continue; } } i = 0; left = ptr; uint32_t add_flags = 0; char in_dummy[8192]; if (ptr[0] == 0x5B) { void *l_next_ref; char *s_ptr = l_mppd_shell_ex(ptr, in_dummy, sizeof(in_dummy), &l_next_ref, 0x5B, 0x5D, F_MPPD_SHX_TZERO); if (NULL == s_ptr) { f_ret = 130; goto f_end; } if (NULL == l_next_ref || ((char*) l_next_ref)[0] == 0x0) { f_ret = 131; goto f_end; } left = s_ptr; ptr = l_next_ref; add_flags |= F_MATH_STRCONV; } else { if (ptr[0] == 0x2B || ptr[0] == 0x2D) { ptr++; } while (is_ascii_arith_bin_oper(ptr[0]) && ptr[0] && ptr[0] != 0x23 && ptr[0] != 0x7D && ptr[0] != 0x29 && ptr[0] != 0x3A && ptr[0] != 0x29 && ptr[0] != 0x20) { i++; ptr++; } if (!i) { f_ret = 1; goto f_end; } } if (ptr[0] && ptr[0] != 0x23 && ptr[0] != 0x7D && ptr[0] != 0x29 && ptr[0] != 0x3A && ptr[0] != 0x29) { if (is_ascii_arith_bin_oper(ptr[0])) { f_ret = 23; goto f_end; } if (ptr[0] == 0x3C || ptr[0] == 0x3E) { if (ptr[0] != ptr[1]) { f_ret = 2; goto f_end; } ptr++; } oper = ptr[0]; ptr++; } else { oper = 0x0; } __g_math mm; *ret = g_build_math_packet(hdl, left, oper, mdm, &mm, flags | add_flags); if (*ret) { f_ret = 6; goto f_end; } if (oper == 0x7E && (ptr[0] == 0x7D || ptr[0] == 0x29)) { *ret = g_build_math_packet(hdl, left, oper, mdm, NULL, flags | add_flags); if (*ret) { f_ret = 7; goto f_end; } } } f_end: ; //free(string_p); return f_ret; }
void overlapandsave2NE(int N, unsigned int flags, const long blk[N], const long odims[N], complex float* dst, const long dims1[N], complex float* src1, const long dims2[N], complex float* src2, const long mdims[N], complex float* msk) { long dims1B[N]; long tdims[2 * N]; long nodims[2 * N]; long ndims1[2 * N]; long ndims2[2 * N]; long shift[2 * N]; unsigned int nflags = 0; for (int i = 0; i < N; i++) { if (MD_IS_SET(flags, i)) { nflags = MD_SET(nflags, 2 * i); assert(1 == dims2[i] % 2); assert(0 == blk[i] % 2); assert(0 == dims1[i] % 2); assert(0 == odims[i] % blk[i]); assert(0 == dims1[i] % blk[i]); assert(dims1[i] == odims[i]); assert(dims2[i] <= blk[i]); assert(dims1[i] >= dims2[i]); // blocked output nodims[i * 2 + 1] = odims[i] / blk[i]; nodims[i * 2 + 0] = blk[i]; // expanded temporary storage tdims[i * 2 + 1] = dims1[i] / blk[i]; tdims[i * 2 + 0] = blk[i] + dims2[i] - 1; // blocked input // ---|---,---,---|--- // + +++ + // + +++ + // resized input dims1B[i] = dims1[i] + 2 * blk[i]; ndims1[i * 2 + 1] = dims1[i] / blk[i] + 2; // do we need two full blocks? ndims1[i * 2 + 0] = blk[i]; shift[i * 2 + 1] = 0; shift[i * 2 + 0] = blk[i] - (dims2[i] - 1) / 2; // kernel ndims2[i * 2 + 1] = 1; ndims2[i * 2 + 0] = dims2[i]; } else { nodims[i * 2 + 1] = 1; nodims[i * 2 + 0] = odims[i]; tdims[i * 2 + 1] = 1; tdims[i * 2 + 0] = dims1[i]; ndims1[i * 2 + 1] = 1; ndims1[i * 2 + 0] = dims1[i]; shift[i * 2 + 1] = 0; shift[i * 2 + 0] = 0; dims1B[i] = dims1[i]; ndims2[i * 2 + 1] = 1; ndims2[i * 2 + 0] = dims2[i]; } } complex float* src1B = md_alloc(N, dims1B, CFL_SIZE); complex float* tmp = md_alloc(2 * N, tdims, CFL_SIZE); complex float* tmpX = md_alloc(N, odims, CFL_SIZE); long str1[2 * N]; long str2[2 * N]; md_calc_strides(2 * N, str1, ndims1, sizeof(complex float)); md_calc_strides(2 * N, str2, tdims, sizeof(complex float)); long off = md_calc_offset(2 * N, str1, shift); md_resize_center(N, dims1B, src1B, dims1, src1, sizeof(complex float)); // we can loop here md_copy2(2 * N, tdims, str2, tmp, str1, ((void*)src1B) + off, sizeof(complex float)); conv(2 * N, nflags, CONV_VALID, CONV_SYMMETRIC, nodims, tmpX, tdims, tmp, ndims2, src2); long ostr[N]; long mstr[N]; md_calc_strides(N, ostr, odims, sizeof(complex float)); md_calc_strides(N, mstr, mdims, sizeof(complex float)); md_zmul2(N, odims, ostr, tmpX, ostr, tmpX, mstr, msk); convH(2 * N, nflags, CONV_VALID, CONV_SYMMETRIC, tdims, tmp, nodims, tmpX, ndims2, src2); md_clear(N, dims1B, src1B, sizeof(complex float)); md_zadd2(2 * N, tdims, str1, ((void*)src1B) + off, str1, ((void*)src1B) + off, str2, tmp); // md_resize_center(N, dims1, dst, dims1B, src1B, sizeof(complex float)); md_free(src1B); md_free(tmpX); md_free(tmp); }
int g_build_math_packet(__g_handle hdl, char *field, char oper, pmda mdm, __g_math *ret, uint32_t flags) { g_setjmp(0, "g_build_math_packet", NULL, NULL); int rt = 0; md_init(mdm, 16); __g_math p_math = (__g_math ) mdm->pos->ptr; __g_math math = (__g_math ) md_alloc(mdm, sizeof(_g_math)); if (!math) { rt = 1; goto end; } math->flags |= flags; if ((rt = g_get_math_g_t_ptr(hdl, field, math, 0, p_math))) { goto end; } if (!(math->flags & F_MATH_TYPES)) { rt = 6; goto end; } if (math->_m_p) { math->op_t = m_get_op_proc(oper, math); if ( NULL == math->op_t) { rt = 7; goto end; } /*if (oper == 0x7E) { math->flags |= F_MATH_IS_SQRT; }*/ } if (ret) { *ret = math; } end: if (rt) { md_unlink(mdm, mdm->pos); } return rt; }
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); }
// [RING] Caclucate intersection points static void calc_intersections(unsigned int Nint, unsigned int N, unsigned int no_intersec_sp, float dist[2][Nint], long idx[2][Nint], const float angles[N], const long kc_dims[DIMS], const complex float* kc, const int ROI) { long spoke_dims[DIMS]; md_copy_dims(DIMS, spoke_dims, kc_dims); spoke_dims[PHS2_DIM] = 1; complex float* spoke_i = md_alloc(DIMS, spoke_dims, CFL_SIZE); complex float* spoke_j = md_alloc(DIMS, spoke_dims, CFL_SIZE); long pos_i[DIMS] = { 0 }; long pos_j[DIMS] = { 0 }; long coilPixel_dims[DIMS]; md_copy_dims(DIMS, coilPixel_dims, spoke_dims); coilPixel_dims[PHS1_DIM] = 1; complex float* coilPixel_l = md_alloc(DIMS, coilPixel_dims, CFL_SIZE); complex float* coilPixel_m = md_alloc(DIMS, coilPixel_dims, CFL_SIZE); complex float* diff = md_alloc(DIMS, coilPixel_dims, CFL_SIZE); long diff_rss_dims[DIMS]; md_copy_dims(DIMS, diff_rss_dims, coilPixel_dims); diff_rss_dims[COIL_DIM] = 1; diff_rss_dims[PHS1_DIM] = 1; complex float* diff_rss = md_alloc(DIMS, diff_rss_dims, CFL_SIZE); long pos_l[DIMS] = { 0 }; long pos_m[DIMS] = { 0 }; // Array to store indices of spokes that build an angle close to pi/2 with the current spoke long intersec_sp[no_intersec_sp]; for (unsigned int i = 0; i < no_intersec_sp; i++) intersec_sp[i] = -1; // Boundaries for spoke comparison int myROI = ROI; myROI += (ROI % 2 == 0) ? 1 : 0; // make odd int low = 0; int high = myROI - 1; int count = 0; // Intersection determination for (unsigned int i = 0; i < N; i++) { pos_i[PHS2_DIM] = i; md_slice(DIMS, PHS2_FLAG, pos_i, kc_dims, spoke_i, kc, CFL_SIZE); find_intersec_sp(no_intersec_sp, intersec_sp, i, N, angles); for (unsigned int j = 0; j < no_intersec_sp; j++) { pos_j[PHS2_DIM] = intersec_sp[j]; md_slice(DIMS, PHS2_FLAG, pos_j, kc_dims, spoke_j, kc, CFL_SIZE); idx[0][i * no_intersec_sp + j] = i; idx[1][i * no_intersec_sp + j] = intersec_sp[j]; // Elementwise rss comparisson float rss = FLT_MAX; for (int l = low; l <= high; l++) { pos_l[PHS1_DIM] = l; md_copy_block(DIMS, pos_l, coilPixel_dims, coilPixel_l, spoke_dims, spoke_i, CFL_SIZE); for (int m = low; m <= high; m++) { pos_m[PHS1_DIM] = m; md_copy_block(DIMS, pos_m, coilPixel_dims, coilPixel_m, spoke_dims, spoke_j, CFL_SIZE); md_zsub(DIMS, coilPixel_dims, diff, coilPixel_l, coilPixel_m); md_zrss(DIMS, coilPixel_dims, PHS1_FLAG|COIL_FLAG, diff_rss, diff); if (cabsf(diff_rss[0]) < rss) { // New minimum found rss = cabsf(diff_rss[0]); dist[0][i * no_intersec_sp + j] = (l + 1/2 - ROI/2); dist[1][i * no_intersec_sp + j] = (m + 1/2 - ROI/2); } } } count++; } } #ifdef RING_PAPER // Print projection angles and corresponding offsets to files const char* idx_out = "projangle.txt"; FILE* fp = fopen(idx_out, "w"); const char* d_out = "offset.txt"; FILE* fp1 = fopen(d_out, "w"); for (unsigned int i = 0; i < N; i++) { for (unsigned int j = 0; j < no_intersec_sp; j++) { fprintf(fp, "%f \t %f\n", angles[idx[0][i * no_intersec_sp + j]], angles[idx[1][i * no_intersec_sp + j]]); fprintf(fp1, "%f \t %f\n", dist[0][i * no_intersec_sp + j], dist[1][i * no_intersec_sp + j]); } } fclose(fp); fclose(fp1); #endif md_free(spoke_i); md_free(spoke_j); md_free(coilPixel_l); md_free(coilPixel_m); md_free(diff); md_free(diff_rss); }
int main_pocsense(int argc, char* argv[]) { float alpha = 0.; int maxiter = 50; bool l1wav = false; float lambda = -1.; bool use_gpu = false; bool use_admm = false; float admm_rho = -1.; int l1type = 2; const struct opt_s opts[] = { { 'i', true, opt_int, &maxiter, NULL }, { 'r', true, opt_float, &alpha, " alpha\tregularization parameter" }, { 'l', true, opt_int, &l1type, "1/-l2\t\ttoggle l1-wavelet or l2 regularization" }, { 'g', false, opt_set, &use_gpu, NULL }, { 'o', true, opt_float, &lambda, NULL }, { 'm', true, opt_float, &admm_rho, NULL }, }; cmdline(&argc, argv, 3, 3, usage_str, help_str, ARRAY_SIZE(opts), opts); if (1 == l1type) l1wav = true; else if (2 == l1type) l1wav = false; else error("Unknown regularization type."); unsigned int N = DIMS; long dims[N]; long ksp_dims[N]; complex float* kspace_data = load_cfl(argv[1], N, ksp_dims); complex float* sens_maps = load_cfl(argv[2], N, dims); for (int i = 0; i < 4; i++) // sizes2[4] may be > 1 if (ksp_dims[i] != dims[i]) error("Dimensions of kspace and sensitivities do not match!\n"); assert(1 == ksp_dims[MAPS_DIM]); num_init(); long dims1[N]; md_select_dims(N, ~(COIL_FLAG|MAPS_FLAG), dims1, dims); // ----------------------------------------------------------- // memory allocation complex float* result = create_cfl(argv[3], N, ksp_dims); complex float* pattern = md_alloc(N, dims1, CFL_SIZE); // ----------------------------------------------------------- // pre-process data float scaling = estimate_scaling(ksp_dims, NULL, kspace_data); md_zsmul(N, ksp_dims, kspace_data, kspace_data, 1. / scaling); estimate_pattern(N, ksp_dims, COIL_DIM, pattern, kspace_data); // ----------------------------------------------------------- // l1-norm threshold operator const struct operator_p_s* thresh_op = NULL; const struct linop_s* wave_op = NULL; if (l1wav) { long minsize[DIMS] = { [0 ... DIMS - 1] = 1 }; minsize[0] = MIN(ksp_dims[0], 16); minsize[1] = MIN(ksp_dims[1], 16); minsize[2] = MIN(ksp_dims[2], 16); wave_op = wavelet_create(DIMS, ksp_dims, FFT_FLAGS, minsize, true, use_gpu); thresh_op = prox_unithresh_create(DIMS, wave_op, alpha, COIL_FLAG, use_gpu); } #if 0 else {
int main_homodyne(int argc, char* argv[]) { bool clear = false; bool image = false; const char* phase_ref = NULL; float alpha = 0.; num_init(); const struct opt_s opts[] = { { 'r', true, opt_float, &alpha, " <alpha>\tOffset of ramp filter, between 0 and 1. alpha=0 is a full ramp, alpha=1 is a horizontal line" }, { 'I', false, opt_set, &image, "\tInput is in image domain" }, { 'C', false, opt_set, &clear, "\tClear unacquired portion of kspace" }, { 'P', true, opt_string, &phase_ref, " <phase_ref>\tUse <phase_ref> as phase reference" }, }; cmdline(&argc, argv, 4, 4, usage_str, help_str, ARRAY_SIZE(opts), opts); const int N = DIMS; long dims[N]; complex float* idata = load_cfl(argv[3], N, dims); complex float* data = create_cfl(argv[4], N, dims); int pfdim = atoi(argv[1]); float frac = atof(argv[2]); assert((0 <= pfdim) && (pfdim < N)); assert(frac > 0.); if (image) { complex float* ksp_in = md_alloc(N, dims, CFL_SIZE); fftuc(N, dims, FFT_FLAGS, ksp_in, idata); md_copy(N, dims, idata, ksp_in, CFL_SIZE); md_free(ksp_in); } long strs[N]; md_calc_strides(N, strs, dims, CFL_SIZE); struct wdata wdata; wdata.frac = frac; wdata.pfdim = pfdim; md_select_dims(N, MD_BIT(pfdim), wdata.wdims, dims); md_calc_strides(N, wdata.wstrs, wdata.wdims, CFL_SIZE); wdata.weights = md_alloc(N, wdata.wdims, CFL_SIZE); wdata.alpha = alpha; wdata.clear = clear; md_loop(N, wdata.wdims, &wdata, comp_weights); long pstrs[N]; long pdims[N]; complex float* phase = NULL; if (NULL == phase_ref) { phase = estimate_phase(wdata, FFT_FLAGS, N, dims, idata); md_copy_dims(N, pdims, dims); } else phase = load_cfl(phase_ref, N, pdims); md_calc_strides(N, pstrs, pdims, CFL_SIZE); homodyne(wdata, FFT_FLAGS, N, dims, strs, data, idata, pstrs, phase); md_free(wdata.weights); if (NULL == phase_ref) md_free(phase); else { unmap_cfl(N, pdims, phase); free((void*)phase_ref); } unmap_cfl(N, dims, idata); unmap_cfl(N, dims, data); exit(0); }
struct noir_data* noir_init(const long dims[DIMS], const complex float* mask, const complex float* psf, bool rvc, bool use_gpu) { #ifdef USE_CUDA md_alloc_fun_t my_alloc = use_gpu ? md_alloc_gpu : md_alloc; #else assert(!use_gpu); md_alloc_fun_t my_alloc = md_alloc; #endif PTR_ALLOC(struct noir_data, data); data->rvc = rvc; md_copy_dims(DIMS, data->dims, dims); md_select_dims(DIMS, FFT_FLAGS|COIL_FLAG|CSHIFT_FLAG, data->sign_dims, dims); md_calc_strides(DIMS, data->sign_strs, data->sign_dims, CFL_SIZE); md_select_dims(DIMS, FFT_FLAGS|COIL_FLAG|MAPS_FLAG, data->coil_dims, dims); md_calc_strides(DIMS, data->coil_strs, data->coil_dims, CFL_SIZE); md_select_dims(DIMS, FFT_FLAGS|MAPS_FLAG|CSHIFT_FLAG, data->imgs_dims, dims); md_calc_strides(DIMS, data->imgs_strs, data->imgs_dims, CFL_SIZE); md_select_dims(DIMS, FFT_FLAGS|COIL_FLAG, data->data_dims, dims); md_calc_strides(DIMS, data->data_strs, data->data_dims, CFL_SIZE); md_select_dims(DIMS, FFT_FLAGS, data->mask_dims, dims); md_calc_strides(DIMS, data->mask_strs, data->mask_dims, CFL_SIZE); md_select_dims(DIMS, FFT_FLAGS, data->wght_dims, dims); md_calc_strides(DIMS, data->wght_strs, data->wght_dims, CFL_SIZE); md_select_dims(DIMS, FFT_FLAGS|CSHIFT_FLAG, data->ptrn_dims, dims); md_calc_strides(DIMS, data->ptrn_strs, data->ptrn_dims, CFL_SIZE); complex float* weights = md_alloc(DIMS, data->wght_dims, CFL_SIZE); noir_calc_weights(dims, weights); fftmod(DIMS, data->wght_dims, FFT_FLAGS, weights, weights); fftscale(DIMS, data->wght_dims, FFT_FLAGS, weights, weights); data->weights = weights; #ifdef USE_CUDA if (use_gpu) { data->weights = md_gpu_move(DIMS, data->wght_dims, weights, CFL_SIZE); } #endif complex float* ptr = my_alloc(DIMS, data->ptrn_dims, CFL_SIZE); md_copy(DIMS, data->ptrn_dims, ptr, psf, CFL_SIZE); fftmod(DIMS, data->ptrn_dims, FFT_FLAGS, ptr, ptr); data->pattern = ptr; complex float* msk = my_alloc(DIMS, data->mask_dims, CFL_SIZE); if (NULL == mask) { assert(!use_gpu); md_zfill(DIMS, data->mask_dims, msk, 1.); } else { md_copy(DIMS, data->mask_dims, msk, mask, CFL_SIZE); } // fftmod(DIMS, data->mask_dims, 7, msk, msk); fftscale(DIMS, data->mask_dims, FFT_FLAGS, msk, msk); data->mask = msk; data->sens = my_alloc(DIMS, data->coil_dims, CFL_SIZE); data->xn = my_alloc(DIMS, data->imgs_dims, CFL_SIZE); data->tmp = my_alloc(DIMS, data->sign_dims, CFL_SIZE); return data; }
int main_bpsense(int argc, char* argv[]) { // ----------------------------------------------------------- // set up conf and option parser struct bpsense_conf conf = bpsense_defaults; struct iter_admm_conf iconf = iter_admm_defaults; conf.iconf = &iconf; conf.iconf->rho = 10; // more sensibile default bool usegpu = false; const char* psf = NULL; const char* image_truth_fname = NULL; bool im_truth = false; bool use_tvnorm = false; double start_time = timestamp(); const struct opt_s opts[] = { OPT_FLOAT('e', &conf.eps, "eps", "data consistency error"), OPT_FLOAT('r', &conf.lambda, "lambda", "l2 regularization parameter"), OPT_FLOAT('u', &conf.iconf->rho, "rho", "ADMM penalty parameter"), OPT_SET('c', &conf.rvc, "real-value constraint"), OPT_SET('t', &use_tvnorm, "use TV norm"), OPT_STRING('T', &image_truth_fname, "file", "compare to truth image"), OPT_UINT('i', &conf.iconf->maxiter, "iter", "max. iterations"), OPT_SET('g', &usegpu, "(use gpu)"), OPT_STRING('p', &psf, "file", "point-spread function"), }; cmdline(&argc, argv, 3, 3, usage_str, help_str, ARRAY_SIZE(opts), opts); if (NULL != image_truth_fname) im_truth = true; // ----------------------------------------------------------- // load data and print some info about the recon int N = DIMS; long dims[N]; long dims1[N]; long img_dims[N]; long ksp_dims[N]; complex float* kspace_data = load_cfl(argv[1], N, ksp_dims); complex float* sens_maps = load_cfl(argv[2], N, dims); for (int i = 0; i < 4; i++) // sizes2[4] may be > 1 if (ksp_dims[i] != dims[i]) error("Dimensions of kspace and sensitivities do not match!\n"); assert(1 == ksp_dims[MAPS_DIM]); (usegpu ? num_init_gpu : num_init)(); if (dims[MAPS_DIM] > 1) debug_printf(DP_INFO, "%ld maps.\nESPIRiT reconstruction.\n", dims[4]); if (conf.lambda > 0.) debug_printf(DP_INFO, "l2 regularization: %f\n", conf.lambda); if (use_tvnorm) debug_printf(DP_INFO, "use Total Variation\n"); else debug_printf(DP_INFO, "use Wavelets\n"); if (im_truth) debug_printf(DP_INFO, "Compare to truth\n"); md_select_dims(N, ~(COIL_FLAG | MAPS_FLAG), dims1, dims); md_select_dims(N, ~COIL_FLAG, img_dims, dims); // ----------------------------------------------------------- // initialize sampling pattern complex float* pattern = NULL; long pat_dims[N]; if (NULL != psf) { pattern = load_cfl(psf, N, pat_dims); // FIXME: check compatibility } else { pattern = md_alloc(N, dims1, CFL_SIZE); estimate_pattern(N, ksp_dims, COIL_DIM, pattern, kspace_data); } // ----------------------------------------------------------- // print some statistics size_t T = md_calc_size(N, dims1); long samples = (long)pow(md_znorm(N, dims1, pattern), 2.); debug_printf(DP_INFO, "Size: %ld Samples: %ld Acc: %.2f\n", T, samples, (float)T/(float)samples); // ----------------------------------------------------------- // fftmod to un-center data fftmod(N, ksp_dims, FFT_FLAGS, kspace_data, kspace_data); fftmod(N, dims, FFT_FLAGS, sens_maps, sens_maps); // ----------------------------------------------------------- // apply scaling float scaling = estimate_scaling(ksp_dims, NULL, kspace_data); debug_printf(DP_INFO, "Scaling: %f\n", scaling); if (scaling != 0.) md_zsmul(N, ksp_dims, kspace_data, kspace_data, 1. / scaling); // ----------------------------------------------------------- // create l1 prox operator and transform long minsize[DIMS] = { [0 ... DIMS - 1] = 1 }; minsize[0] = MIN(img_dims[0], 16); minsize[1] = MIN(img_dims[1], 16); minsize[2] = MIN(img_dims[2], 16); const struct linop_s* l1op = NULL; const struct operator_p_s* l1prox = NULL; if (use_tvnorm) { l1op = grad_init(DIMS, img_dims, FFT_FLAGS); l1prox = prox_thresh_create(DIMS + 1, linop_codomain(l1op)->dims, 1., 0u, usegpu); conf.l1op_obj = l1op; } else { bool randshift = true; l1op = linop_identity_create(DIMS, img_dims); conf.l1op_obj = wavelet_create(DIMS, img_dims, FFT_FLAGS, minsize, false, usegpu); l1prox = prox_wavethresh_create(DIMS, img_dims, FFT_FLAGS, minsize, 1., randshift, usegpu); } // ----------------------------------------------------------- // create image and load truth image complex float* image = create_cfl(argv[3], N, img_dims); md_clear(N, img_dims, image, CFL_SIZE); long img_truth_dims[DIMS]; complex float* image_truth = NULL; if (im_truth) image_truth = load_cfl(image_truth_fname, DIMS, img_truth_dims); // ----------------------------------------------------------- // call recon if (usegpu) #ifdef USE_CUDA bpsense_recon_gpu(&conf, dims, image, sens_maps, dims1, pattern, l1op, l1prox, ksp_dims, kspace_data, image_truth); #else assert(0); #endif else
int main_ecaltwo(int argc, char* argv[]) { long maps = 2; // channels; struct ecalib_conf conf = ecalib_defaults; int c; while (-1 != (c = getopt(argc, argv, "OSc:m:gh"))) { switch (c) { case 'S': conf.softcrop = true; break; case 'O': conf.orthiter = false; break; case 'c': conf.crop = atof(optarg); break; case 'm': maps = atoi(optarg); break; case 'g': conf.usegpu = true; break; case 'h': usage(argv[0], stdout); help(); exit(0); default: usage(argv[0], stderr); exit(1); } } if ((argc - optind != 5) && (argc - optind != 6)) { usage(argv[0], stderr); exit(1); } long in_dims[DIMS]; complex float* in_data = load_cfl(argv[optind + 3], DIMS, in_dims); int channels = 0; while (in_dims[3] != (channels * (channels + 1) / 2)) channels++; printf("Channels: %d\n", channels); assert(maps <= channels); long out_dims[DIMS] = { [0 ... DIMS - 1] = 1 }; long map_dims[DIMS] = { [0 ... DIMS - 1] = 1 }; out_dims[0] = atoi(argv[optind + 0]); out_dims[1] = atoi(argv[optind + 1]); out_dims[2] = atoi(argv[optind + 2]); out_dims[3] = channels; out_dims[4] = maps; assert((out_dims[0] >= in_dims[0])); assert((out_dims[1] >= in_dims[1])); assert((out_dims[2] >= in_dims[2])); for (int i = 0; i < 3; i++) map_dims[i] = out_dims[i]; map_dims[3] = 1; map_dims[4] = maps; complex float* out_data = create_cfl(argv[optind + 4], DIMS, out_dims); complex float* emaps; if (6 == argc - optind) emaps = create_cfl(argv[optind + 5], DIMS, map_dims); else emaps = md_alloc(DIMS, map_dims, CFL_SIZE); caltwo(&conf, out_dims, out_data, emaps, in_dims, in_data, NULL, NULL); if (conf.intensity) { debug_printf(DP_DEBUG1, "Normalize...\n"); normalizel1(DIMS, COIL_FLAG, out_dims, out_data); } debug_printf(DP_DEBUG1, "Crop maps... (%.2f)\n", conf.crop); crop_sens(out_dims, out_data, conf.softcrop, conf.crop, emaps); debug_printf(DP_DEBUG1, "Fix phase...\n"); fixphase(DIMS, out_dims, COIL_DIM, out_data, out_data); printf("Done.\n"); unmap_cfl(DIMS, in_dims, in_data); unmap_cfl(DIMS, out_dims, out_data); if (6 == argc - optind) unmap_cfl(DIMS, map_dims, emaps); else md_free(emaps); exit(0); }