pcntoolkit 0.32.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- pcntoolkit/__init__.py +4 -0
- pcntoolkit/configs.py +9 -0
- pcntoolkit/dataio/__init__.py +1 -0
- pcntoolkit/dataio/fileio.py +608 -0
- pcntoolkit/model/KnuOp.py +48 -0
- pcntoolkit/model/NP.py +88 -0
- pcntoolkit/model/NPR.py +86 -0
- pcntoolkit/model/SHASH.py +509 -0
- pcntoolkit/model/__init__.py +6 -0
- pcntoolkit/model/architecture.py +219 -0
- pcntoolkit/model/bayesreg.py +585 -0
- pcntoolkit/model/core.21290 +0 -0
- pcntoolkit/model/gp.py +489 -0
- pcntoolkit/model/hbr.py +1584 -0
- pcntoolkit/model/rfa.py +245 -0
- pcntoolkit/normative.py +1647 -0
- pcntoolkit/normative_NP.py +336 -0
- pcntoolkit/normative_model/__init__.py +6 -0
- pcntoolkit/normative_model/norm_base.py +62 -0
- pcntoolkit/normative_model/norm_blr.py +303 -0
- pcntoolkit/normative_model/norm_gpr.py +112 -0
- pcntoolkit/normative_model/norm_hbr.py +752 -0
- pcntoolkit/normative_model/norm_np.py +333 -0
- pcntoolkit/normative_model/norm_rfa.py +109 -0
- pcntoolkit/normative_model/norm_utils.py +29 -0
- pcntoolkit/normative_parallel.py +1420 -0
- pcntoolkit/regression_model/blr/warp.py +1 -0
- pcntoolkit/trendsurf.py +315 -0
- pcntoolkit/util/__init__.py +1 -0
- pcntoolkit/util/bspline.py +149 -0
- pcntoolkit/util/hbr_utils.py +242 -0
- pcntoolkit/util/utils.py +1698 -0
- pcntoolkit-0.32.0.dist-info/LICENSE +674 -0
- pcntoolkit-0.32.0.dist-info/METADATA +134 -0
- pcntoolkit-0.32.0.dist-info/RECORD +37 -0
- pcntoolkit-0.32.0.dist-info/WHEEL +4 -0
- pcntoolkit-0.32.0.dist-info/entry_points.txt +5 -0
pcntoolkit/__init__.py
ADDED
pcntoolkit/configs.py
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
from . import fileio
|
|
@@ -0,0 +1,608 @@
|
|
|
1
|
+
from __future__ import print_function
|
|
2
|
+
|
|
3
|
+
import os
|
|
4
|
+
import sys
|
|
5
|
+
import numpy as np
|
|
6
|
+
import nibabel as nib
|
|
7
|
+
import tempfile
|
|
8
|
+
import pandas as pd
|
|
9
|
+
import re
|
|
10
|
+
|
|
11
|
+
try: # run as a package if installed
|
|
12
|
+
from pcntoolkit import configs
|
|
13
|
+
except ImportError:
|
|
14
|
+
pass
|
|
15
|
+
|
|
16
|
+
path = os.path.abspath(os.path.dirname(__file__))
|
|
17
|
+
path = os.path.dirname(path) # parent directory
|
|
18
|
+
if path not in sys.path:
|
|
19
|
+
sys.path.append(path)
|
|
20
|
+
del path
|
|
21
|
+
import configs
|
|
22
|
+
|
|
23
|
+
CIFTI_MAPPINGS = ('dconn', 'dtseries', 'pconn', 'ptseries', 'dscalar',
|
|
24
|
+
'dlabel', 'pscalar', 'pdconn', 'dpconn',
|
|
25
|
+
'pconnseries', 'pconnscalar')
|
|
26
|
+
|
|
27
|
+
CIFTI_VOL_ATLAS = 'Atlas_ROIs.2.nii.gz'
|
|
28
|
+
|
|
29
|
+
PICKLE_PROTOCOL = configs.PICKLE_PROTOCOL
|
|
30
|
+
|
|
31
|
+
# ------------------------
|
|
32
|
+
# general utility routines
|
|
33
|
+
# ------------------------
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
def predictive_interval(s2_forward,
|
|
37
|
+
cov_forward,
|
|
38
|
+
multiplicator):
|
|
39
|
+
"""
|
|
40
|
+
Calculates a predictive interval for the forward model
|
|
41
|
+
"""
|
|
42
|
+
# calculates a predictive interval
|
|
43
|
+
|
|
44
|
+
PI = np.zeros(len(cov_forward))
|
|
45
|
+
for i, xdot in enumerate(cov_forward):
|
|
46
|
+
s = np.sqrt(s2_forward[i])
|
|
47
|
+
PI[i] = multiplicator*s
|
|
48
|
+
return PI
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
def create_mask(data_array, mask, verbose=False):
|
|
52
|
+
"""
|
|
53
|
+
Create a mask from a data array or a nifti file
|
|
54
|
+
|
|
55
|
+
Basic usage::
|
|
56
|
+
|
|
57
|
+
create_mask(data_array, mask, verbose)
|
|
58
|
+
|
|
59
|
+
:param data_array: numpy array containing the data to write out
|
|
60
|
+
:param mask: nifti image containing a mask for the image
|
|
61
|
+
:param verbose: verbose output
|
|
62
|
+
"""
|
|
63
|
+
|
|
64
|
+
# create a (volumetric) mask either from an input nifti or the nifti itself
|
|
65
|
+
|
|
66
|
+
if mask is not None:
|
|
67
|
+
if verbose:
|
|
68
|
+
print('Loading ROI mask ...')
|
|
69
|
+
maskvol = load_nifti(mask, vol=True)
|
|
70
|
+
maskvol = maskvol != 0
|
|
71
|
+
else:
|
|
72
|
+
if len(data_array.shape) < 4:
|
|
73
|
+
dim = data_array.shape[0:3] + (1,)
|
|
74
|
+
else:
|
|
75
|
+
dim = data_array.shape[0:3] + (data_array.shape[3],)
|
|
76
|
+
|
|
77
|
+
if verbose:
|
|
78
|
+
print('Generating mask automatically ...')
|
|
79
|
+
if dim[3] == 1:
|
|
80
|
+
maskvol = data_array[:, :, :] != 0
|
|
81
|
+
else:
|
|
82
|
+
maskvol = data_array[:, :, :, 0] != 0
|
|
83
|
+
|
|
84
|
+
return maskvol
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
def vol2vec(dat, mask, verbose=False):
|
|
88
|
+
"""
|
|
89
|
+
Vectorise a 3d image
|
|
90
|
+
|
|
91
|
+
Basic usage::
|
|
92
|
+
|
|
93
|
+
vol2vec(dat, mask, verbose)
|
|
94
|
+
|
|
95
|
+
:param dat: numpy array containing the data to write out
|
|
96
|
+
:param mask: nifti image containing a mask for the image
|
|
97
|
+
:param verbose: verbose output
|
|
98
|
+
"""
|
|
99
|
+
# vectorise a 3d image
|
|
100
|
+
|
|
101
|
+
if len(dat.shape) < 4:
|
|
102
|
+
dim = dat.shape[0:3] + (1,)
|
|
103
|
+
else:
|
|
104
|
+
dim = dat.shape[0:3] + (dat.shape[3],)
|
|
105
|
+
|
|
106
|
+
# mask = create_mask(dat, mask=mask, verbose=verbose)
|
|
107
|
+
if mask is None:
|
|
108
|
+
mask = create_mask(dat, mask=mask, verbose=verbose)
|
|
109
|
+
|
|
110
|
+
# mask the image
|
|
111
|
+
maskid = np.where(mask.ravel())[0]
|
|
112
|
+
dat = np.reshape(dat, (np.prod(dim[0:3]), dim[3]))
|
|
113
|
+
dat = dat[maskid, :]
|
|
114
|
+
|
|
115
|
+
# convert to 1-d array if the file only contains one volume
|
|
116
|
+
if dim[3] == 1:
|
|
117
|
+
dat = dat.ravel()
|
|
118
|
+
|
|
119
|
+
return dat
|
|
120
|
+
|
|
121
|
+
|
|
122
|
+
def file_type(filename):
|
|
123
|
+
"""
|
|
124
|
+
Determine the file type of a file
|
|
125
|
+
|
|
126
|
+
Basic usage::
|
|
127
|
+
|
|
128
|
+
file_type(filename)
|
|
129
|
+
|
|
130
|
+
:param filename: name of the file to check
|
|
131
|
+
"""
|
|
132
|
+
# routine to determine filetype
|
|
133
|
+
|
|
134
|
+
if filename.endswith(('.dtseries.nii', '.dscalar.nii', '.dlabel.nii')):
|
|
135
|
+
ftype = 'cifti'
|
|
136
|
+
elif filename.endswith(('.nii.gz', '.nii', '.img', '.hdr')):
|
|
137
|
+
ftype = 'nifti'
|
|
138
|
+
elif filename.endswith(('.txt', '.csv', '.tsv', '.asc')):
|
|
139
|
+
ftype = 'text'
|
|
140
|
+
elif filename.endswith(('.pkl')):
|
|
141
|
+
ftype = 'binary'
|
|
142
|
+
else:
|
|
143
|
+
raise ValueError("I don't know what to do with " + filename)
|
|
144
|
+
|
|
145
|
+
return ftype
|
|
146
|
+
|
|
147
|
+
|
|
148
|
+
def file_extension(filename):
|
|
149
|
+
"""
|
|
150
|
+
Determine the file extension of a file (e.g. .nii.gz)
|
|
151
|
+
|
|
152
|
+
Basic usage::
|
|
153
|
+
|
|
154
|
+
file_extension(filename)
|
|
155
|
+
|
|
156
|
+
:param filename: name of the file to check
|
|
157
|
+
"""
|
|
158
|
+
|
|
159
|
+
# routine to get the full file extension (e.g. .nii.gz, not just .gz)
|
|
160
|
+
|
|
161
|
+
parts = filename.split(os.extsep)
|
|
162
|
+
|
|
163
|
+
if parts[-1] == 'gz':
|
|
164
|
+
if parts[-2] == 'nii' or parts[-2] == 'img' or parts[-2] == 'hdr':
|
|
165
|
+
ext = parts[-2] + '.' + parts[-1]
|
|
166
|
+
else:
|
|
167
|
+
ext = parts[-1]
|
|
168
|
+
elif parts[-1] == 'nii':
|
|
169
|
+
if parts[-2] in CIFTI_MAPPINGS:
|
|
170
|
+
ext = parts[-2] + '.' + parts[-1]
|
|
171
|
+
else:
|
|
172
|
+
ext = parts[-1]
|
|
173
|
+
else:
|
|
174
|
+
ext = parts[-1]
|
|
175
|
+
|
|
176
|
+
ext = '.' + ext
|
|
177
|
+
return ext
|
|
178
|
+
|
|
179
|
+
|
|
180
|
+
def file_stem(filename):
|
|
181
|
+
"""
|
|
182
|
+
Determine the file stem of a file (e.g. /path/to/file.nii.gz -> file)
|
|
183
|
+
|
|
184
|
+
Basic usage::
|
|
185
|
+
|
|
186
|
+
file_stem(filename)
|
|
187
|
+
|
|
188
|
+
:param filename: name of the file to check
|
|
189
|
+
"""
|
|
190
|
+
idx = filename.find(file_extension(filename))
|
|
191
|
+
stm = filename[0:idx]
|
|
192
|
+
|
|
193
|
+
return stm
|
|
194
|
+
|
|
195
|
+
# --------------
|
|
196
|
+
# nifti routines
|
|
197
|
+
# --------------
|
|
198
|
+
|
|
199
|
+
|
|
200
|
+
def load_nifti(datafile, mask=None, vol=False, verbose=False):
|
|
201
|
+
"""
|
|
202
|
+
Load a nifti file into a numpy array
|
|
203
|
+
|
|
204
|
+
Basic usage::
|
|
205
|
+
|
|
206
|
+
load_nifti(datafile, mask, vol, verbose)
|
|
207
|
+
|
|
208
|
+
:param datafile: name of the file to load
|
|
209
|
+
:param mask: nifti image containing a mask for the image
|
|
210
|
+
:param vol: whether to load the image as a volume
|
|
211
|
+
:param verbose: verbose output
|
|
212
|
+
"""
|
|
213
|
+
|
|
214
|
+
if verbose:
|
|
215
|
+
print('Loading nifti: ' + datafile + ' ...')
|
|
216
|
+
img = nib.load(datafile)
|
|
217
|
+
dat = img.get_data()
|
|
218
|
+
|
|
219
|
+
if mask is not None:
|
|
220
|
+
mask = load_nifti(mask, vol=True)
|
|
221
|
+
|
|
222
|
+
if not vol:
|
|
223
|
+
dat = vol2vec(dat, mask)
|
|
224
|
+
|
|
225
|
+
return dat
|
|
226
|
+
|
|
227
|
+
|
|
228
|
+
def save_nifti(data, filename, examplenii, mask, dtype=None):
|
|
229
|
+
'''
|
|
230
|
+
Write output to nifti
|
|
231
|
+
|
|
232
|
+
Basic usage::
|
|
233
|
+
|
|
234
|
+
save_nifti(data, filename mask, dtype)
|
|
235
|
+
|
|
236
|
+
:param data: numpy array containing the data to write out
|
|
237
|
+
:param filename: where to store it
|
|
238
|
+
:param examplenii: nifti to copy the geometry and data type from
|
|
239
|
+
:mask: nifti image containing a mask for the image
|
|
240
|
+
:param dtype: data type for the output image (if different from the image)
|
|
241
|
+
'''
|
|
242
|
+
|
|
243
|
+
# load mask
|
|
244
|
+
if isinstance(mask, str):
|
|
245
|
+
mask = load_nifti(mask, vol=True)
|
|
246
|
+
mask = mask != 0
|
|
247
|
+
|
|
248
|
+
# load example image
|
|
249
|
+
ex_img = nib.load(examplenii)
|
|
250
|
+
ex_img.shape
|
|
251
|
+
dim = ex_img.shape[0:3]
|
|
252
|
+
if len(data.shape) < 2:
|
|
253
|
+
nvol = 1
|
|
254
|
+
data = data[:, np.newaxis]
|
|
255
|
+
else:
|
|
256
|
+
nvol = int(data.shape[1])
|
|
257
|
+
|
|
258
|
+
# write data
|
|
259
|
+
array_data = np.zeros((np.prod(dim), nvol))
|
|
260
|
+
array_data[mask.flatten(), :] = data
|
|
261
|
+
array_data = np.reshape(array_data, dim+(nvol,))
|
|
262
|
+
hdr = ex_img.header
|
|
263
|
+
if dtype is not None:
|
|
264
|
+
hdr.set_data_dtype(dtype)
|
|
265
|
+
array_data = array_data.astype(dtype)
|
|
266
|
+
array_img = nib.Nifti1Image(array_data, ex_img.affine, hdr)
|
|
267
|
+
|
|
268
|
+
nib.save(array_img, filename)
|
|
269
|
+
|
|
270
|
+
# --------------
|
|
271
|
+
# cifti routines
|
|
272
|
+
# --------------
|
|
273
|
+
|
|
274
|
+
|
|
275
|
+
def load_cifti(filename, vol=False, mask=None, rmtmp=True):
|
|
276
|
+
"""
|
|
277
|
+
Load a cifti file into a numpy array
|
|
278
|
+
|
|
279
|
+
Basic usage::
|
|
280
|
+
|
|
281
|
+
load_cifti(filename, vol, mask, rmtmp)
|
|
282
|
+
|
|
283
|
+
:param filename: name of the file to load
|
|
284
|
+
:param vol: whether to load the image as a volume
|
|
285
|
+
:param mask: nifti image containing a mask for the image
|
|
286
|
+
:param rmtmp: whether to remove temporary files
|
|
287
|
+
"""
|
|
288
|
+
# parse the name
|
|
289
|
+
dnam, fnam = os.path.split(filename)
|
|
290
|
+
fpref = file_stem(fnam)
|
|
291
|
+
outstem = os.path.join(tempfile.gettempdir(),
|
|
292
|
+
str(os.getpid()) + "-" + fpref)
|
|
293
|
+
|
|
294
|
+
# extract surface data from the cifti file
|
|
295
|
+
print("Extracting cifti surface data to ", outstem, '-*.func.gii', sep="")
|
|
296
|
+
giinamel = outstem + '-left.func.gii'
|
|
297
|
+
giinamer = outstem + '-right.func.gii'
|
|
298
|
+
os.system('wb_command -cifti-separate ' + filename +
|
|
299
|
+
' COLUMN -metric CORTEX_LEFT ' + giinamel)
|
|
300
|
+
os.system('wb_command -cifti-separate ' + filename +
|
|
301
|
+
' COLUMN -metric CORTEX_RIGHT ' + giinamer)
|
|
302
|
+
|
|
303
|
+
# load the surface data
|
|
304
|
+
giil = nib.load(giinamel)
|
|
305
|
+
giir = nib.load(giinamer)
|
|
306
|
+
Nimg = len(giil.darrays)
|
|
307
|
+
Nvert = len(giil.darrays[0].data)
|
|
308
|
+
if Nimg == 1:
|
|
309
|
+
out = np.concatenate((giil.darrays[0].data, giir.darrays[0].data),
|
|
310
|
+
axis=0)
|
|
311
|
+
else:
|
|
312
|
+
Gl = np.zeros((Nvert, Nimg))
|
|
313
|
+
Gr = np.zeros((Nvert, Nimg))
|
|
314
|
+
for i in range(0, Nimg):
|
|
315
|
+
Gl[:, i] = giil.darrays[i].data
|
|
316
|
+
Gr[:, i] = giir.darrays[i].data
|
|
317
|
+
out = np.concatenate((Gl, Gr), axis=0)
|
|
318
|
+
if rmtmp:
|
|
319
|
+
# clean up temporary files
|
|
320
|
+
os.remove(giinamel)
|
|
321
|
+
os.remove(giinamer)
|
|
322
|
+
|
|
323
|
+
if vol:
|
|
324
|
+
niiname = outstem + '-vol.nii'
|
|
325
|
+
print("Extracting cifti volume data to ", niiname, sep="")
|
|
326
|
+
os.system('wb_command -cifti-separate ' + filename +
|
|
327
|
+
' COLUMN -volume-all ' + niiname)
|
|
328
|
+
vol = load_nifti(niiname, vol=True)
|
|
329
|
+
volmask = create_mask(vol)
|
|
330
|
+
out = np.concatenate((out, vol2vec(vol, volmask)), axis=0)
|
|
331
|
+
if rmtmp:
|
|
332
|
+
os.remove(niiname)
|
|
333
|
+
|
|
334
|
+
return out
|
|
335
|
+
|
|
336
|
+
|
|
337
|
+
def save_cifti(data, filename, example, mask=None, vol=True, volatlas=None):
|
|
338
|
+
"""
|
|
339
|
+
Save a cifti file from a numpy array
|
|
340
|
+
|
|
341
|
+
Basic usage::
|
|
342
|
+
|
|
343
|
+
save_cifti(data, filename, example, mask, vol, volatlas)
|
|
344
|
+
|
|
345
|
+
:param data: numpy array containing the data to write out
|
|
346
|
+
:param filename: where to store it
|
|
347
|
+
:param example: example file to copy the geometry from
|
|
348
|
+
:param mask: nifti image containing a mask for the image
|
|
349
|
+
:param vol: whether to load the image as a volume
|
|
350
|
+
:param volatlas: atlas to use for the volume
|
|
351
|
+
"""
|
|
352
|
+
|
|
353
|
+
# do some sanity checks
|
|
354
|
+
if data.dtype == 'float32' or \
|
|
355
|
+
data.dtype == 'float' or \
|
|
356
|
+
data.dtype == 'float64':
|
|
357
|
+
data = data.astype('float32') # force 32 bit output
|
|
358
|
+
dtype = 'NIFTI_TYPE_FLOAT32'
|
|
359
|
+
else:
|
|
360
|
+
raise ValueError('Only float data types currently handled')
|
|
361
|
+
|
|
362
|
+
if len(data.shape) == 1:
|
|
363
|
+
Nimg = 1
|
|
364
|
+
data = data[:, np.newaxis]
|
|
365
|
+
else:
|
|
366
|
+
Nimg = data.shape[1]
|
|
367
|
+
|
|
368
|
+
# get the base filename
|
|
369
|
+
dnam, fnam = os.path.split(filename)
|
|
370
|
+
fstem = file_stem(fnam)
|
|
371
|
+
|
|
372
|
+
# Split the template
|
|
373
|
+
estem = os.path.join(tempfile.gettempdir(), str(os.getpid()) + "-" + fstem)
|
|
374
|
+
giiexnamel = estem + '-left.func.gii'
|
|
375
|
+
giiexnamer = estem + '-right.func.gii'
|
|
376
|
+
os.system('wb_command -cifti-separate ' + example +
|
|
377
|
+
' COLUMN -metric CORTEX_LEFT ' + giiexnamel)
|
|
378
|
+
os.system('wb_command -cifti-separate ' + example +
|
|
379
|
+
' COLUMN -metric CORTEX_RIGHT ' + giiexnamer)
|
|
380
|
+
|
|
381
|
+
# write left hemisphere
|
|
382
|
+
giiexl = nib.load(giiexnamel)
|
|
383
|
+
Nvertl = len(giiexl.darrays[0].data)
|
|
384
|
+
garraysl = []
|
|
385
|
+
for i in range(0, Nimg):
|
|
386
|
+
garraysl.append(
|
|
387
|
+
nib.gifti.gifti.GiftiDataArray(data=data[0:Nvertl, i],
|
|
388
|
+
datatype=dtype))
|
|
389
|
+
giil = nib.gifti.gifti.GiftiImage(darrays=garraysl)
|
|
390
|
+
fnamel = fstem + '-left.func.gii'
|
|
391
|
+
nib.save(giil, fnamel)
|
|
392
|
+
|
|
393
|
+
# write right hemisphere
|
|
394
|
+
giiexr = nib.load(giiexnamer)
|
|
395
|
+
Nvertr = len(giiexr.darrays[0].data)
|
|
396
|
+
garraysr = []
|
|
397
|
+
for i in range(0, Nimg):
|
|
398
|
+
garraysr.append(
|
|
399
|
+
nib.gifti.gifti.GiftiDataArray(data=data[Nvertl:Nvertl+Nvertr, i],
|
|
400
|
+
datatype=dtype))
|
|
401
|
+
giir = nib.gifti.gifti.GiftiImage(darrays=garraysr)
|
|
402
|
+
fnamer = fstem + '-right.func.gii'
|
|
403
|
+
nib.save(giir, fnamer)
|
|
404
|
+
|
|
405
|
+
tmpfiles = [fnamer, fnamel, giiexnamel, giiexnamer]
|
|
406
|
+
|
|
407
|
+
# process volumetric data
|
|
408
|
+
if vol:
|
|
409
|
+
niiexname = estem + '-vol.nii'
|
|
410
|
+
os.system('wb_command -cifti-separate ' + example +
|
|
411
|
+
' COLUMN -volume-all ' + niiexname)
|
|
412
|
+
niivol = load_nifti(niiexname, vol=True)
|
|
413
|
+
if mask is None:
|
|
414
|
+
mask = create_mask(niivol)
|
|
415
|
+
|
|
416
|
+
if volatlas is None:
|
|
417
|
+
volatlas = CIFTI_VOL_ATLAS
|
|
418
|
+
fnamev = fstem + '-vol.nii'
|
|
419
|
+
|
|
420
|
+
save_nifti(data[Nvertr+Nvertl:, :], fnamev, niiexname, mask)
|
|
421
|
+
tmpfiles.extend([fnamev, niiexname])
|
|
422
|
+
|
|
423
|
+
# write cifti
|
|
424
|
+
fname = fstem + '.dtseries.nii'
|
|
425
|
+
os.system('wb_command -cifti-create-dense-timeseries ' + fname +
|
|
426
|
+
' -volume ' + fnamev + ' ' + volatlas +
|
|
427
|
+
' -left-metric ' + fnamel + ' -right-metric ' + fnamer)
|
|
428
|
+
|
|
429
|
+
# clean up
|
|
430
|
+
for f in tmpfiles:
|
|
431
|
+
os.remove(f)
|
|
432
|
+
|
|
433
|
+
# --------------
|
|
434
|
+
# ascii routines
|
|
435
|
+
# --------------
|
|
436
|
+
|
|
437
|
+
|
|
438
|
+
def load_pd(filename):
|
|
439
|
+
"""
|
|
440
|
+
Load a csv file into a pandas dataframe
|
|
441
|
+
|
|
442
|
+
Basic usage::
|
|
443
|
+
|
|
444
|
+
load_pd(filename)
|
|
445
|
+
|
|
446
|
+
:param filename: name of the file to load
|
|
447
|
+
"""
|
|
448
|
+
|
|
449
|
+
# based on pandas
|
|
450
|
+
x = pd.read_csv(filename,
|
|
451
|
+
sep=' ',
|
|
452
|
+
header=None)
|
|
453
|
+
return x
|
|
454
|
+
|
|
455
|
+
|
|
456
|
+
def save_pd(data, filename):
|
|
457
|
+
"""
|
|
458
|
+
Save a pandas dataframe to a csv file
|
|
459
|
+
|
|
460
|
+
Basic usage::
|
|
461
|
+
|
|
462
|
+
save_pd(data, filename)
|
|
463
|
+
|
|
464
|
+
:param data: pandas dataframe containing the data to write out
|
|
465
|
+
:param filename: where to store it
|
|
466
|
+
"""
|
|
467
|
+
# based on pandas
|
|
468
|
+
data.to_csv(filename,
|
|
469
|
+
index=None,
|
|
470
|
+
header=None,
|
|
471
|
+
sep=' ',
|
|
472
|
+
na_rep='NaN')
|
|
473
|
+
|
|
474
|
+
|
|
475
|
+
def load_ascii(filename):
|
|
476
|
+
"""
|
|
477
|
+
Load an ascii file into a numpy array
|
|
478
|
+
|
|
479
|
+
Basic usage::
|
|
480
|
+
|
|
481
|
+
load_ascii(filename)
|
|
482
|
+
|
|
483
|
+
:param filename: name of the file to load
|
|
484
|
+
"""
|
|
485
|
+
|
|
486
|
+
# based on pandas
|
|
487
|
+
x = np.loadtxt(filename)
|
|
488
|
+
return x
|
|
489
|
+
|
|
490
|
+
|
|
491
|
+
def save_ascii(data, filename):
|
|
492
|
+
"""
|
|
493
|
+
Save a numpy array to an ascii file
|
|
494
|
+
|
|
495
|
+
Basic usage::
|
|
496
|
+
|
|
497
|
+
save_ascii(data, filename)
|
|
498
|
+
|
|
499
|
+
:param data: numpy array containing the data to write out
|
|
500
|
+
:param filename: where to store it
|
|
501
|
+
"""
|
|
502
|
+
# based on pandas
|
|
503
|
+
np.savetxt(filename, data)
|
|
504
|
+
|
|
505
|
+
# ----------------
|
|
506
|
+
# generic routines
|
|
507
|
+
# ----------------
|
|
508
|
+
|
|
509
|
+
|
|
510
|
+
def save(data, filename, example=None, mask=None, text=False, dtype=None):
|
|
511
|
+
"""
|
|
512
|
+
Save a numpy array to a file
|
|
513
|
+
|
|
514
|
+
Basic usage::
|
|
515
|
+
|
|
516
|
+
save(data, filename, example, mask, text, dtype)
|
|
517
|
+
|
|
518
|
+
:param data: numpy array containing the data to write out
|
|
519
|
+
:param filename: where to store it
|
|
520
|
+
:param example: example file to copy the geometry from
|
|
521
|
+
:param mask: nifti image containing a mask for the image
|
|
522
|
+
:param text: whether to write out a text file
|
|
523
|
+
:param dtype: data type for the output image (if different from the image)
|
|
524
|
+
"""
|
|
525
|
+
|
|
526
|
+
if file_type(filename) == 'cifti':
|
|
527
|
+
save_cifti(data.T, filename, example, vol=True)
|
|
528
|
+
elif file_type(filename) == 'nifti':
|
|
529
|
+
save_nifti(data.T, filename, example, mask, dtype=dtype)
|
|
530
|
+
elif text or file_type(filename) == 'text':
|
|
531
|
+
save_ascii(data, filename)
|
|
532
|
+
elif file_type(filename) == 'binary':
|
|
533
|
+
data = pd.DataFrame(data)
|
|
534
|
+
data.to_pickle(filename, protocol=PICKLE_PROTOCOL)
|
|
535
|
+
|
|
536
|
+
|
|
537
|
+
def load(filename, mask=None, text=False, vol=True):
|
|
538
|
+
"""
|
|
539
|
+
Load a numpy array from a file
|
|
540
|
+
|
|
541
|
+
Basic usage::
|
|
542
|
+
|
|
543
|
+
load(filename, mask, text, vol)
|
|
544
|
+
|
|
545
|
+
:param filename: name of the file to load
|
|
546
|
+
:param mask: nifti image containing a mask for the image
|
|
547
|
+
:param text: whether to write out a text file
|
|
548
|
+
:param vol: whether to load the image as a volume
|
|
549
|
+
"""
|
|
550
|
+
|
|
551
|
+
if file_type(filename) == 'cifti':
|
|
552
|
+
x = load_cifti(filename, vol=vol)
|
|
553
|
+
elif file_type(filename) == 'nifti':
|
|
554
|
+
x = load_nifti(filename, mask, vol=vol)
|
|
555
|
+
elif text or file_type(filename) == 'text':
|
|
556
|
+
x = load_ascii(filename)
|
|
557
|
+
elif file_type(filename) == 'binary':
|
|
558
|
+
x = pd.read_pickle(filename)
|
|
559
|
+
x = x.to_numpy()
|
|
560
|
+
return x
|
|
561
|
+
|
|
562
|
+
# -------------------
|
|
563
|
+
# sorting routines for batched in normative parallel
|
|
564
|
+
# -------------------
|
|
565
|
+
|
|
566
|
+
|
|
567
|
+
def tryint(s):
|
|
568
|
+
"""
|
|
569
|
+
Try to convert a string to an integer
|
|
570
|
+
|
|
571
|
+
Basic usage::
|
|
572
|
+
|
|
573
|
+
tryint(s)
|
|
574
|
+
|
|
575
|
+
:param s: string to convert
|
|
576
|
+
"""
|
|
577
|
+
|
|
578
|
+
try:
|
|
579
|
+
return int(s)
|
|
580
|
+
except ValueError:
|
|
581
|
+
return s
|
|
582
|
+
|
|
583
|
+
|
|
584
|
+
def alphanum_key(s):
|
|
585
|
+
"""
|
|
586
|
+
Turn a string into a list of numbers
|
|
587
|
+
|
|
588
|
+
Basic usage::
|
|
589
|
+
|
|
590
|
+
alphanum_key(s)
|
|
591
|
+
|
|
592
|
+
:param s: string to convert
|
|
593
|
+
"""
|
|
594
|
+
return [tryint(c) for c in re.split('([0-9]+)', s)]
|
|
595
|
+
|
|
596
|
+
|
|
597
|
+
def sort_nicely(l):
|
|
598
|
+
"""
|
|
599
|
+
Sort a list of strings in a natural way
|
|
600
|
+
|
|
601
|
+
Basic usage::
|
|
602
|
+
|
|
603
|
+
sort_nicely(l)
|
|
604
|
+
|
|
605
|
+
:param l: list of strings to sort
|
|
606
|
+
"""
|
|
607
|
+
|
|
608
|
+
return sorted(l, key=alphanum_key)
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
# Third-party imports
|
|
2
|
+
import scipy.special as spp
|
|
3
|
+
from pytensor.gradient import grad_not_implemented
|
|
4
|
+
from pytensor.scalar.basic import BinaryScalarOp, upgrade_to_float
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
class KnuOp(BinaryScalarOp):
|
|
8
|
+
"""
|
|
9
|
+
Modified Bessel function of the second kind, pytensor wrapper for scipy.special.kv
|
|
10
|
+
"""
|
|
11
|
+
|
|
12
|
+
nfunc_spec = ("scipy.special.kv", 2, 1)
|
|
13
|
+
|
|
14
|
+
@staticmethod
|
|
15
|
+
def st_impl(p, x):
|
|
16
|
+
return spp.kv(p, x)
|
|
17
|
+
|
|
18
|
+
def impl(self, p, x):
|
|
19
|
+
return KnuOp.st_impl(p, x)
|
|
20
|
+
|
|
21
|
+
def grad(self, inputs, grads):
|
|
22
|
+
dp = 1e-16
|
|
23
|
+
(p, x) = inputs
|
|
24
|
+
(gz,) = grads
|
|
25
|
+
dfdp = (knuop(p + dp, x) - knuop(p - dp, x)) / (2 * dp)
|
|
26
|
+
return [gz * dfdp, gz * knupop(p, x)]
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
class KnuPrimeOp(BinaryScalarOp):
|
|
30
|
+
"""
|
|
31
|
+
Derivative of the modified Bessel function of the second kind.
|
|
32
|
+
"""
|
|
33
|
+
|
|
34
|
+
nfunc_spec = ("scipy.special.kvp", 2, 1)
|
|
35
|
+
|
|
36
|
+
@staticmethod
|
|
37
|
+
def st_impl(p, x):
|
|
38
|
+
return spp.kvp(p, x)
|
|
39
|
+
|
|
40
|
+
def impl(self, p, x):
|
|
41
|
+
return KnuPrimeOp.st_impl(p, x)
|
|
42
|
+
|
|
43
|
+
def grad(self, inputs, grads):
|
|
44
|
+
return [grad_not_implemented(self, 0, "p"), grad_not_implemented(self, 1, "x")]
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
knuop = KnuOp(upgrade_to_float, name="knuop")
|
|
48
|
+
knupop = KnuPrimeOp(upgrade_to_float, name="knupop")
|