|
11 | 11 | #include "bioimage_cpp/graph/lifted_from_affinities.hxx" |
12 | 12 | #include "bioimage_cpp/graph/lifted_multicut.hxx" |
13 | 13 | #include "bioimage_cpp/graph/lifted_multicut/fusion_move.hxx" |
| 14 | +#include "bioimage_cpp/graph/lifted_multicut/lifted_from_node_labels.hxx" |
14 | 15 | #include "bioimage_cpp/graph/multicut.hxx" |
15 | 16 | #include "bioimage_cpp/graph/mutex_watershed.hxx" |
16 | 17 | #include "bioimage_cpp/graph/multicut/fusion_move.hxx" |
|
25 | 26 | #include "bioimage_cpp/graph/undirected_graph.hxx" |
26 | 27 |
|
27 | 28 | #include <nanobind/ndarray.h> |
| 29 | +#include <nanobind/stl/optional.h> |
28 | 30 | #include <nanobind/stl/pair.h> |
| 31 | +#include <nanobind/stl/string.h> |
29 | 32 | #include <nanobind/stl/unique_ptr.h> |
30 | 33 | #include <nanobind/stl/vector.h> |
31 | 34 |
|
32 | 35 | #include <array> |
33 | 36 | #include <cstddef> |
34 | 37 | #include <cstdint> |
35 | 38 | #include <memory> |
| 39 | +#include <optional> |
36 | 40 | #include <stdexcept> |
37 | 41 | #include <string> |
38 | 42 | #include <utility> |
@@ -1161,6 +1165,58 @@ UInt64Array lifted_edges_from_affinities_t( |
1161 | 1165 | return result; |
1162 | 1166 | } |
1163 | 1167 |
|
| 1168 | +template <class LabelT> |
| 1169 | +UInt64Array lifted_edges_from_node_labels_t( |
| 1170 | + const Graph &graph, |
| 1171 | + LabelArray<LabelT> node_labels, |
| 1172 | + const std::uint64_t graph_depth, |
| 1173 | + const std::string &mode, |
| 1174 | + std::optional<LabelT> ignore_label, |
| 1175 | + const std::size_t number_of_threads |
| 1176 | +) { |
| 1177 | + if (node_labels.ndim() != 1) { |
| 1178 | + throw std::invalid_argument("node_labels must be a 1D array"); |
| 1179 | + } |
| 1180 | + if (node_labels.shape(0) != graph.number_of_nodes()) { |
| 1181 | + throw std::invalid_argument( |
| 1182 | + "node_labels length must match graph number_of_nodes" |
| 1183 | + ); |
| 1184 | + } |
| 1185 | + graph::lifted_multicut::LiftedNodeLabelMode mode_enum; |
| 1186 | + if (mode == "all") { |
| 1187 | + mode_enum = graph::lifted_multicut::LiftedNodeLabelMode::all; |
| 1188 | + } else if (mode == "same") { |
| 1189 | + mode_enum = graph::lifted_multicut::LiftedNodeLabelMode::same; |
| 1190 | + } else if (mode == "different") { |
| 1191 | + mode_enum = graph::lifted_multicut::LiftedNodeLabelMode::different; |
| 1192 | + } else { |
| 1193 | + throw std::invalid_argument( |
| 1194 | + "mode must be one of 'all', 'same', 'different', got '" + mode + "'" |
| 1195 | + ); |
| 1196 | + } |
| 1197 | + |
| 1198 | + ConstArrayView<LabelT> labels_view{ |
| 1199 | + node_labels.data(), |
| 1200 | + {static_cast<std::ptrdiff_t>(node_labels.shape(0))}, |
| 1201 | + {}, |
| 1202 | + }; |
| 1203 | + |
| 1204 | + std::vector<bioimage_cpp::detail::Edge> lifted_edges; |
| 1205 | + { |
| 1206 | + nb::gil_scoped_release release; |
| 1207 | + lifted_edges = graph::lifted_multicut::lifted_edges_from_node_labels<LabelT>( |
| 1208 | + graph, labels_view, graph_depth, mode_enum, ignore_label, number_of_threads |
| 1209 | + ); |
| 1210 | + } |
| 1211 | + auto result = make_uint64_array({lifted_edges.size(), 2}); |
| 1212 | + auto *data = result.data(); |
| 1213 | + for (std::size_t index = 0; index < lifted_edges.size(); ++index) { |
| 1214 | + data[2 * index] = lifted_edges[index].first; |
| 1215 | + data[2 * index + 1] = lifted_edges[index].second; |
| 1216 | + } |
| 1217 | + return result; |
| 1218 | +} |
| 1219 | + |
1164 | 1220 | template <class LabelT> |
1165 | 1221 | DoubleArray accumulate_lifted_affinity_features_t( |
1166 | 1222 | LabelArray<LabelT> labels, |
@@ -1880,6 +1936,47 @@ void bind_graph(nb::module_ &m) { |
1880 | 1936 | nb::arg("number_of_threads") |
1881 | 1937 | ); |
1882 | 1938 |
|
| 1939 | + m.def( |
| 1940 | + "_lifted_edges_from_node_labels_uint32", |
| 1941 | + &lifted_edges_from_node_labels_t<std::uint32_t>, |
| 1942 | + nb::arg("graph"), |
| 1943 | + nb::arg("node_labels"), |
| 1944 | + nb::arg("graph_depth"), |
| 1945 | + nb::arg("mode"), |
| 1946 | + nb::arg("ignore_label"), |
| 1947 | + nb::arg("number_of_threads") |
| 1948 | + ); |
| 1949 | + m.def( |
| 1950 | + "_lifted_edges_from_node_labels_uint64", |
| 1951 | + &lifted_edges_from_node_labels_t<std::uint64_t>, |
| 1952 | + nb::arg("graph"), |
| 1953 | + nb::arg("node_labels"), |
| 1954 | + nb::arg("graph_depth"), |
| 1955 | + nb::arg("mode"), |
| 1956 | + nb::arg("ignore_label"), |
| 1957 | + nb::arg("number_of_threads") |
| 1958 | + ); |
| 1959 | + m.def( |
| 1960 | + "_lifted_edges_from_node_labels_int32", |
| 1961 | + &lifted_edges_from_node_labels_t<std::int32_t>, |
| 1962 | + nb::arg("graph"), |
| 1963 | + nb::arg("node_labels"), |
| 1964 | + nb::arg("graph_depth"), |
| 1965 | + nb::arg("mode"), |
| 1966 | + nb::arg("ignore_label"), |
| 1967 | + nb::arg("number_of_threads") |
| 1968 | + ); |
| 1969 | + m.def( |
| 1970 | + "_lifted_edges_from_node_labels_int64", |
| 1971 | + &lifted_edges_from_node_labels_t<std::int64_t>, |
| 1972 | + nb::arg("graph"), |
| 1973 | + nb::arg("node_labels"), |
| 1974 | + nb::arg("graph_depth"), |
| 1975 | + nb::arg("mode"), |
| 1976 | + nb::arg("ignore_label"), |
| 1977 | + nb::arg("number_of_threads") |
| 1978 | + ); |
| 1979 | + |
1883 | 1980 | m.def( |
1884 | 1981 | "_accumulate_lifted_affinity_features_uint32", |
1885 | 1982 | &accumulate_lifted_affinity_features_t<std::uint32_t>, |
|
0 commit comments