Developer documentation
Version 3.0.3-105-gd3941f44
Looping functions

Classes

class  MR::Iterator
 a dummy image to iterate over, useful for multi-threaded looping. More...
 
struct  MR::LoopAlongSingleAxis
 
struct  MR::LoopAlongSingleAxisProgress
 
struct  MR::LoopAlongAxisRange
 
struct  MR::LoopAlongAxisRangeProgress
 
struct  MR::LoopAlongAxes
 
struct  MR::LoopAlongAxesProgress
 
struct  MR::LoopAlongStaticAxes
 
struct  MR::LoopAlongStaticAxesProgress
 
struct  MR::LoopAlongDynamicAxes
 
struct  MR::LoopAlongDynamicAxesProgress
 
class  MR::NeighbourhoodIterator
 a dummy image to iterate over a certain neighbourhood, useful for multi-threaded looping. More...
 

Functions

FORCE_INLINE LoopAlongAxes MR::Loop ()
 
FORCE_INLINE LoopAlongAxesProgress MR::Loop (const std::string &progress_message)
 
FORCE_INLINE LoopAlongSingleAxis MR::Loop (size_t axis)
 
FORCE_INLINE LoopAlongSingleAxisProgress MR::Loop (const std::string &progress_message, size_t axis)
 
FORCE_INLINE LoopAlongAxisRange MR::Loop (size_t axis_from, size_t axis_to)
 
FORCE_INLINE LoopAlongAxisRangeProgress MR::Loop (const std::string &progress_message, size_t axis_from, size_t axis_to)
 
FORCE_INLINE LoopAlongStaticAxes MR::Loop (std::initializer_list< size_t > axes)
 
FORCE_INLINE LoopAlongStaticAxesProgress MR::Loop (const std::string &progress_message, std::initializer_list< size_t > axes)
 
FORCE_INLINE LoopAlongDynamicAxes MR::Loop (const vector< size_t > &axes)
 
FORCE_INLINE LoopAlongDynamicAxesProgress MR::Loop (const std::string &progress_message, const vector< size_t > &axes)
 
template<class ImageType >
FORCE_INLINE LoopAlongDynamicAxes MR::Loop (const ImageType &source, size_t axis_from=0, size_t axis_to=std::numeric_limits< size_t >::max(), typename std::enable_if< std::is_class< ImageType >::value &&!std::is_same< ImageType, std::string >::value, int >::type=0)
 
template<class ImageType >
FORCE_INLINE LoopAlongDynamicAxesProgress MR::Loop (const std::string &progress_message, const ImageType &source, size_t axis_from=0, size_t axis_to=std::numeric_limits< size_t >::max(), typename std::enable_if< std::is_class< ImageType >::value &&!std::is_same< ImageType, std::string >::value, int >::type=0)
 

Detailed Description

These functions can be used to loop over any number of axes of one of more ImageType, in any specified order, within the same thread of execution (for multi-threaded applications, see ThreadedLoop()).

Looping over a single axis

To loop over a single axis, use the following syntax:

auto loop = Loop (axis);
for (auto l = loop (image); l; ++l) {
// do something:
image.value() = ...
}
FORCE_INLINE LoopAlongAxes Loop()
Definition: loop.h:419
int axis

To clarify the process:

Looping with smallest stride first

The looping strategy most likely to make most efficient use of the memory infrastructure is one where the innermost loop iterates over the axis with the smallest absolute stride, since voxels along this axis are most likely to be adjacent. This is most likely to optimise both throughput to and from system RAM or disk (which are typically optimised for bursts of contiguous sections of memory), and CPU cache usage.

The LoopInOrder class is designed to facilitate this. In the following example, the ImageType of interest is passed as an argument to the constructor, so that its strides can be used to compute the nesting order for the loops over the corresponding axes. Here, we assume that vox is a 3D ImageType (i.e. vox.ndim() == 3) with strides [ 2 -1 3 ]:

float sum = 0.0;
for (auto i = Image::LoopInOrder().run (vox); i; ++i)
sum += vox.value();
void run()

This is equivalent to:

float sum = 0.0;
for (vox.index(2) = 0; vox.index(2) < vox.size(2); ++vox.index(2))
for (vox.index(0) = 0; vox.index(0) < vox.size(0); ++vox.index(0))
for (vox.index(1) = 0; vox.index(1) < vox.size(1); ++vox.index(1))
sum += vox.value();

Looping over a specific range of axes

It is also possible to explicitly specify the range of axes to be looped over. In the following example, the program will loop over each 3D volume in the ImageType in turn using the Loop class, and use the LoopInOrder class to iterate over the axes of each volume to ensure efficient memory bandwidth use when each volume is being processed.

