topologicpy 0.5.3__py3-none-any.whl → 0.5.5__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/Graph.py CHANGED
@@ -337,7 +337,7 @@ class Graph:
337
337
  elif (len(gk) < 1) and (len(vk) > 0):
338
338
  d = vd
339
339
  if d:
340
- _ = Topology.SetDictionary(gv,d)
340
+ _ = Topology.SetDictionary(gv, d)
341
341
  unique = False
342
342
  returnVertex = gv
343
343
  break
@@ -527,6 +527,370 @@ class Graph:
527
527
  lcc = Graph.LocalClusteringCoefficient(graph, vertices)
528
528
  acc = round(sum(lcc)/float(len(lcc)), mantissa)
529
529
  return acc
530
+
531
+ @staticmethod
532
+ def BOTGraph(graph,
533
+ bidirectional=False,
534
+ includeAttributes=False,
535
+ includeLabel=False,
536
+ siteLabel = "Site_0001",
537
+ siteDictionary = None,
538
+ buildingLabel = "Building_0001",
539
+ buildingDictionary = None ,
540
+ storeyPrefix = "Storey",
541
+ floorLevels =[],
542
+ labelKey="label",
543
+ typeKey="type",
544
+ sourceKey="source",
545
+ targetKey="target",
546
+ xKey = "x",
547
+ yKey = "y",
548
+ zKey = "z",
549
+ spaceType = "space",
550
+ wallType = "wall",
551
+ slabType = "slab",
552
+ doorType = "door",
553
+ windowType = "window",
554
+ contentType = "content"
555
+ ):
556
+ """
557
+ Creates an RDF graph according to the BOT ontology. See https://w3c-lbd-cg.github.io/bot/.
558
+
559
+ Parameters
560
+ ----------
561
+ graph : topologic.Graph
562
+ The input graph.
563
+ bidirectional : bool , optional
564
+ If set to True, reverse relationships are created wherever possible. Otherwise, they are not. The default is False.
565
+ includeAttributes : bool , optional
566
+ If set to True, the attributes associated with vertices in the graph are written out. Otherwise, they are not. The default is False.
567
+ includeLabel : bool , optional
568
+ If set to True, a label is attached to each node. Otherwise, it is not. The default is False.
569
+ siteLabel : str , optional
570
+ The desired site label. The default is "Site_0001".
571
+ siteDictionary : dict , optional
572
+ The dictionary of site attributes to include in the output. The default is None.
573
+ buildingLabel : str , optional
574
+ The desired building label. The default is "Building_0001".
575
+ buildingDictionary : dict , optional
576
+ The dictionary of building attributes to include in the output. The default is None.
577
+ storeyPrefix : str , optional
578
+ The desired prefixed to use for each building storey. The default is "Storey".
579
+ floorLevels : list , optional
580
+ The list of floor levels. This should be a numeric list, sorted from lowest to highest.
581
+ If not provided, floorLevels will be computed automatically based on the nodes' 'z' attribute.
582
+ typeKey : str , optional
583
+ The dictionary key to use to look up the type of the node. The default is "type".
584
+ labelKey : str , optional
585
+ The dictionary key to use to look up the label of the node. The default is "label".
586
+ sourceKey : str , optional
587
+ The desired dictionary key to use to store the source vertex. The default is "source".
588
+ targetKey : str , optional
589
+ The desired dictionary key to use to store the target vertex. The default is "target".
590
+ xKey : str , optional
591
+ The dictionary key to use to look up the x-coordinate of the node. The default is "x".
592
+ yKey : str , optional
593
+ The dictionary key to use to look up the y-coordinate of the node. The default is "y".
594
+ zKey : str , optional
595
+ The dictionary key to use to look up the z-coordinate of the node. The default is "z".
596
+ spaceType : str , optional
597
+ The dictionary string value to use to look up nodes of type "space". The default is "space".
598
+ wallType : str , optional
599
+ The dictionary string value to use to look up nodes of type "wall". The default is "wall".
600
+ slabType : str , optional
601
+ The dictionary string value to use to look up nodes of type "slab". The default is "slab".
602
+ doorType : str , optional
603
+ The dictionary string value to use to look up nodes of type "door". The default is "door".
604
+ windowType : str , optional
605
+ The dictionary string value to use to look up nodes of type "window". The default is "window".
606
+ contentType : str , optional
607
+ The dictionary string value to use to look up nodes of type "content". The default is "contents".
608
+
609
+ Returns
610
+ -------
611
+ rdflib.graph.Graph
612
+ The rdf graph using the BOT ontology.
613
+ """
614
+
615
+ from topologicpy.Helper import Helper
616
+ import os
617
+ import warnings
618
+
619
+ try:
620
+ from rdflib import Graph as RDFGraph
621
+ from rdflib import URIRef, Literal, Namespace
622
+ from rdflib.namespace import RDF, RDFS
623
+ except:
624
+ print("Graph.BOTGraph - Installing required rdflib library.")
625
+ try:
626
+ os.system("pip install rdflib")
627
+ except:
628
+ os.system("pip install rdflib --user")
629
+ try:
630
+ from rdflib import Graph as RDFGraph
631
+ from rdflib import URIRef, Literal, Namespace
632
+ from rdflib.namespace import RDF, RDFS
633
+ print("Graph.BOTGraph - rdflib library installed correctly.")
634
+ except:
635
+ warnings.warn("Graph.BOTGraph - Error: Could not import rdflib. Please try to install rdflib manually. Returning None.")
636
+ return None
637
+
638
+ if floorLevels == None:
639
+ floorLevels = []
640
+ json_data = Graph.JSONData(graph, vertexLabelKey=labelKey)
641
+ # Create an empty RDF graph
642
+ rdf_graph = RDFGraph()
643
+
644
+ # Define namespaces
645
+ rdf = Namespace("http://www.w3.org/1999/02/22-rdf-syntax-ns#")
646
+ rdfs = Namespace("http://www.w3.org/2000/01/rdf-schema#")
647
+ bot = Namespace("https://w3id.org/bot#")
648
+
649
+ # Define a custom prefix mapping
650
+ rdf_graph.namespace_manager.bind("bot", bot)
651
+
652
+ # Add site
653
+ site_uri = URIRef(siteLabel)
654
+ rdf_graph.add((site_uri, rdf.type, bot.Site))
655
+ if includeLabel:
656
+ rdf_graph.add((site_uri, RDFS.label, Literal("Site_0001")))
657
+ if isinstance(siteDictionary, topologic.Dictionary):
658
+ keys = Dictionary.Keys(siteDictionary)
659
+ for key in keys:
660
+ value = Dictionary.ValueAtKey(siteDictionary, key)
661
+ if key == labelKey:
662
+ if includeLabel:
663
+ rdf_graph.add((site_uri, RDFS.label, Literal(value)))
664
+ elif key != typeKey:
665
+ rdf_graph.add((site_uri, bot[key], Literal(value)))
666
+ # Add building
667
+ building_uri = URIRef(buildingLabel)
668
+ rdf_graph.add((building_uri, rdf.type, bot.Building))
669
+ if includeLabel:
670
+ rdf_graph.add((building_uri, RDFS.label, Literal(buildingLabel)))
671
+ if isinstance(buildingDictionary, topologic.Dictionary):
672
+ keys = Dictionary.Keys(buildingDictionary)
673
+ for key in keys:
674
+ value = Dictionary.ValueAtKey(buildingDictionary, key)
675
+ if key == labelKey:
676
+ if includeLabel:
677
+ rdf_graph.add((building_uri, RDFS.label, Literal(value)))
678
+ elif key != typeKey:
679
+ rdf_graph.add((building_uri, bot[key], Literal(value)))
680
+ # Add stories
681
+ # if floor levels are not given, then need to be computed
682
+ if len(floorLevels) == 0:
683
+ for node, attributes in json_data['nodes'].items():
684
+ if slabType.lower() in attributes[typeKey].lower():
685
+ floorLevels.append(attributes[zKey])
686
+ floorLevels = list(set(floorLevels))
687
+ floorLevels.sort()
688
+ storey_uris = []
689
+ n = max(len(str(len(floorLevels))),4)
690
+ for i, floor_level in enumerate(floorLevels):
691
+ storey_uri = URIRef(storeyPrefix+"_"+str(i+1).zfill(n))
692
+ rdf_graph.add((storey_uri, rdf.type, bot.Storey))
693
+ if includeLabel:
694
+ rdf_graph.add((storey_uri, RDFS.label, Literal(storeyPrefix+"_"+str(i+1).zfill(n))))
695
+ storey_uris.append(storey_uri)
696
+
697
+ # Add triples to relate building to site and stories to building
698
+ rdf_graph.add((site_uri, bot.hasBuilding, building_uri))
699
+ if bidirectional:
700
+ rdf_graph.add((building_uri, bot.isPartOf, site_uri)) # might not be needed
701
+
702
+ for storey_uri in storey_uris:
703
+ rdf_graph.add((building_uri, bot.hasStorey, storey_uri))
704
+ if bidirectional:
705
+ rdf_graph.add((storey_uri, bot.isPartOf, building_uri)) # might not be needed
706
+
707
+ # Add vertices as RDF resources
708
+ for node, attributes in json_data['nodes'].items():
709
+ node_uri = URIRef(node)
710
+ if spaceType.lower() in attributes[typeKey].lower():
711
+ rdf_graph.add((node_uri, rdf.type, bot.Space))
712
+ # Find the storey it is on
713
+ z = attributes[zKey]
714
+ level = Helper.Position(z, floorLevels)
715
+ if level > len(storey_uris):
716
+ level = len(storey_uris)
717
+ storey_uri = storey_uris[level-1]
718
+ rdf_graph.add((storey_uri, bot.hasSpace, node_uri))
719
+ if bidirectional:
720
+ rdf_graph.add((node_uri, bot.isPartOf, storey_uri)) # might not be needed
721
+ elif windowType.lower() in attributes[typeKey].lower():
722
+ rdf_graph.add((node_uri, rdf.type, bot.Window))
723
+ elif doorType.lower() in attributes[typeKey].lower():
724
+ rdf_graph.add((node_uri, rdf.type, bot.Door))
725
+ elif wallType.lower() in attributes[typeKey].lower():
726
+ rdf_graph.add((node_uri, rdf.type, bot.Wall))
727
+ elif slabType.lower() in attributes[typeKey].lower():
728
+ rdf_graph.add((node_uri, rdf.type, bot.Slab))
729
+ else:
730
+ rdf_graph.add((node_uri, rdf.type, bot.Element))
731
+
732
+ if includeAttributes:
733
+ for key, value in attributes.items():
734
+ if key == labelKey:
735
+ if includeLabel:
736
+ rdf_graph.add((node_uri, RDFS.label, Literal(value)))
737
+ elif key != typeKey:
738
+ rdf_graph.add((node_uri, bot[key], Literal(value)))
739
+ if includeLabel:
740
+ for key, value in attributes.items():
741
+ if key == labelKey:
742
+ rdf_graph.add((node_uri, RDFS.label, Literal(value)))
743
+
744
+ # Add edges as RDF triples
745
+ for edge, attributes in json_data['edges'].items():
746
+ source = attributes[sourceKey]
747
+ target = attributes[targetKey]
748
+ source_uri = URIRef(source)
749
+ target_uri = URIRef(target)
750
+ if spaceType.lower() in json_data['nodes'][source][typeKey].lower() and spaceType.lower() in json_data['nodes'][target][typeKey].lower():
751
+ rdf_graph.add((source_uri, bot.adjacentTo, target_uri))
752
+ if bidirectional:
753
+ rdf_graph.add((target_uri, bot.adjacentTo, source_uri))
754
+ elif spaceType.lower() in json_data['nodes'][source][typeKey].lower() and wallType.lower() in json_data['nodes'][target][typeKey].lower():
755
+ rdf_graph.add((target_uri, bot.interfaceOf, source_uri))
756
+ elif spaceType.lower() in json_data['nodes'][source][typeKey].lower() and slabType.lower() in json_data['nodes'][target][typeKey].lower():
757
+ rdf_graph.add((target_uri, bot.interfaceOf, source_uri))
758
+ elif spaceType.lower() in json_data['nodes'][source][typeKey].lower() and contentType.lower() in json_data['nodes'][target][typeKey].lower():
759
+ rdf_graph.add((source_uri, bot.containsElement, target_uri))
760
+ if bidirectional:
761
+ rdf_graph.add((target_uri, bot.isPartOf, source_uri))
762
+ else:
763
+ rdf_graph.add((source_uri, bot.connectsTo, target_uri))
764
+ if bidirectional:
765
+ rdf_graph.add((target_uri, bot.connectsTo, source_uri))
766
+ #for key, value in attributes.items():
767
+ #rdf_graph.add((source_uri, bot[key], Literal(value)))
768
+ # Return serialized RDF graph
769
+ #rdf_serialized = rdf_graph.serialize(format=format)
770
+ return rdf_graph
771
+
772
+ @staticmethod
773
+ def BOTString(graph,
774
+ format="turtle",
775
+ bidirectional=False,
776
+ includeAttributes=False,
777
+ includeLabel=False,
778
+ siteLabel = "Site_0001",
779
+ siteDictionary = None,
780
+ buildingLabel = "Building_0001",
781
+ buildingDictionary = None ,
782
+ storeyPrefix = "Storey",
783
+ floorLevels =[],
784
+ labelKey="label",
785
+ typeKey="type",
786
+ sourceKey="source",
787
+ targetKey="target",
788
+ xKey = "x",
789
+ yKey = "y",
790
+ zKey = "z",
791
+ spaceType = "space",
792
+ wallType = "wall",
793
+ slabType = "slab",
794
+ doorType = "door",
795
+ windowType = "window",
796
+ contentType = "content",
797
+ ):
798
+
799
+ """
800
+ Returns an RDF graph serialized string according to the BOT ontology. See https://w3c-lbd-cg.github.io/bot/.
801
+
802
+ Parameters
803
+ ----------
804
+ graph : topologic.Graph
805
+ The input graph.
806
+ format : str , optional
807
+ The desired output format, the options are listed below. Thde default is "turtle".
808
+ turtle, ttl or turtle2 : Turtle, turtle2 is just turtle with more spacing & linebreaks
809
+ xml or pretty-xml : RDF/XML, Was the default format, rdflib < 6.0.0
810
+ json-ld : JSON-LD , There are further options for compact syntax and other JSON-LD variants
811
+ ntriples, nt or nt11 : N-Triples , nt11 is exactly like nt, only utf8 encoded
812
+ n3 : Notation-3 , N3 is a superset of Turtle that also caters for rules and a few other things
813
+ trig : Trig , Turtle-like format for RDF triples + context (RDF quads) and thus multiple graphs
814
+ trix : Trix , RDF/XML-like format for RDF quads
815
+ nquads : N-Quads , N-Triples-like format for RDF quads
816
+ bidirectional : bool , optional
817
+ If set to True, reverse relationships are created wherever possible. Otherwise, they are not. The default is False.
818
+ includeAttributes : bool , optional
819
+ If set to True, the attributes associated with vertices in the graph are written out. Otherwise, they are not. The default is False.
820
+ includeLabel : bool , optional
821
+ If set to True, a label is attached to each node. Otherwise, it is not. The default is False.
822
+ siteLabel : str , optional
823
+ The desired site label. The default is "Site_0001".
824
+ siteDictionary : dict , optional
825
+ The dictionary of site attributes to include in the output. The default is None.
826
+ buildingLabel : str , optional
827
+ The desired building label. The default is "Building_0001".
828
+ buildingDictionary : dict , optional
829
+ The dictionary of building attributes to include in the output. The default is None.
830
+ storeyPrefix : str , optional
831
+ The desired prefixed to use for each building storey. The default is "Storey".
832
+ floorLevels : list , optional
833
+ The list of floor levels. This should be a numeric list, sorted from lowest to highest.
834
+ If not provided, floorLevels will be computed automatically based on the nodes' 'z' attribute.
835
+ typeKey : str , optional
836
+ The dictionary key to use to look up the type of the node. The default is "type".
837
+ labelKey : str , optional
838
+ The dictionary key to use to look up the label of the node. The default is "label".
839
+ sourceKey : str , optional
840
+ The desired dictionary key to use to store the source vertex. The default is "source".
841
+ targetKey : str , optional
842
+ The desired dictionary key to use to store the target vertex. The default is "target".
843
+ xKey : str , optional
844
+ The dictionary key to use to look up the x-coordinate of the node. The default is "x".
845
+ yKey : str , optional
846
+ The dictionary key to use to look up the y-coordinate of the node. The default is "y".
847
+ zKey : str , optional
848
+ The dictionary key to use to look up the z-coordinate of the node. The default is "z".
849
+ spaceType : str , optional
850
+ The dictionary string value to use to look up nodes of type "space". The default is "space".
851
+ wallType : str , optional
852
+ The dictionary string value to use to look up nodes of type "wall". The default is "wall".
853
+ slabType : str , optional
854
+ The dictionary string value to use to look up nodes of type "slab". The default is "slab".
855
+ doorType : str , optional
856
+ The dictionary string value to use to look up nodes of type "door". The default is "door".
857
+ windowType : str , optional
858
+ The dictionary string value to use to look up nodes of type "window". The default is "window".
859
+ contentType : str , optional
860
+ The dictionary string value to use to look up nodes of type "content". The default is "contents".
861
+
862
+
863
+ Returns
864
+ -------
865
+ str
866
+ The rdf graph serialized string using the BOT ontology.
867
+ """
868
+
869
+ bot_graph = Graph.BOTGraph(graph,
870
+ bidirectional=bidirectional,
871
+ includeAttributes=includeAttributes,
872
+ includeLabel=includeLabel,
873
+ siteLabel=siteLabel,
874
+ siteDictionary=siteDictionary,
875
+ buildingLabel=buildingLabel,
876
+ buildingDictionary=buildingDictionary,
877
+ storeyPrefix=storeyPrefix,
878
+ floorLevels=floorLevels,
879
+ labelKey=labelKey,
880
+ typeKey=typeKey,
881
+ sourceKey=sourceKey,
882
+ targetKey=targetKey,
883
+ xKey=xKey,
884
+ yKey=yKey,
885
+ zKey=zKey,
886
+ spaceType = spaceType,
887
+ wallType = wallType,
888
+ slabType = slabType,
889
+ doorType = doorType,
890
+ windowType = windowType,
891
+ contentType = contentType
892
+ )
893
+ return bot_graph.serialize(format=format)
530
894
 
