De nuevo mis líneas de escorrentía superficial. Hice un script, resolviendo el tema cuando las líneas se cruzan con otras líneas. Algo así como la generalización. Como en la imagen de abajo. El problema es que tengo que resolver 30 millones. de estas líneas. Lo he probado con 20 000 líneas y el tiempo necesario para ejecutarlo fue de 2h 30 min. Así que, aproximadamente, si lo hago con 30 millones de líneas, el tiempo de ejecución es de 5 a 6 meses.
Soy un principiante en Python.
¿Cómo puedo ajustar mi script para que se ejecute más rápido?
Estoy usando Python 2.7.3, ArcGIS 10.2 y Windows 7. Pongo mi script aquí:
'
#IMPORT MODULES, SETTINGS
# ##############################################################################
import arcpy, datetime
start = datetime.datetime.now()
arcpy.env.overwriteOutput = True
arcpy.env.workspace = r"C:\Users\david\Desktop\GAEC\TEST\TEST1.gdb"
# DEFINITION OF VARIABLES
# ##############################################################################
OL = "OL" # LAYER WITH LINES
OL_FC = "in_memory" + "\\" + "OL_FC"
OL_buff = "in_memory" + "\\" + "OL_buff"
memOne = "in_memory" + "\\" + "OL_one"
memSelect = "in_memory" + "\\" + "memSelect"
memErase = "in_memory" + "\\" + "OL_erase"
memOut = "in_memory" + "\\" + "OL_out"
memOutTemp = "in_memory" + "\\" + "OL_outTemp"
memDissolve = "in_memory" + "\\" + "memDissolve"
memSplit = "in_memory" + "\\" + "memSplit"
memUnsplit = "in_memory" + "\\" + "memUnsplit"
OL_final = "OL_final"
# TESTING AND CREATING FIELDS IN ATRB TABLE, CALCULATING LENGTH
# ##############################################################################
if len(arcpy.ListFields(OL, "LENGTH")) > 0:
print "Table already has a field LENGTH!..."
else:
arcpy.AddField_management(OL, "LENGTH", "LONG")
print "Missinf field LENGTH -> creating..."
arcpy.CalculateField_management(OL, "LENGTH", "!shape.length!", "PYTHON")
print "Calculate length for lines..."
if len(arcpy.ListFields(OL, "EDIT")) > 0:
print "Table already has a field EDIT!..."
arcpy.DeleteField_management(OL, "EDIT")
arcpy.AddField_management(OL, "EDIT", "SHORT")
else:
arcpy.AddField_management(OL, "EDIT", "SHORT")
print "Missinf field EDIT -> creating..."
arcpy.MakeFeatureLayer_management(OL, OL_FC)
rows = arcpy.SearchCursor(OL_FC)
sql = '"LENGTH" < ' + str(10)
lengths = list()
lengths0 = list()
i = 1
a = -1
# CYCLE WHICH MAKE LIST OF LENGHTS, USED FOR NUMBER OF LINES (CYCLES)
# ##############################################################################
for row in rows:
x = row.getValue("LENGTH")
lengths.append(x)
# WHOLE PROGRAMM CYCLE
# ##############################################################################
for q in (lengths):
# COUNTING LENGTHS FOR LINES, NEED TO BE UPDATED CAUSE LENGHTS ARE CHANGING
rows0 = arcpy.SearchCursor(OL_FC)
for row0 in rows0:
x0 = row0.getValue("LENGTH")
lengths0.append(x0)
lengths0.sort()
# ##########################################################################
leng = lengths0[a]
# SELECTION OF ACTUAL LONGEST LINE, STARTS FROM END OF THE LIST AND DESCENDING
sql1 = '"LENGTH" = ' + str(leng)
arcpy.SelectLayerByAttribute_management(OL_FC, "NEW_SELECTION", sql1)
# ##########################################################################
curA = arcpy.SearchCursor(OL_FC)
for rowA in curA:
# TESTING IF LINE WAS EDITED BEFORE (IF YES, FIELD 'EDIT' = 1, THEN SKIP)
test0 = rowA.getValue("EDIT")
if test0 != 1:
# ######################################################################
arcpy.MakeFeatureLayer_management(OL_FC, memOne)
print "Line exported into independently layer"
arcpy.Buffer_analysis(memOne, OL_buff, "1.3 Meters")
print "Created buffer around the line"
arcpy.SelectLayerByLocation_management(OL_FC, "INTERSECT", OL_buff, "", "NEW_SELECTION")
curAA = arcpy.UpdateCursor(OL_FC)
for w2 in curAA:
# FILLING FIELD EDIT WITH 1, SETTING FIELD LENGTH TO 0
# ##############################################################
w2.setValue("EDIT", 1)
w2.setValue("LENGTH", 0)
curAA.updateRow(w2)
arcpy.MakeFeatureLayer_management(OL_FC, memSelect)
print "Exporting affected lines"
test = int(arcpy.GetCount_management(OL_FC)[0])
# TESTING IF LINE TOUCHES AT LEAST ONE ANOTHER LINE, IF NO, SKIP
# ##################################################################
if test != 1:
arcpy.Dissolve_management(memSelect, memDissolve)
arcpy.Erase_analysis(memDissolve, OL_buff, memErase)
arcpy.SplitLine_management(memErase, memSplit)
arcpy.UnsplitLine_management(memSplit, memUnsplit)
arcpy.Merge_management([memUnsplit, memJedna], memOut)
print "Merge with original line (which buffer erases)"
arcpy.Snap_edit(memOut, [[memOne, "EDGE", "1.4 Meters"]])
print "LINES ARE SNAPPED TO ORIGINAL LINES"
# DELETING LINES THAT ARE SHORTER THAN 10 M
# ##############################################################
arcpy.MakeFeatureLayer_management(memOut, memOutTemp)
arcpy.CalculateField_management(memOutTemp, "LENGTH", "!shape.length!", "PYTHON")
arcpy.SelectLayerByAttribute_management(memOutTemp, "NEW_SELECTION", sql)
arcpy.DeleteFeatures_management(memOutTemp)
print "Lines shorter than 10 m deleted"
# FIRST CYCLE CREATES OL_finan, AFTER LINES ARE APPENDING TO FINAL
# ##############################################################
if i == 1:
arcpy.CopyFeatures_management(memOutTemp, OL_final)
else:
arcpy.Append_management(memOutTemp, OL_final)
print "New layer is append to layer before"
# LINES WITHOUT CROSSING ANY OTHER LINE
# ##################################################################
else:
for w2 in curAA:
w2.setValue("EDIT", 1)
w2.setValue("LENGTH", 0)
arcpy.Append_management(OL_FC, OL_final)
curAA.updateRow(w2)
print "Standalone line appends to final layer"
print "Imputed i, i = " + str(i) + "..."
# DELETE RAM MEMORY
# ##############################################################
arcpy.Delete_management("in_memory")
# IMPUTED TO NEXT CYCLE
# ##########################################################################
i+=1
a-=1
# DELETE ASSISTANT FILEDS
# ##############################################################
arcpy.DeleteField_management(memOutTemp, "LENGTH")
arcpy.DeleteField_management(memOutTemp, "EDIT")
# ENDING OF TIMER
# ##############################################################################
end = datetime.datetime.now()
print "\nStart: " + start.strftime("%Y-%m-%d %H:%M:%S")
print "End of script: " + end.strftime("%Y-%m-%d %H:%M:%S")
2 votos
Algo pasa con el procedimiento utilizado para calcular las líneas de flujo si permite que se crucen. ¿Por qué no utilizar un procedimiento mejor desde el principio y evitar por completo este tratamiento posterior?
3 votos
Parece que está pidiendo una revisión del código, lo que hace que su pregunta sea demasiado amplia para nuestro formato de preguntas y respuestas. Creo que debería identificar los cuellos de botella utilizando más código de sincronización y luego buscar preguntar sobre las alternativas a esos como fragmentos de código individuales.
0 votos
Calculamos las líneas del MDT para toda la república. El MDT tenía una resolución de 5x5m y se utilizó el GRASS para ello. Había muchas imprecisiones en el MDT, como lugares sin salida y ruido digital. Así que se utilizó la función Fill para generalizar el MDT y rellenar las zonas sin flujo de salida. Ahora vamos a intentar calcular las líneas de nuevo con un mejor MDT, pero creo que este tipo de errores (como el cruce y así sucesivamente - este tema es sólo sobre el cruce, pero trato de resolver muchos otros problemas) todavía aparecerá.
1 votos
Como sugirió Whuber, intente obtener resultados más limpios. No estoy seguro de cómo llegó a sus resultados por encima, pero no parece como producto directo de, por ejemplo, las herramientas de hidrología en el Arco. Las líneas no se conecta, etc. No hay nada malo con el script ya que está haciendo el trabajo, pero algunos desarrolladores de Python diría que FOR(For(for())) no es la mejor manera de hacer las cosas :) ¿Consideraste la posibilidad de operar con raster? Creo que tu área debe ser masiva, así que siempre puedes dividir el raster en mosaicos y procesarlos en modo paralelo.
1 votos
Para obtener resultados más limpios de la DEM puede intentar utilizar algo como blogs.esri.com/esri/arcgis/2013/03/05/ o lago-consulting.com/fill_sinks_plus.html . Nunca lo he probado, pero se puede dar un grito y compartir algunas experiencias.
0 votos
Es una buena idea. Tal vez me centré en hacer un modelo DEM correcto, y luego hacer líneas de ejecución de nuevo. ¿Y tienes alguna sugerencia sobre qué función / algoritmo es el mejor para hacer un MDE hidrológicamente correcto?
0 votos
Arriba tienes algunos ejemplos de relleno/sumidero. Puede que encuentres algunas pistas aquí: gis.stackexchange.com/questions/9237/
0 votos
El uso de generadores en lugar de bucles for aumentaría mucho la velocidad al reducir el consumo de memoria
0 votos
¿Qué quiere decir exactamente con generadores?