// define inner loop to iterate over axes 0 to 2
LoopInOrder inner (vox, 0, 3);
// outer loop iterates over axes 3 and above:
for (auto i = Loop(3).run (vox); i; ++i) {
float sum = 0.0;
for (auto j = inner.run (vox); j; ++j) {
sum += vox.value();
print ("total = " + str (sum) + "\n");
}
void(* print)(const std::string &msg)
print primary output to stdout as-is.
std::string str(const T &value, int precision=0)
Definition: mrtrix.h:247

Arbitrary order loop

It is also possible to specify the looping order explictly, as in the following example:

float value = 0.0;
vector<size_t> order = { 1, 0, 2 };
LoopInOrder loop (vox, order);
for (auto i = loop.run (vox); i; ++i)
value += std::exp (-vox.value());
VectorType::Scalar value(const VectorType &coefs, typename VectorType::Scalar cos_elevation, typename VectorType::Scalar cos_azimuth, typename VectorType::Scalar sin_azimuth, int lmax)
Definition: SH.h:233
vector< size_t > order(const HeaderType &header, size_t from_axis=0, size_t to_axis=std::numeric_limits< size_t >::max())
sort range of axes with respect to their absolute stride.
Definition: stride.h:159

This will iterate over the axes in the same order as the first example above, irrespective of the strides of the ImageType.

Looping over multiple ImageType objects:

As with the Loop class, it is possible to loop over more than one ImageType of the same dimensions, by passing any additional ImageType objects to be looped over to the run() member function. For example, this code snippet will copy the contents of the ImageType src into a ImageType dest (assumed to have the same dimensions as src), with the looping order optimised for the src ImageType:

LoopInOrder loop (src);
for (auto i = loop.run(src, dest); i; ++i)
dest.value() = src.value();

Displaying progress status

As in the Loop class, the LoopInOrder object can also display its progress as it proceeds, using the appropriate constructor. In the following example, the program will display its progress as it averages an ImageType:

float sum = 0.0;
LoopInOrder loop (vox, "averaging");
for (auto i = loop.run (vox); i; ++i)
sum += vox.value();
float average = sum / float (Image::voxel_count (vox));
print ("average = " + str (average) + "\n");

The output would look something like this:

myprogram: [100%] averaging
average = 23.42

Function Documentation

◆ Loop() [1/12]

Definition at line 419 of file loop.h.

◆ Loop() [2/12]

template<class ImageType >
FORCE_INLINE LoopAlongDynamicAxes MR::Loop ( const ImageType &  source,
size_t  axis_from = 0,
size_t  axis_to = std::numeric_limits<size_t>::max(),
typename std::enable_if< std::is_class< ImageType >::value &&!std::is_same< ImageType, std::string >::value, int >::type  = 0 
)

Definition at line 459 of file loop.h.

◆ Loop() [3/12]

FORCE_INLINE LoopAlongAxesProgress MR::Loop ( const std::string &  progress_message)

Definition at line 423 of file loop.h.

◆ Loop() [4/12]

template<class ImageType >
FORCE_INLINE LoopAlongDynamicAxesProgress MR::Loop ( const std::string &  progress_message,
const ImageType &  source,
size_t  axis_from = 0,
size_t  axis_to = std::numeric_limits<size_t>::max(),
typename std::enable_if< std::is_class< ImageType >::value &&!std::is_same< ImageType, std::string >::value, int >::type  = 0 
)

Definition at line 466 of file loop.h.

◆ Loop() [5/12]

FORCE_INLINE LoopAlongDynamicAxesProgress MR::Loop ( const std::string &  progress_message,
const vector< size_t > &  axes 
)

Definition at line 455 of file loop.h.

◆ Loop() [6/12]

FORCE_INLINE LoopAlongSingleAxisProgress MR::Loop ( const std::string &  progress_message,
size_t  axis 
)

Definition at line 431 of file loop.h.

◆ Loop() [7/12]

FORCE_INLINE LoopAlongAxisRangeProgress MR::Loop ( const std::string &  progress_message,
size_t  axis_from,
size_t  axis_to 
)

Definition at line 439 of file loop.h.

◆ Loop() [8/12]

FORCE_INLINE LoopAlongStaticAxesProgress MR::Loop ( const std::string &  progress_message,
std::initializer_list< size_t >  axes 
)

Definition at line 447 of file loop.h.

◆ Loop() [9/12]

FORCE_INLINE LoopAlongDynamicAxes MR::Loop ( const vector< size_t > &  axes)

Definition at line 451 of file loop.h.

◆ Loop() [10/12]

FORCE_INLINE LoopAlongSingleAxis MR::Loop ( size_t  axis)

Definition at line 427 of file loop.h.

◆ Loop() [11/12]

FORCE_INLINE LoopAlongAxisRange MR::Loop ( size_t  axis_from,
size_t  axis_to 
)

Definition at line 435 of file loop.h.

◆ Loop() [12/12]

FORCE_INLINE LoopAlongStaticAxes MR::Loop ( std::initializer_list< size_t >  axes)

Definition at line 443 of file loop.h.