static void maps_init_normal(struct maps_data* data) { if (NULL != data->norm) return; data->norm = md_alloc_sameplace(DIMS, data->img_dims, CFL_SIZE, data->sens); md_zrss(DIMS, data->mps_dims, COIL_FLAG, data->norm, data->sens); md_zmul(DIMS, data->img_dims, data->norm, data->norm, data->norm); }
void estimate_pattern(unsigned int D, const long dims[D], unsigned int flags, complex float* pattern, const complex float* kspace_data) { md_zrss(D, dims, flags, pattern, kspace_data); long dims2[D]; long strs2[D]; md_select_dims(D, ~flags, dims2, dims); md_calc_strides(D, strs2, dims2, CFL_SIZE); long strs1[D]; md_singleton_strides(D, strs1); md_zcmp2(D, dims2, strs2, pattern, strs2, pattern, strs1, &(complex float){ 0. });
void grad(unsigned int D, const long dims[D], unsigned int flags, complex float* out, const complex float* in) { long dims2[D + 1]; grad_dims(D, dims2, flags, dims); complex float* tmp = md_alloc_sameplace(D + 1, dims2, CFL_SIZE, out); grad_op(D + 1, dims2, flags, tmp, in); // rss should be moved elsewhere md_zrss(D + 1, dims2, flags, out, tmp); md_free(tmp); }
void tv(unsigned int D, const long dims[D], unsigned int flags, complex float* out, const complex float* in) { unsigned int N = bitcount(flags); long dims2[D + 1]; md_copy_dims(D, dims2, dims); dims2[D] = N; complex float* tmp = md_alloc_sameplace(D + 1, dims2, CFL_SIZE, out); tv_op(D + 1, dims2, flags, tmp, in); // rss should be moved elsewhere md_zrss(D + 1, dims2, flags, out, tmp); md_free(tmp); }
int main_rss(int argc, char* argv[argc]) { mini_cmdline(argc, argv, 3, usage_str, help_str); long dims[DIMS]; complex float* data = load_cfl(argv[2], DIMS, dims); int flags = atoi(argv[1]); assert(0 <= flags); long odims[DIMS]; md_select_dims(DIMS, ~flags, odims, dims); complex float* out = create_cfl(argv[3], DIMS, odims); md_zrss(DIMS, dims, flags, out, data); unmap_cfl(DIMS, dims, data); unmap_cfl(DIMS, odims, out); exit(0); }
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); }
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); }
// [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); }