topologicpy 0.7.54__py3-none-any.whl → 0.7.56__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/Neo4j.py CHANGED
@@ -20,340 +20,134 @@ import os
20
20
  import warnings
21
21
 
22
22
  try:
23
- import py2neo
24
- from py2neo import NodeMatcher,RelationshipMatcher
25
- from py2neo.data import spatial as sp
23
+ import neo4j
24
+ from neo4j import GraphDatabase
26
25
  except:
27
- print("Neo4j - Installing required py2neo library.")
26
+ print("Neo4j - Installing required neo4j library.")
28
27
  try:
29
- os.system("pip install py2neo")
28
+ os.system("pip install neo4j")
30
29
  except:
31
- os.system("pip install py2neo --user")
30
+ os.system("pip install neo4j --user")
32
31
  try:
33
- import py2neo
34
- from py2neo import NodeMatcher,RelationshipMatcher
35
- from py2neo.data import spatial as sp
32
+ import neo4j
33
+ from neo4j import GraphDatabase
36
34
  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_core.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
35
+ warnings.warn("Neo4j - Error: Could not import neo4j")
86
36
 
37
+ class Neo4j:
87
38
  @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):
39
+ def ExportToGraph(neo4jGraph, cypher=None, xMin=-0.5, yMin=-0.5, zMin=-0.5, xMax=0.5, yMax=0.5, zMax=0.5, tolerance=0.0001, silent=False):
102
40
  """
103
41
  Exports the input neo4j graph to a topologic graph.
104
42
 
105
43
  Parameters
106
44
  ----------
107
- subGraph : Neo4j.SubGraph
108
- The input neo4j subgraph.
109
- tolerance : float , optional
45
+ neo4jGraph : neo4j._sync.driver.BoltDriver
46
+ The input neo4j bolt driver.
47
+ cypher : str, optional
48
+ If set to a non-empty string, a Cypher query will be run on the neo4j graph database to return a sub-graph. Default is None.
49
+ xMin : float, optional
50
+ The desired minimum value to assign for a vertex's X coordinate. The default is -0.5.
51
+ yMin : float, optional
52
+ The desired minimum value to assign for a vertex's Y coordinate. The default is -0.5.
53
+ zMin : float, optional
54
+ The desired minimum value to assign for a vertex's Z coordinate. The default is -0.5.
55
+ xMax : float, optional
56
+ The desired maximum value to assign for a vertex's X coordinate. The default is 0.5.
57
+ yMax : float, optional
58
+ The desired maximum value to assign for a vertex's Y coordinate. The default is 0.5.
59
+ zMax : float, optional
60
+ The desired maximum value to assign for a vertex's Z coordinate. The default is 0.5.
61
+ silent : bool, optional
62
+ If set to True, no warnings or error messages are displayed. The default is False.
63
+ tolerance : float, optional
110
64
  The desired tolerance. The default is 0.0001.
111
65
 
112
66
  Returns
113
67
  -------
114
68
  topologic_core.Graph
115
- The output topologic graph.
116
-
69
+ The output Topologic graph.
117
70
  """
71
+ import random
118
72
  from topologicpy.Vertex import Vertex
119
73
  from topologicpy.Edge import Edge
120
74
  from topologicpy.Topology import Topology
121
- from topologicpy.Dictionary import Dictionary
122
75
  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_core.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
76
  from topologicpy.Dictionary import Dictionary
210
- from topologicpy.Graph import Graph
211
77
 
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
78
  vertices = []
237
79
  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)
80
+ all_vertices = []
81
+
82
+ with neo4jGraph.session() as session:
83
+ nodes_result = session.run("MATCH (n) RETURN n")
84
+ # Process nodes
85
+ nodes = [record.get('n') for record in nodes_result]
86
+ for node in nodes:
87
+ if node:
88
+ properties = dict(node.items())
89
+ x = properties.get('x', random.uniform(xMin, xMax))
90
+ y = properties.get('y', random.uniform(yMin, yMax))
91
+ z = properties.get('z', random.uniform(zMin, zMax))
92
+ vertex = Vertex.ByCoordinates(x, y, z) # Create Topologic vertex
93
+ d = Dictionary.ByPythonDictionary(properties)
94
+ vertex = Topology.SetDictionary(vertex, d)
95
+ all_vertices.append(vertex)
96
+
97
+ if cypher:
98
+ # Run the provided Cypher query
99
+ nodes_result = session.run(cypher)
248
100
  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']
