Source code for soma.aims.graph_comparison

# -*- coding: utf-8 -*-
#  This software and supporting documentation are distributed by
#      Institut Federatif de Recherche 49
#      CEA/NeuroSpin, Batiment 145,
#      91191 Gif-sur-Yvette cedex
#      France
#
# This software is governed by the CeCILL-B license under
# French law and abiding by the rules of distribution of free software.
# You can  use, modify and/or redistribute the software under the
# terms of the CeCILL-B license as circulated by CEA, CNRS
# and INRIA at the following URL "http://www.cecill.info".
#
# As a counterpart to the access to the source code and  rights to copy,
# modify and redistribute granted by the license, users are provided only
# with a limited warranty  and the software's author,  the holder of the
# economic rights,  and the successive licensors  have only  limited
# liability.
#
# In this respect, the user's attention is drawn to the risks associated
# with loading,  using,  modifying and/or developing or reproducing the
# software by the user in light of its specific status of free software,
# that may mean  that it is complicated to manipulate,  and  that  also
# therefore means  that it is reserved for developers  and  experienced
# professionals having in-depth computer knowledge. Users are therefore
# encouraged to load and test the software's suitability as regards their
# requirements in conditions enabling the security of their systems and/or
# data to be ensured and,  more generally, to use and operate it in the
# same conditions as regards security.
#
# The fact that you are presently reading this means that you have had
# knowledge of the CeCILL-B license and that you accept its terms.

from __future__ import print_function

from __future__ import absolute_import
from soma import aims
import six
import sys


rel_flx_max_diff = 1e-4
''' max accepted relative difference of float numbers
'''

[docs]def same_graphs(ref_graph, test_graph, verbose=False): ''' Compare two graphs and return if they are identical. This function is useful for testing and validation purposes. Graphs structure are compared, and vertices / edges attributes. AIMS objects inside attributes are not compared (meshes, bucket, volumes in sulci graphs for instance) Parameters ---------- ref_graph: string or Graph object reference graph to be compared. A filename may be passed here: in this case the graph is read using aims.read() function. test_graph: string or Graph object test graph to be compared. A filename may be passed here: in this case the graph is read using aims.read() function. verbose: bool (optional, default: False) if True, messages are print on the standard output during comparison. Returns ------- True if ref and test graphs are identical, or False otherwise. ''' if isinstance(ref_graph, six.string_types): ref_graph = aims.read(ref_graph) if isinstance(test_graph, six.string_types): test_graph = aims.read(test_graph) ref_vertices = _build_vertice_dictionary(ref_graph) test_vertices = _build_vertice_dictionary(test_graph) if verbose: print("Compare vertices:") if not _same_dictionary(ref_vertices, test_vertices, _same_vertice, verbose): if verbose: print(" differences in vertices") return False ref_edges = _build_edge_dictionary(ref_graph) test_edges = _build_edge_dictionary(test_graph) if verbose: print("Compare edges:") if not _same_dictionary(ref_edges, test_edges, _same_edge, verbose): if verbose: print(" differences in edges") return False return True
def _build_vertice_dictionary(graph): vertice_dict = {} for vertice in graph.vertices(): vertice_dict[vertice['index']] = vertice return vertice_dict def _build_edge_dictionary(graph): edge_dict = {} for edge in graph.edges(): index = (edge.vertices()[0]['index'], edge.vertices()[1]['index'], edge.getSyntax()) assert(index not in edge_dict) edge_dict[index] = edge return edge_dict def _same_dictionary(ref_dict, test_dict, same_element_function, verbose=False): if verbose: print(" first: " + str(len(ref_dict)) + " elements.") print(" second: " + str(len(test_dict)) + " elements.") if not len(ref_dict) == len(test_dict): if verbose: print(" different number of elements.") return False same_dict = True for index, ref in six.iteritems(ref_dict): same_item = True if index not in test_dict: same_item = False same_dict = False if verbose: print(" test dict has no element with index " + repr(index)) else: break if same_item: same_item = same_element_function(ref, test_dict[index], verbose) if not same_item: same_dict = False if verbose: print("difference in " + repr(index)) else: break return same_dict def _same_value(ref_value, test_value): if isinstance(ref_value, float): if ref_value != test_value and \ abs(ref_value - test_value) / max(abs(ref_value), abs(test_value)) \ > rel_flx_max_diff: return False elif not isinstance(ref_value, str) and hasattr(ref_value, '__len__'): #print('comp lists', ref_value, '*/*', test_value) if len(ref_value) != len(test_value): return False return len([1 for x, y in zip(ref_value, test_value) if not _same_value(x, y)]) == 0 elif str(ref_value) != str(test_value): return False return True def _same_vertice(ref_vertice, test_vertice, verbose): if not len(ref_vertice) == len(test_vertice): if verbose: print(" different number of arguments " + repr(len(ref_vertice)) + " " + repr(len(test_vertice))) return False for key in ref_vertice.keys(): if key not in test_vertice: if verbose: print(repr(key) + " not in test_vertice") return False if key not in ['aims_bottom', 'aims_other', 'aims_ss', 'aims_Tmtktri', 'bottom_label', 'other_label', 'ss_label', 'Tmtktri_label']: ref_value = ref_vertice[key] test_value = test_vertice[key] if not _same_value(ref_value, test_value): if verbose: print("vertex " + repr(key) + " " + str(ref_vertice[key]) + " != " + str(test_vertice[key])) return False return True def _same_edge(ref_edge, test_edge, verbose): # TODO remove the duplication with same_vertice same = len(ref_edge) == len(test_edge) if not same: if verbose: print("different numbers of arguments " + repr(len(ref_edge)) + " " + repr(len(test_edge))) return False for key in ref_edge.keys(): if key not in test_edge: if verbose: print(repr(key) + " not in test_edge") return False if key not in ['aims_cortical', 'aims_junction', 'aims_plidepassage', 'cortical_label', 'junction_label', 'plidepassage_label']: ref_value = ref_edge[key] test_value = test_edge[key] if not _same_value(ref_value, test_value): if verbose: print("edge " + repr(key) + " " + str(ref_edge[key]) + " " + str(test_edge[key])) return False return True