Python: Geo-HMS "Centroidal Longest Flowpath"

4166
3
Jump to solution
02-02-2016 11:10 PM
PeterWilson
Occasional Contributor III

I'm trying to get Geo-HMS "Centroidal Longest Flowpath" to run from within Python.

My current configuration is:

  1. ArcGIS 10.2.2
  2. ArcHydro 10.2.0.191
  3. HEC-GeoHMS 10.2.0.41
  4. HEC-GeoRAS 10.2.0.12
  5. HEC-RAS 4.1.0

I've generated a python module using the following code:

import arcpy
import arcpy.toolbox_code
arcpy.toolbox_code.generate_toolbox_module(r'C:\Program Files (x86)\ArcGIS\Desktop10.2\ArcToolbox\Toolboxes\GeoHMS Tools.tbx', r'C:\Program Files (x86)\HEC\HEC-GeoHMS\bin\GeoHMSTools.py' False, False, True)

I then generated a python path file that points to the GeoHMSTools.py module file under the following directory:

C:\Python27\ArcGIS10.2\Lib\site-packages\GeoHMSTools.pth

I'm able to import GeoHMSTools within my Python IDE (Eclipse) as well as within ArcMap Python Interpreter Window and all the tools are visisble. When I try to run Centroidal Longest Flowpath from within Python I receive the following error message after Python crashes:

'''
Created on Feb 2, 2016

@author: PeterW
'''
import arcpy
import GeoHMSTools


subbasin = r"E:\Python\Temp\Model02\Model02.gdb\Layers\Subwatershed"
centroid = r"E:\Python\Temp\Model02\Model02.gdb\Layers\Centroid"
longestflowpath = r"E:\Python\Temp\Model02\Model02.gdb\Layers\LongestFlowPath_2D"
centroidallongestflowpath = r"E:\Python\Temp\Model02\Model02.gdb\Layers\CentroidalLongestFlowPath10"

GeoHMSTools.CentroidalLongestFlowpath(subbasin, centroid, longestflowpath, centroidallongestflowpath)

Unhandled Exception: System.ArgumentException: The object's type must be __ComObject or derived from __ComObject.
Parameter name: o
   at System.Runtime.InteropServices.Marshal.ReleaseComObject(Object o)
   at ESRI.APWR.HECGeoHMS10.GPCentroidalLongestFlowPath.Finalize()

Any help in being able to resolve the following will be appreciated.

1 Solution

Accepted Solutions
PeterWilson
Occasional Contributor III

Hi Cynthia

I eventually landed up re-writing the Centroidal Longest Flowpath Tool within Python. I've added the code below if you'd like to use it.

Please note that you will need Python Pathlib Package or other wise replace it with os.path.join​.

Also note that the following feature class needs to be within the input file geodatabase:

  • LongestFlowPath_2D (i.e. its the longest flow path feature class for each subwatershed or watershed)

'''
Created on Feb 23, 2016

Determine CentroidalongestFlowPath

@author: PeterW
'''
# import site-packages and modules
from pathlib import Path
import arcpy

# set input and output arguments
fgdb = Path(r"E:\Projects\2016\G112491\ArcHydro\ArcHydro\Northern\Model01\Model01.gdb")

# set environment variables
arcpy.env.overwriteOutput = True


# add centroidalfl field to longestflowpath_2d
def centroidal_flow_line_field(fgdb):
    longestflowpath_2d = "{0}\\{1}".format(Path(fgdb, "Layers"),
                                          "LongestFlowPath_2D")
    fieldname = "CentroidalFL"
    fields = arcpy.ListFields(longestflowpath_2d)
    for field in fields:
        if field.name.lower() == fieldname.lower():
            arcpy.DeleteField_management(longestflowpath_2d, fieldname)
            arcpy.AddField_management(longestflowpath_2d, fieldname, "DOUBLE")
        else:
            arcpy.AddField_management(longestflowpath_2d, fieldname, "DOUBLE")
    return longestflowpath_2d

longestflowpath_2d = centroidal_flow_line_field(fgdb)


# flip longestflowpath_2d downstream to upstream
def flip_longestflowpath(longestflowpath_2d):
    arcpy.FlipLine_edit(longestflowpath_2d)

flip_longestflowpath(longestflowpath_2d)


# determine centroidal longest flowpath length and point geometry
def centroidal_flow_line_length(fgdb, longestflowpath_2d):
    centroid = "{0}\\{1}".format(Path(fgdb, "Layers"), "Centroid")
    centroidalfl_geometry = []
    with arcpy.da.SearchCursor(centroid, ["SHAPE@", "DrainID"]) as scur:  # @UndefinedVariable
        for row1 in scur:
            with arcpy.da.UpdateCursor(longestflowpath_2d, ["SHAPE@", "DrainID", "CentroidalFL"]) as upcur:  # @UndefinedVariable
                for row2 in upcur:
                    if row1[1] == row2[1]:
                        tpl = row2[0].queryPointAndDistance(row1[0], False)
                        row2[2] = tpl[1]
                        upcur.updateRow(row2)
                        centroidalfl_geometry.append(tpl[0])
    return centroidalfl_geometry
centroidalfl_geometry = centroidal_flow_line_length(fgdb, longestflowpath_2d)

# flip longestflowpath_2d upstream to downstream
flip_longestflowpath(longestflowpath_2d)


