void run() { Image::Header input_SH_header (argument[0]); if (input_SH_header.ndim() != 4) throw Exception ("input SH image should contain 4 dimensions"); std::vector<ssize_t> strides (4, 0); strides[3] = 1; Image::BufferPreload<value_type> input_buf (input_SH_header, strides); Math::Vector<value_type> responseSH; responseSH.load (argument[1]); Math::Vector<value_type> responseRH; Math::SH::SH2RH (responseRH, responseSH); Ptr<Image::Buffer<bool> > mask_buf; Options opt = get_options ("mask"); if (opt.size()) { mask_buf = new Image::Buffer<bool> (opt[0][0]); Image::check_dimensions (*mask_buf, input_buf, 0, 3); } Image::Header output_SH_header (input_SH_header); Image::Stride::set_from_command_line (output_SH_header, Image::Stride::contiguous_along_axis (3)); Image::Buffer<value_type> output_SH_buf (argument[2], output_SH_header); SDeconvFunctor sconv (input_buf, output_SH_buf, mask_buf, responseRH); Image::ThreadedLoop loop ("performing convolution...", input_buf, 2, 0, 3); loop.run (sconv); }
void run () { Image::Buffer<value_type> dwi_data (argument[0]); if (dwi_data.ndim() != 4) throw Exception ("dwi image should contain 4 dimensions"); Math::Matrix<value_type> grad = DWI::get_valid_DW_scheme<value_type> (dwi_data); DWI::Shells shells (grad); // Keep the b=0 shell (may be used for normalisation), but force single non-zero shell shells.select_shells (true, true); Math::Matrix<value_type> DW_dirs = DWI::gen_direction_matrix (grad, shells.largest().get_volumes()); Options opt = get_options ("lmax"); lmax = opt.size() ? opt[0][0] : Math::SH::LforN (shells.largest().count()); INFO ("calculating even spherical harmonic components up to order " + str (lmax)); Math::Matrix<value_type> HR_dirs; Math::Matrix<value_type> HR_SHT; opt = get_options ("normalise"); if (opt.size()) { normalise = true; opt = get_options ("directions"); if (opt.size()) HR_dirs.load (opt[0][0]); else DWI::Directions::electrostatic_repulsion_300 (HR_dirs); Math::SH::init_transform (HR_SHT, HR_dirs, lmax); } // set Lmax int i; for (i = 0; Math::SH::NforL(i) < shells.largest().count(); i += 2); i -= 2; if (lmax > i) { WARN ("not enough data for SH order " + str(lmax) + ", falling back to " + str(i)); lmax = i; } INFO("setting maximum even spherical harmonic order to " + str(lmax)); // Setup response function int num_RH = (lmax + 2)/2; Math::Vector<value_type> sigs(num_RH); std::vector<value_type> AL (lmax+1); Math::Legendre::Plm_sph<value_type>(&AL[0], lmax, 0, 0); for (int l = 0; l <= lmax; l += 2) sigs[l/2] = AL[l]; Math::Vector<value_type> response(num_RH); Math::SH::SH2RH(response, sigs); opt = get_options ("filter"); Math::Vector<value_type> filter; if (opt.size()) { filter.load (opt[0][0]); if (filter.size() <= response.size()) throw Exception ("not enough filter coefficients supplied for lmax" + str(lmax)); for (int i = 0; i <= lmax/2; i++) response[i] *= filter[i]; INFO ("using initial filter coefficients: " + str (filter)); } Math::SH::Transform<value_type> FRT_SHT(DW_dirs, lmax); FRT_SHT.set_filter(response); Image::Header qbi_header (dwi_data); qbi_header.dim(3) = Math::SH::NforL (lmax); qbi_header.datatype() = DataType::Float32; Image::Stride::set (qbi_header, Image::Stride::contiguous_along_axis (3, dwi_data)); Image::Buffer<value_type> qbi_data (argument[1], qbi_header); opt = get_options ("mask"); if (opt.size()) { Image::Buffer<bool> mask_data (opt[0][0]); Image::ThreadedLoop ("estimating dODFs using Q-ball imaging...", dwi_data, 0, 3) .run (DWI2QBI (FRT_SHT.mat_A2SH(), HR_SHT, shells), mask_data.voxel(), dwi_data.voxel(), qbi_data.voxel()); } else Image::ThreadedLoop ("estimating dODFs using Q-ball imaging...", dwi_data, 0, 3) .run (DWI2QBI (FRT_SHT.mat_A2SH(), HR_SHT, shells), dwi_data.voxel(), qbi_data.voxel()); }