Question

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

Was it helpful?

Solution

Immediate Problem

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.

  1. the shape key with no value
  2. the keys that have tuple-like values (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"
  ]
]

Alternative Solution

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
  ]
]
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top