topologicpy 0.3.0__py3-none-any.whl → 0.3.2__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/Plotly.py CHANGED
@@ -10,6 +10,7 @@ from topologicpy.Cell import Cell
10
10
  from topologicpy.CellComplex import CellComplex
11
11
  from topologicpy.Cluster import Cluster
12
12
  from topologicpy.Topology import Topology
13
+ import numpy as np
13
14
 
14
15
  class Plotly:
15
16
  @staticmethod
@@ -638,6 +639,7 @@ class Plotly:
638
639
  #data.append(vertexData(vertices, dictionaries=[], vertexColor=vertexColor, vertexSize=5, vertexLabelKey=vertexLabelKey, vertexGroupKey=vertexGroupKey, vertexGroups=vertexGroups))
639
640
  return data
640
641
 
642
+
641
643
  @staticmethod
642
644
  def FigureByConfusionMatrix(matrix,
643
645
  categories=[],
@@ -661,7 +663,92 @@ class Plotly:
661
663
 
662
664
  Parameters
663
665
  ----------
664
- matrix : list
666
+ matrix : list or numpy.array
667
+ The matrix to display.
668
+ categories : list
669
+ The list of categories to use on the X and Y axes.
670
+ minValue : float , optional
671
+ The desired minimum value to use for the color scale. If set to None, the minmum value found in the input matrix will be used. The default is None.
672
+ maxValue : float , optional
673
+ The desired maximum value to use for the color scale. If set to None, the maximum value found in the input matrix will be used. The default is None.
674
+ title : str , optional
675
+ The desired title to display. The default is "Confusion Matrix".
676
+ xTitle : str , optional
677
+ The desired X-axis title to display. The default is "Actual".
678
+ yTitle : str , optional
679
+ The desired Y-axis title to display. The default is "Predicted".
680
+ width : int , optional
681
+ The desired width of the figure. The default is 950.
682
+ height : int , optional
683
+ The desired height of the figure. The default is 500.
684
+ showScale : bool , optional
685
+ If set to True, a color scale is shown on the right side of the figure. The default is True.
686
+ colorScale : str , optional
687
+ 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/.
688
+ colorSamples : int , optional
689
+ The number of discrete color samples to use for displaying the data. The default is 10.
690
+ backgroundColor : str , optional
691
+ The desired background color. This can be any plotly color string and may be specified as:
692
+ - A hex string (e.g. '#ff0000')
693
+ - An rgb/rgba string (e.g. 'rgb(255,0,0)')
694
+ - An hsl/hsla string (e.g. 'hsl(0,100%,50%)')
695
+ - An hsv/hsva string (e.g. 'hsv(0,100%,100%)')
696
+ - A named CSS color.
697
+ The default is 'rgba(0,0,0,0)' (transparent).
698
+ marginLeft : int , optional
699
+ The desired left margin in pixels. The default is 0.
700
+ marginRight : int , optional
701
+ The desired right margin in pixels. The default is 0.
702
+ marginTop : int , optional
703
+ The desired top margin in pixels. The default is 40.
704
+ marginBottom : int , optional
705
+ The desired bottom margin in pixels. The default is 0.
706
+
707
+ """
708
+
709
+ return Plotly.FigureByMatrix(matrix,
710
+ xCategories=categories,
711
+ minValue=minValue,
712
+ maxValue=maxValue,
713
+ title=title,
714
+ xTitle=xTitle,
715
+ yTitle=yTitle,
716
+ width=width,
717
+ height=height,
718
+ showScale=showScale,
719
+ colorScale=colorScale,
720
+ colorSamples=colorSamples,
721
+ backgroundColor=backgroundColor,
722
+ marginLeft=marginLeft,
723
+ marginRight=marginRight,
724
+ marginTop=marginTop,
725
+ marginBottom=marginBottom)
726
+
727
+ @staticmethod
728
+ def FigureByMatrix(matrix,
729
+ xCategories=[],
730
+ yCategories=[],
731
+ minValue=None,
732
+ maxValue=None,
733
+ title="Matrix",
734
+ xTitle = "X Axis",
735
+ yTitle = "Y Axis",
736
+ width=950,
737
+ height=950,
738
+ showScale = False,
739
+ colorScale='gray',
740
+ colorSamples=10,
741
+ backgroundColor='rgba(0,0,0,0)',
742
+ marginLeft=0,
743
+ marginRight=0,
744
+ marginTop=40,
745
+ marginBottom=0):
746
+ """
747
+ Returns a Plotly Figure of the input matrix.
748
+
749
+ Parameters
750
+ ----------
751
+ matrix : list or numpy.array
665
752
  The matrix to display.
666
753
  categories : list
667
754
  The list of categories to use on the X and Y axes.
@@ -709,20 +796,27 @@ class Plotly:
709
796
 
710
797
  annotations = []
711
798
 
712
- # Transpose the confusion matrix
713
- matrix = matrix.T
799
+ if isinstance(matrix, list):
800
+ matrix = np.array(matrix)
714
801
  colors = px.colors.sample_colorscale(colorScale, [n/(colorSamples -1) for n in range(colorSamples)])
715
- if not minValue:
716
- minValue = 0
717
- if not maxValue:
802
+
803
+ if not xCategories:
804
+ xCategories = [x for x in range(len(matrix[0]))]
805
+ if not yCategories:
806
+ yCategories = [y for y in range(len(matrix))]
807
+
808
+ if not maxValue or not minValue:
718
809
  max_values = []
719
- for i, row in enumerate(matrix):
810
+ min_values = []
811
+ for i in range(len(matrix)):
812
+ row = matrix[i]
720
813
  max_values.append(max(row))
814
+ min_values.append(min(row))
721
815
  for j, value in enumerate(row):
722
816
  annotations.append(
723
817
  {
724
- "x": categories[j],
725
- "y": categories[i],
818
+ "x": xCategories[j],
819
+ "y": yCategories[i],
726
820
  "font": {"color": "black"},
727
821
  "bgcolor": "white",
728
822
  "opacity": 0.5,
@@ -732,14 +826,18 @@ class Plotly:
732
826
  "showarrow": False
733
827
  }
734
828
  )
735
- maxValue = max(max_values)
829
+ if not minValue:
830
+ minValueB = min(min_values)
831
+ if not maxValue:
832
+ maxValue = max(max_values)
736
833
  else:
737
- for i, row in enumerate(matrix):
834
+ for i in range(len(matrix)):
835
+ row = matrix[i]
738
836
  for j, value in enumerate(row):
739
837
  annotations.append(
740
838
  {
741
- "x": categories[j],
742
- "y": categories[i],
839
+ "x": xCategories[j],
840
+ "y": yCategories[i],
743
841
  "font": {"color": "black"},
744
842
  "bgcolor": "white",
745
843
  "opacity": 0.5,
@@ -749,7 +847,15 @@ class Plotly:
749
847
  "showarrow": False
750
848
  }
751
849
  )
752
- data = go.Heatmap(z=matrix, y=categories, x=categories, zmin=minValue, zmax=maxValue, showscale=showScale, colorscale=colors)
850
+ new_matrix = []
851
+ for i in range(len(matrix)):
852
+ row = matrix[i]
853
+ new_row = []
854
+ maxRow = sum(row)
855
+ for j in range(len(row)):
856
+ new_row.append(round(float(row[j])/float(maxRow), 3))
857
+ new_matrix.append(new_row)
858
+ data = go.Heatmap(z=new_matrix, y=yCategories, x=xCategories, zmin=minValue, zmax=maxValue, showscale=showScale, colorscale=colors)
753
859
 
754
860
  layout = {
755
861
  "width": width,
@@ -763,8 +869,8 @@ class Plotly:
763
869
  "margin":dict(l=marginLeft, r=marginRight, t=marginTop, b=marginBottom)
764
870
  }
765
871
  fig = go.Figure(data=data, layout=layout)
766
- fig.update_xaxes( tickvals=categories)
767
- fig.update_yaxes( tickvals=categories)
872
+ fig.update_xaxes( tickvals=xCategories)
873
+ fig.update_yaxes( tickvals=yCategories)
768
874
  return fig
769
875
 
770
876
  @staticmethod
topologicpy/Topology.py CHANGED
@@ -3605,19 +3605,20 @@ class Topology():
3605
3605
  dy = y2 - y1
3606
3606
  dz = z2 - z1
3607
3607
  dist = math.sqrt(dx**2 + dy**2 + dz**2)
3608
+ world_origin = Vertex.ByCoordinates(0,0,0)
3609
+
3608
3610
  phi = math.degrees(math.atan2(dy, dx)) # Rotation around Y-Axis
3609
- if dist < tolerance:
3611
+ if dist < 0.0001:
3610
3612
  theta = 0
3611
3613
  else:
3612
3614
  theta = math.degrees(math.acos(dz/dist)) # Rotation around Z-Axis
3613
- world_origin = Vertex.ByCoordinates(0,0,0)
3614
- returnTopology = Topology.Rotate(topology, world_origin, 0, 0, 1, -phi)
3615
- returnTopology = Topology.Rotate(returnTopology, world_origin, 0, 1, 0, -theta)
3615
+ returnTopology = Topology.Rotate(topology, world_origin, 0, 1, 0, theta)
3616
+ returnTopology = Topology.Rotate(returnTopology, world_origin, 0, 0, 1, phi)
3616
3617
  returnTopology = Topology.Place(returnTopology, world_origin, origin)
3617
3618
  return returnTopology
3618
3619
 
3619
3620
  @staticmethod
3620
- def Place(topology, oldLocation=None, newLocation=None):
3621
+ def Place(topology, originA=None, originB=None):
3621
3622
  """
3622
3623
  Places the input topology at the specified location.
3623
3624
 
@@ -3625,9 +3626,9 @@ class Topology():
3625
3626
  ----------
3626
3627
  topology : topologic.Topology
3627
3628
  The input topology.
3628
- oldLocation : topologic.Vertex , optional
3629
+ originA : topologic.Vertex , optional
3629
3630
  The old location to use as the origin of the movement. If set to None, the centroid of the input topology is used. The default is None.
3630
- newLocation : topologic.Vertex , optional
3631
+ originB : topologic.Vertex , optional
3631
3632
  The new location at which to place the topology. If set to None, the world origin (0,0,0) is used. The default is None.
3632
3633
 
3633
3634
  Returns
@@ -3639,14 +3640,14 @@ class Topology():
3639
3640
  from topologicpy.Vertex import Vertex
3640
3641
  if not isinstance(topology, topologic.Topology):
3641
3642
  return None
3642
- if not isinstance(oldLocation, topologic.Vertex):
3643
- oldLocation = Topology.Centroid(topology)
3644
- if not isinstance(newLocation, topologic.Vertex):
3645
- newLocation = Vertex.ByCoordinates(0,0,0)
3646
-
3647
- x = newLocation.X() - oldLocation.X()
3648
- y = newLocation.Y() - oldLocation.Y()
3649
- z = newLocation.Z() - oldLocation.Z()
3643
+ if not isinstance(originA, topologic.Vertex):
3644
+ originA = Topology.Centroid(topology)
3645
+ if not isinstance(originA, topologic.Vertex):
3646
+ originA = Vertex.ByCoordinates(0,0,0)
3647
+
3648
+ x = originB.X() - originA.X()
3649
+ y = originB.Y() - originA.Y()
3650
+ z = originB.Z() - originA.Z()
3650
3651
  newTopology = None
3651
3652
  try:
3652
3653
  newTopology = Topology.Translate(topology, x, y, z)
@@ -4787,6 +4788,8 @@ class Topology():
4787
4788
  _ = topology.Clusters(None, subTopologies)
4788
4789
  elif subTopologyType.lower() == "aperture":
4789
4790
  _ = topology.Apertures(subTopologies)
4791
+ if not subTopologies:
4792
+ return [] # Make sure to return an empty list instead of None
4790
4793
  return subTopologies
4791
4794
 
4792
4795
 
@@ -4840,6 +4843,8 @@ class Topology():
4840
4843
  topology.Cluster(hostTopology, superTopologies)
4841
4844
  else:
4842
4845
  return None
4846
+ if not superTopologies:
4847
+ return [] # Make sure you return an empty list instead of None
4843
4848
  return superTopologies
4844
4849
 
4845
4850
  @staticmethod
@@ -5079,7 +5084,7 @@ class Topology():
5079
5084
  return topologic.TopologyUtility.Translate(topology, x, y, z)
5080
5085
 
5081
5086
  @staticmethod
5082
- def TranslateByDirectionDistance(topology, direction, distance):
5087
+ def TranslateByDirectionDistance(topology, direction=[0,0,0], distance=0):
5083
5088
  """
5084
5089
  Translates (moves) the input topology along the input direction by the specified distance.
5085
5090
 
@@ -5087,12 +5092,10 @@ class Topology():
5087
5092
  ----------
5088
5093
  topology : topologic.topology
5089
5094
  The input topology.
5090
- x : float , optional
5091
- The x translation value. The default is 0.
5092
- y : float , optional
5093
- The y translation value. The default is 0.
5094
- z : float , optional
5095
- The z translation value. The default is 0.
5095
+ direction : list , optional
5096
+ The direction vector in which the topology should be moved. The default is [0,0,0]
5097
+ distance : float , optional
5098
+ The distance by which the toplogy should be moved. The default is 0.
5096
5099
 
5097
5100
  Returns
5098
5101
  -------
@@ -5104,7 +5107,7 @@ class Topology():
5104
5107
  if not isinstance(topology, topologic.Topology):
5105
5108
  return None
5106
5109
  v = Vector.SetMagnitude(direction, distance)
5107
- return topologic.TopologyUtility.Translate(topology, v[0], v[1], v[2])
5110
+ return Topology.Translate(topology, v[0], v[1], v[2])
5108
5111
 
5109
5112
 
5110
5113
  @staticmethod
topologicpy/Vertex.py CHANGED
@@ -6,7 +6,7 @@ import collections
6
6
 
7
7
  class Vertex(Topology):
8
8
  @staticmethod
9
- def AreIpsilateral(vertices, face):
9
+ def AreIpsilateral(vertices: list, face: topologic.Face) -> bool:
10
10
  """
11
11
  Returns True if the two input vertices are on the same side of the input face. Returns False otherwise. If at least one of the vertices is on the face, this method return True.
12
12
 
@@ -62,7 +62,7 @@ class Vertex(Topology):
62
62
  return True
63
63
 
64
64
  @staticmethod
65
- def AreOnSameSide(vertices, face):
65
+ def AreOnSameSide(vertices: list, face: topologicpy.Face.Face) -> bool:
66
66
  """
67
67
  Returns True if the two input vertices are on the same side of the input face. Returns False otherwise. If at least one of the vertices is on the face, this method return True.
68
68
 
@@ -82,7 +82,7 @@ class Vertex(Topology):
82
82
  return IsIpsileteral(vertices, face)
83
83
 
84
84
  @staticmethod
85
- def AreOnSameSideCluster(cluster, face):
85
+ def AreOnSameSideCluster(cluster: topologic.Cluster, face: topologic.Face) -> bool:
86
86
  """
87
87
  Returns True if the two input vertices are on the same side of the input face. Returns False otherwise. If at least one of the vertices is on the face, this method return True.
88
88
 
@@ -106,18 +106,18 @@ class Vertex(Topology):
106
106
  return AreIpsilateral(vertices, face)
107
107
 
108
108
  @staticmethod
109
- def ByCoordinates(x, y, z):
109
+ def ByCoordinates(x: float = 0, y: float = 0, z: float = 0) -> topologic.Vertex:
110
110
  """
111
111
  Creates a vertex at the coordinates specified by the x, y, z inputs.
112
112
 
113
113
  Parameters
114
114
  ----------
115
- x : float
116
- The X coordinate.
117
- y : float
118
- The Y coordinate.
119
- z : float
120
- The Z coodinate.
115
+ x : float , optional
116
+ The X coordinate. The default is 0.
117
+ y : float , optional
118
+ The Y coordinate. The default is 0.
119
+ z : float , optional
120
+ The Z coordinate. The defaults is 0.
121
121
 
122
122
  Returns
123
123
  -------
@@ -133,7 +133,7 @@ class Vertex(Topology):
133
133
  return vertex
134
134
 
135
135
  @staticmethod
136
- def Coordinates(vertex, outputType="xyz", mantissa=4):
136
+ def Coordinates(vertex: topologic.Vertex, outputType: str = "xyz", mantissa: int = 4) -> list:
137
137
  """
138
138
  Returns the coordinates of the input vertex.
139
139
 
@@ -176,9 +176,8 @@ class Vertex(Topology):
176
176
  output.append(z)
177
177
  return output
178
178
 
179
-
180
179
  @staticmethod
181
- def Distance(vertex, topology, mantissa=4):
180
+ def Distance(vertex: topologic.Vertex, topology: topologic.Topology, mantissa: int = 4) -> float:
182
181
  """
183
182
  Returns the distance between the input vertex and the input topology.
184
183
 
@@ -202,7 +201,7 @@ class Vertex(Topology):
202
201
  return round(topologic.VertexUtility.Distance(vertex, topology), mantissa)
203
202
 
204
203
  @staticmethod
205
- def EnclosingCell(vertex, topology, exclusive=True, tolerance=0.0001):
204
+ def EnclosingCell(vertex: topologic.Vertex, topology: topologic.Topology, exclusive: bool = True, tolerance: float = 0.0001) -> list:
206
205
  """
207
206
  Returns the list of Cells found in the input topology that enclose the input vertex.
208
207
 
@@ -257,7 +256,7 @@ class Vertex(Topology):
257
256
  return enclosingCells
258
257
 
259
258
  @staticmethod
260
- def Index(vertex, vertices, strict=False, tolerance=0.0001):
259
+ def Index(vertex: topologic.Vertex, vertices: list, strict: bool = False, tolerance: float = 0.0001) -> int:
261
260
  """
262
261
  Returns index of the input vertex in the input list of vertices
263
262
 
@@ -291,12 +290,13 @@ class Vertex(Topology):
291
290
  if Topology.IsSame(vertex, vertices[i]):
292
291
  return i
293
292
  else:
294
- if Vertex.Distance(vertex, vertices[i]) < tolerance:
293
+ d = Vertex.Distance(vertex, vertices[i])
294
+ if d < tolerance:
295
295
  return i
296
296
  return None
297
297
 
298
298
  @staticmethod
299
- def IsInside(vertex, topology, tolerance=0.0001):
299
+ def IsInside(vertex: topologic.Vertex, topology: topologic.Topology, tolerance: float = 0.0001) -> bool:
300
300
  """
301
301
  Returns True if the input vertex is inside the input topology. Returns False otherwise.
302
302
 
@@ -372,7 +372,7 @@ class Vertex(Topology):
372
372
  return False
373
373
 
374
374
  @staticmethod
375
- def NearestVertex(vertex, topology, useKDTree=True):
375
+ def NearestVertex(vertex: topologic.Vertex, topology: topologic.Topology, useKDTree: bool = True) -> topologic.Vertex:
376
376
  """
377
377
  Returns the vertex found in the input topology that is the nearest to the input vertex.
378
378
 
@@ -514,9 +514,22 @@ class Vertex(Topology):
514
514
  sorted_indices = [x for _, x in sorted(zip(distances, indices))]
515
515
  return vertices[sorted_indices[0]]
516
516
 
517
+ @staticmethod
518
+ def Origin() -> topologic.Vertex:
519
+ """
520
+ Returns a vertex with coordinates (0,0,0)
521
+
522
+ Parameters
523
+ -----------
524
+
525
+ Return
526
+ -----------
527
+ topologic.Vertex
528
+ """
529
+ return Vertex.ByCoordinates(0,0,0)
517
530
 
518
531
  @staticmethod
519
- def Project(vertex, face, direction=None, mantissa=4, tolerance=0.0001):
532
+ def Project(vertex: topologic.Vertex, face: topologic.Face, direction: bool = None, mantissa: int = 4, tolerance: float = 0.0001) -> topologic.Vertex:
520
533
  """
521
534
  Returns a vertex that is the projection of the input vertex unto the input face.
522
535
 
@@ -567,7 +580,7 @@ class Vertex(Topology):
567
580
  return None
568
581
 
569
582
  @staticmethod
570
- def X(vertex, mantissa=4):
583
+ def X(vertex: topologic.Vertex, mantissa: int = 4) -> float:
571
584
  """
572
585
  Returns the X coordinate of the input vertex.
573
586
 
@@ -589,7 +602,7 @@ class Vertex(Topology):
589
602
  return round(vertex.X(), mantissa)
590
603
 
591
604
  @staticmethod
592
- def Y(vertex, mantissa=4):
605
+ def Y(vertex: topologic.Vertex, mantissa: int = 4) -> float:
593
606
  """
594
607
  Returns the Y coordinate of the input vertex.
595
608
 
@@ -611,7 +624,7 @@ class Vertex(Topology):
611
624
  return round(vertex.Y(), mantissa)
612
625
 
613
626
  @staticmethod
614
- def Z(vertex, mantissa=4):
627
+ def Z(vertex: topologic.Vertex, mantissa: int = 4) -> float:
615
628
  """
616
629
  Returns the Z coordinate of the input vertex.
617
630