101
+ # Fetch all nodes and relationships
102
+ nodes_result = session.run("MATCH (n) RETURN n")
103
+ relationships_result = session.run("MATCH (a)-[r]->(b) RETURN a, r, b")
104
+
105
+ # Process nodes
106
+ nodes = [record.get('n') for record in nodes_result]
107
+ for node in nodes:
108
+ if node:
109
+ properties = dict(node.items())
110
+ x = properties.get('x', random.uniform(xMin, xMax))
111
+ y = properties.get('y', random.uniform(yMin, yMax))
112
+ z = properties.get('z', random.uniform(zMin, zMax))
113
+ vertex = Vertex.ByCoordinates(x, y, z) # Create Topologic vertex
114
+ d = Dictionary.ByPythonDictionary(properties)
115
+ vertex = Topology.SetDictionary(vertex, d)
116
+ vertices.append(vertex)
117
+
118
+ # If a Cypher query was provided, process edges
119
+ if cypher:
120
+ relationships_result = session.run(cypher)
121
+
122
+ # Process relationships
123
+ for record in relationships_result:
124
+ start_node = record.get('a')
125
+ end_node = record.get('b')
126
+ relationship = record.get('r')
127
+
128
+ if start_node and end_node:
129
+ # Find corresponding vertices
130
+ #start_vertex = next((v for v in vertices if v.id == start_node.id), None)
131
+ #end_vertex = next((v for v in vertices if v.id == end_node.id), None)
132
+ start_filter = Topology.Filter(all_vertices, searchType="equal to", key="id", value=start_node['id'])['filtered']
133
+ if len(start_filter) > 0:
134
+ start_vertex = start_filter[0]
266
135
  else:
267
- sv_name = 'None'
268
- if relationship.end_node['name']:
269
- ev_name = relationship.end_node['name']
136
+ start_vertex = NotImplemented
137
+ end_filter = Topology.Filter(all_vertices, searchType="equal to", key="id", value=end_node['id'])['filtered']
138
+ if len(end_filter) > 0:
139
+ end_vertex = end_filter[0]
270
140
  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, mantissa: int = 6, tolerance: float = 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_core.Graph
288
- The input topologic graph.
289
- labelKey : str , optional
290
- The label key in the dictionary under which to look for the label value.
291
- relationshipKey: str , optional
292
- The relationship key in the dictionary under which to look for the relationship value.
293
- mantissa : int, optional
294
- The desired length of the mantissa. The default is 6.
295
- tolerance : float , optional
296
- The desired tolerance. The default is 0.0001.
141
+ end_vertex = None
297
142
 
298
- Returns
299
- -------
300
- Neo4j.Graph
301
- The input neo4j graph with the input topologic graph added to it.
143
+ if not start_vertex == None and not end_vertex == None:
144
+ edge = Edge.ByVertices(start_vertex, end_vertex)
145
+ relationship_props = dict(relationship.items())
146
+ d = Dictionary.ByPythonDictionary(relationship_props)
147
+ edge = Topology.SetDictionary(edge, d)
148
+ edges.append(edge)
149
+ return Graph.ByVerticesEdges(vertices, edges)
302
150
 
303
- """
304
- from topologicpy.Vertex import Vertex
305
- from topologicpy.Topology import Topology
306
- from topologicpy.Graph import Graph
307
- from topologicpy.Dictionary import Dictionary
308
-
309
- gmt = time.gmtime()
310
- 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)
311
- vertices = Graph.Vertices(graph)
312
- edges = Graph.Edges(graph)
313
- tx = neo4jGraph.begin()
314
- nodes = []
315
- for i in range(len(vertices)):
316
- vDict = Topology.Dictionary(vertices[i])
317
- keys = Dictionary.Keyus(vDict)
318
- values = Dictionary.Values(vDict)
319
- keys.append("x")
320
- keys.append("y")
321
- keys.append("z")
322
- keys.append("timestamp")
323
- keys.append("location")
324
- values.append(Vertex.X(vertices[i], mantissa=mantissa))
325
- values.append(Vertex.Y(vertices[i], mantissa=mantissa))
326
- values.append(Vertex.Z(vertices[i], mantissa=mantissa))
327
- values.append(timestamp)
328
- values.append(sp.CartesianPoint([Vertex.X(vertices[i], mantissa=mantissa), Vertex.Y(vertices[i], mantissa=mantissa), Vertex.Z(vertices[i], mantissa=mantissa)]))
329
- zip_iterator = zip(keys, values)
330
- pydict = dict(zip_iterator)
331
- if labelKey == 'None':
332
- nodeName = "TopologicGraphVertex"
333
- else:
334
- nodeName = str(values[keys.index(labelKey)])
335
- n = py2neo.Node(nodeName, **pydict)
336
- neo4jGraph.cypher.execute("CREATE INDEX FOR (n:%s) on (n.name)" %
337
- n.nodelabel)
338
- tx.create(n)
339
- nodes.append(n)
340
- for i in range(len(edges)):
341
- e = edges[i]
342
- sv = e.StartVertex()
343
- ev = e.EndVertex()
344
- sn = nodes[Vertex.Index(sv, vertices, tolerance=tolerance)]
345
- en = nodes[Vertex.Index(ev, vertices, tolerance=tolerance)]
346
- relationshipType = Dictionary.ValueAtKey(e, relationshipKey)
347
- if not (relationshipType):
348
- relationshipType = "Connected To"
349
- snen = py2neo.Relationship(sn, relationshipType, en)
350
- tx.create(snen)
351
- snen = py2neo.Relationship(en, relationshipType, sn)
352
- tx.create(snen)
353
- neo4jGraph.commit(tx)
354
- return neo4jGraph
355
-
356
-
357
151
  @staticmethod
358
152
  def ByParameters(url, username, password):
359
153
  """