531
895
  @staticmethod
532
896
  def BetweenessCentrality(graph, vertices=None, sources=None, destinations=None, tolerance=0.001):
@@ -858,7 +1222,7 @@ class Graph:
858
1222
  # Iterate through the grouped nodes DataFrames
859
1223
  for graph_id, group_node_df in grouped_nodes:
860
1224
  vertices = []
861
- verts = [] #This is a list of x,y,z tuples to make sure the vertices have unique locations.
1225
+ verts = [] #This is a list of x, y, z tuples to make sure the vertices have unique locations.
862
1226
  n_verts = 0
863
1227
  for index, row in group_node_df.iterrows():
864
1228
  n_verts += 1
@@ -886,12 +1250,12 @@ class Graph:
886
1250
  y = random.randrange(0,1000)
887
1251
  if not isinstance(z, numbers.Number):
888
1252
  z = random.randrange(0,1000)
889
- while [x,y,z] in verts:
1253
+ while [x, y, z] in verts:
890
1254
  x = x + random.randrange(10000,30000,1000)
891
1255
  y = y + random.randrange(4000,6000, 100)
892
1256
  z = z + random.randrange(70000,90000, 1000)
893
- verts.append([x,y,z])
894
- v = Vertex.ByCoordinates(x,y,z)
1257
+ verts.append([x, y, z])
1258
+ v = Vertex.ByCoordinates(x, y, z)
895
1259
  if isinstance(v, topologic.Vertex):
