Skip to content

Commit 234a46e

Browse files
authored
Merge pull request #57 from smoia/feat/io
Improve extension handling, and make `.tsv.gz` the default extension
2 parents 9af86c5 + 09a74bd commit 234a46e

7 files changed

Lines changed: 63 additions & 45 deletions

File tree

nigsp/blocks.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -72,15 +72,15 @@ def export_metric(scgraph, outext, outprefix):
7272
except ImportError:
7373
LGR.warning(
7474
"The necessary library for nifti export (nibabel) "
75-
"was not found. Exporting metrics in CSV format instead."
75+
"was not found. Exporting metrics in TSV format instead."
7676
)
77-
outext = ".csv"
77+
outext = ".tsv.gz"
7878
if scgraph.img is None:
7979
LGR.warning(
8080
"A necessary atlas nifti image was not found. "
81-
"Exporting metrics in CSV format instead."
81+
"Exporting metrics in TSV format instead."
8282
)
83-
outext = ".csv"
83+
outext = ".tsv.gz"
8484

8585
if scgraph.sdi is not None:
8686
if outext in io.EXT_NIFTI:
@@ -127,7 +127,7 @@ def plot_metric(scgraph, outprefix, atlas=None, thr=None):
127127
atlas_plot = atlas
128128
except AttributeError:
129129
LGR.warning(
130-
"The provided atlas is not in a format supported for " "markerplots."
130+
"The provided atlas is not in a format supported for markerplots."
131131
)
132132
atlas_plot = None
133133

nigsp/io.py

Lines changed: 45 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,12 @@
1212
List of supported nifti file extensions, in lower case.
1313
EXT_XLS : list
1414
List of supported XLS-like file extensions, in lower case.
15-
LGR
16-
Logger
15+
EXT_ALL : list
16+
All supported file extensions, in lower case.
17+
EXT_DICT : dictionary
18+
Dictionary associating values to extension lists
19+
LOADMAT_DICT : dictionary
20+
Dictionary assocting the same values in EXT_DICT to loading functions.
1721
"""
1822

1923
import logging
@@ -25,9 +29,9 @@
2529
from nigsp.utils import change_var_type
2630

2731
EXT_1D = [".txt", ".csv", ".tsv", ".1d", ".par", ".tsv.gz", ".csv.gz"]
28-
EXT_XLS = [".xls"]
2932
EXT_MAT = [".mat"]
3033
EXT_NIFTI = [".nii", ".nii.gz"]
34+
EXT_XLS = [".xls"]
3135
EXT_ALL = EXT_1D + EXT_XLS + EXT_MAT + EXT_NIFTI
3236

3337
EXT_DICT = {"1D": EXT_1D, "xls": EXT_XLS, "mat": EXT_MAT, "nifti": EXT_NIFTI}
@@ -84,7 +88,7 @@ def check_ext(all_ext, fname, scan=False, remove=False):
8488
if has_ext:
8589
obj_return += [fname[: -len(ext)], ext] # case insensitive solution
8690
else:
87-
obj_return += [fname, ""]
91+
obj_return += [fname, None]
8892
else:
8993
obj_return += [fname]
9094

@@ -404,12 +408,9 @@ def export_nifti(data, img, fname):
404408
"Please see install instructions."
405409
)
406410

407-
for e in EXT_NIFTI:
408-
has_ext, fname, ext = check_ext(e, fname, remove=True)
409-
if has_ext:
410-
break
411+
has_ext, fname, ext = check_ext(EXT_NIFTI, fname, remove=True)
411412

412-
if ext == "":
413+
if ext is None:
413414
ext = ".nii.gz"
414415

415416
LGR.info(f"Exporting nifti data into {fname}{ext}.")
@@ -437,6 +438,21 @@ def export_txt(data, fname, ext=None):
437438
0
438439
On a successful run
439440
"""
441+
has_ext, fname, ext_check = check_ext(EXT_ALL, fname, remove=True)
442+
443+
if has_ext:
444+
if ext is not None:
445+
LGR.warning(
446+
f"Specified filename {fname}{ext_check} has an extension, but the "
447+
f"extension {ext} was specified. Forcing specified extension."
448+
)
449+
else:
450+
ext = ext_check
451+
else:
452+
if ext is None:
453+
LGR.warning("Extension not specified. Forcing export in TSV.GZ format.")
454+
ext = ".tsv.gz"
455+
440456
if ext.lower() in [".csv", ".csv.gz", "", None]:
441457
delimiter = ","
442458
elif ext.lower() in [".tsv", ".tsv.gz"]:
@@ -494,22 +510,23 @@ def export_mtx(data, fname, ext=None):
494510
0
495511
On a successful run
496512
"""
497-
if ext is None:
498-
# Check if extension was provided in fname.
499-
for e in EXT_ALL:
500-
has_ext, fname, ext = check_ext(e, fname, remove=True)
501-
if has_ext:
502-
break
503-
elif ext.lower() not in EXT_ALL:
504-
# Check if extension is supported.
505-
ext = None
513+
has_ext, fname, ext_check = check_ext(EXT_ALL, fname, remove=True)
514+
515+
if has_ext:
516+
if ext is None:
517+
ext = ext_check
518+
else:
519+
LGR.warning(
520+
f"Specified filename {fname}{ext_check} has an extension, but the "
521+
f"extension {ext} was specified. Forcing specified extension."
522+
)
506523

507524
if ext in [None, ""]:
508525
LGR.warning(
509526
"Extension not specified, or specified extension not "
510-
"supported. Forcing export in CSV format."
527+
"supported. Forcing export in TSV.GZ format."
511528
)
512-
ext = ".csv"
529+
ext = ".tsv.gz"
513530
elif ext.lower() in EXT_NIFTI:
514531
LGR.warning("Found nifti extension, exporting data in .1D instead")
515532
ext = ".1D"
@@ -520,7 +537,7 @@ def export_mtx(data, fname, ext=None):
520537
import scipy
521538
except ImportError:
522539
raise ImportError(
523-
"To export .mat files, scipy is required. " "Please install it."
540+
"To export .mat files, scipy is required. Please install it."
524541
)
525542
scipy.io.savemat(f"{fname}{ext}", {"data": data})
526543
elif ext.lower() in EXT_XLS:
@@ -529,13 +546,18 @@ def export_mtx(data, fname, ext=None):
529546
export_txt(data, fname, ext)
530547
else:
531548
raise BrokenPipeError(
532-
f"This should not have happened: {ext} was the " "selected extension."
549+
f"This should not have happened: {ext} was the selected extension."
533550
)
534551

535552
return 0
536553

537554

538-
LOADMAT_DICT = {"1D": load_txt, "xls": load_xls, "mat": load_mat}
555+
LOADMAT_DICT = {
556+
"1D": load_txt,
557+
"xls": load_xls,
558+
"mat": load_mat,
559+
"nifti": load_nifti_get_mask,
560+
}
539561

540562

541563
"""

