topologicpy 0.4.36__py3-none-any.whl → 0.4.38__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.
topologicpy/Color.py CHANGED
@@ -157,6 +157,33 @@ class Color:
157
157
  rgbList.append(alpha)
158
158
  return rgbList
159
159
 
160
+ @staticmethod
161
+ def HEXToRGB(hex_color):
162
+ """
163
+ Converts a hexadecimal color string to RGB color values.
164
+
165
+ Parameters
166
+ ----------
167
+ hex_color : str
168
+ A hexadecimal color string in the format '#RRGGBB'.
169
+
170
+ Returns
171
+ -------
172
+ tuple
173
+ A tuple containing three integers representing the RGB values.
174
+
175
+ """
176
+
177
+ hex_color = hex_color.lstrip('#')
178
+ if len(hex_color) != 6:
179
+ raise ValueError("Invalid hexadecimal color format. It should be a 6-digit hex value.")
180
+
181
+ r = int(hex_color[0:2], 16)
182
+ g = int(hex_color[2:4], 16)
183
+ b = int(hex_color[4:6], 16)
184
+
185
+ return (r, g, b)
186
+
160
187
  @staticmethod
161
188
  def PlotlyColor(color, alpha=1.0, useAlpha=False):
162
189
  """
@@ -189,3 +216,23 @@ class Color:
189
216
  if useAlpha:
190
217
  return "rgba("+str(color[0])+","+str(color[1])+","+str(color[2])+","+str(alpha)+")"
191
218
  return "rgb("+str(color[0])+","+str(color[1])+","+str(color[2])+")"
219
+
220
+ @staticmethod
221
+ def RGBToHex(rgb):
222
+ """
223
+ Converts RGB color values to a hexadecimal color string.
224
+
225
+ Parameters
226
+ ----------
227
+ rgb : tuple
228
+ A tuple containing three integers representing the RGB values.
229
+
230
+ Returns
231
+ -------
232
+ str
233
+ A hexadecimal color string in the format '#RRGGBB'.
234
+ """
235
+
236
+ r, g, b = rgb
237
+ hex_value = "#{:02x}{:02x}{:02x}".format(r, g, b)
238
+ return hex_value.upper()
topologicpy/Graph.py CHANGED
@@ -28,6 +28,16 @@ except:
28
28
  except:
29
29
  print("Graph - Error: Could not import numpy")
30
30
 
31
+ try:
32
+ from pyvis.network import Network
33
+ except:
34
+ call = [sys.executable, '-m', 'pip', 'install', 'pyvis', '-t', sys.path[0]]
35
+ subprocess.run(call)
36
+ try:
37
+ from pyvis.network import Network
38
+ except:
39
+ print("Graph - Error: Could not import pyvis")
40
+
31
41
  class _Tree:
32
42
  def __init__(self, node="", *children):
33
43
  self.node = node
@@ -4402,6 +4412,177 @@ class Graph:
4402
4412
  return None
4403
4413
  return graph.Path(vertexA, vertexB)
4404
4414
 
4415
+ @staticmethod
4416
+ def PyvisGraph(graph, path, overwrite=True, height=900, backgroundColor="white", fontColor="black", notebook=False,
4417
+ vertexSize=6, vertexSizeKey=None, vertexColor="black", vertexColorKey=None, vertexLabelKey=None, vertexGroupKey=None, vertexGroups=None, minVertexGroup=None, maxVertexGroup=None,
4418
+ edgeWeight=0, edgeWeightKey=None, showNeighbours=True, selectMenu=True, filterMenu=True, colorScale="viridis"):
4419
+ """
4420
+ Displays a pyvis graph. See https://pyvis.readthedocs.io/.
4421
+
4422
+ Parameters
4423
+ ----------
4424
+ graph : topologic.Graph
4425
+ The input graph.
4426
+ path : str
4427
+ The desired file path to the HTML file into which to save the pyvis graph.
4428
+ overwrite : bool , optional
4429
+ If set to True, the HTML file is overwritten.
4430
+ height : int , optional
4431
+ The desired figure height in pixels. The default is 900 pixels.
4432
+ backgroundColor : str, optional
4433
+ The desired background color for the figure. This can be a named color or a hexadecimal value. The default is 'white'.
4434
+ fontColor : str , optional
4435
+ The desired font color for the figure. This can be a named color or a hexadecimal value. The default is 'black'.
4436
+ notebook : bool , optional
4437
+ If set to True, the figure will be targeted at a Jupyter Notebook. Note that this is not working well. Pyvis has bugs. The default is False.
4438
+ vertexSize : int , optional
4439
+ The desired default vertex size. The default is 6.
4440
+ vertexSizeKey : str , optional
4441
+ If not set to None, the vertex size will be derived from the dictionary value set at this key. If set to "degree", the size of the vertex will be determined by its degree (number of neighbors). The default is None.
4442
+ vertexColor : int , optional
4443
+ The desired default vertex color. his can be a named color or a hexadecimal value. The default is 'black'.
4444
+ vertexColorKey : str , optional
4445
+ If not set to None, the vertex color will be derived from the dictionary value set at this key. The default is None.
4446
+ vertexLabelKey : str , optional
4447
+ If not set to None, the vertex label will be derived from the dictionary value set at this key. The default is None.
4448
+ vertexGroupKey : str , optional
4449
+ If not set to None, the vertex color will be determined by the group the vertex belongs to as derived from the value set at this key. The default is None.
4450
+ vertexGroups : list , optional
4451
+ The list of all possible vertex groups. This will help in vertex coloring. The default is None.
4452
+ minVertexGroup : int or float , optional
4453
+ If the vertex groups are numeric, specify the minimum value you wish to consider for vertex coloring. The default is None.
4454
+ maxVertexGroup : int or float , optional
4455
+ If the vertex groups are numeric, specify the maximum value you wish to consider for vertex coloring. The default is None.
4456
+
4457
+ edgeWeight : int , optional
4458
+ The desired default weight of the edge. This determines its thickness. The default is 0.
4459
+ edgeWeightKey : str, optional
4460
+ If not set to None, the edge weight will be derived from the dictionary value set at this key. If set to "length" or "distance", the weight of the edge will be determined by its geometric length. The default is None.
4461
+ showNeighbors : bool , optional
4462
+ If set to True, a list of neighbors is shown when you hover over a vertex. The default is True.
4463
+ selectMenu : bool , optional
4464
+ If set to True, a selection menu will be displayed. The default is True
4465
+ filterMenu : bool , optional
4466
+ If set to True, a filtering menu will be displayed. The default is True.
4467
+ colorScale : str , optional
4468
+ The desired type of plotly color scales to use (e.g. "viridis", "plasma"). The default is "viridis". For a full list of names, see https://plotly.com/python/builtin-colorscales/.
4469
+
4470
+ Returns
4471
+ -------
4472
+ None
4473
+ The pyvis graph is displayed either inline (notebook mode) or in a new browser window or tab.
4474
+
4475
+ """
4476
+ from topologicpy.Vertex import Vertex
4477
+ from topologicpy.Edge import Edge
4478
+ from topologicpy.Topology import Topology
4479
+ from topologicpy.Dictionary import Dictionary
4480
+ from topologicpy.Color import Color
4481
+ from os.path import exists
4482
+ net = Network(height=str(height)+"px", width="100%", bgcolor=backgroundColor, font_color=fontColor, select_menu=selectMenu, filter_menu=filterMenu, cdn_resources="remote", notebook=notebook)
4483
+ if notebook == True:
4484
+ net.prep_notebook()
4485
+
4486
+ vertices = Graph.Vertices(graph)
4487
+ edges = Graph.Edges(graph)
4488
+
4489
+ nodes = [i for i in range(len(vertices))]
4490
+ if not vertexLabelKey == None:
4491
+ node_labels = [Dictionary.ValueAtKey(Topology.Dictionary(v), vertexLabelKey) for v in vertices]
4492
+ else:
4493
+ node_labels = list(range(len(vertices)))
4494
+ if not vertexColorKey == None:
4495
+ colors = [Dictionary.ValueAtKey(Topology.Dictionary(v), vertexColorKey) for v in vertices]
4496
+ else:
4497
+ colors = [vertexColor for v in vertices]
4498
+ node_titles = [str(n) for n in node_labels]
4499
+ group = ""
4500
+ if not vertexGroupKey == None:
4501
+ colors = []
4502
+ if vertexGroups:
4503
+ if len(vertexGroups) > 0:
4504
+ if type(vertexGroups[0]) == int or type(vertexGroups[0]) == float:
4505
+ if not minVertexGroup:
4506
+ minVertexGroup = min(vertexGroups)
4507
+ if not maxVertexGroup:
4508
+ maxVertexGroup = max(vertexGroups)
4509
+ else:
4510
+ minVertexGroup = 0
4511
+ maxVertexGroup = len(vertexGroups) - 1
4512
+ else:
4513
+ minVertexGroup = 0
4514
+ maxVertexGroup = 1
4515
+ for m, v in enumerate(vertices):
4516
+ group = ""
4517
+ d = Topology.Dictionary(v)
4518
+ if d:
4519
+ try:
4520
+ group = Dictionary.ValueAtKey(d, key=vertexGroupKey) or None
4521
+ except:
4522
+ group = ""
4523
+ try:
4524
+ if type(group) == int or type(group) == float:
4525
+ if group < minVertexGroup:
4526
+ group = minVertexGroup
4527
+ if group > maxVertexGroup:
4528
+ group = maxVertexGroup
4529
+ color = Color.RGBToHex(Color.ByValueInRange(group, minValue=minVertexGroup, maxValue=maxVertexGroup, colorScale=colorScale))
4530
+ else:
4531
+ color = Color.RGBToHex(Color.ByValueInRange(vertexGroups.index(group), minValue=minVertexGroup, maxValue=maxVertexGroup, colorScale=colorScale))
4532
+ colors.append(color)
4533
+ except:
4534
+ colors.append(vertexColor)
4535
+ net.add_nodes(nodes, label=node_labels, title=node_titles, color=colors)
4536
+
4537
+ for e in edges:
4538
+ w = edgeWeight
4539
+ if not edgeWeightKey == None:
4540
+ d = Topology.Dictionary(e)
4541
+ if edgeWeightKey.lower() == "length" or edgeWeightKey.lower() == "distance":
4542
+ w = Edge.Length(e)
4543
+ else:
4544
+ weightValue = Dictionary.ValueAtKey(d, edgeWeightKey)
4545
+ if weightValue:
4546
+ w = weightValue
4547
+ sv = Edge.StartVertex(e)
4548
+ ev = Edge.EndVertex(e)
4549
+ svi = Vertex.Index(sv, vertices)
4550
+ evi = Vertex.Index(ev, vertices)
4551
+ net.add_edge(svi, evi, weight=w)
4552
+ net.inherit_edge_colors(False)
4553
+
4554
+ # add neighbor data to node hover data and compute vertexSize
4555
+ if showNeighbours == True or not vertexSizeKey == None:
4556
+ for i, node in enumerate(net.nodes):
4557
+ if showNeighbours == True:
4558
+ neighbors = list(net.neighbors(node["id"]))
4559
+ neighbor_labels = [str(net.nodes[n]["id"])+": "+net.nodes[n]["label"] for n in neighbors]
4560
+ node["title"] = str(node["id"])+": "+node["title"]+"\n"
4561
+ node["title"] += "Neighbors:\n" + "\n".join(neighbor_labels)
4562
+ vs = vertexSize
4563
+ if not vertexSizeKey == None:
4564
+ d = Topology.Dictionary(vertices[i])
4565
+ if vertexSizeKey.lower() == "neighbours" or vertexSizeKey.lower() == "degree":
4566
+ temp_vs = Graph.VertexDegree(graph, vertices[i])
4567
+ else:
4568
+ temp_vs = Dictionary.ValueAtKey(vertices[i], vertexSizeKey)
4569
+ if temp_vs:
4570
+ vs = temp_vs
4571
+ node["value"] = vs
4572
+
4573
+ # Make sure the file extension is .html
4574
+ ext = path[len(path)-5:len(path)]
4575
+ if ext.lower() != ".html":
4576
+ path = path+".html"
4577
+ if not overwrite and exists(path):
4578
+ print("Graph.PyvisGraph - Error: a file already exists at the specified path and overwrite is set to False. Returning None.")
4579
+ return None
4580
+ if overwrite == True:
4581
+ net.save_graph(path)
4582
+ net.show_buttons()
4583
+ net.show(path, notebook=notebook)
4584
+ return None
4585
+
4405
4586
  @staticmethod
4406
4587
  def RemoveEdge(graph, edge, tolerance=0.0001):
4407
4588
  """
