Skip to content

Commit

Permalink
Add final refactoring edits, and updated documentation.
Browse files Browse the repository at this point in the history
  • Loading branch information
jesselangdon committed Jan 22, 2018
1 parent 30bd3a3 commit eef598e
Show file tree
Hide file tree
Showing 32 changed files with 1,552 additions and 277 deletions.
26 changes: 6 additions & 20 deletions FindSubnetworks.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,28 +31,16 @@
except ImportError:
arcpy.AddError(error_msg)

arcpy.env.overwriteOutput = True

def display_subnets(out_shp, list_subnets):
mxd = arcpy.mapping.MapDocument("current")
lyr = arcpy.mapping.ListLayers(mxd, "Subnetworks")[0]
if lyr.symbologyType == "UNIQUE_VALUES":
lyr.symbology.classValues = list_subnets
lyr.symbology.showOtherValues = False

arcpy.RefreshActiveView()
arcpy.RefreshTOC()
return


def find_errors(theNetwork, G, oid_field):
def find_errors(theNetwork, G):
"""
This function attempt to find potential topology errors in the stream network.
:param theNetwork:
:param G:
:param oid_field:
:param G: multidgraph
:return:
"""

net_ids = theNetwork.attribute_as_list(G, "_netid_")
# iterate through list of network IDs generate attributes, and produce a subnetwork graph
list_subnets = []
Expand All @@ -62,15 +50,15 @@ def find_errors(theNetwork, G, oid_field):
duplicates_G = theNetwork.error_dup(subnet_G)
outflow_G = theNetwork.error_outflow(subnet_G)
conf_G = theNetwork.error_confluence(subnet_G)
if theNetwork.check_attribute(outflow_G, "_edgetype_"):
theNetwork.delete_attribute(outflow_G, "_edgetype_")
# merge all error graphs
error_G = nx.compose_all([subnet_G, duplicates_G, conf_G, outflow_G])
list_subnets.append(error_G)
arcpy.AddMessage("Subnetwork #{} complete...".format(id))

# Union all subnetwork graphs
union_G = nx.union_all(list_subnets)
if theNetwork.check_attribute(union_G, "_edgetype_"):
theNetwork.delete_attribute(union_G, "_edgetype_")
return union_G


Expand All @@ -95,14 +83,12 @@ def main(in_shp, out_shp, bool_error=False):
# find topology errors
if bool_error:
arcpy.AddMessage("FSN: Finding network topology errors...")
error_G = find_errors(theNetwork, id_G, "_FID_")
error_G = find_errors(theNetwork, id_G)
final_G = error_G
else:
final_G = id_G

arcpy.AddMessage("FSN: Writing networkx graph to shapefile...")
theNetwork._nx_to_shp(final_G, out_shp, bool_node = False)

display_subnets(out_shp, list_SG)

return
640 changes: 640 additions & 0 deletions GNAT.FindSubnetworksTool.pyt.xml

Large diffs are not rendered by default.