896
1260
  if len(nodeFeaturesKeys) == 0:
897
1261
  values = [node_id, label, mask, features]
@@ -1247,7 +1611,7 @@ class Graph:
1247
1611
  x = random.uniform(xMin,xMax)
1248
1612
  y = random.uniform(yMin,yMax)
1249
1613
  z = random.uniform(zMin,zMax)
1250
- centroid = Vertex.ByCoordinates(x,y,z)
1614
+ centroid = Vertex.ByCoordinates(x, y, z)
1251
1615
  d = Dictionary.ByKeysValues(["id","psets", "type", "type_id", "name", "label"], [obj_id, psets, obj_type, obj_type_id, name, label])
1252
1616
  centroid = Topology.SetDictionary(centroid, d)
1253
1617
  return centroid
@@ -1375,9 +1739,9 @@ class Graph:
1375
1739
  Parameters
1376
1740
  ----------
1377
1741
  vertices : list
1378
- The list of [x,y,z] coordinates of the vertices/
1742
+ The list of [x, y, z] coordinates of the vertices/
1379
1743
  edges : list
1380
- the list of [i,j] indices into the vertices list to signify and edge that connects vertices[i] to vertices[j].
1744
+ the list of [i, j] indices into the vertices list to signify and edge that connects vertices[i] to vertices[j].
1381
1745
  vertexDictionaries : list , optional
1382
1746
  The python dictionaries of the vertices (in the same order as the list of vertices).
1383
1747
  edgeDictionaries : list , optional
@@ -1469,6 +1833,7 @@ class Graph:
1469
1833
  from topologicpy.Edge import Edge
1470
1834
  from topologicpy.Cluster import Cluster
1471
1835
  from topologicpy.Topology import Topology
1836
+ from topologicpy.Aperture import Aperture
1472
1837
 
1473
1838
  def mergeDictionaries(sources):
1474
1839
  if isinstance(sources, list) == False:
@@ -1687,7 +2052,7 @@ class Graph:
1687
2052
 
1688
2053
  cells = []
1689
2054
  _ = topology.Cells(None, cells)
1690
- if (viaSharedTopologies == True) or (viaSharedApertures == True) or (toExteriorTopologies == True) or (toExteriorApertures == True) or (toContents == True):
2055
+ if any([viaSharedTopologies, viaSharedApertures, toExteriorTopologies, toExteriorApertures, toContents]):
1691
2056
  for aCell in cells:
1692
2057
  if useInternalVertex == True:
1693
2058
  vCell = Topology.InternalVertex(aCell, tolerance=tolerance)
@@ -1710,9 +2075,9 @@ class Graph:
1710
2075
  contents = []
1711
2076
  _ = aCell.Contents(contents)
1712
2077
  for aFace in faces:
1713
- cells = []
1714
- _ = aFace.Cells(topology, cells)
1715
- if len(cells) > 1:
2078
+ cells1 = []
2079
+ _ = aFace.Cells(topology, cells1)
2080
+ if len(cells1) > 1:
1716
2081
  sharedTopologies.append(aFace)