topologicpy/Plotly.py CHANGED
@@ -388,7 +388,7 @@ class Plotly:
388
388
  faceMinGroup=None, faceMaxGroup=None,
389
389
  showFaceLegend=False, faceLegendLabel="Topology Faces", faceLegendRank=3,
390
390
  faceLegendGroup=3,
391
- intensityKey=None, colorScale="Viridis", tolerance=0.0001):
391
+ intensityKey=None, colorScale="Viridis", mantissa=4, tolerance=0.0001):
392
392
  """
393
393
  Creates plotly face, edge, and vertex data.
394
394
 
@@ -493,6 +493,8 @@ class Plotly:
493
493
  If not None, the dictionary of each vertex is searched for the value associated with the intensity key. This value is then used to color-code the vertex based on the colorScale. The default is None.
494
494
  colorScale : str , optional
495
495
  The desired type of plotly color scales to use (e.g. "Viridis", "Plasma"). The default is "Viridis". For a full list of names, see https://plotly.com/python/builtin-colorscales/.
496
+ mantissa : int , optional
497
+ The desired length of the mantissa. The default is 4.
496
498
  tolerance : float , optional
497
499
  The desired tolerance. The default is 0.0001.
498
500
 
@@ -528,9 +530,9 @@ class Plotly:
528
530
  minGroup = 0
529
531
  maxGroup = 1
530
532
  for m, v in enumerate(vertices):
531
- x.append(v[0])
532
- y.append(v[1])
533
- z.append(v[2])
533
+ x.append(round(v[0], mantissa))
534
+ y.append(round(v[1], mantissa))
535
+ z.append(round(v[2], mantissa))
534
536
  label = ""
535
537
  group = ""
536
538
  if len(dictionaries) > 0:
@@ -560,9 +562,9 @@ class Plotly:
560
562
  labels.append(label)
561
563
  else:
562
564
  for v in vertices:
563
- x.append(v[0])
564
- y.append(v[1])
565
- z.append(v[2])
565
+ x.append(round(v[0], mantissa))
566
+ y.append(round(v[1], mantissa))
567
+ z.append(round(v[2], mantissa))
566
568
 
567
569
  if len(list(set(groupList))) < 2:
568
570
  groupList = color
@@ -607,9 +609,9 @@ class Plotly:
607
609
  for m, e in enumerate(edges):
608
610
  sv = vertices[e[0]]
609
611
  ev = vertices[e[1]]
610
- x+=[sv[0],ev[0], None] # x-coordinates of edge ends
611
- y+=[sv[1],ev[1], None] # y-coordinates of edge ends
612
- z+=[sv[2],ev[2], None] # z-coordinates of edge ends
612
+ x+=[round(sv[0],5),round(ev[0],mantissa), None] # x-coordinates of edge ends
613
+ y+=[round(sv[1],5),round(ev[1],mantissa), None] # y-coordinates of edge ends
614
+ z+=[round(sv[2],5),round(ev[2],mantissa), None] # z-coordinates of edge ends
613
615
  label = ""
614
616
  group = ""
615
617
  if len(dictionaries) > 0:
@@ -641,9 +643,9 @@ class Plotly:
641
643
  for e in edges:
642
644
  sv = vertices[e[0]]
643
645
  ev = vertices[e[1]]
644
- x+=[sv[0],ev[0], None] # x-coordinates of edge ends
645
- y+=[sv[1],ev[1], None] # y-coordinates of edge ends
646
- z+=[sv[2],ev[2], None] # z-coordinates of edge ends
646
+ x+=[round(sv[0],mantissa),round(ev[0],mantissa), None] # x-coordinates of edge ends
647
+ y+=[round(sv[1],mantissa),round(ev[1],mantissa), None] # y-coordinates of edge ends
648
+ z+=[round(sv[2],mantissa),round(ev[2],mantissa), None] # z-coordinates of edge ends
647
649
 
648
650
  if len(list(set(groupList))) < 2:
649
651
  groupList = color
@@ -668,9 +670,9 @@ class Plotly:
668
670
  y = []
669
671
  z = []
670
672
  for v in vertices:
671
- x.append(v[0])
672
- y.append(v[1])
673
- z.append(v[2])
673
+ x.append(round(v[0], mantissa))
674
+ y.append(round(v[1], mantissa))
675
+ z.append(round(v[2], mantissa))
674
676
  i = []
675
677
  j = []
676
678
  k = []
@@ -951,7 +953,8 @@ class Plotly:
951
953
  marginLeft=0,
952
954
  marginRight=0,
953
955
  marginTop=40,
954
- marginBottom=0):
956
+ marginBottom=0,
957
+ mantissa=4):
955
958
  """
