topologicpy 0.5.9__py3-none-any.whl → 6.0.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.
Files changed (94) hide show
  1. topologicpy/Aperture.py +72 -72
  2. topologicpy/Cell.py +2169 -2169
  3. topologicpy/CellComplex.py +1137 -1137
  4. topologicpy/Cluster.py +1288 -1280
  5. topologicpy/Color.py +423 -423
  6. topologicpy/Context.py +79 -79
  7. topologicpy/DGL.py +3213 -3240
  8. topologicpy/Dictionary.py +698 -698
  9. topologicpy/Edge.py +1187 -1187
  10. topologicpy/EnergyModel.py +1180 -1152
  11. topologicpy/Face.py +2141 -2141
  12. topologicpy/Graph.py +7768 -7768
  13. topologicpy/Grid.py +353 -353
  14. topologicpy/Helper.py +507 -507
  15. topologicpy/Honeybee.py +461 -461
  16. topologicpy/Matrix.py +271 -271
  17. topologicpy/Neo4j.py +521 -521
  18. topologicpy/Plotly.py +2 -2
  19. topologicpy/Polyskel.py +541 -541
  20. topologicpy/Shell.py +1768 -1768
  21. topologicpy/Speckle.py +508 -508
  22. topologicpy/Topology.py +7060 -7002
  23. topologicpy/Vector.py +905 -905
  24. topologicpy/Vertex.py +1585 -1585
  25. topologicpy/Wire.py +3050 -3050
  26. topologicpy/__init__.py +22 -38
  27. topologicpy/version.py +1 -0
  28. {topologicpy-0.5.9.dist-info → topologicpy-6.0.0.dist-info}/LICENSE +661 -704
  29. topologicpy-6.0.0.dist-info/METADATA +751 -0
  30. topologicpy-6.0.0.dist-info/RECORD +32 -0
  31. topologicpy/bin/linux/topologic/__init__.py +0 -2
  32. topologicpy/bin/linux/topologic/libTKBO-6bdf205d.so.7.7.0 +0 -0
  33. topologicpy/bin/linux/topologic/libTKBRep-2960a069.so.7.7.0 +0 -0
  34. topologicpy/bin/linux/topologic/libTKBool-c44b74bd.so.7.7.0 +0 -0
  35. topologicpy/bin/linux/topologic/libTKFillet-9a670ba0.so.7.7.0 +0 -0
  36. topologicpy/bin/linux/topologic/libTKG2d-8f31849e.so.7.7.0 +0 -0
  37. topologicpy/bin/linux/topologic/libTKG3d-4c6bce57.so.7.7.0 +0 -0
  38. topologicpy/bin/linux/topologic/libTKGeomAlgo-26066fd9.so.7.7.0 +0 -0
  39. topologicpy/bin/linux/topologic/libTKGeomBase-2116cabe.so.7.7.0 +0 -0
  40. topologicpy/bin/linux/topologic/libTKMath-72572fa8.so.7.7.0 +0 -0
  41. topologicpy/bin/linux/topologic/libTKMesh-2a060427.so.7.7.0 +0 -0
  42. topologicpy/bin/linux/topologic/libTKOffset-6cab68ff.so.7.7.0 +0 -0
  43. topologicpy/bin/linux/topologic/libTKPrim-eb1262b3.so.7.7.0 +0 -0
  44. topologicpy/bin/linux/topologic/libTKShHealing-e67e5cc7.so.7.7.0 +0 -0
  45. topologicpy/bin/linux/topologic/libTKTopAlgo-e4c96c33.so.7.7.0 +0 -0
  46. topologicpy/bin/linux/topologic/libTKernel-fb7fe3b7.so.7.7.0 +0 -0
  47. topologicpy/bin/linux/topologic/libgcc_s-32c1665e.so.1 +0 -0
  48. topologicpy/bin/linux/topologic/libstdc++-672d7b41.so.6.0.30 +0 -0
  49. topologicpy/bin/linux/topologic/topologic.cpython-310-x86_64-linux-gnu.so +0 -0
  50. topologicpy/bin/linux/topologic/topologic.cpython-311-x86_64-linux-gnu.so +0 -0
  51. topologicpy/bin/linux/topologic/topologic.cpython-38-x86_64-linux-gnu.so +0 -0
  52. topologicpy/bin/linux/topologic/topologic.cpython-39-x86_64-linux-gnu.so +0 -0
  53. topologicpy/bin/linux/topologic.libs/libTKBO-6bdf205d.so.7.7.0 +0 -0
  54. topologicpy/bin/linux/topologic.libs/libTKBRep-2960a069.so.7.7.0 +0 -0
  55. topologicpy/bin/linux/topologic.libs/libTKBool-c44b74bd.so.7.7.0 +0 -0
  56. topologicpy/bin/linux/topologic.libs/libTKFillet-9a670ba0.so.7.7.0 +0 -0
  57. topologicpy/bin/linux/topologic.libs/libTKG2d-8f31849e.so.7.7.0 +0 -0
  58. topologicpy/bin/linux/topologic.libs/libTKG3d-4c6bce57.so.7.7.0 +0 -0
  59. topologicpy/bin/linux/topologic.libs/libTKGeomAlgo-26066fd9.so.7.7.0 +0 -0
  60. topologicpy/bin/linux/topologic.libs/libTKGeomBase-2116cabe.so.7.7.0 +0 -0
  61. topologicpy/bin/linux/topologic.libs/libTKMath-72572fa8.so.7.7.0 +0 -0
  62. topologicpy/bin/linux/topologic.libs/libTKMesh-2a060427.so.7.7.0 +0 -0
  63. topologicpy/bin/linux/topologic.libs/libTKOffset-6cab68ff.so.7.7.0 +0 -0
  64. topologicpy/bin/linux/topologic.libs/libTKPrim-eb1262b3.so.7.7.0 +0 -0
  65. topologicpy/bin/linux/topologic.libs/libTKShHealing-e67e5cc7.so.7.7.0 +0 -0
  66. topologicpy/bin/linux/topologic.libs/libTKTopAlgo-e4c96c33.so.7.7.0 +0 -0
  67. topologicpy/bin/linux/topologic.libs/libTKernel-fb7fe3b7.so.7.7.0 +0 -0
  68. topologicpy/bin/linux/topologic.libs/libgcc_s-32c1665e.so.1 +0 -0
  69. topologicpy/bin/linux/topologic.libs/libstdc++-672d7b41.so.6.0.30 +0 -0
  70. topologicpy/bin/macos/topologic/__init__.py +0 -2
  71. topologicpy/bin/windows/topologic/TKBO-f6b191de.dll +0 -0
  72. topologicpy/bin/windows/topologic/TKBRep-e56a600e.dll +0 -0
  73. topologicpy/bin/windows/topologic/TKBool-7b8d47ae.dll +0 -0
  74. topologicpy/bin/windows/topologic/TKFillet-0ddbf0a8.dll +0 -0
  75. topologicpy/bin/windows/topologic/TKG2d-2e2dee3d.dll +0 -0
  76. topologicpy/bin/windows/topologic/TKG3d-6674513d.dll +0 -0
  77. topologicpy/bin/windows/topologic/TKGeomAlgo-d240e370.dll +0 -0
  78. topologicpy/bin/windows/topologic/TKGeomBase-df87aba5.dll +0 -0
  79. topologicpy/bin/windows/topologic/TKMath-45bd625a.dll +0 -0
  80. topologicpy/bin/windows/topologic/TKMesh-d6e826b1.dll +0 -0
  81. topologicpy/bin/windows/topologic/TKOffset-79b9cc94.dll +0 -0
  82. topologicpy/bin/windows/topologic/TKPrim-aa430a86.dll +0 -0
  83. topologicpy/bin/windows/topologic/TKShHealing-bb48be89.dll +0 -0
  84. topologicpy/bin/windows/topologic/TKTopAlgo-7d0d1e22.dll +0 -0
  85. topologicpy/bin/windows/topologic/TKernel-08c8cfbb.dll +0 -0
  86. topologicpy/bin/windows/topologic/__init__.py +0 -2
  87. topologicpy/bin/windows/topologic/topologic.cp310-win_amd64.pyd +0 -0
  88. topologicpy/bin/windows/topologic/topologic.cp311-win_amd64.pyd +0 -0
  89. topologicpy/bin/windows/topologic/topologic.cp38-win_amd64.pyd +0 -0
  90. topologicpy/bin/windows/topologic/topologic.cp39-win_amd64.pyd +0 -0
  91. topologicpy-0.5.9.dist-info/METADATA +0 -86
  92. topologicpy-0.5.9.dist-info/RECORD +0 -91
  93. {topologicpy-0.5.9.dist-info → topologicpy-6.0.0.dist-info}/WHEEL +0 -0
  94. {topologicpy-0.5.9.dist-info → topologicpy-6.0.0.dist-info}/top_level.txt +0 -0