1717
2082
  apertures = []
1718
2083
  _ = aFace.Apertures(apertures)
@@ -1724,6 +2089,7 @@ class Graph:
1724
2089
  _ = aFace.Apertures(apertures)
1725
2090
  for anAperture in apertures:
1726
2091
  exteriorApertures.append(anAperture)
2092
+
1727
2093
  if viaSharedTopologies:
1728
2094
  for sharedTopology in sharedTopologies:
1729
2095
  if useInternalVertex == True:
@@ -1746,6 +2112,8 @@ class Graph:
1746
2112
  contents = []
1747
2113
  _ = sharedTopology.Contents(contents)
1748
2114
  for content in contents:
2115
+ if isinstance(content, topologic.Aperture):
2116
+ content = Aperture.Topology(content)
1749
2117
  if useInternalVertex == True:
1750
2118
  vst2 = Topology.InternalVertex(content, tolerance)
1751
2119
  else:
@@ -1767,38 +2135,38 @@ class Graph:
1767
2135
  for sharedAperture in sharedApertures:
1768
2136
  sharedAp = sharedAperture.Topology()
1769
2137
  if useInternalVertex == True:
1770
- vst = Topology.InternalVertex(sharedAp, tolerance)
2138
+ vsa = Topology.InternalVertex(sharedAp, tolerance)
1771
2139
  else:
1772
- vst = sharedAp.CenterOfMass()
2140
+ vsa = sharedAp.CenterOfMass()
1773
2141
  d1 = sharedAp.GetDictionary()
1774
- vst = topologic.Vertex.ByCoordinates(vst.X()+(tolerance*100), vst.Y()+(tolerance*100), vst.Z()+(tolerance*100))
2142
+ vsa = topologic.Vertex.ByCoordinates(vsa.X()+(tolerance*100), vsa.Y()+(tolerance*100), vsa.Z()+(tolerance*100))
1775
2143
  if storeBRep:
1776
2144
  d2 = Dictionary.ByKeysValues(["brep", "brepType", "brepTypeString"], [Topology.BREPString(sharedAperture), Topology.Type(sharedAperture), Topology.TypeAsString(sharedAperture)])
1777
2145
  d3 = mergeDictionaries2([d1, d2])
1778
- _ = vst.SetDictionary(d3)
2146
+ _ = vsa.SetDictionary(d3)
1779
2147
  else:
1780
- _ = vst.SetDictionary(d1)
1781
- vertices.append(vst)
1782
- tempe = Edge.ByStartVertexEndVertex(vCell, vst, tolerance=tolerance)
2148
+ _ = vsa.SetDictionary(d1)
2149
+ vertices.append(vsa)
2150
+ tempe = Edge.ByStartVertexEndVertex(vCell, vsa, tolerance=tolerance)
1783
2151
  tempd = Dictionary.ByKeysValues(["relationship"],["Via Shared Apertures"])
1784
2152
  _ = tempe.SetDictionary(tempd)
1785
2153
  edges.append(tempe)
1786
2154
  if toExteriorTopologies:
1787
2155
  for exteriorTopology in exteriorTopologies:
1788
2156
  if useInternalVertex == True:
1789
- vst = Topology.InternalVertex(exteriorTopology, tolerance)
2157
+ vet = Topology.InternalVertex(exteriorTopology, tolerance)
1790
2158
  else:
1791
- vst = exteriorTopology.CenterOfMass()
1792
- _ = vst.SetDictionary(exteriorTopology.GetDictionary())
2159
+ vet = exteriorTopology.CenterOfMass()
2160
+ _ = vet.SetDictionary(exteriorTopology.GetDictionary())
1793
2161
  d1 = exteriorTopology.GetDictionary()
1794
2162
  if storeBRep:
1795
2163
  d2 = Dictionary.ByKeysValues(["brep", "brepType", "brepTypeString"], [Topology.BREPString(exteriorTopology), Topology.Type(exteriorTopology), Topology.TypeAsString(exteriorTopology)])
1796
2164
  d3 = mergeDictionaries2([d1, d2])
1797
- _ = vst.SetDictionary(d3)
2165
+ _ = vet.SetDictionary(d3)
1798
2166
  else:
1799
- _ = vst.SetDictionary(d1)
1800
- vertices.append(vst)
1801
- tempe = Edge.ByStartVertexEndVertex(vCell, vst, tolerance=tolerance)
2167
+ _ = vet.SetDictionary(d1)
2168
+ vertices.append(vet)
2169
+ tempe = Edge.ByStartVertexEndVertex(vCell, vet, tolerance=tolerance)
1802
2170
  tempd = Dictionary.ByKeysValues(["relationship"],["To Exterior Topologies"])
1803
2171
  _ = tempe.SetDictionary(tempd)
1804
2172
  edges.append(tempe)
@@ -1806,6 +2174,8 @@ class Graph:
1806
2174
  contents = []
1807
2175
  _ = exteriorTopology.Contents(contents)
1808
2176
  for content in contents:
2177
+ if isinstance(content, topologic.Aperture):
2178
+ content = Aperture.Topology(content)
1809
2179
  if useInternalVertex == True:
1810
2180
  vst2 = Topology.InternalVertex(content, tolerance)
1811
2181
  else:
@@ -1819,7 +2189,7 @@ class Graph:
1819
2189
  else:
1820
2190
  _ = vst2.SetDictionary(d1)
1821
2191
  vertices.append(vst2)
1822
- tempe = Edge.ByStartVertexEndVertex(vst, vst2, tolerance=tolerance)
2192
+ tempe = Edge.ByStartVertexEndVertex(vet, vst2, tolerance=tolerance)
1823
2193
  tempd = Dictionary.ByKeysValues(["relationship"],["To Contents"])
1824
2194
  _ = tempe.SetDictionary(tempd)
1825
2195
  edges.append(tempe)
@@ -1827,19 +2197,19 @@ class Graph:
1827
2197
  for exteriorAperture in exteriorApertures:
1828
2198
  extTop = exteriorAperture.Topology()
1829
2199
  if useInternalVertex == True:
1830
- vst = Topology.InternalVertex(extTop, tolerance)
2200
+ vea = Topology.InternalVertex(extTop, tolerance)
1831
2201
  else:
1832
- vst = exteriorAperture.Topology().CenterOfMass()
2202
+ vea = exteriorAperture.Topology().CenterOfMass()
1833
2203
  d1 = exteriorAperture.Topology().GetDictionary()
1834
- vst = topologic.Vertex.ByCoordinates(vst.X()+(tolerance*100), vst.Y()+(tolerance*100), vst.Z()+(tolerance*100))
2204
+ vea = topologic.Vertex.ByCoordinates(vea.X()+(tolerance*100), vea.Y()+(tolerance*100), vea.Z()+(tolerance*100))
1835
2205
  if storeBRep:
1836
2206
  d2 = Dictionary.ByKeysValues(["brep", "brepType", "brepTypeString"], [Topology.BREPString(exteriorAperture), Topology.Type(exteriorAperture), Topology.TypeAsString(exteriorAperture)])
1837
2207
  d3 = mergeDictionaries2([d1, d2])
1838
- _ = vst.SetDictionary(d3)
2208
+ _ = vea.SetDictionary(d3)
1839
2209
  else:
1840
- _ = vst.SetDictionary(d1)
1841
- vertices.append(vst)
1842
- tempe = Edge.ByStartVertexEndVertex(vCell, vst, tolerance=tolerance)
2210
+ _ = vea.SetDictionary(d1)
2211
+ vertices.append(vea)
2212
+ tempe = Edge.ByStartVertexEndVertex(vCell, vea, tolerance=tolerance)
1843
2213
  tempd = Dictionary.ByKeysValues(["relationship"],["To Exterior Apertures"])
