Skip to content

Commit 28d424f

Browse files
authored
Merge pull request #3538 from effigies/fix/nibabel5
FIX: NiBabel 5, and NetworkX 3 and DIPY 1.6 compatibility
2 parents 7382b3d + f6bf0af commit 28d424f

File tree

13 files changed

+84
-44
lines changed

13 files changed

+84
-44
lines changed

nipype/algorithms/tests/test_ErrorMap.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ def test_errormap(tmpdir):
1717
volume1 = np.array([[[2.0, 8.0], [1.0, 2.0]], [[1.0, 9.0], [0.0, 3.0]]])
1818
# Alan Turing's birthday
1919
volume2 = np.array([[[0.0, 7.0], [2.0, 3.0]], [[1.0, 9.0], [1.0, 2.0]]])
20-
mask = np.array([[[1, 0], [0, 1]], [[1, 0], [0, 1]]])
20+
mask = np.array([[[1, 0], [0, 1]], [[1, 0], [0, 1]]], dtype=np.uint8)
2121

2222
img1 = nb.Nifti1Image(volume1, np.eye(4))
2323
img2 = nb.Nifti1Image(volume2, np.eye(4))

nipype/algorithms/tests/test_TSNR.py

+2-1
Original file line numberDiff line numberDiff line change
@@ -131,5 +131,6 @@ def assert_unchanged(self, expected_ranges):
131131
[
132132
[[[2, 4, 3, 9, 1], [3, 6, 4, 7, 4]], [[8, 3, 4, 6, 2], [4, 0, 4, 4, 2]]],
133133
[[[9, 7, 5, 5, 7], [7, 8, 4, 8, 4]], [[0, 4, 7, 1, 7], [6, 8, 8, 8, 7]]],
134-
]
134+
],
135+
dtype=np.int16,
135136
)

nipype/algorithms/tests/test_metrics.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ def test_fuzzy_overlap(tmpdir):
4545

4646
# Just considering the mask, the central pixel
4747
# that raised the index now is left aside.
48-
data = np.zeros((3, 3, 3), dtype=int)
48+
data = np.zeros((3, 3, 3), dtype=np.uint8)
4949
data[0, 0, 0] = 1
5050
data[2, 2, 2] = 1
5151
nb.Nifti1Image(data, np.eye(4)).to_filename("mask.nii.gz")

nipype/interfaces/cmtk/cmtk.py