nigsp/operations/nifti.py

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -64,9 +64,7 @@ def mat_to_vol(data, shape=None, asdata=None):
6464
)
6565
shape = asdata.shape
6666
elif shape is None:
67-
raise ValueError(
68-
"Both shape and asdata are empty. " "Must specify at least one"
69-
)
67+
raise ValueError("Both shape and asdata are empty. Must specify at least one")
7068

7169
LGR.info(f"Reshape {data.ndim}D matrix into volume with shape {shape}.")
7270
return data.reshape(shape, order="F")
@@ -147,9 +145,7 @@ def unmask(data, mask, shape=None, asdata=None):
147145
)
148146
shape = asdata.shape
149147
elif shape is None:
150-
raise ValueError(
151-
"Both shape and asdata are empty. " "Must specify at least one."
152-
)
148+
raise ValueError("Both shape and asdata are empty. Must specify at least one.")
153149

154150
if shape[: mask.ndim] != mask.shape:
155151
raise ValueError(
@@ -205,7 +201,7 @@ def apply_atlas(data, atlas, mask=None):
205201

206202
if atlas.ndim > 3:
207203
raise NotImplementedError(
208-
f"Files with {atlas.ndim} dimensions are not " "supported as atlases."
204+
f"Files with {atlas.ndim} dimensions are not supported as atlases."
209205
)
210206
if data.shape[: mask.ndim] != mask.shape:
211207
raise ValueError(

nigsp/operations/timeseries.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ def normalise_ts(timeseries, globally=False):
4141
"""
4242
if timeseries.ndim < 2 or (timeseries.ndim == 2 and timeseries.shape[1] == 1):
4343
LGR.warning(
44-
"Given timeseries seems to be a single timepoint. " "Returning it as is."
44+
"Given timeseries seems to be a single timepoint. Returning it as is."
4545
)
4646
return timeseries
4747

@@ -81,7 +81,7 @@ def spc_ts(timeseries, globally=False):
8181
"""
8282
if timeseries.ndim < 2 or (timeseries.ndim == 2 and timeseries.shape[1] == 1):
8383
LGR.warning(
84-
"Given timeseries seems to be a single timepoint. " "Returning it as is."
84+
"Given timeseries seems to be a single timepoint. Returning it as is."
8585
)
8686
return timeseries
8787

@@ -119,7 +119,7 @@ def demean_ts(timeseries, globally=False):
119119
"""
120120
if timeseries.ndim < 2 or (timeseries.ndim == 2 and timeseries.shape[1] == 1):
121121
LGR.warning(
122-
"Given timeseries seems to be a single timepoint. " "Returning it as is."
122+
"Given timeseries seems to be a single timepoint. Returning it as is."
123123
)
124124
return timeseries
125125

@@ -157,7 +157,7 @@ def rescale_ts(timeseries, vmin=0, vmax=1, globally=False):
157157
"""
158158
if timeseries.ndim < 2 or (timeseries.ndim == 2 and timeseries.shape[1] == 1):
159159
LGR.warning(
160-
"Given timeseries seems to be a single timepoint. " "Returning it as is."
160+
"Given timeseries seems to be a single timepoint. Returning it as is."
161161
)
162162
return timeseries
163163

nigsp/tests/test_blocks.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -70,14 +70,14 @@ def test_export_metrics_nifti(sc_mtx, atlas, sdi, testdir):
7070
scgraph = SCGraph(mtx, ts, atlas=atlas_in, sdi=sdi_in)
7171
blocks.export_metric(scgraph, ".nii.gz", join(testdir, "molly_"))
7272

73-
assert isfile(join(testdir, "molly_sdi.csv"))
73+
assert isfile(join(testdir, "molly_sdi.tsv.gz"))
7474

7575
sys.modules["nibabel"] = None
7676
scgraph = SCGraph(mtx, ts, atlas=atlas_in, img=img, sdi=sdi_in)
7777
blocks.export_metric(scgraph, ".nii.gz", join(testdir, "molly_"))
7878
sys.modules["nibabel"] = nibabel
7979

80-
assert isfile(join(testdir, "molly_sdi.csv"))
80+
assert isfile(join(testdir, "molly_sdi.tsv.gz"))
8181
shutil.rmtree(testdir)
8282
remove(sc_mtx)
8383
remove(atlas)

nigsp/tests/test_io.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ def test_check_ext():
4848

4949
assert has_ext is False
5050
assert fname_out == fname
51-
assert ext_out == ""
51+
assert ext_out == None
5252

5353

5454
@mark.parametrize("data", [(rand(3, 4)), (rand(3, 4, 1)), (rand(3, 1, 4))])
@@ -135,7 +135,7 @@ def test_export_nifti(atlas):
135135
(".1D", ".1D"),
136136
(".csv", ".csv"),
137137
(".tsv", ".tsv"),
138-
("", ".csv"),
138+
("", ".tsv.gz"),
139139
(".mat", ".mat"),
140140
],
141141
)
@@ -147,7 +147,7 @@ def test_export_mtx(ext_in, ext_out):
147147

148148
if ext_out in [".csv"]:
149149
data_in = genfromtxt(f"serenity{ext_out}", delimiter=",")
150-
if ext_out in [".tsv", ".1D"]:
150+
if ext_out in [".tsv", ".tsv.gz", ".1D"]:
151151
data_in = genfromtxt(f"serenity{ext_out}")
152152

153153
if ext_out in [".mat"]:

nigsp/workflow.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -309,7 +309,7 @@ def nigsp(
309309
atlas_is["1D"] or atlas_is["mat"] or atlas_is["xls"] or atlas_is["nifti"]
310310
) is False:
311311
raise NotImplementedError(
312-
f"Input file {atlasname} is not of a " "supported type."
312+
f"Input file {atlasname} is not of a supported type."
313313
)
314314
elif atlas_is["1D"]:
315315
atlas = io.load_txt(atlasname)

0 commit comments

Comments
 (0)