@@ -370,67 +164,217 @@ class Neo4j:
370
164
 
371
165
  Returns
372
166
  -------
373
- Neo4j.Graph
374
- The returned Neo4j graph.
167
+ neo4j._sync.driver.BoltDriver
168
+ The returned neo4j bolt driver.
375
169
 
376
170
  """
377
- return py2neo.Graph(url, auth=(username, password))
171
+ return GraphDatabase.driver(url, auth=(username, password))
378
172
 
379
173
  @staticmethod
380
- def DeleteAll(neo4jGraph):
174
+ def Reset(neo4jGraph):
381
175
  """
382
- Deletes all entities in the input Neo4j graph.
176
+ Resets the database completely.
383
177
 
384
178
  Parameters
385
179
  ----------
386
- neo4jGraph : Neo4j Graph
387
- The input Neo4jGraph.
180
+ neo4jGraph : neo4j._sync.driver.BoltDriver
181
+ The input neo4j bolt driver.
388
182
 
389
183
  Returns
390
184
  -------
391
- Neo4J Graph
392
- The returned empty graph.
185
+ neo4j._sync.driver.BoltDriver
186
+ The returned neo4j bolt driver.
393
187
 
394
188
  """
395
- neo4jGraph.delete_all()
189
+ with neo4jGraph.session() as session:
190
+ # Delete all nodes and relationships
191
+ session.run("MATCH (n) DETACH DELETE n")
192
+
193
+ # Drop all indexes
194
+ indexes = session.run("SHOW INDEXES").data()
195
+ for index in indexes:
196
+ index_name = index['name']
197
+ session.run(f"DROP INDEX {index_name}")
198
+
199
+ # Drop all constraints
200
+ constraints = session.run("SHOW CONSTRAINTS").data()
201
+ for constraint in constraints:
202
+ constraint_name = constraint['name']
203
+ session.run(f"DROP CONSTRAINT {constraint_name}")
204
+
396
205
  return neo4jGraph
397
-
398
- @staticmethod
399
- def NodeLabels(neo4jGraph):
206
+
207
+ def ByGraph(neo4jGraph,
208
+ graph,
209
+ vertexLabelKey: str = "label",
210
+ defaultVertexLabel: str = "NODE",
211
+ vertexCategoryKey: str = "category",
212
+ defaultVertexCategory: str = None,
213
+ edgeLabelKey: str = "label",
214
+ defaultEdgeLabel: str = "CONNECTED_TO",
215
+ edgeCategoryKey: str = "category",
216
+ defaultEdgeCategory: str = None,
217
+ bidirectional: bool = True,
218
+ mantissa: int = 6,
219
+ tolerance: float = 0.0001,
220
+ silent: bool = False):
400
221
  """
401
- Returns all the node labels used in the input neo4j graph.
402
-
222
+ Converts a Topologic graph to a Neo4j graph.
223
+
403
224
  Parameters
404
225
  ----------