517 changes: 517 additions & 0 deletions GNAT.GenerateNetworkAttributesTool.pyt.xml

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions GNAT.GenerateStreamOrderTool.pyt.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
<metadata xml:lang="en"><Esri><CreaDate>20180116</CreaDate><CreaTime>13402700</CreaTime><ArcGISFormat>1.0</ArcGISFormat><SyncOnce>TRUE</SyncOnce><ModDate>20180122</ModDate><ModTime>13471600</ModTime><scaleRange><minScale>150000000</minScale><maxScale>5000</maxScale></scaleRange><ArcGISProfile>ItemDescription</ArcGISProfile></Esri><tool name="GenerateStreamOrderTool" displayname="Generate Stream Order" toolboxalias="GNAT" xmlns=""><arcToolboxHelpPath>c:\program files (x86)\arcgis\desktop10.4\Help\gp</arcToolboxHelpPath><parameters><param name="InputStreamNetwork" displayname="Input stream network shapefile" type="Required" direction="Input" datatype="Shapefile" expression="InputStreamNetwork"><dialogReference>&lt;DIV STYLE="text-align:Left;"&gt;&lt;DIV&gt;&lt;P&gt;&lt;SPAN&gt;Line shapefile representing a stream network. All line features should be digitized in a downstream direction, with topological errors removed.&lt;/SPAN&gt;&lt;/P&gt;&lt;/DIV&gt;&lt;/DIV&gt;</dialogReference></param><param name="OutputStreamNetwork" displayname="Output network shapefile with stream order" type="Required" direction="Output" datatype="Shapefile" expression="OutputStreamNetwork"><dialogReference>&lt;DIV STYLE="text-align:Left;"&gt;&lt;DIV&gt;&lt;P&gt;&lt;SPAN&gt;Line shapefile produced by the tool. Includes a new _strmordr_ attribute field which stores Strahler stream order values.&lt;/SPAN&gt;&lt;/P&gt;&lt;/DIV&gt;&lt;/DIV&gt;</dialogReference></param><param name="TempWorkspace" displayname="Temporary workspace" type="Required" direction="Input" datatype="Workspace" expression="TempWorkspace"><dialogReference>&lt;DIV STYLE="text-align:Left;"&gt;&lt;DIV&gt;&lt;P&gt;&lt;SPAN&gt;Workspace for storing intermediate data fiels produced during tool processing.&lt;/SPAN&gt;&lt;/P&gt;&lt;/DIV&gt;&lt;/DIV&gt;</dialogReference></param></parameters><summary>&lt;DIV STYLE="text-align:Left;"&gt;&lt;DIV&gt;&lt;DIV&gt;&lt;P&gt;&lt;SPAN&gt;The &lt;/SPAN&gt;&lt;SPAN STYLE="font-weight:bold;"&gt;Generate Stream Order&lt;/SPAN&gt;&lt;SPAN&gt;tool calculates the Strahler stream order values for each feature within a linear shapefile. More detailed help documentation is available &lt;/SPAN&gt;&lt;A href="https://gnat.riverscapes.xyz/Generate-Stream-Order"&gt;&lt;SPAN&gt;here&lt;/SPAN&gt;&lt;/A&gt;&lt;SPAN&gt;.&lt;/SPAN&gt;&lt;/P&gt;&lt;/DIV&gt;&lt;/DIV&gt;&lt;/DIV&gt;</summary></tool><dataIdInfo><idCitation><resTitle>Generate Stream Order</resTitle></idCitation><idAbs>&lt;DIV STYLE="text-align:Left;"&gt;&lt;DIV&gt;&lt;DIV&gt;&lt;P&gt;&lt;SPAN&gt;The &lt;/SPAN&gt;&lt;SPAN STYLE="font-weight:bold;"&gt;Generate Stream Order&lt;/SPAN&gt;&lt;SPAN&gt;tool calculates the Strahler stream order values for each feature within a linear shapefile. More detailed help documentation is available &lt;/SPAN&gt;&lt;A href="https://gnat.riverscapes.xyz/Generate-Stream-Order"&gt;&lt;SPAN&gt;here&lt;/SPAN&gt;&lt;/A&gt;&lt;SPAN&gt;.&lt;/SPAN&gt;&lt;/P&gt;&lt;/DIV&gt;&lt;/DIV&gt;&lt;/DIV&gt;</idAbs><idCredit>Jesse Langdon, SFR Inc., 2018</idCredit><searchKeys><keyword>stream</keyword><keyword>network</keyword><keyword>geomorphic</keyword><keyword>drainage</keyword><keyword>GNAT</keyword><keyword>Strahler</keyword></searchKeys></dataIdInfo><distInfo><distributor><distorFormat><formatName>ArcToolbox Tool</formatName></distorFormat></distributor></distInfo><mdHrLv><ScopeCd value="005"/></mdHrLv></metadata>
113 changes: 50 additions & 63 deletions GNAT.pyt
Original file line number Diff line number Diff line change
Expand Up @@ -11,15 +11,14 @@
# #
# Created: 2015-Jan-08 #
# Version: 2.4.0 #
# Revised: 2017-Nov-20 #
# Revised: 2018-Jan-18 #
# Released: #
# #
# License: MIT License #
# #
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
#!/usr/bin/env python