1844
2214
  _ = tempe.SetDictionary(tempd)
1845
2215
  edges.append(tempe)
@@ -1847,20 +2217,22 @@ class Graph:
1847
2217
  contents = []
1848
2218
  _ = aCell.Contents(contents)
1849
2219
  for content in contents:
2220
+ if isinstance(content, topologic.Aperture):
2221
+ content = Aperture.Topology(content)
1850
2222
  if useInternalVertex == True:
1851
- vst = Topology.InternalVertex(content, tolerance)
2223
+ vcn = Topology.InternalVertex(content, tolerance)
1852
2224
  else:
1853
- vst = content.CenterOfMass()
1854
- vst = topologic.Vertex.ByCoordinates(vst.X()+(tolerance*100), vst.Y()+(tolerance*100), vst.Z()+(tolerance*100))
2225
+ vcn = content.CenterOfMass()
2226
+ vcn = topologic.Vertex.ByCoordinates(vcn.X()+(tolerance*100), vcn.Y()+(tolerance*100), vcn.Z()+(tolerance*100))
1855
2227
  d1 = content.GetDictionary()
1856
2228
  if storeBRep:
1857
2229
  d2 = Dictionary.ByKeysValues(["brep", "brepType", "brepTypeString"], [Topology.BREPString(content), Topology.Type(content), Topology.TypeAsString(content)])
1858
2230
  d3 = mergeDictionaries2([d1, d2])
1859
- _ = vst.SetDictionary(d3)
2231
+ _ = vcn.SetDictionary(d3)
1860
2232
  else:
1861
- _ = vst.SetDictionary(d1)
1862
- vertices.append(vst)
1863
- tempe = Edge.ByStartVertexEndVertex(vCell, vst, tolerance=tolerance)
2233
+ _ = vcn.SetDictionary(d1)
2234
+ vertices.append(vcn)
2235
+ tempe = Edge.ByStartVertexEndVertex(vCell, vcn, tolerance=tolerance)
1864
2236
  tempd = Dictionary.ByKeysValues(["relationship"],["To Contents"])
1865
2237
  _ = tempe.SetDictionary(tempd)
1866
2238
  edges.append(tempe)
@@ -1885,7 +2257,7 @@ class Graph:
1885
2257
  vertices = []
1886
2258
  edges = []
1887
2259
  if useInternalVertex == True:
1888
- vCell = Topology.InternalVertex(Topology.Copy(topology), tolerance=tolerance)
2260
+ vCell = Topology.InternalVertex(topology, tolerance=tolerance)
1889
2261
  else:
1890
2262
  vCell = topology.CenterOfMass()
1891
2263
  d1 = topology.GetDictionary()
@@ -1920,7 +2292,7 @@ class Graph:
1920
2292
  tempd = Dictionary.ByKeysValues(["relationship"],["To Outposts"])
1921
2293
  _ = tempe.SetDictionary(tempd)
1922
2294
  edges.append(tempe)
1923
- if (toExteriorTopologies == True) or (toExteriorApertures == True) or (toContents == True):
2295
+ if any([toExteriorTopologies, toExteriorApertures, toContents]):
1924
2296
  faces = Topology.Faces(topology)
1925
2297
  exteriorTopologies = []
1926
2298
  exteriorApertures = []
@@ -1951,6 +2323,8 @@ class Graph:
1951
2323
  contents = []
1952
2324
  _ = exteriorTopology.Contents(contents)
1953
2325
  for content in contents:
2326
+ if isinstance(content, topologic.Aperture):
2327
+ content = Aperture.Topology(content)
1954
2328
  if useInternalVertex == True:
1955
2329
  vst2 = Topology.InternalVertex(content, tolerance)
1956
2330
  else:
@@ -1992,6 +2366,8 @@ class Graph:
1992
2366
  contents = []
1993
2367
  _ = topology.Contents(contents)
1994
2368
  for content in contents:
2369
+ if isinstance(content, topologic.Aperture):
2370
+ content = Aperture.Topology(content)
1995
2371
  if useInternalVertex == True:
1996
2372
  vst = Topology.InternalVertex(content, tolerance)
1997
2373
  else:
@@ -2094,7 +2470,7 @@ class Graph:
2094
2470
 
2095
2471
  topFaces = []
2096
2472
  _ = topology.Faces(None, topFaces)
2097
- if (viaSharedTopologies == True) or (viaSharedApertures == True) or (toExteriorTopologies == True) or (toExteriorApertures == True) or (toContents == True):
2473
+ if any([viaSharedTopologies, viaSharedApertures, toExteriorTopologies, toExteriorApertures, toContents == True]):
2098
2474
  for aFace in topFaces:
2099
2475
  if useInternalVertex == True:
2100
2476
  vFace = Topology.InternalVertex(aFace, tolerance=tolerance)
@@ -2145,6 +2521,8 @@ class Graph:
2145
2521
  contents = []
2146
2522
  _ = sharedTopology.Contents(contents)
2147
2523
  for content in contents:
2524
+ if isinstance(content, topologic.Aperture):
2525
+ content = Aperture.Topology(content)
2148
2526
  if useInternalVertex == True:
2149
2527
  vst2 = Topology.InternalVertex(content, tolerance)
2150
2528
  else:
@@ -2203,6 +2581,8 @@ class Graph:
2203
2581
  contents = []
2204
2582
  _ = exteriorTopology.Contents(contents)
2205
2583
  for content in contents:
2584
+ if isinstance(content, topologic.Aperture):
2585
+ content = Aperture.Topology(content)
2206
2586
  if useInternalVertex == True:
2207
2587
  vst2 = Topology.InternalVertex(content, tolerance)
2208
2588
  else:
@@ -2244,6 +2624,8 @@ class Graph:
2244
2624
  contents = []
2245
2625
  _ = aFace.Contents(contents)
2246
2626
  for content in contents:
2627
+ if isinstance(content, topologic.Aperture):
2628
+ content = Aperture.Topology(content)
2247
2629
  if useInternalVertex == True:
2248
2630
  vst = Topology.InternalVertex(content, tolerance)
2249
2631
  else:
@@ -2388,6 +2770,8 @@ class Graph:
2388
2770
  contents = []
2389
2771
  _ = exteriorTopology.Contents(contents)
2390
2772
  for content in contents:
2773
+ if isinstance(content, topologic.Aperture):
2774
+ content = Aperture.Topology(content)
2391
2775
  if useInternalVertex == True:
2392
2776
  vst2 = Topology.InternalVertex(content, tolerance)
2393
2777
  else:
@@ -2429,6 +2813,8 @@ class Graph:
2429
2813
  contents = []
2430
2814
  _ = topology.Contents(contents)
2431
2815
  for content in contents:
2816
+ if isinstance(content, topologic.Aperture):
2817
+ content = Aperture.Topology(content)
2432
2818
  if useInternalVertex == True:
2433
2819
  vst = Topology.InternalVertex(content, tolerance)
2434
2820
  else:
@@ -2590,6 +2976,8 @@ class Graph:
2590
2976
  contents = []
2591
2977
  _ = sharedTopology.Contents(contents)
2592
2978
  for content in contents:
2979
+ if isinstance(content, topologic.Aperture):
2980
+ content = Aperture.Topology(content)
2593
2981
  if useInternalVertex == True:
2594
2982
  vst2 = Topology.InternalVertex(content, tolerance)
2595
2983
  else:
@@ -2639,6 +3027,8 @@ class Graph:
2639
3027
  contents = []
2640
3028
  _ = vst.Contents(contents)
2641
3029
  for content in contents:
3030
+ if isinstance(content, topologic.Aperture):
3031
+ content = Aperture.Topology(content)
2642
3032
  if useInternalVertex == True:
2643
3033
  vst2 = Topology.InternalVertex(content, tolerance)
2644
3034
  else:
@@ -2680,6 +3070,8 @@ class Graph:
2680
3070
  contents = []
2681
3071
  _ = anEdge.Contents(contents)
2682
3072
  for content in contents:
3073
+ if isinstance(content, topologic.Aperture):
3074
+ content = Aperture.Topology(content)
2683
3075
  if useInternalVertex == True:
2684
3076
  vst = Topology.InternalVertex(content, tolerance)
2685
3077
  else:
@@ -2830,6 +3222,8 @@ class Graph:
2830
3222
  contents = []
2831
3223
  _ = vst.Contents(contents)
2832
3224
  for content in contents:
3225
+ if isinstance(content, topologic.Aperture):
3226
+ content = Aperture.Topology(content)
2833
3227
  if useInternalVertex == True:
2834
3228
  vst2 = Topology.InternalVertex(content, tolerance)
2835
3229
  else:
@@ -2880,6 +3274,8 @@ class Graph:
2880
3274
  contents = []
2881
3275
  _ = topology.Contents(contents)
2882
3276
  for content in contents:
3277
+ if isinstance(content, topologic.Aperture):
3278
+ content = Aperture.Topology(content)
2883
3279
  if useInternalVertex == True:
2884
3280
  vst = Topology.InternalVertex(content, tolerance)
2885
3281
  else:
@@ -2929,7 +3325,6 @@ class Graph:
2929
3325
  if not isinstance(topology, topologic.Topology):
2930
3326
  print("Graph.ByTopology - Error: The input topology is not a valid topology. Returning None.")
2931
3327
  return None
2932
- topology = Topology.Copy(topology)
2933
3328
  graph = None
2934
3329
  item = [topology, None, None, None, direct, directApertures, viaSharedTopologies, viaSharedApertures, toExteriorTopologies, toExteriorApertures, toContents, None, useInternalVertex, storeBRep, tolerance]
2935
3330
  vertices = []
@@ -3172,7 +3567,7 @@ class Graph:
3172
3567
  for i, v in enumerate(vertices):
3173
3568
  d = Topology.Dictionary(v)
3174
3569
  d = Dictionary.SetValueAtKey(d, newKey, colors[i])
3175
- v = Topology.SetDictionary(v,d)
3570
+ v = Topology.SetDictionary(v, d)
3176
3571
  return graph
3177
3572
 
3178
3573
  @staticmethod
@@ -3208,8 +3603,8 @@ class Graph:
3208
3603
  d1 = Vertex.Distance(vertex, sv)
3209
3604
  d2 = Vertex.Distance(vertex, ev)
3210
3605
  if d1 < d2:
3211
- return [ev,1]
3212
- return [sv,0]
3606
+ return [ev, 1]
3607
+ return [sv, 0]
3213
3608
  if not isinstance(graph, topologic.Graph):
3214
3609
  print("Graph.ContractEdge - Error: The input graph parameter is not a valid graph. Returning None.")
3215
3610
  return None
@@ -3699,6 +4094,177 @@ class Graph:
3699
4094
  except:
3700
4095
  return False
3701
4096
 
4097
+ @staticmethod
4098
+ def ExportToBOT(graph,
4099
+ path,
4100
+ format="turtle",
4101
+ overwrite = False,
4102
+ bidirectional=False,
4103
+ includeAttributes=False,
4104
+ includeLabel=False,
4105
+ siteLabel = "Site_0001",
4106
+ siteDictionary = None,
4107
+ buildingLabel = "Building_0001",
4108
+ buildingDictionary = None ,
4109
+ storeyPrefix = "Storey",
4110
+ floorLevels =[],
4111
+ labelKey="label",
4112
+ typeKey="type",
4113
+ sourceKey="source",
4114
+ targetKey="target",
4115
+ xKey = "x",
4116
+ yKey = "y",
4117
+ zKey = "z",
4118
+ spaceType = "space",
4119
+ wallType = "wall",
4120
+ slabType = "slab",
4121
+ doorType = "door",
4122
+ windowType = "window",
4123
+ contentType = "content",
4124
+ ):
4125
+
4126
+ """
4127
+ Returns an RDF graph serialized string according to the BOT ontology. See https://w3c-lbd-cg.github.io/bot/.
4128
+
4129
+ Parameters
4130
+ ----------
4131
+ graph : topologic.Graph
4132
+ The input graph.
4133
+ format : str , optional
4134
+ The desired output format, the options are listed below. Thde default is "turtle".
4135
+ turtle, ttl or turtle2 : Turtle, turtle2 is just turtle with more spacing & linebreaks
4136
+ xml or pretty-xml : RDF/XML, Was the default format, rdflib < 6.0.0
4137
+ json-ld : JSON-LD , There are further options for compact syntax and other JSON-LD variants
4138
+ ntriples, nt or nt11 : N-Triples , nt11 is exactly like nt, only utf8 encoded
4139
+ n3 : Notation-3 , N3 is a superset of Turtle that also caters for rules and a few other things
4140
+ trig : Trig , Turtle-like format for RDF triples + context (RDF quads) and thus multiple graphs
4141
+ trix : Trix , RDF/XML-like format for RDF quads
4142
+ nquads : N-Quads , N-Triples-like format for RDF quads
4143
+ path : str
4144
+ The desired path to where the RDF/BOT file will be saved.
4145
+ overwrite : bool , optional
4146
+ If set to True, any existing file is overwritten. Otherwise, it is not. The default is False.
4147
+ bidirectional : bool , optional
4148
+ If set to True, reverse relationships are created wherever possible. Otherwise, they are not. The default is False.
4149
+ includeAttributes : bool , optional
4150
+ If set to True, the attributes associated with vertices in the graph are written out. Otherwise, they are not. The default is False.
4151
+ includeLabel : bool , optional
4152
+ If set to True, a label is attached to each node. Otherwise, it is not. The default is False.
4153
+ siteLabel : str , optional
4154
+ The desired site label. The default is "Site_0001".
4155
+ siteDictionary : dict , optional
4156
+ The dictionary of site attributes to include in the output. The default is None.
4157
+ buildingLabel : str , optional
4158
+ The desired building label. The default is "Building_0001".
4159
+ buildingDictionary : dict , optional
4160
+ The dictionary of building attributes to include in the output. The default is None.
4161
+ storeyPrefix : str , optional
4162
+ The desired prefixed to use for each building storey. The default is "Storey".
4163
+ floorLevels : list , optional
4164
+ The list of floor levels. This should be a numeric list, sorted from lowest to highest.
4165
+ If not provided, floorLevels will be computed automatically based on the nodes' 'z' attribute.
4166
+ typeKey : str , optional
4167
+ The dictionary key to use to look up the type of the node. The default is "type".
4168
+ labelKey : str , optional
4169
+ The dictionary key to use to look up the label of the node. The default is "label".
4170
+ sourceKey : str , optional
4171
+ The desired dictionary key to use to store the source vertex. The default is "source".
4172
+ targetKey : str , optional
4173
+ The desired dictionary key to use to store the target vertex. The default is "target".
4174
+ xKey : str , optional
4175
+ The dictionary key to use to look up the x-coordinate of the node. The default is "x".
4176
+ yKey : str , optional
4177
+ The dictionary key to use to look up the y-coordinate of the node. The default is "y".
4178
+ zKey : str , optional
4179
+ The dictionary key to use to look up the z-coordinate of the node. The default is "z".
4180
+ spaceType : str , optional
4181
+ The dictionary string value to use to look up nodes of type "space". The default is "space".
4182
+ wallType : str , optional
4183
+ The dictionary string value to use to look up nodes of type "wall". The default is "wall".
4184
+ slabType : str , optional
4185
+ The dictionary string value to use to look up nodes of type "slab". The default is "slab".
4186
+ doorType : str , optional
4187
+ The dictionary string value to use to look up nodes of type "door". The default is "door".
4188
+ windowType : str , optional
4189
+ The dictionary string value to use to look up nodes of type "window". The default is "window".
4190
+ contentType : str , optional
4191
+ The dictionary string value to use to look up nodes of type "content". The default is "contents".
4192
+ format : str , optional
4193
+ The desired output format, the options are listed below. Thde default is "turtle".
4194
+ turtle, ttl or turtle2 : Turtle, turtle2 is just turtle with more spacing & linebreaks
4195
+ xml or pretty-xml : RDF/XML, Was the default format, rdflib < 6.0.0
4196
+ json-ld : JSON-LD , There are further options for compact syntax and other JSON-LD variants
4197
+ ntriples, nt or nt11 : N-Triples , nt11 is exactly like nt, only utf8 encoded
4198
+ n3 : Notation-3 , N3 is a superset of Turtle that also caters for rules and a few other things
4199
+ trig : Trig , Turtle-like format for RDF triples + context (RDF quads) and thus multiple graphs
4200
+ trix : Trix , RDF/XML-like format for RDF quads
4201
+ nquads : N-Quads , N-Triples-like format for RDF quads
4202
+
4203
+ Returns
4204
+ -------
4205
+ str
4206
+ The rdf graph serialized string using the BOT ontology.
4207
+ """
4208
+ from os.path import exists
4209
+ bot_graph = Graph.BOTGraph(graph,
4210
+ bidirectional=bidirectional,
4211
+ includeAttributes=includeAttributes,
4212
+ includeLabel=includeLabel,
4213
+ siteLabel=siteLabel,
4214
+ siteDictionary=siteDictionary,
4215
+ buildingLabel=buildingLabel,
4216
+ buildingDictionary=buildingDictionary,
4217
+ storeyPrefix=storeyPrefix,
4218
+ floorLevels=floorLevels,
4219
+ labelKey=labelKey,
4220
+ typeKey=typeKey,
4221
+ sourceKey=sourceKey,
4222
+ targetKey=targetKey,
4223
+ xKey=xKey,
4224
+ yKey=yKey,
4225
+ zKey=zKey,
4226
+ spaceType = spaceType,
4227
+ wallType = wallType,
4228
+ slabType = slabType,
4229
+ doorType = doorType,
4230
+ windowType = windowType,
4231
+ contentType = contentType
4232
+ )
4233
+ if "turtle" in format.lower() or "ttl" in format.lower() or "turtle2" in format.lower():
4234
+ ext = ".ttl"
4235
+ elif "xml" in format.lower() or "pretty=xml" in format.lower() or "rdf/xml" in format.lower():
4236
+ ext = ".xml"
4237
+ elif "json" in format.lower():
4238
+ ext = ".json"
4239
+ elif "ntriples" in format.lower() or "nt" in format.lower() or "nt11" in format.lower():
4240
+ ext = ".nt"
4241
+ elif "n3" in format.lower() or "notation" in format.lower():
4242
+ ext = ".n3"
4243
+ elif "trig" in format.lower():
4244
+ ext = ".trig"
4245
+ elif "trix" in format.lower():
4246
+ ext = ".trix"
4247
+ elif "nquads" in format.lower():
4248
+ ext = ".nquads"
4249
+ else:
4250
+ format = "turtle"
4251
+ ext = ".ttl"
4252
+ n = len(ext)
4253
+ # Make sure the file extension is .brep
4254
+ ext = path[len(path)-n:len(path)]
4255
+ if ext.lower() != ext:
4256
+ path = path+ext
4257
+ if not overwrite and exists(path):
4258
+ print("Graph.ExportToBOT - Error: a file already exists at the specified path and overwrite is set to False. Returning None.")
4259
+ return None
4260
+ status = False
4261
+ try:
4262
+ bot_graph.serialize(destination=path, format=format)
4263
+ status = True
4264
+ except:
4265
+ status = False
4266
+ return status
4267
+
3702
4268
  @staticmethod