405
- neo4jGraph : Newo4j.Graph
406
- The input neo4j graph.
407
-
226
+ neo4jGraph : neo4j._sync.driver.BoltDriver
227
+ The input neo4j bolt driver.
228
+ vertexLabelKey : str , optional
229
+ The returned vertices are labelled according to the dictionary values stored under this key.
230
+ If the vertexLabelKey does not exist, it will be created and the vertices are labelled numerically using the format defaultVertexLabel_XXX. The default is "label".
231
+ defaultVertexLabel : str , optional
232
+ The default vertex label to use if no value is found under the vertexLabelKey. The default is "NODE".
233
+ vertexCategoryKey : str , optional
234
+ The returned vertices are categorized according to the dictionary values stored under this key. The dfefault is "category".
235
+ defaultVertexCategory : str , optional
236
+ The default vertex category to use if no value is found under the vertexCategoryKey. The default is None.
237
+ edgeLabelKey : str , optional
238
+ The returned edges are labelled according to the dictionary values stored under this key.
239
+ If the edgeLabelKey does not exist, it will be created and the edges are labelled numerically using the format defaultEdgeLabel_XXX. The default is "label".
240
+ defaultEdgeLabel : str , optional
241
+ The default edge label to use if no value is found under the edgeLabelKey. The default is "CONNECTED_TO".
242
+ edgeCategoryKey : str , optional
243
+ The returned edges are categorized according to the dictionary values stored under this key. The dfefault is "category".
244
+ defaultEdgeCategory : str , optional
245
+ The default edge category to use if no value is found under the edgeCategoryKey. The default is None.
246
+ bidirectional : bool , optional
247
+ If set to True, the output Neo4j graph is forced to be bidirectional. The defaul is True.
248
+ mantissa : int , optional
249
+ The desired length of the mantissa. The default is 6.
250
+ tolerance : float , optional
251
+ The desired tolerance. The default is 0.0001.
252
+ silent : bool , optional
253
+ If set to True, no error and warning messages are printed. Otherwise, they are. The default is False.
254
+
408
255
  Returns
409
256
  -------
410
- list
411
- The list of node labels used in the input neo4j graph.
412
-
413
- """
414
- return list(neo4jGraph.schema.node_labels)
415
-
416
- @staticmethod
417
- def RelationshipTypes(neo4jGraph):
257
+ neo4j._sync.driver.BoltDriver
258
+ The returned neo4j bolt driver.
259
+
418
260
  """
419
- Returns all the relationship types used in the input neo4j graph.
261
+ from topologicpy.Vertex import Vertex
262
+ from topologicpy.Edge import Edge
263
+ from topologicpy.Graph import Graph
264
+ from topologicpy.Dictionary import Dictionary
265
+ from topologicpy.Topology import Topology
266
+
267
+ def sanitize_for_neo4j(identifier):
268
+ """
269
+ Replaces illegal characters in Neo4j labels or relationship types with an underscore ('_').
270
+ Ensures the identifier starts with an alphabetic character and contains only valid characters.
271
+ """
272
+ import re
273
+ # Replace any non-alphanumeric characters with underscores
274
+ sanitized = re.sub(r'[^a-zA-Z0-9]', '_', identifier)
275
+
276
+ # Ensure the identifier starts with an alphabetic character
277
+ if not sanitized[0].isalpha():
278
+ sanitized = f"_{sanitized}"
279
+
280
+ return sanitized
420
281
 
