Skip to content

Commit 80fcc91

Browse files
committed
base code for new AddCSVRow interface
1 parent 504858e commit 80fcc91

File tree

1 file changed

+136
-0
lines changed

1 file changed

+136
-0
lines changed

nipype/algorithms/misc.py

Lines changed: 136 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1147,6 +1147,142 @@ def _list_outputs(self):
11471147
return outputs
11481148

11491149

1150+
class AddCSVRowInputSpec(TraitedSpec):
1151+
in_file = traits.File(mandatory=True, desc='Input comma-separated value (CSV) files')
1152+
cols = traits.Int(desc='Number of columns')
1153+
field_headings = traits.List(traits.Str(), mandatory=True,
1154+
desc='Heading list of available field to be added.')
1155+
1156+
float_trait = traits.Float( 0.0, argstr='%.5f' )
1157+
int_trait = traits.Int( 0, argstr='%d' )
1158+
str_trait = traits.Str( '', argstr='"%s"')
1159+
row_trait = traits.Either( int_trait, float_trait, str_trait )
1160+
new_fields = traits.List( row_trait, mandatory=True, desc='List of new values in row')
1161+
1162+
class AddCSVRowOutputSpec(TraitedSpec):
1163+
csv_file = File(desc='Output CSV file containing rows ')
1164+
1165+
1166+
class AddCSVRow(BaseInterface):
1167+
"""
1168+
Short interface to add an extra row to a text file
1169+
1170+
Example
1171+
-------
1172+
1173+
>>> import nipype.algorithms.misc as misc
1174+
>>> addrow = misc.AddCSVRow()
1175+
>>> addrow.inputs.in_file = 'degree.csv'
1176+
>>> addrow.inputs.field_headings = [ 'id', 'group', 'age', 'degree' ]
1177+
>>> addrow.inputs.new_fields = [ 'S400', 'male', '25', '10.5' ]
1178+
>>> addrow.run() # doctest: +SKIP
1179+
"""
1180+
input_spec = AddCSVRowInputSpec
1181+
output_spec = AddCSVRowOutputSpec
1182+
1183+
def _run_interface(self, runtime):
1184+
cols = 0
1185+
headings = []
1186+
1187+
if not isdefined( self.inputs.cols ) and not isdefined( self.inputs.field_headings ):
1188+
iflogger.error( 'Either number of cols or field headings is required' )
1189+
1190+
if isdefined( self.inputs.cols ) and isdefined( self.inputs.field_headings ):
1191+
if( len( self.inputs.field_headings ) != self.inputs.cols ):
1192+
iflogger.error( 'Number of cols and length of field headings list should match' )
1193+
else:
1194+
cols = self.inputs.cols
1195+
headings = self.inputs.field_headings
1196+
1197+
if isdefined( self.inputs.cols ) and not isdefined( self.inputs.field_headings ):
1198+
cols = self.inputs.cols
1199+
iflogger.warn( 'No column headers were set.')
1200+
1201+
if not isdefined( self.inputs.cols ) and isdefined( self.inputs.field_headings ):
1202+
cols = len( self.inputs.field_headings )
1203+
1204+
if cols == 0:
1205+
iflogger.error( 'Number of cols and length of field headings must be > 0' )
1206+
1207+
if len( self.inputs.new_fields ) != cols:
1208+
iflogger.error( 'Wrong length of fields, does not match number of cols' )
1209+
1210+
with open(self.inputs.in_file, 'r+') as in_file:
1211+
lines = in_file.readlines()
1212+
1213+
if len(headings)>0 and (len(lines) == 0 or lines[0] == ''):
1214+
hdr = [ '"%s"' % h for h in self.inputs.field_headings ]
1215+
hdrstr = ",".join(hdr)
1216+
lines.insert( 0, hdrstr )
1217+
1218+
print self.inputs.new_fields.items()
1219+
1220+
metadata = dict(argstr=lambda t: t is not None)
1221+
for name, spec in sorted(self.inputs.traits(**metadata).items()):
1222+
print name
1223+
value = getattr(self.inputs, name)
1224+
if not value is None:
1225+
print value
1226+
#arg = self._format_row( name, spec, value )
1227+
1228+
1229+
1230+
#newrow = ",".join( self.inputs.new_fields )
1231+
#lines.append( newrow )
1232+
#in_file.writelines( lines )
1233+
1234+
return runtime
1235+
1236+
1237+
1238+
def _format_row(self, name, trait_spec, value):
1239+
"""A helper function for _run_interface
1240+
"""
1241+
argstr = trait_spec.argstr
1242+
iflogger.debug('%s_%s' % (name, str(value)))
1243+
if trait_spec.is_trait_type(traits.Bool) and "%" not in argstr:
1244+
if value:
1245+
# Boolean options have no format string. Just append options
1246+
# if True.
1247+
return argstr
1248+
else:
1249+
return None
1250+
# traits.Either turns into traits.TraitCompound and does not have any
1251+
# inner_traits
1252+
elif trait_spec.is_trait_type(traits.List) \
1253+
or (trait_spec.is_trait_type(traits.TraitCompound)
1254+
and isinstance(value, list)):
1255+
# This is a bit simple-minded at present, and should be
1256+
# construed as the default. If more sophisticated behavior
1257+
# is needed, it can be accomplished with metadata (e.g.
1258+
# format string for list member str'ification, specifying
1259+
# the separator, etc.)
1260+
1261+
# Depending on whether we stick with traitlets, and whether or
1262+
# not we beef up traitlets.List, we may want to put some
1263+
# type-checking code here as well
1264+
sep = trait_spec.sep
1265+
if sep is None:
1266+
sep = ' '
1267+
if argstr.endswith('...'):
1268+
1269+
# repeatable option
1270+
# --id %d... will expand to
1271+
# --id 1 --id 2 --id 3 etc.,.
1272+
argstr = argstr.replace('...', '')
1273+
return sep.join([argstr % elt for elt in value])
1274+
else:
1275+
return argstr % sep.join(str(elt) for elt in value)
1276+
else:
1277+
# Append options using format string.
1278+
return argstr % value
1279+
1280+
def _list_outputs(self):
1281+
outputs = self.output_spec().get()
1282+
outputs['csv_file'] = self.inputs.in_file
1283+
return outputs
1284+
1285+
11501286
class CalculateNormalizedMomentsInputSpec(TraitedSpec):
11511287
timeseries_file = File(
11521288
exists=True, mandatory=True,

0 commit comments

Comments
 (0)