topolib 0.4.2__py3-none-any.whl → 0.6.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of topolib might be problematic. Click here for more details.

Files changed (42) hide show
  1. topolib/assets/AMRES.json +1265 -0
  2. topolib/assets/Bell_canada.json +925 -0
  3. topolib/assets/Brazil.json +699 -0
  4. topolib/assets/CESNET.json +657 -0
  5. topolib/assets/CORONET.json +1957 -0
  6. topolib/assets/{China_pop.json → China.json} +109 -37
  7. topolib/assets/DT-14.json +470 -0
  8. topolib/assets/DT-17.json +525 -0
  9. topolib/assets/{DT-50_pop.json → DT-50.json} +165 -65
  10. topolib/assets/ES-30.json +967 -0
  11. topolib/assets/EURO-16.json +455 -0
  12. topolib/assets/FR-43.json +1277 -0
  13. topolib/assets/FUNET.json +317 -0
  14. topolib/assets/GCN-BG.json +855 -0
  15. topolib/assets/GRNET.json +1717 -0
  16. topolib/assets/HyperOne.json +255 -0
  17. topolib/assets/IT-21.json +649 -0
  18. topolib/assets/India.json +517 -0
  19. topolib/assets/JPN-12.json +331 -0
  20. topolib/assets/KOREN.json +287 -0
  21. topolib/assets/NORDUNet.json +783 -0
  22. topolib/assets/NSFNet.json +399 -0
  23. topolib/assets/PANEURO.json +757 -0
  24. topolib/assets/PAVLOV.json +465 -0
  25. topolib/assets/PLN-12.json +343 -0
  26. topolib/assets/SANReN.json +161 -0
  27. topolib/assets/SERBIA-MONTENEGRO.json +139 -0
  28. topolib/assets/Telefonica-21.json +637 -0
  29. topolib/assets/Turk_Telekom.json +551 -0
  30. topolib/assets/UKNet.json +685 -0
  31. topolib/assets/Vega_Telecom.json +819 -0
  32. topolib/elements/__init__.py +0 -3
  33. topolib/elements/link.py +0 -21
  34. topolib/elements/node.py +0 -2
  35. topolib/topology/topology.py +349 -8
  36. topolib/visualization/mapview.py +53 -1
  37. {topolib-0.4.2.dist-info → topolib-0.6.0.dist-info}/METADATA +10 -4
  38. topolib-0.6.0.dist-info/RECORD +47 -0
  39. topolib-0.4.2.dist-info/RECORD +0 -18
  40. /topolib/assets/{Abilene_IXP.json → Abilene.json} +0 -0
  41. {topolib-0.4.2.dist-info → topolib-0.6.0.dist-info}/WHEEL +0 -0
  42. {topolib-0.4.2.dist-info → topolib-0.6.0.dist-info}/licenses/LICENSE +0 -0
@@ -2,7 +2,4 @@
2
2
  from .node import Node
3
3
  from .link import Link
4
4
 
5
- # Hide re-exported Link from Sphinx index to avoid duplicate warnings
6
- Link.__doc__ = """.. :noindex:"""
7
-
8
5
  __all__ = ["Node", "Link"]
topolib/elements/link.py CHANGED
@@ -9,8 +9,6 @@ if TYPE_CHECKING:
9
9
  class Link:
10
10
 
11
11
  """
12
- .. :noindex:
13
-
14
12
  Represents a link between two nodes.
15
13
 
16
14
  Parameters
@@ -24,17 +22,6 @@ class Link:
24
22
  length : float
25
23
  Length of the link (must be non-negative).
26
24
 
27
- Attributes
28
- ----------
29
- id : int
30
- Unique identifier for the link.
31
- source : :class:`topolib.elements.node.Node`
32
- Source node of the link.
33
- target : :class:`topolib.elements.node.Node`
34
- Target node of the link.
35
- length : float
36
- Length of the link.
37
-
38
25
  Examples
39
26
  --------
40
27
  >>> link = Link(1, nodeA, nodeB, 10.5)
@@ -50,8 +37,6 @@ class Link:
50
37
  @property
51
38
  def id(self) -> int:
52
39
  """
53
- .. :noindex:
54
-
55
40
  int: Unique identifier for the link.
56
41
  """
57
42
  return self._id
@@ -66,8 +51,6 @@ class Link:
66
51
  @property
67
52
  def source(self) -> "Node":
68
53
  """
69
- .. :noindex:
70
-
71
54
  :class:`topolib.elements.node.Node`: Source node of the link.
72
55
  """
73
56
  return self._source
@@ -87,8 +70,6 @@ class Link:
87
70
  @property
88
71
  def target(self) -> "Node":
89
72
  """
