Python Trace Geometric Network

5865
3
02-24-2013 03:48 PM
ChadMarch1
New Contributor III
Not sure why they post in the Desktop/Online help that this can be run via a standalone python script because the output is a group layer which isn't a data type that can be written out by python. The only way I've been able to get this to run successfully is to use this in the Python Window in an ArcMap Session using the network data you want to trace. If someone else out there has been able to use this successfully via a standalone script, please let me know the steps involved because I'd very much appreciate it.

Here's what I have so far. Definitely not the end product, but the only way I can work it so far:

sdnNet = r'C:\SDNTest\SDN.gdb\SDN\SDN_Net'
cbs = r'C:\SDNTest\SDN.gdb\SDN\CatchBasin'
oid = 1
rows = arcpy.SearchCursor(cbs)
for row in rows:
    newNet = 'SDN_Net'+str(oid)
    flags = 'flags'+str(oid)
    exp = '"OBJECTID" = '+str(oid)
    arcpy.MakeFeatureLayer_management(cbs,flags,exp)
    arcpy.gp.TraceGeometricNetwork(sdnNet, newNet, flags, "TRACE_DOWNSTREAM")
    oid += 1


Now that this is automated, I'm going to total the flow times along the paths that I calculated from another script and add them in to the corresponding flag in the actual network. Eventually I would like to turn this into a geoprocessing task on a public side arcgis server that users can perform this on the fly by selecting the flag of their choice, but for now I'm going to calc them all in myself.
3 Replies
KennethPierce
New Contributor II
I'm trying the same thing and not getting anywhere with the stand alone script. Bump.
0 Kudos
KevinHibma
Esri Regular Contributor
While the help mentions Modelbuilder, the true is same for scripting.
In ModelBuilder, you can use the Select Data tool to extract specific layers from the group layer and the Make_Feature_Layer tool to create a feature layer from the output of the Select Data tool.


I find it easier to run it in ArcMap once to figure out what layer you want from the group, then write the Python for Select followed by either Copy Features or Make Feature Layer (depending on the goals of your task).
0 Kudos
ChadMarch1
New Contributor III
While the help mentions Modelbuilder, the true is same for scripting.


I find it easier to run it in ArcMap once to figure out what layer you want from the group, then write the Python for Select followed by either Copy Features or Make Feature Layer (depending on the goals of your task).


That's exactly what I was trying to do, but it will not work as a standalone script. Since it's output is a 'Group Layer' which is only supported within ArcMap, you can do nothing with the trace results. I've worked long and hard on this and this is what I've come to:

# import arcpy module
import arcpy, os, sys, traceback
print 'done importing'

output = r'C:\SDNTest\SDN_Trace_Output.gdb'
if not os.path.exists(output):
    path = output.rsplit('\\',1)[0]
    name = output.rsplit('\\',1)[1]
    arcpy.CreateFileGDB_management(path,name)
    print 'Output fgdb created at '+output
else:
    print 'deleting old outputs'
    arcpy.env.workspace = output
    fcList = [f for f in arcpy.ListFeatureClasses()]
    for fc in fcList:
        arcpy.Delete_management(fc)

# Set workspace
workspace = r'C:\SDNTest\SDN_Temp.gdb'
arcpy.env.workspace = workspace
arcpy.gp.overwriteOutput = True

# Global Variables

# Name of geometric network
sdnNet = 'SDN_Net'
# Feature class to be used as flags in tracing the geometric network
flags = 'CatchBasin'


# Predefined functions
def calcFlow(line,name,traceNet):
    
    # Select the feature class of the traced network
    arcpy.SelectData_management(os.path.join(workspace,'SDN',sdnNet), name)
    
    # Used to check to see how many features in each feature class are selected in the trace
    desc = arcpy.Describe(name)
    print "Number of selected features:", str(len(desc.fidSet.split(";")))

    # Make an in memory reference to the selected feature class
    arcpy.MakeFeatureLayer_management(os.path.join(workspace,name),line)

    linecount = int(arcpy.GetCount_management(line).getOutput(0))
    print linecount
 
    # Make an in memory reference to the selected feature class
    arcpy.MakeFeatureLayer_management(os.path.join(workspace,name),name)

    # Local variable to hold total of time in selected feature class
    time = 0

    # Begin cursor on selected feature class
    with arcpy.da.SearchCursor(line,["FlowTime_secs"]) as rows:
        for row in rows:
            # Get value from FlowTime_secs field
            flow = row[0]
            # If value has a value and it is not a space
            if flow != None or flow != ' ':
                time += flow

    if time != 0:
        print 'Time for {0} is {1}.'.format(line,time)
        return [time,line]

