'''------------------------------------------------------------------------------- Tool Name: CreateDischargeMap Source Name: CreateDischargeMap.py Version: ArcGIS 10.2 License: Apache 2.0 Author: Environmental Systems Research Institute Inc. Updated by: Environmental Systems Research Institute Inc. Description: Create a dischage map document. History: Initial coding - 05/8/2015, version 1.0 Updated: Version 1.0, 06/02/2015, rename the default template layer file names from FGDB_TimeEnabled_5NaturalBreaks.lyr and SQL_TimeEnabled_5NaturalBreaks.lyr to FGDB_TimeEnabled.lyr and SQL_TimeEnabled.lyr Version 1.1, 06/24/2015, add all layers into a group layer named as "AllScales", which is specified in the template .mxd Version 1.1, 04/01/2016, deleted unnecessary line of import netCDF4 -------------------------------------------------------------------------------''' import os import arcpy import numpy as NUM import time class CreateDischargeMap(object): def __init__(self): """Define the tool (tool name is the name of the class).""" self.label = "Create Discharge Map" self.description = "Create a discharge map document for stream flow visualization based on \ the discharge table and the drainage line feature class" self.name_ID = "COMID" self.GDBtemplate_layer = os.path.join(os.path.dirname(__file__), "templates", "FGDB_TimeEnabled.lyr") self.SQLtemplate_layer = os.path.join(os.path.dirname(__file__), "templates", "SQL_TimeEnabled.lyr") self.template_mxd = os.path.join(os.path.dirname(__file__), "templates", "template_mxd.mxd") self.name_df = "DischargeMap" self.field_streamOrder = "StreamOrde" self.layer_minScale_maxScale_query = {"All": [None, None, None]} self.canRunInBackground = False self.category = "Postprocessing" def copyFlowlines(self, in_drainage_line, path_database, list_uniqueID): """Create copies of flowlines based on the layer query definitions""" # make a feature layer for query selection name_lyr = "flowlines" arcpy.MakeFeatureLayer_management(in_drainage_line, name_lyr) '''Create the query expression for line features with matching records in the flat table''' expression_base = self.name_ID + " IN (" count = len(list_uniqueID) counter = 1 for each_ID in list_uniqueID: if counter == count: expression_base = expression_base + str(each_ID) + ")" else: expression_base = expression_base + str(each_ID) + ", " counter += 1 for each_key in self.layer_minScale_maxScale_query.keys(): out_copy = os.path.join(path_database, "Flowline_"+each_key) pars = self.layer_minScale_maxScale_query[each_key] query = pars[2] expression = expression_base if query is not None: expression = expression_base + "AND " + query arcpy.SelectLayerByAttribute_management(name_lyr, "NEW_SELECTION", expression) arcpy.CopyFeatures_management(name_lyr, out_copy) arcpy.AddIndex_management(out_copy, self.name_ID, self.name_ID, "UNIQUE", "ASCENDING") return def getParameterInfo(self): """Define parameter definitions""" param0 = arcpy.Parameter(name = "in_drainage_line", displayName = "Input Drainage Line Features", direction = "Input", parameterType = "Required", datatype = "GPFeatureLayer") param1 = arcpy.Parameter(name = "in_discharge_table", displayName = "Input Discharge Table", direction = "Input", parameterType = "Required", datatype = "DETable") param2 = arcpy.Parameter(name = "out_discharge_map", displayName = "Output Discharge Map", direction = "Output", parameterType = "Required", datatype = "DEMapDocument" ) param3 = arcpy.Parameter(name = "in_unique_ID_table", displayName = "Input Unique ID Table", direction = "Input", parameterType = "Optional", datatype = "DETable") param4 = arcpy.Parameter(name = "in_layer_info", displayName = "Input Layer Information", direction = "Input", parameterType = "Optional", datatype = "GPValueTable") param4.columns = [['String', 'Layer Name'], ['Long', 'Minimum Scale'], ['Long', 'Maximum Scale'], ['Long', 'Minimum Stream Order']] params = [param0, param1, param2, param3, param4] return params def isLicensed(self): """Set whether tool is licensed to execute.""" return True def updateParameters(self, parameters): """Modify the values and properties of parameters before internal validation is performed. This method is called whenever a parameter has been changed.""" '''Add .mxd suffix to the output map document name''' if parameters[2].altered: (dirnm, basenm) = os.path.split(parameters[2].valueAsText) if not basenm.endswith(".mxd"): parameters[2].value = os.path.join(dirnm, "{}.mxd".format(basenm)) return def updateMessages(self, parameters): """Modify the messages created by internal validation for each tool parameter. This method is called after internal validation.""" return def execute(self, parameters, messages): """The source code of the tool.""" arcpy.env.overwriteOutput = True in_drainage_line = parameters[0].valueAsText in_flat_table = parameters[1].valueAsText out_map_document = parameters[2].valueAsText in_uniqueID_table = parameters[3].valueAsText in_layer_info = parameters[4].value ''' Obtain a list of unique IDs ''' list_uniqueID = [] if in_uniqueID_table is not None: arr_uniqueID = arcpy.da.TableToNumPyArray(in_uniqueID_table, self.name_ID) arr_uniqueID = arr_uniqueID[self.name_ID] list_uniqueID = list(arr_uniqueID) else: arr_ID = arcpy.da.TableToNumPyArray(in_flat_table, self.name_ID) arr_ID = arr_ID[self.name_ID] list_uniqueID = list(NUM.unique(arr_ID)) ''' Update self.layer_minScale_maxScale_query if user defines the map layer information''' if in_layer_info is not None: self.layer_minScale_maxScale_query = {} for each_list in in_layer_info: layer_minScale = None layer_maxScale = None layer_query = None if each_list[1] > 0: layer_minScale = each_list[1] if each_list[2] > 0: layer_maxScale = each_list[2] if each_list[3] > 0: layer_query = self.field_streamOrder + " >= " + str(each_list[3]) key_in_dict = each_list[0] list_in_dict = [layer_minScale, layer_maxScale, layer_query] self.layer_minScale_maxScale_query[key_in_dict] = list_in_dict # Get the database path of the flat table (dirnm, basenm) = os.path.split(in_flat_table) '''Copy Flow line features and add attribute index''' self.copyFlowlines(in_drainage_line, dirnm, list_uniqueID) '''Create Map Document''' mxd = arcpy.mapping.MapDocument(self.template_mxd) df = arcpy.mapping.ListDataFrames(mxd)[0] df.name = self.name_df mxd.saveACopy(out_map_document) del mxd, df template_lyr = self.GDBtemplate_layer if not dirnm.endswith('.gdb'): template_lyr = self.SQLtemplate_layer for each_key in self.layer_minScale_maxScale_query.keys(): mxd = arcpy.mapping.MapDocument(out_map_document) df = arcpy.mapping.ListDataFrames(mxd)[0] targetGroupLayer = arcpy.mapping.ListLayers(mxd, "AllScales", df)[0] lyrFile = arcpy.mapping.Layer(template_lyr) out_flowlines = os.path.join(dirnm, "Flowline_"+each_key) # Create Layer lyr = arcpy.mapping.Layer(out_flowlines) # Add join to layer arcpy.AddJoin_management(lyr, self.name_ID, in_flat_table, self.name_ID, "KEEP_COMMON") # Set min and max scales for layers minScale = self.layer_minScale_maxScale_query[each_key][0] maxScale = self.layer_minScale_maxScale_query[each_key][1] if minScale is not None: lyr.minScale = minScale if maxScale is not None: lyr.maxScale = maxScale # Apply symbology from template arcpy.ApplySymbologyFromLayer_management(lyr, template_lyr) # Add layer arcpy.mapping.AddLayerToGroup(df, targetGroupLayer, lyr, "BOTTOM") mxd.save() del mxd, df, lyr, targetGroupLayer # Update layer time property for each_key in self.layer_minScale_maxScale_query.keys(): mxd = arcpy.mapping.MapDocument(out_map_document) df = arcpy.mapping.ListDataFrames(mxd)[0] lyr = arcpy.mapping.ListLayers(mxd, "Flowline_"+each_key, df)[0] arcpy.mapping.UpdateLayerTime(df, lyr, lyrFile) dft = df.time dft.startTime = lyr.time.startTime dft.endTime = lyr.time.endTime mxd.save() del mxd, df, lyr # Add the flat table into map: as a workaround for a potential bug in publishing mxd = arcpy.mapping.MapDocument(out_map_document) df = arcpy.mapping.ListDataFrames(mxd)[0] flat_Table = arcpy.mapping.TableView(in_flat_table) arcpy.mapping.AddTableView(df, flat_Table) mxd.save() del mxd, df, flat_Table return