Why is list index out of range here but not here?

6550
12
Jump to solution
09-16-2018 11:53 PM
LindsayRaabe_FPCWA
Occasional Contributor III

The code below seems to function correctly most of the time except when running through a situation where line 43 is False (no extent updates based on this layer) and Line 51 is True (1+ feature in this layer), meaning Line 54 is also True (extent set at Line 22 should still match extent at Line 52). 

What I'm not understanding is 2 things:

1. Why is it running through the elif at Line 61 when the condition should be False (as per Line 54 being True)

2. Why when it does run through the elif at Line 61 I get the below Trackback error about the list Index being out of range when it works elsewhere in the same manner?

Hope that all makes sense!

import arcpy
from arcpy import env, mapping
from bisect import bisect

#input parameters;
Plantation = arcpy.GetParameter(0)
ForestID = arcpy.GetParameter(1)
CommonName = arcpy.GetParameter(2)
PYear = arcpy.GetParameter(3)
OpCode = arcpy.GetParameter(4)

#variables;
title1 = Plantation + " PLANTATION"
title2 = Plantation + "\r\nPLANTATION"
title3 = Plantation + " (" + CommonName + ")"
title4 = Plantation + " P" + PYear + " AREA STATEMENT"
mxd = mapping.MapDocument("CURRENT")
elements = mapping.ListLayoutElements(mxd)
layers = mapping.ListLayers(mxd)
HTL_layer_list = ["Entered In GeoMaster", "Entered In GeoMaster Archive"]
dflist = arcpy.mapping.ListDataFrames(mxd, "")
orig_ext = dflist[0].extent
new_exp = "PLANTATION = '" + Plantation + "'"
new_sur_exp = "PLANTATION <> '" + Plantation + "'"
as_new_exp = "EnteredInGeoMaster IS NOT NULL AND Plantation = '" + Plantation + "'"
opcode_exp1 = "Entered_In_GeoMaster IS NOT NULL AND Ops_Code = '" + OpCode + "'"
opcode_exp2 = "Ops_Code = '" + OpCode + "'"
scalelist = [5000, 7500, 10000, 12500, 20000, 25000, 30000, 40000, 50000, 60000, 70000, 75000, 80000, 90000, 100000]

if mxd.title <> ("Cutting Returns Entered in GeoMaster"):

    ###other code here###

elif mxd.title == ("Cutting Returns Entered in GeoMaster"):

    mxd.activeView = "Page_Layout"
    
    for lyr in layers:
        if lyr.name == "Entered In GeoMaster":
            lyr.definitionQuery = opcode_exp1
            arcpy.AddMessage(lyr.name + " definition query updated")
            EIGfeature_count = arcpy.GetCount_management(lyr)[0]
            if EIGfeature_count > 0:
                ext = lyr.getExtent() #gets the new extent of the Entered In GeoMaster layer
                dflist[0].extent = ext #applies the Entered In GeoMaster layer extent to the dataframe
                    
        elif lyr.name == "Entered In GeoMaster Archive":
            lyr.definitionQuery = opcode_exp2
            arcpy.AddMessage(lyr.name + " definition query updated")
            EIGAfeature_count = arcpy.GetCount_management(lyr)[0]
            if EIGAfeature_count > 0:
                current_ext = dflist[0].extent

                if current_ext == orig_ext:
                    ext = lyr.getExtent() #gets the new extent of the Entered In GeoMaster layer
                    dflist[0].extent = ext #applies the Entered In GeoMaster layer extent to the dataframe
                    oldscale = dflist[0].scale # Get scale of dataframe
                    newscale = scalelist[bisect(scalelist, oldscale)] # bisect old scale to get new scale
                    dflist[0].scale = newscale # Apply new scale to dataframe

                elif current_ext <> orig_ext:
                    # get current map extent
                    xmin, xmax = dflist[0].extent.XMin, dflist[0].extent.XMax
                    ymin, ymax = dflist[0].extent.YMin, dflist[0].extent.YMax
                    # loop through def query layer extents and create one extent to fit them all
                    lyr_ext = lyr.getExtent()
                    if lyr_ext.XMin < xmin:
                        xmin = lyr_ext.XMin
                    if lyr_ext.YMin < ymin:
                        ymin = lyr_ext.YMin
                    if lyr_ext.XMax > xmax:
                        xmax = lyr_ext.XMax
                    if lyr_ext.YMax > ymax:
                        ymax = lyr_ext.YMax
                    # set df extent to new extent
                    dflist[0].extent = arcpy.Extent(xmin, ymin, xmax, ymax)
                    oldscale = dflist[0].scale # Get scale of dataframe
                    newscale = scalelist[bisect(scalelist, oldscale)] # bisect old scale to get new scale
                    dflist[0].scale = newscale # Apply new scale to dataframe

        elif lyr.name == "PlantationsHarvestPlan_OperationsPlanner_WA":
            lyr.definitionQuery = new_exp
            arcpy.AddMessage(lyr.name + " definition query updated")‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍
Traceback (most recent call last):
 File "W:\Mapping\ToolboxPythonCodes\SCRIPTS\Update Definition Queries.py", line 78, in <module>
 newscale = scalelist[bisect(scalelist, oldscale)] # bisect old scale to get new scale
IndexError: list index out of range

For reference, the aim here is to updated the definition queries on 2 layers in an open MXD, check for features in each layer and zoom the extent to view all the features in both layers before stepping the scale up (using bisect) to the next round scale in the list. 

Lindsay Raabe
GIS Officer
Forest Products Commission WA
Tags (4)
0 Kudos
12 Replies
LindsayRaabe_FPCWA
Occasional Contributor III

Thanks for your help. Glad we at least got the index issues sorted! I'll have to look into python 3. Anything in particular here that won't talk in the new version? I'm guessing the syntax has changed?

Lindsay Raabe
GIS Officer
Forest Products Commission WA
0 Kudos
DanPatterson_Retired
MVP Emeritus

As for python 3, I have forgotten most of the differences since I have been using 3 for so long (even with arcmap code).

The porting isn't that difficult and many of the differences don't affect the average user.

print.... no longer  print "stuff"   but    print("stuff")

It is all in the python docs which are at 3.8 beta, 3.6 is used by python

I try to maintain any significant change in my blog post

/blogs/dan_patterson/2016/05/09/the-links 

as for ArcGIS Pro and transitioning to it... this is a good place to start and there is something for modelbuilder checks as well

Tools that are not available in ArcGIS Pro—Appendices | ArcGIS Desktop 

good luck

LindsayRaabe_FPCWA
Occasional Contributor III

I found a solution. I had a niggling feeling that it was the comparisons between original and current extent that was not behaving the way I expected. I originally thought this would be the best indication of the map having moved/changed based on the features in the layers. After seeing the scale print statements and how fine they were (i.e. oldscale = 404659.559547) I figured it would be highly unlikely these would ever occur twice. Thus, I changed the code from comparing original and current extent to scales and now it works as expected. 

Can't thank you enough for your help with this!

Lindsay Raabe
GIS Officer
Forest Products Commission WA
0 Kudos