421
- Parameters
422
- ----------
423
- neo4jGraph : Newo4j.Graph
424
- The input neo4j graph.
282
+ if not isinstance(neo4jGraph, neo4j._sync.driver.BoltDriver):
283
+ if not silent:
284
+ print("Neo4j.ByGraph - Error: The input neo4jGraph is not a valid neo4j graph. Returning None.")
285
+ return None
286
+ if not Topology.IsInstance(graph, "Graph"):
287
+ if not silent:
288
+ print("Neo4j.ByGraph - Error: The input graph is not a valid topologic graph. Returning None.")
289
+ return None
290
+ # if not isinstance(vertexLabelKey, str):
291
+ # if not silent:
292
+ # print("Neo4j.ByGraph - Error: The input vertexLabelKey is not a valid string. Returning None.")
293
+ # return None
294
+ # if not isinstance(defaultVertexLabel, str):
295
+ # if not silent:
296
+ # print("Neo4j.ByGraph - Error: The input defaultVertexLabel is not a valid string. Returning None.")
297
+ # return None
298
+ # if not isinstance(vertexCategoryKey, str):
299
+ # if not silent:
300
+ # print("Neo4j.ByGraph - Error: The input vertexCategoryKey is not a valid string. Returning None.")
301
+ # return None
302
+ # if not isinstance(edgeLabelKey, str):
303
+ # if not silent:
304
+ # print("Neo4j.ByGraph - Error: The input vertexLabelKey is not a valid string. Returning None.")
305
+ # return None
306
+ # if not isinstance(defaultEdgeLabel, str):
307
+ # if not silent:
308
+ # print("Neo4j.ByGraph - Error: The input defaultEdgeLabel is not a valid string. Returning None.")
309
+ # return None
310
+ vertices = Graph.Vertices(graph)
311
+ edges = Graph.Edges(graph)
312
+
313
+ with neo4jGraph.session() as session:
314
+ # Create vertices (nodes in Neo4j)
315
+ n = max(len(str(len(vertices))), 3)
316
+ for i, vertex in enumerate(vertices):
317
+ vertex_props = Dictionary.PythonDictionary(Topology.Dictionary(vertex)) # Get the dictionary of vertex attributes
318
+
319
+ # Extract label and category, remove them from the properties
320
+ value = defaultVertexLabel+"_"+str(i+1).zfill(n)
321
+ vertex_label = vertex_props.pop(vertexLabelKey, value)
322
+ vertex_label = sanitize_for_neo4j(vertex_label)
323
+ vertex_category = vertex_props.pop(vertexCategoryKey, defaultVertexCategory) # Extract category if it exists
324
+ # Add coordinates to the vertex properties
325
+ vertex_props.update({
326
+ 'x': Vertex.X(vertex, mantissa=mantissa), # X coordinate
327
+ 'y': Vertex.Y(vertex, mantissa=mantissa), # Y coordinate
328
+ 'z': Vertex.Z(vertex, mantissa=mantissa), # Z coordinate
329
+ })
330
+
331
+ if not vertex_category == None:
332
+ vertex_props['category'] = vertex_category # Add category to properties if it exists
333
+ if not vertex_label == None:
334
+ vertex_props[vertexLabelKey] = vertex_label # Add label to properties if it exists
335
+
336
+ vertex_props['id'] = i
337
+
338
+ # Create a node with dynamic label and properties
339
+ session.run(f"""
340
+ CREATE (n:{vertex_label} $properties)
341
+ """, properties=vertex_props)
342
+
343
+ # Create edges (relationships in Neo4j)
344
+ for edge in edges:
345
+ edge_props = Dictionary.PythonDictionary(Topology.Dictionary(edge)) # Get the dictionary of edge attributes
346
+
347
+ # Extract label and category for the relationship
348
+ edge_label = edge_props.pop(edgeLabelKey, defaultEdgeLabel) # Default label is 'CONNECTED_TO'
349
+ edge_label = sanitize_for_neo4j(edge_label)
350
+ edge_category = edge_props.pop(edgeCategoryKey, defaultEdgeCategory) # Extract category if it exists
351
+
352
+ start_vertex = Edge.StartVertex(edge) # Get the starting vertex of the edge
353
+ start_id = Vertex.Index(vertex=start_vertex, vertices=vertices, strict=False, tolerance=tolerance)
354
+ end_vertex = Edge.EndVertex(edge) # Get the ending vertex of the edge
355
+ end_id = Vertex.Index(vertex=end_vertex, vertices=vertices, strict=False, tolerance=tolerance)
356
+
357
+ # Add category to edge properties if it exists
358
+ if not edge_category == None:
359
+ edge_props['category'] = edge_category
360
+ if not edge_label == None:
361
+ edge_props[edgeLabelKey] = edge_label # Add label to properties if it exists
362
+ # Create the relationship with dynamic label and properties
363
+ session.run(f"""
364
+ MATCH (a {{id: $start_id}}), (b {{id: $end_id}})
365
+ CREATE (a)-[r:{edge_label} $properties]->(b)
366
+ """, start_id=start_id, end_id=end_id, properties=edge_props)
367
+
368
+ # If the graph is bi-directional, add the reverse edge as well
369
+ if bidirectional:
370
+ session.run(f"""
371
+ MATCH (a {{id: $end_id}}), (b {{id: $start_id}})
372
+ CREATE (a)-[r:{edge_label} $properties]->(b)
373
+ """, start_id=start_id, end_id=end_id, properties=edge_props)
374
+
375
+ return neo4jGraph
425
376
 
426
- Returns
427
- -------
428
- list
429
- The list of relationship types used in the input neo4j graph.
430
377
 
431
- """
432
- return list(neo4jGraph.schema.relationship_types)
433
-
434
378
  @staticmethod
435
379
  def SetGraph(neo4jGraph,
436
380
  graph,