-
Notifications
You must be signed in to change notification settings - Fork 3
/
rebuild_map_service_tiles_in_updated_areas.py
154 lines (133 loc) · 6.92 KB
/
rebuild_map_service_tiles_in_updated_areas.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
# ---------------------------------------------------------------------------------------------------------------
# Name: Rebuild Cached Map Service Tiles in Updated Areas
#
# Purpose: Rebuilds tiles for a cached map service in areas that have been updated in a reference layer within a time period specified relative to the day the script runs.
#
# Author: Patrick McKinney
#
# Created: 9/2/2020
#
# Updated: 9/21/2022
# -------------------------------------------------------------------------------------------------------------------
# Import system modules
import arcpy
import sys
import time
from datetime import date
from datetime import timedelta
from os import path
from os import environ
try:
# get timestamp for starting processing
start_time = time.perf_counter()
# Name of service
service_name = 'Name of Service'
# date for the day the script is run on
date_today = date.today()
# Date formatted as month-day-year (1-1-2017)
formatted_date_today = date_today.strftime('%m-%d-%Y')
# date for how many days back you want to check for changes in a dataset
# change 8 to how many days back you want to check for changes
date_ago = date_today - timedelta(days=8)
# variable to store messages for log file. Messages written in finally statement at end of script
log_message = ''
# Create text file for logging results of script
log_file = path.join(r'C:\GIS\Logs', f'Rebuild Map Tiles Report {formatted_date_today}.txt')
# layer you want to check for changes in
# there needs to be a Date field that captures when edits occur
# ideally this would be an Editor Tracking field
# see https://pro.arcgis.com/en/pro-app/tool-reference/data-management/enable-editor-tracking.htm
reference_layer = r'C:\GIS\Data\reference_layer.shp'
# make feature layer so you can use the select by attributes function
ref_lyr_file = arcpy.MakeFeatureLayer_management(
reference_layer, 'My_Layer')
# SQL query clause
# the format for queries using date fields changes based upon your data's format
# read the docs > https://pro.arcgis.com/en/pro-app/help/mapping/navigation/sql-reference-for-elements-used-in-query-expressions.htm
# replace "last_edited_date" with whatever field represents the date last modiefied
where_clause = f"""last_edited_date >= date '{date_ago}' AND last_edited_date <= date '{date_today}'"""
# select features from reference layer that have been modified within your specified date range (i.e., within last week)
arcpy.SelectLayerByAttribute_management(
ref_lyr_file, 'NEW_SELECTION', where_clause)
# get count of features
count_selected_reference = arcpy.GetCount_management(ref_lyr_file)[0]
# verify records have been selected; if not, add message and exit script
if count_selected_reference == 0:
# add message
log_message += f'No "Reference Layer" records have been modified between {date_ago} and {date_today}\n'
# exit
sys.exit()
# grid layer that covers your area of interest (city, county, state, etc)
cache_grid_tiles = r'C:\GIS\Data\grids_layer.shp'
# make feature layer so you can select by location
cache_grid_tiles_lyr = arcpy.MakeFeatureLayer_management(
cache_grid_tiles, 'Grid_Tiles')
# select tile grids that intersect selected records from reference layer
arcpy.SelectLayerByLocation_management(
cache_grid_tiles_lyr, 'INTERSECT', ref_lyr_file)
# get count of features
count_selected_grids = arcpy.GetCount_management(cache_grid_tiles_lyr)[0]
# verify records have been selected; if not, add message and exit script
if count_selected_grids == 0:
# add message
log_message += f'No "Grid" features intersect "Reference Layer" records that have been modified between {date_ago} and {date_today}\n'
# exit
sys.exit()
# use selected records from grid tiles as area of interest for rebuilding cached map service tiles
area_of_interest_lyr = r'memory\selected_grids'
# copy selected features from grid layer to in memory
arcpy.CopyFeatures_management(cache_grid_tiles_lyr, area_of_interest_lyr)
# add message
log_message += f'Added selected "Grid" features to {area_of_interest_lyr}\n'
log_message += '\nSelected grids:\n\n'
# loop through Grid layer and list what records have been selected
# you can then use these as areas to check to verify your tiles have rebuilt the data
# replace 'LabelField' with a field in your Grid layer
with arcpy.da.SearchCursor(area_of_interest_lyr, 'LabelField') as cursor:
for row in cursor:
log_message += f'\t{row[0]}\n'
# create feature set object
# see https://pro.arcgis.com/en/pro-app/arcpy/classes/featureset.htm
feature_set = arcpy.FeatureSet()
# load selected records from Grid layer into feature set
feature_set.load(area_of_interest_lyr)
# ArcGIS Online or Portal URL
portal = ""
# user name of owner of item (admin users may be able to overwrite)
# create environment variable to store username; pass that variable name into get() method
user = environ.get('user_name_environment_variable')
# password of owner of item (admin users may be able to overwrite)
# create environment variable to store pasword; pass that variable name into get() method
password = environ.get('password_environment_variable')
# sign-in to Portal or ArcGIS Online
arcpy.SignInToPortal(portal, user, password)
# geoprocessing - rebuild map service cache tiles
# see https://pro.arcgis.com/en/pro-app/tool-reference/server/manage-map-server-cache-tiles.htm
# manually rebuilding the tiles for the service and copying the geoprocessing tool as a Python snippet
# can be used to get set this function
arcpy.server.ManageMapServerCacheTiles('service url', [
'scales to rebuild'], 'RECREATE_ALL_TILES', -1, feature_set, wait_for_job_completion='WAIT')
# get time stamp for end of processing
finish_time = time.perf_counter()
# time of processing in seconds
elapsed_time = finish_time - start_time
# time in minutes
elapsed_time_minutes = round((elapsed_time / 60), 2)
# time in hours
elapsed_time_hours = round((elapsed_time_minutes / 60), 2)
log_message += f'\n\nRebuilt cached tiles for {service_name} in {elapsed_time_hours}-hours on {formatted_date_today}\n'
# If an error occurs running geoprocessing tool(s) capture error and write message
# handle error outside of Python system
except (Exception, EnvironmentError) as e:
tbE = sys.exc_info()[2]
# Write the line number the error occured to the log file
log_message += f'\nFailed at Line {tbE.tb_lineno}\n'
# Write the error message to the log file
log_message += f'Error: {str(e)}'
finally:
# write message to log file
try:
with open(log_file, 'w') as f:
f.write(str(log_message))
except:
pass