# # Import Modules # #
import os
from os import path, makedirs
import arcpy
Expand All @@ -41,12 +40,14 @@ import CalculateThreadedness

GNAT_version = "2.4.0"


strCatagoryStreamNetworkPreparation = "Analyze Network Attributes\\Step 1 - Stream Network Preparation"
strCatagoryStreamNetworkSegmentation = "Analyze Network Attributes\\Step 2 - Stream Network Segmentation"
strCatagoryGeomorphicAnalysis = "Analyze Network Attributes\\Step 3 - Geomorphic Attributes"
strCatagoryProjectManagement = "Riverscapes Project Management"
strCatagoryUtilities = "Utilities"


class Toolbox(object):
def __init__(self):
"""Define the toolbox (the name of the toolbox is the name of the
Expand Down Expand Up @@ -403,19 +404,19 @@ class FindSubnetworksTool(object):
def getParameterInfo(self):
"""Define parameter definitions"""
param0 = arcpy.Parameter(
displayName="Input stream network polyline feature class",
displayName="Input stream network shapefle",
name="InputStreamNetwork",
datatype="DEFeatureClass",
datatype="DEShapefile",
parameterType="Required",
direction="Input")
param0.filter.list = ["Polyline"]

param1 = arcpy.Parameter(
displayName="Output workspace",
name="OutputWorkspace",
datatype="DEWorkspace",
displayName="Output shapefile",
name="OutputStreamNetwork",
datatype="DEShapefile",
parameterType="Required",
direction="Input")
direction="Output")

param2 = arcpy.Parameter(
displayName="Find topology errors",
Expand All @@ -424,14 +425,8 @@ class FindSubnetworksTool(object):
parameterType="Optional",
direction="Input")

param3 = arcpy.Parameter(
displayName="Downstream Reach ID",
name="ReachID",
datatype="GPLong",
parameterType="Optional",
direction="Input")

return [param0, param1, param2, param3]
return [param0, param1, param2]

def isLicensed(self):
"""Set whether tool is licensed to execute."""
Expand All @@ -441,11 +436,6 @@ class FindSubnetworksTool(object):
"""Modify the values and properties of parameters before internal
validation is performed. This method is called whenever a parameter
has been changed."""
if p[2].value:
p[3].enabled = True
else:
p[3].enabled = False

return

def updateMessages(self, parameters):
Expand All @@ -457,18 +447,17 @@ class FindSubnetworksTool(object):
"""The source code of the tool."""
reload(FindSubnetworks)

# TEST
in_shp = r'C:\JL\Testing\arcGNAT\networkx-refactor\NetworkFeatures\In\MinamSubset_noerrors.shp'
out_shp = r'C:\JL\Testing\arcGNAT\networkx-refactor\NetworkFeatures\Out\Test_MinamSubset_subnet.shp'
error_bool = False
testFType(in_shp, 336) # check to see if canals have been removed from input feature class
FindSubnetworks.main(in_shp, out_shp, error_bool)
# # TEST
# in_shp = r'C:\JL\Testing\arcGNAT\networkx-refactor\NetworkFeatures\Out\Test_FullNetwork_subnet_noerrors.shp'
# out_shp = r'C:\JL\Testing\arcGNAT\networkx-refactor\NetworkFeatures\Out\Test_FullNetwork_subnet_redo.shp'
# error_bool = True
# testFType(in_shp, 336) # check to see if canals have been removed from input feature class
# FindSubnetworks.main(in_shp, out_shp, error_bool)

# testFType(p[0].valueAsText, 336) # check to see if canals have been removed from input feature class
# FindSubnetworks.main(p[0].valueAsText,
# p[1].valueAsText,
# p[2].valueAsText,
# p[3].value)
testFType(p[0].valueAsText, 336) # check to see if canals have been removed from input feature class
FindSubnetworks.main(p[0].valueAsText,
p[1].valueAsText,
p[2].valueAsText)

return

Expand All @@ -479,25 +468,25 @@ class GenerateNetworkAttributesTool(object):
self.label = "Generate Network Attributes"
self.description = "Generates a series of network attributes, including edge type, node type, river kilometers," \
"and stream order."
self.canRunInBackground = True
self.canRunInBackground = False
self.category = strCatagoryStreamNetworkPreparation

def getParameterInfo(self):
"""Define parameter definitions"""
param0 = arcpy.Parameter(
displayName="Input stream network polyline feature class",
name="InputStreamNetwork",
datatype="DEFeatureClass",
datatype="DEShapefile",
parameterType="Required",
direction="Input")
param0.filter.list = ["Polyline"]

param1 = arcpy.Parameter(
displayName="Output workspace",
name="OutputWorkspace",
datatype="DEWorkspace",
displayName="Output polyline feature class",
name="OutputStreamNetwork",
datatype="DEShapefile",
parameterType="Required",
direction="Input")
direction="Output")

param2 = arcpy.Parameter(
displayName="Calculate river kilometers",
Expand Down Expand Up @@ -527,15 +516,15 @@ class GenerateNetworkAttributesTool(object):
"""The source code of the tool."""
reload(GenerateNetworkAttributes)

# TEST
in_shp = r"C:\JL\Testing\arcGNAT\networkx-refactor\NetworkFeatures\Out\Test_MinamSubset_subnet.shp"
riverkm_bool = False
out_shp = r"C:\JL\Testing\arcGNAT\networkx-refactor\NetworkFeatures\Out\Test_MinamSubset_attrb.shp"
GenerateNetworkAttributes.main(in_shp, out_shp, riverkm_bool)
# # TEST
# in_shp = r'C:\JL\Testing\arcGNAT\networkx-refactor\NetworkFeatures\Out\Test_FullNetwork_subnet_noerrors2.shp'
# riverkm_bool = False
# out_shp = r"C:\JL\Testing\arcGNAT\networkx-refactor\NetworkFeatures\Out\Test_FullNetwork_attrb.shp"
# GenerateNetworkAttributes.main(in_shp, out_shp, riverkm_bool)

# GenerateNetworkAttributes.main(p[0].valueAsText,
# p[1].valueAsText,
# p[2].valueAsText)
GenerateNetworkAttributes.main(p[0].valueAsText,
p[1].valueAsText,
p[2].valueAsText)
return


Expand Down Expand Up @@ -590,23 +579,23 @@ class GenerateStreamOrderTool(object):
parameter. This method is called after internal validation."""