+13-9
Original file line numberDiff line numberDiff line change
@@ -226,7 +226,8 @@ def cmat(
226226
# Add node information from specified parcellation scheme
227227
path, name, ext = split_filename(resolution_network_file)
228228
if ext == ".pck":
229-
gp = nx.read_gpickle(resolution_network_file)
229+
with open(resolution_network_file, 'rb') as f:
230+
gp = pickle.load(f)
230231
elif ext == ".graphml":
231232
gp = nx.read_graphml(resolution_network_file)
232233
else:
@@ -263,7 +264,7 @@ def cmat(
263264
)
264265
intersection_matrix = np.matrix(intersection_matrix)
265266
I = G.copy()
266-
H = nx.from_numpy_matrix(np.matrix(intersection_matrix))
267+
H = nx.from_numpy_array(np.matrix(intersection_matrix))
267268
H = nx.relabel_nodes(H, lambda x: x + 1) # relabel nodes so they start at 1
268269
I.add_weighted_edges_from(
269270
((u, v, d["weight"]) for u, v, d in H.edges(data=True))
@@ -379,22 +380,24 @@ def cmat(
379380
fibdev.add_edge(u, v, weight=di["fiber_length_std"])
380381

381382
iflogger.info("Writing network as %s", matrix_name)
382-
nx.write_gpickle(G, op.abspath(matrix_name))
383+
with open(op.abspath(matrix_name), 'wb') as f:
384+
pickle.dump(G, f, pickle.HIGHEST_PROTOCOL)
383385

384-
numfib_mlab = nx.to_numpy_matrix(numfib, dtype=int)
386+
numfib_mlab = nx.to_numpy_array(numfib, dtype=int)
385387
numfib_dict = {"number_of_fibers": numfib_mlab}
386-
fibmean_mlab = nx.to_numpy_matrix(fibmean, dtype=np.float64)
388+
fibmean_mlab = nx.to_numpy_array(fibmean, dtype=np.float64)
387389
fibmean_dict = {"mean_fiber_length": fibmean_mlab}
388-
fibmedian_mlab = nx.to_numpy_matrix(fibmedian, dtype=np.float64)
390+
fibmedian_mlab = nx.to_numpy_array(fibmedian, dtype=np.float64)
389391
fibmedian_dict = {"median_fiber_length": fibmedian_mlab}
390-
fibdev_mlab = nx.to_numpy_matrix(fibdev, dtype=np.float64)
392+
fibdev_mlab = nx.to_numpy_array(fibdev, dtype=np.float64)
391393
fibdev_dict = {"fiber_length_std": fibdev_mlab}
392394

393395
if intersections:
394396
path, name, ext = split_filename(matrix_name)
395397
intersection_matrix_name = op.abspath(name + "_intersections") + ext
396398
iflogger.info("Writing intersection network as %s", intersection_matrix_name)
397-
nx.write_gpickle(I, intersection_matrix_name)
399+
with open(intersection_matrix_name, 'wb') as f:
400+
pickle.dump(I, f, pickle.HIGHEST_PROTOCOL)
398401

399402
path, name, ext = split_filename(matrix_mat_name)
400403
if not ext == ".mat":
@@ -1070,7 +1073,8 @@ def create_nodes(roi_file, resolution_network_file, out_filename):
10701073
)
10711074
)
10721075
G.nodes[int(u)]["dn_position"] = tuple([xyz[0], xyz[2], -xyz[1]])
1073-
nx.write_gpickle(G, out_filename)
1076+
with open(out_filename, 'wb') as f:
1077+
pickle.dump(G, f, pickle.HIGHEST_PROTOCOL)
10741078
return out_filename
10751079

10761080

nipype/interfaces/cmtk/convert.py

+8-1
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,13 @@
1818
from .base import CFFBaseInterface, have_cfflib
1919

2020

21+
def _read_pickle(fname):
22+
import pickle
23+
24+
with open(fname, 'rb') as f:
25+
return pickle.load(f)
26+
27+
2128
class CFFConverterInputSpec(BaseInterfaceInputSpec):
2229
graphml_networks = InputMultiPath(
2330
File(exists=True), desc="list of graphML networks"
@@ -135,7 +142,7 @@ def _run_interface(self, runtime):
135142
unpickled = []
136143
for ntwk in self.inputs.gpickled_networks:
137144
_, ntwk_name, _ = split_filename(ntwk)
138-
unpickled = nx.read_gpickle(ntwk)
145+
unpickled = _read_pickle(ntwk)
139146
cnet = cf.CNetwork(name=ntwk_name)
140147
cnet.set_with_nxgraph(unpickled)
141148
a.add_connectome_network(cnet)

nipype/interfaces/cmtk/nbs.py

+16-8
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66

77
import numpy as np
88
import networkx as nx
9+
import pickle
910

1011
from ... import logging
1112
from ..base import (
@@ -23,13 +24,18 @@
2324
iflogger = logging.getLogger("nipype.interface")
2425

2526

27+
def _read_pickle(fname):
28+
with open(fname, 'rb') as f:
29+
return pickle.load(f)
30+
31+
2632
def ntwks_to_matrices(in_files, edge_key):
27-
first = nx.read_gpickle(in_files[0])
33+
first = _read_pickle(in_files[0])
2834
files = len(in_files)
2935
nodes = len(first.nodes())
3036
matrix = np.zeros((nodes, nodes, files))
3137
for idx, name in enumerate(in_files):
32-
graph = nx.read_gpickle(name)
38+
graph = _read_pickle(name)
3339
for u, v, d in graph.edges(data=True):
3440
try:
3541
graph[u][v]["weight"] = d[
@@ -39,7 +45,7 @@ def ntwks_to_matrices(in_files, edge_key):
3945
raise KeyError(
4046
"the graph edges do not have {} attribute".format(edge_key)
4147
)
42-
matrix[:, :, idx] = nx.to_numpy_matrix(graph) # Retrieve the matrix
48+
matrix[:, :, idx] = nx.to_numpy_array(graph) # Retrieve the matrix
4349
return matrix
4450

4551

@@ -149,8 +155,8 @@ def _run_interface(self, runtime):
149155
pADJ[x, y] = PVAL[idx]
150156

151157
# Create networkx graphs from the adjacency matrix
152-
nbsgraph = nx.from_numpy_matrix(ADJ)
153-
nbs_pval_graph = nx.from_numpy_matrix(pADJ)
158+
nbsgraph = nx.from_numpy_array(ADJ)
159+
nbs_pval_graph = nx.from_numpy_array(pADJ)
154160

155161
# Relabel nodes because they should not start at zero for our convention
156162
nbsgraph = nx.relabel_nodes(nbsgraph, lambda x: x + 1)
@@ -161,7 +167,7 @@ def _run_interface(self, runtime):
161167
else:
162168
node_ntwk_name = self.inputs.in_group1[0]
163169

164-
node_network = nx.read_gpickle(node_ntwk_name)
170+
node_network = _read_pickle(node_ntwk_name)
165171
iflogger.info(
166172
"Populating node dictionaries with attributes from %s", node_ntwk_name
167173
)
@@ -172,12 +178,14 @@ def _run_interface(self, runtime):
172178

173179
path = op.abspath("NBS_Result_" + details)
174180
iflogger.info(path)
175-
nx.write_gpickle(nbsgraph, path)
181+
with open(path, 'wb') as f:
182+
pickle.dump(nbsgraph, f, pickle.HIGHEST_PROTOCOL)
176183
iflogger.info("Saving output NBS edge network as %s", path)
177184

178185
pval_path = op.abspath("NBS_P_vals_" + details)
179186
iflogger.info(pval_path)
180-
nx.write_gpickle(nbs_pval_graph, pval_path)
187+
with open(pval_path, 'wb') as f:
188+
pickle.dump(nbs_pval_graph, f, pickle.HIGHEST_PROTOCOL)
181189
iflogger.info("Saving output p-value network as %s", pval_path)
182190
return runtime
183191

nipype/interfaces/cmtk/nx.py

+16-7
Original file line numberDiff line numberDiff line change
@@ -24,11 +24,16 @@
2424
iflogger = logging.getLogger("nipype.interface")
2525

2626

27+
def _read_pickle(fname):
28+
with open(fname, 'rb') as f:
29+
return pickle.load(f)
30+
31+
2732
def read_unknown_ntwk(ntwk):
2833
if not isinstance(ntwk, nx.classes.graph.Graph):
2934
_, _, ext = split_filename(ntwk)
3035
if ext == ".pck":
31-
ntwk = nx.read_gpickle(ntwk)
36+
ntwk = _read_pickle(ntwk)
3237
elif ext == ".graphml":
3338
ntwk = nx.read_graphml(ntwk)
3439
return ntwk
@@ -121,7 +126,7 @@ def average_networks(in_files, ntwk_res_file, group_id):
121126
counting_ntwk = ntwk.copy()
122127
# Sums all the relevant variables
123128
for index, subject in enumerate(in_files):
124-
tmp = nx.read_gpickle(subject)
129+
tmp = _read_pickle(subject)
125130
iflogger.info("File %s has %i edges", subject, tmp.number_of_edges())
126131
edges = list(tmp.edges())
127132
for edge in edges:
@@ -200,7 +205,8 @@ def average_networks(in_files, ntwk_res_file, group_id):
200205

201206
# Writes the networks and returns the name
202207
network_name = group_id + "_average.pck"
203-
nx.write_gpickle(avg_ntwk, op.abspath(network_name))
208+
with open(op.abspath(network_name), 'wb') as f:
209+
pickle.dump(avg_ntwk, f, pickle.HIGHEST_PROTOCOL)
204210
iflogger.info("Saving average network as %s", op.abspath(network_name))
205211
avg_ntwk = fix_keys_for_gexf(avg_ntwk)
206212
network_name = group_id + "_average.gexf"
@@ -460,7 +466,7 @@ def _run_interface(self, runtime):
460466
edgentwks = list()
461467
kntwks = list()
462468
matlab = list()
463-
ntwk = nx.read_gpickle(self.inputs.in_file)
469+
ntwk = _read_pickle(self.inputs.in_file)
464470

465471
# Each block computes, writes, and saves a measure
466472
# The names are then added to the output .pck file list
@@ -483,7 +489,8 @@ def _run_interface(self, runtime):
483489
for key in list(node_measures.keys()):
484490
newntwk = add_node_data(node_measures[key], ntwk)
485491
out_file = op.abspath(self._gen_outfilename(key, "pck"))
486-
nx.write_gpickle(newntwk, out_file)
492+
with open(out_file, 'wb') as f:
493+
pickle.dump(newntwk, f, pickle.HIGHEST_PROTOCOL)
487494
nodentwks.append(out_file)
488495
if isdefined(self.inputs.out_node_metrics_matlab):
489496
node_out_file = op.abspath(self.inputs.out_node_metrics_matlab)
@@ -497,7 +504,8 @@ def _run_interface(self, runtime):
497504
for key in list(edge_measures.keys()):
498505
newntwk = add_edge_data(edge_measures[key], ntwk)
499506
out_file = op.abspath(self._gen_outfilename(key, "pck"))
500-
nx.write_gpickle(newntwk, out_file)
507+
with open(out_file, 'wb') as f:
508+
pickle.dump(newntwk, f, pickle.HIGHEST_PROTOCOL)
501509
edgentwks.append(out_file)
502510
if isdefined(self.inputs.out_edge_metrics_matlab):
503511
edge_out_file = op.abspath(self.inputs.out_edge_metrics_matlab)
@@ -521,7 +529,8 @@ def _run_interface(self, runtime):
521529
out_file = op.abspath(
522530
self._gen_outfilename(self.inputs.out_k_crust, "pck")
523531
)
524-
nx.write_gpickle(ntwk_measures[key], out_file)
532+
with open(out_file, 'wb') as f:
533+
pickle.dump(ntwk_measures[key], f, pickle.HIGHEST_PROTOCOL)
525534
kntwks.append(out_file)
526535
gpickled.extend(kntwks)
527536

nipype/interfaces/cmtk/tests/test_nbs.py

+4-2
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
from ....utils.misc import package_check
33
import numpy as np
44
import networkx as nx
5+
import pickle
56
import pytest
67

78
have_cv = True
@@ -17,10 +18,11 @@ def creating_graphs(tmpdir):
1718
graphnames = ["name" + str(i) for i in range(6)]
1819
for idx, name in enumerate(graphnames):
1920
graph = np.random.rand(10, 10)
20-
G = nx.from_numpy_matrix(graph)
21+
G = nx.from_numpy_array(graph)
2122
out_file = tmpdir.strpath + graphnames[idx] + ".pck"
2223
# Save as pck file
23-
nx.write_gpickle(G, out_file)
24+
with open(out_file, 'wb') as f:
25+
pickle.dump(G, f, pickle.HIGHEST_PROTOCOL)
2426
graphlist.append(out_file)
2527
return graphlist
2628

nipype/interfaces/dipy/base.py

+3-3
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,7 @@ def convert_to_traits_type(dipy_type, is_file=False):
110110
"""Convert DIPY type to Traits type."""
111111
dipy_type = dipy_type.lower()
112112
is_mandatory = bool("optional" not in dipy_type)
113-
if "variable" in dipy_type and "string" in dipy_type:
113+
if "variable" in dipy_type and "str" in dipy_type:
114114
return traits.ListStr, is_mandatory
115115
elif "variable" in dipy_type and "int" in dipy_type:
116116
return traits.ListInt, is_mandatory
@@ -120,9 +120,9 @@ def convert_to_traits_type(dipy_type, is_file=False):
120120
return traits.ListBool, is_mandatory
121121
elif "variable" in dipy_type and "complex" in dipy_type:
122122
return traits.ListComplex, is_mandatory
123-
elif "string" in dipy_type and not is_file:
123+
elif "str" in dipy_type and not is_file:
124124
return traits.Str, is_mandatory
125-
elif "string" in dipy_type and is_file:
125+
elif "str" in dipy_type and is_file:
126126
return File, is_mandatory
127127
elif "int" in dipy_type:
128128
return traits.Int, is_mandatory

nipype/interfaces/nilearn.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -155,7 +155,7 @@ def _process_inputs(self):
155155
if self.inputs.include_global:
156156
global_label_data = label_data.dataobj.sum(axis=3) # sum across all regions
157157
global_label_data = (
158-
np.rint(global_label_data).astype(int).clip(0, 1)
158+
np.rint(global_label_data).clip(0, 1).astype('u1')
159159
) # binarize
160160
global_label_data = self._4d(global_label_data, label_data.affine)
161161
global_masker = nl.NiftiLabelsMasker(

nipype/interfaces/tests/test_nilearn.py

+3-2
Original file line numberDiff line numberDiff line change
@@ -184,10 +184,11 @@ def assert_expected_output(self, labels, wanted):
184184
[[2, -2, -1, -2, -5], [3, 0, 3, -5, -2]],
185185
[[-4, -2, -2, 1, -2], [3, 1, 4, -3, -2]],
186186
],
187-
]
187+
],
188+
np.int16,
188189
)
189190

190-
fake_label_data = np.array([[[1, 0], [3, 1]], [[2, 0], [1, 3]]])
191+
fake_label_data = np.array([[[1, 0], [3, 1]], [[2, 0], [1, 3]]], np.uint8)
191192

192193
fake_equiv_4d_label_data = np.array(
193194
[

nipype/pipeline/plugins/base.py

+13-5
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,18 @@
2121
logger = logging.getLogger("nipype.workflow")
2222

2323

24+
def _graph_to_lil_matrix(graph, nodelist):
25+
"""Provide a sparse linked list matrix across various NetworkX versions"""
26+
import scipy.sparse as ssp
27+
28+
try:
29+
from networkx import to_scipy_sparse_array
30+
except ImportError: # NetworkX < 2.7
31+
from networkx import to_scipy_sparse_matrix as to_scipy_sparse_array
32+
33+
return ssp.lil_matrix(to_scipy_sparse_array(graph, nodelist=nodelist, format="lil"))
34+
35+
2436
class PluginBase(object):
2537
"""Base class for plugins."""
2638

@@ -431,12 +443,8 @@ def _task_finished_cb(self, jobid, cached=False):
431443

432444
def _generate_dependency_list(self, graph):
433445
"""Generates a dependency list for a list of graphs."""
434-
import networkx as nx
435-
436446
self.procs, _ = topological_sort(graph)
437-
self.depidx = nx.to_scipy_sparse_matrix(
438-
graph, nodelist=self.procs, format="lil"
439-
)
447+
self.depidx = _graph_to_lil_matrix(graph, nodelist=self.procs)
440448
self.refidx = self.depidx.astype(int)
441449
self.proc_done = np.zeros(len(self.procs), dtype=bool)
442450
self.proc_pending = np.zeros(len(self.procs), dtype=bool)

requirements.txt

+3-3
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,15 @@
22
click>=6.6.0
33
networkx>=2.0
44
nibabel>=2.1.0
5-
numpy>=1.13 ; python_version < "3.7"
6-
numpy>=1.15.3 ; python_version >= "3.7"
5+
numpy>=1.17
76
packaging
87
prov>=1.5.2
98
pydot>=1.2.3
109
python-dateutil>=2.2
1110
rdflib>=5.0.0
1211
scipy>=0.14
1312
simplejson>=3.8.0
14-
traits>=4.6,!=5.0
13+
traits>=4.6,<6.4,!=5.0
1514
filelock>=3.0.0
1615
etelemetry>=0.2.0
16+
looseversion

0 commit comments

Comments
 (0)