956
959
  Returns a Plotly Figure of the input matrix.
957
960
 
@@ -997,6 +1000,8 @@ class Plotly:
997
1000
  The desired top margin in pixels. The default is 40.
998
1001
  marginBottom : int , optional
999
1002
  The desired bottom margin in pixels. The default is 0.
1003
+ mantissa : int , optional
1004
+ The desired number of digits of the mantissa. The default is 4.
1000
1005
 
1001
1006
  """
1002
1007
  #import plotly.figure_factory as ff
@@ -1033,7 +1038,7 @@ class Plotly:
1033
1038
  "font": {"color": "black"},
1034
1039
  "bgcolor": "white",
1035
1040
  "opacity": 0.5,
1036
- "text": str(round(value,2)),
1041
+ "text": str(round(value, mantissa)),
1037
1042
  "xref": "x1",
1038
1043
  "yref": "y1",
1039
1044
  "showarrow": False
@@ -1054,7 +1059,7 @@ class Plotly:
1054
1059
  "font": {"color": "black"},
1055
1060
  "bgcolor": "white",
1056
1061
  "opacity": 0.5,
1057
- "text": str(round(value,2)),
1062
+ "text": str(round(value,mantissa)),
1058
1063
  "xref": "x1",
1059
1064
  "yref": "y1",
1060
1065
  "showarrow": False
@@ -1067,9 +1072,9 @@ class Plotly:
1067
1072
  maxRow = sum(row)
1068
1073
  for j in range(len(row)):
1069
1074
  if maxRow == 0:
1070
- new_row.append(round(0, 3))
1075
+ new_row.append(round(0, mantissa))
1071
1076
  else:
1072
- new_row.append(round(float(row[j])/float(maxRow), 3))
1077
+ new_row.append(round(float(row[j])/float(maxRow), mantissa))
1073
1078
  new_matrix.append(new_row)
1074
1079
  data = go.Heatmap(z=new_matrix, y=yCategories, x=xCategories, zmin=minValue, zmax=maxValue, showscale=showScale, colorscale=colors)
1075
1080
 
@@ -1544,7 +1549,7 @@ class Plotly:
1544
1549
 
1545
1550
  """
