def test_binary_shortest_paths(): ''' Test shortests paths with BFS algorithm ''' for bckd in backends: nngt.use_backend(bckd) num_nodes = 5 # UNDIRECTED edge_list = [(0, 1), (0, 3), (1, 2), (1, 4), (2, 3), (3, 4)] g = nngt.Graph(num_nodes, directed=False) g.new_edges(edge_list) assert na.shortest_path(g, 0, 0) == [0] assert na.shortest_path(g, 0, 1) == [0, 1] assert na.shortest_path(g, 0, 2) in ([0, 1, 2], [0, 3, 2]) count = 0 for p in na.all_shortest_paths(g, 4, 2): assert p in ([4, 1, 2], [4, 3, 2]) count += 1 assert count == 2 count = 0 for p in na.all_shortest_paths(g, 1, 1): assert p == [1] count += 1 assert count == 1 # DIRECTED edge_list = [(0, 1), (0, 3), (1, 2), (1, 4), (3, 2), (4, 3)] g = nngt.Graph(num_nodes, directed=True) g.new_edges(edge_list) assert na.shortest_path(g, 0, 0) == [0] assert na.shortest_path(g, 2, 4) == [] assert na.shortest_path(g, 0, 2) in ([0, 1, 2], [0, 3, 2]) count = 0 for p in na.all_shortest_paths(g, 4, 2): assert p == [4, 3, 2] count += 1 assert count == 1 count = 0 for p in na.all_shortest_paths(g, 1, 1): assert p == [1] count += 1 assert count == 1
def test_subgraph_centrality(): ''' Check subgraph centrality with networkx implementation ''' num_nodes = 5 edge_list = [(0, 1), (0, 2), (0, 3), (1, 3), (2, 3), (2, 4), (3, 4)] # this test requires networkx as backend nngt.use_backend("networkx") g = nngt.Graph(num_nodes, directed=False) g.new_edges(edge_list) # test full centralities import networkx as nx sc_nx = nx.subgraph_centrality(g.graph) sc_nx = np.array([sc_nx[i] for i in range(num_nodes)]) sc_nngt = nngt.analysis.subgraph_centrality(g, weights=False, normalize=False) assert np.all(np.isclose(sc_nx, sc_nngt)) # test max_centrality sc_nngt = nngt.analysis.subgraph_centrality(g, weights=False, normalize="max_centrality") assert np.all(np.isclose(sc_nx / sc_nx.max(), sc_nngt)) # test subpart sc_nngt = nngt.analysis.subgraph_centrality(g, weights=False, normalize=False, nodes=[0, 1]) assert np.all(np.isclose(sc_nx[:2], sc_nngt))
def set_config(config, value=None, silent=False): ''' Set NNGT's configuration. Parameters ---------- config : dict or str Either a full configuration dictionary or one key to be set together with its associated value. value : object, optional (default: None) Value associated to `config` if `config` is a key. Examples -------- >>> nngt.set_config({'multithreading': True, 'omp': 4}) >>> nngt.set_config('multithreading', False) Notes ----- See the config file `nngt/nngt.conf.default` or `~/.nngt/nngt.conf` for details about your configuration. This function has an MPI barrier on it, so it must always be called on all processes. See also -------- :func:`~nngt.get_config` ''' old_mt = nngt._config["multithreading"] old_mpi = nngt._config["mpi"] old_omp = nngt._config["omp"] old_gl = nngt._config["backend"] old_msd = nngt._config["msd"] old_config = nngt._config.copy() new_config = None if not isinstance(config, dict): new_config = {config: value} else: new_config = config.copy() for key, val in new_config.items(): # support for previous "palette" keyword if key not in nngt._config: if key == "palette": _log_message( logger, "WARNING", "`palette` argument is deprecated and will be " "removed in version 3.") else: raise KeyError( "Unknown configuration property: {}".format(key)) if key == "log_level": new_config[key] = _convert(val) if key == "backend" and val != old_gl: nngt.use_backend(val) if key == "log_folder": new_config["log_folder"] = os.path.abspath(os.path.expanduser(val)) if key == "db_folder": new_config["db_folder"] = os.path.abspath(os.path.expanduser(val)) # support for previous "palette" keyword if "palette" in new_config: new_config["palette_continuous"] = new_config["palette"] new_config["palette_discrete"] = new_config["palette"] del new_config["palette"] # check multithreading status and number of threads _pre_update_parallelism(new_config, old_mt, old_omp, old_mpi) # update nngt._config.update(new_config) # apply multithreading parameters _post_update_parallelism(new_config, old_gl, old_msd, old_mt, old_mpi) # update matplotlib if nngt._config['use_tex']: import matplotlib matplotlib.rc('text', usetex=True) # update database if nngt._config["use_database"] and not hasattr(nngt, "db"): from .. import database sys.modules["nngt.database"] = database if nngt._config["db_to_file"]: _log_message(logger, "WARNING", "This functionality is not available") # update nest if nngt._config["load_nest"] and imputil.find_spec("nest") is not None: _lazy_load("nngt.simulation") nngt._config["with_nest"] = True else: nngt._config["with_nest"] = False # check geometry try: import svg.path has_svg = True except: has_svg = False try: import dxfgrabber has_dxf = True except: has_dxf = False try: import shapely has_shapely = shapely.__version__ except: has_shapely = False # check geospatial has_geospatial = False has_geopandas = imputil.find_spec("geopandas") is not None if nngt._config["load_gis"] and has_geopandas and has_shapely: _lazy_load("nngt.geospatial") has_geospatial = True # log changes _configure_logger(nngt._logger) glib = (nngt._config["library"] if nngt._config["library"] is not None else nngt) num_mpi = num_mpi_processes() s_mpi = False if not nngt._config["mpi"] \ else "True ({} process{})".format( num_mpi, "es" if num_mpi > 1 else "") conf_info = _config_info.format( gl=nngt._config["backend"] + " " + glib.__version__[:5], thread=nngt._config["multithreading"], plot=nngt._config["with_plot"], nest=nngt._config["with_nest"], db=nngt._config["use_database"], omp=nngt._config["omp"], s="s" if nngt._config["omp"] > 1 else "", mpi=s_mpi, shapely=has_shapely, svg=has_svg, dxf=has_dxf, geotool=has_geospatial, ) if not silent and old_config != nngt._config: _log_conf_changed(conf_info)
import importlib from os import listdir, environ from os.path import abspath, dirname, isfile import unittest # personal library import nngt # ------------- # # Get the tests # # ------------- # # get the arguments for the graph library backend = environ.get("GL", None) if backend == "gt": nngt.use_backend("graph-tool") assert nngt.get_config('backend') == "graph-tool", \ "Loading graph-tool failed..." elif backend == "ig": nngt.use_backend("igraph") assert nngt.get_config('backend') == "igraph", \ "Loading igraph failed..." elif backend == "nx": nngt.use_backend("networkx") assert nngt.get_config('backend') == "networkx", \ "Loading networkx failed..." elif backend == "nngt": nngt.use_backend("nngt") assert nngt.get_config('backend') == "nngt", \ "Loading nngt failed..."
''' SpatialNetwork generation, complex shapes ''' import os import time import numpy as np import matplotlib.pyplot as plt import nngt from nngt.geometry import Shape import pickle import pdb print('PDB DEBUGGER ACTIVATED') # nngt.use_backend("graph-tool") nngt.use_backend("networkx") # nngt.set_config({"omp": 8, "palette": 'RdYlBu'}) nngt.set_config("multithreading", False) nngt.seed(0) ''' Runtime options''' plot_distribution = True # plot of the connectivity distribution plot_graphs = False # graphic output of spatial network simulate_activity = True # whether to run or not a NEST simlation on the model sim_duration = 2000 # simulation duration in ms plot_activity = True # whether to plot simulation activity animation_movie = True # wheter to generate activity on map movie save_spikes = False # whether to save the spikes of all the neurons obstacles = True # set to True for simulation with elevated obstacles
def test_weighted_shortest_paths(): ''' Test shortest paths with Dijsktra algorithm ''' for bckd in backends: nngt.use_backend(bckd) num_nodes = 5 # UNDIRECTED edge_list = [(0, 1), (0, 3), (1, 2), (1, 4), (2, 3), (3, 4)] weights = [5, 0.1, 3., 0.5, 1, 3.5] g = nngt.Graph(num_nodes, directed=False) g.new_edges(edge_list) g.set_weights(weights) assert na.shortest_path(g, 0, 0, weights='weight') == [0] assert na.shortest_path(g, 0, 1, weights='weight') == [0, 3, 2, 1] sp = na.shortest_path(g, 1, 3, weights=weights) assert sp in ([1, 4, 3], [1, 2, 3]) count = 0 for p in na.all_shortest_paths(g, 1, 3, weights='weight'): assert p in ([1, 4, 3], [1, 2, 3]) count += 1 assert count == 2 count = 0 for p in na.all_shortest_paths(g, 1, 1, weights='weight'): assert p == [1] count += 1 assert count == 1 # DIRECTED edge_list = [(0, 1), (0, 3), (1, 2), (1, 4), (3, 2), (4, 3)] weights = [1., 0.1, 0.1, 0.5, 1, 3.5] g = nngt.Graph(num_nodes, directed=True) g.new_edges(edge_list, attributes={"weight": weights}) assert na.shortest_path(g, 0, 0, weights='weight') == [0] assert na.shortest_path(g, 2, 4, weights='weight') == [] assert na.shortest_path(g, 1, 3, weights=weights) == [1, 4, 3] count = 0 for p in na.all_shortest_paths(g, 0, 2, weights='weight'): assert p in ([0, 1, 2], [0, 3, 2]) count += 1 assert count == 2 count = 0 for p in na.all_shortest_paths(g, 1, 1, weights='weight'): assert p == [1] count += 1 assert count == 1 # UNDIRECTED FROM DIRECTED weights = [5, 0.1, 3., 0.5, 1, 3.5] # reset weights g.set_weights(weights) assert na.shortest_path(g, 0, 0, False, weights='weight') == [0] assert na.shortest_path(g, 0, 1, False, weights='weight') == [0, 3, 2, 1] sp = na.shortest_path(g, 1, 3, False, weights=weights) assert sp in ([1, 4, 3], [1, 2, 3]) count = 0 for p in na.all_shortest_paths(g, 1, 3, False, weights='weight'): assert p in ([1, 4, 3], [1, 2, 3]) count += 1 assert count == 2 count = 0 for p in na.all_shortest_paths(g, 1, 1, False, weights='weight'): assert p == [1] count += 1 assert count == 1
def test_weighted_shortest_distance(): ''' Check shortest distance ''' for bckd in backends: nngt.use_backend(bckd) num_nodes = 5 edge_list = [(0, 3), (1, 0), (1, 2), (2, 4), (4, 1), (4, 3), (4, 0)] weights = [2., 1., 1., 3., 2., 3., 2.] # UNDIRECTED g = nngt.Graph(num_nodes, directed=False) g.new_edges(edge_list) mat_dist = na.shortest_distance(g, weights=weights) undirected_dist = np.array([ [0, 1, 2, 2, 2], [1, 0, 1, 3, 2], [2, 1, 0, 4, 3], [2, 3, 4, 0, 3], [2, 2, 3, 3, 0], ]) assert np.array_equal(mat_dist, undirected_dist) # undirected, sources g.set_weights(weights) mat_dist = na.shortest_distance(g, sources=[0, 1, 2], weights='weight') assert np.array_equal(mat_dist, undirected_dist[:3]) # undirected targets mat_dist = na.shortest_distance(g, targets=[0, 1, 2], weights='weight') assert np.array_equal(mat_dist[:, :3], undirected_dist[:, :3]) # single source/target dist = na.shortest_distance(g, sources=3, targets=2, weights='weight') assert dist == 4 # DIRECTED g = nngt.Graph(num_nodes, directed=True) g.new_edges(edge_list) directed_dist = np.array([[0., np.inf, np.inf, 2., np.inf], [1., 0., 1., 3., 4.], [5., 5., 0., 6., 3.], [np.inf, np.inf, np.inf, 0., np.inf], [2., 2., 3., 3., 0.]]) mat_dist = na.shortest_distance(g, weights=weights) assert np.array_equal(mat_dist, directed_dist) # check undirected from directed gives back undirected results mat_dist = na.shortest_distance(g, directed=False, weights=weights) assert np.array_equal(mat_dist, undirected_dist) # single source g.set_weights(weights) mat_dist = na.shortest_distance(g, sources=[0], weights='weight') assert np.array_equal(mat_dist, directed_dist[:1].ravel()) # single target mat_dist = na.shortest_distance(g, targets=0, weights='weight') assert np.array_equal(mat_dist, directed_dist[:, 0].ravel()) # single source/target directed assert np.isinf( na.shortest_distance(g, sources=0, targets=2, weights='weight'))
def test_binary_shortest_distance(): ''' Check shortest distance ''' num_nodes = 5 for bckd in backends: nngt.use_backend(bckd) # UNDIRECTED edge_list = [(0, 3), (1, 0), (1, 2), (2, 4), (4, 1), (4, 3), (4, 0)] g = nngt.Graph(num_nodes, directed=False) g.new_edges(edge_list) mat_dist = na.shortest_distance(g) undirected_dist = np.array([ [0, 1, 2, 1, 1], [1, 0, 1, 2, 1], [2, 1, 0, 2, 1], [1, 2, 2, 0, 1], [1, 1, 1, 1, 0], ]) assert np.array_equal(mat_dist, undirected_dist) # undirected, sources mat_dist = na.shortest_distance(g, sources=[0, 1, 2]) assert np.array_equal(mat_dist, undirected_dist[:3]) # undirected targets mat_dist = na.shortest_distance(g, targets=[0, 1, 2]) assert np.array_equal(mat_dist[:, :3], undirected_dist[:, :3]) # single source/target assert na.shortest_distance(g, sources=0, targets=2) == 2 # DIRECTED g = nngt.Graph(num_nodes, directed=True) edge_list = [(0, 3), (1, 0), (1, 2), (2, 4), (4, 1), (4, 3), (4, 2), (4, 0)] g.new_edges(edge_list) directed_dist = np.array([[0., np.inf, np.inf, 1., np.inf], [1., 0., 1., 2., 2.], [2., 2., 0., 2., 1.], [np.inf, np.inf, np.inf, 0., np.inf], [1., 1., 1., 1., 0.]]) mat_dist = na.shortest_distance(g) assert np.array_equal(mat_dist, directed_dist) # check undirected from directed mat_dist = na.shortest_distance(g, directed=False) assert np.array_equal(mat_dist, undirected_dist) # single source mat_dist = na.shortest_distance(g, sources=[0]) assert np.array_equal(mat_dist, directed_dist[:1].ravel()) # single target mat_dist = na.shortest_distance(g, targets=0) assert np.array_equal(mat_dist, directed_dist[:, 0].ravel()) # single source/target directed assert np.isinf(na.shortest_distance(g, sources=0, targets=2))
def set_config(config, value=None, silent=False): ''' Set NNGT's configuration. Parameters ---------- config : dict or str Either a full configuration dictionary or one key to be set together with its associated value. value : object, optional (default: None) Value associated to `config` if `config` is a key. Examples -------- >>> nngt.set_config({'multithreading': True, 'omp': 4}) >>> nngt.set_config('multithreading', False) Notes ----- See the config file `nngt/nngt.conf.default` or `~/.nngt/nngt.conf` for details about your configuration. This function has an MPI barrier on it, so it must always be called on all processes. See also -------- :func:`~nngt.get_config` ''' old_mt = nngt._config["multithreading"] old_mpi = nngt._config["mpi"] old_omp = nngt._config["omp"] old_gl = nngt._config["backend"] old_msd = nngt._config["msd"] new_config = None if not isinstance(config, dict): new_config = {config: value} else: new_config = config.copy() for key in new_config: if key not in nngt._config: raise KeyError("Unknown configuration property: {}".format(key)) if key == "log_level": new_config[key] = _convert(new_config[key]) if key == "backend" and new_config[key] != old_gl: nngt.use_backend(new_config[key]) # check multithreading status and number of threads _pre_update_parallelism(new_config, old_mt, old_omp, old_mpi) # update nngt._config.update(new_config) # apply multithreading parameters _post_update_parallelism(new_config, old_gl, old_msd, old_mt, old_mpi) # update matplotlib if nngt._config['use_tex']: import matplotlib matplotlib.rc('text', usetex=True) # log changes _configure_logger(nngt._logger) glib = (nngt._config["library"] if nngt._config["library"] is not None else nngt) num_mpi = num_mpi_processes() s_mpi = False if not nngt._config["mpi"] else "True ({} process{})".format( num_mpi, "es" if num_mpi > 1 else "") conf_info = config_info.format(gl=nngt._config["backend"] + " " + glib.__version__[:5], thread=nngt._config["multithreading"], plot=nngt._config["with_plot"], nest=nngt._config["with_nest"], db=nngt._config["use_database"], omp=nngt._config["omp"], s="s" if nngt._config["omp"] > 1 else "", mpi=s_mpi) if not silent: _log_conf_changed(conf_info)