17#ifndef __dwi_tractography_sift_model_h__
18#define __dwi_tractography_sift_model_h__
51 namespace Tractography
57 template <
class Fixel>
70 Track_fixel_contribution::set_scaling (
dwi);
108 class TrackMappingWorker
113 mapper (i.header(), i.
dirs),
114 mutex (
new std::mutex),
116 fixel_TDs (master.fixels.size(), 0.0),
117 fixel_counts (master.fixels.size(), 0)
119 mapper.set_upsample_ratio (upsample_ratio);
120 mapper.set_use_precise_mapping (
true);
122 TrackMappingWorker (
const TrackMappingWorker& that) :
123 master (that.master),
124 mapper (that.mapper),
127 fixel_TDs (master.fixels.size(), 0.0),
128 fixel_counts (master.fixels.size(), 0) { }
129 ~TrackMappingWorker();
134 std::shared_ptr<std::mutex> mutex;
158 template <
class Fixel>
172 template <
class Fixel>
178 const track_t count = (properties.find (
"count") == properties.end()) ? 0 : to<track_t>(properties[
"count"]);
182 contributions.assign (count,
nullptr);
192 if (!contributions.back()) {
193 track_t num_tracks = 0, max_index = 0;
194 for (
track_t i = 0; i != contributions.size(); ++i) {
195 if (contributions[i]) {
197 max_index = std::max (max_index, i);
199 WARN (
"Only " +
str (num_tracks) +
" tracks read from input track file; expected " +
str (contributions.size()));
200 contributions.resize (max_index + 1);
204 tck_file_path = path;
206 INFO (
"Proportionality coefficient after streamline mapping is " +
str (mu()));
213 template <
class Fixel>
217 const bool remove_untracked_fixels =
App::get_options (
"remove_untracked").size();
219 const float min_fibre_density = opt.size() ? float(opt[0][0]) : 0.0;
221 if (!remove_untracked_fixels && !min_fibre_density)
228 new_fixels.push_back (
Fixel());
231 for (
auto l =
Loop (v) (v); l; ++l) {
234 size_t new_start_index = new_fixels.size();
237 if ((!remove_untracked_fixels || i().get_TD()) && (i().get_FOD() > min_fibre_density)) {
238 fixel_index_mapping [size_t (i)] = new_fixels.size();
239 new_fixels.push_back (i());
240 FOD_sum += i().get_weight() * i().get_FOD();
246 if (new_fixels.size() == new_start_index)
249 v.value() =
new MapVoxel (new_start_index, new_fixels.size() - new_start_index);
254 INFO (
str (fixels.size() - new_fixels.size()) +
" out of " +
str(fixels.size()) +
" fixels removed from reconstruction (" +
str(new_fixels.size()) +
") remaining)");
256 fixels.swap (new_fixels);
259 FixelRemapper remapper (*
this, fixel_index_mapping);
264 TD_sum += i->get_weight() * i->get_TD();
266 INFO (
"After fixel exclusion, the proportionality coefficient is " +
str(mu()));
276 template <
class Fixel>
280 double sum_from_fixels = 0.0, sum_from_fixels_weighted = 0.0;
282 sum_from_fixels += i->get_TD();
283 sum_from_fixels_weighted += i->get_TD() * i->get_weight();
285 VAR (sum_from_fixels);
286 VAR (sum_from_fixels_weighted);
287 double sum_from_tracks = 0.0;
290 sum_from_tracks += (*i)->get_total_contribution();
292 VAR (sum_from_tracks);
299 template <
class Fixel>
306 ProgressBar progress (
"Writing non-contributing streamlines output file", contributions.size());
308 while (reader (tck) && tck_counter < contributions.size()) {
309 if (contributions[tck_counter] && !contributions[tck_counter++]->get_total_contribution())
325 template <
typename... Ts>
328 template <
typename T,
typename =
void>
329 struct has_add_TD_function : std::false_type {
NOMEMALIGN };
330 template <
typename T>
331 struct has_add_TD_function<T, decltype (
std::declval<T>().add_TD(0.0, 0))> : std::true_type {
NOMEMALIGN };
333 template <
typename FixelType>
335 fixel.add_TD (
length, count);
337 template <
typename FixelType>
343 template <
class Fixel>
344 Model<Fixel>::TrackMappingWorker::~TrackMappingWorker()
346 std::lock_guard<std::mutex> lock (*mutex);
347 master.TD_sum += TD_sum;
348 for (
size_t i = 0; i != fixel_TDs.size(); ++i)
349 increment (master.fixels[i], fixel_TDs[i], fixel_counts[i]);
354 template <
class Fixel>
355 bool Model<Fixel>::TrackMappingWorker::operator() (
const Tractography::Streamline<>& in)
357 assert (in.get_index() < master.contributions.size());
358 assert (!master.contributions[in.get_index()]);
362 Mapping::SetDixel dixels;
365 vector<Track_fixel_contribution> masked_contributions;
366 default_type total_contribution = 0.0, total_length = 0.0;
368 for (Mapping::SetDixel::const_iterator i = dixels.begin(); i != dixels.end(); ++i) {
369 total_length += i->get_length();
370 const size_t fixel_index = master.dixel2fixel (*i);
371 if (fixel_index && (i->get_length() > Track_fixel_contribution::min())) {
372 total_contribution += i->get_length() * master.fixels[fixel_index].get_weight();
373 bool incremented =
false;
374 for (vector<Track_fixel_contribution>::iterator c = masked_contributions.begin(); !incremented && c != masked_contributions.end(); ++c) {
375 if ((c->get_fixel_index() == fixel_index) && c->add (i->get_length()))
379 masked_contributions.push_back (Track_fixel_contribution (fixel_index, i->get_length()));
383 master.contributions[in.get_index()] =
new TrackContribution (masked_contributions, total_contribution, total_length);
385 TD_sum += total_contribution;
386 for (vector<Track_fixel_contribution>::const_iterator i = masked_contributions.begin(); i != masked_contributions.end(); ++i) {
387 fixel_TDs [i->get_fixel_index()] += i->get_length();
388 ++fixel_counts [i->get_fixel_index()];
394 throw Exception (
"Error allocating memory for streamline visitations");
403 template <
class Fixel>
404 bool Model<Fixel>::FixelRemapper::operator() (
const TrackIndexRange& in)
406 for (
track_t track_index = in.first; track_index != in.second; ++track_index) {
407 if (master.contributions[track_index]) {
408 TrackContribution& this_cont (*master.contributions[track_index]);
409 vector<Track_fixel_contribution> new_cont;
410 double total_contribution = 0.0;
411 for (
size_t i = 0; i != this_cont.dim(); ++i) {
412 const size_t new_index = remapper[this_cont[i].get_fixel_index()];
414 new_cont.push_back (Track_fixel_contribution (new_index, this_cont[i].get_length()));
415 total_contribution += this_cont[i].get_length() * master[new_index].get_weight();
418 TrackContribution* new_contribution =
new TrackContribution (new_cont, total_contribution, this_cont.get_total_length());
419 delete master.contributions[track_index];
420 master.contributions[track_index] = new_contribution;
const DWI::Directions::FastLookupSet & dirs
A class to read streamlines data.
virtual bool operator()(const FMLS::FOD_lobes &in)
std::string tck_file_path
Model(Set &dwi, const DWI::Directions::FastLookupSet &dirs)
void map_streamlines(const std::string &)
void output_non_contributing_streamlines(const std::string &) const
Model(const Model &that)=delete
vector< TrackContribution * > contributions
track_t num_tracks() const
void remove_excluded_fixels()
class to handle writing tracks to file, with RAM buffer
implements a progress meter to provide feedback to the user
#define VAR(variable)
Prints a variable name and its value, followed by the function, file and line number.
FORCE_INLINE LoopAlongAxes Loop()
VectorType::Scalar value(const VectorType &coefs, typename VectorType::Scalar cos_elevation, typename VectorType::Scalar cos_azimuth, typename VectorType::Scalar sin_azimuth, int lmax)
__Multi< typename std::remove_reference< Functor >::type > multi(Functor &&functor, size_t nthreads=threads_to_execute())
used to request multiple threads of the corresponding functor
void run_queue(Source &&source, const Item &item, Sink &&sink, size_t capacity=128)
convenience function to set up and run a 2-stage multi-threaded pipeline.
__Batch< Item > batch(const Item &, size_t number=128)
used to request batched processing of items
const vector< ParsedOption > get_options(const std::string &name)
return all command-line options matching name
size_t determine_upsample_ratio(const Header &, const float, const float)
std::pair< track_t, track_t > TrackIndexRange
PointType::Scalar length(const vector< PointType > &tck)
std::string basename(const std::string &name)
double default_type
the default type used throughout MRtrix
std::string str(const T &value, int precision=0)
#define SIFT_TRACK_INDEX_BUFFER_SIZE