topologicpy/Neo4j.py CHANGED
@@ -1,522 +1,522 @@
1
- # Copyright (C) 2024
2
- # Wassim Jabi <wassim.jabi@gmail.com>
3
- #
4
- # This program is free software: you can redistribute it and/or modify it under
5
- # the terms of the GNU Affero General Public License as published by the Free Software
6
- # Foundation, either version 3 of the License, or (at your option) any later
7
- # version.
8
- #
9
- # This program is distributed in the hope that it will be useful, but WITHOUT
10
- # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
11
- # FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
12
- # details.
13
- #
14
- # You should have received a copy of the GNU Affero General Public License along with
15
- # this program. If not, see <https://www.gnu.org/licenses/>.
16
-
17
- import time
18
- import random
19
- import os
20
- import warnings
21
-
22
- try:
23
- import py2neo
24
- from py2neo import NodeMatcher,RelationshipMatcher
25
- from py2neo.data import spatial as sp
26
- except:
27
- print("Neo4j - Installing required py2neo library.")
28
- try:
29
- os.system("pip install py2neo")
30
- except:
31
- os.system("pip install py2neo --user")
32
- try:
33
- import py2neo
34
- from py2neo import NodeMatcher,RelationshipMatcher
35
- from py2neo.data import spatial as sp
36
- except:
37
- warnings.warn("Neo4j - Error: Could not import py2neo")
38
-
39
- class Neo4j:
40
-
41
- @staticmethod
42
- def NodeToVertex(node):
43
- """
44
- Converts the input neo4j node to a topologic vertex.
45
-
46
- Parameters
47
- ----------
48
- node : Neo4j.Node
49
- The input neo4j node.
50
-
51
- Returns
52
- -------
53
- topologic.Vertex
54
- The output topologic vertex.
55
-
56
- """
57
- from topologicpy.Vertex import Vertex
58
- from topologicpy.Topology import Topology
59
- from topologicpy.Dictionary import Dictionary
60
-
61
- if ('x' in node.keys()) and ('y' in node.keys()) and ('z' in node.keys()) or ('X' in node.keys()) and ('Y' in node.keys()) and ('Z' in node.keys()):
62
- x = node['x']
63
- y = node['y']
64
- z = node['z']
65
- vertex = Vertex.ByCoordinates(x, y, z)
66
- else:
67
- x = random.uniform(0, 1000)
68
- y = random.uniform(0, 1000)
69
- z = random.uniform(0, 1000)
70
- vertex = Vertex.ByCoordinates(x, y, z)
71
- keys = list(node.keys())
72
- values = list(node.values())
73
- d = Dictionary.ByKeysValues(keys, values)
74
- vertex = Topology.SetDictionary(vertex, d)
75
- return vertex
76
-
77
-
78
- @staticmethod
79
- def NodesByCypher(neo4jGraph, cypher):
80
- dataList = neo4jGraph.run(cypher).data()
81
- nodes = []
82
- for data in dataList:
83
- path = data['p']
84
- nodes += list(path.nodes)
85
- return nodes
86
-
87
- @staticmethod
88
- def NodesBySubGraph(subGraph):
89
- data = subGraph.data()
90
- nodes = []
91
- for data in subGraph:
92
- path = data['p']
93
- nodes += list(path.nodes)
94
- return nodes
95
-
96
- @staticmethod
97
- def SubGraphByCypher(neo4jGraph, cypher):
98
- return neo4jGraph.run(cypher).to_subgraph()
99
-
100
- @staticmethod
101
- def SubGraphExportToGraph(subGraph, tolerance=0.0001):
102
- """
103
- Exports the input neo4j graph to a topologic graph.
104
-
105
- Parameters
106
- ----------
107
- subGraph : Neo4j.SubGraph
108
- The input neo4j subgraph.
109
- tolerance : float , optional
110
- The desired tolerance. The default is 0.0001.
111
-
112
- Returns
113
- -------
114
- topologic.Graph
115
- The output topologic graph.
116
-
117
- """
118
- from topologicpy.Vertex import Vertex
119
- from topologicpy.Edge import Edge
120
- from topologicpy.Topology import Topology
121
- from topologicpy.Dictionary import Dictionary
122
- from topologicpy.Graph import Graph
123
-
124
- def randomVertex(vertices, minDistance):
125
- flag = True
126
- while flag:
127
- x = random.uniform(0, 1000)
128
- y = random.uniform(0, 1000)
129
- z = random.uniform(0, 1000)
130
- v = Vertex.ByCoordinates(x, y, z)
131
- test = False
132
- if len(vertices) < 1:
133
- return v
134
- for vertex in vertices:
135
- d = Vertex.Distance(v, vertex)
136
- if d < minDistance:
137
- test = True
138
- break
139
- if test == False:
140
- return v
141
- else:
142
- continue
143
-
144
- nodes = subGraph.nodes
145
- relationships = list(subGraph.relationships)
146
- vertices = []
147
- edges = []
148
- for node in nodes:
149
- #Check if they have X, Y, Z coordinates
150
- if ('x' in node.keys()) and ('y' in node.keys()) and ('z' in node.keys()) or ('X' in node.keys()) and ('Y' in node.keys()) and ('Z' in node.keys()):
151
- x = node['x']
152
- y = node['y']
153
- z = node['z']
154
- vertex = Vertex.ByCoordinates(x, y, z)
155
- else:
156
- vertex = randomVertex(vertices, 1)
157
- keys = list(node.keys())
158
- keys.append("identity")
159
- values = [node.identity]
160
- for key in keys:
161
- values.append(node[key])
162
- d = Dictionary.ByKeysValues(keys, values)
163
- vertex = Topology.SetDictionary(vertex, d)
164
- vertices.append(vertex)
165
- for relationship in relationships:
166
- keys = list(relationship.keys())
167
- keys.append("identity")
168
- values = [relationship.identity]
169
- for key in keys:
170
- values.append(node[key])
171
- sv = vertices[nodes.index(relationship.start_node)]
172
- ev = vertices[nodes.index(relationship.end_node)]
173
- edge = Edge.ByVertices([sv, ev], tolerance=tolerance)
174
- if relationship.start_node['name']:
175
- sv_name = relationship.start_node['name']
176
- else:
177
- sv_name = 'None'
178
- if relationship.end_node['name']:
179
- ev_name = relationship.end_node['name']
180
- else:
181
- ev_name = 'None'
182
- d = Dictionary.ByKeysValues(["relationship_type", "from", "to"], [relationship.__class__.__name__, sv_name, ev_name])
183
- if d:
184
- _ = Topology.SetDictionary(edge, d)
185
- edges.append(edge)
186
- return Graph.ByVerticesEdges(vertices,edges)
187
-
188
- @staticmethod
189
- def ExportToGraph(neo4jGraph, tolerance=0.0001):
190
- """
191
- Exports the input neo4j graph to a topologic graph.
192
-
193
- Parameters
194
- ----------
195
- neo4jGraph : Neo4j.Graph
196
- The input neo4j graph.
197
- tolerance : float , optional
198
- The desired tolerance. The default is 0.0001.
199
-
200
- Returns
201
- -------
202
- topologic.Graph
203
- The output topologic graph.
204
-
205
- """
206
- from topologicpy.Vertex import Vertex
207
- from topologicpy.Edge import Edge
208
- from topologicpy.Topology import Topology
209
- from topologicpy.Dictionary import Dictionary
210
- from topologicpy.Graph import Graph
211
-
212
- def randomVertex(vertices, minDistance):
213
- flag = True
214
- while flag:
215
- x = random.uniform(0, 1000)
216
- y = random.uniform(0, 1000)
217
- z = random.uniform(0, 1000)
218
- v = Vertex.ByCoordinates(x, y, z)
219
- test = False
220
- if len(vertices) < 1:
221
- return v
222
- for vertex in vertices:
223
- d = Vertex.Distance(v, vertex)
224
- if d < minDistance:
225
- test = True
226
- break
227
- if test == False:
228
- return v
229
- else:
230
- continue
231
-
232
- node_labels = neo4jGraph.schema.node_labels
233
- relationship_types = neo4jGraph.schema.relationship_types
234
- node_matcher = NodeMatcher(neo4jGraph)
235
- relationship_matcher = RelationshipMatcher(neo4jGraph)
236
- vertices = []
237
- edges = []
238
- nodes = []
239
- for node_label in node_labels:
240
- nodes = nodes + (list(node_matcher.match(node_label)))
241
- for node in nodes:
242
- #Check if they have X, Y, Z coordinates
243
- if ('x' in node.keys()) and ('y' in node.keys()) and ('z' in node.keys()) or ('X' in node.keys()) and ('Y' in node.keys()) and ('Z' in node.keys()):
244
- x = node['x']
245
- y = node['y']
246
- z = node['z']
247
- vertex = Vertex.ByCoordinates(x, y, z)
248
- else:
249
- vertex = randomVertex(vertices, 1)
250
- keys = list(node.keys())
251
- values = []
252
- for key in keys:
253
- values.append(node[key])
254
- d = Dictionary.ByKeysValues(keys, values)
255
- vertex = Topology.SetDictionary(vertex, d)
256
- vertices.append(vertex)
257
- for node in nodes:
258
- for relationship_type in relationship_types:
259
- relationships = list(relationship_matcher.match([node], r_type=relationship_type))
260
- for relationship in relationships:
261
- sv = vertices[nodes.index(relationship.start_node)]
262
- ev = vertices[nodes.index(relationship.end_node)]
263
- edge = Edge.ByVertices([sv, ev], tolerance=tolerance)
264
- if relationship.start_node['name']:
265
- sv_name = relationship.start_node['name']
266
- else:
267
- sv_name = 'None'
268
- if relationship.end_node['name']:
269
- ev_name = relationship.end_node['name']
270
- else:
271
- ev_name = 'None'
272
- d = Dictionary.ByKeysValues(["relationship_type", "from", "to"], [relationship_type, sv_name, ev_name])
273
- if d:
274
- _ = Topology.SetDictionary(edge, d)
275
- edges.append(edge)
276
- return Graph.ByVerticesEdges(vertices,edges)
277
-
278
- @staticmethod
279
- def AddGraph(neo4jGraph, graph, labelKey=None, relationshipKey=None, bidirectional=True, deleteAll=True, tolerance=0.0001):
280
- """
281
- Adds the input topologic graph to the input neo4j graph
282
-
283
- Parameters
284
- ----------
285
- neo4jGraph : Neo4j.Graph
286
- The input neo4j graph.
287
- graph : topologic.Graph
288
- The input topologic graph.
289
- categoryKey : str
290
- The category key in the dictionary under which to look for the category value.
291
- tolerance : float , optional
292
- The desired tolerance. The default is 0.0001.
293
-
294
- Returns
295
- -------
296
- Neo4j.Graph
297
- The input neo4j graph with the input topologic graph added to it.
298
-
299
- """
300
- from topologicpy.Vertex import Vertex
301
- from topologicpy.Topology import Topology
302
- from topologicpy.Graph import Graph
303
- from topologicpy.Dictionary import Dictionary
304
- gmt = time.gmtime()
305
- timestamp = str(gmt.tm_zone)+"_"+str(gmt.tm_year)+"_"+str(gmt.tm_mon)+"_"+str(gmt.tm_wday)+"_"+str(gmt.tm_hour)+"_"+str(gmt.tm_min)+"_"+str(gmt.tm_sec)
306
- vertices = Graph.Vertices(graph)
307
- edges = Graph.Edges(graph)
308
- tx = neo4jGraph.begin()
309
- nodes = []
310
- for i in range(len(vertices)):
311
- vDict = Topology.Dictionary(vertices[i])
312
- keys = Dictionary.Keyus(vDict)
313
- values = Dictionary.Values(vDict)
314
- keys.append("x")
315
- keys.append("y")
316
- keys.append("z")
317
- keys.append("timestamp")
318
- keys.append("location")
319
- values.append(vertices[i].X())
320
- values.append(vertices[i].Y())
321
- values.append(vertices[i].Z())
322
- values.append(timestamp)
323
- values.append(sp.CartesianPoint([vertices[i].X(),vertices[i].Y(),vertices[i].Z()]))
324
- zip_iterator = zip(keys, values)
325
- pydict = dict(zip_iterator)
326
- if labelKey == 'None':
327
- nodeName = "TopologicGraphVertex"
328
- else:
329
- nodeName = str(values[keys.index(labelKey)])
330
- n = py2neo.Node(nodeName, **pydict)
331
- neo4jGraph.cypher.execute("CREATE INDEX FOR (n:%s) on (n.name)" %
332
- n.nodelabel)
333
- tx.create(n)
334
- nodes.append(n)
335
- for i in range(len(edges)):
336
- e = edges[i]
337
- sv = e.StartVertex()
338
- ev = e.EndVertex()
339
- sn = nodes[Vertex.Index(sv, vertices, tolerance)]
340
- en = nodes[Vertex.Index(ev, vertices, tolerance)]
341
- relationshipType = Dictionary.ValueAtKey(e, relationshipKey)
342
- if not (relationshipType):
343
- relationshipType = "Connected To"
344
- snen = py2neo.Relationship(sn, relationshipType, en)
345
- tx.create(snen)
346
- snen = py2neo.Relationship(en, relationshipType, sn)
347
- tx.create(snen)
348
- neo4jGraph.commit(tx)
349
- return neo4jGraph
350
-
351
-
352
- @staticmethod
353
- def ByParameters(url, username, password):
354
- """
355
- Returns a Neo4j graph by the input parameters.
356
-
357
- Parameters
358
- ----------
359
- url : str
360
- The URL of the server.
361
- username : str
362
- The username to use for logging in.
363
- password : str
364
- The password to use for logging in.
365
-
366
- Returns
367
- -------
368
- Neo4j.Graph
369
- The returned Neo4j graph.
370
-
371
- """
372
- return py2neo.Graph(url, auth=(username, password))
373
-
374
- @staticmethod
375
- def DeleteAll(neo4jGraph):
376
- """
377
- Deletes all entities in the input Neo4j graph.
378
-
379
- Parameters
380
- ----------
381
- neo4jGraph : Neo4j Graph
382
- The input Neo4jGraph.
383
-
384
- Returns
385
- -------
386
- Neo4J Graph
387
- The returned empty graph.
388
-
389
- """
390
- neo4jGraph.delete_all()
391
- return neo4jGraph
392
-
393
- @staticmethod
394
- def NodeLabels(neo4jGraph):
395
- """
396
- Returns all the node labels used in the input neo4j graph.
397
-
398
- Parameters
399
- ----------
400
- neo4jGraph : Newo4j.Graph
401
- The input neo4j graph.
402
-
403
- Returns
404
- -------
405
- list
406
- The list of node labels used in the input neo4j graph.
407
-
408
- """
409
- return list(neo4jGraph.schema.node_labels)
410
-
411
- @staticmethod
412
- def RelationshipTypes(neo4jGraph):
413
- """
414
- Returns all the relationship types used in the input neo4j graph.
415
-
416
- Parameters
417
- ----------
418
- neo4jGraph : Newo4j.Graph
419
- The input neo4j graph.
420
-
421
- Returns
422
- -------
423
- list
424
- The list of relationship types used in the input neo4j graph.
425
-
426
- """
427
- return list(neo4jGraph.schema.relationship_types)
428
-
429
- @staticmethod
430
- def SetGraph(neo4jGraph, graph, labelKey=None, relationshipKey=None, bidirectional=True, deleteAll=True, tolerance=0.0001):
431
- """
432
- Sets the input topologic graph to the input neo4jGraph.
433
-
434
- Parameters
435
- ----------
436
- neo4jGraph : Neo4j.Graph
437
- The input neo4j graph.
438
- graph : topologic.Graph
439
- The input topologic graph.
440
- labelKey : str , optional
441
- The dictionary key under which to find the vertex's label value. The default is None which means the vertex gets the name 'TopologicGraphVertex'.
442
- relationshipKey : str , optional
443
- The dictionary key under which to find the edge's relationship value. The default is None which means the edge gets the relationship type 'Connected To'.
444
- bidirectional : bool , optional
445
- If set to True, the edges in the neo4j graph are set to be bi-drectional.
446
- deleteAll : bool , optional
447
- If set to True, all previous entities are deleted before adding the new entities.
448
- tolerance : float , optional
449
- The desired tolerance. The default is 0.0001.
450
-
451
- Returns
452
- -------
453
- neo4jGraph : TYPE
454
- The input neo4j graph with the input topologic graph added to it.
455
-
456
- """
457
- from topologicpy.Vertex import Vertex
458
- from topologicpy.Graph import Graph
459
- from topologicpy.Topology import Topology
460
- from topologicpy.Dictionary import Dictionary
461
-
462
- import time
463
- gmt = time.gmtime()
464
- timestamp = str(gmt.tm_zone)+"_"+str(gmt.tm_year)+"_"+str(gmt.tm_mon)+"_"+str(gmt.tm_wday)+"_"+str(gmt.tm_hour)+"_"+str(gmt.tm_min)+"_"+str(gmt.tm_sec)
465
-
466
- vertices = Graph.Vertices(graph)
467
- edges = Graph.Edges(graph)
468
- tx = neo4jGraph.begin()
469
- nodes = []
470
- for i in range(len(vertices)):
471
- vDict = Topology.Dictionary(vertices[i])
472
- if not vDict:
473
- keys = []
474
- values = []
475
- else:
476
- keys = Dictionary.Keys(vDict)
477
- if not keys:
478
- keys = []
479
- values = Dictionary.Values(vDict)
480
- if not values:
481
- values = []
482
- keys.append("x")
483
- keys.append("y")
484
- keys.append("z")
485
- keys.append("timestamp")
486
- keys.append("location")
487
- values.append(vertices[i].X())
488
- values.append(vertices[i].Y())
489
- values.append(vertices[i].Z())
490
- values.append(timestamp)
491
- values.append(sp.CartesianPoint([vertices[i].X(),vertices[i].Y(),vertices[i].Z()]))
492
- zip_iterator = zip(keys, values)
493
- pydict = dict(zip_iterator)
494
- if (labelKey == 'None') or (not (labelKey)):
495
- nodeName = "TopologicGraphVertex"
496
- else:
497
- nodeName = str(Dictionary.ValueAtKey(vDict, labelKey))
498
- n = py2neo.Node(nodeName, **pydict)
499
- tx.create(n)
500
- nodes.append(n)
501
- for i in range(len(edges)):
502
- e = edges[i]
503
- sv = e.StartVertex()
504
- ev = e.EndVertex()
505
- sn = nodes[Vertex.Index(vertex=sv, vertices=vertices, strict=False, tolerance=tolerance)]
506
- en = nodes[Vertex.Index(vertex=ev, vertices=vertices, strict=False, tolerance=tolerance)]
507
- ed = Topology.Dictionary(e)
508
- if relationshipKey:
509
- relationshipType = Dictionary.ValueAtKey(ed, relationshipKey)
510
- else:
511
- relationshipType = "Connected To"
512
- if not (relationshipType):
513
- relationshipType = "Connected To"
514
- snen = py2neo.Relationship(sn, relationshipType, en)
515
- tx.create(snen)
516
- if bidirectional:
517
- snen = py2neo.Relationship(en, relationshipType, sn)
518
- tx.create(snen)
519
- if deleteAll:
520
- neo4jGraph.delete_all()
521
- neo4jGraph.commit(tx)
1
+ # Copyright (C) 2024
2
+ # Wassim Jabi <wassim.jabi@gmail.com>
3
+ #
4
+ # This program is free software: you can redistribute it and/or modify it under
5
+ # the terms of the GNU Affero General Public License as published by the Free Software
6
+ # Foundation, either version 3 of the License, or (at your option) any later
7
+ # version.
8
+ #
9
+ # This program is distributed in the hope that it will be useful, but WITHOUT
10
+ # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
11
+ # FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
12
+ # details.
13
+ #
14
+ # You should have received a copy of the GNU Affero General Public License along with
15
+ # this program. If not, see <https://www.gnu.org/licenses/>.
16
+
17
+ import time
18
+ import random
19
+ import os
20
+ import warnings
21
+
22
+ try:
23
+ import py2neo
24
+ from py2neo import NodeMatcher,RelationshipMatcher
25
+ from py2neo.data import spatial as sp
26
+ except:
27
+ print("Neo4j - Installing required py2neo library.")
28
+ try:
29
+ os.system("pip install py2neo")
30
+ except:
31
+ os.system("pip install py2neo --user")
32
+ try:
33
+ import py2neo
34
+ from py2neo import NodeMatcher,RelationshipMatcher
35
+ from py2neo.data import spatial as sp
36
+ except:
37
+ warnings.warn("Neo4j - Error: Could not import py2neo")
38
+
39
+ class Neo4j:
40
+
41
+ @staticmethod
42
+ def NodeToVertex(node):
43
+ """
44
+ Converts the input neo4j node to a topologic vertex.
45
+
46
+ Parameters
47
+ ----------
48
+ node : Neo4j.Node
49
+ The input neo4j node.
50
+
51
+ Returns
52
+ -------
53
+ topologic.Vertex
54
+ The output topologic vertex.
55
+
56
+ """
57
+ from topologicpy.Vertex import Vertex
58
+ from topologicpy.Topology import Topology
59
+ from topologicpy.Dictionary import Dictionary
60
+
61
+ if ('x' in node.keys()) and ('y' in node.keys()) and ('z' in node.keys()) or ('X' in node.keys()) and ('Y' in node.keys()) and ('Z' in node.keys()):
62
+ x = node['x']
63
+ y = node['y']
64
+ z = node['z']
65
+ vertex = Vertex.ByCoordinates(x, y, z)
66
+ else:
67
+ x = random.uniform(0, 1000)
68
+ y = random.uniform(0, 1000)
69
+ z = random.uniform(0, 1000)
70
+ vertex = Vertex.ByCoordinates(x, y, z)
71
+ keys = list(node.keys())
72
+ values = list(node.values())
73
+ d = Dictionary.ByKeysValues(keys, values)
74
+ vertex = Topology.SetDictionary(vertex, d)
75
+ return vertex
76
+
77
+
78
+ @staticmethod
79
+ def NodesByCypher(neo4jGraph, cypher):
80
+ dataList = neo4jGraph.run(cypher).data()
81
+ nodes = []
82
+ for data in dataList:
83
+ path = data['p']
84
+ nodes += list(path.nodes)
85
+ return nodes
86
+
87
+ @staticmethod
88
+ def NodesBySubGraph(subGraph):
89
+ data = subGraph.data()
90
+ nodes = []
91
+ for data in subGraph:
92
+ path = data['p']
93
+ nodes += list(path.nodes)
94
+ return nodes
95
+
96
+ @staticmethod
97
+ def SubGraphByCypher(neo4jGraph, cypher):
98
+ return neo4jGraph.run(cypher).to_subgraph()
99
+
100
+ @staticmethod
101
+ def SubGraphExportToGraph(subGraph, tolerance=0.0001):
102
+ """
103
+ Exports the input neo4j graph to a topologic graph.
104
+
105
+ Parameters
106
+ ----------
107
+ subGraph : Neo4j.SubGraph
108
+ The input neo4j subgraph.
109
+ tolerance : float , optional
110
+ The desired tolerance. The default is 0.0001.
111
+
112
+ Returns
113
+ -------
114
+ topologic.Graph
115
+ The output topologic graph.
116
+
117
+ """
118
+ from topologicpy.Vertex import Vertex
119
+ from topologicpy.Edge import Edge
120
+ from topologicpy.Topology import Topology
121
+ from topologicpy.Dictionary import Dictionary
122
+ from topologicpy.Graph import Graph
123
+
124
+ def randomVertex(vertices, minDistance):
125
+ flag = True
126
+ while flag:
127
+ x = random.uniform(0, 1000)
128
+ y = random.uniform(0, 1000)
129
+ z = random.uniform(0, 1000)
130
+ v = Vertex.ByCoordinates(x, y, z)
131
+ test = False
132
+ if len(vertices) < 1:
133
+ return v
134
+ for vertex in vertices:
135
+ d = Vertex.Distance(v, vertex)
136
+ if d < minDistance:
137
+ test = True
138
+ break
139
+ if test == False:
140
+ return v
141
+ else:
142
+ continue
143
+
144
+ nodes = subGraph.nodes
145
+ relationships = list(subGraph.relationships)
146
+ vertices = []
147
+ edges = []
148
+ for node in nodes:
149
+ #Check if they have X, Y, Z coordinates
150
+ if ('x' in node.keys()) and ('y' in node.keys()) and ('z' in node.keys()) or ('X' in node.keys()) and ('Y' in node.keys()) and ('Z' in node.keys()):
151
+ x = node['x']
152
+ y = node['y']
153
+ z = node['z']
154
+ vertex = Vertex.ByCoordinates(x, y, z)
155
+ else:
156
+ vertex = randomVertex(vertices, 1)
157
+ keys = list(node.keys())
158
+ keys.append("identity")
159
+ values = [node.identity]
160
+ for key in keys:
161
+ values.append(node[key])
162
+ d = Dictionary.ByKeysValues(keys, values)
163
+ vertex = Topology.SetDictionary(vertex, d)
164
+ vertices.append(vertex)
165
+ for relationship in relationships:
166
+ keys = list(relationship.keys())
167
+ keys.append("identity")
168
+ values = [relationship.identity]
169
+ for key in keys:
170
+ values.append(node[key])
171
+ sv = vertices[nodes.index(relationship.start_node)]
172
+ ev = vertices[nodes.index(relationship.end_node)]
173
+ edge = Edge.ByVertices([sv, ev], tolerance=tolerance)
174
+ if relationship.start_node['name']:
175
+ sv_name = relationship.start_node['name']
176
+ else:
177
+ sv_name = 'None'
178
+ if relationship.end_node['name']:
179
+ ev_name = relationship.end_node['name']
180
+ else:
181
+ ev_name = 'None'
182
+ d = Dictionary.ByKeysValues(["relationship_type", "from", "to"], [relationship.__class__.__name__, sv_name, ev_name])
183
+ if d:
184
+ _ = Topology.SetDictionary(edge, d)
185
+ edges.append(edge)
186
+ return Graph.ByVerticesEdges(vertices,edges)
187
+
188
+ @staticmethod
189
+ def ExportToGraph(neo4jGraph, tolerance=0.0001):
190
+ """
191
+ Exports the input neo4j graph to a topologic graph.
192
+
193
+ Parameters
194
+ ----------
195
+ neo4jGraph : Neo4j.Graph
196
+ The input neo4j graph.
197
+ tolerance : float , optional
198
+ The desired tolerance. The default is 0.0001.
199
+
200
+ Returns
201
+ -------
202
+ topologic.Graph
203
+ The output topologic graph.
204
+
205
+ """
206
+ from topologicpy.Vertex import Vertex
207
+ from topologicpy.Edge import Edge
208
+ from topologicpy.Topology import Topology
209
+ from topologicpy.Dictionary import Dictionary
210
+ from topologicpy.Graph import Graph
211
+
212
+ def randomVertex(vertices, minDistance):
213
+ flag = True
214
+ while flag:
215
+ x = random.uniform(0, 1000)
216
+ y = random.uniform(0, 1000)
217
+ z = random.uniform(0, 1000)
218
+ v = Vertex.ByCoordinates(x, y, z)
219
+ test = False
220
+ if len(vertices) < 1:
221
+ return v
222
+ for vertex in vertices:
223
+ d = Vertex.Distance(v, vertex)
224
+ if d < minDistance:
225
+ test = True
226
+ break
227
+ if test == False:
228
+ return v
229
+ else:
230
+ continue
231
+
232
+ node_labels = neo4jGraph.schema.node_labels
233
+ relationship_types = neo4jGraph.schema.relationship_types
234
+ node_matcher = NodeMatcher(neo4jGraph)
235
+ relationship_matcher = RelationshipMatcher(neo4jGraph)
236
+ vertices = []
237
+ edges = []
238
+ nodes = []
239
+ for node_label in node_labels:
240
+ nodes = nodes + (list(node_matcher.match(node_label)))
241
+ for node in nodes:
242
+ #Check if they have X, Y, Z coordinates
243
+ if ('x' in node.keys()) and ('y' in node.keys()) and ('z' in node.keys()) or ('X' in node.keys()) and ('Y' in node.keys()) and ('Z' in node.keys()):
244
+ x = node['x']
245
+ y = node['y']
246
+ z = node['z']
247
+ vertex = Vertex.ByCoordinates(x, y, z)
248
+ else:
249
+ vertex = randomVertex(vertices, 1)
250
+ keys = list(node.keys())
251
+ values = []
252
+ for key in keys:
253
+ values.append(node[key])
254
+ d = Dictionary.ByKeysValues(keys, values)
255
+ vertex = Topology.SetDictionary(vertex, d)
256
+ vertices.append(vertex)
257
+ for node in nodes:
258
+ for relationship_type in relationship_types:
259
+ relationships = list(relationship_matcher.match([node], r_type=relationship_type))
260
+ for relationship in relationships:
261
+ sv = vertices[nodes.index(relationship.start_node)]
262
+ ev = vertices[nodes.index(relationship.end_node)]
263
+ edge = Edge.ByVertices([sv, ev], tolerance=tolerance)
264
+ if relationship.start_node['name']:
265
+ sv_name = relationship.start_node['name']
266
+ else:
267
+ sv_name = 'None'
268
+ if relationship.end_node['name']:
269
+ ev_name = relationship.end_node['name']
270
+ else:
271
+ ev_name = 'None'
272
+ d = Dictionary.ByKeysValues(["relationship_type", "from", "to"], [relationship_type, sv_name, ev_name])
273
+ if d:
274
+ _ = Topology.SetDictionary(edge, d)
275
+ edges.append(edge)
276
+ return Graph.ByVerticesEdges(vertices,edges)
277
+
278
+ @staticmethod
279
+ def AddGraph(neo4jGraph, graph, labelKey=None, relationshipKey=None, bidirectional=True, deleteAll=True, tolerance=0.0001):
280
+ """
281
+ Adds the input topologic graph to the input neo4j graph
282
+
283
+ Parameters
284
+ ----------
285
+ neo4jGraph : Neo4j.Graph
286
+ The input neo4j graph.
287
+ graph : topologic.Graph
288
+ The input topologic graph.
289
+ categoryKey : str
290
+ The category key in the dictionary under which to look for the category value.
291
+ tolerance : float , optional
292
+ The desired tolerance. The default is 0.0001.
293
+
294
+ Returns
295
+ -------
296
+ Neo4j.Graph
297
+ The input neo4j graph with the input topologic graph added to it.
298
+
299
+ """
300
+ from topologicpy.Vertex import Vertex
301
+ from topologicpy.Topology import Topology
302
+ from topologicpy.Graph import Graph
303
+ from topologicpy.Dictionary import Dictionary
304
+ gmt = time.gmtime()
305
+ timestamp = str(gmt.tm_zone)+"_"+str(gmt.tm_year)+"_"+str(gmt.tm_mon)+"_"+str(gmt.tm_wday)+"_"+str(gmt.tm_hour)+"_"+str(gmt.tm_min)+"_"+str(gmt.tm_sec)
306
+ vertices = Graph.Vertices(graph)
307
+ edges = Graph.Edges(graph)
308
+ tx = neo4jGraph.begin()
309
+ nodes = []
310
+ for i in range(len(vertices)):
311
+ vDict = Topology.Dictionary(vertices[i])
312
+ keys = Dictionary.Keyus(vDict)
313
+ values = Dictionary.Values(vDict)
314
+ keys.append("x")
315
+ keys.append("y")
316
+ keys.append("z")
317
+ keys.append("timestamp")
318
+ keys.append("location")
319
+ values.append(vertices[i].X())
320
+ values.append(vertices[i].Y())
321
+ values.append(vertices[i].Z())
322
+ values.append(timestamp)
323
+ values.append(sp.CartesianPoint([vertices[i].X(),vertices[i].Y(),vertices[i].Z()]))
324
+ zip_iterator = zip(keys, values)
325
+ pydict = dict(zip_iterator)
326
+ if labelKey == 'None':
327
+ nodeName = "TopologicGraphVertex"
328
+ else:
329
+ nodeName = str(values[keys.index(labelKey)])
330
+ n = py2neo.Node(nodeName, **pydict)
331
+ neo4jGraph.cypher.execute("CREATE INDEX FOR (n:%s) on (n.name)" %
332
+ n.nodelabel)
333
+ tx.create(n)
334
+ nodes.append(n)
335
+ for i in range(len(edges)):
336
+ e = edges[i]
337
+ sv = e.StartVertex()
338
+ ev = e.EndVertex()
339
+ sn = nodes[Vertex.Index(sv, vertices, tolerance)]
340
+ en = nodes[Vertex.Index(ev, vertices, tolerance)]
341
+ relationshipType = Dictionary.ValueAtKey(e, relationshipKey)
342
+ if not (relationshipType):
343
+ relationshipType = "Connected To"
344
+ snen = py2neo.Relationship(sn, relationshipType, en)
345
+ tx.create(snen)
346
+ snen = py2neo.Relationship(en, relationshipType, sn)
347
+ tx.create(snen)
348
+ neo4jGraph.commit(tx)
349
+ return neo4jGraph
350
+
351
+
352
+ @staticmethod
353
+ def ByParameters(url, username, password):
354
+ """
355
+ Returns a Neo4j graph by the input parameters.
356
+
357
+ Parameters
358
+ ----------
359
+ url : str
360
+ The URL of the server.
361
+ username : str
362
+ The username to use for logging in.
363
+ password : str
364
+ The password to use for logging in.
365
+
366
+ Returns
367
+ -------
368
+ Neo4j.Graph
369
+ The returned Neo4j graph.
370
+
371
+ """
372
+ return py2neo.Graph(url, auth=(username, password))
373
+
374
+ @staticmethod
375
+ def DeleteAll(neo4jGraph):
376
+ """
377
+ Deletes all entities in the input Neo4j graph.
378
+
379
+ Parameters
380
+ ----------
381
+ neo4jGraph : Neo4j Graph
382
+ The input Neo4jGraph.
383
+
384
+ Returns
385
+ -------
386
+ Neo4J Graph
387
+ The returned empty graph.
388
+
389
+ """
390
+ neo4jGraph.delete_all()
391
+ return neo4jGraph
392
+
393
+ @staticmethod
394
+ def NodeLabels(neo4jGraph):
395
+ """
396
+ Returns all the node labels used in the input neo4j graph.
397
+
398
+ Parameters
399
+ ----------
400
+ neo4jGraph : Newo4j.Graph
401
+ The input neo4j graph.
402
+
403
+ Returns
404
+ -------
405
+ list
406
+ The list of node labels used in the input neo4j graph.
407
+
408
+ """
409
+ return list(neo4jGraph.schema.node_labels)
410
+
411
+ @staticmethod
412
+ def RelationshipTypes(neo4jGraph):
413
+ """
414
+ Returns all the relationship types used in the input neo4j graph.
415
+
416
+ Parameters
417
+ ----------
418
+ neo4jGraph : Newo4j.Graph
419
+ The input neo4j graph.
420
+
421
+ Returns
422
+ -------
423
+ list
424
+ The list of relationship types used in the input neo4j graph.
425
+
426
+ """
427
+ return list(neo4jGraph.schema.relationship_types)
428
+
429
+ @staticmethod
430
+ def SetGraph(neo4jGraph, graph, labelKey=None, relationshipKey=None, bidirectional=True, deleteAll=True, tolerance=0.0001):
431
+ """
432
+ Sets the input topologic graph to the input neo4jGraph.
433
+
434
+ Parameters
435
+ ----------
436
+ neo4jGraph : Neo4j.Graph
437
+ The input neo4j graph.
438
+ graph : topologic.Graph
439
+ The input topologic graph.
440
+ labelKey : str , optional
441
+ The dictionary key under which to find the vertex's label value. The default is None which means the vertex gets the name 'TopologicGraphVertex'.
442
+ relationshipKey : str , optional
443
+ The dictionary key under which to find the edge's relationship value. The default is None which means the edge gets the relationship type 'Connected To'.
444
+ bidirectional : bool , optional
445
+ If set to True, the edges in the neo4j graph are set to be bi-drectional.
446
+ deleteAll : bool , optional
447
+ If set to True, all previous entities are deleted before adding the new entities.
448
+ tolerance : float , optional
449
+ The desired tolerance. The default is 0.0001.
450
+
451
+ Returns
452
+ -------
453
+ neo4jGraph : TYPE
454
+ The input neo4j graph with the input topologic graph added to it.
455
+
456
+ """
457
+ from topologicpy.Vertex import Vertex
458
+ from topologicpy.Graph import Graph
459
+ from topologicpy.Topology import Topology
460
+ from topologicpy.Dictionary import Dictionary
461
+
462
+ import time
463
+ gmt = time.gmtime()
464
+ timestamp = str(gmt.tm_zone)+"_"+str(gmt.tm_year)+"_"+str(gmt.tm_mon)+"_"+str(gmt.tm_wday)+"_"+str(gmt.tm_hour)+"_"+str(gmt.tm_min)+"_"+str(gmt.tm_sec)
465
+
466
+ vertices = Graph.Vertices(graph)
467
+ edges = Graph.Edges(graph)
468
+ tx = neo4jGraph.begin()
469
+ nodes = []
470
+ for i in range(len(vertices)):
471
+ vDict = Topology.Dictionary(vertices[i])
472
+ if not vDict:
473
+ keys = []
474
+ values = []
475
+ else:
476
+ keys = Dictionary.Keys(vDict)
477
+ if not keys:
478
+ keys = []
479
+ values = Dictionary.Values(vDict)
480
+ if not values:
481
+ values = []
482
+ keys.append("x")
483
+ keys.append("y")
484
+ keys.append("z")
485
+ keys.append("timestamp")
486
+ keys.append("location")
487
+ values.append(vertices[i].X())
488
+ values.append(vertices[i].Y())
489
+ values.append(vertices[i].Z())
490
+ values.append(timestamp)
491
+ values.append(sp.CartesianPoint([vertices[i].X(),vertices[i].Y(),vertices[i].Z()]))
492
+ zip_iterator = zip(keys, values)
493
+ pydict = dict(zip_iterator)
494
+ if (labelKey == 'None') or (not (labelKey)):
495
+ nodeName = "TopologicGraphVertex"
496
+ else:
497
+ nodeName = str(Dictionary.ValueAtKey(vDict, labelKey))
498
+ n = py2neo.Node(nodeName, **pydict)
499
+ tx.create(n)
500
+ nodes.append(n)
501
+ for i in range(len(edges)):
502
+ e = edges[i]
503
+ sv = e.StartVertex()
504
+ ev = e.EndVertex()
505
+ sn = nodes[Vertex.Index(vertex=sv, vertices=vertices, strict=False, tolerance=tolerance)]
506
+ en = nodes[Vertex.Index(vertex=ev, vertices=vertices, strict=False, tolerance=tolerance)]
507
+ ed = Topology.Dictionary(e)
508
+ if relationshipKey:
509
+ relationshipType = Dictionary.ValueAtKey(ed, relationshipKey)
510
+ else:
511
+ relationshipType = "Connected To"
512
+ if not (relationshipType):
513
+ relationshipType = "Connected To"
514
+ snen = py2neo.Relationship(sn, relationshipType, en)
515
+ tx.create(snen)
516
+ if bidirectional:
517
+ snen = py2neo.Relationship(en, relationshipType, sn)
518
+ tx.create(snen)
519
+ if deleteAll:
520
+ neo4jGraph.delete_all()
521
+ neo4jGraph.commit(tx)
522
522
  return neo4jGraph