44template <
typename elemT,
typename potentialT>
51template <
typename elemT,
typename potentialT>
57 this->parser.add_key(
"only 2D", &
only_2D);
59 this->parser.add_key(
"weights", &
weights);
61 this->
potential.initialise_keymap(this->parser);
65template <
typename elemT,
typename potentialT>
74 bool warn_about_even_size =
false;
82 if (!this->
weights.is_regular())
84 warning(
"Sorry. GibbsPrior currently only supports regular arrays for the weights");
88 const unsigned int size_z = this->
weights.size();
90 warn_about_even_size =
true;
91 const int min_index_z = -
static_cast<int>(size_z / 2);
92 this->
weights.set_min_index(min_index_z);
94 for (
int z = min_index_z; z <= this->
weights.get_max_index(); ++z)
96 const unsigned int size_y = this->
weights[z].size();
98 warn_about_even_size =
true;
99 const int min_index_y = -
static_cast<int>(size_y / 2);
100 this->
weights[z].set_min_index(min_index_y);
101 for (
int y = min_index_y; y <= this->
weights[z].get_max_index(); ++y)
103 const unsigned int size_x = this->
weights[z][y].size();
105 warn_about_even_size =
true;
106 const int min_index_x = -
static_cast<int>(size_x / 2);
107 this->
weights[z][y].set_min_index(min_index_x);
112 if (warn_about_even_size)
113 warning(
"Parsing GibbsPrior: even number of weights occured in either x,y or z dimension.\n"
114 "I'll (effectively) make this odd by appending a 0 at the end.");
118template <
typename elemT,
typename potentialT>
123 return Succeeded::no;
124 this->_already_set_up =
false;
131 auto sizes = target_cast.get_lengths();
132 image_dim = { sizes[1], sizes[2], sizes[3] };
135 image_min_indices = target_cast.get_min_indices();
138 this->_already_set_up =
true;
139 return Succeeded::yes;
142template <
typename elemT,
typename potentialT>
150 std::string explanation;
151 if (!this->
kappa_ptr->has_same_characteristics(current_image_estimate, explanation))
152 error(
": GibbsPrior : kappa image does not have the same index range as the reconstructed image:" + explanation);
156template <
typename elemT,
typename potentialT>
164 this->_already_set_up =
false;
168template <
typename elemT,
typename potentialT>
172 return potentialT::is_convex();
175template <
typename elemT,
typename PotentialT>
181template <
typename elemT,
typename PotentialT>
185 this->penalisation_factor = penalisation_factor_v;
189template <
typename elemT,
typename PotentialT>
203 weights = Array<3, float>(IndexRange3D(min_dz, max_dz, -1, 1, -1, 1));
204 for (
int z = min_dz; z <= max_dz; ++z)
205 for (
int y = -1; y <= 1; ++y)
206 for (
int x = -1; x <= 1; ++x)
208 if (z == 0 && y == 0 && x == 0)
209 weights[0][0][0] = 0;
214 / sqrt(
square(x * grid_spacing.x()) +
square(y * grid_spacing.y()) +
square(z * grid_spacing.z()));
220template <
typename elemT,
typename PotentialT>
228template <
typename elemT,
typename PotentialT>
240template <
typename elemT,
typename PotentialT>
241shared_ptr<const DiscretisedDensity<3, elemT>>
248template <
typename elemT,
typename PotentialT>
255template <
typename elemT,
typename PotentialT>
260 this->
check(current_image_estimate);
261 if (this->_already_set_up ==
false)
262 error(
"GibbsPenalty: set_up has not been called");
263 if (this->penalisation_factor == 0)
266 const bool do_kappa = !is_null_ptr(
kappa_ptr);
270# if _OPENMP >= 201107
271# pragma omp parallel for collapse(3) reduction(+ : result)
273# pragma omp parallel for reduction(+ : result)
287 const elemT val_center = current_image_estimate[z][y][x];
289 for (
int dz = min_dz; dz <= max_dz; ++dz)
290 for (
int dy = min_dy; dy <= max_dy; ++dy)
291 for (
int dx = min_dx; dx <= max_dx; ++dx)
293 if ((dx == 0) && (dy == 0) && (dz == 0))
295 const elemT val_neigh = current_image_estimate[z + dz][y + dy][x + dx];
296 double current =
weights[dz][dy][dx] * this->
potential.value(val_center, val_neigh, z, y, x);
299 current *= (*kappa_ptr)[z][y][x] * (*kappa_ptr)[z + dz][y + dy][x + dx];
305 return result * this->penalisation_factor;
308template <
typename elemT,
typename PotentialT>
315 this->
check(current_image_estimate);
316 if (this->_already_set_up ==
false)
317 error(
"GibbsPenalty: set_up has not been called");
318 if (this->penalisation_factor == 0)
320 prior_gradient.
fill(0);
324 const bool do_kappa = !is_null_ptr(
kappa_ptr);
327# if _OPENMP >= 201107
328# pragma omp parallel for collapse(3)
330# pragma omp parallel for
344 const elemT val_center = current_image_estimate[z][y][x];
346 double gradient = 0.;
347 for (
int dz = min_dz; dz <= max_dz; ++dz)
348 for (
int dy = min_dy; dy <= max_dy; ++dy)
349 for (
int dx = min_dx; dx <= max_dx; ++dx)
351 if ((dx == 0) && (dy == 0) && (dz == 0))
353 const elemT val_neigh = current_image_estimate[z + dz][y + dy][x + dx];
354 double current =
weights[dz][dy][dx] * this->
potential.derivative_10(val_center, val_neigh, z, y, x);
356 current *= (*kappa_ptr)[z][y][x] * (*kappa_ptr)[z + dz][y + dy][x + dx];
359 prior_gradient[z][y][x] = 2 *
static_cast<elemT
>(gradient * this->penalisation_factor);
363template <
typename elemT,
typename PotentialT>
370 this->
check(current_image_estimate);
371 if (this->_already_set_up ==
false)
372 error(
"GibbsPenalty: set_up has not been called");
373 if (this->penalisation_factor == 0)
378 const bool do_kappa = !is_null_ptr(
kappa_ptr);
382# if _OPENMP >= 201107
383# pragma omp parallel for collapse(3) reduction(+ : result)
385# pragma omp parallel for reduction(+ : result)
400 const elemT val_center = current_image_estimate[z][y][x];
402 double gradient = 0.0;
403 for (
int dz = min_dz; dz <= max_dz; ++dz)
404 for (
int dy = min_dy; dy <= max_dy; ++dy)
405 for (
int dx = min_dx; dx <= max_dx; ++dx)
407 if ((dx == 0) && (dy == 0) && (dz == 0))
409 const elemT val_neigh = current_image_estimate[z + dz][y + dy][x + dx];
410 double current =
weights[dz][dy][dx] * this->
potential.derivative_10(val_center, val_neigh, z, y, x);
412 current *= (*kappa_ptr)[z][y][x] * (*kappa_ptr)[z + dz][y + dy][x + dx];
415 result += 2 * gradient * input[z][y][x];
417 return result * this->penalisation_factor;
420template <
typename elemT,
typename PotentialT>
427 this->
check(current_image_estimate);
428 if (this->_already_set_up ==
false)
429 error(
"GibbsPenalty: set_up has not been called");
430 prior_Hessian_for_single_densel.
fill(0);
431 if (this->penalisation_factor == 0)
433 prior_Hessian_for_single_densel.
fill(0);
440 const bool do_kappa = !is_null_ptr(
kappa_ptr);
442 const int z = coords[1];
443 const int y = coords[2];
444 const int x = coords[3];
446 const elemT val_center = current_image_estimate[z][y][x];
454 for (
int dz = min_dz; dz <= max_dz; ++dz)
455 for (
int dy = min_dy; dy <= max_dy; ++dy)
456 for (
int dx = min_dx; dx <= max_dx; ++dx)
459 if (dz == 0 && dy == 0 && dx == 0)
462 for (
int ddz = min_dz; ddz <= max_dz; ++ddz)
463 for (
int ddy = min_dy; ddy <= max_dy; ++ddy)
464 for (
int ddx = min_dx; ddx <= max_dx; ++ddx)
466 elemT diagonal_current =
weights[ddz][ddy][ddx] * 2
468 val_center, current_image_estimate[z + ddz][y + ddy][x + ddx], z, y, x);
470 diagonal_current *= (*kappa_ptr)[z][y][x] * (*kappa_ptr)[z + ddz][y + ddy][x + ddx];
471 current += diagonal_current;
477 current =
weights[dz][dy][dx] * 2
478 * this->
potential.derivative_11(val_center, current_image_estimate[z + dz][y + dy][x + dx], z, y, x);
480 current *= (*kappa_ptr)[z][y][x] * (*kappa_ptr)[z + dz][y + dy][x + dx];
482 prior_Hessian_for_single_densel_cast[z + dz][y + dy][x + dx] = current * this->penalisation_factor;
487template <
typename elemT,
typename PotentialT>
494 this->
check(current_image_estimate);
495 if (this->_already_set_up ==
false)
496 error(
"GibbsPenalty: set_up has not been called");
497 if (this->penalisation_factor == 0)
499 Hessian_diagonal.
fill(0);
503 const bool do_kappa = !is_null_ptr(
kappa_ptr);
506# if _OPENMP >= 201107
507# pragma omp parallel for collapse(3)
509# pragma omp parallel for
523 const elemT val_center = current_image_estimate[z][y][x];
525 double Hessian_diag_element = 0.;
526 for (
int dz = min_dz; dz <= max_dz; ++dz)
527 for (
int dy = min_dy; dy <= max_dy; ++dy)
528 for (
int dx = min_dx; dx <= max_dx; ++dx)
530 if ((dx == 0) && (dy == 0) && (dz == 0))
532 const elemT val_neigh = current_image_estimate[z + dz][y + dy][x + dx];
533 double current =
weights[dz][dy][dx] * this->
potential.derivative_20(val_center, val_neigh, z, y, x);
535 current *= (*kappa_ptr)[z][y][x] * (*kappa_ptr)[z + dz][y + dy][x + dx];
536 Hessian_diag_element += current;
538 Hessian_diagonal[z][y][x] = 2 *
static_cast<elemT
>(Hessian_diag_element * this->penalisation_factor);
542template <
typename elemT,
typename PotentialT>
551 this->
check(current_image_estimate);
552 if (this->_already_set_up ==
false)
553 error(
"GibbsPenalty: set_up has not been called");
554 if (this->penalisation_factor == 0)
560 const bool do_kappa = !is_null_ptr(
kappa_ptr);
563# if _OPENMP >= 201107
564# pragma omp parallel for collapse(3)
566# pragma omp parallel for
581 const elemT val_center = current_image_estimate[z][y][x];
582 const elemT input_center = input[z][y][x];
593 for (
int dz = min_dz; dz <= max_dz; ++dz)
594 for (
int dy = min_dy; dy <= max_dy; ++dy)
595 for (
int dx = min_dx; dx <= max_dx; ++dx)
597 elemT current =
weights[dz][dy][dx];
598 const elemT val_neigh = current_image_estimate[z + dz][y + dy][x + dx];
599 const elemT input_neigh = input[z + dz][y + dy][x + dx];
601 if ((dz == 0) && (dy == 0) && (dx == 0))
602 current *= this->
potential.derivative_20(val_center, val_neigh, z, y, x) * input_center;
605 current *=
potential.derivative_20(val_center, val_neigh, z, y, x) * input_center
606 +
potential.derivative_11(val_center, val_neigh, z, y, x) * input_neigh;
609 current *= (*kappa_ptr)[z][y][x] * (*kappa_ptr)[z + dz][y + dy][x + dx];
614 output[z][y][x] += 2 * result * this->penalisation_factor;
This file declares class stir::BasicCoordinate and some functions acting on stir::BasicCoordinate obj...
defines the stir::DiscretisedDensityOnCartesianGrid class
Declaration of the stir::GibbsPenalty class.
This file declares the class stir::IndexRange3D.
Declaration of class stir::Succeeded.
defines the stir::VoxelsOnCartesianGrid class
This class defines multi-dimensional (numeric) arrays.
Definition Array.h:78
void fill(const elemT &n)
Fill elements with value n.
Definition Array.inl:439
class BasicCoordinate<int num_dimensions, typename coordT> defines num_dimensions -dimensional coordi...
Definition BasicCoordinate.h:57
a templated class for 3-dimensional coordinates.
Definition CartesianCoordinate3D.h:53
This abstract class is the basis for images on a Cartesian grid.
Definition DiscretisedDensityOnCartesianGrid.h:45
This abstract class is the basis for all image representations.
Definition DiscretisedDensity.h:99
bool has_same_characteristics(self_type const &, std::string &explanation) const
Checks if the 2 objects have the same type, index range, origin etc.
virtual Succeeded set_up(shared_ptr< const DiscretisedDensity< 3, elemT > > const &target_sptr)
virtual void check(DiscretisedDensity< 3, elemT > const ¤t_estimate) const
void initialise_keymap() override
void set_defaults() override
bool post_processing() override
This will be called at the end of the parsing.
Definition GibbsPenalty.inl:67
CartesianCoordinate3D< int > image_max_indices
Definition GibbsPenalty.h:165
bool is_convex() const override
Return whether the prior is convex or not.
Definition GibbsPenalty.inl:170
CartesianCoordinate3D< int > image_dim
Definition GibbsPenalty.h:164
Succeeded set_up(shared_ptr< const DiscretisedDensity< 3, elemT > > const &target_sptr) override
Set up the prior for a target image. Must be called before use.
Definition GibbsPenalty.inl:120
void check(DiscretisedDensity< 3, elemT > const ¤t_image_estimate) const override
Check that the prior is ready to be used.
Definition GibbsPenalty.inl:144
potentialT potential
Gibbs Potential Function.
Definition GibbsPenalty.h:186
CartesianCoordinate3D< int > image_min_indices
Minimum image indices.
Definition GibbsPenalty.h:166
shared_ptr< const DiscretisedDensity< 3, elemT > > get_kappa_sptr() const
get current kappa image
Definition GibbsPenalty.inl:242
void compute_default_weights(const CartesianCoordinate3D< float > &grid_spacing, bool only_2D)
const Array< 3, float > & get_weights() const
Get the current weights array.
Definition GibbsPenalty.inl:222
void compute_Hessian(DiscretisedDensity< 3, elemT > &prior_Hessian_for_single_densel, const BasicCoordinate< 3, int > &coords, const DiscretisedDensity< 3, elemT > ¤t_image_estimate) const override
Compute the Hessian row of the prior at (coords).
Definition GibbsPenalty.inl:422
std::string kappa_filename
Filename for the image that will be read by post_processing()
Definition GibbsPenalty.h:183
virtual std::string get_parsing_name() const
Getter method to retrieve the parsing name.
Definition GibbsPenalty.inl:46
virtual void set_kappa_sptr(const shared_ptr< const DiscretisedDensity< 3, elemT > > &)
Set the kappa image (spatially-varying penalty factors).
Definition GibbsPenalty.inl:250
void set_defaults() override
sets value for penalisation factor
Definition GibbsPenalty.inl:158
double compute_gradient_times_input(const DiscretisedDensity< 3, elemT > &input, const DiscretisedDensity< 3, elemT > ¤t_image_estimate) override
Compute the dot product of the prior gradient and an input image.
Definition GibbsPenalty.inl:365
bool only_2D
can be set during parsing to restrict the weights to the 2D case
Definition GibbsPenalty.h:173
double compute_value(const DiscretisedDensity< 3, elemT > ¤t_image_estimate) override
Compute the value of the prior for the current image estimate.
Definition GibbsPenalty.inl:257
virtual void set_weights(const Array< 3, float > &)
Set the weights array for the prior.
Definition GibbsPenalty.inl:230
shared_ptr< const DiscretisedDensity< 3, elemT > > kappa_ptr
The kappa image (spatially-varying penalty factors).
Definition GibbsPenalty.h:199
Array< 3, float > weights
The weights for the neighbourhood.
Definition GibbsPenalty.h:170
std::string gradient_filename_prefix
filename prefix for outputing the gradient whenever compute_gradient() is called.
Definition GibbsPenalty.h:180
void initialise_keymap() override
sets key for penalisation factor
Definition GibbsPenalty.inl:53
void compute_Hessian_diagonal(DiscretisedDensity< 3, elemT > &Hessian_diagonal, const DiscretisedDensity< 3, elemT > ¤t_estimate) const override
Compute the diagonal of the Hessian matrix.
Definition GibbsPenalty.inl:489
GibbsPenalty()
Default constructor.
Definition GibbsPenalty.inl:176
void accumulate_Hessian_times_input(DiscretisedDensity< 3, elemT > &output, const DiscretisedDensity< 3, elemT > ¤t_estimate, const DiscretisedDensity< 3, elemT > &input) const override
Accumulate Hessian times input image into output.
Definition GibbsPenalty.inl:544
void compute_gradient(DiscretisedDensity< 3, elemT > &prior_gradient, const DiscretisedDensity< 3, elemT > ¤t_image_estimate) override
Compute the gradient of the prior for the current image estimate.
Definition GibbsPenalty.inl:310
virtual bool post_processing()
This will be called at the end of the parsing.
Definition ParsingObject.cxx:56
virtual std::string get_registered_name() const =0
Returns the name of the type of the object.
a class containing an enumeration type that can be used by functions to signal successful operation o...
Definition Succeeded.h:44
This class is used to represent voxelised densities on a cuboid grid (3D).
Definition VoxelsOnCartesianGrid.h:46
Declaration of stir::error()
unique_ptr< DataT > read_from_file(const FileSignature &signature, FileT file)
Function that reads data from file using the default InputFileFormatRegistry, using the provided File...
Definition read_from_file.h:46
void error(const char *const s,...)
Print error with format string a la printf and throw exception.
Definition error.cxx:42
void warning(const char *const s,...)
Print warning with format string a la printf.
Definition warning.cxx:41
NUMBER square(const NUMBER &x)
returns the square of a number, templated.
Definition common.h:154
Declaration of stir::info()
Definition of stir::is_null_ptr functions.
Declaration of stir::read_from_file functions (providing easy access to class stir::InputFileFormatRe...
Declaration of stir::warning()
Declaration of stir::write_to_file function (providing easy access to the default stir::OutputFileFor...