diff --git a/README.md b/README.md index 1345f98..f80e05c 100644 --- a/README.md +++ b/README.md @@ -42,6 +42,8 @@ Check that you have installed all the required libraries used in the toolbox. Al * ```shapely``` * ```statsmodels``` (from ArcGIS version 3.2 this package is included in the base ArcGIS ```anaconda``` environment) * ```cartopy``` +* ```seaborn``` +* ```contextily``` In terms of data, this tool relies on the use of the following two files: * **Baseline** (Vector - Polyline). This is the reference line used to assess the evolution of the coastal stretch. It can be digitized manually by the user with the help of a background orthophoto, it is recommended to place the baseline **inland**. The baseline must capture the general orientation of the coast. @@ -51,7 +53,7 @@ In terms of data, this tool relies on the use of the following two files: ### Installation 0. Make sure you have cloned the base ArcGIS ```anaconda``` environment so you can install more packages. More info [here](https://pro.arcgis.com/en/pro-app/latest/arcpy/get-started/clone-an-environment.htm). -1. Install ```shapely```, ```statsmodels``` and ```cartopy``` packages if you do not have it installed yet. +1. Install the required packages listed in the *Prerequisites* section if they are not already installed. 2. Download the content in the [src](https://github.com/AlbertGallegoJimenez/shoreline-evolution-tool/tree/main/src) folder. 3. Open the Catalog Pane in ArcGIS Pro and open the downloaded Toolbox (.pyt) to see the tools.
diff --git a/requirements.txt b/requirements.txt index 4e34f5d..31403b3 100644 --- a/requirements.txt +++ b/requirements.txt @@ -2,6 +2,7 @@ arcgispro (software) 3.1 arcpy 3.1 cartopy 0.21.1 +contextily 1.5.0 matplotlib 3.6.0 numpy 1.20.1 pandas 1.4.4 diff --git a/src/Shoreline Evolution Analysis Toolbox.ComputeIntersection.pyt.xml b/src/Shoreline Evolution Analysis Toolbox.ComputeIntersection.pyt.xml new file mode 100644 index 0000000..49ddda9 --- /dev/null +++ b/src/Shoreline Evolution Analysis Toolbox.ComputeIntersection.pyt.xml @@ -0,0 +1,2 @@ + +20240129115315001.0TRUE diff --git a/src/Shoreline Evolution Analysis Toolbox.CorrectTransects.pyt.xml b/src/Shoreline Evolution Analysis Toolbox.CorrectTransects.pyt.xml new file mode 100644 index 0000000..2d9931b --- /dev/null +++ b/src/Shoreline Evolution Analysis Toolbox.CorrectTransects.pyt.xml @@ -0,0 +1,2 @@ + +20240129115826001.0TRUE diff --git a/src/Shoreline Evolution Analysis Toolbox.PerformAnalysis.pyt.xml b/src/Shoreline Evolution Analysis Toolbox.PerformAnalysis.pyt.xml new file mode 100644 index 0000000..35106ca --- /dev/null +++ b/src/Shoreline Evolution Analysis Toolbox.PerformAnalysis.pyt.xml @@ -0,0 +1,2 @@ + +20240129115304001.0TRUE diff --git a/src/Shoreline Evolution Analysis Toolbox.PlotResults.pyt.xml b/src/Shoreline Evolution Analysis Toolbox.PlotResults.pyt.xml new file mode 100644 index 0000000..4e46fb0 --- /dev/null +++ b/src/Shoreline Evolution Analysis Toolbox.PlotResults.pyt.xml @@ -0,0 +1,2 @@ + +20240129095749001.0TRUE diff --git a/src/Shoreline Evolution Analysis Toolbox.pyt b/src/Shoreline Evolution Analysis Toolbox.pyt index bcccdf5..37172c5 100644 --- a/src/Shoreline Evolution Analysis Toolbox.pyt +++ b/src/Shoreline Evolution Analysis Toolbox.pyt @@ -1,22 +1,23 @@ import arcpy -# 1. Generate Transects Along Baseline +# 1a. Generate Transects Along Baseline from tools.generateTransects import GenerateTransects -# 2. Correct Transects +# 1b. Correct Transects from tools.correctTransects import CorrectTransects -# 3. Compute Intersections +# 2. Compute Intersections from tools.computeIntersections import ComputeIntersection -# 4. Perform the Shoreline Evolution Analysis +# 3. Perform the Shoreline Evolution Analysis from tools.performAnalysis import PerformAnalysis -# 5. Plot The Analysis Results +# 4. Plot The Analysis Results from tools.plotResults import PlotResults class Toolbox(object): def __init__(self): # List of tool classes associated with this toolbox - self.tools = [GenerateTransects, CorrectTransects, ComputeIntersection, PerformAnalysis, PlotResults] + self.tools = [GenerateTransects, CorrectTransects, ComputeIntersection, + PerformAnalysis, PlotResults] diff --git a/src/Shoreline Evolution Analysis Toolbox.pyt.xml b/src/Shoreline Evolution Analysis Toolbox.pyt.xml index b05ffc7..8436fbc 100644 --- a/src/Shoreline Evolution Analysis Toolbox.pyt.xml +++ b/src/Shoreline Evolution Analysis Toolbox.pyt.xml @@ -1,2 +1,2 @@ -20231121191525001.0TRUE20231121191525c:\program files\arcgis\pro\Resources\Help\gpShoreline Evolution Analysis ToolboxArcToolbox Toolbox +20231121191525001.0TRUE20240129115229c:\program files\arcgis\pro\Resources\Help\gpShoreline Evolution Analysis ToolboxArcToolbox Toolbox diff --git a/src/tools/__pycache__/computeIntersections.cpython-39.pyc b/src/tools/__pycache__/computeIntersections.cpython-39.pyc index ab4b4c3..856e01f 100644 Binary files a/src/tools/__pycache__/computeIntersections.cpython-39.pyc and b/src/tools/__pycache__/computeIntersections.cpython-39.pyc differ diff --git a/src/tools/__pycache__/correctTransects.cpython-39.pyc b/src/tools/__pycache__/correctTransects.cpython-39.pyc index 79bc4f5..4c33438 100644 Binary files a/src/tools/__pycache__/correctTransects.cpython-39.pyc and b/src/tools/__pycache__/correctTransects.cpython-39.pyc differ diff --git a/src/tools/__pycache__/generateTransects.cpython-39.pyc b/src/tools/__pycache__/generateTransects.cpython-39.pyc index be93296..f5d0023 100644 Binary files a/src/tools/__pycache__/generateTransects.cpython-39.pyc and b/src/tools/__pycache__/generateTransects.cpython-39.pyc differ diff --git a/src/tools/__pycache__/performAnalysis.cpython-39.pyc b/src/tools/__pycache__/performAnalysis.cpython-39.pyc index cada5f0..37ad74e 100644 Binary files a/src/tools/__pycache__/performAnalysis.cpython-39.pyc and b/src/tools/__pycache__/performAnalysis.cpython-39.pyc differ diff --git a/src/tools/__pycache__/plotResults.cpython-39.pyc b/src/tools/__pycache__/plotResults.cpython-39.pyc new file mode 100644 index 0000000..559a882 Binary files /dev/null and b/src/tools/__pycache__/plotResults.cpython-39.pyc differ diff --git a/src/tools/computeIntersections.py b/src/tools/computeIntersections.py index 9f14178..3bfd39d 100644 --- a/src/tools/computeIntersections.py +++ b/src/tools/computeIntersections.py @@ -29,7 +29,7 @@ def getParameterInfo(self): shoreline_param.filter.list = ['Polyline'] shore_id_param = arcpy.Parameter( - displayName="Name of ID Shoreline Field", + displayName="Name of Shorelines ID Field", name="id_shore", datatype="Field", parameterType="Required", diff --git a/src/tools/performAnalysis.py b/src/tools/performAnalysis.py index 432ad2e..adfdb8b 100644 --- a/src/tools/performAnalysis.py +++ b/src/tools/performAnalysis.py @@ -7,7 +7,7 @@ class PerformAnalysis(object): def __init__(self): """Define the tool (tool name is the name of the class).""" self.label = "3. Perform The Analysis" - self.description = "" + self.description = "Perform the Linear Regression Analysis on each transect." self.canRunInBackground = False def getParameterInfo(self): diff --git a/src/tools/plotResults.py b/src/tools/plotResults.py index b695d67..7652a05 100644 --- a/src/tools/plotResults.py +++ b/src/tools/plotResults.py @@ -4,8 +4,8 @@ class PlotResults(object): def __init__(self): """Define the tool (tool name is the name of the class).""" - self.label = "5. Plot The Analysis Results" - self.description = "" + self.label = "4. Plot The Analysis Results" + self.description = "Plot some figures to see the analysis results." self.canRunInBackground = False def getParameterInfo(self): diff --git a/src/tools/utils/__pycache__/intersect_lines.cpython-39.pyc b/src/tools/utils/__pycache__/intersect_lines.cpython-39.pyc index 11a22c9..c951706 100644 Binary files a/src/tools/utils/__pycache__/intersect_lines.cpython-39.pyc and b/src/tools/utils/__pycache__/intersect_lines.cpython-39.pyc differ diff --git a/src/tools/utils/__pycache__/plot_results.cpython-39.pyc b/src/tools/utils/__pycache__/plot_results.cpython-39.pyc index f0f12c5..b4917fa 100644 Binary files a/src/tools/utils/__pycache__/plot_results.cpython-39.pyc and b/src/tools/utils/__pycache__/plot_results.cpython-39.pyc differ diff --git a/src/tools/utils/__pycache__/shoreline_evolution.cpython-39.pyc b/src/tools/utils/__pycache__/shoreline_evolution.cpython-39.pyc index e230549..35ba9ae 100644 Binary files a/src/tools/utils/__pycache__/shoreline_evolution.cpython-39.pyc and b/src/tools/utils/__pycache__/shoreline_evolution.cpython-39.pyc differ diff --git a/src/tools/utils/__pycache__/transect_processor.cpython-39.pyc b/src/tools/utils/__pycache__/transect_processor.cpython-39.pyc index 3dbc1ea..1c2eca8 100644 Binary files a/src/tools/utils/__pycache__/transect_processor.cpython-39.pyc and b/src/tools/utils/__pycache__/transect_processor.cpython-39.pyc differ diff --git a/src/tools/utils/plot_results.py b/src/tools/utils/plot_results.py index 4b60cd1..fb3f863 100644 --- a/src/tools/utils/plot_results.py +++ b/src/tools/utils/plot_results.py @@ -5,6 +5,7 @@ import pandas as pd import os import re +import contextily as cx import cartopy.crs as ccrs from tools.utils.intersect_lines import * from matplotlib.colors import Normalize, TwoSlopeNorm @@ -118,6 +119,32 @@ def _set_map_configuration(self, metric): return cmap, norm, extend_cbar + def _set_xylim(self, list_shapely): + """ + Private method to set the x and y limits for plotting LRR, SCE and NSM. + + Parameters: + list_shapely (dict): Dictionary of transect_id (key) and transects geometry in Shapely format (value). + + Returns: + x_lim (list): List with the starting and ending x limits. + y_lim (list): List with the starting and ending y limits. + """ + # Get a list with all longitudes and latitudes values for all vertices of each transect + lons = [x for t in list_shapely.values() for x in t.xy[0]] + lats = [y for t in list_shapely.values() for y in t.xy[1]] + + # Calculate the offset for each axis + x_offset = abs(max(lons) - min(lons)) / 10 + y_offset = abs(max(lats) - min(lats)) / 10 + + # Set the x and y limits + x_lim = [min(lons) - x_offset, max(lons) + x_offset] + y_lim = [min(lats) - y_offset, max(lats) + y_offset] + + return x_lim, y_lim + + # ===== FROM HERE, ALL THE FUNCTIONS TO CREATE THE PLOTS ARE DEFINED ===== def plot_spatial_evolution(self): @@ -282,7 +309,8 @@ def plot_map(self, metric): ls = '--' # Plot the transect line - ax.plot(*t.xy, + x, y = t.xy + ax.plot(x, y, color=color, transform=proj, lw=3, @@ -308,9 +336,15 @@ def plot_map(self, metric): ax.set_title('Net Shoreline Movement, NSM (m)', y=1.05) # Set limits, labels, legend, and save the figure - lons = [x for t in self.transects_shapely.values() for x in t.xy[0]] # Extract the longitudes for plotting purposes (Sometimes the plot is centered to the west and a blank space is left to the east of the study area) - ax.set_xlim([ax.get_xlim()[0], max(lons)]) + try: + cx.add_basemap(ax, crs=proj, source=cx.providers.Esri.WorldImagery, alpha=.7, attribution_size=6) + except: + arcpy.AddMessage("Basemap could not be added to the {}_transect.png map.".format(metric)) + + x_lim, y_lim = self._set_xylim(self.transects_shapely) + ax.set_xlim(x_lim) + ax.set_ylim(y_lim) ax.set_xlabel('Eastings (m)') ax.set_ylabel('Northings (m)') - ax.legend(handles=[legend_entry], fontsize='small') + ax.legend(handles=[legend_entry], fontsize='small', loc='best') fig.savefig(os.path.join(self.out_dir, '{0}_transects.png'.format(metric)), dpi=300, bbox_inches='tight') diff --git a/src/tools/utils/transect_processor.py b/src/tools/utils/transect_processor.py index ae487d1..48016ad 100644 --- a/src/tools/utils/transect_processor.py +++ b/src/tools/utils/transect_processor.py @@ -76,5 +76,3 @@ def rotatepoint(point, pivotpoint, angle): qx = ox + math.cos(angle_rad) * (px - ox) - math.sin(angle_rad) * (py - oy) qy = oy + math.sin(angle_rad) * (px - ox) + math.cos(angle_rad) * (py - oy) return arcpy.Point(qx, qy) - -