testProjected(parameters[0])
testWorkspacePath(parameters[4])
testWorkspacePath(parameters[2])
return

def execute(self, p, messages):
"""The source code of the tool."""

reload(GenerateStreamOrder)

# TEST
in_shape = r"C:\JL\Testing\arcGNAT\networkx-refactor\NetworkFeatures\Out\Test_MinamSubset_attrb.shp"
out_shape = r"C:\JL\Testing\arcGNAT\networkx-refactor\NetworkFeatures\Out\Test_MinamSubset_so.shp"
temp_workspace = r"C:\JL\Testing\arcGNAT\networkx-refactor\TempWorkspace"
GenerateStreamOrder.main(in_shape, out_shape, temp_workspace)
# # TEST
# in_shape = r"C:\JL\Testing\arcGNAT\networkx-refactor\NetworkFeatures\Out\Test_FullNetwork_attrb.shp"
# out_shape = r"C:\JL\Testing\arcGNAT\networkx-refactor\NetworkFeatures\Out\Test_FullNetwork_so.shp"
# temp_workspace = r"C:\JL\Testing\arcGNAT\networkx-refactor\TempWorkspace"
# GenerateStreamOrder.main(in_shape, out_shape, temp_workspace)

# GenerateStreamOrder.main(p[0].valueAsText,
# p[1].valueAsText,
# p[2].valueAsText)
GenerateStreamOrder.main(p[0].valueAsText,
p[1].valueAsText,
p[2].valueAsText)


