STIR 6.4.0
GibbsPenalty.inl
Go to the documentation of this file.
1//
2//
3/*
4 Copyright (C) 2025, University College London
5 Copyright (C) 2025, University of Milano-Bicocca
6 Copyright (C) 2000- 2005, Hammersmith Imanet Ltd
7
8 This file is part of STIR.
9
10 SPDX-License-Identifier: Apache-2.0
11
12 See STIR/LICENSE.txt for details
13*/
24
26#include "stir/Succeeded.h"
29#include "stir/IndexRange3D.h"
33#include "stir/is_null_ptr.h"
34#include "stir/info.h"
35#include "stir/warning.h"
36#include "stir/error.h"
37#include <algorithm>
38#ifdef STIR_OPENMP
39# include <omp.h>
40#endif
41
42START_NAMESPACE_STIR
43
44template <typename elemT, typename potentialT>
45std::string
47{
48 return this->get_registered_name() + " Penalty Parameters";
49}
50
51template <typename elemT, typename potentialT>
52void
54{
56 this->parser.add_start_key(this->get_parsing_name());
57 this->parser.add_key("only 2D", &only_2D);
58 this->parser.add_key("kappa filename", &kappa_filename);
59 this->parser.add_key("weights", &weights);
60 this->parser.add_key("gradient filename prefix", &gradient_filename_prefix);
61 this->potential.initialise_keymap(this->parser);
62 this->parser.add_stop_key("END " + this->get_parsing_name());
63}
64
65template <typename elemT, typename potentialT>
66bool
68{
69 if (base_type::post_processing() == true)
70 return true;
71 if (kappa_filename.size() != 0)
73
74 bool warn_about_even_size = false;
75
76 if (this->weights.size() == 0)
77 {
78 // will call compute_weights() to fill it in
79 }
80 else
81 {
82 if (!this->weights.is_regular())
83 {
84 warning("Sorry. GibbsPrior currently only supports regular arrays for the weights");
85 return true;
86 }
87
88 const unsigned int size_z = this->weights.size();
89 if (size_z % 2 == 0)
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);
93
94 for (int z = min_index_z; z <= this->weights.get_max_index(); ++z)
95 {
96 const unsigned int size_y = this->weights[z].size();
97 if (size_y % 2 == 0)
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)
102 {
103 const unsigned int size_x = this->weights[z][y].size();
104 if (size_x % 2 == 0)
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);
109 }
110 }
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.");
115 return false;
116}
117
118template <typename elemT, typename potentialT>
121{
122 if (base_type::set_up(target_sptr) == Succeeded::no)
123 return Succeeded::no;
124 this->_already_set_up = false;
125 auto& target_cast = dynamic_cast<const VoxelsOnCartesianGrid<elemT>&>(*target_sptr);
126
127 // Set the default weights if not set
128 if (weights.get_length() == 0)
129 compute_default_weights(target_cast.get_voxel_size(), this->only_2D);
130
131 auto sizes = target_cast.get_lengths();
132 image_dim = { sizes[1], sizes[2], sizes[3] };
133
134 // Set the boundary of the image
135 image_min_indices = target_cast.get_min_indices();
136 image_max_indices = target_cast.get_max_indices();
137
138 this->_already_set_up = true;
139 return Succeeded::yes;
140}
141
142template <typename elemT, typename potentialT>
143void
145{
146 // Do base-class check
147 base_type::check(current_image_estimate);
148 if (!is_null_ptr(this->kappa_ptr))
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);
153 }
154}
155
156template <typename elemT, typename potentialT>
157void
161 this->only_2D = false;
162 this->kappa_ptr.reset();
163 this->weights.recycle();
164 this->_already_set_up = false;
165 this->potential.set_defaults();
166}
167
168template <typename elemT, typename potentialT>
169bool
171{
172 return potentialT::is_convex();
173}
174
175template <typename elemT, typename PotentialT>
180
181template <typename elemT, typename PotentialT>
182GibbsPenalty<elemT, PotentialT>::GibbsPenalty(const bool only_2D_v, float penalisation_factor_v)
183 : only_2D(only_2D_v)
184{
185 this->penalisation_factor = penalisation_factor_v;
186}
187
188// initialise weights to dx/Euclidean distance
189template <typename elemT, typename PotentialT>
190void
193 int min_dz, max_dz;
196 min_dz = max_dz = 0;
197 }
198 else
199 {
200 min_dz = -1;
201 max_dz = 1;
202 }
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)
207 {
208 if (z == 0 && y == 0 && x == 0)
209 weights[0][0][0] = 0;
210 else
211 {
212 weights[z][y][x]
213 = grid_spacing.x()
214 / sqrt(square(x * grid_spacing.x()) + square(y * grid_spacing.y()) + square(z * grid_spacing.z()));
215 }
216 }
217}
218
220template <typename elemT, typename PotentialT>
221const Array<3, float>&
223{
224 return this->weights;
225}
226
228template <typename elemT, typename PotentialT>
229void
234
236
240template <typename elemT, typename PotentialT>
241shared_ptr<const DiscretisedDensity<3, elemT>>
246
248template <typename elemT, typename PotentialT>
249void
254
255template <typename elemT, typename PotentialT>
256double
258{
259 // Preliminary Checks
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)
264 return 0.;
265
266 const bool do_kappa = !is_null_ptr(kappa_ptr);
267
268 double result = 0.0;
269#ifdef STIR_OPENMP
270# if _OPENMP >= 201107 // OpenMP 3.1 or newer supports collapse(3)
271# pragma omp parallel for collapse(3) reduction(+ : result)
272# else // just parallelize the outermost loop
273# pragma omp parallel for reduction(+ : result)
274# endif
275#endif
276
277 for (int z = image_min_indices.z(); z <= image_max_indices.z(); ++z)
278 for (int y = image_min_indices.y(); y <= image_max_indices.y(); ++y)
279 for (int x = image_min_indices.x(); x <= image_max_indices.x(); ++x)
280 {
281 const int min_dz = std::max(weights.get_min_index(), image_min_indices.z() - z);
282 const int max_dz = std::min(weights.get_max_index(), image_max_indices.z() - z);
283 const int min_dy = std::max(weights[0].get_min_index(), image_min_indices.y() - y);
284 const int max_dy = std::min(weights[0].get_max_index(), image_max_indices.y() - y);
285 const int min_dx = std::max(weights[0][0].get_min_index(), image_min_indices.x() - x);
286 const int max_dx = std::min(weights[0][0].get_max_index(), image_max_indices.x() - x);
287 const elemT val_center = current_image_estimate[z][y][x];
288
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)
292 {
293 if ((dx == 0) && (dy == 0) && (dz == 0))
294 continue;
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);
297
298 if (do_kappa)
299 current *= (*kappa_ptr)[z][y][x] * (*kappa_ptr)[z + dz][y + dy][x + dx];
300
301 result += current;
302 }
303 }
304
305 return result * this->penalisation_factor;
306}
307
308template <typename elemT, typename PotentialT>
309void
311 const DiscretisedDensity<3, elemT>& current_image_estimate)
312{
313 // Preliminary Checks
314 assert(prior_gradient.has_same_characteristics(current_image_estimate));
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)
319 {
320 prior_gradient.fill(0);
321 return;
322 }
323
324 const bool do_kappa = !is_null_ptr(kappa_ptr);
325
326#ifdef STIR_OPENMP
327# if _OPENMP >= 201107 // OpenMP 3.1 or newer supports collapse(3)
328# pragma omp parallel for collapse(3)
329# else // just parallelize the outermost loop
330# pragma omp parallel for
331# endif
332#endif
333
334 for (int z = image_min_indices.z(); z <= image_max_indices.z(); ++z)
335 for (int y = image_min_indices.y(); y <= image_max_indices.y(); ++y)
336 for (int x = image_min_indices.x(); x <= image_max_indices.x(); ++x)
337 {
338 const int min_dz = std::max(weights.get_min_index(), image_min_indices.z() - z);
339 const int max_dz = std::min(weights.get_max_index(), image_max_indices.z() - z);
340 const int min_dy = std::max(weights[0].get_min_index(), image_min_indices.y() - y);
341 const int max_dy = std::min(weights[0].get_max_index(), image_max_indices.y() - y);
342 const int min_dx = std::max(weights[0][0].get_min_index(), image_min_indices.x() - x);
343 const int max_dx = std::min(weights[0][0].get_max_index(), image_max_indices.x() - x);
344 const elemT val_center = current_image_estimate[z][y][x];
345
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)
350 {
351 if ((dx == 0) && (dy == 0) && (dz == 0))
352 continue;
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);
355 if (do_kappa)
356 current *= (*kappa_ptr)[z][y][x] * (*kappa_ptr)[z + dz][y + dy][x + dx];
357 gradient += current;
358 }
359 prior_gradient[z][y][x] = 2 * static_cast<elemT>(gradient * this->penalisation_factor);
360 }
361}
362
363template <typename elemT, typename PotentialT>
364double
366 const DiscretisedDensity<3, elemT>& current_image_estimate)
367{
368 // Preliminary Checks
369 assert(input.has_same_characteristics(current_image_estimate));
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)
374 {
375 return 0.0;
376 }
377
378 const bool do_kappa = !is_null_ptr(kappa_ptr);
379
380 double result = 0.0;
381#ifdef STIR_OPENMP
382# if _OPENMP >= 201107 // OpenMP 3.1 or newer supports collapse(3)
383# pragma omp parallel for collapse(3) reduction(+ : result)
384# else // just parallelize the outermost loop
385# pragma omp parallel for reduction(+ : result)
386# endif
387#endif
388
389 for (int z = image_min_indices.z(); z <= image_max_indices.z(); ++z)
390 for (int y = image_min_indices.y(); y <= image_max_indices.y(); ++y)
391 for (int x = image_min_indices.x(); x <= image_max_indices.x(); ++x)
392
393 {
394 const int min_dz = std::max(weights.get_min_index(), image_min_indices.z() - z);
395 const int max_dz = std::min(weights.get_max_index(), image_max_indices.z() - z);
396 const int min_dy = std::max(weights[0].get_min_index(), image_min_indices.y() - y);
397 const int max_dy = std::min(weights[0].get_max_index(), image_max_indices.y() - y);
398 const int min_dx = std::max(weights[0][0].get_min_index(), image_min_indices.x() - x);
399 const int max_dx = std::min(weights[0][0].get_max_index(), image_max_indices.x() - x);
400 const elemT val_center = current_image_estimate[z][y][x];
401
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)
406 {
407 if ((dx == 0) && (dy == 0) && (dz == 0))
408 continue;
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);
411 if (do_kappa)
412 current *= (*kappa_ptr)[z][y][x] * (*kappa_ptr)[z + dz][y + dy][x + dx];
413 gradient += current;
414 }
415 result += 2 * gradient * input[z][y][x];
416 }
417 return result * this->penalisation_factor;
418}
419
420template <typename elemT, typename PotentialT>
421void
423 const BasicCoordinate<3, int>& coords,
424 const DiscretisedDensity<3, elemT>& current_image_estimate) const
425{
426 assert(prior_Hessian_for_single_densel.has_same_characteristics(current_image_estimate));
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)
432 {
433 prior_Hessian_for_single_densel.fill(0);
434 return;
435 }
436
437 DiscretisedDensityOnCartesianGrid<3, elemT>& prior_Hessian_for_single_densel_cast
438 = dynamic_cast<DiscretisedDensityOnCartesianGrid<3, elemT>&>(prior_Hessian_for_single_densel);
439
440 const bool do_kappa = !is_null_ptr(kappa_ptr);
441
442 const int z = coords[1];
443 const int y = coords[2];
444 const int x = coords[3];
445
446 const elemT val_center = current_image_estimate[z][y][x];
447
448 const int min_dz = std::max(weights.get_min_index(), image_min_indices.z() - z);
449 const int max_dz = std::min(weights.get_max_index(), image_max_indices.z() - z);
450 const int min_dy = std::max(weights[0].get_min_index(), image_min_indices.y() - y);
451 const int max_dy = std::min(weights[0].get_max_index(), image_max_indices.y() - y);
452 const int min_dx = std::max(weights[0][0].get_min_index(), image_min_indices.x() - x);
453 const int max_dx = std::min(weights[0][0].get_max_index(), image_max_indices.x() - 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)
457 {
458 elemT current = 0.0;
459 if (dz == 0 && dy == 0 && dx == 0)
460 {
461 // The j == k case (diagonal Hessian element), which is a sum over the neighbourhood.
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)
465 {
466 elemT diagonal_current = weights[ddz][ddy][ddx] * 2
467 * this->potential.derivative_20(
468 val_center, current_image_estimate[z + ddz][y + ddy][x + ddx], z, y, x);
469 if (do_kappa)
470 diagonal_current *= (*kappa_ptr)[z][y][x] * (*kappa_ptr)[z + ddz][y + ddy][x + ddx];
471 current += diagonal_current;
472 }
473 }
474 else
475 {
476 // The j != k vases (off-diagonal Hessian elements)
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);
479 if (do_kappa)
480 current *= (*kappa_ptr)[z][y][x] * (*kappa_ptr)[z + dz][y + dy][x + dx];
481 }
482 prior_Hessian_for_single_densel_cast[z + dz][y + dy][x + dx] = current * this->penalisation_factor;
483 // std::cout<<"val ["<<z + dz<<"]["<<y + dy<<"]["<<x + dx<<"] = "<<current<<std::endl;
484 }
485}
486
487template <typename elemT, typename PotentialT>
488void
490 const DiscretisedDensity<3, elemT>& current_image_estimate) const
491{
492 // Preliminary Checks
493 assert(Hessian_diagonal.has_same_characteristics(current_image_estimate));
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)
498 {
499 Hessian_diagonal.fill(0);
500 return;
501 }
502
503 const bool do_kappa = !is_null_ptr(kappa_ptr);
504
505#ifdef STIR_OPENMP
506# if _OPENMP >= 201107 // OpenMP 3.1 or newer supports collapse(3)
507# pragma omp parallel for collapse(3)
508# else // just parallelize the outermost loop
509# pragma omp parallel for
510# endif
511#endif
512
513 for (int z = image_min_indices.z(); z <= image_max_indices.z(); ++z)
514 for (int y = image_min_indices.y(); y <= image_max_indices.y(); ++y)
515 for (int x = image_min_indices.x(); x <= image_max_indices.x(); ++x)
516 {
517 const int min_dz = std::max(weights.get_min_index(), image_min_indices.z() - z);
518 const int max_dz = std::min(weights.get_max_index(), image_max_indices.z() - z);
519 const int min_dy = std::max(weights[0].get_min_index(), image_min_indices.y() - y);
520 const int max_dy = std::min(weights[0].get_max_index(), image_max_indices.y() - y);
521 const int min_dx = std::max(weights[0][0].get_min_index(), image_min_indices.x() - x);
522 const int max_dx = std::min(weights[0][0].get_max_index(), image_max_indices.x() - x);
523 const elemT val_center = current_image_estimate[z][y][x];
524
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)
529 {
530 if ((dx == 0) && (dy == 0) && (dz == 0))
531 continue;
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);
534 if (do_kappa)
535 current *= (*kappa_ptr)[z][y][x] * (*kappa_ptr)[z + dz][y + dy][x + dx];
536 Hessian_diag_element += current;
537 }
538 Hessian_diagonal[z][y][x] = 2 * static_cast<elemT>(Hessian_diag_element * this->penalisation_factor);
539 }
540}
541
542template <typename elemT, typename PotentialT>
543void
545 const DiscretisedDensity<3, elemT>& current_image_estimate,
546 const DiscretisedDensity<3, elemT>& input) const
547{
548 // Preliminary Checks
549 assert(output.has_same_characteristics(current_image_estimate));
550 assert(input.has_same_characteristics(current_image_estimate));
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)
555 {
556 return;
557 }
558
559 this->check(input);
560 const bool do_kappa = !is_null_ptr(kappa_ptr);
561
562#ifdef STIR_OPENMP
563# if _OPENMP >= 201107 // OpenMP 3.1 or newer supports collapse(3)
564# pragma omp parallel for collapse(3)
565# else // just parallelize the outermost loop
566# pragma omp parallel for
567# endif
568#endif
569
570 for (int z = image_min_indices.z(); z <= image_max_indices.z(); ++z)
571 for (int y = image_min_indices.y(); y <= image_max_indices.y(); ++y)
572 for (int x = image_min_indices.x(); x <= image_max_indices.x(); ++x)
573 {
574 const int min_dz = std::max(weights.get_min_index(), image_min_indices.z() - z);
575 const int max_dz = std::min(weights.get_max_index(), image_max_indices.z() - z);
576 const int min_dy = std::max(weights[0].get_min_index(), image_min_indices.y() - y);
577 const int max_dy = std::min(weights[0].get_max_index(), image_max_indices.y() - y);
578 const int min_dx = std::max(weights[0][0].get_min_index(), image_min_indices.x() - x);
579 const int max_dx = std::min(weights[0][0].get_max_index(), image_max_indices.x() - x);
580
581 const elemT val_center = current_image_estimate[z][y][x];
582 const elemT input_center = input[z][y][x];
583
584 // At this point, we have j = [z][y][x]
585 // The next for loops will have k = [z+dz][y+dy][x+dx]
586 // The following computes
587 //[H y]_j =
588 // \sum_{k\in N_j} w_{(j,k)} f''_{d}(x_j,x_k) y_j +
589 // \sum_{(i \in N_j) \ne j} w_{(j,i)} f''_{od}(x_j, x_i) y_i
590 // Note the condition in the second sum that i is not equal to j
591
592 elemT result = 0;
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)
596 {
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];
600
601 if ((dz == 0) && (dy == 0) && (dx == 0))
602 current *= this->potential.derivative_20(val_center, val_neigh, z, y, x) * input_center;
603
604 else
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;
607
608 if (do_kappa)
609 current *= (*kappa_ptr)[z][y][x] * (*kappa_ptr)[z + dz][y + dy][x + dx];
610
611 result += current;
612 }
613
614 output[z][y][x] += 2 * result * this->penalisation_factor;
615 }
616}
617
618END_NAMESPACE_STIR
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 &current_estimate) const
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 &current_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 > &current_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 > &current_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 > &current_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 > &current_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 > &current_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 > &current_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...