Hi Carl,
I am trying to do exactly this but am struggling slightly. Would you mind sharing the code with me at all please?
Many thanks in advance
Well, are you struggling slightly(almost there, just something in your code is not right) or are you lost (nothing works like it should) Perhaps i can help you if you have something that just isn't quite working, if you are just lost,or not sure how to go about this.
My script uses numpy, matplotlib, and scipy, so you would need to install those modules in python (not sure if numpy is installed with arcpy, but i think it is.)
What my script does:
1. So you have a point feature class with a field that matches the DDP sheet number that it falls in
2. It then selects those features, and creates a graph, for that page generalizing for missing data to get rid of the jagged edges, as a png in the output folder
3. Then it inserts the graph onto the page and exports, and moves on to the next.
So at the end, in the output folder there are the pdf's with the graph inserted on them and all of the png's in case you want them for something else.
I really only use this as a function now to create the graphs, I have other functions in my tools that inserts graphs, graphics, pictures, labels, etc on the map. I tried to comment it to make it easier to understand, but let me know if you have any questions.
import arcpy,os,glob import matplotlib.pyplot as plt import numpy as np from scipy.interpolate import spline mxd = arcpy.mapping.MapDocument(r"<MXD file with Data Driven Pages>") outputFolder = "C:/<ouput location>/" # there should be a picture element on your page at the location where you want the graph inserted pictureElementName = "<Picture Element Name>" eleFieldFeature = "<Elevation Point Feature Class>" eleField = "<Elevation Field>" # distField can be whatever field you want for the X axis distField = "<Distance Field>" df = arcpy.mapping.ListDataFrames(mxd, "Layers")[0] pict = arcpy.mapping.ListLayoutElements(mxd, "PICTURE_ELEMENT", pictureElementName)[0] lyr = arcpy.mapping.ListLayers(mxd, eleFieldFeature, df)[0] for pageNum in range(1, mxd.dataDrivenPages.pageCount + 1): mxd.dataDrivenPages.currentPageID = pageNum # change this SeqId to match the field name that you have in the DDP featureclass # this is redundant, but it works all the same and I didn't feel like changing it. :) pageName = mxd.dataDrivenPages.pageRow.getValue("SeqId") # change this SeqId to match the field name that you have in the Elevation featureclass arcpy.SelectLayerByAttribute_management(lyr, "NEW_SELECTION", ' "SeqId" = '+ repr(pageName)) # create array of selected arr = arcpy.da.FeatureClassToNumPyArray(lyr, (eleField, distField)) # set min and max for the graph from the array mineleField = arr[eleField].min() maxeleField = arr[eleField].max() minStation = arr[distField].min() maxStation = arr[distField].max() # matplotlib stuff x = [] y = [] elevPNG = outputFolder+"\elev"+repr(pageNum)+".png" fig = plt.figure(figsize=(32, 2.8)) table = lyr fields = [distField, eleField] with arcpy.da.SearchCursor(table, fields) as rows: for row in rows: x.append(row[0]) y.append(row[1]) # the next 7 lines generalize, smooth the line in case of missing data x_sm = np.array(x) y_sm = np.array(y) x_smooth = np.linspace(x_sm.min(), x_sm.max(),200) y_smooth = spline(x,y,x_smooth) # subtract/add 10 to the min max of the graph so elevation fits, can increase or decrease as you need plt.ylim((mineleField-10,maxeleField+10)) plt.xlim((minStation,maxStation)) plt.plot(x_smooth,y_smooth, color='red', linewidth=3) ## the next 3 is your X label, Y Label, and Graph Title plt.xlabel('Distance') plt.ylabel('Elevation') plt.title('Landscape Profile') plt.grid(True) fig.savefig(elevPNG, bbox_inches='tight', dpi=(100)) pict.sourceImage = elevPNG # end of matplotlib stuff print "Exporting page {0} of {1}".format(str(mxd.dataDrivenPages.currentPageID), str(mxd.dataDrivenPages.pageCount)) arcpy.mapping.ExportToPDF(mxd, outputFolder + str(pageName) + "_W_GRAPH.pdf", resolution=150, image_quality="NORMAL") plt.clf() plt.close() del fig del mxd
Hi Carl! This helped immensely and I've now changed the chart to a bar chart which is what I needed for my output! Thanks so much for your prompt reply and such detailed comments - much appreciated!
Thanks for this, Carl.
This script was very helpful. I just adapted it for getting the elevation and distance data directly from a polyline FeatureClass with Z and M coordinates and it worked like a charm. Thanks again.
How are you creating the graph? i have successfully done this with arcpy and matplotlib for data driven pages.
import arcpy,os path = os.getcwd() pageCount = 1 mxd = arcpy.mapping.MapDocument(path + r"\test_graph_exp.mxd") df = arcpy.mapping.ListDataFrames(mxd)[0] lyr = arcpy.mapping.ListLayers(mxd, "Counties_sel")[0] list_of_attributes = [row.getValue('Name') for row in arcpy.SearchCursor(lyr.dataSource)] for bez in list_of_attributes: #Make a graph for each line of the attribute table whereClause = "\"name\" = '" + bez + "'" lyr.definitionQuery = whereClause arcpy.SelectLayerByAttribute_management(lyr,"NEW_SELECTION", whereClause) arcpy.SaveGraph_management("test_graph", (path + r"\graph" + str(pageCount) + ".bmp") , "MAINTAIN_ASPECT_RATIO", "600", "375") arcpy.SelectLayerByAttribute_management(lyr, "CLEAR_SELECTION") pageCount = pageCount + 1 del mxd