+
+
+
+
+
+
+
+
+
+
+
+
+
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);
+
+
241template <
class T,
class S>
+
+
+
+
+
+
+
+
+
249 for (
size_t i = 0; i < a.size(); ++i) {
+
250 ret(a.flat(i)) = b.flat(i);
+
+
+
+
+
+
+
+
+
+
+
265 using value_type =
typename T::value_type;
+
266 std::map<value_type, value_type> map;
+
+
268 for (
size_t i = 0; i < a.size(); ++i) {
+
269 map.try_emplace(a.flat(i), b.flat(i));
+
+
+
+
+
274 xt::empty<typename T::value_type>(std::array<size_t, 2>{map.size(), 2});
+
+
276 for (
auto const& [key, val] : map) {
+
+
+
+
+
+
+
+
+
+
291template <
class L,
class A>
+
+
+
+
+
+
296 using value_type =
typename A::value_type;
+
297 std::map<value_type, value_type> map;
+
298 for (
size_t i = 0; i < rename.shape(0); ++i) {
+
299 map.emplace(rename(i, 0), rename(i, 1));
+
+
+
302#ifdef GOOSEEYE_ENABLE_ASSERT
+
303 auto l = xt::unique(labels);
+
304 for (
size_t i = 0; i < l.size(); ++i) {
+
+
+
+
+
309 L ret = xt::empty_like(labels);
+
310 for (
size_t i = 0; i < labels.size(); ++i) {
+
311 ret.flat(i) = map[labels.flat(i)];
+
+
+
+
+
+
+
323template <
class L,
class A>
+
+
+
+
326#ifdef GOOSEEYE_ENABLE_ASSERT
+
327 auto a = xt::unique(labels);
+
328 auto b = xt::unique(order);
+
+
+
+
+
333 auto maxlab = *std::max_element(order.begin(), order.end());
+
334 std::vector<typename A::value_type> renum(maxlab + 1);
+
+
336 for (
size_t i = 0; i < order.size(); ++i) {
+
+
+
+
340 L ret = xt::empty_like(labels);
+
341 for (
size_t i = 0; i < labels.size(); ++i) {
+
342 ret.flat(i) = renum[labels.flat(i)];
+
+
+
+
+
+
+
+
+
+
+
356 using value_type =
typename T::value_type;
+
357 std::map<value_type, value_type> map;
+
+
359 for (
size_t i = 0; i < labels.size(); ++i) {
+
360 if (map.count(labels.flat(i)) == 0) {
+
361 map.emplace(labels.flat(i), 1);
+
+
+
364 map[labels.flat(i)]++;
+
+
+
+
+
+
370 xt::empty<value_type>(std::array<size_t, 2>{map.size(), 2});
+
+
372 for (
auto const& [key, val] : map) {
+
+
+
+
+
+
+
+
+
+
+
+
388template <
size_t Dim,
class T>
+
+
+
391#ifdef GOOSEEYE_ENABLE_ASSERT
+
392 for (
size_t i = 0; i < Dim; ++i) {
+
+
+
+
+
397 std::array<size_t, Dim> mid;
+
398 for (
size_t i = 0; i < Dim; ++i) {
+
399 mid[i] = (kernel.shape(i) - 1) / 2;
+
+
+
402 for (
size_t i = 0; i < Dim; ++i) {
+
403 idx += mid[i] * kernel.strides()[i];
+
+
+
406 kernel.flat(idx) = 0;
+
+
408 if constexpr (Dim == 1) {
+
409 return xt::flatten_indices(xt::argwhere(kernel)) - mid[0];
+
+
+
412 auto ret = xt::from_indices(xt::argwhere(kernel));
+
413 for (
size_t i = 0; i < Dim; ++i) {
+
414 xt::view(ret, xt::all(), i) -= mid[i];
+
+
+
+
+
+
+
426template <
size_t Dimension,
bool Periodicity = true>
+
+
+
+
429 static constexpr size_t Dim = Dimension;
+
+
+
+
433 std::array<ptrdiff_t, Dim> m_shape;
+
+
+
436 ptrdiff_t m_new_label = 1;
+
+
438 std::array<ptrdiff_t, Dim> m_strides;
+
+
446 std::vector<ptrdiff_t> m_renum;
+
+
458 std::vector<ptrdiff_t> m_next;
+
459 std::vector<ptrdiff_t> m_connected;
+
+
+
+
+
+
+
468 if constexpr (
Dim == 1) {
+
+
+
+
472 else if constexpr (
Dim == 2) {
+
+
474 m_dx = {{-1, 0}, {0, -1}, {0, 1}, {1, 0}};
+
+
+
+
+
+
483 template <
class T,
class K>
+
+
+
+
486 m_dx = detail::kernel_to_dx<Dim>(kernel);
+
+
+
+
+
+
+
492 void init(
const T&
shape)
+
+
494 static_assert(
Dim == 1 ||
Dim == 2,
"WIP: 1d and 2d supported.");
+
495 m_label = xt::empty<ptrdiff_t>(
shape);
+
496 m_renum.resize(m_label.size() + 1);
+
497 m_next.resize(m_label.size() + 1);
+
498 for (
size_t i = 0; i <
Dim; ++i) {
+
499 m_shape[i] =
static_cast<ptrdiff_t
>(
shape[i]);
+
500 m_strides[i] =
static_cast<ptrdiff_t
>(m_label.strides()[i]);
+
+
+
+
504 m_connected.resize(m_dx.shape(0));
+
+
+
+
+
+
+
513 std::fill(m_label.begin(), m_label.end(), 0);
+
514 std::iota(m_renum.begin(), m_renum.end(), 0);
+
+
+
+
+
+
+
+
+
525 ptrdiff_t n =
static_cast<ptrdiff_t
>(m_new_label);
+
+
+
528 for (ptrdiff_t i = 1; i < n; ++i) {
+
529 if (m_renum[i] == i) {
+
530 m_renum[i] = m_new_label;
+
+
+
+
534 this->private_renumber(m_renum);
+
535 std::iota(m_renum.begin(), m_renum.begin() + n, 0);
+
+
+
+
+
+
+
544 std::fill(m_next.begin(), m_next.end(), -1);
+
+
+
+
552 void private_renumber(
const T& renum)
+
+
554 for (
size_t i = 0; i < m_label.size(); ++i) {
+
555 m_label.flat(i) = renum[m_label.flat(i)];
+
+
+
+
567 void merge_detail(ptrdiff_t a, ptrdiff_t b)
+
+
+
570 ptrdiff_t i = m_renum[b];
+
571 ptrdiff_t target = m_renum[a];
+
+
+
+
+
+
+
+
+
+
581 while (m_next[a] != -1) {
+
+
+
+
+
+
594 ptrdiff_t merge(ptrdiff_t*
labels,
size_t nlabels)
+
+
+
+
598 ptrdiff_t target =
labels[0];
+
599 for (
size_t i = 1; i < nlabels; ++i) {
+
600 this->merge_detail(target,
labels[i]);
+
+
+
+
+
+
+
+
+
+
+
611 this->private_renumber(m_renum);
+
+
+
+
+
616 void label_impl(
size_t idx)
+
+
618 static_assert(
Dim == 1 ||
Dim == 2,
"WIP: 1d and 2d supported.");
+
+
+
621 size_t nconnected = 0;
+
+
623 for (
size_t j = 0; j < m_dx.shape(0); ++j) {
+
+
625 compare = (m_shape[0] + idx + m_dx(j)) % m_shape[0];
+
+
+
628 if (compare < 0 || compare >= m_shape[0]) {
+
+
+
631 compare = idx + m_dx(j);
+
+
+
634 ptrdiff_t ii = (m_shape[0] + (idx / m_strides[0]) + m_dx(j, 0)) % m_shape[0];
+
635 ptrdiff_t jj = (m_shape[1] + (idx % m_strides[0]) + m_dx(j, 1)) % m_shape[1];
+
636 compare = ii * m_shape[1] + jj;
+
+
+
639 ptrdiff_t ii = (idx / m_strides[0]) + m_dx(j, 0);
+
640 ptrdiff_t jj = (idx % m_strides[0]) + m_dx(j, 1);
+
641 if (ii < 0 || ii >= m_shape[0] || jj < 0 || jj >= m_shape[1]) {
+
+
+
644 compare = ii * m_shape[1] + jj;
+
+
+
647 if (m_label.flat(compare) != 0) {
+
648 m_connected[nconnected] = m_renum[m_label.flat(compare)];
+
+
+
+
+
653 if (nconnected == 0) {
+
654 m_label.flat(idx) = m_new_label;
+
+
+
+
+
659 if (nconnected == 1) {
+
660 m_label.flat(idx) = m_connected[0];
+
+
+
+
+
+
+
667 m_label.flat(idx) = this->merge(&m_connected[0], nconnected);
+
+
+
+
+
+
+
+
+
679 GOOSEEYE_ASSERT(xt::has_shape(img, m_label.shape()), std::out_of_range);
+
+
681 for (
size_t idx = 0; idx < img.size(); ++idx) {
+
682 if (img.flat(idx) == 0) {
+
+
+
685 if (m_label.flat(idx) != 0) {
+
+
+
688 this->label_impl(idx);
+
+
+
+
+
+
+
+
+
+
701#ifdef GOOSEEYE_ENABLE_ASSERT
+
702 size_t n = m_label.size();
+
+
704 !std::any_of(begin, end, [n](
size_t i) {
return i < 0 || i >= n; }), std::out_of_range);
+
+
+
707 for (
auto it = begin; it != end; ++it) {
+
708 if (m_label.flat(*it) != 0) {
+
+
+
711 this->label_impl(*it);
+
+
+
+
+
+
+
+
+
+
+
724 return this->
add_points(idx.begin(), idx.end());
+
+
+
+
+
+
+
733 return detail::get_namespace() +
"ClusterLabeller" + std::to_string(
Dim) +
" " +
+
734 detail::shape_to_string(m_shape);
+
+
+
+
+
+
+
743 return m_label.shape();
+
+
+
+
+
+
+
752 return m_label.size();
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
782 :
Clusters(f, kernel::nearest(f.dimension()), periodic)
+
+
+
+
+
793 template <
class T,
class S>
+
+
794 Clusters(
const T& f,
const S& kernel,
bool periodic =
true) : m_periodic(periodic)
+
+
+
797 "(please open a PR for missing functions)");
+
+
799 static_assert(std::is_integral<typename T::value_type>::value,
"Integral labels required.");
+
800 static_assert(std::is_integral<typename S::value_type>::value,
"Integral kernel required.");
+
+
802 GOOSEEYE_ASSERT(xt::all(xt::equal(f, 0) || xt::equal(f, 1)), std::out_of_range);
+
803 GOOSEEYE_ASSERT(xt::all(xt::equal(kernel, 0) || xt::equal(kernel, 1)), std::out_of_range);
+
804 GOOSEEYE_ASSERT(f.dimension() == kernel.dimension(), std::out_of_range);
+
+
806 m_shape = detail::shape(f);
+
807 m_kernel = xt::atleast_3d(kernel);
+
808 m_pad = detail::pad_width(m_kernel);
+
809 m_l = xt::atleast_3d(f);
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
824 xt::view(renum, xt::keep(labels)) = xt::arange<int>(
static_cast<int>(labels.size()));
+
825 for (
auto& i : m_l) {
+
+
+
+
+
+
+
+
+
836 return xt::adapt(m_l.data(), m_shape);
+
+
+
+
+
+
+
+
+
+
848 for (
int l = 1; l < static_cast<int>(x.shape(0)); ++l) {
+
849 c(x(l, 0), x(l, 1), x(l, 2)) = l;
+
+
+
+
+
+
+
+
+
+
+
+
+
+
865 x = this->average_position_periodic();
+
+
+
868 x = this->average_position(m_l);
+
+
+
+
+
+
+
+
876 return xt::view(x, xt::all(), xt::keep(axes));
+
+
+
+
+
+
+
+
+
+
888 for (
size_t h = 0; h < m_l.shape(0); ++h) {
+
889 for (
size_t i = 0; i < m_l.shape(1); ++i) {
+
890 for (
size_t j = 0; j < m_l.shape(2); ++j) {
+
+
+
+
+
+
+
+
+
+
+
+
+
902 xt::pad_mode pad_mode = xt::pad_mode::constant;
+
+
+
+
906 pad_mode = xt::pad_mode::periodic;
+
+
+
909 m_l = xt::pad(m_l, m_pad, pad_mode, pad_value);
+
+
+
+
+
+
+
+
+
918 array_type::tensor<int, 1> renum = xt::arange<int>(
static_cast<int>(m_l.size()));
+
+
920 for (
size_t h = m_pad[0][0]; h < m_l.shape(0) - m_pad[0][1]; ++h) {
+
921 for (
size_t i = m_pad[1][0]; i < m_l.shape(1) - m_pad[1][1]; ++i) {
+
922 for (
size_t j = m_pad[2][0]; j < m_l.shape(2) - m_pad[2][1]; ++j) {
+
+
+
+
+
+
+
+
930 xt::range(h - m_pad[0][0], h + m_pad[0][1] + 1),
+
931 xt::range(i - m_pad[1][0], i + m_pad[1][1] + 1),
+
932 xt::range(j - m_pad[2][0], j + m_pad[2][1] + 1));
+
+
934 auto Ni = Li * m_kernel;
+
+
936 int l = xt::amax(Ni)();
+
+
+
+
+
+
+
943 Li = xt::where(xt::equal(Ni, 1), l, Li);
+
+
945 if (xt::all(xt::equal(Li, l) || xt::equal(Li, 0) || xt::equal(Li, 1))) {
+
+
+
+
+
950 array_type::array<int> merge = xt::where(xt::less_equal(Li, 1), l, Li);
+
951 merge = xt::unique(merge);
+
+
953 int linkto = xt::amin(xt::view(renum, xt::keep(merge)))[0];
+
954 for (
auto& a : merge) {
+
955 renum = xt::where(xt::equal(renum, renum(a)), linkto, renum);
+
+
+
+
+
+
+
+
+
964 xt::range(m_pad[0][0], m_l.shape(0) - m_pad[0][1]),
+
965 xt::range(m_pad[1][0], m_l.shape(1) - m_pad[1][1]),
+
966 xt::range(m_pad[2][0], m_l.shape(2) - m_pad[2][1]));
+
+
+
969 for (
auto& i : m_l) {
+
+
+
+
+
+
975 array_type::tensor<double, 2> average_position(
const T& lab)
const
+
+
+
978 size_t N = xt::amax(lab)() + 1;
+
+
+
981 array_type::tensor<double, 2> x = xt::zeros<double>({N, size_t(3)});
+
982 array_type::tensor<double, 1> n = xt::zeros<double>({N});
+
+
984 for (
size_t h = 0; h < lab.shape(0); ++h) {
+
985 for (
size_t i = 0; i < lab.shape(1); ++i) {
+
986 for (
size_t j = 0; j < lab.shape(2); ++j) {
+
+
988 int l = lab(h, i, j);
+
+
+
991 x(l, 0) += (double)h;
+
992 x(l, 1) += (double)i;
+
993 x(l, 2) += (double)j;
+
+
+
+
+
+
+
+
1001 n = xt::where(xt::equal(n, 0), 1, n);
+
+
+
1004 for (
size_t i = 0; i < x.shape(1); ++i) {
+
1005 auto xi = xt::view(x, xt::all(), i);
+
+
+
+
+
+
+
1012 array_type::tensor<double, 2> average_position_periodic()
const
+
+
+
+
+
+
1018 auto x_np = this->average_position(m_l_np);
+
+
+
1021 auto mid = detail::half_shape(m_shape);
+
+
+
1024 array_type::tensor<double, 2> shift = xt::zeros<double>({x_np.shape(0),
size_t(3)});
+
+
+
1027 for (
size_t i = 0; i < shift.shape(0); ++i) {
+
1028 for (
size_t j = 0; j < shift.shape(1); ++j) {
+
1029 if (x_np(i, j) > mid[j]) {
+
1030 shift(i, j) = -(double)m_shape[j];
+
+
+
+
+
+
1036 size_t N = xt::amax(m_l)() + 1;
+
+
+
1039 array_type::tensor<double, 2> x = xt::zeros<double>({N, size_t(3)});
+
1040 array_type::tensor<double, 1> n = xt::zeros<double>({N});
+
+
1042 for (
size_t h = 0; h < m_l.shape(0); ++h) {
+
1043 for (
size_t i = 0; i < m_l.shape(1); ++i) {
+
1044 for (
size_t j = 0; j < m_l.shape(2); ++j) {
+
+
1046 int l = m_l_np(h, i, j);
+
+
+
1049 x(relabel(l), 0) += (double)h + shift(l, 0);
+
1050 x(relabel(l), 1) += (double)i + shift(l, 1);
+
1051 x(relabel(l), 2) += (double)j + shift(l, 2);
+
1052 n(relabel(l)) += 1.0;
+
+
+
+
+
+
+
1059 n = xt::where(xt::equal(n, 0), 1, n);
+
+
+
1062 for (
size_t i = 0; i < x.shape(1); ++i) {
+
1063 auto xi = xt::view(x, xt::all(), i);
+
+
1065 xi = xt::where(xi < 0, xi + m_shape[i], xi);
+
+
+
+
+
+
1071 static const size_t MAX_DIM = 3;
+
1072 std::vector<size_t> m_shape;
+
1073 std::vector<std::vector<size_t>> m_pad;
+
1074 array_type::tensor<int, 3> m_kernel;
+
+
1076 array_type::tensor<int, 3> m_l;
+
1077 array_type::tensor<int, 3> m_l_np;
+
+
+
+
+
+
1082template <
size_t Dimension,
bool Periodicity>
+
1083class ClusterLabellerOverload :
public ClusterLabeller<Dimension, Periodicity> {
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
1109 auto n = f.dimension();
+
1110 if (n == 1 && periodic) {
+
1111 return detail::ClusterLabellerOverload<1, true>(f).get();
+
+
1113 if (n == 1 && !periodic) {
+
1114 return detail::ClusterLabellerOverload<1, false>(f).get();
+
+
1116 if (n == 2 && periodic) {
+
1117 return detail::ClusterLabellerOverload<2, true>(f).get();
+
+
1119 if (n == 2 && !periodic) {
+
1120 return detail::ClusterLabellerOverload<2, false>(f).get();
+
+
+
1123 GOOSEEYE_WARNING(
"WIP: updated 3d implementation needs to be completed. Please file a PR.");
+
+
+
+
+
1134template <
typename T,
typename U,
typename V>
+
+
1135inline T
pos2img(
const T& img,
const U& positions,
const V& labels)
+
+
+
+
1139 GOOSEEYE_ASSERT(img.dimension() == positions.shape(1), std::out_of_range);
+
1140 GOOSEEYE_ASSERT(positions.shape(0) == labels.size(), std::out_of_range);
+
+
+
1143 using value_type =
typename T::value_type;
+
+
+
1146 if (res.dimension() == 1) {
+
1147 xt::view(res, xt::keep(positions)) = labels;
+
+
1149 else if (res.dimension() == 2) {
+
1150 for (
size_t i = 0; i < positions.shape(0); ++i) {
+
1151 res(positions(i, 0), positions(i, 1)) =
static_cast<value_type
>(labels(i));
+
+
+
+
1155 for (
size_t i = 0; i < positions.shape(0); ++i) {
+
1156 res(positions(i, 0), positions(i, 1), positions(i, 2)) =
+
1157 static_cast<value_type
>(labels(i));
+
+
+
+
+
+
+
+
+
+
+
+
1178 static_assert(std::is_integral<typename T::value_type>::value,
"Integral labels required.");
+
+
+
+
+
1183 double pi = xt::numeric_constants<double>::PI;
+
1184 size_t N =
static_cast<size_t>(xt::amax(labels)(0)) + 1ul;
+
1185 size_t rank = labels.dimension();
+
1186 auto axes = detail::atleast_3d_axes(rank);
+
+
+
+
1190 for (
size_t l = 0; l < N; ++l) {
+
+
1192 xt::from_indices(xt::argwhere(xt::equal(labels, l)));
+
1193 if (positions.size() == 0) {
+
+
+
+
1197 xt::view(ret, l, xt::all()) = xt::mean(positions, 0);
+
+
+
1200 if (xt::all(xt::equal(positions, 0.0))) {
+
+
+
1203 auto theta = 2.0 * pi * positions / shape;
+
1204 auto xi = xt::cos(theta);
+
1205 auto zeta = xt::sin(theta);
+
1206 auto xi_bar = xt::mean(xi, 0);
+
1207 auto zeta_bar = xt::mean(zeta, 0);
+
1208 auto theta_bar = xt::atan2(-zeta_bar, -xi_bar) + pi;
+
1209 auto positions_bar = shape * theta_bar / (2.0 * pi);
+
1210 xt::view(ret, l, xt::all()) = positions_bar;
+
+
+
+
1214 return xt::view(ret, xt::all(), xt::keep(axes));
+
+
+
+
+
+
+
+
+
1240 Ensemble(
const std::vector<size_t>& roi,
bool periodic =
true,
bool variance =
true);
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
1309 void mean(
const T& f);
+
+
1316 template <
class T,
class M>
+
1317 void mean(
const T& f,
const M& fmask);
+
+
+
1325 void S2(
const T& f,
const T& g);
+
+
1334 template <
class T,
class M>
+
1335 void S2(
const T& f,
const T& g,
const M& fmask,
const M& gmask);
+
+
+
1343 void C2(
const T& f,
const T& g);
+
+
1352 template <
class T,
class M>
+
1353 void C2(
const T& f,
const T& g,
const M& fmask,
const M& gmask);
+
+
+
1361 void W2(
const T& w,
const T& f);
+
+
1369 template <
class T,
class M>
+
1370 void W2(
const T& w,
const T& f,
const M& fmask);
+
+
1379 template <
class C,
class T>
+
+
+
+
1391 template <
class C,
class T,
class M>
+
+
+
+
+
+
+
+
+
+
+
1413 template <
class T,
class M>
+
+
+
+
+
+
+
+
+
+
+
1429 Type m_stat = Type::Unset;
+
+
+
1432 static const size_t MAX_DIM = 3;
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
1449 std::vector<size_t> m_shape_orig;
+
+
+
1452 std::vector<size_t> m_shape;
+
+
+
1455 std::vector<std::vector<size_t>> m_pad;
+
+
+
+
+
+
+
+
1467inline auto distance(
const std::vector<size_t>& roi);
+
+
1475inline auto distance(
const std::vector<size_t>& roi,
size_t axis);
+
+
1483inline auto distance(
const std::vector<size_t>& roi,
const std::vector<double>& h);
+
+
1492inline auto distance(
const std::vector<size_t>& roi,
const std::vector<double>& h,
size_t axis);
+
+
+
1502inline auto S2(
const std::vector<size_t>& roi,
const T& f,
const T& g,
bool periodic =
true);
+
+
1513template <
class T,
class M>
+
+
1515S2(
const std::vector<size_t>& roi,
+
+
+
+
+
1520 bool periodic =
true);
+
+
+
1530inline auto C2(
const std::vector<size_t>& roi,
const T& f,
const T& g,
bool periodic =
true);
+
+
1541template <
class T,
class M>
+
+
1543C2(
const std::vector<size_t>& roi,
+
+
+
+
+
1548 bool periodic =
true);
+
+
+
1558inline auto W2(
const std::vector<size_t>& roi,
const T& w,
const T& f,
bool periodic =
true);
+
+
1568template <
class T,
class M>
+
+
1570W2(
const std::vector<size_t>& roi,
const T& w,
const T& f,
const M& fmask,
bool periodic =
true);
+
+
1581template <
class C,
class T>
+
+
1583W2c(
const std::vector<size_t>& roi,
+
+
+
+
+
1588 bool periodic =
true);
+
+
1600template <
class C,
class T,
class M>
+
+
1602W2c(
const std::vector<size_t>& roi,
+
+
+
+
+
+
1608 bool periodic =
true);
+
+
+
1617inline auto heightheight(
const std::vector<size_t>& roi,
const T& f,
bool periodic =
true);
+
+
1626template <
class T,
class M>
+
+
1628heightheight(
const std::vector<size_t>& roi,
const T& f,
const M& fmask,
bool periodic =
true);
+
+
+
+
1639L(
const std::vector<size_t>& roi,
+
+
1641 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).
+
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 clusters and obtain certain characteristic about them.
+
array_type::array< int > centers() const
Return label only in the center of gravity (1..n).
+
array_type::tensor< size_t, 1 > sizes() const
Return size per cluster.
+
Clusters(const T &f, const S &kernel, bool periodic=true)
Constructor.
+
Clusters(const T &f, bool periodic=true)
Constructor.
+
array_type::array< int > labels() const
Return labels (1..n).
+
array_type::tensor< double, 2 > center_positions(bool as3d=false) const
Return positions of the centers of gravity (in the original rank, or as 3-d).
+
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_WARNING(message)
Warnings are implemented as:
+
#define GOOSEEYE_ASSERT(expr, assertion)
All assertions are implemented as:
+
#define GOOSEEYE_WARNING_PYTHON(message)
Warnings specific to the Python API 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.
+
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.
+
array_type::tensor< double, 2 > center_of_mass(const T &labels, bool periodic=true)
Get the position of the center of each label.
+
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.
+
L labels_rename(const L &labels, const A &rename)
Rename labels.
+
T pos2img(const T &img, const U &positions, const V &labels)
Convert positions to an image.
+
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.
+
array_type::tensor< size_t, 1 > relabel_map(const T &a, const S &b)
Find map to relabel from a to b.
+
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.
+
+