DrBwts - 2 months ago 17
Python Question

# Matplotlib 3D scatter autoscale issue

Python 2.7, matplotlib 1.5.1, Win 7, x64

I am trying to plot the shortest distances between a node & its geometrical nearest neighbour (ie not its nearest connected neighbour) in a graph using Dijkstra's algorithm.

The algorithm is working fine but when it comes to plotting, matplotlib's scaling freaks out when I plot certain nodes.

Code snippet:

``````import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D

# Find the paths between a given node & its nearest neighbours

def plotPath(pathStart, pathEnd, pointCol='b'):

shortPath = graph.dijkstra(pathStart, pathEnd) # this calculates the shortest path

pathNodesIdx = [i-1 for i in shortPath] # Algorithm returns 1 indexed whilst Python uses 0 indexed
pathCoords = L3.nodes[pathNodesIdx, 1:4] # retrieves the coordinate for the nodes on the path

ax.scatter(pathCoords[1:-1,0], pathCoords[1:-1,1], pathCoords[1:-1,2], s=240, c=pointCol, marker='o')
startNode = pathCoords[0]
endNode = pathCoords[-1]
ax.scatter(startNode[0], startNode[1], startNode[2], s=240, c='g', marker='o')
ax.scatter(endNode[0], endNode[1], endNode[2], s=240, c='r', marker='o')
for node in pathCoords[1:]:
ax.plot([startNode[0], node[0]], [startNode[1], node[1]], [startNode[2], node[2]], color=pointCol, linewidth=2.0)
startNode = node

return pathCoords

pointCol = 'b'
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')

pathStart = 1 # given node
graph=Graph(L3.trabGraph) # L3.trabGraph is list conataining the edge/node/cost information for the graph

# Return indices for nearest neighbours
nearest = [i+1 for i in L3.nodeNeighbours(pathStart, numNeighs=6, method='brute')[1:]]
``````

For example I just plot the path to the 2nd nearest neighbour using
`plotPath(1, nearest[2])`
I get:

But if I add the other nearest neighbours using,

``````p0 = plotPath(1, nearest[0])
p1 = plotPath(1, nearest[1])
p2 = plotPath(1, nearest[2])
p3 = plotPath(1, nearest[3])
p4 = plotPath(1, nearest[4])
``````

I get:

For reference the coordinates of the nodes for each case:

``````p0 = array([[ 1.094,  1.76 ,  1.125],
[ 1.188,  1.75 ,  1.104]])

p1 = array([[ 1.094,  1.76 ,  1.125],
[ 1.104,  1.875,  1.094]])

p2 = array([[ 1.094,  1.76 ,  1.125],
[ 1.188,  1.75 ,  1.104],
[ 1.188,  1.688,  1.094]])

p3 = array([[ 1.094,  1.76 ,  1.125],
[ 1.198,  1.76 ,  1.198]])

p4 = array([[ 1.094,  1.76 ,  1.125],
[ 1.198,  1.76 ,  1.198],
[ 1.188,  1.708,  1.198]])
``````

For the life of me I dont see why matplotlib does this? Anybody know?

I have left out the implementations of the Dijkstra algorithm (from Rosetta code FYI) & the creation of the graph for the sake of brevity & the fact that I'm not at liberty to share the graph information.

If the question here really is "How do I set the limits of a 3d plot in matplotlib?" then the answer would be:

Just as you do in the 2d case:

``````ax.set_xlim([xmin, xmax])
ax.set_ylim([ymin, ymax])
ax.set_zlim([zmin, zmax])
``````

Finding the values of min and max for respective cases might of course be automated.

Source (Stackoverflow)