From e07d25acbad5567772c28876ba2bf1ef6205da28 Mon Sep 17 00:00:00 2001 From: Constantin Pape Date: Fri, 5 Jun 2026 07:36:33 +0200 Subject: [PATCH 1/2] Pin elf version and bump own version --- cluster_tools/version.py | 2 +- environment.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/cluster_tools/version.py b/cluster_tools/version.py index dd9b22c..7225152 100644 --- a/cluster_tools/version.py +++ b/cluster_tools/version.py @@ -1 +1 @@ -__version__ = "0.5.1" +__version__ = "0.5.2" diff --git a/environment.yml b/environment.yml index 1659e12..363440a 100644 --- a/environment.yml +++ b/environment.yml @@ -6,7 +6,7 @@ channels: dependencies: - affogato >=0.4.2 - nifty >=1.2.4 - - python-elf >=0.4.1 + - python-elf >=0.4.1,<0.9.0 - luigi - pybdv >=0.5.0 - gdown From c39889add2b9df8ad38a4488261a525dc46746aa Mon Sep 17 00:00:00 2001 From: Constantin Pape Date: Fri, 5 Jun 2026 08:06:43 +0200 Subject: [PATCH 2/2] Numpy v2 compatibility --- cluster_tools/affinities/insert_affinities.py | 2 +- cluster_tools/costs/probs_to_costs.py | 2 +- cluster_tools/lifted_multicut/solve_lifted_subproblems.py | 4 ++-- cluster_tools/mutex_watershed/two_pass_mws.py | 4 ++-- cluster_tools/postprocess/background_size_filter.py | 2 +- cluster_tools/postprocess/filling_size_filter.py | 2 +- cluster_tools/postprocess/filter_blocks.py | 4 ++-- cluster_tools/postprocess/graph_watershed_assignments.py | 2 +- cluster_tools/postprocess/id_filter.py | 2 +- cluster_tools/write/write.py | 2 +- test/lifted_features/sparse_lifted_neighborhood.py | 2 +- 11 files changed, 14 insertions(+), 14 deletions(-) diff --git a/cluster_tools/affinities/insert_affinities.py b/cluster_tools/affinities/insert_affinities.py index 5f35c01..88e53fe 100644 --- a/cluster_tools/affinities/insert_affinities.py +++ b/cluster_tools/affinities/insert_affinities.py @@ -206,7 +206,7 @@ def _insert_affinities_block(block_id, blocking, ds_in, ds_out, objects, offsets # zero out some affs if necessary if zero_objects_list is not None: - zero_ids = obj_ids[np.in1d(obj_ids, zero_objects_list)] + zero_ids = obj_ids[np.isin(obj_ids, zero_objects_list)] if zero_ids.size: for zero_id in zero_ids: # erode the mask to avoid ugly boundary artifacts diff --git a/cluster_tools/costs/probs_to_costs.py b/cluster_tools/costs/probs_to_costs.py index 2c64deb..cfb0a51 100644 --- a/cluster_tools/costs/probs_to_costs.py +++ b/cluster_tools/costs/probs_to_costs.py @@ -132,7 +132,7 @@ def _apply_node_labels(costs, uv_ids, mode, labels, # isolate mode: set all edges that connect to a node with label to node without label to max repulsive fu.log("Node-label mode: isolate") # ignore mode: set all edges that connect two node with label to max attractive - edges_with_label = np.in1d(uv_ids, with_label).reshape(uv_ids.shape) + edges_with_label = np.isin(uv_ids, with_label).reshape(uv_ids.shape) label_sum = edges_with_label.sum(axis=1) att_edges = label_sum == 2 rep_edges = label_sum == 1 diff --git a/cluster_tools/lifted_multicut/solve_lifted_subproblems.py b/cluster_tools/lifted_multicut/solve_lifted_subproblems.py index c14eda7..79997ab 100644 --- a/cluster_tools/lifted_multicut/solve_lifted_subproblems.py +++ b/cluster_tools/lifted_multicut/solve_lifted_subproblems.py @@ -132,11 +132,11 @@ class SolveLiftedSubproblemsLSF(SolveLiftedSubproblemsBase, LSFTask): def _find_lifted_edges(lifted_uv_ids, node_list): lifted_indices = np.arange(len(lifted_uv_ids), dtype='uint64') # find overlap of node_list with u-edges - inner_us = np.in1d(lifted_uv_ids[:, 0], node_list) + inner_us = np.isin(lifted_uv_ids[:, 0], node_list) inner_indices = lifted_indices[inner_us] inner_uvs = lifted_uv_ids[inner_us] # find overlap of node_list with v-edges - inner_vs = np.in1d(inner_uvs[:, 1], node_list) + inner_vs = np.isin(inner_uvs[:, 1], node_list) return inner_indices[inner_vs] diff --git a/cluster_tools/mutex_watershed/two_pass_mws.py b/cluster_tools/mutex_watershed/two_pass_mws.py index 1cf8de1..4054063 100644 --- a/cluster_tools/mutex_watershed/two_pass_mws.py +++ b/cluster_tools/mutex_watershed/two_pass_mws.py @@ -248,7 +248,7 @@ def _mws_block_pass2(block_id, blocking, with vu.file_reader(save_path) as f: # first, load the edges and see if they have overlap with our seed ids ngb_edges = f['edges'][:] - ngb_edge_mask = np.in1d(ngb_edges, seed_ids).reshape(ngb_edges.shape) + ngb_edge_mask = np.isin(ngb_edges, seed_ids).reshape(ngb_edges.shape) ngb_edge_mask = ngb_edge_mask.all(axis=1) # if we have edges, load the corresponding weights @@ -292,7 +292,7 @@ def _mws_block_pass2(block_id, blocking, # filter the assignments from ids that are not in the crop crop_ids = np.unique(seg_crop) - filter_mask = np.in1d(assignments[:, 1], crop_ids) + filter_mask = np.isin(assignments[:, 1], crop_ids) assignments = assignments[filter_mask] # store assignments to tmp folder diff --git a/cluster_tools/postprocess/background_size_filter.py b/cluster_tools/postprocess/background_size_filter.py index 37c6ec6..c5284aa 100644 --- a/cluster_tools/postprocess/background_size_filter.py +++ b/cluster_tools/postprocess/background_size_filter.py @@ -118,7 +118,7 @@ def apply_block(block_id, blocking, ds_in, ds_out, discard_ids): fu.log_block_success(block_id) return - discard_mask = np.in1d(labels, discard_ids).reshape(labels.shape) + discard_mask = np.isin(labels, discard_ids).reshape(labels.shape) # check if the discard-mask is empty if np.sum(discard_mask) == 0: ds_out[bb] = labels diff --git a/cluster_tools/postprocess/filling_size_filter.py b/cluster_tools/postprocess/filling_size_filter.py index f0ba093..72f596d 100644 --- a/cluster_tools/postprocess/filling_size_filter.py +++ b/cluster_tools/postprocess/filling_size_filter.py @@ -122,7 +122,7 @@ def apply_block(block_id, blocking, ds_hmap, ds_in, ds_out, discard_ids, preserv fu.log_block_success(block_id) return - discard_mask = np.in1d(labels, discard_ids).reshape(labels.shape) + discard_mask = np.isin(labels, discard_ids).reshape(labels.shape) # check if the discard-mask is empty if np.sum(discard_mask) == 0: ds_out[bb] = labels diff --git a/cluster_tools/postprocess/filter_blocks.py b/cluster_tools/postprocess/filter_blocks.py index 6f0c14d..4b9b1a5 100644 --- a/cluster_tools/postprocess/filter_blocks.py +++ b/cluster_tools/postprocess/filter_blocks.py @@ -117,7 +117,7 @@ def _filter_block(blocking, block_id, return # check for filter_ids - filter_mask = np.in1d(seg, filter_ids).reshape(seg.shape) + filter_mask = np.isin(seg, filter_ids).reshape(seg.shape) seg[filter_mask] = 0 ds_out[bb] = seg fu.log_block_success(block_id) @@ -138,7 +138,7 @@ def _filter_block_inplace(blocking, block_id, return # check for filter_ids - filter_mask = np.in1d(seg, filter_ids).reshape(seg.shape) + filter_mask = np.isin(seg, filter_ids).reshape(seg.shape) # check if we filter any ids if filter_mask.sum() == 0: diff --git a/cluster_tools/postprocess/graph_watershed_assignments.py b/cluster_tools/postprocess/graph_watershed_assignments.py index 19cbc7c..adaf9ed 100644 --- a/cluster_tools/postprocess/graph_watershed_assignments.py +++ b/cluster_tools/postprocess/graph_watershed_assignments.py @@ -163,7 +163,7 @@ def graph_watershed_assignments(job_id, config_path): # map zero label to new id assignments[assignments == 0] = seed_offset - discard_mask = np.in1d(assignments, discard_ids) + discard_mask = np.isin(assignments, discard_ids) assignments[discard_mask] = 0 n_discard = int(discard_mask.sum()) diff --git a/cluster_tools/postprocess/id_filter.py b/cluster_tools/postprocess/id_filter.py index 87d525f..40563f3 100644 --- a/cluster_tools/postprocess/id_filter.py +++ b/cluster_tools/postprocess/id_filter.py @@ -98,7 +98,7 @@ def id_filter(job_id, config_path): node_labels = f[node_label_key][:] # find the node ids that overlap with the filter labels - filter_mask = np.in1d(node_labels, filter_labels) + filter_mask = np.isin(node_labels, filter_labels) filter_ids = np.where(filter_mask)[0].tolist() fu.log("%i ids will be filtered" % len(filter_ids)) diff --git a/cluster_tools/write/write.py b/cluster_tools/write/write.py index 968a035..232fc90 100644 --- a/cluster_tools/write/write.py +++ b/cluster_tools/write/write.py @@ -174,7 +174,7 @@ def _apply_node_labels(seg, node_labels, allow_empty_assignments): else: this_assignment = {label: node_labels[label] for label in this_labels} else: - this_assignment = node_labels[:, 1][np.in1d(node_labels[:, 0], this_labels)] + this_assignment = node_labels[:, 1][np.isin(node_labels[:, 0], this_labels)] this_assignment = {label: this_assignment[ii] for ii, label in enumerate(this_labels)} # FIXME this casts to uint32 which can lead to nasty over-flows seg = nt.takeDict(this_assignment, seg) diff --git a/test/lifted_features/sparse_lifted_neighborhood.py b/test/lifted_features/sparse_lifted_neighborhood.py index 9bfd407..f905f35 100644 --- a/test/lifted_features/sparse_lifted_neighborhood.py +++ b/test/lifted_features/sparse_lifted_neighborhood.py @@ -40,7 +40,7 @@ def compute_nh(self, graph_depth, label_path, label_key): # filter by nodes which have a node labeling node_ids = np.arange(len(node_labels)) nodes_with_label = node_ids[node_labels != 0] - nh_mask = np.in1d(nh, nodes_with_label).reshape(nh.shape) + nh_mask = np.isin(nh, nodes_with_label).reshape(nh.shape) nh_mask = nh_mask.all(axis=1) nh = nh[nh_mask] # need to lexsort - awkward in numpy ...