void run() { auto input_image = Image<float>::open (argument[0]); Eigen::MatrixXd grad = DWI::get_valid_DW_scheme (input_image); // Want to support non-shell-like data if it's just a straight extraction // of all dwis or all bzeros i.e. don't initialise the Shells class std::vector<int> volumes; bool bzero = get_options ("bzero").size(); auto opt = get_options ("shell"); if (opt.size()) { DWI::Shells shells (grad); shells.select_shells (false, false); for (size_t s = 0; s != shells.count(); ++s) { DEBUG ("Including data from shell b=" + str(shells[s].get_mean()) + " +- " + str(shells[s].get_stdev())); for (const auto v : shells[s].get_volumes()) volumes.push_back (v); } bzero = (shells.count() == 1 && shells[0].is_bzero()); } else { const float bzero_threshold = File::Config::get_float ("BValueThreshold", 10.0); for (ssize_t row = 0; row != grad.rows(); ++row) { if ((bzero && (grad (row, 3) < bzero_threshold)) || (!bzero && (grad (row, 3) > bzero_threshold))) volumes.push_back (row); } } if (volumes.empty()) { auto type = (bzero) ? "b=0" : "dwi"; throw Exception ("No " + str(type) + " volumes present"); } std::sort (volumes.begin(), volumes.end()); Header header (input_image); Stride::set_from_command_line (header); header.size (3) = volumes.size(); Eigen::MatrixXd new_grad (volumes.size(), grad.cols()); for (size_t i = 0; i < volumes.size(); i++) new_grad.row (i) = grad.row (volumes[i]); header.set_DW_scheme (new_grad); auto output_image = Image<float>::create (argument[1], header); auto input_volumes = Adapter::make<Adapter::Extract1D> (input_image, 3, volumes); threaded_copy_with_progress_message ("extracting volumes", input_volumes, output_image); }
void run () { try { auto directions = DWI::Directions::load_cartesian (argument[0]); report (argument[0], directions); } catch (Exception& E) { auto directions = load_matrix<double> (argument[0]); DWI::normalise_grad (directions); if (directions.cols() < 3) throw Exception ("unexpected matrix size for DW scheme \"" + str(argument[0]) + "\""); print (str(argument[0]) + " [ " + str(directions.rows()) + " volumes ]\n"); DWI::Shells shells (directions); for (size_t n = 0; n < shells.count(); ++n) { Eigen::MatrixXd subset (shells[n].count(), 3); for (ssize_t i = 0; i < subset.rows(); ++i) subset.row(i) = directions.row(shells[n].get_volumes()[i]).head(3); report ("\nb = " + str(shells[n].get_mean(), precision), subset); } } }
void run () { try { Math::Matrix<value_type> directions = DWI::Directions::load_cartesian<value_type> (argument[0]); report (str(argument[0]), directions); } catch (Exception& E) { Math::Matrix<value_type> directions (str(argument[0])); DWI::normalise_grad (directions); if (directions.columns() < 3) throw Exception ("unexpected matrix size for DW scheme \"" + str(argument[0]) + "\""); print (str(argument[0]) + " [ " + str(directions.rows()) + " volumes ]\n"); DWI::Shells shells (directions); for (size_t n = 0; n < shells.count(); ++n) { Math::Matrix<value_type> subset (shells[n].count(), 3); for (size_t i = 0; i < subset.rows(); ++i) subset.row(i) = directions.row(shells[n].get_volumes()[i]).sub(0,3); report ("\nb = " + str(shells[n].get_mean()), subset); } } }
void run () { auto sh_data = Image<value_type>::open(argument[0]); Math::SH::check (sh_data); auto amp_header = sh_data.original_header(); Eigen::MatrixXd directions; if (get_options("gradient").size()) { Eigen::MatrixXd grad; grad = load_matrix(argument[1]); DWI::Shells shells (grad); directions = DWI::gen_direction_matrix (grad, shells.largest().get_volumes()); } else { directions = load_matrix(argument[1]); } if (!directions.rows()) throw Exception ("no directions found in input directions file"); std::stringstream dir_stream; for (ssize_t d = 0; d < directions.rows() - 1; ++d) dir_stream << directions(d,0) << "," << directions(d,1) << "\n"; dir_stream << directions(directions.rows() - 1,0) << "," << directions(directions.rows() - 1,1); amp_header.keyval().insert(std::pair<std::string, std::string> ("directions", dir_stream.str())); amp_header.size(3) = directions.rows(); Stride::set_from_command_line (amp_header, Stride::contiguous_along_axis (3)); amp_header.datatype() = DataType::from_command_line (DataType::Float32); auto amp_data = Image<value_type>::create(argument[2], amp_header); SH2Amp sh2amp (directions, Math::SH::LforN (sh_data.size(3)), get_options("nonnegative").size()); ThreadedLoop("computing amplitudes", sh_data, 0, 3, 2).run(sh2amp, sh_data, amp_data); }
void run() { auto input_image = Image<float>::open (argument[0]).with_direct_io (3); Eigen::MatrixXd grad = DWI::get_valid_DW_scheme (input_image); // Want to support non-shell-like data if it's just a straight extraction // of all dwis or all bzeros i.e. don't initialise the Shells class std::vector<size_t> volumes; bool bzero = get_options ("bzero").size(); auto opt = get_options ("shell"); if (opt.size()) { DWI::Shells shells (grad); shells.select_shells (false, false); for (size_t s = 0; s != shells.count(); ++s) { DEBUG ("Including data from shell b=" + str(shells[s].get_mean()) + " +- " + str(shells[s].get_stdev())); for (std::vector<size_t>::const_iterator v = shells[s].get_volumes().begin(); v != shells[s].get_volumes().end(); ++v) volumes.push_back (*v); } // Remove DW information from header if b=0 is the only 'shell' selected bzero = (shells.count() == 1 && shells[0].is_bzero()); } else { const float bzero_threshold = File::Config::get_float ("BValueThreshold", 10.0); for (ssize_t row = 0; row != grad.rows(); ++row) { if ((bzero && (grad (row, 3) < bzero_threshold)) || (!bzero && (grad (row, 3) > bzero_threshold))) volumes.push_back (row); } } if (volumes.empty()) { auto type = (bzero) ? "b=0" : "dwi"; throw Exception ("No " + str(type) + " volumes present"); } std::sort (volumes.begin(), volumes.end()); Header header (input_image); if (volumes.size() == 1) header.set_ndim (3); else header.size (3) = volumes.size(); Eigen::MatrixXd new_grad (volumes.size(), grad.cols()); for (size_t i = 0; i < volumes.size(); i++) new_grad.row (i) = grad.row (volumes[i]); header.set_DW_scheme (new_grad); auto output_image = Image<float>::create (argument[1], header); auto outer = Loop ("extracting volumes", input_image, 0, 3); if (output_image.ndim() == 4) { for (auto i = outer (output_image, input_image); i; ++i) { for (size_t i = 0; i < volumes.size(); i++) { input_image.index(3) = volumes[i]; output_image.index(3) = i; output_image.value() = input_image.value(); } } } else { const size_t volume = volumes[0]; for (auto i = outer (output_image, input_image); i; ++i) { input_image.index(3) = volume; output_image.value() = input_image.value(); } } }
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()); }
void run () { auto amp = Image<value_type>::open (argument[0]).with_direct_io (3); Header header (amp); std::vector<size_t> bzeros, dwis; Eigen::MatrixXd dirs; auto opt = get_options ("directions"); if (opt.size()) { dirs = load_matrix (opt[0][0]); } else { auto hit = header.keyval().find ("directions"); if (hit != header.keyval().end()) { std::vector<default_type> dir_vector; for (auto line : split_lines (hit->second)) { auto v = parse_floats (line); dir_vector.insert (dir_vector.end(), v.begin(), v.end()); } dirs.resize(dir_vector.size() / 2, 2); for (size_t i = 0; i < dir_vector.size(); i += 2) { dirs(i/2, 0) = dir_vector[i]; dirs(i/2, 1) = dir_vector[i+1]; } } else { auto grad = DWI::get_valid_DW_scheme (amp); DWI::Shells shells (grad); shells.select_shells (true, true); if (shells.smallest().is_bzero()) bzeros = shells.smallest().get_volumes(); dwis = shells.largest().get_volumes(); dirs = DWI::gen_direction_matrix (grad, dwis); } } auto sh2amp = DWI::compute_SH2amp_mapping (dirs, true, 8); bool normalise = get_options ("normalise").size(); if (normalise && !bzeros.size()) throw Exception ("the normalise option is only available if the input data contains b=0 images."); header.size (3) = sh2amp.cols(); Stride::set_from_command_line (header); auto SH = Image<value_type>::create (argument[1], header); Amp2SHCommon common (sh2amp, bzeros, dwis, normalise); opt = get_options ("rician"); if (opt.size()) { auto noise = Image<value_type>::open (opt[0][0]).with_direct_io(); ThreadedLoop ("mapping amplitudes to SH coefficients", amp, 0, 3) .run (Amp2SH (common), SH, amp, noise); } else { ThreadedLoop ("mapping amplitudes to SH coefficients", amp, 0, 3) .run (Amp2SH (common), SH, amp); } }
void run() { Image::BufferPreload<float> data_in (argument[0], Image::Stride::contiguous_along_axis (3)); auto voxel_in = data_in.voxel(); Math::Matrix<value_type> grad (DWI::get_valid_DW_scheme<float> (data_in)); // Want to support non-shell-like data if it's just a straight extraction // of all dwis or all bzeros i.e. don't initialise the Shells class std::vector<size_t> volumes; bool bzero = get_options ("bzero").size(); Options opt = get_options ("shell"); if (opt.size()) { DWI::Shells shells (grad); shells.select_shells (false, false); for (size_t s = 0; s != shells.count(); ++s) { DEBUG ("Including data from shell b=" + str(shells[s].get_mean()) + " +- " + str(shells[s].get_stdev())); for (std::vector<size_t>::const_iterator v = shells[s].get_volumes().begin(); v != shells[s].get_volumes().end(); ++v) volumes.push_back (*v); } // Remove DW information from header if b=0 is the only 'shell' selected bzero = (shells.count() == 1 && shells[0].is_bzero()); } else { const float bzero_threshold = File::Config::get_float ("BValueThreshold", 10.0); for (size_t row = 0; row != grad.rows(); ++row) { if ((bzero && (grad (row, 3) < bzero_threshold)) || (!bzero && (grad (row, 3) > bzero_threshold))) volumes.push_back (row); } } if (volumes.empty()) throw Exception ("No " + str(bzero ? "b=0" : "dwi") + " volumes present"); std::sort (volumes.begin(), volumes.end()); Image::Header header (data_in); if (volumes.size() == 1) header.set_ndim (3); else header.dim (3) = volumes.size(); Math::Matrix<value_type> new_grad (volumes.size(), grad.columns()); for (size_t i = 0; i < volumes.size(); i++) new_grad.row (i) = grad.row (volumes[i]); header.DW_scheme() = new_grad; Image::Buffer<value_type> data_out (argument[1], header); auto voxel_out = data_out.voxel(); Image::Loop outer ("extracting volumes...", 0, 3); if (voxel_out.ndim() == 4) { for (auto i = outer (voxel_out, voxel_in); i; ++i) { for (size_t i = 0; i < volumes.size(); i++) { voxel_in[3] = volumes[i]; voxel_out[3] = i; voxel_out.value() = voxel_in.value(); } } } else { const size_t volume = volumes[0]; for (auto i = outer (voxel_out, voxel_in); i; ++i) { voxel_in[3] = volume; voxel_out.value() = voxel_in.value(); } } }