Working with kernel files in arcpy: NbrIrregular bug

3380
0
09-04-2014 12:03 PM
curtvprice
MVP Esteemed Contributor

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

0 Kudos
0 Replies