shapeography 0.1__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- shapeography-0.1/LICENSE +21 -0
- shapeography-0.1/PKG-INFO +85 -0
- shapeography-0.1/README.md +66 -0
- shapeography-0.1/pyproject.toml +33 -0
- shapeography-0.1/setup.cfg +4 -0
- shapeography-0.1/src/shapeography/__init__.py +12 -0
- shapeography-0.1/src/shapeography/client/__init__.py +1 -0
- shapeography-0.1/src/shapeography/client/client.py +154 -0
- shapeography-0.1/src/shapeography/utils/__init__.py +2 -0
- shapeography-0.1/src/shapeography/utils/geometry.py +92 -0
- shapeography-0.1/src/shapeography/utils/unzip.py +127 -0
- shapeography-0.1/src/shapeography.egg-info/PKG-INFO +85 -0
- shapeography-0.1/src/shapeography.egg-info/SOURCES.txt +14 -0
- shapeography-0.1/src/shapeography.egg-info/dependency_links.txt +1 -0
- shapeography-0.1/src/shapeography.egg-info/requires.txt +3 -0
- shapeography-0.1/src/shapeography.egg-info/top_level.txt +1 -0
shapeography-0.1/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) Eric J. Drewitz 2026
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: shapeography
|
|
3
|
+
Version: 0.1
|
|
4
|
+
Summary: A Python library that both a client that downloads various shapefiles and GEOJSON files from the web and processes these geometry files. Users can also process locally hosted shapefiles and GEOJSON files. Also works for those on VPN/PROXY connections.
|
|
5
|
+
Author: Eric J. Drewitz
|
|
6
|
+
Project-URL: Documentation, https://github.com/edrewitz/shapeography?tab=readme-ov-file#shapeography
|
|
7
|
+
Project-URL: Repository, https://github.com/edrewitz/shapeography/tree/main
|
|
8
|
+
Keywords: cartography,geography
|
|
9
|
+
Classifier: Programming Language :: Python
|
|
10
|
+
Classifier: Topic :: Scientific/Engineering
|
|
11
|
+
Classifier: Operating System :: OS Independent
|
|
12
|
+
Requires-Python: >=3.10
|
|
13
|
+
Description-Content-Type: text/markdown
|
|
14
|
+
License-File: LICENSE
|
|
15
|
+
Requires-Dist: cartopy>=0.24.0
|
|
16
|
+
Requires-Dist: geopandas>=1.1.0
|
|
17
|
+
Requires-Dist: requests>=2.32.4
|
|
18
|
+
Dynamic: license-file
|
|
19
|
+
|
|
20
|
+
# shapeography
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
<img src="https://github.com/edrewitz/shapeography/blob/main/Thumbnails/86506Livingston-Rev-Base.jpg?raw=true" width="200" alt="Alt text" /> <img src="https://github.com/edrewitz/WxData/blob/1be590e9a16033974a592d8cf99f3cd521f95e0b/icons/python%20logo.png?raw=true" width="200" alt="Alt text" />
|
|
25
|
+
|
|
26
|
+
**(C) Eric J. Drewitz 2026**
|
|
27
|
+
|
|
28
|
+
An open-source Python package that manages shapefiles and GEOJSON files.
|
|
29
|
+
|
|
30
|
+
***Jupyter Lab Examples***
|
|
31
|
+
|
|
32
|
+
1) [Downloading and Plotting the National Weather Service Public Forecast Zones](https://github.com/edrewitz/shapeography-Jupyter-Lab-Examples/blob/main/nws_public_zones.ipynb)
|
|
33
|
+
2) [Downloading and Plotting the NOAA/NWS Climate Prediction Center 6-10 Day Probabilistic Precipitation Outlook](https://github.com/edrewitz/shapeography-Jupyter-Lab-Examples/blob/main/cpc_outlook.ipynb)
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
***Client Module***
|
|
37
|
+
|
|
38
|
+
[Documentation](https://github.com/edrewitz/shapeography/blob/main/Documentation/client.md#client-module)
|
|
39
|
+
|
|
40
|
+
The `client` module hosts the client function `get_shapefiles()` that downloads shapefiles/GEOJSON file from a user-defined URL address into a folder locally on your PC.
|
|
41
|
+
|
|
42
|
+
The user must specify the path and filename and the file is saved to {path}/{filename}.
|
|
43
|
+
|
|
44
|
+
This client is also helpful for those using shapeography in automated scripts. If the user keeps the optional argument `refresh=True` - The directory hosting the shapefiles/GEOJSON file will be refreshed as the old files will be deleted and new files downloaded. This can be helpful in automation due to periodic shapefile updates on the server-side as it ensures that the user will always have the most recent and up to date shapefiles/GEOJSON file.
|
|
45
|
+
|
|
46
|
+
This client supports users on a VPN/PROXY connection.
|
|
47
|
+
|
|
48
|
+
**Proxy Example**
|
|
49
|
+
|
|
50
|
+
proxies=None ---> proxies={
|
|
51
|
+
'http':'address:port',
|
|
52
|
+
'https':'address:port'
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
shapeography.client.get_shapefiles(url, path, filename, proxies=proxies)
|
|
56
|
+
|
|
57
|
+
***Unzip Module***
|
|
58
|
+
|
|
59
|
+
[Documentation](https://github.com/edrewitz/shapeography/blob/main/Documentation/unzip.md#unzip-module)
|
|
60
|
+
|
|
61
|
+
The `unzip` module hosts the function that unzips the shapefiles/GEOJSON file if the file(s) need to be unzipped.
|
|
62
|
+
|
|
63
|
+
In nearly all cases, shapefile components are within a zipfile server-side so needing to unzip is very common.
|
|
64
|
+
|
|
65
|
+
The function `extract_files()` unzips the shapefiles/GEOJSON into a user-specified extraction folder that is automatically generated.
|
|
66
|
+
|
|
67
|
+
Supports the following file extentions: .zip, .gz, .tar, .tar.gz
|
|
68
|
+
|
|
69
|
+
***Geometry Module***
|
|
70
|
+
|
|
71
|
+
[Documentation](https://github.com/edrewitz/shapeography/blob/main/Documentation/geometry.md#geometry-module)
|
|
72
|
+
|
|
73
|
+
The `geometry` module hosts functions that extract data from these shapefiles/GEOJSON file and make it significantly easier to work with this data in Python.
|
|
74
|
+
|
|
75
|
+
The current functions are:
|
|
76
|
+
|
|
77
|
+
1) [`cartopy_shapefeature()`](https://github.com/edrewitz/shapeography/blob/main/Documentation/geometry.md#1-cartopy_shapefeature) - Returns a cartopy.shapefeature from the data inside the shapefile/GEOJSON.
|
|
78
|
+
2) [`get_geometries()`](https://github.com/edrewitz/shapeography/blob/main/Documentation/geometry.md#2-get_geometries) - Returns a gpd.GeoDataFrame of the geometry data of the shapefile/GEOJSON in the coordinate reference system (CRS) specified by the user. (Default CRS = 'EPSG:4326' --> `ccrs.PlateCarree()`)
|
|
79
|
+
3) [`geodataframe()`](https://github.com/edrewitz/shapeography/blob/main/Documentation/geometry.md#3-geodataframe) - Returns gpd.GeoDataFrame hosting all the data in the shapefile/GEOJSON in the coordinate reference system (CRS) specified by the user. (Default CRS = 'EPSG:4326' --> `ccrs.PlateCarree()`)
|
|
80
|
+
|
|
81
|
+
# Citations
|
|
82
|
+
|
|
83
|
+
1) **cartopy**: Phil Elson, Elliott Sales de Andrade, Greg Lucas, Ryan May, Richard Hattersley, Ed Campbell, Andrew Dawson, Bill Little, Stephane Raynaud, scmc72, Alan D. Snow, Ruth Comer, Kevin Donkers, Byron Blay, Peter Killick, Nat Wilson, Patrick Peglar, lgolston, lbdreyer, … Chris Havlin. (2023). SciTools/cartopy: v0.22.0 (v0.22.0). Zenodo. https://doi.org/10.5281/zenodo.8216315
|
|
84
|
+
2) **geopandas**: Kelsey Jordahl, Joris Van den Bossche, Martin Fleischmann, Jacob Wasserman, James McBride, Jeffrey Gerard, … François Leblanc. (2020, July 15). geopandas/geopandas: v0.8.1 (Version v0.8.1). Zenodo. http://doi.org/10.5281/zenodo.3946761
|
|
85
|
+
3) **requests**: K. Reitz, "Requests: HTTP for Humans". Available: https://requests.readthedocs.io/.
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
# shapeography
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
<img src="https://github.com/edrewitz/shapeography/blob/main/Thumbnails/86506Livingston-Rev-Base.jpg?raw=true" width="200" alt="Alt text" /> <img src="https://github.com/edrewitz/WxData/blob/1be590e9a16033974a592d8cf99f3cd521f95e0b/icons/python%20logo.png?raw=true" width="200" alt="Alt text" />
|
|
6
|
+
|
|
7
|
+
**(C) Eric J. Drewitz 2026**
|
|
8
|
+
|
|
9
|
+
An open-source Python package that manages shapefiles and GEOJSON files.
|
|
10
|
+
|
|
11
|
+
***Jupyter Lab Examples***
|
|
12
|
+
|
|
13
|
+
1) [Downloading and Plotting the National Weather Service Public Forecast Zones](https://github.com/edrewitz/shapeography-Jupyter-Lab-Examples/blob/main/nws_public_zones.ipynb)
|
|
14
|
+
2) [Downloading and Plotting the NOAA/NWS Climate Prediction Center 6-10 Day Probabilistic Precipitation Outlook](https://github.com/edrewitz/shapeography-Jupyter-Lab-Examples/blob/main/cpc_outlook.ipynb)
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
***Client Module***
|
|
18
|
+
|
|
19
|
+
[Documentation](https://github.com/edrewitz/shapeography/blob/main/Documentation/client.md#client-module)
|
|
20
|
+
|
|
21
|
+
The `client` module hosts the client function `get_shapefiles()` that downloads shapefiles/GEOJSON file from a user-defined URL address into a folder locally on your PC.
|
|
22
|
+
|
|
23
|
+
The user must specify the path and filename and the file is saved to {path}/{filename}.
|
|
24
|
+
|
|
25
|
+
This client is also helpful for those using shapeography in automated scripts. If the user keeps the optional argument `refresh=True` - The directory hosting the shapefiles/GEOJSON file will be refreshed as the old files will be deleted and new files downloaded. This can be helpful in automation due to periodic shapefile updates on the server-side as it ensures that the user will always have the most recent and up to date shapefiles/GEOJSON file.
|
|
26
|
+
|
|
27
|
+
This client supports users on a VPN/PROXY connection.
|
|
28
|
+
|
|
29
|
+
**Proxy Example**
|
|
30
|
+
|
|
31
|
+
proxies=None ---> proxies={
|
|
32
|
+
'http':'address:port',
|
|
33
|
+
'https':'address:port'
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
shapeography.client.get_shapefiles(url, path, filename, proxies=proxies)
|
|
37
|
+
|
|
38
|
+
***Unzip Module***
|
|
39
|
+
|
|
40
|
+
[Documentation](https://github.com/edrewitz/shapeography/blob/main/Documentation/unzip.md#unzip-module)
|
|
41
|
+
|
|
42
|
+
The `unzip` module hosts the function that unzips the shapefiles/GEOJSON file if the file(s) need to be unzipped.
|
|
43
|
+
|
|
44
|
+
In nearly all cases, shapefile components are within a zipfile server-side so needing to unzip is very common.
|
|
45
|
+
|
|
46
|
+
The function `extract_files()` unzips the shapefiles/GEOJSON into a user-specified extraction folder that is automatically generated.
|
|
47
|
+
|
|
48
|
+
Supports the following file extentions: .zip, .gz, .tar, .tar.gz
|
|
49
|
+
|
|
50
|
+
***Geometry Module***
|
|
51
|
+
|
|
52
|
+
[Documentation](https://github.com/edrewitz/shapeography/blob/main/Documentation/geometry.md#geometry-module)
|
|
53
|
+
|
|
54
|
+
The `geometry` module hosts functions that extract data from these shapefiles/GEOJSON file and make it significantly easier to work with this data in Python.
|
|
55
|
+
|
|
56
|
+
The current functions are:
|
|
57
|
+
|
|
58
|
+
1) [`cartopy_shapefeature()`](https://github.com/edrewitz/shapeography/blob/main/Documentation/geometry.md#1-cartopy_shapefeature) - Returns a cartopy.shapefeature from the data inside the shapefile/GEOJSON.
|
|
59
|
+
2) [`get_geometries()`](https://github.com/edrewitz/shapeography/blob/main/Documentation/geometry.md#2-get_geometries) - Returns a gpd.GeoDataFrame of the geometry data of the shapefile/GEOJSON in the coordinate reference system (CRS) specified by the user. (Default CRS = 'EPSG:4326' --> `ccrs.PlateCarree()`)
|
|
60
|
+
3) [`geodataframe()`](https://github.com/edrewitz/shapeography/blob/main/Documentation/geometry.md#3-geodataframe) - Returns gpd.GeoDataFrame hosting all the data in the shapefile/GEOJSON in the coordinate reference system (CRS) specified by the user. (Default CRS = 'EPSG:4326' --> `ccrs.PlateCarree()`)
|
|
61
|
+
|
|
62
|
+
# Citations
|
|
63
|
+
|
|
64
|
+
1) **cartopy**: Phil Elson, Elliott Sales de Andrade, Greg Lucas, Ryan May, Richard Hattersley, Ed Campbell, Andrew Dawson, Bill Little, Stephane Raynaud, scmc72, Alan D. Snow, Ruth Comer, Kevin Donkers, Byron Blay, Peter Killick, Nat Wilson, Patrick Peglar, lgolston, lbdreyer, … Chris Havlin. (2023). SciTools/cartopy: v0.22.0 (v0.22.0). Zenodo. https://doi.org/10.5281/zenodo.8216315
|
|
65
|
+
2) **geopandas**: Kelsey Jordahl, Joris Van den Bossche, Martin Fleischmann, Jacob Wasserman, James McBride, Jeffrey Gerard, … François Leblanc. (2020, July 15). geopandas/geopandas: v0.8.1 (Version v0.8.1). Zenodo. http://doi.org/10.5281/zenodo.3946761
|
|
66
|
+
3) **requests**: K. Reitz, "Requests: HTTP for Humans". Available: https://requests.readthedocs.io/.
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
[project]
|
|
2
|
+
name = "shapeography"
|
|
3
|
+
version = "0.1"
|
|
4
|
+
description = "A Python library that both a client that downloads various shapefiles and GEOJSON files from the web and processes these geometry files. Users can also process locally hosted shapefiles and GEOJSON files. Also works for those on VPN/PROXY connections."
|
|
5
|
+
readme = "README.md"
|
|
6
|
+
requires-python = ">=3.10"
|
|
7
|
+
license-files = ["LICENSE*"]
|
|
8
|
+
authors = [
|
|
9
|
+
{ name = "Eric J. Drewitz" },
|
|
10
|
+
]
|
|
11
|
+
keywords = ["cartography", "geography"]
|
|
12
|
+
classifiers = [
|
|
13
|
+
"Programming Language :: Python",
|
|
14
|
+
"Topic :: Scientific/Engineering",
|
|
15
|
+
"Operating System :: OS Independent",
|
|
16
|
+
]
|
|
17
|
+
|
|
18
|
+
dependencies = [
|
|
19
|
+
"cartopy>=0.24.0",
|
|
20
|
+
"geopandas>=1.1.0",
|
|
21
|
+
"requests>=2.32.4",
|
|
22
|
+
]
|
|
23
|
+
|
|
24
|
+
[build-system]
|
|
25
|
+
requires = ["setuptools>=64.0.0", "wheel"]
|
|
26
|
+
build-backend = "setuptools.build_meta"
|
|
27
|
+
|
|
28
|
+
[tool.setuptools.packages.find]
|
|
29
|
+
where = ["src"] # Look for packages in the src directory
|
|
30
|
+
|
|
31
|
+
[project.urls]
|
|
32
|
+
Documentation = "https://github.com/edrewitz/shapeography?tab=readme-ov-file#shapeography"
|
|
33
|
+
Repository = "https://github.com/edrewitz/shapeography/tree/main"
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
"""
|
|
2
|
+
This file hosts all of the functions in the shapeography package that directly interact with the user.
|
|
3
|
+
|
|
4
|
+
(C) Eric J. Drewitz 2026
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
import shapeography.utils.geometry as geometry
|
|
10
|
+
import shapeography.utils.unzip as unzip
|
|
11
|
+
import shapeography.client.client as client
|
|
12
|
+
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import shapeography.client.client as client
|
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
"""
|
|
2
|
+
This file hosts the client that retrieves the shapefile/geojson from the web and manages these files locally.
|
|
3
|
+
|
|
4
|
+
(C) Eric J. Drewitz 2026
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
import requests as _requests
|
|
8
|
+
import os as _os
|
|
9
|
+
import time as _time
|
|
10
|
+
import sys as _sys
|
|
11
|
+
import shutil as _shutil
|
|
12
|
+
|
|
13
|
+
def get_shapefiles(url,
|
|
14
|
+
path,
|
|
15
|
+
filename,
|
|
16
|
+
proxies=None,
|
|
17
|
+
chunk_size=8192,
|
|
18
|
+
notifications='on',
|
|
19
|
+
refresh=True):
|
|
20
|
+
|
|
21
|
+
"""
|
|
22
|
+
This function is the client that downloads and locally manages shapefiles and GEOJSON files.
|
|
23
|
+
This client supports VPN/PROXY connections.
|
|
24
|
+
|
|
25
|
+
Required Arguments:
|
|
26
|
+
|
|
27
|
+
1) url (String) - The download URL to the file.
|
|
28
|
+
|
|
29
|
+
2) path (String) - The directory where the file is saved to.
|
|
30
|
+
|
|
31
|
+
3) filename (String) - The name the user wishes to save the file as.
|
|
32
|
+
|
|
33
|
+
Optional Arguments:
|
|
34
|
+
|
|
35
|
+
1) proxies (dict or None) - Default=None. If the user is using proxy server(s), the user must change the following:
|
|
36
|
+
|
|
37
|
+
proxies=None ---> proxies={
|
|
38
|
+
'http':'http://url',
|
|
39
|
+
'https':'https://url'
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
get_shapefiles(url, path, filename, proxies=proxies)
|
|
43
|
+
|
|
44
|
+
2) chunk_size (Integer) - Default=8192. The size of the chunks when writing the GRIB/NETCDF data to a file.
|
|
45
|
+
|
|
46
|
+
3) notifications (String) - Default='on'. Notification when a file is downloaded and saved to {path}
|
|
47
|
+
|
|
48
|
+
4) refresh (Boolean) - Default=True. When set to True, the branch that hosts the shapefiles/GEOJSON files is completely
|
|
49
|
+
cleaned out and a new set of shapefiles/GEOJSON is downloaded with each run. This is recommended for those using
|
|
50
|
+
shapeography in automated tasks to account for periodic shapefile/GEOJSON updates on the servers that host the shapefiles/GEOJSONs.
|
|
51
|
+
|
|
52
|
+
Returns
|
|
53
|
+
-------
|
|
54
|
+
|
|
55
|
+
Zipped Shapefile and/or GEOJSON to f:{path}/{filename}
|
|
56
|
+
"""
|
|
57
|
+
|
|
58
|
+
if refresh == True:
|
|
59
|
+
try:
|
|
60
|
+
_shutil.rmtree(f"{path}")
|
|
61
|
+
except Exception as e:
|
|
62
|
+
pass
|
|
63
|
+
else:
|
|
64
|
+
pass
|
|
65
|
+
|
|
66
|
+
try:
|
|
67
|
+
_os.makedirs(f"{path}")
|
|
68
|
+
except Exception as e:
|
|
69
|
+
pass
|
|
70
|
+
|
|
71
|
+
if proxies == None:
|
|
72
|
+
try:
|
|
73
|
+
with _requests.get(url, stream=True) as r:
|
|
74
|
+
r.raise_for_status()
|
|
75
|
+
with open(f"{path}/{filename}", 'wb') as f:
|
|
76
|
+
for chunk in r.iter_content(chunk_size=chunk_size):
|
|
77
|
+
f.write(chunk)
|
|
78
|
+
if notifications == 'on':
|
|
79
|
+
print(f"Successfully saved {filename} to f:{path}")
|
|
80
|
+
else:
|
|
81
|
+
pass
|
|
82
|
+
except _requests.exceptions.RequestException as e:
|
|
83
|
+
for i in range(0, 6, 1):
|
|
84
|
+
if i < 3:
|
|
85
|
+
print(f"Alert: Network connection unstable.\nWaiting 30 seconds then automatically trying again.\nAttempts remaining: {5 - i}")
|
|
86
|
+
_time.sleep(30)
|
|
87
|
+
else:
|
|
88
|
+
print(f"Alert: Network connection unstable.\nWaiting 60 seconds then automatically trying again.\nAttempts remaining: {5 - i}")
|
|
89
|
+
_time.sleep(60)
|
|
90
|
+
|
|
91
|
+
try:
|
|
92
|
+
with _requests.get(url, stream=True) as r:
|
|
93
|
+
r.raise_for_status()
|
|
94
|
+
with open(f"{path}/{filename}", 'wb') as f:
|
|
95
|
+
for chunk in r.iter_content(chunk_size=chunk_size):
|
|
96
|
+
f.write(chunk)
|
|
97
|
+
if notifications == 'on':
|
|
98
|
+
print(f"Successfully saved {filename} to f:{path}")
|
|
99
|
+
break
|
|
100
|
+
except _requests.exceptions.RequestException as e:
|
|
101
|
+
i = i
|
|
102
|
+
if i >= 5:
|
|
103
|
+
print(f"Error - File Cannot Be Downloaded.\nError Code: {e}")
|
|
104
|
+
_sys.exit(1)
|
|
105
|
+
|
|
106
|
+
finally:
|
|
107
|
+
if r:
|
|
108
|
+
r.close() # Ensure the connection is closed.
|
|
109
|
+
|
|
110
|
+
else:
|
|
111
|
+
try:
|
|
112
|
+
with _requests.get(url, stream=True, proxies=proxies) as r:
|
|
113
|
+
r.raise_for_status()
|
|
114
|
+
with open(f"{path}/{filename}", 'wb') as f:
|
|
115
|
+
for chunk in r.iter_content(chunk_size=chunk_size):
|
|
116
|
+
f.write(chunk)
|
|
117
|
+
if notifications == 'on':
|
|
118
|
+
print(f"Successfully saved {filename} to f:{path}")
|
|
119
|
+
else:
|
|
120
|
+
pass
|
|
121
|
+
except _requests.exceptions.RequestException as e:
|
|
122
|
+
for i in range(0, 6, 1):
|
|
123
|
+
if i < 3:
|
|
124
|
+
print(f"Alert: Network connection unstable.\nWaiting 30 seconds then automatically trying again.\nAttempts remaining: {5 - i}")
|
|
125
|
+
_time.sleep(30)
|
|
126
|
+
else:
|
|
127
|
+
print(f"Alert: Network connection unstable.\nWaiting 60 seconds then automatically trying again.\nAttempts remaining: {5 - i}")
|
|
128
|
+
_time.sleep(60)
|
|
129
|
+
|
|
130
|
+
try:
|
|
131
|
+
with _requests.get(url, stream=True, proxies=proxies) as r:
|
|
132
|
+
r.raise_for_status()
|
|
133
|
+
with open(f"{path}/{filename}", 'wb') as f:
|
|
134
|
+
for chunk in r.iter_content(chunk_size=chunk_size):
|
|
135
|
+
f.write(chunk)
|
|
136
|
+
if notifications == 'on':
|
|
137
|
+
print(f"Successfully saved {filename} to f:{path}")
|
|
138
|
+
break
|
|
139
|
+
except _requests.exceptions.RequestException as e:
|
|
140
|
+
i = i
|
|
141
|
+
if i >= 5:
|
|
142
|
+
print(f"Error - File Cannot Be Downloaded.\nError Code: {e}")
|
|
143
|
+
_sys.exit(1)
|
|
144
|
+
|
|
145
|
+
finally:
|
|
146
|
+
if r:
|
|
147
|
+
r.close() # Ensure the connection is closed.
|
|
148
|
+
|
|
149
|
+
|
|
150
|
+
|
|
151
|
+
|
|
152
|
+
|
|
153
|
+
|
|
154
|
+
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
"""
|
|
2
|
+
This file hosts the functions that extract data from the shapefiles/GEOJSON files and return that data.
|
|
3
|
+
This file also has a geopandas wrapper to extract GeoDataFrames
|
|
4
|
+
|
|
5
|
+
(C) Eric J. Drewitz 2026
|
|
6
|
+
"""
|
|
7
|
+
import geopandas as _gpd
|
|
8
|
+
import cartopy.crs as _ccrs
|
|
9
|
+
import cartopy.io.shapereader as _shapereader
|
|
10
|
+
import cartopy.feature as _cfeature
|
|
11
|
+
|
|
12
|
+
def cartopy_shapefeature(file_path,
|
|
13
|
+
edgecolor='black'):
|
|
14
|
+
|
|
15
|
+
"""
|
|
16
|
+
This function extracts the geometries from the shapefile and returns those geometries to the user.
|
|
17
|
+
|
|
18
|
+
Required Arguments:
|
|
19
|
+
|
|
20
|
+
1) file_path (String) - The full filepath to the shapefile.
|
|
21
|
+
|
|
22
|
+
Optional Arguments:
|
|
23
|
+
|
|
24
|
+
1) edgecolor (String) - Default='black'. The color of the bordr demarcations on the map.
|
|
25
|
+
|
|
26
|
+
Returns
|
|
27
|
+
-------
|
|
28
|
+
|
|
29
|
+
A cartopy.shapefeature from the data inside the shapefile/GEOJSON.
|
|
30
|
+
"""
|
|
31
|
+
|
|
32
|
+
shape_feature = _cfeature.ShapelyFeature(_shapereader.Reader(file_path).geometries(),
|
|
33
|
+
crs=_ccrs.PlateCarree(), facecolor=(0,0,0,0), edgecolor=edgecolor)
|
|
34
|
+
|
|
35
|
+
return shape_feature
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
def get_geometries(file_path,
|
|
39
|
+
crs='EPSG:4326'):
|
|
40
|
+
|
|
41
|
+
"""
|
|
42
|
+
This function converts the shapefile geometries to a CRS specified by the user using geopandas.
|
|
43
|
+
|
|
44
|
+
Required Arguments:
|
|
45
|
+
|
|
46
|
+
1) file_path (String) - The full filepath to the shapefile.
|
|
47
|
+
|
|
48
|
+
Optional Arguments:
|
|
49
|
+
|
|
50
|
+
1) crs (String) - Default='EPSG:4326' (ccrs.PlateCarree()) - The coordinate reference system the user wants the geometry coordinates in.
|
|
51
|
+
|
|
52
|
+
Returns
|
|
53
|
+
-------
|
|
54
|
+
|
|
55
|
+
A gpd.GeoDataFrame geometry data of the shapefile/GEOJSON in the CRS specified by the user.
|
|
56
|
+
"""
|
|
57
|
+
|
|
58
|
+
gdf = _gpd.read_file(f"{file_path}")
|
|
59
|
+
|
|
60
|
+
gdf = gdf.to_crs(crs)
|
|
61
|
+
|
|
62
|
+
return gdf['geometry']
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
def geodataframe(file_path,
|
|
66
|
+
crs='EPSG:4326'):
|
|
67
|
+
|
|
68
|
+
"""
|
|
69
|
+
This function extracts a gpd.GeoDataFrame from the shapefile/GEOJSON.
|
|
70
|
+
|
|
71
|
+
Required Arguments:
|
|
72
|
+
|
|
73
|
+
1) file_path (String) - The full filepath to the shapefile.
|
|
74
|
+
|
|
75
|
+
Optional Arguments:
|
|
76
|
+
|
|
77
|
+
1) crs (String) - Default='EPSG:4326' (ccrs.PlateCarree()) - The coordinate reference system the user wants the geometry coordinates in.
|
|
78
|
+
|
|
79
|
+
Returns
|
|
80
|
+
-------
|
|
81
|
+
|
|
82
|
+
A gpd.GeoDataFrame hosting all the data in the shapefile/GEOJSON.
|
|
83
|
+
"""
|
|
84
|
+
|
|
85
|
+
gdf = _gpd.read_file(f"{file_path}")
|
|
86
|
+
|
|
87
|
+
gdf = gdf.to_crs(crs)
|
|
88
|
+
|
|
89
|
+
return gdf
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
"""
|
|
2
|
+
This file hosts the functions responsible for unzipping the shapefiles
|
|
3
|
+
|
|
4
|
+
(C) Eric J. Drewitz 2026
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
import os as _os
|
|
8
|
+
import gzip as _gzip
|
|
9
|
+
import tarfile as _tarfile
|
|
10
|
+
|
|
11
|
+
from zipfile import ZipFile as _ZipFile
|
|
12
|
+
|
|
13
|
+
def extract_files(file_directory,
|
|
14
|
+
file_extension='.zip'):
|
|
15
|
+
|
|
16
|
+
"""
|
|
17
|
+
This function extracts shapefiles that are zipped in a .zip file
|
|
18
|
+
|
|
19
|
+
Required Arguments:
|
|
20
|
+
|
|
21
|
+
1) file_directory (String) - The path of the directory to the initial .zip file.
|
|
22
|
+
|
|
23
|
+
Optional Arguments:
|
|
24
|
+
|
|
25
|
+
1) file_extension (String) - Default='.zip'. - The extension of the zip file.
|
|
26
|
+
|
|
27
|
+
Supported zip file extentions
|
|
28
|
+
-----------------------------
|
|
29
|
+
|
|
30
|
+
1) .zip
|
|
31
|
+
2) .gz
|
|
32
|
+
3) .tar.gz
|
|
33
|
+
4) .tar
|
|
34
|
+
|
|
35
|
+
Returns
|
|
36
|
+
-------
|
|
37
|
+
|
|
38
|
+
A directory of unzipped shapefiles.
|
|
39
|
+
"""
|
|
40
|
+
|
|
41
|
+
file_extension = file_extension.lower()
|
|
42
|
+
|
|
43
|
+
if file_extension == '.gz':
|
|
44
|
+
try:
|
|
45
|
+
for f in _os.listdir(f"{file_directory}"):
|
|
46
|
+
extraction_folder = f.split('.', 1)[0]
|
|
47
|
+
with _gzip.open(f"{file_directory}/{f}", 'rb') as f_in:
|
|
48
|
+
with open(f"{file_directory}/{extraction_folder}", 'wb') as f_out:
|
|
49
|
+
f_out.write(f_in.read())
|
|
50
|
+
except Exception as e:
|
|
51
|
+
pass
|
|
52
|
+
|
|
53
|
+
try:
|
|
54
|
+
for f in _os.listdir(f"{file_directory}/{extraction_folder}"):
|
|
55
|
+
ex_folder = f.split('.', 1)[0]
|
|
56
|
+
with _gzip.open(f"{file_directory}/{extraction_folder}/{f}", 'rb') as f_in:
|
|
57
|
+
with open(f"{file_directory}/{extraction_folder}/{ex_folder}", 'wb') as f_out:
|
|
58
|
+
f_out.write(f_in.read())
|
|
59
|
+
except Exception as e:
|
|
60
|
+
pass
|
|
61
|
+
|
|
62
|
+
elif file_extension == '.tar.gz':
|
|
63
|
+
try:
|
|
64
|
+
for f in _os.listdir(f"{file_directory}"):
|
|
65
|
+
extraction_folder = f.split('.', 1)[0]
|
|
66
|
+
with _tarfile.open(f"{file_directory}/{f}", "r:gz") as tar:
|
|
67
|
+
tar.extractall(path=f"{file_directory}/{extraction_folder}")
|
|
68
|
+
except Exception as e:
|
|
69
|
+
pass
|
|
70
|
+
|
|
71
|
+
try:
|
|
72
|
+
for f in _os.listdir(f"{file_directory}/{extraction_folder}"):
|
|
73
|
+
ex_folder = f.split('.', 1)[0]
|
|
74
|
+
with _tarfile.open(f"{file_directory}/{extraction_folder}/{f}", "r:gz") as tar:
|
|
75
|
+
tar.extractall(path=f"{file_directory}/{extraction_folder}/{ex_folder}")
|
|
76
|
+
except Exception as e:
|
|
77
|
+
pass
|
|
78
|
+
|
|
79
|
+
elif file_extension == '.tar':
|
|
80
|
+
try:
|
|
81
|
+
for f in _os.listdir(f"{file_directory}"):
|
|
82
|
+
extraction_folder = f.split('.', 1)[0]
|
|
83
|
+
with _tarfile.open(f"{file_directory}/{f}", 'r') as tar:
|
|
84
|
+
tar.extractall(path=f"{file_directory}/{extraction_folder}")
|
|
85
|
+
except Exception as e:
|
|
86
|
+
pass
|
|
87
|
+
|
|
88
|
+
try:
|
|
89
|
+
for f in _os.listdir(f"{file_directory}"):
|
|
90
|
+
ex_folder = f.split('.', 1)[0]
|
|
91
|
+
with _tarfile.open(f"{file_directory}/{extraction_folder}/{f}", 'r') as tar:
|
|
92
|
+
tar.extractall(path=f"{file_directory}/{extraction_folder}/{ex_folder}")
|
|
93
|
+
except Exception as e:
|
|
94
|
+
pass
|
|
95
|
+
|
|
96
|
+
else:
|
|
97
|
+
try:
|
|
98
|
+
for f in _os.listdir(f"{file_directory}"):
|
|
99
|
+
extraction_folder = f.split('.', 1)[0]
|
|
100
|
+
with _ZipFile(f"{file_directory}/{f}", 'r') as zObject:
|
|
101
|
+
zObject.extractall(f"{file_directory}/{extraction_folder}")
|
|
102
|
+
zObject.close()
|
|
103
|
+
except Exception as e:
|
|
104
|
+
pass
|
|
105
|
+
|
|
106
|
+
try:
|
|
107
|
+
for f in _os.listdir(f"{file_directory}/{extraction_folder}"):
|
|
108
|
+
ex_folder = f.split('.', 1)[0]
|
|
109
|
+
with _ZipFile(f"{file_directory}/{extraction_folder}/{f}", 'r') as zObject:
|
|
110
|
+
zObject.extractall(f"{file_directory}/{extraction_folder}/{ex_folder}")
|
|
111
|
+
zObject.close()
|
|
112
|
+
except Exception as e:
|
|
113
|
+
pass
|
|
114
|
+
|
|
115
|
+
try:
|
|
116
|
+
for f in _os.listdir(f"{file_directory}"):
|
|
117
|
+
if f.endswith(file_extension):
|
|
118
|
+
_os.remove(f"{file_directory}/{f}")
|
|
119
|
+
except Exception as e:
|
|
120
|
+
pass
|
|
121
|
+
|
|
122
|
+
try:
|
|
123
|
+
for f in _os.listdir(f"{file_directory}/{extraction_folder}"):
|
|
124
|
+
if f.endswith(file_extension):
|
|
125
|
+
_os.remove(f"{file_directory}/{extraction_folder}/{f}")
|
|
126
|
+
except Exception as e:
|
|
127
|
+
pass
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: shapeography
|
|
3
|
+
Version: 0.1
|
|
4
|
+
Summary: A Python library that both a client that downloads various shapefiles and GEOJSON files from the web and processes these geometry files. Users can also process locally hosted shapefiles and GEOJSON files. Also works for those on VPN/PROXY connections.
|
|
5
|
+
Author: Eric J. Drewitz
|
|
6
|
+
Project-URL: Documentation, https://github.com/edrewitz/shapeography?tab=readme-ov-file#shapeography
|
|
7
|
+
Project-URL: Repository, https://github.com/edrewitz/shapeography/tree/main
|
|
8
|
+
Keywords: cartography,geography
|
|
9
|
+
Classifier: Programming Language :: Python
|
|
10
|
+
Classifier: Topic :: Scientific/Engineering
|
|
11
|
+
Classifier: Operating System :: OS Independent
|
|
12
|
+
Requires-Python: >=3.10
|
|
13
|
+
Description-Content-Type: text/markdown
|
|
14
|
+
License-File: LICENSE
|
|
15
|
+
Requires-Dist: cartopy>=0.24.0
|
|
16
|
+
Requires-Dist: geopandas>=1.1.0
|
|
17
|
+
Requires-Dist: requests>=2.32.4
|
|
18
|
+
Dynamic: license-file
|
|
19
|
+
|
|
20
|
+
# shapeography
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
<img src="https://github.com/edrewitz/shapeography/blob/main/Thumbnails/86506Livingston-Rev-Base.jpg?raw=true" width="200" alt="Alt text" /> <img src="https://github.com/edrewitz/WxData/blob/1be590e9a16033974a592d8cf99f3cd521f95e0b/icons/python%20logo.png?raw=true" width="200" alt="Alt text" />
|
|
25
|
+
|
|
26
|
+
**(C) Eric J. Drewitz 2026**
|
|
27
|
+
|
|
28
|
+
An open-source Python package that manages shapefiles and GEOJSON files.
|
|
29
|
+
|
|
30
|
+
***Jupyter Lab Examples***
|
|
31
|
+
|
|
32
|
+
1) [Downloading and Plotting the National Weather Service Public Forecast Zones](https://github.com/edrewitz/shapeography-Jupyter-Lab-Examples/blob/main/nws_public_zones.ipynb)
|
|
33
|
+
2) [Downloading and Plotting the NOAA/NWS Climate Prediction Center 6-10 Day Probabilistic Precipitation Outlook](https://github.com/edrewitz/shapeography-Jupyter-Lab-Examples/blob/main/cpc_outlook.ipynb)
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
***Client Module***
|
|
37
|
+
|
|
38
|
+
[Documentation](https://github.com/edrewitz/shapeography/blob/main/Documentation/client.md#client-module)
|
|
39
|
+
|
|
40
|
+
The `client` module hosts the client function `get_shapefiles()` that downloads shapefiles/GEOJSON file from a user-defined URL address into a folder locally on your PC.
|
|
41
|
+
|
|
42
|
+
The user must specify the path and filename and the file is saved to {path}/{filename}.
|
|
43
|
+
|
|
44
|
+
This client is also helpful for those using shapeography in automated scripts. If the user keeps the optional argument `refresh=True` - The directory hosting the shapefiles/GEOJSON file will be refreshed as the old files will be deleted and new files downloaded. This can be helpful in automation due to periodic shapefile updates on the server-side as it ensures that the user will always have the most recent and up to date shapefiles/GEOJSON file.
|
|
45
|
+
|
|
46
|
+
This client supports users on a VPN/PROXY connection.
|
|
47
|
+
|
|
48
|
+
**Proxy Example**
|
|
49
|
+
|
|
50
|
+
proxies=None ---> proxies={
|
|
51
|
+
'http':'address:port',
|
|
52
|
+
'https':'address:port'
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
shapeography.client.get_shapefiles(url, path, filename, proxies=proxies)
|
|
56
|
+
|
|
57
|
+
***Unzip Module***
|
|
58
|
+
|
|
59
|
+
[Documentation](https://github.com/edrewitz/shapeography/blob/main/Documentation/unzip.md#unzip-module)
|
|
60
|
+
|
|
61
|
+
The `unzip` module hosts the function that unzips the shapefiles/GEOJSON file if the file(s) need to be unzipped.
|
|
62
|
+
|
|
63
|
+
In nearly all cases, shapefile components are within a zipfile server-side so needing to unzip is very common.
|
|
64
|
+
|
|
65
|
+
The function `extract_files()` unzips the shapefiles/GEOJSON into a user-specified extraction folder that is automatically generated.
|
|
66
|
+
|
|
67
|
+
Supports the following file extentions: .zip, .gz, .tar, .tar.gz
|
|
68
|
+
|
|
69
|
+
***Geometry Module***
|
|
70
|
+
|
|
71
|
+
[Documentation](https://github.com/edrewitz/shapeography/blob/main/Documentation/geometry.md#geometry-module)
|
|
72
|
+
|
|
73
|
+
The `geometry` module hosts functions that extract data from these shapefiles/GEOJSON file and make it significantly easier to work with this data in Python.
|
|
74
|
+
|
|
75
|
+
The current functions are:
|
|
76
|
+
|
|
77
|
+
1) [`cartopy_shapefeature()`](https://github.com/edrewitz/shapeography/blob/main/Documentation/geometry.md#1-cartopy_shapefeature) - Returns a cartopy.shapefeature from the data inside the shapefile/GEOJSON.
|
|
78
|
+
2) [`get_geometries()`](https://github.com/edrewitz/shapeography/blob/main/Documentation/geometry.md#2-get_geometries) - Returns a gpd.GeoDataFrame of the geometry data of the shapefile/GEOJSON in the coordinate reference system (CRS) specified by the user. (Default CRS = 'EPSG:4326' --> `ccrs.PlateCarree()`)
|
|
79
|
+
3) [`geodataframe()`](https://github.com/edrewitz/shapeography/blob/main/Documentation/geometry.md#3-geodataframe) - Returns gpd.GeoDataFrame hosting all the data in the shapefile/GEOJSON in the coordinate reference system (CRS) specified by the user. (Default CRS = 'EPSG:4326' --> `ccrs.PlateCarree()`)
|
|
80
|
+
|
|
81
|
+
# Citations
|
|
82
|
+
|
|
83
|
+
1) **cartopy**: Phil Elson, Elliott Sales de Andrade, Greg Lucas, Ryan May, Richard Hattersley, Ed Campbell, Andrew Dawson, Bill Little, Stephane Raynaud, scmc72, Alan D. Snow, Ruth Comer, Kevin Donkers, Byron Blay, Peter Killick, Nat Wilson, Patrick Peglar, lgolston, lbdreyer, … Chris Havlin. (2023). SciTools/cartopy: v0.22.0 (v0.22.0). Zenodo. https://doi.org/10.5281/zenodo.8216315
|
|
84
|
+
2) **geopandas**: Kelsey Jordahl, Joris Van den Bossche, Martin Fleischmann, Jacob Wasserman, James McBride, Jeffrey Gerard, … François Leblanc. (2020, July 15). geopandas/geopandas: v0.8.1 (Version v0.8.1). Zenodo. http://doi.org/10.5281/zenodo.3946761
|
|
85
|
+
3) **requests**: K. Reitz, "Requests: HTTP for Humans". Available: https://requests.readthedocs.io/.
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
LICENSE
|
|
2
|
+
README.md
|
|
3
|
+
pyproject.toml
|
|
4
|
+
src/shapeography/__init__.py
|
|
5
|
+
src/shapeography.egg-info/PKG-INFO
|
|
6
|
+
src/shapeography.egg-info/SOURCES.txt
|
|
7
|
+
src/shapeography.egg-info/dependency_links.txt
|
|
8
|
+
src/shapeography.egg-info/requires.txt
|
|
9
|
+
src/shapeography.egg-info/top_level.txt
|
|
10
|
+
src/shapeography/client/__init__.py
|
|
11
|
+
src/shapeography/client/client.py
|
|
12
|
+
src/shapeography/utils/__init__.py
|
|
13
|
+
src/shapeography/utils/geometry.py
|
|
14
|
+
src/shapeography/utils/unzip.py
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
shapeography
|