# generate centroidal longest flowpath polylines from longestflowpath_2d
def centroidal_flow_line_polyline(fgdb, longestflowpath_2d,
                                  centroidalfl_geometry):
    centroidalfl_polyline = "{0}\\{1}".format(Path(fgdb, "Layers"),
                                              "CentroidalFL")
    arcpy.SplitLineAtPoint_management(longestflowpath_2d,
                                      centroidalfl_geometry,
                                      centroidalfl_polyline)
    centroidalfl_length = []
    with arcpy.da.SearchCursor(longestflowpath_2d, ["CentroidalFL"]) as scur:  # @UndefinedVariable
        for row in scur:
            centroidalfl_length.append("{0:.6f}".format(row[0]))
    with arcpy.da.UpdateCursor(centroidalfl_polyline, ["SHAPE@LENGTH"]) as upcur:  # @UndefinedVariable
        for row in upcur:
            shape_length = "{0:.6f}".format(row[0])
            if shape_length not in centroidalfl_length:
                upcur.deleteRow()


centroidal_flow_line_polyline(fgdb, longestflowpath_2d, centroidalfl_geometry)

Hope the following helps

View solution in original post

3 Replies
CynthiaCastro1
New Contributor

I also have this question.  So far this is what I have:

arcpy.ImportToolbox(r"Toolboxes\System Toolboxes\GeoHMS Tools.tbx")

arcpy.BasinCentroid_geohms("Center of gravity", "Subbasin", "Centroid")

arcpy.CentroidalLongestFlowpath_geohms("Subbasin", "Centroid", "Longest", "Longest_Centroid")

The "Longest" flowpath layer was created correctly with ArcHydro.  I cannot get the Python codes to work and create a longest flowpath layer with HEC-GeoHMS.  I think this is where the error is coming in.  Any help from Esri?

0 Kudos
PeterWilson
Occasional Contributor III

Hi Cynthia

I eventually landed up re-writing the Centroidal Longest Flowpath Tool within Python. I've added the code below if you'd like to use it.

Please note that you will need Python Pathlib Package or other wise replace it with os.path.join​.

Also note that the following feature class needs to be within the input file geodatabase:

  • LongestFlowPath_2D (i.e. its the longest flow path feature class for each subwatershed or watershed)

'''
Created on Feb 23, 2016

Determine CentroidalongestFlowPath

@author: PeterW
'''
# import site-packages and modules
from pathlib import Path
import arcpy

# set input and output arguments
fgdb = Path(r"E:\Projects\2016\G112491\ArcHydro\ArcHydro\Northern\Model01\Model01.gdb")

# set environment variables
arcpy.env.overwriteOutput = True


# add centroidalfl field to longestflowpath_2d
def centroidal_flow_line_field(fgdb):
    longestflowpath_2d = "{0}\\{1}".format(Path(fgdb, "Layers"),
                                          "LongestFlowPath_2D")
    fieldname = "CentroidalFL"
    fields = arcpy.ListFields(longestflowpath_2d)
    for field in fields:
        if field.name.lower() == fieldname.lower():
            arcpy.DeleteField_management(longestflowpath_2d, fieldname)
            arcpy.AddField_management(longestflowpath_2d, fieldname, "DOUBLE")
        else:
            arcpy.AddField_management(longestflowpath_2d, fieldname, "DOUBLE")
    return longestflowpath_2d

longestflowpath_2d = centroidal_flow_line_field(fgdb)


# flip longestflowpath_2d downstream to upstream
def flip_longestflowpath(longestflowpath_2d):
    arcpy.FlipLine_edit(longestflowpath_2d)

flip_longestflowpath(longestflowpath_2d)


# determine centroidal longest flowpath length and point geometry
def centroidal_flow_line_length(fgdb, longestflowpath_2d):
    centroid = "{0}\\{1}".format(Path(fgdb, "Layers"), "Centroid")
    centroidalfl_geometry = []
    with arcpy.da.SearchCursor(centroid, ["SHAPE@", "DrainID"]) as scur:  # @UndefinedVariable
        for row1 in scur:
            with arcpy.da.UpdateCursor(longestflowpath_2d, ["SHAPE@", "DrainID", "CentroidalFL"]) as upcur:  # @UndefinedVariable
                for row2 in upcur:
                    if row1[1] == row2[1]:
                        tpl = row2[0].queryPointAndDistance(row1[0], False)
                        row2[2] = tpl[1]
                        upcur.updateRow(row2)
                        centroidalfl_geometry.append(tpl[0])
    return centroidalfl_geometry
centroidalfl_geometry = centroidal_flow_line_length(fgdb, longestflowpath_2d)

# flip longestflowpath_2d upstream to downstream
flip_longestflowpath(longestflowpath_2d)


# generate centroidal longest flowpath polylines from longestflowpath_2d
def centroidal_flow_line_polyline(fgdb, longestflowpath_2d,
                                  centroidalfl_geometry):
    centroidalfl_polyline = "{0}\\{1}".format(Path(fgdb, "Layers"),
                                              "CentroidalFL")
    arcpy.SplitLineAtPoint_management(longestflowpath_2d,
                                      centroidalfl_geometry,
                                      centroidalfl_polyline)
    centroidalfl_length = []
    with arcpy.da.SearchCursor(longestflowpath_2d, ["CentroidalFL"]) as scur:  # @UndefinedVariable
        for row in scur:
            centroidalfl_length.append("{0:.6f}".format(row[0]))
    with arcpy.da.UpdateCursor(centroidalfl_polyline, ["SHAPE@LENGTH"]) as upcur:  # @UndefinedVariable
        for row in upcur:
            shape_length = "{0:.6f}".format(row[0])
            if shape_length not in centroidalfl_length:
                upcur.deleteRow()


centroidal_flow_line_polyline(fgdb, longestflowpath_2d, centroidalfl_geometry)

Hope the following helps

DorotaNowicz
New Contributor

Hi, I have the same problem. Does anyone find a solution?

0 Kudos