Python Forum
Finding nearest point of a Multidigraph in Python 3.7 - Printable Version

+- Python Forum (https://python-forum.io)
+-- Forum: Python Coding (https://python-forum.io/forum-7.html)
+--- Forum: General Coding Help (https://python-forum.io/forum-8.html)
+--- Thread: Finding nearest point of a Multidigraph in Python 3.7 (/thread-20073.html)



Finding nearest point of a Multidigraph in Python 3.7 - stixmagiggins - Jul-26-2019

I have two point layers, one with bus stops and train stations, and another with playground centrepoints.
From QGIS I created a cleaned up network containing roads and footpaths, which I have converted to a multidigraph in Python. This so I can loop through each bus/train station and find the network to the playground point, if there is one.

The problem is trying to get the closest edge node to the playground spits out an error.

path = "C:\\........\\Footpath_Roads_Extended_Python.shp"
def read_multi_shp(path): #create multidigraph
    """
    copied from read_shp, but allowing MultiDiGraph instead.
    """
    try:
        from osgeo import ogr
    except ImportError:
        raise ImportError("read_shp requires OGR: http://www.gdal.org/")

    net = nx.MultiDiGraph()

    def getfieldinfo(lyr, feature, flds):
            f = feature
            return [f.GetField(f.GetFieldIndex(x)) for x in flds]

    def addlyr(lyr, fields):
        for findex in range(lyr.GetFeatureCount()):
            f = lyr.GetFeature(findex)
            flddata = getfieldinfo(lyr, f, fields)
            g = f.geometry()
            attributes = dict(zip(fields, flddata))
            attributes["ShpName"] = lyr.GetName()
            if g.GetGeometryType() == 1:  # point
                net.add_node((g.GetPoint_2D(0)), attributes)
            if g.GetGeometryType() == 2:  # linestring
                attributes["Wkb"] = g.ExportToWkb()
                attributes["Wkt"] = g.ExportToWkt()
                attributes["Json"] = g.ExportToJson()
                last = g.GetPointCount() - 1
                net.add_edge(g.GetPoint_2D(0), g.GetPoint_2D(last), attr_dict=attributes)

    if isinstance(path, str):
        shp = ogr.Open(path)
        lyrcount = shp.GetLayerCount()
        for lyrindex in range(lyrcount):
            lyr = shp.GetLayerByIndex(lyrindex)
            flds = [x.GetName() for x in lyr.schema]
            addlyr(lyr, flds)
	
    return net

H=read_multi_shp(path)

PTV_Playground_Shortest_Path_300_400 = []
while i < len(PTV_Playground_Joined_initial): #loop through playgrounds and find nearest path node

	orig_xy = (df.loc[i,"PTV_N"], "-"+df.loc[i,"PTV_E"])

	target_xy = (df.loc[i,"Playgroun1"], df.loc[i,"Playground"])
	
	orig_node = ox.get_nearest_node(H, orig_xy, method='euclidean') #H seems to cause the error.................
The error I receive is

Traceback (most recent call last):
  File "C:\Users\geogjo\Desktop\PythonTraining\Network_Analysis_Test.py", line 100, in <module>
    orig_node = ox.get_nearest_node(H, orig_xy, method='euclidean')
  File "C:\Users\geogjo\AppData\Local\Continuum\anaconda3\lib\site-packages\osmnx\utils.py", line 461, in get_nearest_node
    coords = [[node, data['x'], data['y']] for node, data in G.nodes(data=True)]
  File "C:\Users\geogjo\AppData\Local\Continuum\anaconda3\lib\site-packages\osmnx\utils.py", line 461, in <listcomp>
    coords = [[node, data['x'], data['y']] for node, data in G.nodes(data=True)]
KeyError: 'x'
I snapped all linework to itself to keep it as simple as possible. When I test the type it says it's a multidigraph.
Yes you can use QGIS shortest path tools but only if you have one end point or one start point. This has many start and end points so I will be looping through each.


RE: Finding nearest point of a Multidigraph in Python 3.7 - ThomasL - Jul-26-2019

The error tells you that there is no key 'x' in data which you get from G.nodes()
So i would look what i get back from G.nodes()


RE: Finding nearest point of a Multidigraph in Python 3.7 - stixmagiggins - Aug-16-2019

When I print the multi-digraph that is being passed into this function it looks like the following...

[(327688.2817133684, 5739552.011543424), (341508.08128750307, 5767378.745506252), (341481.1308291708, 5767277.219589586), (341364.9730373633, 5767271.420884848), (341364.8637279594, 5767271.415428021), (341374.82312183146, 5767212.4025153965) etc.....

Does this look correct. The error is coming from utils.


RE: Finding nearest point of a Multidigraph in Python 3.7 - ThomasL - Aug-16-2019

I can´t tell you, i don´t know.
You are calling ox.get_nearest_node(H, orig_xy, method='euclidean') and then you get the error.

So either parameter H, which comes from H = read_multi_shp(path)
or orig_xy which comes from orig_xy = (df.loc[i, "PTV_N"], "-" + df.loc[i, "PTV_E"]) is faulty.
I would guess it´s the building of orig_xy, are you sure about the part above marked red?


RE: Finding nearest point of a Multidigraph in Python 3.7 - stixmagiggins - Aug-24-2019

It is coming from H. It looks like I need to add keys for X and Y with the corresponding values. At the moment it is just coordinates i.e. (1,2) without a key value, whereas I think it should be (X:1, Y:2). How can I do that in a multidigraph created from a shp?


RE: Finding nearest point of a Multidigraph in Python 3.7 - ThomasL - Aug-24-2019

H = [(1,2), (2,3), (1,3), (3,2), (3,4)]

new_H = {'x': [], 'y': []}
for x, y in H:
    new_H['x'].append(x)
    new_H['y'].append(y)

print(new_H)

# {'x': [1, 2, 1, 3, 3], 'y': [2, 3, 3, 2, 4]}