90
- .. :noindex:
91
-
92
73
  :class:`topolib.elements.node.Node`: Target node of the link.
93
74
  """
94
75
  return self._target
@@ -108,8 +89,6 @@ class Link:
108
89
  @property
109
90
  def length(self) -> float:
110
91
  """
111
- .. :noindex:
112
-
113
92
  float: Length of the link (non-negative).
114
93
  """
115
94
  return self._length
topolib/elements/node.py CHANGED
@@ -9,8 +9,6 @@ from typing import Tuple
9
9
 
10
10
  class Node:
11
11
  """
12
- .. :noindex:
13
-
14
12
  Represents a node in an optical network topology.
15
13
 
16
14
  :param id: Unique identifier for the node.
@@ -8,9 +8,25 @@ This file uses NetworkX (BSD 3-Clause License):
8
8
  https://github.com/networkx/networkx/blob/main/LICENSE.txt
9
9
  """
10
10
 
11
- from typing import List, Dict, Any, Optional
11
+ from typing import List, Optional, Any
12
+ from numpy.typing import NDArray
13
+
14
+
15
+ # Standard library imports
16
+ import json
17
+ import csv
18
+ from pathlib import Path
19
+
20
+ # Third-party imports
12
21
  import numpy as np
13
22
  import networkx as nx
23
+ import jsonschema
24
+ import matplotlib.pyplot as plt
25
+ import contextily as ctx
26
+ import geopandas as gpd
27
+ from shapely.geometry import Point
28
+
29
+ # Local imports
14
30
  from topolib.elements.node import Node
15
31
  from topolib.elements.link import Link
16
32
 
@@ -62,7 +78,7 @@ class Topology:
62
78
  self.links = links if links is not None else []
63
79
  self.name = name
64
80
  # Internal NetworkX graph for algorithms and visualization
65
- self._graph = nx.Graph()
81
+ self._graph: nx.DiGraph[Any] = nx.DiGraph()
66
82
  for node in self.nodes:
67
83
  self._graph.add_node(node.id, node=node)
68
84
  for link in self.links:
@@ -78,12 +94,51 @@ class Topology:
78
94
  :return: Topology instance loaded from the file.
79
95
  :rtype: Topology
80
96
  """
81
- import json
82
- from topolib.elements.node import Node
83
- from topolib.elements.link import Link
84
-
85
97
  with open(json_path, "r", encoding="utf-8") as f:
86
98
  data = json.load(f)
