Ejemplo n.º 1
0
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);
}
Ejemplo n.º 2
0
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);
    }
  }
}
Ejemplo n.º 3
0
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);
    }
  }
}
Ejemplo n.º 4
0
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);
  
}
Ejemplo n.º 5
0
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();
    }
  }
}
Ejemplo n.º 6
0
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());
}
Ejemplo n.º 7
0
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);
  }
}
Ejemplo n.º 8
0
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();
    }

  }


}