-
Notifications
You must be signed in to change notification settings - Fork 2
/
Merge_HEL_Soil_by_CLU.py
341 lines (275 loc) · 14.5 KB
/
Merge_HEL_Soil_by_CLU.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
# ==========================================================================================
# Name: Merge HEL Soil by CLU
#
# Author(s): Chris.Morse
# State GIS Specialist
# e-mail: [email protected]
# phone: 317.295.5849
# Adolfo.Diaz
# Region 10 GIS Specialist
# e-mail: [email protected]
# phone: 608.662.4422 ext. 216
# Contributor: Kevin Godsey
# Soil Scientist
# e-mail: [email protected]
# phone: 608.662.4422 ext. 190
# Contributor: Christiane Roy
# MN Area GIS Specialist
# e-mail: [email protected]
# phone: 507.405.3580
# Maintenance Point of Contact: T.B.D.
## ===================================================================================
def AddMsgAndPrint(msg, severity=0):
# prints message to screen if run as a python script
# Adds tool message to the geoprocessor
#
#Split the message on \n first, so that if it's multiple lines, a GPMessage will be added for each line
try:
#print msg
#for string in msg.split('\n'):
#Add a geoprocessing message (in case this is run as a tool)
if severity == 0:
arcpy.AddMessage(msg)
elif severity == 1:
arcpy.AddWarning(msg)
elif severity == 2:
arcpy.AddError(msg)
except:
pass
## ===================================================================================
def errorMsg():
# Print traceback exceptions. If sys.exit was trapped by default exception then
# ignore traceback message.
try:
exc_type, exc_value, exc_traceback = sys.exc_info()
theMsg = "\t" + traceback.format_exception(exc_type, exc_value, exc_traceback)[1] + "\n\t" + traceback.format_exception(exc_type, exc_value, exc_traceback)[-1]
if theMsg.find("sys.exit") > -1:
AddMsgAndPrint("\n\n")
pass
else:
AddMsgAndPrint(theMsg,2)
except:
AddMsgAndPrint("Unhandled error in errorMsg method", 2)
pass
## ===================================================================================
def setScratchWorkspace():
""" This function will set the scratchWorkspace for the interim of the execution
of this tool. The scratchWorkspace is used to set the scratchGDB which is
where all of the temporary files will be written to. The path of the user-defined
scratchWorkspace will be compared to existing paths from the user's system
variables. If there is any overlap in directories the scratchWorkspace will
be set to C:\TEMP, assuming C:\ is the system drive. If all else fails then
the packageWorkspace Environment will be set as the scratchWorkspace. This
function returns the scratchGDB environment which is set upon setting the scratchWorkspace"""
try:
AddMsgAndPrint("\nSetting Scratch Workspace")
scratchWK = arcpy.env.scratchWorkspace
# -----------------------------------------------
# Scratch Workspace is defined by user or default is set
if scratchWK is not None:
# dictionary of system environmental variables
envVariables = os.environ
# get the root system drive
if envVariables.has_key('SYSTEMDRIVE'):
sysDrive = envVariables['SYSTEMDRIVE']
else:
sysDrive = None
varsToSearch = ['ESRI_OS_DATADIR_LOCAL_DONOTUSE','ESRI_OS_DIR_DONOTUSE','ESRI_OS_DATADIR_MYDOCUMENTS_DONOTUSE',
'ESRI_OS_DATADIR_ROAMING_DONOTUSE','TEMP','LOCALAPPDATA','PROGRAMW6432','COMMONPROGRAMFILES','APPDATA',
'USERPROFILE','PUBLIC','SYSTEMROOT','PROGRAMFILES','COMMONPROGRAMFILES(X86)','ALLUSERSPROFILE']
""" This is a printout of my system environmmental variables - Windows 7
-----------------------------------------------------------------------------------------
ESRI_OS_DATADIR_LOCAL_DONOTUSE C:\Users\adolfo.diaz\AppData\Local\
ESRI_OS_DIR_DONOTUSE C:\Users\ADOLFO~1.DIA\AppData\Local\Temp\6\arc3765\
ESRI_OS_DATADIR_MYDOCUMENTS_DONOTUSE C:\Users\adolfo.diaz\Documents\
ESRI_OS_DATADIR_COMMON_DONOTUSE C:\ProgramData\
ESRI_OS_DATADIR_ROAMING_DONOTUSE C:\Users\adolfo.diaz\AppData\Roaming\
TEMP C:\Users\ADOLFO~1.DIA\AppData\Local\Temp\6\arc3765\
LOCALAPPDATA C:\Users\adolfo.diaz\AppData\Local
PROGRAMW6432 C:\Program Files
COMMONPROGRAMFILES : C:\Program Files (x86)\Common Files
APPDATA C:\Users\adolfo.diaz\AppData\Roaming
USERPROFILE C:\Users\adolfo.diaz
PUBLIC C:\Users\Public
SYSTEMROOT : C:\Windows
PROGRAMFILES : C:\Program Files (x86)
COMMONPROGRAMFILES(X86) : C:\Program Files (x86)\Common Files
ALLUSERSPROFILE : C:\ProgramData
------------------------------------------------------------------------------------------"""
bSetTempWorkSpace = False
""" Iterate through each Environmental variable; If the variable is within the 'varsToSearch' list
list above then check their value against the user-set scratch workspace. If they have anything
in common then switch the workspace to something local """
for var in envVariables:
if not var in varsToSearch:
continue
# make a list from the scratch and environmental paths
varValueList = (envVariables[var].lower()).split(os.sep) # ['C:', 'Users', 'adolfo.diaz', 'AppData', 'Local']
scratchWSList = (scratchWK.lower()).split(os.sep) # [u'C:', u'Users', u'adolfo.diaz', u'Documents', u'ArcGIS', u'Default.gdb', u'']
# remove any blanks items from lists
if '' in varValueList: varValueList.remove('')
if '' in scratchWSList: scratchWSList.remove('')
# First element is the drive letter; remove it if they are
# the same otherwise review the next variable.
if varValueList[0] == scratchWSList[0]:
scratchWSList.remove(scratchWSList[0])
varValueList.remove(varValueList[0])
# obtain a similarity ratio between the 2 lists above
#sM = SequenceMatcher(None,varValueList,scratchWSList)
# Compare the values of 2 lists; order is significant
common = [i for i, j in zip(varValueList, scratchWSList) if i == j]
if len(common) > 0:
bSetTempWorkSpace = True
break
# The current scratch workspace shares 1 or more directory paths with the
# system env variables. Create a temp folder at root
if bSetTempWorkSpace:
AddMsgAndPrint("\tCurrent Workspace: " + scratchWK,0)
if sysDrive:
tempFolder = sysDrive + os.sep + "TEMP"
if not os.path.exists(tempFolder):
os.makedirs(tempFolder,mode=777)
arcpy.env.scratchWorkspace = tempFolder
AddMsgAndPrint("\tTemporarily setting scratch workspace to: " + arcpy.env.scratchGDB,1)
else:
packageWS = [f for f in arcpy.ListEnvironments() if f=='packageWorkspace']
if arcpy.env[packageWS[0]]:
arcpy.env.scratchWorkspace = arcpy.env[packageWS[0]]
AddMsgAndPrint("\tTemporarily setting scratch workspace to: " + arcpy.env.scratchGDB,1)
else:
AddMsgAndPrint("\tCould not set any scratch workspace",2)
return False
# user-set workspace does not violate system paths; Check for read/write
# permissions; if write permissions are denied then set workspace to TEMP folder
else:
arcpy.env.scratchWorkspace = scratchWK
if arcpy.env.scratchGDB == None:
AddMsgAndPrint("\tCurrent scratch workspace: " + scratchWK + " is READ only!",0)
if sysDrive:
tempFolder = sysDrive + os.sep + "TEMP"
if not os.path.exists(tempFolder):
os.makedirs(tempFolder,mode=777)
arcpy.env.scratchWorkspace = tempFolder
AddMsgAndPrint("\tTemporarily setting scratch workspace to: " + arcpy.env.scratchGDB,1)
else:
packageWS = [f for f in arcpy.ListEnvironments() if f=='packageWorkspace']
if arcpy.env[packageWS[0]]:
arcpy.env.scratchWorkspace = arcpy.env[packageWS[0]]
AddMsgAndPrint("\tTemporarily setting scratch workspace to: " + arcpy.env.scratchGDB,1)
else:
AddMsgAndPrint("\tCould not set any scratch workspace",2)
return False
else:
AddMsgAndPrint("\tUser-defined scratch workspace is set to: " + arcpy.env.scratchGDB,0)
# No workspace set (Very odd that it would go in here unless running directly from python)
else:
AddMsgAndPrint("\tNo user-defined scratch workspace ",0)
sysDrive = os.environ['SYSTEMDRIVE']
if sysDrive:
tempFolder = sysDrive + os.sep + "TEMP"
if not os.path.exists(tempFolder):
os.makedirs(tempFolder,mode=777)
arcpy.env.scratchWorkspace = tempFolder
AddMsgAndPrint("\tTemporarily setting scratch workspace to: " + arcpy.env.scratchGDB,1)
else:
packageWS = [f for f in arcpy.ListEnvironments() if f=='packageWorkspace']
if arcpy.env[packageWS[0]]:
arcpy.env.scratchWorkspace = arcpy.env[packageWS[0]]
AddMsgAndPrint("\tTemporarily setting scratch workspace to: " + arcpy.env.scratchGDB,1)
else:
AddMsgAndPrint("\tCould not set scratchWorkspace. Not even to default!",2)
return False
arcpy.Compact_management(arcpy.env.scratchGDB)
return arcpy.env.scratchGDB
except:
# All Failed; set workspace to packageWorkspace environment
try:
packageWS = [f for f in arcpy.ListEnvironments() if f=='packageWorkspace']
if arcpy.env[packageWS[0]]:
arcpy.env.scratchWorkspace = arcpy.env[packageWS[0]]
arcpy.Compact_management(arcpy.env.scratchGDB)
return arcpy.env.scratchGDB
else:
AddMsgAndPrint("\tCould not set scratchWorkspace. Not even to default!",2)
return False
except:
errorMsg()
return False
## =============================================== Main Body ====================================================
import arcpy, sys, os, traceback
# Set overwrite
arcpy.env.overwriteOutput = True
try:
# Define and set the scratch workspace
scratchWS = setScratchWorkspace()
arcpy.env.scratchWorkspace = scratchWS
if not scratchWS:
arcpy.AddError("\n Could not set scratch workspace... Exiting!\n")
sys.exit()
# Inputs
arcpy.AddMessage("\nExaming inputs...")
source_clu = arcpy.GetParameterAsText(0)
source_soils = arcpy.GetParameterAsText(1).split(";")
datasets = len(source_soils)
# Make sure at least 2 datasets to be merged were entered
if datasets < 2:
arcpy.AddError("\n Only one input soil layer selected. If you need multiple layers, please run again and select multiple soil layers... Exiting!\n")
sys.exit()
# List of valid HEL soil layer schema for the tool (in lower case for comparative purposes)
schema = ["areasymbol", "spatialver", "musym", "muname", "muhelcl", "t", "k", "r"]
# Check the input soil layers to make sure they contain fields with the same field names
x = 0
for layer in source_soils:
field_names = [f.name.lower() for f in arcpy.ListFields(source_soils[x])]
for s in schema:
if s not in field_names:
arcpy.AddMessage("\n The layer " + str(source_soils[x]) + " is missing field " + str(s) + "... Exiting!\n")
sys.exit()
x += 1
del x
arcpy.AddMessage("Done!\n")
# Variables
temp_soil = os.path.join(os.path.dirname(sys.argv[0]), "HEL.mdb" + os.sep + "temp_soil")
merged_soil = os.path.join(os.path.dirname(sys.argv[0]), "HEL.mdb" + os.sep + "Merged_HEL_Soil")
# Clip out the soils that were entered
arcpy.AddMessage("\nClipping inputs...")
x = 0
del_list = []
# Start an empty list that will be used to clean up the temporary clips after merge is done
while x < datasets:
current_soil = source_soils[x].replace("'", "")
out_clip = temp_soil + "_" + str(x)
try:
arcpy.Clip_analysis(current_soil, source_clu, out_clip)
except:
arcpy.AddError("\n The input fields may not cover the input soil layers. Clip & Merge failed...Exiting!\n")
sys.exit()
if x == 0:
# Start list of layers to merge
merge_list = "" + str(out_clip) + ""
else:
# Append to list
merge_list = merge_list + ";" + str(out_clip)
# Append name of temporary output to the list of temp soil layers to be deleted
del_list.append(str(out_clip))
x += 1
del x
arcpy.AddMessage("Done!\n")
# Merge Clipped Datasets
arcpy.AddMessage("\nMerging inputs...")
if arcpy.Exists(merged_soil):
arcpy.Delete_management(merged_soil)
arcpy.Merge_management(merge_list, merged_soil, "")
arcpy.AddMessage("Done!\n")
# Clean-up
# Delete temporary soils
arcpy.AddMessage("\nCleaning up...")
for lyr in del_list:
arcpy.Delete_management(lyr)
arcpy.AddMessage("Done!\n")
# Add resulting data to map
arcpy.AddMessage("\nAdding layer to map...")
arcpy.SetParameterAsText(2, merged_soil)
arcpy.AddMessage("Done!\n")
except:
pass