99
+
100
+ # Validation schema for the assets JSON format
101
+ topology_schema: dict[str, Any] = {
102
+ "type": "object",
103
+ "properties": {
104
+ "name": {"type": "string"},
105
+ "nodes": {
106
+ "type": "array",
107
+ "items": {
108
+ "type": "object",
109
+ "properties": {
110
+ "id": {"type": "integer"},
111
+ "name": {"type": "string"},
112
+ "weight": {"type": "number"},
113
+ "latitude": {"type": "number"},
114
+ "longitude": {"type": "number"},
115
+ "pop": {"type": "integer"},
116
+ "DC": {"type": "integer"},
117
+ "IXP": {"type": "integer"},
118
+ },
119
+ "required": ["id", "name", "latitude", "longitude"],
120
+ },
121
+ },
122
+ "links": {
123
+ "type": "array",
124
+ "items": {
125
+ "type": "object",
126
+ "properties": {
127
+ "id": {"type": "integer"},
128
+ "src": {"type": "integer"},
129
+ "dst": {"type": "integer"},
130
+ "length": {"type": "number"},
131
+ },
132
+ "required": ["id", "src", "dst", "length"],
133
+ },
134
+ },
135
+ },
136
+ "required": ["nodes", "links"],
137
+ }
138
+ try:
139
+ jsonschema.validate(instance=data, schema=topology_schema)
140
+ except jsonschema.ValidationError as e:
141
+ raise ValueError(f"Invalid topology JSON format: {e.message}")
87
142
  nodes = [
88
143
  Node(
89
144
  n["id"],
@@ -100,7 +155,8 @@ class Topology:
100
155
  # Crear un dict para mapear id a Node
101
156
  node_dict = {n.id: n for n in nodes}
102
157
  links = [
103
- Link(l["id"], node_dict[l["src"]], node_dict[l["dst"]], l["length"])
158
+ Link(l["id"], node_dict[l["src"]],
159
+ node_dict[l["dst"]], l["length"])
104
160
  for l in data["links"]
105
161
  ]
106
162
  name = data.get("name", None)
@@ -152,7 +208,7 @@ class Topology:
152
208
  self._graph.remove_edge(link.source.id, link.target.id)
153
209
  self.links = [l for l in self.links if l.id != link_id]
154
210
 
155
- def adjacency_matrix(self) -> np.ndarray:
211
+ def adjacency_matrix(self) -> NDArray[np.int_]:
156
212
  """
157
213
  Return the adjacency matrix of the topology as a numpy array.
158
214
 
@@ -170,3 +226,288 @@ class Topology:
170
226
  node_ids = [n.id for n in self.nodes]
171
227
  mat = nx.to_numpy_array(self._graph, nodelist=node_ids, dtype=int)
172
228
  return mat
229
+
230
+ def export_to_json(self, file_path: str) -> None:
231
+ """
232
+ Export the current topology to the JSON format used in the assets folder.
233
+
234
+ :param file_path: Path where the JSON file will be saved.
235
+ :type file_path: str
236
+
237
+ Example usage::
238
+
239
+ topo.export_to_json("/path/output.json")
240
+
241
+ Example output format::
242
+
243
+ {
244
+ "name": "Abilene",
245
+ "nodes": [
246
+ {
247
+ "id": 0,
248
+ "name": "Seattle",
249
+ ...
250
+ }
251
+ ],
252
+ "links": [
253
+ {
254
+ "id": 0,
255
+ "src": 0,
256
+ "dst": 1,
257
+ "length": 1482.26
258
+ }
259
+ ]
260
+ }
261
+ """
262
+ nodes_list: list[dict[str, Any]] = []
263
+ for n in self.nodes:
264
+ node_dict: dict[str, Any] = {
265
+ "id": n.id,
266
+ "name": getattr(n, "name", None),
267
+ "weight": getattr(n, "weight", 0),
268
+ "latitude": getattr(n, "latitude", None),
269
+ "longitude": getattr(n, "longitude", None),
270
+ "pop": getattr(n, "pop", 0),
271
+ "DC": getattr(n, "dc", getattr(n, "DC", 0)),
272
+ "IXP": getattr(n, "ixp", getattr(n, "IXP", 0)),
273
+ }
274
+ nodes_list.append(node_dict)
275
+ links_list: list[dict[str, Any]] = []
276
+ for l in self.links:
277
+ link_dict: dict[str, Any] = {
278
+ "id": l.id,
279
+ "src": l.source.id,
280
+ "dst": l.target.id,
281
+ "length": getattr(l, "length", None),
282
+ }
283
+ links_list.append(link_dict)
284
+ data: dict[str, Any] = {
285
+ "name": self.name if self.name else "Topology",
286
+ "nodes": nodes_list,
287
+ "links": links_list,
288
+ }
289
+ with open(file_path, "w", encoding="utf-8") as f:
290
+ json.dump(data, f, indent=4, ensure_ascii=False)
291
+
292
+ def export_to_csv(self, filename_prefix: str) -> None:
293
+ """
294
+ Export the topology to two CSV files: one for nodes and one for links.
295
+ The files will be named as <filename_prefix>_nodes.csv and <filename_prefix>_links.csv.
296
+
297
+ :param filename_prefix: Prefix for the output files (e.g., 'topology1').
298
+ :type filename_prefix: str
299
+
300
+ Example:
301
+ >>> topo.export_to_csv("mytopo")
302
+ # Generates 'mytopo_nodes.csv' and 'mytopo_links.csv'
303
+ """
304
+ # Export nodes
305
+ nodes_path = f"{filename_prefix}_nodes.csv"
306
+ with open(nodes_path, "w", newline="", encoding="utf-8") as f:
307
+ writer = csv.writer(f)
308
+ # Header
309
+ writer.writerow(
310
+ ["id", "name", "weight", "latitude",
311
+ "longitude", "pop", "DC", "IXP"]
312
+ )
313
+ for n in self.nodes:
314
+ writer.writerow(
315
+ [
316
+ n.id,
317
+ getattr(n, "name", None),
318
+ getattr(n, "weight", 0),
319
+ getattr(n, "latitude", None),
320
+ getattr(n, "longitude", None),
321
+ getattr(n, "pop", 0),
322
+ getattr(n, "dc", getattr(n, "DC", 0)),
323
+ getattr(n, "ixp", getattr(n, "IXP", 0)),
324
+ ]
325
+ )
326
+ # Export links
327
+ links_path = f"{filename_prefix}_links.csv"
328
+ with open(links_path, "w", newline="", encoding="utf-8") as f:
329
+ writer = csv.writer(f)
330
+ writer.writerow(["id", "src", "dst", "length"])
331
+ for l in self.links:
332
+ writer.writerow(
333
+ [
334
+ l.id,
335
+ l.source.id,
336
+ l.target.id,
337
+ getattr(l, "length", None),
338
+ ]
339
+ )
340
+
341
+ def export_to_flexnetsim_json(self, file_path: str, slots: int) -> None:
342
+ """
343
+ Export the current topology to a JSON file compatible with Flex Net Sim.
344
+
345
+ :param file_path: Path where the JSON file will be saved.
346
+ :type file_path: str
347
+ :param slots: Number of slots for each link.
348
+ :type slots: int
349
+
350
+ The generated format includes the following fields:
351
+ - alias: short name of the topology (uses self.name if available)
352
+ - name: full name of the topology (uses self.name if available)
353
+ - nodes: list of nodes with 'id' field
354
+ - links: list of links with id, src, dst, length, slots
355
+ """
356
+ alias = self.name if self.name else "Topology"
357
+ name = self.name if self.name else "Topology"
358
+ nodes_list = [{"id": n.id} for n in self.nodes]
359
+ links_list = []
360
+ for l in self.links:
361
+ link_dict = {
362
+ "id": l.id,
363
+ "src": l.source.id,
364
+ "dst": l.target.id,
365
+ "length": getattr(l, "length", None),
366
+ "slots": slots,
367
+ }
368
+ links_list.append(link_dict)
369
+ data = {
370
+ "alias": alias,
371
+ "name": name,
372
+ "nodes": nodes_list,
373
+ "links": links_list,
374
+ }
375
+ with open(file_path, "w", encoding="utf-8") as f:
376
+ json.dump(data, f, indent=4, ensure_ascii=False)
377
+
378
+ def export_to_flexnetsim_ksp_json(self, file_path: str, k: int = 3) -> None:
379
+ """
380
+ Export the k-shortest paths between all node pairs to a JSON file compatible with Flex Net Sim.
381
+
382
+ :param file_path: Path where the JSON file will be saved.
383
+ :type file_path: str
384
+ :param k: Number of shortest paths to compute for each node pair (default: 3).
385
+ :type k: int
386
+
387
+ Example output format::
388
+
389
+ {
390
+ "name": self.name,
391
+ "alias": self.name,
392
+ "routes": [
393
+ {"src": <id>, "dst": <id>, "paths": [[id, ...], ...]},
394
+ ...
395
+ ]
396
+ }
397
+ """
398
+
399
+ # Build a weighted graph using link length as edge weight
400
+ G = nx.DiGraph()
401
+ for l in self.links:
402
+ G.add_edge(l.source.id, l.target.id,
403
+ weight=getattr(l, "length", 1))
404
+ routes = []
405
+ node_ids = [n.id for n in self.nodes]
406
+ for src in node_ids:
407
+ for dst in node_ids:
408
+ if src == dst:
409
+ continue
410
+ try:
411
+ # Compute k shortest paths using link length as weight
412
+ paths_gen = nx.shortest_simple_paths(
413
+ G, src, dst, weight="weight")
414
+ paths = []
415
+ for i, path in enumerate(paths_gen):
416
+ if i >= k:
417
+ break
418
+ paths.append(path)
419
+ except (nx.NetworkXNoPath, nx.NodeNotFound):
420
+ paths = []
421
+ routes.append({"src": src, "dst": dst, "paths": paths})
422
+ data = {
423
+ "name": self.name if self.name else "Topology",
424
+ "alias": self.name if self.name else "Topology",
425
+ "routes": routes,
426
+ }
427
+ with open(file_path, "w", encoding="utf-8") as f:
428
+ json.dump(data, f, indent=4, ensure_ascii=False)
429
+
430
+ @classmethod
431
+ def list_available_topologies(cls) -> list[dict]:
432
+ """
433
+ List available topologies in the assets folder.
434
+
435
+ Returns a list of dictionaries with keys:
436
+ - 'name': topology name (filename without extension)
437
+ - 'nodes': number of nodes
438
+ - 'links': number of links
439
+
440
+ :return: List of available topologies with metadata.
441
+ :rtype: list[dict]
442
+ """
443
+ asset_dir = Path(__file__).parent.parent / "assets"
444
+ result = []
445
+ for json_path in asset_dir.glob("*.json"):
446
+ try:
447
+ topo = cls.from_json(str(json_path))
448
+ result.append({
449
+ "name": json_path.stem,
450
+ "nodes": len(topo.nodes),
451
+ "links": len(topo.links),
452
+ })
453
+ except Exception:
454
+ continue
455
+ return result
456
+
457
+ @staticmethod
458
+ def load_default_topology(name: str) -> "Topology":
459
+ """
460
+ Load a default topology from the assets folder by name (filename without extension).
461
+
462
+ :param name: Name of the topology asset (without .json extension)
463
+ :type name: str
464
+ :return: Topology instance loaded from the asset file
465
+ :rtype: Topology
466
+ :raises FileNotFoundError: If the asset file does not exist
467
+ """
468
+ asset_dir = Path(__file__).parent.parent / "assets"
469
+ asset_path = asset_dir / f"{name}.json"
470
+ if not asset_path.exists():
471
+ raise FileNotFoundError(
472
+ f"Topology asset '{name}.json' not found in assets directory.")
473
+ return Topology.from_json(str(asset_path))
474
+
475
+ def export_graph_png(self, filename: str, dpi: int = 150) -> None:
476
+ """
477
+ Export the topology graph as a PNG image using Matplotlib and Contextily.
478
+
479
+ :param filename: Output PNG file path.
480
+ :type filename: str
481
+ :param dpi: Dots per inch for the saved image (default: 150).
482
+ :type dpi: int
483
+ """
484
+ lons = [node.longitude for node in self.nodes]
485
+ lats = [node.latitude for node in self.nodes]
486
+ names = [node.name for node in self.nodes]
487
+ gdf = gpd.GeoDataFrame(
488
+ {"name": names},
489
+ geometry=[Point(x, y) for x, y in zip(lons, lats)],
490
+ crs="EPSG:4326",
491
+ )
492
+ gdf = gdf.to_crs(epsg=3857)
493
+ node_id_to_xy = {node.id: (pt.x, pt.y)
494
+ for node, pt in zip(self.nodes, gdf.geometry)}
495
+ topo_name = self.name if self.name else "Topology"
496
+ fig, ax = plt.subplots(figsize=(10, 7))
497
+ fig.suptitle(topo_name, fontsize=16)
498
+ for link in self.links:
499
+ src_id = link.source.id
500
+ tgt_id = link.target.id
501
+ if src_id in node_id_to_xy and tgt_id in node_id_to_xy:
502
+ x0, y0 = node_id_to_xy[src_id]
503
+ x1, y1 = node_id_to_xy[tgt_id]
504
+ ax.plot([x0, x1], [y0, y1], color="gray",
505
+ linewidth=1, alpha=0.7, zorder=2)
506
+ gdf.plot(ax=ax, color="blue", markersize=40, zorder=5)
507
+ for x, y, name in zip(gdf.geometry.x, gdf.geometry.y, gdf["name"]):
508
+ ax.text(x, y, name, fontsize=8, ha="right",
509
+ va="bottom", color="black")
510
+ ax.set_axis_off()
511
+ plt.tight_layout()
512
+ plt.savefig(filename, dpi=dpi)
513
+ plt.close(fig)
@@ -67,9 +67,61 @@ class MapView:
67
67
  # Draw nodes
68
68
  gdf.plot(ax=ax, color="blue", markersize=40, zorder=5)
69
69
  for x, y, name in zip(gdf.geometry.x, gdf.geometry.y, gdf["name"]):
70
- ax.text(x, y, name, fontsize=8, ha="right", va="bottom", color="black")
70
+ ax.text(x, y, name, fontsize=8, ha="right",
71
+ va="bottom", color="black")
71
72
  ctx.add_basemap(ax, source=ctx.providers.OpenStreetMap.Mapnik)
72
73
  ax.set_axis_off()
73
74
  ax.set_title(f"Nodes and links ({topo_name})")
74
75
  plt.tight_layout()
75
76
  plt.show()
77
+
78
+ def export_map_png(self, filename: str, dpi: int = 150) -> None:
79
+ """
80
+ Export the topology map as a PNG image using Matplotlib and Contextily.
81
+
82
+ :param filename: Output PNG file path.
83
+ :type filename: str
84
+ :param dpi: Dots per inch for the saved image (default: 150).
85
+ :type dpi: int
86
+ """
87
+ lons: list[float] = [node.longitude for node in self.topology.nodes]
88
+ lats: list[float] = [node.latitude for node in self.topology.nodes]
89
+ names: list[str] = [node.name for node in self.topology.nodes]
90
+ gdf: gpd.GeoDataFrame = gpd.GeoDataFrame(
91
+ {"name": names},
92
+ geometry=[Point(x, y) for x, y in zip(lons, lats)],
93
+ crs="EPSG:4326",
94
+ )
95
+ gdf = gdf.to_crs(epsg=3857)
96
+
97
+ node_id_to_xy = {
98
+ node.id: (pt.x, pt.y) for node, pt in zip(self.topology.nodes, gdf.geometry)
99
+ }
100
+
101
+ topo_name = getattr(self.topology, "name", None)
102
+ if topo_name is None:
103
+ topo_name = getattr(self.topology, "_name", None)
104
+ if topo_name is None:
105
+ topo_name = "Topology"
106
+
107
+ fig, ax = plt.subplots(figsize=(10, 7))
108
+ fig.suptitle(topo_name, fontsize=16)
109
+ for link in getattr(self.topology, "links", []):
110
+ src_id = getattr(link, "source").id
111
+ tgt_id = getattr(link, "target").id
112
+ if src_id in node_id_to_xy and tgt_id in node_id_to_xy:
113
+ x0, y0 = node_id_to_xy[src_id]
114
+ x1, y1 = node_id_to_xy[tgt_id]
115
+ ax.plot(
116
+ [x0, x1], [y0, y1], color="gray", linewidth=1, alpha=0.7, zorder=2
117
+ )
118
+ gdf.plot(ax=ax, color="blue", markersize=40, zorder=5)
119
+ for x, y, name in zip(gdf.geometry.x, gdf.geometry.y, gdf["name"]):
120
+ ax.text(x, y, name, fontsize=8, ha="right",
121
+ va="bottom", color="black")
122
+ ctx.add_basemap(ax, source=ctx.providers.OpenStreetMap.Mapnik)
123
+ ax.set_axis_off()
124
+ ax.set_title(f"Nodes and links ({topo_name})")
125
+ plt.tight_layout()
126
+ plt.savefig(filename, dpi=dpi)
127
+ plt.close(fig)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: topolib
3
- Version: 0.4.2
3
+ Version: 0.6.0
4
4
  Summary: A compact Python library for modeling, analyzing, and visualizing optical network topologies.
5
5
  License: MIT
6
6
  License-File: LICENSE
@@ -21,6 +21,7 @@ Classifier: Topic :: Scientific/Engineering :: Information Analysis
21
21
  Classifier: Topic :: Software Development :: Libraries :: Python Modules
22
22
  Requires-Dist: contextily
23
23
  Requires-Dist: geopandas
24
+ Requires-Dist: jsonschema (>=4.0)
24
25
  Requires-Dist: matplotlib
25
26
  Requires-Dist: networkx (>=2.6)
26
27
  Requires-Dist: numpy (>=1.21)
@@ -49,9 +50,14 @@ Description-Content-Type: text/markdown
49
50
 
50
51
  ## 📂 Examples
51
52
 
52
- Explore ready-to-run usage examples in the [`examples/`](examples/) folder!
53
- - [Show topology on a map](examples/show_topology_in_map.py) 🗺️
54
- - More coming soon!
53
+
54
+ Explore ready-to-run usage examples in the [`examples/`](examples/) folder!
55
+
56
+ - [Show topology on a map](examples/show_topology_in_map.py) 🗺️
57
+ - [Show default topology in map](examples/show_default_topology_in_map.py) 🗺️
58
+ - [Export topology as PNG](examples/export_topology_png.py) 🖼️
59
+ - [Export topology to CSV and JSON](examples/export_csv_json.py) 📄
60
+ - [Export topology and k-shortest paths for FlexNetSim](examples/export_flexnetsim.py) 🔀
55
61
 
56
62
  ---
57
63
 
@@ -0,0 +1,47 @@
1
+ topolib/__init__.py,sha256=iLmy2rOkHS_4KZWMD8BgT7R3tLMKeaTCDVf3B4FyYxM,91
2
+ topolib/analysis/__init__.py,sha256=qvUC9wV_jQNQIlwJXk7LJ-dkTXhH1Ttn0lKWIdwBbrc,52
3
+ topolib/analysis/metrics.py,sha256=2o5PlMVzepDWwSQjzamtKemggqkxh9JuzzCUaeahfok,2555
4
+ topolib/assets/AMRES.json,sha256=PWQLEOOIpQzDelkWg27EUTg331Ewlqm-jIQGMNyIIdo,27082
5
+ topolib/assets/Abilene.json,sha256=5cnPMbjsNDjmpySdQDYQ2yd83zOFvCRjlAnbX1wyzgk,6010
6
+ topolib/assets/Bell_canada.json,sha256=pjsZBZcp6j-IP57P8MOlcBqnfnLkzbintKzgJxcC7ZE,19921
7
+ topolib/assets/Brazil.json,sha256=_4rSY46CKBd6ylpLLigaUuWjLrP83OYiYorg4wChmFU,14876
8
+ topolib/assets/CESNET.json,sha256=i6ebe-cDZJtTCDbbeuBo-dQwb7dhD4SRdc0I0N0Eczo,13739
9
+ topolib/assets/CORONET.json,sha256=dSpBSR-vBdxeG1IPcnjw5YYwpzujKMceBuLghGt3xQQ,42017
10
+ topolib/assets/China.json,sha256=L3co98t0MYzPApUi0Hv9i-QthDPHZQSsGcCvunspsGA,23820
11
+ topolib/assets/DT-14.json,sha256=IyNZIWelc2lW1eOa6nHOH4HRfCIOGZtBdwFUQhiS5is,9924
12
+ topolib/assets/DT-17.json,sha256=LBqGD3e3ad9nSaFlnJnrIWMk1eEVC6uF6zDElFzPUu8,10972
13
+ topolib/assets/DT-50.json,sha256=4Pe6R3eWaiHB_KOWO2Pprm3veHl6ttZA2dPyh_GxEGQ,31869
14
+ topolib/assets/ES-30.json,sha256=gXrrOGNveIlWNvO214FHcGo08pCCs1mElCRHXdvIJGY,20186
15
+ topolib/assets/EURO-16.json,sha256=LEd_oq9nY9XP-5wzrCcmhe3VI0D_iDlaNg1lAjeRHik,9513
16
+ topolib/assets/FR-43.json,sha256=QK4-95ETMw4C98jMzpgkpL8y2vlSkbiS7mN9-9QCEPw,26797
17
+ topolib/assets/FUNET.json,sha256=RtVbWVmJHGO-a8gSqCiGWkuxjfou-Ep1JWV4b9M2qIc,6650
18
+ topolib/assets/GCN-BG.json,sha256=e24fO_IlVUu6x9S2zpSJWBD7S9Obkw39TkHcKGzayDQ,18299
19
+ topolib/assets/GRNET.json,sha256=xJMwR4DGANRBcLdjv_8gWQp3ymuSSCR2Cws9_sAx9eg,36781
20
+ topolib/assets/HyperOne.json,sha256=jP-BT5jmozezD0AgOkwdb6nXyqiiL6TMy6BjjVOKEGE,5264
21
+ topolib/assets/IT-21.json,sha256=GmYsmC8jycG1WYGwRvVJtnrurZQ7uy8LN0Kmb8Zmg6w,13503
22
+ topolib/assets/India.json,sha256=7wiXKgWBIO0THTpV8pNE8TCriV-zfytI2lPKK6Y3Zoc,10839
23
+ topolib/assets/JPN-12.json,sha256=qz4uZAjE4GvLQnlBpKAiC9Zrp197r5hI8029hsRlDEY,6902
24
+ topolib/assets/KOREN.json,sha256=lKW2if-IdGxQsiX6vpysXpYw__3_6OTWeZ9-oD-h5Eg,5951
25
+ topolib/assets/NORDUNet.json,sha256=X934bx4bTyn98ASz8Eb0-UuEBxnR-3vTy14-gFn8Oms,16412
26
+ topolib/assets/NSFNet.json,sha256=LeU7h6H76HXEyIpUhlzuR6cbs6Q61eEgxmyUMaNUeEk,8375
27
+ topolib/assets/PANEURO.json,sha256=Xh_pmTBOwlusDhAUGpPzJz4tSRXbK-FTsN3Dnlbwf48,15969
28
+ topolib/assets/PAVLOV.json,sha256=YRDqlodGj-zqErX1cwk4bX-XuUkgP1CpiOmtlLIBmIk,9816
29
+ topolib/assets/PLN-12.json,sha256=oxKs0MTe-pEqD-kTa_LATWfDRswwAnlEFubeQlXMFRU,7135
30
+ topolib/assets/SANReN.json,sha256=VUe7JFbzmte6ED3lNyfm1cWhefsapeZ4P-zIG6-rZXc,3394
31
+ topolib/assets/SERBIA-MONTENEGRO.json,sha256=83Mk5yNju7B50JolE1uCwy8wQJgsaBzZ71xxhMGYOSc,2897
32
+ topolib/assets/Telefonica-21.json,sha256=Wom5SQn3lLL-z-ESZ3Du_Fz_ZQ2bzP2_bNhzmnmmW_I,13302
33
+ topolib/assets/Turk_Telekom.json,sha256=5yO0cgtJOmh6ulCCIb8g_nDFSmv8Wn52Yt_Oyoc1Y0w,11533
34
+ topolib/assets/UKNet.json,sha256=9BEkRM9YFeMMpih5kyDY34TsOGFzt5KBGsmgWd6KoB0,14210
35
+ topolib/assets/Vega_Telecom.json,sha256=E07ZCvG4exRj1a5DV8lqS3Sdo5tRm_Lc07IzIjP2EW0,17324
36
+ topolib/elements/__init__.py,sha256=RIQGFgI3_R7Saf679LaP8o8D8kVtM-JadZt6XufJcQ4,75
37
+ topolib/elements/link.py,sha256=oTOq_Uqj8YP8VQXOpQv9Yf2A2ozhpzEAZgFV6lRER0I,3377
38
+ topolib/elements/node.py,sha256=ZP-2MmtJBZkqMyoN2GEEDXrt2YfPJX6LbzLkM5upb-k,4956
39
+ topolib/topology/__init__.py,sha256=2VRhVm4ZvKBiTDB2T8BDmLZBpwGCVFRF3fvtxxC_d28,86
40
+ topolib/topology/path.py,sha256=oUNwmpBcS6LMMAJIxokROm3MVqr7vRR44M3Fh5ADq_w,2057
41
+ topolib/topology/topology.py,sha256=LfMfBtxCu8GIJJG3Dmmw_hIQwDWDTeDA31zwOpBcVnc,18354
42
+ topolib/visualization/__init__.py,sha256=wv065-KB5uDbTaQIASPVfMMW5sE76Bs-q0oai48vAzk,29
43
+ topolib/visualization/mapview.py,sha256=pgexEKu4ibet8lmGaEGLuAh6SGRdRSWFGXLS1xSgkbA,4968
44
+ topolib-0.6.0.dist-info/METADATA,sha256=UTKHu9xJiegA_7mqc0IiDpx7s2wl4CWqdXOrHBCKYCk,4318
45
+ topolib-0.6.0.dist-info/WHEEL,sha256=zp0Cn7JsFoX2ATtOhtaFYIiE2rmFAD4OcMhtUki8W3U,88
46
+ topolib-0.6.0.dist-info/licenses/LICENSE,sha256=kbnIP0XU6f2ualiTjEawdlU81IGPBbwc-_GF3N-1e9E,1081
47
+ topolib-0.6.0.dist-info/RECORD,,
@@ -1,18 +0,0 @@
1
- topolib/__init__.py,sha256=iLmy2rOkHS_4KZWMD8BgT7R3tLMKeaTCDVf3B4FyYxM,91
2
- topolib/analysis/__init__.py,sha256=qvUC9wV_jQNQIlwJXk7LJ-dkTXhH1Ttn0lKWIdwBbrc,52
3
- topolib/analysis/metrics.py,sha256=2o5PlMVzepDWwSQjzamtKemggqkxh9JuzzCUaeahfok,2555
4
- topolib/assets/Abilene_IXP.json,sha256=5cnPMbjsNDjmpySdQDYQ2yd83zOFvCRjlAnbX1wyzgk,6010
5
- topolib/assets/China_pop.json,sha256=v-bs5qib8-CB81rvBNNM9ssoelrNGuFrPEyRCht9YpY,22262
6
- topolib/assets/DT-50_pop.json,sha256=hCv1MCvipgdrQ34VT-qXJ68BdATriQ8ZObh0fLPqar4,29719
7
- topolib/elements/__init__.py,sha256=ZWSd5uwVtppJtMnZ30zrAdzXhUAYIK62RrUaH9rsWu0,180
8
- topolib/elements/link.py,sha256=BwjdCR8peh7dDpKunZodlIsjKcfvwjKxyQ3tmp1obb8,3778
9
- topolib/elements/node.py,sha256=uOnljwA3jcVR4utUfI-om4SIt_QBsEQt8QLW9uvjr3Y,4974
10
- topolib/topology/__init__.py,sha256=2VRhVm4ZvKBiTDB2T8BDmLZBpwGCVFRF3fvtxxC_d28,86
11
- topolib/topology/path.py,sha256=oUNwmpBcS6LMMAJIxokROm3MVqr7vRR44M3Fh5ADq_w,2057
12
- topolib/topology/topology.py,sha256=PzPx80TxWMcOwpOCh4fohcWT2YUra-4m04tBjqyMU40,5605
13
- topolib/visualization/__init__.py,sha256=wv065-KB5uDbTaQIASPVfMMW5sE76Bs-q0oai48vAzk,29
14
- topolib/visualization/mapview.py,sha256=4iKJMYsH6oFNj9tOcgSKLVRtoYfUuH3XLjShsGwUXcM,2799
15
- topolib-0.4.2.dist-info/METADATA,sha256=O2V7bL8xtAJOhNVmbLX0mHLj1ic5ZZu_3bbnFFbEzAw,3993
16
- topolib-0.4.2.dist-info/WHEEL,sha256=zp0Cn7JsFoX2ATtOhtaFYIiE2rmFAD4OcMhtUki8W3U,88
17
- topolib-0.4.2.dist-info/licenses/LICENSE,sha256=kbnIP0XU6f2ualiTjEawdlU81IGPBbwc-_GF3N-1e9E,1081
18
- topolib-0.4.2.dist-info/RECORD,,
File without changes