curtvprice

Working with kernel files in arcpy: NbrIrregular bug

Discussion created by curtvprice Champion on Sep 4, 2014

When I try to use NbrIrregular in arcpy the tool fails:

 

>>> z = FocalStatistics("xg", NbrIrregular(r"D:\Users\cprice\work\scratch\x.txt"))

ERROR 010385: Invalid neighborhood type

 

I logged an incident with support and discovered this is a bug; fixed at 10.3:

[Bug NIM089705: The Focal Statistics tool in Python does not recognize the irregular neighborhood file using the NbrIrregular() object]

 

You can work around this problem by  using the text representation (I discovered this by using Copy As Python Snippet from the Results window:

 

NbrIrregular("Irregular <full_path_to_file>")
NbrIrregular("Irregular C:\kernels\ker.txt>") # for example

 

I think it's pretty weak that I have to write a kernel file in notepad too. I requested an enhancement, but in the meantime, here's a python function to make the process a little more convenient.

 

import arcpy
def NbrKernelFile(kernel="0 1 0; 1 1 1; 0 1 0", ktype="INTEGER"):
    """Create an ArcGIS Spatial Analyst kernel file
   
    example
    
      kerfile = NbrKernelFile("0 1 0;1 1 1;0 1 0")
      out_raster = arcpy.sa.FocalStatistics(in_raster, "Irregular {}".format(kerfile))
      arcpy.Delete_management(kerfile)
      
    note
    
    At 10.1/10.2 there is a bug, so we can't use NbrIrregular().
    The following code fails with ERROR 010385: Invalid neighborhood type:
    
    out_raster = arcpy.sa.FocalStatistics(in_raster, NbrIrregular(kerfile))

    Bug NIM089705: The Focal Statistics tool in Python does not recognize
    the irregular neighborhood file using the NbrIrregular() object.    
        
    Testing showed we could use this text representation, as used in
    the example above:
    
    "Irregular <full-path-to-kernel-file-no-quotes>"
      
    Curtis Price, cprice@usgs.gov, 2014/09/04
    """
    # set up output file name
    out_file = arcpy.CreateScratchName(suffix="ker.txt" , 
                                       workspace=arcpy.env.scratchFolder)
   
    try:
        # process kernel text        
        krows = kernel.split(";")
        if str(ktype)[:3].lower() == "int": ktype = "INTEGER"
        if ktype == "INTEGER":
            krows = [[str(int(k)) for k in krow.split()] for krow in krows]
        else:
            krows = [[str(float(k)) for k in krow.split()] for krow in krows]
        # check that we have an equal # of elements in each row
        ncols = len(krows[0])
        nrows = len(krows)
        for krow in krows:
            if len(krow) != ncols: raise
    except:
        raise Exception("Invalid kernel string: {0}".format(repr(kernel)))

    # write the kernel file
    try:
        kf = open(out_file, "w")
    except:
        raise Exception("Could not write file: {}".format(out_file))
    kf.write("{0} {1}\n".format(ncols, nrows))
    kf.writelines([" ".join(krow) + "\n" for krow in krows])
    kf.close()
    
    return out_file





 

CP - minor editorial changes

Outcomes