I am trying to read a GML (graph modelling language) file from networkX, but it returns a ParseError.
I just wrote a couple of lines of code:
import networkx as nx
G = nx.read_gml('test.gml')
print G.node
This is the GML file:
graph [
directed 1
node [
id 0
label 1
shape
name "square"
center (132, 258)
]
node [
id 1
label 2
shape
name "triangle"
center (132, 128)
]
edge [
source 0
target 1
relation "below"
]
edge [
source 1
target 0
relation "above"
]
]
And this is the error I got:
ParseException: Expected "]" (at char 23), (line:3, col:3)
However, I don't see any ]
missing
The parser is getting confused with your input. I have never used gml before but I built your gml file up one piece at a time and found two problems.
shape
key with no value(132, 258)
Assuming that this reference is correct, there are 4 possible value types:
A value may have one out of four possible types, an integer (type gml$ _$int), a double (type gml$ _$double), a string (type gml$ _$string), or a list of GML objects (type gml$ _$list).
Therefore (132, 258)
is not valid and I believe having no value also would not be valid.
Try the below commented-out gml and it will load.
graph [
directed 1
node [
id 0
label 1
#shape
name "square"
#center (132, 258)
]
node [
id 1
label 2
#shape
name "triangle"
#center (132, 128)
]
edge [
source 0
target 1
relation "below"
]
edge [
source 1
target 0
relation "above"
]
]
I found somewhere that nx.write_gml
does not support mixed graphs including nested graphs. So even if you are creating the graph correctly, it's not going to write it correctly to a file.
Here is an alternative flat structure that will write although I don't know if this is a good way to structure the data. It makes labels that can be constructed to identify the corners of each shape.
import networkx as nx
dg = nx.DiGraph()
# square data
square_label = '0'
square_corners = [(0, 0), (0, 1), (1, 1), (1, 0)]
# main square node
dg.add_node(square_label, name='square')
# shape data for square
base_id = '{0}.corners.'.format(square_label)
last_corner_id = '{0}{1}'.format(base_id, len(square_corners)-1)
for i, corner in enumerate(square_corners):
x, y = corner
corner_id = '{0}{1}'.format(base_id, i)
dg.add_node(corner_id, x=x, y=y)
# instead of linking the square to every corner, you might want to link
# only to one corner and handle the cycle with edges between the corners
# or whatever. there are many ways it could be done I guess.
dg.add_edge(square_label, corner_id) # link from square to each corner
dg.add_edge(last_corner_id, corner_id) # corner to corner edges
last_corner_id = corner_id
nx.write_gml(dg, 'test.gml')
output:
graph [
directed 1
node [
id 1
label "0"
name "square"
]
node [
id 0
label "0.corners.1"
y 1
x 0
]
node [
id 2
label "0.corners.3"
y 0
x 1
]
node [
id 3
label "0.corners.2"
y 1
x 1
]
node [
id 4
label "0.corners.0"
y 0
x 0
]
edge [
source 0
target 3
]
edge [
source 1
target 0
]
edge [
source 1
target 4
]
edge [
source 1
target 2
]
edge [
source 1
target 3
]
edge [
source 2
target 4
]
edge [
source 3
target 2
]
edge [
source 4
target 0
]
]