+
+
+
+
+
+
+
+
+
+
+
+
+
22inline std::string get_namespace()
+
+
24 std::string ret =
"GooseEYE";
+
25#ifdef GOOSEEYE_USE_XTENSOR_PYTHON
+
+
+
+
+
+
+
+
37inline std::string shape_to_string(
const T& shape)
+
+
39 std::string ret =
"[";
+
40 for (
size_t i = 0; i < shape.size(); ++i) {
+
41 ret += std::to_string(shape[i]);
+
42 if (i < shape.size() - 1) {
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
97 const std::vector<size_t>& shape,
+
+
+
+
101 bool periodic =
true)
+
+
+
+
+
+
+
+
+
110 for (
size_t i = 0; i < row.size(); ++i) {
+
111 for (
int di = -r(i); di <= r(i); ++di) {
+
112 for (
int dj = -r(i); dj <= r(i); ++dj) {
+
113 int dr = (int)(ceil(pow((
double)(pow(di, 2) + pow(dj, 2)), 0.5)));
+
+
115 out.periodic(row(i) + di, col(i) + dj) = 1;
+
+
+
+
+
+
+
+
+
124 for (
size_t i = 0; i < row.size(); ++i) {
+
125 for (
int di = -r(i); di <= r(i); ++di) {
+
126 for (
int dj = -r(i); dj <= r(i); ++dj) {
+
127 if (out.in_bounds(row(i) + di, col(i) + dj)) {
+
128 int dr = (int)(ceil(pow((
double)(pow(di, 2) + pow(dj, 2)), 0.5)));
+
+
130 out(row(i) + di, col(i) + dj) = 1;
+
+
+
+
+
+
+
+
+
+
+
+
+
148dummy_circles(
const std::vector<size_t>& shape,
bool periodic =
true, uint64_t seed = 0)
+
+
+
151 prrng::pcg32 rng(seed);
+
+
+
154 size_t N = (size_t)(0.05 * (
double)shape[0]);
+
155 size_t M = (size_t)(0.05 * (
double)shape[1]);
+
156 size_t R = (size_t)(pow((0.3 * (
double)(shape[0] * shape[1])) / (M_PI * (double)(N * M)), 0.5));
+
+
+
+
+
+
+
163 for (
size_t i = 0; i < N; i++) {
+
164 for (
size_t j = 0; j < M; j++) {
+
165 row[i * M + j] = (int)((
double)i * (double)shape[0] / (
double)N);
+
166 col[i * M + j] = (int)((
double)j * (double)shape[1] / (
double)M);
+
167 r[i * M + j] = (int)R;
+
+
+
+
+
172 int dN = (int)(0.5 * (
double)shape[0] / (double)N);
+
173 int dM = (int)(0.5 * (
double)shape[1] / (double)M);
+
+
+
176 for (
size_t i = 0; i < N * M; i++) {
+
177 row(i) += rng.randint(2 * dN) - dN;
+
178 col(i) += rng.randint(2 * dM) - dM;
+
179 r(i) = (double)r(i) * 2.0 * rng.random();
+
+
+
+
+
+
+
+
+
+
+
+
199 std::is_integral<typename T::value_type>::value &&
+
200 std::is_integral<typename S::value_type>::value,
+
+
+
+
+
+
206 bool periodic =
true);
+
+
212template <class T, std::enable_if_t<std::is_integral<typename T::value_type>::value,
int> = 0>
+
+
+
+
+
+
+
223 std::is_integral<typename T::value_type>::value &&
+
224 std::is_integral<typename S::value_type>::value,
+
+
226inline T
dilate(
const T& f,
const S& kernel,
size_t iterations = 1,
bool periodic =
true);
+
+
232template <class T, std::enable_if_t<std::is_integral<typename T::value_type>::value,
int> = 0>
+
233inline T
dilate(
const T& f,
size_t iterations = 1,
bool periodic =
true);
+
+
+
+
+
+
244 using value_type =
typename T::value_type;
+
245 std::map<value_type, value_type> map;
+
+
247 for (
size_t i = 0; i < a.size(); ++i) {
+
248 map.try_emplace(a.flat(i), b.flat(i));
+
+
+
+
+
253 xt::empty<typename T::value_type>(std::array<size_t, 2>{map.size(), 2});
+
+
255 for (
auto const& [key, val] : map) {
+
+
+
+
+
+
+
+
+
+
270template <
class L,
class A>
+
+
+
+
+
+
275 using value_type =
typename A::value_type;
+
276 std::map<value_type, value_type> map;
+
277 for (
size_t i = 0; i < rename.shape(0); ++i) {
+
278 map.emplace(rename(i, 0), rename(i, 1));
+
+
+
281#ifdef GOOSEEYE_ENABLE_ASSERT
+
282 auto l = xt::unique(labels);
+
283 for (
size_t i = 0; i < l.size(); ++i) {
+
+
+
+
+
288 L ret = xt::empty_like(labels);
+
289 for (
size_t i = 0; i < labels.size(); ++i) {
+
290 ret.flat(i) = map[labels.flat(i)];
+
+
+
+
+
+
+
+
+
+
+
306 using value_type =
typename T::value_type;
+
307 auto unq = xt::unique(labels);
+
308 bool background = xt::any(xt::equal(unq, 0));
+
+
310 std::array<size_t, 2> shape = {unq.size(), 2};
+
+
+
+
+
+
+
317 for (
size_t i = 1; i < unq.size(); ++i) {
+
318 rename(i, 0) = unq(i);
+
+
+
+
+
+
324 for (
size_t i = 0; i < unq.size(); ++i) {
+
+
+
+
328 rename(row, 0) = unq(i);
+
329 rename(row, 1) = row;
+
+
+
+
+
+
335 for (
size_t i = 0; i < unq.size(); ++i) {
+
336 rename(i, 0) = unq(i);
+
337 rename(i, 1) = i + 1;
+
+
+
+
+
+
+
349template <
class L,
class A>
+
+
+
+
352#ifdef GOOSEEYE_ENABLE_ASSERT
+
353 auto a = xt::unique(labels);
+
354 auto b = xt::unique(order);
+
+
+
+
+
359 auto maxlab = *std::max_element(order.begin(), order.end());
+
360 std::vector<typename A::value_type> renum(maxlab + 1);
+
+
362 for (
size_t i = 0; i < order.size(); ++i) {
+
+
+
+
366 L ret = xt::empty_like(labels);
+
367 for (
size_t i = 0; i < labels.size(); ++i) {
+
368 ret.flat(i) = renum[labels.flat(i)];
+
+
+
+
+
+
+
+
+
+
377inline auto labels_sizes_impl(
const T& labels)
+
+
379 using value_type =
typename T::value_type;
+
380 std::map<value_type, value_type> map;
+
+
382 for (
size_t i = 0; i < labels.size(); ++i) {
+
383 if (map.count(labels.flat(i)) == 0) {
+
384 map.emplace(labels.flat(i), 1);
+
+
+
387 map[labels.flat(i)]++;
+
+
+
+
+
+
+
+
+
+
+
+
+
404 using value_type =
typename T::value_type;
+
405 auto map = detail::labels_sizes_impl(labels);
+
406 std::array<size_t, 2> shape = {map.size(), 2};
+
+
+
+
410 for (
auto const& [key, val] : map) {
+
+
+
+
+
+
+
+
+
+
425template <
class T,
class N>
+
+
+
+
428 using value_type =
typename T::value_type;
+
429 auto map = detail::labels_sizes_impl(labels);
+
+
431 for (
size_t i = 0; i < names.size(); ++i) {
+
432 ret(i) = map[names(i)];
+
+
+
+
+
+
+
+
444template <
size_t Dim,
class T>
+
+
+
447#ifdef GOOSEEYE_ENABLE_ASSERT
+
448 for (
size_t i = 0; i < Dim; ++i) {
+
+
+
+
+
453 std::array<size_t, Dim> mid;
+
454 for (
size_t i = 0; i < Dim; ++i) {
+
455 mid[i] = (kernel.shape(i) - 1) / 2;
+
+
+
458 for (
size_t i = 0; i < Dim; ++i) {
+
459 idx += mid[i] * kernel.strides()[i];
+
+
+
462 kernel.flat(idx) = 0;
+
+
464 if constexpr (Dim == 1) {
+
465 auto i = xt::flatten_indices(xt::argwhere(kernel)) - mid[0];
+
+
467 std::copy(i.begin(), i.end(), ret.begin());
+
+
+
+
471 auto ret = xt::from_indices(xt::argwhere(kernel));
+
472 for (
size_t i = 0; i < Dim; ++i) {
+
473 xt::view(ret, xt::all(), i) -= mid[i];
+
+
+
+
+
+
+
485template <
size_t Dimension,
bool Periodicity = true>
+
+
+
+
488 static constexpr size_t Dim = Dimension;
+
+
+
+
492 std::array<ptrdiff_t, Dim> m_shape;
+
+
+
495 ptrdiff_t m_new_label = 1;
+
+
497 std::array<ptrdiff_t, Dim> m_strides;
+
+
505 std::vector<ptrdiff_t> m_renum;
+
+
517 std::vector<ptrdiff_t> m_next;
+
518 std::vector<ptrdiff_t> m_connected;
+
+
+
+
+
+
+
+
+
+
530 if constexpr (
Dim == 1) {
+
+
+
+
534 else if constexpr (
Dim == 2) {
+
+
536 m_dx = {{-1, 0}, {0, -1}, {0, 1}, {1, 0}};
+
+
538 else if constexpr (
Dim == 3) {
+
539 m_dx = {{-1, 0, 0}, {0, -1, 0}, {0, 0, -1}, {0, 0, 1}, {0, 1, 0}, {1, 0, 0}};
+
+
+
542 throw std::runtime_error(
"Please specify the kernel in dimensions > 3.");
+
+
+
+
+
+
551 template <
class T,
class K>
+
+
+
+
554 m_dx = detail::kernel_to_dx<Dim>(kernel);
+
+
+
+
+
+
+
560 void init(
const T&
shape)
+
+
562 m_label = xt::empty<ptrdiff_t>(
shape);
+
563 m_renum.resize(m_label.size() + 1);
+
564 m_next.resize(m_label.size() + 1);
+
565 for (
size_t i = 0; i <
Dim; ++i) {
+
566 m_shape[i] =
static_cast<ptrdiff_t
>(
shape[i]);
+
567 if constexpr (
Dim >= 2) {
+
568 m_strides[i] =
static_cast<ptrdiff_t
>(m_label.strides()[i]);
+
+
+
+
572 m_connected.resize(m_dx.shape(0));
+
+
+
+
576 if constexpr (
Dim == 2) {
+
577 if (m_shape[0] == 1) {
+
578 get_compare = &ClusterLabeller<Dimension, Periodicity>::get_compare_2d_1n;
+
+
580 else if (m_shape[1] == 1) {
+
581 get_compare = &ClusterLabeller<Dimension, Periodicity>::get_compare_2d_n1;
+
+
+
+
+
+
+
+
+
592 std::fill(m_label.begin(), m_label.end(), 0);
+
593 std::iota(m_renum.begin(), m_renum.end(), 0);
+
+
+
+
+
+
+
+
+
604 ptrdiff_t n =
static_cast<ptrdiff_t
>(m_new_label);
+
+
+
607 for (ptrdiff_t i = 1; i < n; ++i) {
+
608 if (m_renum[i] == i) {
+
609 m_renum[i] = m_new_label;
+
+
+
+
613 this->private_renumber(m_renum);
+
614 std::iota(m_renum.begin(), m_renum.begin() + n, 0);
+
+
+
+
+
+
+
623 std::fill(m_next.begin(), m_next.end(), -1);
+
+
+
+
631 void private_renumber(
const T& renum)
+
+
633 for (
size_t i = 0; i < m_label.size(); ++i) {
+
634 m_label.flat(i) = renum[m_label.flat(i)];
+
+
+
+
646 void merge_detail(ptrdiff_t a, ptrdiff_t b)
+
+
+
649 ptrdiff_t i = m_renum[b];
+
650 ptrdiff_t target = m_renum[a];
+
+
+
+
+
+
+
+
+
+
660 while (m_next[a] != -1) {
+
+
+
+
+
+
672 size_t unique(ptrdiff_t*
labels,
size_t nlabels)
+
+
+
+
+
+
685 ptrdiff_t merge(ptrdiff_t*
labels,
size_t nlabels)
+
+
687 ptrdiff_t target =
labels[0];
+
688 for (
size_t i = 1; i < nlabels; ++i) {
+
689 this->merge_detail(target,
labels[i]);
+
+
+
+
+
+
+
+
+
+
+
700 this->private_renumber(m_renum);
+
+
+
+
+
709 ptrdiff_t get_compare_2d_1n(
size_t idx,
size_t j)
+
+
+
712 return (m_shape[1] + idx + m_dx(j, 1)) % m_shape[1];
+
+
+
715 ptrdiff_t compare = idx + m_dx(j, 1);
+
716 if (compare < 0 || compare >= m_shape[1]) {
+
+
+
+
+
+
+
727 ptrdiff_t get_compare_2d_n1(
size_t idx,
size_t j)
+
+
+
730 return (m_shape[0] + idx + m_dx(j, 0)) % m_shape[0];
+
+
+
733 ptrdiff_t compare = idx + m_dx(j, 0);
+
734 if (compare < 0 || compare >= m_shape[0]) {
+
+
+
+
+
+
+
749 ptrdiff_t get_compare_default(
size_t idx,
size_t j)
+
+
+
752 return (m_shape[0] + idx + m_dx.flat(j)) % m_shape[0];
+
+
+
755 ptrdiff_t compare = idx + m_dx.flat(j);
+
756 if (compare < 0 || compare >= m_shape[0]) {
+
+
+
759 return idx + m_dx.flat(j);
+
+
+
762 ptrdiff_t ii = (m_shape[0] + (idx / m_strides[0]) + m_dx(j, 0)) % m_shape[0];
+
763 ptrdiff_t jj = (m_shape[1] + (idx % m_strides[0]) + m_dx(j, 1)) % m_shape[1];
+
764 return ii * m_shape[1] + jj;
+
+
+
767 ptrdiff_t ii = (idx / m_strides[0]) + m_dx(j, 0);
+
768 ptrdiff_t jj = (idx % m_strides[0]) + m_dx(j, 1);
+
769 if (ii < 0 || ii >= m_shape[0] || jj < 0 || jj >= m_shape[1]) {
+
+
+
772 return ii * m_shape[1] + jj;
+
+
+
775 auto index = xt::unravel_from_strides(idx, m_strides, xt::layout_type::row_major);
+
776 for (
size_t d = 0; d <
Dim; ++d) {
+
777 index[d] += m_dx(j, d);
+
+
779 if (index[d] < 0 || index[d] >= m_shape[d]) {
+
+
+
+
+
+
785 index[d] = (n + (index[d] % n)) % n;
+
+
+
788 return xt::ravel_index(index, m_shape, xt::layout_type::row_major);
+
+
+
+
792 void label_impl(
size_t idx)
+
+
794 size_t nconnected = 0;
+
+
796 for (
size_t j = 0; j < m_dx.shape(0); ++j) {
+
797 ptrdiff_t compare = (this->*get_compare)(idx, j);
+
+
+
+
+
+
803 if (m_label.flat(compare) != 0) {
+
804 m_connected[nconnected] = m_renum[m_label.flat(compare)];
+
+
+
+
+
809 if (nconnected == 0) {
+
810 m_label.flat(idx) = m_new_label;
+
+
+
+
+
815 if (nconnected == 1) {
+
816 m_label.flat(idx) = m_connected[0];
+
+
+
+
820 nconnected = this->unique(&m_connected[0], nconnected);
+
821 if (nconnected == 1) {
+
822 m_label.flat(idx) = m_connected[0];
+
+
+
+
+
+
+
829 m_label.flat(idx) = this->merge(&m_connected[0], nconnected);
+
+
+
+
+
+
+
+
+
841 GOOSEEYE_ASSERT(xt::has_shape(img, m_label.shape()), std::out_of_range);
+
+
843 for (
size_t idx = 0; idx < img.size(); ++idx) {
+
844 if (img.flat(idx) == 0) {
+
+
+
847 if (m_label.flat(idx) != 0) {
+
+
+
850 this->label_impl(idx);
+
+
+
+
+
+
+
+
857 bool legal_points(
const T& begin,
const T& end)
+
+
859 size_t n = m_label.size();
+
860 if constexpr (std::is_signed_v<typename T::value_type>) {
+
861 return !std::any_of(begin, end, [n](
size_t i) {
return i < 0 || i >= n; });
+
+
+
864 return !std::any_of(begin, end, [n](
size_t i) {
return i >= n; });
+
+
+
+
+
+
+
+
+
+
878 for (
auto it = begin; it != end; ++it) {
+
879 if (m_label.flat(*it) != 0) {
+
+
+
882 this->label_impl(*it);
+
+
+
+
+
+
+
+
+
+
+
895 return this->
add_points(idx.begin(), idx.end());
+
+
+
+
+
+
+
+
+
+
911 GOOSEEYE_ASSERT(this->legal_points(idx.begin(), idx.end()), std::out_of_range);
+
912 std::vector<size_t> ret;
+
+
+
915 auto nl = m_new_label;
+
+
917 auto lab = m_label.flat(idx(i));
+
+
919 for (; i < idx.size(); ++i) {
+
920 auto l = m_label.flat(idx(i));
+
921 if (l != lab && l != 0) {
+
+
+
+
+
+
+
928 this->label_impl(idx(i));
+
929 if (m_new_label != nl || m_nmerge != nm) {
+
+
+
+
+
+
935 if (i == idx.size()) {
+
+
+
+
+
+
941 ret.push_back(idx.size());
+
+
+
+
+
+
+
+
951 return detail::get_namespace() +
"ClusterLabeller" + std::to_string(
Dim) +
" " +
+
952 detail::shape_to_string(m_shape);
+
+
+
+
+
+
+
961 return m_label.shape();
+
+
+
+
+
+
+
970 return m_label.size();
+
+
+
+
+
+
+
+
+
+
+
+
987template <
size_t Dimension,
bool Periodicity>
+
988class ClusterLabellerOverload :
public ClusterLabeller<Dimension, Periodicity> {
+
+
+
991 ClusterLabellerOverload(
const T& img) : ClusterLabeller<Dimension, Periodicity>(img.
shape())
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
1014 GOOSEEYE_ASSERT(f.layout() == xt::layout_type::row_major, std::runtime_error);
+
+
1016 auto n = f.dimension();
+
1017 if (n == 1 && periodic) {
+
1018 return detail::ClusterLabellerOverload<1, true>(f).get();
+
+
1020 if (n == 1 && !periodic) {
+
1021 return detail::ClusterLabellerOverload<1, false>(f).get();
+
+
1023 if (n == 2 && periodic) {
+
1024 return detail::ClusterLabellerOverload<2, true>(f).get();
+
+
1026 if (n == 2 && !periodic) {
+
1027 return detail::ClusterLabellerOverload<2, false>(f).get();
+
+
1029 if (n == 3 && periodic) {
+
1030 return detail::ClusterLabellerOverload<3, true>(f).get();
+
+
1032 if (n == 3 && !periodic) {
+
1033 return detail::ClusterLabellerOverload<3, false>(f).get();
+
+
1035 throw std::runtime_error(
"Please use ClusterLabeller directly for dimensions > 3.");
+
+
+
+
+
+
+
+
1063 bool periodic =
true)
+
+
1065 if (positions.size() == 0) {
+
1066 return xt::zeros<double>({shape.size()});
+
+
+
+
1070 return xt::mean(positions, 0);
+
+
+
1073 double pi = xt::numeric_constants<double>::PI;
+
1074 auto theta = 2.0 * pi * positions / shape;
+
1075 auto xi = xt::cos(theta);
+
1076 auto zeta = xt::sin(theta);
+
1077 auto xi_bar = xt::mean(xi, 0);
+
1078 auto zeta_bar = xt::mean(zeta, 0);
+
1079 auto theta_bar = xt::atan2(-zeta_bar, -xi_bar) + pi;
+
1080 return shape * theta_bar / (2.0 * pi);
+
+
+
+
+
+
+
+
+
+
1092 bool periodic =
true)
+
+
1094 if (positions.size() == 0) {
+
1095 return xt::zeros<double>({shape.size()});
+
+
+
+
1099 return xt::average(positions, weights, 0);
+
+
+
1102 double pi = xt::numeric_constants<double>::PI;
+
1103 auto theta = 2.0 * pi * positions / shape;
+
1104 auto xi = xt::cos(theta);
+
1105 auto zeta = xt::sin(theta);
+
1106 auto xi_bar = xt::average(xi, weights, 0);
+
1107 auto zeta_bar = xt::average(zeta, weights, 0);
+
1108 auto theta_bar = xt::atan2(-zeta_bar, -xi_bar) + pi;
+
1109 return shape * theta_bar / (2.0 * pi);
+
+
+
+
+
+
+
+
+
+
+
+
1120 PositionList() =
default;
+
+
+
1123 void set(
const T& condition)
+
+
1125 positions = xt::from_indices(xt::argwhere(condition));
+
+
+
1128 template <
class T,
class W>
+
1129 void set(
const T& condition,
const W& w)
+
+
1131 auto pos = xt::argwhere(condition);
+
1132 weights = xt::empty<double>({pos.size()});
+
1133 for (
size_t i = 0; i < pos.size(); ++i) {
+
1134 weights(i) = w[pos[i]];
+
+
1136 positions = xt::from_indices(pos);
+
+
+
+
+
+
1152template <
class T,
class N>
+
+
+
+
+
1156 static_assert(std::is_integral<typename T::value_type>::value,
"Integral labels required.");
+
+
+
+
1160 size_t rank = labels.dimension();
+
+
+
1163 detail::PositionList plist;
+
+
1165 for (
size_t l = 0; l < names.size(); ++l) {
+
1166 plist.set(xt::equal(labels, names(l)));
+
1167 if (plist.positions.size() == 0) {
+
+
+
1170 xt::view(ret, l, xt::all()) =
center(shape, plist.positions, periodic);
+
+
+
+
+
+
+
1180template <
class T,
class W,
class N>
+
+
+
+
+
1184 static_assert(std::is_integral<typename T::value_type>::value,
"Integral labels required.");
+
1185 GOOSEEYE_ASSERT(xt::has_shape(labels, weights.shape()), std::out_of_range);
+
+
+
+
1189 size_t rank = labels.dimension();
+
+
+
1192 detail::PositionList plist;
+
+
1194 for (
size_t l = 0; l < names.size(); ++l) {
+
1195 plist.set(xt::equal(labels, names(l)), weights);
+
1196 if (plist.positions.size() == 0) {
+
+
+
1199 xt::view(ret, l, xt::all()) =
+
+
+
+
+
+
+
+
+
+
+
+
+
1229 Ensemble(
const std::vector<size_t>& roi,
bool periodic =
true,
bool variance =
true);
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
1298 void mean(
const T& f);
+
+
1305 template <
class T,
class M>
+
1306 void mean(
const T& f,
const M& fmask);
+
+
+
1314 void S2(
const T& f,
const T& g);
+
+
1323 template <
class T,
class M>
+
1324 void S2(
const T& f,
const T& g,
const M& fmask,
const M& gmask);
+
+
+
1332 void C2(
const T& f,
const T& g);
+
+
1341 template <
class T,
class M>
+
1342 void C2(
const T& f,
const T& g,
const M& fmask,
const M& gmask);
+
+
+
1350 void W2(
const T& w,
const T& f);
+
+
1358 template <
class T,
class M>
+
1359 void W2(
const T& w,
const T& f,
const M& fmask);
+
+
1368 template <
class C,
class T>
+
+
+
+
1380 template <
class C,
class T,
class M>
+
+
+
+
+
+
+
+
+
+
+
1402 template <
class T,
class M>
+
+
+
+
+
+
+
+
+
+
+
1418 Type m_stat = Type::Unset;
+
+
+
1421 static const size_t MAX_DIM = 3;
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
1438 std::vector<size_t> m_shape_orig;
+
+
+
1441 std::vector<size_t> m_shape;
+
+
+
1444 std::vector<std::vector<size_t>> m_pad;
+
+
+
+
+
+
+
+
1456inline auto distance(
const std::vector<size_t>& roi);
+
+
1464inline auto distance(
const std::vector<size_t>& roi,
size_t axis);
+
+
1472inline auto distance(
const std::vector<size_t>& roi,
const std::vector<double>& h);
+
+
1481inline auto distance(
const std::vector<size_t>& roi,
const std::vector<double>& h,
size_t axis);
+
+
+
1491inline auto S2(
const std::vector<size_t>& roi,
const T& f,
const T& g,
bool periodic =
true);
+
+
1502template <
class T,
class M>
+
+
1504S2(
const std::vector<size_t>& roi,
+
+
+
+
+
1509 bool periodic =
true);
+
+
+
1519inline auto C2(
const std::vector<size_t>& roi,
const T& f,
const T& g,
bool periodic =
true);
+
+
1530template <
class T,
class M>
+
+
1532C2(
const std::vector<size_t>& roi,
+
+
+
+
+
1537 bool periodic =
true);
+
+
+
1547inline auto W2(
const std::vector<size_t>& roi,
const T& w,
const T& f,
bool periodic =
true);
+
+
1557template <
class T,
class M>
+
+
1559W2(
const std::vector<size_t>& roi,
const T& w,
const T& f,
const M& fmask,
bool periodic =
true);
+
+
1570template <
class C,
class T>
+
+
1572W2c(
const std::vector<size_t>& roi,
+
+
+
+
+
1577 bool periodic =
true);
+
+
1589template <
class C,
class T,
class M>
+
+
1591W2c(
const std::vector<size_t>& roi,
+
+
+
+
+
+
1597 bool periodic =
true);
+
+
+
1606inline auto heightheight(
const std::vector<size_t>& roi,
const T& f,
bool periodic =
true);
+
+
1615template <
class T,
class M>
+
+
1617heightheight(
const std::vector<size_t>& roi,
const T& f,
const M& fmask,
bool periodic =
true);
+
+
+
+
1628L(
const std::vector<size_t>& roi,
+
+
1630 bool periodic =
true,
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
(Incrementally) Label clusters (0 as background, 1..n as labels).
+
void prune()
Prune: renumber labels to lowest possible label, see also AvalancheSegmenter::nlabels.
+
void add_image(const T &img)
Add image.
+
auto size() const
Size of ClusterLabeller::s and ClusterLabeller::labels (== prod(shape)).
+
ClusterLabeller(const T &shape)
+
ClusterLabeller(const T &shape, const K &kernel)
+
std::string repr() const
Basic class info.
+
const auto & shape() const
Shape of ClusterLabeller::s and ClusterLabeller::labels.
+
static constexpr bool Periodic
Periodicity of the system.
+
void add_points(const T &begin, const T &end)
Add sequence of points.
+
const auto & labels() const
Per block, the label (0 for background).
+
std::vector< size_t > add_sequence(const T &idx)
Add a sequence of points.
+
void add_points(const T &idx)
Add sequence of points.
+
void reset()
Reset labels to zero.
+
static constexpr size_t Dim
Dimensionality of the system.
+
Compute ensemble averaged statistics, by repetitively calling the member-function of a certain statis...
+
void mean(const T &f)
Add realization to arithmetic mean.
+
void L(const T &f, path_mode mode=path_mode::Bresenham)
Add realization to lineal-path function.
+
void S2(const T &f, const T &g)
Add realization to 2-point correlation: P(f(i) * g(i + di)).
+
array_type::array< double > data_second() const
Get raw-data: ensemble sum of the second moment: x_1^2 + x_2^2 + ...
+
Ensemble()=default
Constructor.
+
array_type::array< double > variance() const
Get ensemble variance.
+
void heightheight(const T &f)
Add realization to height-height correlation.
+
void W2c(const C &clusters, const C ¢ers, const T &f, path_mode mode=path_mode::Bresenham)
Add realization to collapsed weighted 2-point correlation.
+
array_type::array< double > data_first() const
Get raw-data: ensemble sum of the first moment: x_1 + x_2 + ...
+
void W2(const T &w, const T &f)
Add realization to weighted 2-point correlation.
+
array_type::array< double > distance() const
Get the relative distance of each pixel in the 'region-of-interest' to its center.
+
array_type::array< double > result() const
Get ensemble average.
+
array_type::array< double > norm() const
Get raw-data: normalisation (number of measurements per pixel).
+
void C2(const T &f, const T &g)
Add realization to 2-point cluster function: P(f(i) == g(i + di)).
+
+
#define GOOSEEYE_ASSERT(expr, assertion)
All assertions are implemented as:
+
+
+
+
xt::xtensor< T, N > tensor
Fixed (static) rank array.
+
array_type::array< int > nearest(size_t ndim)
Return kernel with nearest neighbours.
+
Toolbox to compute statistics.
+
path_mode
Different methods to compute a pixel-path.
+
@ Bresenham
Bresenham algorithm.
+
+
@ full
Similar to actual selecting every voxel that is crossed.
+
array_type::tensor< double, 2 > labels_centers_of_mass(const T &labels, const W &weights, const N &names, bool periodic=true)
Get the position of the center of each label.
+
array_type::tensor< double, 1 > center_of_mass(const array_type::tensor< double, 1 > &shape, const array_type::tensor< double, 2 > &positions, const array_type::tensor< double, 1 > &weights, bool periodic=true)
Return the geometric center of a list of positions.
+
array_type::tensor< double, 1 > center(const array_type::tensor< double, 1 > &shape, const array_type::tensor< double, 2 > &positions, bool periodic=true)
Return the geometric center of a list of positions.
+
auto L(const std::vector< size_t > &roi, const T &f, bool periodic=true, path_mode mode=path_mode::Bresenham)
Lineal-path function.
+
T dilate(const T &f, const S &kernel, const array_type::tensor< size_t, 1 > &iterations, bool periodic)
Dilate image.
+
T labels_prune(const T &labels)
Prune labels: renumber labels to lowest possible label starting from 1.
+
auto W2c(const std::vector< size_t > &roi, const C &clusters, const C ¢ers, const T &f, path_mode mode=path_mode::Bresenham, bool periodic=true)
Collapsed weighted 2-point correlation.
+
array_type::tensor< typename T::value_type, 2 > labels_sizes(const T &labels)
Size per label.
+
array_type::tensor< typename T::value_type, 2 > labels_map(const T &a, const T &b)
Get a map to relabel from a to b.
+
auto C2(const std::vector< size_t > &roi, const T &f, const T &g, bool periodic=true)
2-point cluster function: P(f(i) == g(i + di)).
+
array_type::array< int > clusters(const T &f, bool periodic=true)
Compute clusters.
+
array_type::tensor< double, 2 > labels_centers(const T &labels, const N &names, bool periodic=true)
Get the position of the center of each label.
+
L labels_rename(const L &labels, const A &rename)
Rename labels.
+
auto W2(const std::vector< size_t > &roi, const T &w, const T &f, bool periodic=true)
Weighted 2-point correlation.
+
array_type::array< int > dummy_circles(const std::vector< size_t > &shape, const array_type::tensor< int, 1 > &row, const array_type::tensor< int, 1 > &col, const array_type::tensor< int, 1 > &r, bool periodic=true)
Dummy image with circles.
+
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.
+
auto distance(const std::vector< size_t > &roi)
Get the relative distance of each pixel in the 'region-of-interest' to its center.
+
auto S2(const std::vector< size_t > &roi, const T &f, const T &g, bool periodic=true)
2-point correlation: P(f(i) * g(i + di)).
+
auto heightheight(const std::vector< size_t > &roi, const T &f, bool periodic=true)
Height-height correlation.
+
L labels_reorder(const L &labels, const A &order)
Reorder labels.
+
+