-
Notifications
You must be signed in to change notification settings - Fork 0
/
arcpy_scripts_under_ArcMap_Part2.py
305 lines (252 loc) · 10.3 KB
/
arcpy_scripts_under_ArcMap_Part2.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
import arcpy
# set multi-processing
arcpy.env.parallelProcessingFactor = "6"
# Set current workspace as the Map Document
mxd = arcpy.mapping.MapDocument("CURRENT")
# The first DataFrame would be the only one data frame
df = arcpy.mapping.ListDataFrames(mxd)[0]
def convert(data):
"""
Export each layer as JPEG image
data - name of data layer to be exported
"""
# Loop through each layer in the data frame
for layer in arcpy.mapping.ListLayers(df):
if layer.name.find(data) > -1:
# Set the layer to be visible and refresh the active view
layer.visible = True
arcpy.RefreshActiveView()
# Export the current layer as a JPEG image
arcpy.mapping.ExportToJPEG(mxd,
"D:/Research/GIFs/" + layer.name + ".jpg",
resolution=1000,
color_mode="8-BIT_PALETTE")
# Set the layer to be invisible
layer.visible = False
import os
import arcpy
# A dictionary to map month numbers to abbreviations and vice versa
month = {
"01": "Jan", "02": "Feb", "03": "Mar", "04": "Apr", "05": "May", "06": "Jun",
"07": "Jul", "08": "Aug", "09": "Sep", "10": "Oct", "11": "Nov", "12": "Dec",
}
# Change file names from number to month abbreviation or vice versa
def change_name(direction):
for file in os.listdir("./"):
target = file.split(".")[0].split("_")[-1]
for month_num, month_chr in month.items():
if direction:
if month_num == target:
os.rename(file, file.replace(target, month_chr))
else:
if month_chr == target:
os.rename(file, file.replace(target, month_num))
# Change layer names from number to month abbreviation or vice versa
def convert(direction):
for layer in arcpy.mapping.ListLayers(df):
target = layer.name.split(".")[0].split("_")[-1]
for month_num, month_chr in month.items():
if direction:
if month_num == target:
layer.name = layer.name.replace(target, month_chr)
else:
if month_chr == target:
layer.name = layer.name.replace(target, month_num)
# Sort the layers in the table of contents alphabetically
# Reference: https://gis.stackexchange.com/a/153177
def sort_layers():
# Get the current map document and the first data frame
mxd = arcpy.mapping.MapDocument("CURRENT")
df = arcpy.mapping.ListDataFrames(mxd)[0]
# Find the group layer
group_lyr = [lyr for lyr in arcpy.mapping.ListLayers(mxd) if lyr.isGroupLayer][0]
# Get a sorted list of layer names
lyr_names = sorted(lyr.name for lyr in arcpy.mapping.ListLayers(mxd))
# Move each layer to the group layer in sorted order
for name in lyr_names:
lyr = arcpy.mapping.ListLayers(mxd, name)[0]
arcpy.mapping.MoveLayer(df, group_lyr, lyr, "BEFORE")
# Remove the group layer
arcpy.mapping.RemoveLayer(df, group_lyr)
def extract_by_mask(data="landscan"):
"""
Extracts the input data by mask and saves the output files in the designated path
"""
i = 0
for l in arcpy.mapping.ListLayers(df):
if l.name.find(data) > -1:
extract = ExtractByMask(l.name, "UB_city")
extract.save("D:/Research/temp/UB_" + l.name)
i += 1
print(str(i) + " Done")
def rectify_raster(data="GSMaP"):
"""
Filters out invalid raster values and saves the filtered output in the designated path
"""
i = 0
total = len(arcpy.mapping.ListLayers(df))
for l in arcpy.mapping.ListLayers(df):
if l.name.find(data) > -1:
inRaster = l.name
inFalseRaster = l.name
whereClause = "VALUE>=18 OR VALUE<1"
out = sa.SetNull(inRaster, inFalseRaster, whereClause)
out.save("D:/Research/operation_captial_city_ger/sub_operation_LUCC/tmp/" + l.name)
i += 1
print(str(i) + "/" + str(total) + " Done")
def filter_lulc_grassland(data="LULC_Mongolia_"):
"""
Filters out all pixels except grassland, and saves the filtered output in the designated path
"""
i = 0
for l in arcpy.mapping.ListLayers(df):
if l.name.find(data) > -1:
print(l.name)
# the SetNull expression should filter out all pixels except for class 2
out = sa.SetNull(Raster(l.name) != 2, Raster(l.name))
out.save("D:/Research/temp/grassland_" + l.name[-8:-4] + ".tif")
i += 1
print(str(i) + " Done")
def convert_raster_to_polygon(data="grassland_"):
"""
Converts raster data to polygon and saves the output in the designated path
"""
i = 0
for l in arcpy.mapping.ListLayers(df):
if l.name.find(data) > -1:
arcpy.RasterToPolygon_conversion(l.name, "d:/Research/processed/" + l.name[:-4] + ".shp", "SIMPLIFY")
def extract_and_compute_area(data="grassland_20"):
"""
Extracts the input data by mask, calculates the area, and saves the output in the designated path
"""
i = 0
for l in arcpy.mapping.ListLayers(df):
if l.name.find(data) > -1:
extract = ExtractByMask("nvg_classi", l.name)
# use ZonalGeometry to calculate the area of each polygon
arcpy.sa.ZonalGeometry(extract, "Value", "AREA").save("D:/Research/temp/" + l.name + ".tif")
# use the Spatial Analyst tool ZonalStatisticsAsTable to calculate the statistics and save the output as a csv file
arcpy.sa.ZonalStatisticsAsTable(extract, "Value", "nvg_classi", "D:/Research/temp/area_" + l.name + ".dbf")
i += 1
print(str(i) + " Done")```
def linear_slope(collection):
"""
This function calculates the linear slope of the trend presented on a raster given a list of raster layers.
Parameters:
collection (list): A list of rasters' layer names.
Returns:
None: The calculated linear slope is saved in a new raster layer in the specified location.
Reference:
https://gis.stackexchange.com/questions/65787/making-linear-regression-across-multiple-raster-layers-using-arcgis-desktop/65841#65841
"""
# Calculate the length of the collection
n = len(collection)
# Initialize the result raster layer as the first raster layer in the collection
temp = 12 * Raster(collection[0])
# Iterate over the remaining raster layers in the collection
for i in range(2, n + 1):
# Calculate the coefficient for the current raster layer
coefficient = 12 * i - 6 * (n + 1)
# Multiply the coefficient by the raster layer and add to the result layer
temp += coefficient * Raster(collection[i - 1])
# Divide the result layer by the total coefficient and save the result to a new raster layer
temp /= n ** 3 - n * 1.0
names = collection[0].split("_")
temp.save("D:/Research/temp/" + names[0] + "_linear_slope.tif")
def rename_gsmap_month():
"""
Renames the GSMaP layers with month names appended to the layer names.
Inputs:
None
Outputs:
None
"""
month = {
"01": "Jan", "02": "Feb", "03": "Mar", "04": "Apr", "05": "May", "06": "Jun",
"07": "Jul", "08": "Aug", "09": "Sep", "10": "Oct", "11": "Nov", "12": "Dec",
}
for layer in arcpy.mapping.ListLayers(df):
# Pre-processing GSMAP
if layer.name.find("gsmap") > -1:
# Renaming the layer names: Month attached
file_names = layer.name.split('.')
layer.name = f"GSMaP.{file_names[2]}.{file_names[1][0:4]}.{month[file_names[1][4:]]}.tif"
def remove_GSMaP_if_corrupted():
"""
Checks the GSMaP layers for corruption and removes any corrupted layers from the dataframe.
Inputs:
None
Outputs:
None
"""
for layer in arcpy.mapping.ListLayers(df):
if layer.name.find("GSMaP") > -1:
minimum = arcpy.GetRasterProperties_management(layer.name, "MINIMUM")
if float(minimum.getOutput(0)) > 10000:
print layer.name.split('_')[-2], " ", layer.name.split('_')[-1][:3]
arcpy.mapping.RemoveLayer(df, layer)
def get_years(data):
"""
Returns the years found in the layers for the input data name.
Inputs:
data: Name of the data as string, just some keywords in layer names like "NDVI" or "GSMaP".
Outputs:
A set of years.
"""
years = set()
for layer in arcpy.mapping.ListLayers(df):
if layer.name.find(data) > -1:
year = layer.name[-12:-4]
years.add(year)
return years
def check_data_gaps(set1, set2):
"""
Checks the discrepency in time between two datasets.
Inputs:
set1: The first dataset as a string.
set2: The second dataset as a string.
Outputs:
A list of the years that exist in set1 but not in set2.
"""
y1 = get_years(set1)
y2 = get_years(set2)
if len(y1) < len(y2):
temp = y1
y1 = y2
y2 = temp
return list(y1 - y2)
def refresh_display():
"""
Refreshes the Table of Contents and the active view.
Inputs:
None
Outputs:
None
"""
arcpy.RefreshTOC()
arcpy.RefreshActiveView()
def collection_by_time(time_unit, data):
"""
Collects raster layers into yearly or monthly collections based on their time stamps.
Args:
time_unit (str): The time unit to group by. Either "year" or "month".
data (str): The name in string, just some keywords in layer names like "NDVI" or "GSMaP".
Returns:
dict: A dictionary containing yearly or monthly collections of the raster layers.
"""
# TODO: Raster aggregation by its metadata/properties should be accessed through its object properties rather
# than the names. Refactor this function later.
records = {}
for l in arcpy.mapping.ListLayers(df):
if l.name.find(data) > -1:
if time_unit == "year":
unit = l.name.split('_')[-2]
elif len(l.name) > 14:
unit = l.name.split('_')[-1][0:3]
else:
continue
if unit not in records:
records[unit] = [l.name]
else:
records[unit].append(l.name)
return records