Skip to content

Commit

Permalink
Add utilities.py
Browse files Browse the repository at this point in the history
Factor out common  helper methods.
Makes files easier to read, imports easier.
#7
  • Loading branch information
VaeterchenFrost committed Jun 6, 2020
1 parent 697227b commit 5f0c5ba
Show file tree
Hide file tree
Showing 5 changed files with 141 additions and 111 deletions.
34 changes: 1 addition & 33 deletions tdvisu/dijkstra.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@
from heapq import heappush, heappop
from itertools import count

from tdvisu.utilities import convert_to_adj

def bidirectional_dijkstra(edges, source, target, weight='weight'):
r"""Dijkstra's algorithm for shortest paths using bidirectional search.
Expand Down Expand Up @@ -229,39 +230,6 @@ def _weight_function(weight, multigraph=False):
return lambda u, v, data: data.get(weight, 1)


def convert_to_adj(edgelist, directed=False):
"""
Helper function to convert the edgelist into the adj-format from NetworkX.
Parameters
----------
edgelist : array-like of pairs of vertices.
Simple edgelist. Example:
[(2, 1), (3, 2), (4, 2), (5, 4)]
directed : bool, optional
Whether to add the backward edges too. The default is False.
Returns
-------
adj : dict of edges with empty attributes
See Docs » Module code » networkx.classes.graph.adj(self)
for detailed structure.
Basically: dict of {source1:{target1:{'attr1':value,},},...}
https://networkx.github.io/documentation/networkx-2.1/_modules/networkx/classes/graph.html
"""
adj = dict()
for (u, v) in edgelist:
if u not in adj:
adj[u] = {}
adj[u][v] = {}
if not directed:
# add reversed edge
if v not in adj:
adj[v] = {}
adj[v][u] = {}
return adj


if __name__ == "__main__":
# Show one example and print to console
EDGELIST = [(2, 1), (3, 2), (4, 2), (5, 4)]
Expand Down
35 changes: 2 additions & 33 deletions tdvisu/reader.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ def main()
import logging
import sys

from tdvisu.utilities import add_edge_to

logger = logging.getLogger('reader.py')

Expand Down Expand Up @@ -129,38 +130,6 @@ def preamble(self, lines) -> int:
sys.exit(1)


def _add_edge_to(edges, adjacency_dict, vertex1, vertex2) -> None:
"""
Adding (undirected) edge from 'vertex1' to 'vertex2'
to the edges and adjacency-list.
Parameters
----------
edges : set-like
Set of tuples of vertices.
adjacency_dict : dict-like
Saves adjecent vertices for each vertex.
vertex1 : any
First vertex of the new edge.
vertex2 : any
Second vertex of the new edge.
Returns
-------
None
"""
if vertex1 in adjacency_dict:
adjacency_dict[vertex1].add(vertex2)
else:
adjacency_dict[vertex1] = {vertex2}
if vertex2 in adjacency_dict:
adjacency_dict[vertex2].add(vertex1)
else:
adjacency_dict[vertex2] = {vertex1}
edges.add((vertex1, vertex2))


class TwReader(DimacsReader):
"""Dimacs Reader for the 'tw' format (saving directed edges).
Stores edges and adjacency together with
Expand Down Expand Up @@ -196,7 +165,7 @@ def body(self, lines) -> None:
vertex1 = int(line[0])
vertex2 = int(line[1])

_add_edge_to(self.edges, self.adjacency_dict, vertex1, vertex2)
add_edge_to(self.edges, self.adjacency_dict, vertex1, vertex2)