3703
4269
  def ExportToCSV(graph, path, graphLabel, graphFeatures="",
3704
4270
  graphIDHeader="graph_id", graphLabelHeader="label", graphFeaturesHeader="feat",
@@ -3905,7 +4471,7 @@ class Graph:
3905
4471
  flag = True
3906
4472
  if nodeMaskKey in keys:
3907
4473
  value = Dictionary.ValueAtKey(nd, nodeMaskKey)
3908
- if not value in [0,1,2]:
4474
+ if not value in [0, 1, 2]:
3909
4475
  flag = True
3910
4476
  elif value == 0:
3911
4477
  train_mask = True
@@ -3992,7 +4558,7 @@ class Graph:
3992
4558
  flag = True
3993
4559
  if edgeMaskKey in keys:
3994
4560
  value = Dictionary.ValueAtKey(ed, edgeMaskKey)
3995
- if not value in [0,1,2]:
4561
+ if not value in [0, 1, 2]:
3996
4562
  flag = True
3997
4563
  elif value == 0:
3998
4564
  train_mask = True
@@ -4193,7 +4759,7 @@ class Graph:
4193
4759
  source, target = edge_id
4194
4760
  file.write(f'<edge id="{edge_id}" source="{source}" target="{target}" label="{edge_attrs["label"]}">\n')
4195
4761
  if "color" in edge_attrs:
4196
- r,g,b = Color.ByCSSNamedColor(edge_attrs["color"])
4762
+ r, g, b = Color.ByCSSNamedColor(edge_attrs["color"])
4197
4763
  file.write(f'<viz:color r="{r}" g="{g}" b="{b}"/>\n')
4198
4764
  file.write('<attvalues>\n')
4199
4765
  keys = edge_attrs.keys()
@@ -4302,7 +4868,7 @@ class Graph:
4302
4868
  if not vertex_color in Color.CSSNamedColors():
4303
4869
  vertex_color = defaultVertexColor
4304
4870
  node_dict['color'] = vertex_color
4305
- r,g,b = Color.ByCSSNamedColor(vertex_color)
4871
+ r, g, b = Color.ByCSSNamedColor(vertex_color)
4306
4872
  node_dict['r'] = r
4307
4873
  node_dict['g'] = g
4308
4874
  node_dict['b'] = b
@@ -4370,7 +4936,7 @@ class Graph:
4370
4936
  edge_color = defaultVertexColor
4371
4937
  edge_dict['color'] = edge_color
4372
4938
 
4373
- r,g,b = Color.ByCSSNamedColor(edge_color)
4939
+ r, g, b = Color.ByCSSNamedColor(edge_color)
4374
4940
  edge_dict['r'] = r
4375
4941
  edge_dict['g'] = g
4376
4942
  edge_dict['b'] = b
@@ -4887,7 +5453,7 @@ class Graph:
4887
5453
  return graph.GetGUID()
4888
5454
 
4889
5455
  @staticmethod
4890
- def IncomingEdges(graph: topologic.Graph, vertex: topologic.Vertex, directed: bool=False, tolerance: float=0.0001) -> list:
5456
+ def IncomingEdges(graph: topologic.Graph, vertex: topologic.Vertex, directed: bool = False, tolerance: float = 0.0001) -> list:
4891
5457
  """
4892
5458
  Returns the incoming edges connected to a vertex. An edge is considered incoming if its end vertex is
4893
5459
  coincident with the input vertex.
@@ -4928,7 +5494,7 @@ class Graph:
4928
5494
  return incoming_edges
4929
5495
 
4930
5496
  @staticmethod
4931
- def IncomingVertices(graph: topologic.Graph, vertex: topologic.Vertex, directed: bool=False, tolerance: float=0.0001) -> list:
5497
+ def IncomingVertices(graph: topologic.Graph, vertex: topologic.Vertex, directed: bool = False, tolerance: float = 0.0001) -> list:
4932
5498
  """
4933
5499
  Returns the incoming vertices connected to a vertex. A vertex is considered incoming if it is an adjacent vertex to the input vertex
4934
5500
  and the the edge connecting it to the input vertex is an incoming edge.
@@ -5113,7 +5679,7 @@ class Graph:
5113
5679
  return vertices
5114
5680
 
5115
5681
  @staticmethod
5116
- def JSONData(graph, vertexLabelKey="", edgeLabelKey="", mantissa=6):
5682
+ def JSONData(graph, vertexLabelKey="", edgeLabelKey="", sourceKey="source", targetKey="target", mantissa=6):
5117
5683
  """
5118
5684
  Converts the input graph into JSON data.
5119
5685
 
@@ -5127,6 +5693,10 @@ class Graph:
5127
5693
  edgeLabelKey : str , optional
5128
5694
  If set to a valid string, the edge label will be set to the value at this key. Otherwise it will be set to Edge_XXXX where XXXX is a sequential unique number.
5129
5695
  Note: If edge labels are not unique, they will be forced to be unique.
5696
+ sourceKey : str , optional
5697
+ The dictionary key used to store the source vertex. The default is "source".
5698
+ targetKey : str , optional
5699
+ The dictionary key used to store the target vertex. The default is "source".
5130
5700
  mantissa : int , optional
5131
5701
  The desired length of the mantissa. The default is 6.
5132
5702
 
@@ -5146,7 +5716,7 @@ class Graph:
5146
5716
  j_data = {}
5147
5717
  j_data['nodes'] = {}
5148
5718
  j_data['edges'] = {}
5149
- n = max(len(str(len(vertices))),4)
5719
+ n = max(len(str(len(vertices))), 4)
5150
5720
  v_labels = []
5151
5721
  v_dicts = []
5152
5722
  for i, v in enumerate(vertices):
@@ -5179,8 +5749,8 @@ class Graph:
5179
5749
  ev_label = v_labels[evi]
5180
5750
  d = Topology.Dictionary(e)
5181
5751
 
5182
- d = Dictionary.SetValueAtKey(d, "source", sv_label)
5183
- d = Dictionary.SetValueAtKey(d, "target", ev_label)
5752
+ d = Dictionary.SetValueAtKey(d, sourceKey, sv_label)
5753
+ d = Dictionary.SetValueAtKey(d, targetKey, ev_label)
5184
5754
  e_dict = Dictionary.PythonDictionary(d)
5185
5755
  e_label = Dictionary.ValueAtKey(d, edgeLabelKey)
5186
5756
  if isinstance(e_label, str):
@@ -5534,7 +6104,7 @@ class Graph:
5534
6104
  keys.append(residualKey)
5535
6105
  values.append(residual)
5536
6106
  d = Dictionary.ByKeysValues(keys, values)
5537
- edge = Topology.SetDictionary(edge,d)
6107
+ edge = Topology.SetDictionary(edge, d)
5538
6108
  return max_flow
5539
6109
 
5540
6110
  @staticmethod
@@ -5551,8 +6121,8 @@ class Graph:
5551
6121
  -------
5552
6122
  dict
5553
6123
  The python dictionary of the mesh data of the input graph. The keys in the dictionary are:
5554
- 'vertices' : The list of [x,y,z] coordinates of the vertices.
5555
- 'edges' : the list of [i,j] indices into the vertices list to signify and edge that connects vertices[i] to vertices[j].
6124
+ 'vertices' : The list of [x, y, z] coordinates of the vertices.
6125
+ 'edges' : the list of [i, j] indices into the vertices list to signify and edge that connects vertices[i] to vertices[j].
5556
6126
  'vertexDictionaries' : The python dictionaries of the vertices (in the same order as the list of vertices).
5557
6127
  'edgeDictionaries' : The python dictionaries of the edges (in the same order as the list of edges).
5558
6128
 
@@ -5898,7 +6468,7 @@ class Graph:
5898
6468
  return len(Graph.Vertices(graph))
5899
6469
 
5900
6470
  @staticmethod
5901
- def OutgoingEdges(graph: topologic.Graph, vertex: topologic.Vertex, directed: bool=False, tolerance: float=0.0001) -> list:
6471
+ def OutgoingEdges(graph: topologic.Graph, vertex: topologic.Vertex, directed: bool = False, tolerance: float = 0.0001) -> list:
5902
6472
  """
5903
6473
  Returns the outgoing edges connected to a vertex. An edge is considered outgoing if its start vertex is
5904
6474
  coincident with the input vertex.
@@ -5939,7 +6509,7 @@ class Graph:
5939
6509
  return outgoing_edges
5940
6510
 
5941
6511
  @staticmethod
5942
- def OutgoingVertices(graph: topologic.Graph, vertex: topologic.Vertex, directed: bool=False, tolerance: float=0.0001) -> list:
6512
+ def OutgoingVertices(graph: topologic.Graph, vertex: topologic.Vertex, directed: bool = False, tolerance: float = 0.0001) -> list:
5943
6513
  """
5944
6514
  Returns the list of outgoing vertices connected to a vertex. A vertex is considered outgoing if it is an adjacent vertex to the input vertex
5945
6515
  and the the edge connecting it to the input vertex is an outgoing edge.
@@ -6537,7 +7107,7 @@ class Graph:
6537
7107
  zAxis : bool , optional
6538
7108
  If set to True the z axis is drawn. Otherwise it is not drawn. The default is False.
6539
7109
  axisSize : float , optional
6540
- The size of the X,Y,Z, axes. The default is 1.
7110
+ The size of the X, Y, Z, axes. The default is 1.
6541
7111
  backgroundColor : str , optional
6542
7112
  The desired color of the background. This can be any plotly color string and may be specified as:
6543
7113
  - A hex string (e.g. '#ff0000')
@@ -6555,11 +7125,11 @@ class Graph:
6555
7125
  marginBottom : int , optional
6556
7126
  The size in pixels of the bottom margin. The default value is 0.
6557
7127
  camera : list , optional
6558
- The desired location of the camera). The default is [-1.25,-1.25,1.25].
7128
+ The desired location of the camera). The default is [-1.25, -1.25, 1.25].
6559
7129
  center : list , optional
6560
- The desired center (camera target). The default is [0,0,0].
7130
+ The desired center (camera target). The default is [0, 0, 0].
6561
7131
  up : list , optional
6562
- The desired up vector. The default is [0,0,1].
7132
+ The desired up vector. The default is [0, 0, 1].
6563
7133
  projection : str , optional
6564
7134
  The desired type of projection. The options are "orthographic" or "perspective". It is case insensitive. The default is "perspective"
6565
7135
 
@@ -6735,7 +7305,7 @@ class Graph:
6735
7305
  return Graph.ByVerticesEdges(dictionary['vertices'], dictionary['edges'])
6736
7306
 
6737
7307
  @staticmethod
6738
- def VertexDegree(graph : topologic.Graph, vertex: topologic.Vertex, edgeKey: str=None, tolerance: float=0.0001):
7308
+ def VertexDegree(graph : topologic.Graph, vertex: topologic.Vertex, edgeKey: str = None, tolerance: float = 0.0001):
6739
7309
  """
6740
7310
  Returns the degree of the input vertex. See https://en.wikipedia.org/wiki/Degree_(graph_theory).
6741
7311