예제 #1
0
 def _init_step_ids(self):
     self._step_ids = OrderedDict()
     for i, step in enumerate(self._steps):
         step_id = step.name  ##"%d_%s" % (i, step.name)
         self._step_ids[step_id] = step
예제 #2
0
class Analysis(six.with_metaclass(AnalysisMetaClass, object)):
    # XXX the metaclass automatically registers the Analysis class in the
    # AnalysisFactory and intializes the param_template_map

    def __init__(self, study):
        self._init_steps()
        self._init_step_ids()
        self.study = study
        self.pipeline = None
        self.parameters = None

    def _init_steps(self):
        raise NotImplementedError("Analysis is an Abstract class.") 

    def _init_step_ids(self):
        self._step_ids = OrderedDict()
        for i, step in enumerate(self._steps):
            step_id = step.name  ##"%d_%s" % (i, step.name)
            self._step_ids[step_id] = step

    def step_from_id(self, step_id):
        return self._step_ids.get(step_id)

    def import_data(self, subject):
        raise NotImplementedError("Analysis is an Abstract class. import_data must be redefined.")

    def set_parameters(self, subject):
        raise NotImplementedError("Analysis is an Abstract class. set_parameters must be redefined.")

    def propagate_parameters(self):
        raise NotImplementedError("Analysis is an Abstract class. propagate_parameter must be redefined.") 

    def list_input_parameters_with_existing_files(self):
        raise NotImplementedError("Analysis is an Abstract class. list_input_parameters_with_existing_files must be redefined.")

    def list_output_parameters_with_existing_files(self):
        raise NotImplementedError("Analysis is an Abstract class. list_output_parameters_with_existing_files must be redefined.")

    def has_some_results(self, step_ids=None):
        raise NotImplementedError("Analysis is an Abstract class. has_some_results must be redefined.")

    def has_all_results(self, step_ids=None):
        raise NotImplementedError("Analysis is an Abstract class. has_all_results must be redefined.")

    def existing_results(self, step_ids=None):
        raise NotImplementedError("Analysis is an Abstract class. existing_results must be redefined.")

    def clear_results(self, step_ids=None):
        to_remove = self.existing_results(step_ids)
        for filename in to_remove:
            filenames = self._files_for_format(filename)
            for f in filenames:
                if os.path.isfile(f):
                    os.remove(f)
                elif os.path.isdir(f):
                    shutil.rmtree(f)

    def _files_for_format(self, filename):
        ext_map = {
            'ima': ['ima', 'dim'],
            'img': ['img', 'hdr'],
            'arg': ['arg', 'data'],
        }
        ext_pos = filename.rfind('.')
        if ext_pos < 0:
            return [filename, filename + '.minf']
        ext = filename[ext_pos + 1:]
        exts = ext_map.get(ext, [ext])
        fname_base = filename[:ext_pos + 1]
        return [fname_base + ext for ext in exts] + [filename + '.minf']

    def convert_from_formats(self, old_volumes_format, old_meshes_format):
        # TODO: use aims/somaio IO system for formats extensions
        exts = [['.nii'], ['.nii.gz'], ['.img', '.hdr'], ['.ima', '.dim'],
                ['.dcm'], ['.mnc'],
                ['.gii'], ['.mesh'], ['.ply']]
        vol_formats = ['.nii', '.nii.gz', '.img', '.ima', '.dcm', '.mnc']
        mesh_formats = ['.gii', '.mesh', '.ply']

        def _convert_data(old_name, new_name):
            print('converting:', old_name, 'to:', new_name)
            data = aims.read(old_name)
            aims.write(data, new_name)

        def _remove_data(name):
            for fexts in exts:
                for ext in fexts:
                    if name.endswith(ext):
                        basename =  name[:-len(ext)]
                        real_exts = fexts + [fexts[0] + '.minf']
                        for cext in real_exts:
                            filename = basename + cext
                            if os.path.isdir(filename):
                                print('rmtree', filename)
                                shutil.rmtree(filename)
                            elif os.path.exists(filename):
                                print('rm', filename)
                                os.unlink(filename)

        def _look_for_other_formats(value, new_value):
            old_format = [fext[0] for fext in exts
                          if value.endswith(fext[0])]
            if len(old_format) == 0:
                return value
            old_format = old_format[0]
            if old_format in vol_formats:
                dtype = 0
            elif old_format in mesh_formats:
                dtype = 1
            else:
                return value
            typed_formats = [vol_formats, mesh_formats]

            old_base = value[:-len(old_format)]
            for fexts in exts:
                if not fexts[0] in typed_formats[dtype]:
                    continue
                if not isinstance(new_value, basestring) \
                        or not new_value.endswith(fexts[0]):
                    for ext in fexts:
                        new_old_value = old_base + ext
                        if not os.path.exists(new_old_value):
                            # not OK
                            break
                    else:
                        # found matching format
                        return old_base + fexts[0]
            return value

        print('convert analysis', self.subject, 'from formats:',
              old_volumes_format, old_meshes_format, 'to:',
              self.study.volumes_format, self.study.meshes_format)
        #if old_volumes_format == self.study.volumes_format \
                #and old_meshes_format == self.study.meshes_format:
            #print('    nothing to do.')
            #return
        old_params = self.parameters
        # force re-running FOM
        self.set_parameters(self.subject)
        todo = [(old_params, self.parameters)]
        while todo:
            old_dict, new_dict = todo.pop(0)
            old_state = old_dict.get('state', {})
            new_state = new_dict.get('state', {})
            for key, value in six.iteritems(old_state):
                if isinstance(value, basestring):
                    new_value = new_state.get(key)
                    if not os.path.exists(value) \
                            and (not isinstance(new_value, basestring)
                                 or not os.path.exists(new_value)):
                        value = _look_for_other_formats(value, new_value)
                    if os.path.exists(value):
                        if new_value not in ('', None, traits.Undefined) \
                                and new_value != value:
                            _convert_data(value, new_value)
                        if new_value != value:
                            _remove_data(value)
            old_nodes = old_dict.get('nodes', {})
            new_nodes = new_dict.get('nodes', {})
            if old_nodes:
                todo += [(node, new_nodes.get(key, {}))
                         for key, node in six.iteritems(old_nodes)]