This example simply computes the exponential of the intensity for each data point in the input dataset, producing a new dataset of the same size.
#include "image.h"
using namespace App;
{
AUTHOR =
"Joe Bloggs (joe.bloggs@acme.org)";
+ "compute exponential of each voxel intensity";
+ Argument ("in", "the input image.").type_image_in ()
+ Argument ("out", "the output image.").type_image_out ();
+ Option ("lambda", "the exponent scale factor lambda in the equation 'exp (lambda * intensity)'")
+ Argument ("value").type_float();
}
class ExpFunctor {
public:
lambda (lambda) { }
template <class VoxeltypeIn, class VoxeltypeOut>
void operator() (const VoxeltypeIn& in, VoxeltypeOut& out)
{
out.value() = std::exp (lambda * in.value());
}
protected:
};
{
Header header (in);
header.datatype() = DataType::Float32;
loop.run (ExpFunctor (lambda), in, out);
loop.run ([&] (decltype(in)& vin, decltype(out)& vout) {
vout.value() = std::exp (lambda * vin.value());
}, in, out);
}
static Image open(const std::string &image_name, bool read_write_if_existing=false)
OptionList OPTIONS
the options accepted by the command
vector< ParsedArgument > argument
the list of arguments parsed from the command-line
const char * AUTHOR
set the author of the command
T get_option_value(const std::string &name, const T default_value)
Returns the option value if set, and the default otherwise.
Description DESCRIPTION
additional description of the command over and above the synopsis
ArgumentList ARGUMENTS
the arguments expected by the command
std::unique_ptr< ImageIO::Base > create(Header &H)
MR::default_type value_type
ThreadedLoopRunOuter< decltype(Loop(vector< size_t >()))> ThreadedLoop(const HeaderType &source, const vector< size_t > &outer_axes, const vector< size_t > &inner_axes)
Multi-threaded loop object.
It is worth re-iterating that the final run()
call on the threaded loop does quite a bit of work behind the scenes. The main issue is that it will create copies of the functor you provided using its copy-constructor, and call each of these copies' operator()
method within its own thread. This means you need to ensure that your functor's copy constructor behaves appropriately - each copy must be able to operate independently without affecting any of the other copies. Pay special attention to any data accessed via a member pointer or reference - by default, these are copy-constructed by value, so that each functor still points to the same object - this is fine as long as this object is never written to. If this what you intended, declare these const
to minimise the chances of unintentional write access (see next example for details).