GooseEYE 0.9.1
Loading...
Searching...
No Matches
Ensemble_W2c.hpp
Go to the documentation of this file.
1
7#ifndef GOOSEEYE_ENSEMBLE_W2C_HPP
8#define GOOSEEYE_ENSEMBLE_W2C_HPP
9
10#include "GooseEYE.h"
11
12namespace GooseEYE {
13
14template <class C, class T, class M>
15inline void
16Ensemble::W2c(const C& clusters, const C& centers, const T& f, const M& fmask, path_mode mode)
17{
18 using value_type = typename T::value_type;
19 using mask_type = typename M::value_type;
20 using cluster_type = typename C::value_type;
21
22 static_assert(std::is_integral<cluster_type>::value, "Integral clusters required.");
23 static_assert(std::is_integral<mask_type>::value, "Integral mask required.");
24
25 GOOSEEYE_ASSERT(f.shape() == clusters.shape(), std::out_of_range);
26 GOOSEEYE_ASSERT(f.shape() == centers.shape(), std::out_of_range);
27 GOOSEEYE_ASSERT(xt::has_shape(f, fmask.shape()), std::out_of_range);
28 GOOSEEYE_ASSERT(f.dimension() == m_shape_orig.size(), std::out_of_range);
29 GOOSEEYE_ASSERT(xt::all(xt::equal(fmask, 0) || xt::equal(fmask, 1)), std::out_of_range);
30 GOOSEEYE_ASSERT(m_stat == Type::W2c || m_stat == Type::Unset, std::out_of_range);
31
32 // lock statistic
33 m_stat = Type::W2c;
34
35 // not periodic (default): mask padded items
36 xt::pad_mode pad_mode = xt::pad_mode::constant;
37
38 // periodic: unmask padded items
39 if (m_periodic) {
40 pad_mode = xt::pad_mode::periodic;
41 }
42
43 // apply padding
44 array_type::tensor<value_type, 3> F = xt::pad(xt::atleast_3d(f), m_pad, pad_mode);
45 array_type::tensor<double, 3> Fd = xt::pad(xt::atleast_3d(f), m_pad, pad_mode);
46 array_type::tensor<mask_type, 3> Fmask = xt::pad(xt::atleast_3d(fmask), m_pad, pad_mode);
48 xt::pad(xt::atleast_3d(clusters), m_pad, pad_mode);
49 array_type::tensor<cluster_type, 3> Centers = xt::pad(xt::atleast_3d(centers), m_pad, pad_mode);
50
51 // ROI-shaped array used to extract a pixel stamp:
52 // a set of end-points over which to loop and check the statics
53 // - initialize to 1
54 array_type::tensor<int, 3> r = xt::ones<int>(m_shape);
55 // - determine interior pixels (account for quasi-3D images)
56 auto ix = m_shape[0] > 1 ? xt::range(1, m_shape[0] - 1) : xt::range(0, m_shape[0]);
57 auto iy = m_shape[1] > 1 ? xt::range(1, m_shape[1] - 1) : xt::range(0, m_shape[1]);
58 auto iz = m_shape[2] > 1 ? xt::range(1, m_shape[2] - 1) : xt::range(0, m_shape[2]);
59 // - set interior pixels to 0
60 xt::view(r, ix, iy, iz) = 0;
61
62 // get stamp, from the matrix "r"
63 array_type::tensor<int, 2> stamp = xt::from_indices(xt::argwhere(r));
64 for (size_t i = 0; i < MAX_DIM; ++i) {
65 xt::view(stamp, xt::all(), xt::keep(i)) -= m_pad[i][0];
66 }
67
68 // correlation
69 // N.B. getting the pixel paths is relatively expensive, so it is the output-most loop
70 for (size_t istamp = 0; istamp < stamp.shape(0); ++istamp) {
71
72 // pixel path between the center of the ROI and the current stamp point
74 GooseEYE::path({0, 0, 0}, {stamp(istamp, 0), stamp(istamp, 1), stamp(istamp, 2)}, mode);
75
76 for (size_t h = m_pad[0][0]; h < F.shape(0) - m_pad[0][1]; ++h) {
77 for (size_t i = m_pad[1][0]; i < F.shape(1) - m_pad[1][1]; ++i) {
78 for (size_t j = m_pad[2][0]; j < F.shape(2) - m_pad[2][1]; ++j) {
79
80 auto label = Centers(h, i, j);
81 int q = -1;
82
83 // proceed only when the centre is inside the cluster
84 if (!label || Clusters(h, i, j) != label) {
85 continue;
86 }
87
88 for (size_t p = 0; p < path.shape(0); ++p) {
89
90 int dh = path(p, 0);
91 int di = path(p, 1);
92 int dj = path(p, 2);
93
94 // loop through the voxel-path until the end of a cluster
95 if (Clusters(h + dh, i + di, j + dj) != label && q < 0) {
96 q = 0;
97 }
98
99 // loop from the beginning of the path and store there
100 if (q >= 0) {
101 if (!Fmask(h + dh, i + di, j + dj)) {
102 m_norm(
103 m_pad[0][0] + path(q, 0),
104 m_pad[1][0] + path(q, 1),
105 m_pad[1][0] + path(q, 2)) += 1;
106
107 m_first(
108 m_pad[0][0] + path(q, 0),
109 m_pad[1][0] + path(q, 1),
110 m_pad[1][0] + path(q, 2)) += Fd(h + dh, i + di, j + dj);
111 }
112 }
113
114 q++;
115 }
116 }
117 }
118 }
119 }
120}
121
122template <class C, class T>
123inline void Ensemble::W2c(const C& clusters, const C& centers, const T& f, path_mode mode)
124{
125 array_type::array<int> mask = xt::zeros<int>(f.shape());
126 W2c(clusters, centers, f, mask, mode);
127}
128
129} // namespace GooseEYE
130
131#endif
void W2c(const C &clusters, const C &centers, const T &f, path_mode mode=path_mode::Bresenham)
Add realization to collapsed weighted 2-point correlation.
#define GOOSEEYE_ASSERT(expr, assertion)
All assertions are implemented as:
Definition config.h:91
xt::xtensor< T, N > tensor
Fixed (static) rank array.
Definition config.h:155
Toolbox to compute statistics.
Definition config.h:128
path_mode
Different methods to compute a pixel-path.
Definition GooseEYE.h:93
array_type::array< int > clusters(const T &f, bool periodic=true)
Compute clusters.
Definition GooseEYE.h:1198
array_type::tensor< int, 2 > path(const array_type::tensor< int, 1 > &x0, const array_type::tensor< int, 1 > &x1, path_mode mode=path_mode::Bresenham)
Compute a path between two pixels.
Definition GooseEYE.hpp:15