1546
1551
  if not isinstance(topology, topologic.Topology):
1547
- print("Topology.Show - Error: the input topology is not a valid topology. Returning None.")
1552
+ print("Plotly.FigureByTopology - Error: the input topology is not a valid topology. Returning None.")
1548
1553
  return None
1549
1554
  data = Plotly.DataByTopology(topology=topology,
1550
1555
  showVertices=showVertices, vertexSize=vertexSize, vertexColor=vertexColor,
@@ -1817,7 +1822,11 @@ class Plotly:
1817
1822
  return None
1818
1823
  if not camera == None:
1819
1824
  figure = Plotly.SetCamera(figure, camera=camera, target=target, up=up)
1820
- figure.show(renderer=renderer)
1825
+ if renderer.lower() == "offline":
1826
+ import plotly.offline as ofl
1827
+ ofl.plot(figure)
1828
+ else:
1829
+ figure.show(renderer=renderer)
1821
1830
  return None
1822
1831
 
1823
1832
  @staticmethod
@@ -1838,7 +1847,7 @@ class Plotly:
1838
1847
  'notebook', 'notebook_connected', 'kaggle', 'azure', 'colab',
1839
1848
  'cocalc', 'databricks', 'json', 'png', 'jpeg', 'jpg', 'svg',
1840
1849
  'pdf', 'browser', 'firefox', 'chrome', 'chromium', 'iframe',
1841
- 'iframe_connected', 'sphinx_gallery', 'sphinx_gallery_png']
1850
+ 'iframe_connected', 'sphinx_gallery', 'sphinx_gallery_png', 'offline']
1842
1851
 
1843
1852
  @staticmethod
1844
1853
  def ExportToImage(figure, path, format="png", width="1920", height="1080"):