try:
    
    # Add flow time field to catch basins if not already present
    fields = [f.name for f in arcpy.ListFields(flags)]
    
    newField = ['FlowTime']
    for field in newField:
        if field not in fields:
            arcpy.AddField_management(flags,field,'FLOAT')
            print field+' added'+' to '+flags+'...'
        else:
            break

    # Start an edit session. Must provide the worksapce.
    edit = arcpy.da.Editor(workspace)
    
    # Edit session is started without an undo/redo stack for versioned data
    # (for second argument, use False for unversioned data)
    # For fgdbs, use settings below.
    edit.startEditing(False, False)
    
    # Start an edit operation
    edit.startOperation()
    
    path = 'CatchBasin'
    fields = ['OID@','FlowTime']
    with arcpy.da.UpdateCursor(path,fields) as rows:
        for row in rows:
            oid = row[0]
            newNet = 'SDN_Net'+str(oid)
            flag = 'flag'+str(oid)
            exp = '"OBJECTID" = '+str(oid)
            tempGM = "GravityMain_Temp"+str(oid)
            tempLL = "LateralLine_Temp"+str(oid)
            tempOC = "OpenChannel_Temp"+str(oid)
            tempCul = "Culvert_Temp"+str(oid)
            arcpy.MakeFeatureLayer_management(flags,flag,exp)
            arcpy.TraceGeometricNetwork_management(workspace+'\\SDN\\'+sdnNet,newNet,flag,"TRACE_DOWNSTREAM","#","#","#","#","#","NO_TRACE_ENDS","NO_TRACE_INDETERMINATE_FLOW","#","#","AS_IS","#","#","#","AS_IS")
            edgeList = [tempGM,tempLL,tempOC,tempCul]
            mergeList = []
            total = 0
            for edge in edgeList:
                results = calcFlow(edge,edge.split('_')[0],newNet)
                total += results[0]
                mergeList.append(results[1])
            
            if total != 0:
                row[1] = total
            else:
                break # Leave null
            
            path = "tracePath_"+str(oid)
            if len(mergeList) != 0:
                trace = output+'\\'+path
                arcpy.Merge_management(mergeList,trace)
                arcpy.Dissolve_management(trace,trace+'_dissolved','FlowTime_secs','#','#','DISSOLVE_LINES')
                
            delete = [tempGM,tempLL,tempOC,tempCul,flag,newNet]
            for each in delete:
                arcpy.Delete_management(each)

# Code that runs when error(s) occurs
except:
    # Aborts the edit operation.
    edit.abortOperation()
    # Stop the edit session and save the changes
    edit.stopEditing(False)
    print '\nStopped editing and no changes were saved...'

    # If error occurs, get messages and report them back to user.
    print "\n" +arcpy.GetMessages(2)
    
    # Get the python traceback object
    tb = sys.exc_info()[2]
    tbinfo = traceback.format_tb(tb)[0]
    
    # Concatenate information together concerning the error into a message string
    pymsg = "\nPYTHON ERRORS:\nTraceback info:\n" + tbinfo + "\nError Info:\n" + str(sys.exc_info()[1])
    msgs = "ArcPy ERRORS:\n" + arcpy.GetMessages(2) + "\n"
    
    # Print Python error messages for use in Python / Python Window
    print "\n" + pymsg + "\n" + msgs

# Code that executes when script is done.
finally:
    # Stop the edit operation.
    edit.stopOperation()

    # Stop the edit session and save the changes
    edit.stopEditing(True)
    print 'Script Complete...'


The script will run as a stand alone script, but it writes out empty feature classes for every trace (which obviously isn't helpful).
I've posted on the ideas site regarding this, any up-votes would be appreciated.

Guess my next step is to brush up on my C# and jump into ArcObjects...
0 Kudos