|
26 | 26 | import itertools
|
27 | 27 | import scipy.stats as stats
|
28 | 28 |
|
29 |
| -from .. import logging |
| 29 | +from nipype import logging |
30 | 30 |
|
31 | 31 | import warnings
|
32 | 32 |
|
33 | 33 | import metrics as nam
|
34 | 34 | from ..interfaces.base import (BaseInterface, traits, TraitedSpec, File,
|
35 | 35 | InputMultiPath, OutputMultiPath,
|
36 |
| - BaseInterfaceInputSpec, isdefined) |
37 |
| -from ..utils.filemanip import fname_presuffix, split_filename |
| 36 | + BaseInterfaceInputSpec, isdefined, |
| 37 | + DynamicTraitedSpec ) |
| 38 | +from nipype.utils.filemanip import fname_presuffix, split_filename |
38 | 39 | iflogger = logging.getLogger('interface')
|
39 | 40 |
|
40 | 41 |
|
@@ -782,6 +783,121 @@ def _list_outputs(self):
|
782 | 783 | return outputs
|
783 | 784 |
|
784 | 785 |
|
| 786 | +class AddCSVRowInputSpec(DynamicTraitedSpec, BaseInterfaceInputSpec): |
| 787 | + in_file = traits.File(mandatory=True, desc='Input comma-separated value (CSV) files') |
| 788 | + _outputs = traits.Dict( traits.Any, value={}, usedefault=True ) |
| 789 | + |
| 790 | + def __setattr__(self, key, value): |
| 791 | + if key not in self.copyable_trait_names(): |
| 792 | + if not isdefined(value): |
| 793 | + super(AddCSVRowInputSpec, self).__setattr__(key, value) |
| 794 | + self._outputs[key] = value |
| 795 | + else: |
| 796 | + if key in self._outputs: |
| 797 | + self._outputs[key] = value |
| 798 | + super(AddCSVRowInputSpec, self).__setattr__(key, value) |
| 799 | + |
| 800 | +class AddCSVRowOutputSpec(TraitedSpec): |
| 801 | + csv_file = File(desc='Output CSV file containing rows ') |
| 802 | + |
| 803 | +class AddCSVRow(BaseInterface): |
| 804 | + """Simple interface to add an extra row to a csv file |
| 805 | +
|
| 806 | + .. note:: Requires `pandas <http://pandas.pydata.org/>`_ |
| 807 | +
|
| 808 | + .. warning:: Multi-platform thread-safe execution is possible with |
| 809 | + `lockfile <https://pythonhosted.org/lockfile/lockfile.html>`_. Please recall that (1) |
| 810 | + this module is alpha software; and (2) it should be installed for thread-safe writing. |
| 811 | + If lockfile is not installed, then the interface is not thread-safe. |
| 812 | +
|
| 813 | +
|
| 814 | + Example |
| 815 | + ------- |
| 816 | +
|
| 817 | + >>> import nipype.algorithms.misc as misc |
| 818 | + >>> addrow = misc.AddCSVRow() |
| 819 | + >>> addrow.inputs.in_file = 'scores.csv' |
| 820 | + >>> addrow.inputs.si = 0.74 |
| 821 | + >>> addrow.inputs.di = 0.93 |
| 822 | + >>> addrow.subject_id = 'S400' |
| 823 | + >>> addrow.inputs.list_of_values = [ 0.4, 0.7, 0.3 ] |
| 824 | + >>> addrow.run() # doctest: +SKIP |
| 825 | + """ |
| 826 | + input_spec = AddCSVRowInputSpec |
| 827 | + output_spec = AddCSVRowOutputSpec |
| 828 | + |
| 829 | + def __init__(self, infields=None, force_run=True, **kwargs): |
| 830 | + super(AddCSVRow, self).__init__(**kwargs) |
| 831 | + undefined_traits = {} |
| 832 | + self._infields = infields |
| 833 | + self._have_lock = False |
| 834 | + self._lock = None |
| 835 | + |
| 836 | + if infields: |
| 837 | + for key in infields: |
| 838 | + self.inputs.add_trait(key, traits.Any) |
| 839 | + self.inputs._outputs[key] = Undefined |
| 840 | + undefined_traits[key] = Undefined |
| 841 | + self.inputs.trait_set(trait_change_notify=False, **undefined_traits) |
| 842 | + |
| 843 | + if force_run: |
| 844 | + self._always_run = True |
| 845 | + |
| 846 | + def _run_interface(self, runtime): |
| 847 | + try: |
| 848 | + import pandas as pd |
| 849 | + except ImportError: |
| 850 | + raise ImportError('This interface requires pandas (http://pandas.pydata.org/) to run.') |
| 851 | + |
| 852 | + try: |
| 853 | + import lockfile as pl |
| 854 | + self._have_lock = True |
| 855 | + except ImportError: |
| 856 | + import warnings |
| 857 | + warnings.warn(('Python module lockfile was not found: AddCSVRow will not be thread-safe ' |
| 858 | + 'in multi-processor execution')) |
| 859 | + |
| 860 | + input_dict = {} |
| 861 | + for key, val in self.inputs._outputs.items(): |
| 862 | + # expand lists to several columns |
| 863 | + if isinstance(val, list): |
| 864 | + for i,v in enumerate(val): |
| 865 | + input_dict['%s_%d' % (key,i)]=v |
| 866 | + else: |
| 867 | + input_dict[key] = val |
| 868 | + |
| 869 | + df = pd.DataFrame([input_dict]) |
| 870 | + |
| 871 | + if self._have_lock: |
| 872 | + self._lock = pl.FileLock(self.inputs.in_file) |
| 873 | + |
| 874 | + # Acquire lock |
| 875 | + self._lock.acquire() |
| 876 | + |
| 877 | + if op.exists(self.inputs.in_file): |
| 878 | + formerdf = pd.read_csv(self.inputs.in_file, index_col=0) |
| 879 | + df = pd.concat([formerdf, df], ignore_index=True ) |
| 880 | + |
| 881 | + with open(self.inputs.in_file, 'w') as f: |
| 882 | + df.to_csv(f) |
| 883 | + |
| 884 | + if self._have_lock: |
| 885 | + self._lock.release() |
| 886 | + |
| 887 | + return runtime |
| 888 | + |
| 889 | + def _list_outputs(self): |
| 890 | + outputs = self.output_spec().get() |
| 891 | + outputs['csv_file'] = self.inputs.in_file |
| 892 | + return outputs |
| 893 | + |
| 894 | + def _outputs(self): |
| 895 | + return self._add_output_traits(super(AddCSVRow, self)._outputs()) |
| 896 | + |
| 897 | + def _add_output_traits(self, base): |
| 898 | + return base |
| 899 | + |
| 900 | + |
785 | 901 | class CalculateNormalizedMomentsInputSpec(TraitedSpec):
|
786 | 902 | timeseries_file = File(
|
787 | 903 | exists=True, mandatory=True,
|
|
0 commit comments