# Stream Segmentation
Expand Down Expand Up @@ -2122,8 +2111,6 @@ def testFType(parameter, ftype):
unique_values = set(val for val in value_list)
if ftype in unique_values:
arcpy.AddError("Stream features where FType = 336 must be removed from the input shapefile.")
else:
arcpy.AddWarning("An attribute field named FType was not found in the shapefile.")
return

# Common params
Expand Down Expand Up @@ -2180,10 +2167,10 @@ paramStreamNetwork = arcpy.Parameter(
direction="Input")
paramStreamNetwork.filter.list = ["Polyline"]

# TEST
def main():
tool = GenerateStreamOrderTool()
tool.execute(tool.getParameterInfo(), None)

if __name__ == "__main__":
main()
# # TEST
# def main():
# tool = FindSubnetworksTool()
# tool.execute(tool.getParameterInfo(), None)
#
# if __name__ == "__main__":
# main()
18 changes: 1 addition & 17 deletions GenerateNetworkAttributes.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,9 @@
#!/usr/bin/env python

# Import modules
import os.path
import arcpy
import networkx as nx
import network as net
import gis_tools

import_msg = "{0} module not installed. Please install {0} before executing the {1} tool."\
.format('ogr', "Generate Network Attributes")
Expand All @@ -32,17 +30,7 @@
except ImportError:
arcpy.AddError(import_msg)


def display_types(out_shp, list_types):
mxd = arcpy.mapping.MapDocument("current")
lyr = arcpy.mapping.ListLayers(mxd, "Network Edge Types")[0]
if lyr.symbologyType == "UNIQUE_VALUES":
lyr.symbology.classValues = list_types
lyr.symbology.showOtherValues = False

arcpy.RefreshActiveView()
arcpy.RefreshTOC()
return
arcpy.env.overwriteOutput = True


def main(in_shp, out_shp, riverkm_bool=False):
Expand Down Expand Up @@ -71,7 +59,6 @@ def main(in_shp, out_shp, riverkm_bool=False):
arcpy.AddError("ERROR: {} attribute field not found! The network should first be processed through"
"the Find Subnetworks Tool.".format(netid))


if theNetwork.check_attribute(theNetwork.G, edgetype):
theNetwork.delete_attribute(theNetwork.G, edgetype)

Expand Down Expand Up @@ -111,10 +98,7 @@ def main(in_shp, out_shp, riverkm_bool=False):
arcpy.AddMessage("GNA: Merging all subnetworks...")
theNetwork.G = nx.union_all(list_subnets)


arcpy.AddMessage("GNA: Writing to shapefile...")
theNetwork._nx_to_shp(theNetwork.G, out_shp, bool_node=True)

display_types(out_shp, ['headwater', 'outflow', 'connector', 'mainflow', 'braid'])

return
7 changes: 4 additions & 3 deletions GenerateStreamOrder.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,14 +24,14 @@
import GenerateNetworkAttributes
import network as net

arcpy.env.overwriteOutput = True


def check_field(in_shp, field_name):
fieldnames = [field.name for field in arcpy.ListFields(in_shp)]
if field_name in fieldnames:
return True

# TODO check if in_shp has error fields with "1" values
def check_errors(in_shp, field_list):
return

def get_fieldmap(in_network, in_gnis_pnt):
fm = arcpy.FieldMappings()
Expand Down Expand Up @@ -65,6 +65,7 @@ def dslv_network(in_shp, temp_wspace):
else:
arcpy.AddError("{0} attribute field not found in {1}".format("GNIS_Name", os.path.basename(in_shp)))


def main(in_shp, out_shp, temp_wspace):
"""Main function to calculate Strahler stream order for an input stream network.
:param in_shp: Shapefile output, which is the output from Find Subnetworks tool.
Expand Down
Loading

0 comments on commit eef598e

Please sign in to comment.