4

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?

  • 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. – Kadir Şahbaz Apr 17 '18 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/… – ericoneal Apr 17 '18 at 20:55
  • @ericoneal It's probably not. when deleting plt.show(), no crashing. – Kadir Şahbaz Apr 17 '18 at 22:59
  • 1
    @ericoneal I think they should use with arcpy.da.SearchCursor() as cursor: syntax instead (sample code in its help). – PolyGeo Apr 17 '18 at 23:41
  • @KadirŞahbaz , I fixed the part about 'numOfLayer' in the above code. – Kayson Cho Apr 18 '18 at 10:22
5
+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

  • I have tried this solution and it works great, I never thought we can change the default GUI, thank you @KadirŞahbaz. – Kayson Cho Apr 18 '18 at 10:27

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.