|
7 | 7 | #include "bioimage_cpp/graph/feature_accumulation.hxx" |
8 | 8 | #include "bioimage_cpp/graph/grid_features.hxx" |
9 | 9 | #include "bioimage_cpp/graph/grid_graph.hxx" |
| 10 | +#include "bioimage_cpp/graph/label_accumulation.hxx" |
10 | 11 | #include "bioimage_cpp/graph/lifted_from_affinities.hxx" |
11 | 12 | #include "bioimage_cpp/graph/lifted_multicut.hxx" |
12 | 13 | #include "bioimage_cpp/graph/lifted_multicut/fusion_move.hxx" |
@@ -113,6 +114,20 @@ DoubleArray make_double_array(const std::vector<std::size_t> &shape) { |
113 | 114 | return DoubleArray(data, shape.size(), shape.data(), owner); |
114 | 115 | } |
115 | 116 |
|
| 117 | +template <class T> |
| 118 | +using TypedArray = nb::ndarray<nb::numpy, T, nb::c_contig>; |
| 119 | + |
| 120 | +template <class T> |
| 121 | +TypedArray<T> make_typed_array(const std::vector<std::size_t> &shape) { |
| 122 | + std::size_t size = 1; |
| 123 | + for (const auto axis_size : shape) { |
| 124 | + size *= axis_size; |
| 125 | + } |
| 126 | + auto *data = new T[size](); |
| 127 | + nb::capsule owner(data, [](void *p) noexcept { delete[] static_cast<T *>(p); }); |
| 128 | + return TypedArray<T>(data, shape.size(), shape.data(), owner); |
| 129 | +} |
| 130 | + |
116 | 131 | template <class T> |
117 | 132 | FloatingArray<T> make_floating_array(const std::vector<std::size_t> &shape) { |
118 | 133 | std::size_t size = 1; |
@@ -1245,6 +1260,55 @@ UInt64Array project_node_labels_to_pixels_t( |
1245 | 1260 | return result; |
1246 | 1261 | } |
1247 | 1262 |
|
| 1263 | +template <class LabelT, class OtherT> |
| 1264 | +TypedArray<OtherT> accumulate_labels_t( |
| 1265 | + const Rag &rag, |
| 1266 | + LabelArray<LabelT> labels, |
| 1267 | + LabelArray<OtherT> other_labels, |
| 1268 | + const bool has_ignore_value, |
| 1269 | + const OtherT ignore_value, |
| 1270 | + const std::size_t number_of_threads |
| 1271 | +) { |
| 1272 | + if (labels.ndim() != other_labels.ndim()) { |
| 1273 | + throw std::invalid_argument("other_labels shape must match labels shape"); |
| 1274 | + } |
| 1275 | + for (std::size_t axis = 0; axis < labels.ndim(); ++axis) { |
| 1276 | + if (labels.shape(axis) != other_labels.shape(axis)) { |
| 1277 | + throw std::invalid_argument("other_labels shape must match labels shape"); |
| 1278 | + } |
| 1279 | + } |
| 1280 | + |
| 1281 | + auto result = make_typed_array<OtherT>({static_cast<std::size_t>(rag.number_of_nodes())}); |
| 1282 | + |
| 1283 | + ConstArrayView<LabelT> labels_view{ |
| 1284 | + labels.data(), |
| 1285 | + ndarray_shape(labels), |
| 1286 | + {}, |
| 1287 | + }; |
| 1288 | + ConstArrayView<OtherT> other_labels_view{ |
| 1289 | + other_labels.data(), |
| 1290 | + ndarray_shape(other_labels), |
| 1291 | + {}, |
| 1292 | + }; |
| 1293 | + ArrayView<OtherT> out_view{ |
| 1294 | + result.data(), |
| 1295 | + {static_cast<std::ptrdiff_t>(rag.number_of_nodes())}, |
| 1296 | + {}, |
| 1297 | + }; |
| 1298 | + |
| 1299 | + nb::gil_scoped_release release; |
| 1300 | + graph::accumulate_labels<LabelT, OtherT>( |
| 1301 | + rag, |
| 1302 | + labels_view, |
| 1303 | + other_labels_view, |
| 1304 | + has_ignore_value, |
| 1305 | + ignore_value, |
| 1306 | + number_of_threads, |
| 1307 | + out_view |
| 1308 | + ); |
| 1309 | + return result; |
| 1310 | +} |
| 1311 | + |
1248 | 1312 | } // namespace |
1249 | 1313 |
|
1250 | 1314 | void bind_graph(nb::module_ &m) { |
@@ -1889,6 +1953,37 @@ void bind_graph(nb::module_ &m) { |
1889 | 1953 | nb::arg("node_labels"), |
1890 | 1954 | nb::arg("number_of_threads") |
1891 | 1955 | ); |
| 1956 | + |
| 1957 | +#define BIC_BIND_ACCUMULATE_LABELS(LSUF, LT, OSUF, OT) \ |
| 1958 | + m.def( \ |
| 1959 | + "_accumulate_labels_" #LSUF "_" #OSUF, \ |
| 1960 | + &accumulate_labels_t<LT, OT>, \ |
| 1961 | + nb::arg("rag"), \ |
| 1962 | + nb::arg("labels"), \ |
| 1963 | + nb::arg("other_labels"), \ |
| 1964 | + nb::arg("has_ignore_value"), \ |
| 1965 | + nb::arg("ignore_value"), \ |
| 1966 | + nb::arg("number_of_threads") \ |
| 1967 | + ) |
| 1968 | + |
| 1969 | + BIC_BIND_ACCUMULATE_LABELS(uint32, std::uint32_t, uint32, std::uint32_t); |
| 1970 | + BIC_BIND_ACCUMULATE_LABELS(uint32, std::uint32_t, uint64, std::uint64_t); |
| 1971 | + BIC_BIND_ACCUMULATE_LABELS(uint32, std::uint32_t, int32, std::int32_t); |
| 1972 | + BIC_BIND_ACCUMULATE_LABELS(uint32, std::uint32_t, int64, std::int64_t); |
| 1973 | + BIC_BIND_ACCUMULATE_LABELS(uint64, std::uint64_t, uint32, std::uint32_t); |
| 1974 | + BIC_BIND_ACCUMULATE_LABELS(uint64, std::uint64_t, uint64, std::uint64_t); |
| 1975 | + BIC_BIND_ACCUMULATE_LABELS(uint64, std::uint64_t, int32, std::int32_t); |
| 1976 | + BIC_BIND_ACCUMULATE_LABELS(uint64, std::uint64_t, int64, std::int64_t); |
| 1977 | + BIC_BIND_ACCUMULATE_LABELS(int32, std::int32_t, uint32, std::uint32_t); |
| 1978 | + BIC_BIND_ACCUMULATE_LABELS(int32, std::int32_t, uint64, std::uint64_t); |
| 1979 | + BIC_BIND_ACCUMULATE_LABELS(int32, std::int32_t, int32, std::int32_t); |
| 1980 | + BIC_BIND_ACCUMULATE_LABELS(int32, std::int32_t, int64, std::int64_t); |
| 1981 | + BIC_BIND_ACCUMULATE_LABELS(int64, std::int64_t, uint32, std::uint32_t); |
| 1982 | + BIC_BIND_ACCUMULATE_LABELS(int64, std::int64_t, uint64, std::uint64_t); |
| 1983 | + BIC_BIND_ACCUMULATE_LABELS(int64, std::int64_t, int32, std::int32_t); |
| 1984 | + BIC_BIND_ACCUMULATE_LABELS(int64, std::int64_t, int64, std::int64_t); |
| 1985 | + |
| 1986 | +#undef BIC_BIND_ACCUMULATE_LABELS |
1892 | 1987 | } |
1893 | 1988 |
|
1894 | 1989 | } // namespace bioimage_cpp::bindings |
0 commit comments