Skip to content

Commit 5bf83ea

Browse files
committed
ENH: Added csvReader() utility
1 parent 6601b00 commit 5bf83ea

File tree

3 files changed

+116
-8
lines changed

3 files changed

+116
-8
lines changed

CHANGES

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5,45 +5,46 @@ Next release
55
* FIX: Fix split_filename behaviour when path has no file component (https://github.com/nipy/nipype/pull/1035)
66
* ENH: Updated FSL dtifit to include option for grad non-linearities (https://github.com/nipy/nipype/pull/1032)
77
* ENH: Updated Camino tracking interfaces, which can now use FSL bedpostx output.
8-
New options also include choice of tracker, interpolator, stepsize and
8+
New options also include choice of tracker, interpolator, stepsize and
99
curveinterval for angle threshold (https://github.com/nipy/nipype/pull/1029)
1010
* FIX: Interfaces redirecting X crashed if $DISPLAY not defined (https://github.com/nipy/nipype/pull/1027)
1111
* FIX: Bug crashed 'make api' (https://github.com/nipy/nipype/pull/1026)
1212
* ENH: Updated antsIntroduction to handle RA and RI registrations (https://github.com/nipy/nipype/pull/1009)
13-
* ENH: Updated N4BiasCorrection input spec to include weight image and spline order. Made
13+
* ENH: Updated N4BiasCorrection input spec to include weight image and spline order. Made
1414
argument formatting consistent. Cleaned ants.segmentation according to PEP8.
1515
(https://github.com/nipy/nipype/pull/990/files)
1616
* ENH: SPM12 Normalize interface (https://github.com/nipy/nipype/pull/986)
1717
* FIX: Utility interface test dir (https://github.com/nipy/nipype/pull/986)
1818
* FIX: IPython engine directory reset after crash (https://github.com/nipy/nipype/pull/987)
1919
* ENH: Resting state fMRI example with NiPy realignment and no SPM (https://github.com/nipy/nipype/pull/992)
20-
* FIX: Corrected Freesurfer SegStats _list_outputs to avoid error if summary_file is
20+
* FIX: Corrected Freesurfer SegStats _list_outputs to avoid error if summary_file is
2121
undefined (issue #994)(https://https://github.com/nipy/nipype/pull/996)
2222
* FIX: OpenfMRI support and FSL 5.0.7 changes (https://github.com/nipy/nipype/pull/1006)
2323
* FIX: Output prefix in SPM Normalize with modulation (https://github.com/nipy/nipype/pull/1023)
2424
* ENH: Usability improvements in cluster environments (https://github.com/nipy/nipype/pull/1025)
2525
* ENH: ANTs JointFusion() (https://github.com/nipy/nipype/pull/1042)
26+
* ENH: Added csvReader() utility
2627

2728
Release 0.10.0 (October 10, 2014)
2829
============
2930

3031
* ENH: New miscelaneous interfaces: SplitROIs (mapper), MergeROIs (reducer)
3132
to enable parallel processing of very large images.
3233
* ENH: Updated FSL interfaces: BEDPOSTX and XFibres, former interfaces are still
33-
available with the version suffix: BEDPOSTX4 and XFibres4. Added gpu
34+
available with the version suffix: BEDPOSTX4 and XFibres4. Added gpu
3435
versions of BEDPOSTX: BEDPOSTXGPU, BEDPOSTX5GPU, and BEDPOSTX4GPU
3536
* ENH: Added experimental support for MIPAV algorithms thorugh JIST plugins
3637
* ENH: New dipy interfaces: Denoise, Resample
3738
* ENH: New Freesurfer interfaces: Tkregister2 (for conversion of fsl style matrices to freesurfer format), MRIPretess
3839
* ENH: New FSL interfaces: WarpPoints, WarpPointsToStd, EpiReg, ProbTrackX2, WarpUtils, ConvertWarp
3940
* ENH: New miscelaneous interfaces: AddCSVRow, NormalizeProbabilityMapSet, AddNoise
4041
* ENH: New AFNI interfaces: Eval, Means, SVMTest, SVMTrain
41-
* ENH: FUGUE interface has been refactored to use the name_template system, 3 examples
42+
* ENH: FUGUE interface has been refactored to use the name_template system, 3 examples
4243
added to doctests, some bugs solved.
4344
* API: Interfaces to external packages are no longer available in the top-level
4445
``nipype`` namespace, and must be imported directly (e.g.
4546
``from nipype.interfaces import fsl``).
46-
* ENH: Support for elastix via a set of new interfaces: Registration, ApplyWarp,
47+
* ENH: Support for elastix via a set of new interfaces: Registration, ApplyWarp,
4748
AnalyzeWarp, PointsWarp, and EditTransform
4849
* ENH: New ANTs interface: ApplyTransformsToPoints, LaplacianThickness
4950
* ENH: New Diffusion Toolkit interface: TrackMerge
@@ -59,7 +60,7 @@ Release 0.10.0 (October 10, 2014)
5960
* ENH: New color mode for write_graph
6061
* ENH: You can now force MapNodes to be run serially
6162
* ENH: Added ANTS based openfmri workflow
62-
* ENH: MapNode now supports flattening of nested lists
63+
* ENH: MapNode now supports flattening of nested lists
6364
* ENH: Support for headless mode using Xvfb
6465
* ENH: nipype_display_crash has a debugging mode
6566
* FIX: MRTrix tracking algorithms were ignoring mask parameters.

nipype/interfaces/tests/test_utility.py

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
# vi: set ft=python sts=4 ts=4 sw=4 et:
33
import os
44
import shutil
5-
from tempfile import mkdtemp
5+
from tempfile import mkdtemp, mkstemp
66

77
import numpy as np
88
from nipype.testing import assert_equal, assert_true, assert_raises
@@ -138,3 +138,30 @@ def test_split():
138138
finally:
139139
os.chdir(origdir)
140140
shutil.rmtree(tempdir)
141+
142+
143+
def test_csvReader():
144+
header = "files,labels,erosion\n"
145+
lines = ["foo,hello,300.1\n",
146+
"bar,world,5\n",
147+
"baz,goodbye,0.3\n"]
148+
for x in range(2):
149+
fd, name = mkstemp(suffix=".csv")
150+
with open(name, 'w+b') as fid:
151+
reader = utility.CSVReader()
152+
if x % 2 == 0:
153+
fid.write(header)
154+
reader.inputs.header = True
155+
fid.writelines(lines)
156+
fid.flush()
157+
reader.inputs.in_file = name
158+
out = reader.run()
159+
if x % 2 == 0:
160+
yield assert_equal, out.outputs.files, ['foo', 'bar', 'baz']
161+
yield assert_equal, out.outputs.labels, ['hello', 'world', 'goodbye']
162+
yield assert_equal, out.outputs.erosion, ['300.1', '5', '0.3']
163+
else:
164+
yield assert_equal, out.outputs.column_0, ['foo', 'bar', 'baz']
165+
yield assert_equal, out.outputs.column_1, ['hello', 'world', 'goodbye']
166+
yield assert_equal, out.outputs.column_2, ['300.1', '5', '0.3']
167+
os.unlink(name)

nipype/interfaces/utility.py

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -479,3 +479,83 @@ def _run_interface(self, runtime):
479479
assert_equal(data1, data2)
480480

481481
return runtime
482+
483+
484+
class CSVReaderInputSpec(DynamicTraitedSpec, TraitedSpec):
485+
in_file = File(exists=True, mandatory=True, desc='Input comma-seperated value (CSV) file')
486+
header = traits.Bool(False, usedefault=True, desc='True if the first line is a column header')
487+
488+
489+
class CSVReader(BaseInterface):
490+
"""
491+
Examples
492+
--------
493+
494+
>>> reader = cv.CSVReader()
495+
>>> reader.inputs.in_file = 'noHeader.csv'
496+
>>> out = reader.run()
497+
>>> out.outputs.column_0 == ['foo', 'bar', 'baz'] # doctest: +SKIP
498+
True
499+
>>> out.outputs.column_1 == ['hello', 'world', 'goodbye'] # doctest: +SKIP
500+
True
501+
>>> out.outputs.column_2 == ['300.1', '5', '0.3'] # doctest: +SKIP
502+
True
503+
504+
>>> reader = cv.CSVReader()
505+
>>> reader.inputs.in_file = 'header.csv'
506+
>>> reader.inputs.header = True
507+
>>> out = reader.run()
508+
>>> out.outputs.files == ['foo', 'bar', 'baz'] # doctest: +SKIP
509+
True
510+
>>> out.outputs.labels == ['hello', 'world', 'goodbye'] # doctest: +SKIP
511+
True
512+
>>> out.outputs.erosion == ['300.1', '5', '0.3'] # doctest: +SKIP
513+
True
514+
515+
"""
516+
input_spec = CSVReaderInputSpec
517+
output_spec = DynamicTraitedSpec
518+
_always_run = True
519+
520+
def _append_entry(self, outputs, entry):
521+
for key, value in zip(self._outfields, entry):
522+
outputs[key].append(value)
523+
return outputs
524+
525+
def _parse_line(self, line):
526+
line = line.replace('\n', '')
527+
entry = [x.strip() for x in line.split(',')]
528+
return entry
529+
530+
def _get_outfields(self):
531+
with open(self.inputs.in_file, 'r') as fid:
532+
entry = self._parse_line(fid.readline())
533+
if self.inputs.header:
534+
self._outfields = tuple(entry)
535+
else:
536+
self._outfields = tuple(['column_' + str(x) for x in range(len(entry))])
537+
return self._outfields
538+
539+
def _run_interface(self, runtime):
540+
self._get_outfields()
541+
return runtime
542+
543+
def _outputs(self):
544+
return self._add_output_traits(super(CSVReader, self)._outputs())
545+
546+
def _add_output_traits(self, base):
547+
return add_traits(base, self._get_outfields())
548+
549+
def _list_outputs(self):
550+
outputs = self.output_spec().get()
551+
isHeader = True
552+
for key in self._outfields:
553+
outputs[key] = [] # initialize outfields
554+
with open(self.inputs.in_file, 'r') as fid:
555+
for line in fid.readlines():
556+
if self.inputs.header and isHeader: # skip header line
557+
isHeader = False
558+
continue
559+
entry = self._parse_line(line)
560+
outputs = self._append_entry(outputs, entry)
561+
return outputs

0 commit comments

Comments
 (0)