5

I made a 3D line plot Python add-in with matplotlib for ArcMap.

After I execute this tool 3-4 times, ArcMap crashed. I have also executed it in the Python window, but the situation is just the same.

Here is the code:

import arcpy
import pythonaddins
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
from mpl_toolkits.mplot3d.art3d import Poly3DCollection
class ButtonClass1(object):
 def __init__(self):
 self.enabled = True
 self.checked = False
 def onClick(self):
 fig = plt.figure()
 ax = fig.add_subplot(111, projection = '3d')
 # plot line
 def plotWireframe(x,y,z,c):
 ax.plot_wireframe(x,y,z,color=c)
 mxd = arcpy.mapping.MapDocument("CURRENT")
 arcpy.mapping.ListLayers(mxd)
 layers = arcpy.mapping.ListLayers(mxd)
 select_layers = [str(i.name) for i in layers if arcpy.Describe(i.name).fidSet]
 numOfLayer = 0
 for fc in select_layers:
 if numOfLayer%3 == 0:
 color = (0.1, 0.2, 0.5)
 elif numOfLayer%2 == 0:
 color = (0.5, 0.8, 0.5)
 else:
 color = (0.6, 0.2, 0.1)
 numOfLayer = numOfLayer + 1
 desc = arcpy.Describe(fc)
 geometryType = desc.shapeType
 if geometryType == 'Polyline':
 for row in arcpy.da.SearchCursor(fc, ["SHAPE@"]):
 for part in row[0]:
 x = []
 y = []
 z = []
 for pnt in part:
 x.append(pnt.X)
 y.append(pnt.Y)
 if pnt.Z == None:
 z.append(0)
 else:
 z.append(pnt.Z)
 plotWireframe(x,y,z,color) 
 else:
 print fc, "is not Polyline"
 plt.show()

I guess the problem might caused by:

  1. Memory problem: but it happened even I only select one feature (polyline) to plot.
  2. The python GUI may not play well with ArcMap

The version information is as follows:

  • ArcMap 10.2, 10.5 and 10.5.1 (both got the same crash)
  • matplotlib version 1.5.2 (a build-in module in ArcGIS)

Has anyone using matplotlib in ArcMap encountered a similar problem?

asked Apr 13, 2018 at 7:22
5
  • I noticed that: After executing the tool and closing the window, I hover mouse over the button (no click), aaand ArcMap craches.I also encountered an error like name 'numOfLayer' is not defined. Commented Apr 17, 2018 at 15:15
  • 1
    Maybe related or not, I don't see where you are deleting your SearchCursor (row) after its used... gis.stackexchange.com/questions/254013/… Commented Apr 17, 2018 at 20:55
  • @ericoneal It's probably not. when deleting plt.show(), no crashing. Commented Apr 17, 2018 at 22:59
  • 1
    @ericoneal I think they should use with arcpy.da.SearchCursor() as cursor: syntax instead (sample code in its help). Commented Apr 17, 2018 at 23:41
  • @KadirŞahbaz , I fixed the part about 'numOfLayer' in the above code. Commented Apr 18, 2018 at 10:22

1 Answer 1

6
+50

I think, It's most probably about Python GUI (especially Tkinter). Matplotlib uses Tkinter by default. I couldn't figure it out why, but If I change GUI package for matplotlib to PyQt4, no more crashing with one exception.

First, I tried wxPython, but I encountered errors. Then I installed PyQt4 (cp27m‐win32) and after some editings on script like below, crashing stopped. (Three lines with #)

import arcpy
import pythonaddins
import matplotlib ##########
matplotlib.use("Qt4Agg") ##########
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
from mpl_toolkits.mplot3d.art3d import Poly3DCollection
class ButtonClass1(object):
 def __init__(self):
 self.enabled = True
 self.checked = False
 def onClick(self):
 fig = plt.figure()
 ax = fig.add_subplot(111, projection = '3d')
 # plot line
 def plotWireframe(x,y,z,c):
 ax.plot_wireframe(x,y,z,color=c)
 mxd = arcpy.mapping.MapDocument("CURRENT")
 arcpy.mapping.ListLayers(mxd)
 layers = arcpy.mapping.ListLayers(mxd)
 select_layers = [str(i.name) for i in layers if arcpy.Describe(i.name).fidSet]
 numOfLayer = len(select_layers) ##########
 for fc in select_layers:
 if numOfLayer%3 == 0:
 color = (0.1, 0.2, 0.5)
 elif numOfLayer%2 == 0:
 color = (0.5, 0.8, 0.5)
 else:
 color = (0.6, 0.2, 0.1)
 desc = arcpy.Describe(fc)
 geometryType = desc.shapeType
 if geometryType == 'Polyline':
 for row in arcpy.da.SearchCursor(fc, ["SHAPE@"]):
 for part in row[0]:
 x = []
 y = []
 z = []
 for pnt in part:
 x.append(pnt.X)
 y.append(pnt.Y)
 if pnt.Z == None:
 z.append(0)
 else:
 z.append(pnt.Z)
 plotWireframe(x,y,z,color) 
 else:
 print fc, "is not Polyline"
 plt.show()

However, there is one exception. If you hover mouse over the button while Figure window is open, ArcGIS crashes. Otherwise, everything is fine. (I used ArcGIS 10.5)

For more information about other GUIs for matplotlib, refer to table at the bottom of What is a backend? headline

enter image description here

answered Apr 18, 2018 at 0:48
1
  • I have tried this solution and it works great, I never thought we can change the default GUI, thank you @KadirŞahbaz. Commented Apr 18, 2018 at 10:27

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.