if len(self.edges) != self.num_edges:
logger.warning(
Expand Down
31 changes: 2 additions & 29 deletions tdvisu/svgjoin.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,10 @@

import re
import logging
from typing import Union, Iterable, Generator, Any, List
from collections.abc import Iterable as iter_type
from typing import Union, Iterable, List
from benedict import benedict

from tdvisu.utilities import gen_arg

LOGGER = logging.getLogger('svg_join.py')

Expand All @@ -35,33 +35,6 @@
HEIGHT = 3


def gen_arg(arg_or_iter: Any) -> Generator:
"""
Infinite generator for the next argument of `arg_or_iter`.
If the argument is exhausted, always return the last element.
Parameters
----------
arg_or_iter : object
Object to iterate over. Considers three cases:
string: yields the string as one element indefinitely
iterable: yields all elements from it, and only the last one after.
not iterable: yield the object indefinitely
"""
if isinstance(arg_or_iter, str):
while True:
yield arg_or_iter
elif not isinstance(arg_or_iter, iter_type):
while True:
yield arg_or_iter
else:
item = None
for item in arg_or_iter:
yield item
while True:
yield item


def test_viewbox(viewbox: List[float]):
"""Should be of form [0, 0, +x, +y]"""
assert len(viewbox) == 4, "viewbox should have exactly 4 values"
Expand Down
131 changes: 131 additions & 0 deletions tdvisu/utilities.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
# -*- coding: utf-8 -*-
"""
Helper methods for this module.
Copyright (C) 2020 Martin Röbke
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program.
If not, see https://www.gnu.org/licenses/gpl-3.0.html
"""
from itertools import chain
from collections.abc import Iterable as iter_type
from typing import Generator, Any, Iterable, Iterator, TypeVar


_T = TypeVar('_T')

def flatten(iterable: Iterable[Iterable[_T]]) -> Iterator[_T]:
""" Flatten at first level.
Turn ex=[[1,2],[3,4]] into
[1, 2, 3, 4]
and [ex,ex] into
[[1, 2], [3, 4], [1, 2], [3, 4]]
"""
return chain.from_iterable(iterable)


def convert_to_adj(edgelist, directed=False) -> dict:
"""
Helper function to convert the edgelist into the adj-format from NetworkX.
Parameters
----------
edgelist : array-like of pairs of vertices.
Simple edgelist. Example:
[(2, 1), (3, 2), (4, 2), (5, 4)]
directed : bool, optional
Whether to add the backward edges too. The default is False.
Returns
-------
adj : dict of edges with empty attributes
See Docs » Module code » networkx.classes.graph.adj(self)
for detailed structure.
Basically: dict of {source1:{target1:{'attr1':value,},},...}
https://networkx.github.io/documentation/networkx-2.1/_modules/networkx/classes/graph.html
"""
adj = dict()
for (source, target) in edgelist:
if source not in adj:
adj[source] = {}
adj[source][target] = {}
if not directed:
# add reversed edge
if target not in adj:
adj[target] = {}
adj[target][source] = {}
return adj


def add_edge_to(edges, adjacency_dict, vertex1, vertex2) -> None:
"""
Adding (undirected) edge from 'vertex1' to 'vertex2'
to the edges and adjacency-list.
Parameters
----------
edges : set-like
Set of tuples of vertices.
adjacency_dict : dict-like
Saves adjecent vertices for each vertex.
vertex1 : any
First vertex of the new edge.
vertex2 : any
Second vertex of the new edge.
Returns
-------
None
"""
if vertex1 in adjacency_dict:
adjacency_dict[vertex1].add(vertex2)
else:
adjacency_dict[vertex1] = {vertex2}
if vertex2 in adjacency_dict:
adjacency_dict[vertex2].add(vertex1)
else:
adjacency_dict[vertex2] = {vertex1}
edges.add((vertex1, vertex2))


def gen_arg(arg_or_iter: Any) -> Generator:
"""
Infinite generator for the next argument of `arg_or_iter`.
If the argument is exhausted, always return the last element.
Parameters
----------
arg_or_iter : object
Object to iterate over. Considers three cases:
string: yields the string as one element indefinitely
iterable: yields all elements from it, and only the last one after.
not iterable: yield the object indefinitely
"""
if isinstance(arg_or_iter, str):
while True:
yield arg_or_iter
elif not isinstance(arg_or_iter, iter_type):
while True:
yield arg_or_iter
else:
item = None
for item in arg_or_iter:
yield item
while True:
yield item

21 changes: 5 additions & 16 deletions tdvisu/visualization.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@

import argparse
import io
import itertools
import json
import logging
from dataclasses import asdict
Expand All @@ -40,6 +39,7 @@
GeneralGraphData, SvgJoinData)
from tdvisu.version import __date__, __version__ as version
from tdvisu.svgjoin import svg_join
from tdvisu.utilities import flatten


LOGGER = logging.getLogger('visualization.py')
Expand Down Expand Up @@ -72,20 +72,6 @@ def read_json(json_data) -> dict:
return result


_T = TypeVar('_T')


def flatten(iterable: Iterable[Iterable[_T]]) -> Iterator[_T]:
""" Flatten at first level.
Turn ex=[[1,2],[3,4]] into
[1, 2, 3, 4]
and [ex,ex] into
[[1, 2], [3, 4], [1, 2], [3, 4]]
"""
return itertools.chain.from_iterable(iterable)


class Visualization:
"""Holds and processes the information needed to provide dot-format
and image output for the visualization
Expand Down Expand Up @@ -818,7 +804,10 @@ def main(args: argparse.Namespace) -> None:
-------
None
"""


# Read logging.yml

with open('logging.yml')
# get loglevel
try:
loglevel = int(float(args.loglevel))
Expand Down

0 comments on commit 5f0c5ba

Please sign in to comment.