matplotlib-map-utils 3.0.0__tar.gz → 3.1.0__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.
- {matplotlib_map_utils-3.0.0 → matplotlib_map_utils-3.1.0}/PKG-INFO +59 -8
- {matplotlib_map_utils-3.0.0 → matplotlib_map_utils-3.1.0}/README.md +58 -7
- {matplotlib_map_utils-3.0.0 → matplotlib_map_utils-3.1.0}/matplotlib_map_utils/core/inset_map.py +64 -40
- {matplotlib_map_utils-3.0.0 → matplotlib_map_utils-3.1.0}/matplotlib_map_utils/core/north_arrow.py +24 -9
- {matplotlib_map_utils-3.0.0 → matplotlib_map_utils-3.1.0}/matplotlib_map_utils/core/scale_bar.py +265 -190
- {matplotlib_map_utils-3.0.0 → matplotlib_map_utils-3.1.0}/matplotlib_map_utils/defaults/scale_bar.py +5 -0
- {matplotlib_map_utils-3.0.0 → matplotlib_map_utils-3.1.0}/matplotlib_map_utils/validation/functions.py +3 -6
- {matplotlib_map_utils-3.0.0 → matplotlib_map_utils-3.1.0}/matplotlib_map_utils/validation/inset_map.py +3 -0
- {matplotlib_map_utils-3.0.0 → matplotlib_map_utils-3.1.0}/matplotlib_map_utils/validation/north_arrow.py +1 -0
- {matplotlib_map_utils-3.0.0 → matplotlib_map_utils-3.1.0}/matplotlib_map_utils/validation/scale_bar.py +7 -4
- {matplotlib_map_utils-3.0.0 → matplotlib_map_utils-3.1.0}/matplotlib_map_utils.egg-info/PKG-INFO +59 -8
- {matplotlib_map_utils-3.0.0 → matplotlib_map_utils-3.1.0}/matplotlib_map_utils.egg-info/top_level.txt +0 -1
- {matplotlib_map_utils-3.0.0 → matplotlib_map_utils-3.1.0}/pyproject.toml +1 -1
- {matplotlib_map_utils-3.0.0 → matplotlib_map_utils-3.1.0}/LICENSE +0 -0
- {matplotlib_map_utils-3.0.0 → matplotlib_map_utils-3.1.0}/matplotlib_map_utils/__init__.py +0 -0
- {matplotlib_map_utils-3.0.0 → matplotlib_map_utils-3.1.0}/matplotlib_map_utils/core/__init__.py +0 -0
- {matplotlib_map_utils-3.0.0 → matplotlib_map_utils-3.1.0}/matplotlib_map_utils/defaults/__init__.py +0 -0
- {matplotlib_map_utils-3.0.0 → matplotlib_map_utils-3.1.0}/matplotlib_map_utils/defaults/inset_map.py +0 -0
- {matplotlib_map_utils-3.0.0 → matplotlib_map_utils-3.1.0}/matplotlib_map_utils/defaults/north_arrow.py +0 -0
- {matplotlib_map_utils-3.0.0 → matplotlib_map_utils-3.1.0}/matplotlib_map_utils/scratch/map_utils.py +0 -0
- {matplotlib_map_utils-3.0.0 → matplotlib_map_utils-3.1.0}/matplotlib_map_utils/scratch/north_arrow_old_classes.py +0 -0
- {matplotlib_map_utils-3.0.0 → matplotlib_map_utils-3.1.0}/matplotlib_map_utils/utils/__init__.py +0 -0
- {matplotlib_map_utils-3.0.0 → matplotlib_map_utils-3.1.0}/matplotlib_map_utils/utils/usa.json +0 -0
- {matplotlib_map_utils-3.0.0 → matplotlib_map_utils-3.1.0}/matplotlib_map_utils/utils/usa.py +0 -0
- {matplotlib_map_utils-3.0.0 → matplotlib_map_utils-3.1.0}/matplotlib_map_utils/validation/__init__.py +0 -0
- {matplotlib_map_utils-3.0.0 → matplotlib_map_utils-3.1.0}/matplotlib_map_utils.egg-info/SOURCES.txt +0 -0
- {matplotlib_map_utils-3.0.0 → matplotlib_map_utils-3.1.0}/matplotlib_map_utils.egg-info/dependency_links.txt +0 -0
- {matplotlib_map_utils-3.0.0 → matplotlib_map_utils-3.1.0}/matplotlib_map_utils.egg-info/requires.txt +0 -0
- {matplotlib_map_utils-3.0.0 → matplotlib_map_utils-3.1.0}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.4
|
2
2
|
Name: matplotlib-map-utils
|
3
|
-
Version: 3.
|
3
|
+
Version: 3.1.0
|
4
4
|
Summary: A suite of tools for creating maps in matplotlib
|
5
5
|
Author-email: David Moss <davidmoss1221@gmail.com>
|
6
6
|
Project-URL: Homepage, https://github.com/moss-xyz/matplotlib-map-utils/
|
@@ -29,7 +29,7 @@ Dynamic: license-file
|
|
29
29
|
|
30
30
|
---
|
31
31
|
|
32
|
-
### Introduction
|
32
|
+
### 👋 Introduction
|
33
33
|
|
34
34
|
`matplotlib_map_utils` is intended to be a package that provides various functions and objects that assist with the the creation of maps using [`matplotlib`](https://matplotlib.org/stable/).
|
35
35
|
|
@@ -53,7 +53,7 @@ Together, these allow for the easy creation of a map such as the following:
|
|
53
53
|
|
54
54
|
---
|
55
55
|
|
56
|
-
### Installation
|
56
|
+
### 💾 Installation
|
57
57
|
|
58
58
|
This package is available on PyPi, and can be installed like so:
|
59
59
|
|
@@ -71,7 +71,7 @@ The requirements for this package are:
|
|
71
71
|
|
72
72
|
---
|
73
73
|
|
74
|
-
### Package Structure
|
74
|
+
### 📦 Package Structure
|
75
75
|
|
76
76
|
<details>
|
77
77
|
<summary><i>The package is arrayed in the following way:</i></summary>
|
@@ -211,6 +211,8 @@ There are two available styles for the scale bars: `boxes` and `ticks`. The quic
|
|
211
211
|
|
212
212
|
```python
|
213
213
|
# Setting up a plot
|
214
|
+
# NOTE: you MUST set the desired DPI here, when the subplots are created
|
215
|
+
# so that the scale_bar's DPI matches!
|
214
216
|
fig, ax = matplotlib.pyplot.subplots(1,1, figsize=(5,5), dpi=150)
|
215
217
|
# Adding a scale bar to the upper-right corner of the axis, in the same projection as whatever geodata you plotted
|
216
218
|
# Here, this scale bar will have the "boxes" style
|
@@ -221,6 +223,8 @@ An object-oriented approach is also supported:
|
|
221
223
|
|
222
224
|
```python
|
223
225
|
# Setting up a plot
|
226
|
+
# NOTE: you MUST set the desired DPI here, when the subplots are created
|
227
|
+
# so that the scale_bar's DPI matches!
|
224
228
|
fig, ax = matplotlib.pyplot.subplots(1,1, figsize=(5,5), dpi=150)
|
225
229
|
# Adding a scale bar to the upper-right corner of the axis, in the same projection as whatever geodata you plotted
|
226
230
|
# Here, we change the boxes to "ticks"
|
@@ -256,6 +260,38 @@ This will create an output like the following:
|
|
256
260
|
|
257
261
|
Refer to `docs\howto_scale_bar` for details on how to customize each facet of the scale bar.
|
258
262
|
|
263
|
+
#### Specifying Length
|
264
|
+
|
265
|
+
There are three main ways of specifying the length of a scale bar:
|
266
|
+
|
267
|
+
- `length` is used to set the total length of the bar, either in _inches_ (for values >= 1) or as a _fraction of the axis_ (for values < 1).
|
268
|
+
- The default value of the scale bar utilizes this method, with a `length` value of `0.25` (meaning 25% of the axis).
|
269
|
+
- It will automatically orient itself against the horizontal or vertical axis when calculating its fraction, based on the value supplied for `rotation`.
|
270
|
+
- Note that any values here will be rounded to a "nice" whole integer, so the length will *always be approximate*; ex., if two inches is 9,128 units, your scale bar will end up being 9,000 units, and therefore a little less than two inches.
|
271
|
+
- Values `major_div` and `minor_div` are ignored, while a value for `max` will _override_ `length`.
|
272
|
+
|
273
|
+
- `max` is used to define the total length of the bar, _in the same units as your map_, as determined by the value of `projection` and `unit`.
|
274
|
+
- Ex: If you are using a projection in feet, and give a `max` of `1000`, your scale bar will be representative of 1,000 feet.
|
275
|
+
- Ex: If you are using a projection in feet, but provide a value of `meter` to `unit`, and give a `max` of `1000`, your scale bar will be representative of 1,000 meters.
|
276
|
+
- Will _override_ any value provided for `length`, and give a warning that it is doing so!
|
277
|
+
- Values can be optionally be provided for `major_div` and `minor_div`, to subdivide the bar into major or minor segments as you desire; if left blank, values for these will be calculated automatically (see `preferred_divs` in `validation/scale_bar.py` for the values used).
|
278
|
+
|
279
|
+
- `major_mult` can be used alongside `major_div` to _derive_ the total length: `major_mult` is the _length of a **single** major division_, in the _same units as your map_ (as determined by the value of `projection` and `unit`), which is then multiplied out by `major_div` to arrive at the desired length of the bar.
|
280
|
+
- Ex: If you set `major_mult` to 1,000, and `major_div` to 3, your bar will be 3,000 units long, divided into three 1,000 segments.
|
281
|
+
- This is the _only_ use case for `major_mult` - using it anywhere else will result in warnings and/or errors!
|
282
|
+
- Specifying either `max` or `length` will override this method!
|
283
|
+
- `minor_div` can still be _optionally_ provided.
|
284
|
+
|
285
|
+
All of the above cases expect a valid CRS to be supplied to the `projection` parameter, to correctly calculate the relative size of the bar with respect to the map's underlying units. However, three _additional_ values may be passed to `projection`, to override this behavior entirely:
|
286
|
+
|
287
|
+
- If `projection` is set to `px`, `pixel`, or `pixels`, then values for `max` and `major_mult` are interpreted as being in _pixels_ (so a `max` of 1,000 will result in a bar 1,000 pixels long)
|
288
|
+
|
289
|
+
- If `projection` is set to `pt`, `point`, or `points`, then values for `max` and `major_mult` are interpreted as being in _points_ (so a `max` of 1,000 will result in a bar 1,000 points long (a point is 1/72 of an inch))
|
290
|
+
|
291
|
+
- If `projection` is set to `dx`, `custom`, or `axis`, then values for `max` and `major_mult` are interpreted as being in _the units of the x or y axis_ (so a `max` of 1,000 will result in a bar equal to 1,000 units of the x-axis (if orientated horizontally))
|
292
|
+
|
293
|
+
The intent of these additional methods is to provide an alternative interface for defining the bar, in the case of non-standard projections, or for non-cartographic use cases (in particular, this is inspired by the `dx` implementation of `matplotlib-scalebar`). However, this puts the onus on the user to know how big their bar should be - you also cannot pass a value to `unit` to convert! Note you can provide custom label text to the bar via the `labels` and `units` arguments (ex. if you need to label "inches" or something).
|
294
|
+
|
259
295
|
</details>
|
260
296
|
|
261
297
|
---
|
@@ -343,7 +379,7 @@ usa = USA()
|
|
343
379
|
# Getting a list FIPS codes for US States
|
344
380
|
usa.filter(states=True, to_return="fips")
|
345
381
|
# Getting a list of State Names for states in the South and Midwest regions
|
346
|
-
usa.filter(region=["South","
|
382
|
+
usa.filter(region=["South","Midwest"], to_return="name")
|
347
383
|
```
|
348
384
|
|
349
385
|
Refer to `docs\howto_utils` for details on how to use this class, including with `pandas.apply()`.
|
@@ -352,7 +388,7 @@ Refer to `docs\howto_utils` for details on how to use this class, including with
|
|
352
388
|
|
353
389
|
---
|
354
390
|
|
355
|
-
### Development Notes
|
391
|
+
### 📝 Development Notes
|
356
392
|
|
357
393
|
#### Inspiration and Thanks
|
358
394
|
|
@@ -366,6 +402,9 @@ Two more projects assisted with the creation of this script:
|
|
366
402
|
|
367
403
|
#### Releases
|
368
404
|
|
405
|
+
<details>
|
406
|
+
<summary><i>See prior release notes</i></summary>
|
407
|
+
|
369
408
|
- `v1.0.x`: Initial releases featuring the North Arrow element, along with some minor bug fixes.
|
370
409
|
|
371
410
|
- `v2.0.0`: Initial release of the Scale Bar element.
|
@@ -376,13 +415,21 @@ Two more projects assisted with the creation of this script:
|
|
376
415
|
|
377
416
|
- `v2.1.0`: Added a utility class, `USA`, for filtering subsets of US states and territories based on FIPS code, name, abbreviation, region, division, and more. This is considered a beta release, and might be subject to change later on.
|
378
417
|
|
418
|
+
</details>
|
419
|
+
<br>
|
420
|
+
|
379
421
|
- `v3.0.0`: Release of inset map and extent and detail indicator classes and functions.
|
380
422
|
|
423
|
+
- `v3.0.1`: Fixed a bug that led to an incorrect Scale Bar being rendered when using the function method (`scale_bar()`) on a plot containing raster data (see [here](https://github.com/moss-xyz/matplotlib-map-utils/issues/10) for details).
|
424
|
+
|
425
|
+
- `v3.1.0`: Overhauled the functionality for specifying the the length of a scale bar, including support for custom units/projections (similar to `matplotlib-scalebar`'s `dx` argument) and to specify the length of a major division instead of the entire scale bar, as requested [here](https://github.com/moss-xyz/matplotlib-map-utils/issues/10). Added ability to set artist-level `zorder` variables for all elements, with both the function and class method approaches, as requested [here](https://github.com/moss-xyz/matplotlib-map-utils/issues/9) and [here](https://github.com/moss-xyz/matplotlib-map-utils/issues/10). Also fixed a bug related to custom division labels on the scale bar.
|
426
|
+
|
381
427
|
#### Future Roadmap
|
382
428
|
|
383
429
|
With the release of `v3.x`, this project has achieved full coverage of the "main" map elements I think are necessary.
|
384
430
|
|
385
|
-
|
431
|
+
<details>
|
432
|
+
<summary><i>If I continue development of this project, I will be looking to add or fix the following features:</i></summary>
|
386
433
|
|
387
434
|
* For all: switch to a system based on Pydantic for easier type validation
|
388
435
|
|
@@ -418,14 +465,18 @@ If I continue development of this project, I will be looking to add or fix the f
|
|
418
465
|
|
419
466
|
Future releases (if the project is continued) will probably focus on other functions that I have created myself that give more control in the formatting of maps. I am also open to ideas for other extensions to create!
|
420
467
|
|
468
|
+
</details>
|
469
|
+
|
421
470
|
#### Support and Contributions
|
422
471
|
|
423
472
|
If you notice something is not working as intended or if you'd like to add a feature yourself, I welcome PRs - just be sure to be descriptive as to what you are changing and why, including code examples!
|
424
473
|
|
425
474
|
If you are having issues using this script, feel free to leave a post explaining your issue, and I will try and assist, though I have no guaranteed SLAs as this is just a hobby project.
|
426
475
|
|
476
|
+
I am open to contributions, especially to help tackle the roadmap above!
|
477
|
+
|
427
478
|
---
|
428
479
|
|
429
|
-
### License
|
480
|
+
### ⚖️ License
|
430
481
|
|
431
482
|
I know nothing about licensing, so I went with the GPL license. If that is incompatible with any of the dependencies, please let me know.
|
@@ -10,7 +10,7 @@
|
|
10
10
|
|
11
11
|
---
|
12
12
|
|
13
|
-
### Introduction
|
13
|
+
### 👋 Introduction
|
14
14
|
|
15
15
|
`matplotlib_map_utils` is intended to be a package that provides various functions and objects that assist with the the creation of maps using [`matplotlib`](https://matplotlib.org/stable/).
|
16
16
|
|
@@ -34,7 +34,7 @@ Together, these allow for the easy creation of a map such as the following:
|
|
34
34
|
|
35
35
|
---
|
36
36
|
|
37
|
-
### Installation
|
37
|
+
### 💾 Installation
|
38
38
|
|
39
39
|
This package is available on PyPi, and can be installed like so:
|
40
40
|
|
@@ -52,7 +52,7 @@ The requirements for this package are:
|
|
52
52
|
|
53
53
|
---
|
54
54
|
|
55
|
-
### Package Structure
|
55
|
+
### 📦 Package Structure
|
56
56
|
|
57
57
|
<details>
|
58
58
|
<summary><i>The package is arrayed in the following way:</i></summary>
|
@@ -192,6 +192,8 @@ There are two available styles for the scale bars: `boxes` and `ticks`. The quic
|
|
192
192
|
|
193
193
|
```python
|
194
194
|
# Setting up a plot
|
195
|
+
# NOTE: you MUST set the desired DPI here, when the subplots are created
|
196
|
+
# so that the scale_bar's DPI matches!
|
195
197
|
fig, ax = matplotlib.pyplot.subplots(1,1, figsize=(5,5), dpi=150)
|
196
198
|
# Adding a scale bar to the upper-right corner of the axis, in the same projection as whatever geodata you plotted
|
197
199
|
# Here, this scale bar will have the "boxes" style
|
@@ -202,6 +204,8 @@ An object-oriented approach is also supported:
|
|
202
204
|
|
203
205
|
```python
|
204
206
|
# Setting up a plot
|
207
|
+
# NOTE: you MUST set the desired DPI here, when the subplots are created
|
208
|
+
# so that the scale_bar's DPI matches!
|
205
209
|
fig, ax = matplotlib.pyplot.subplots(1,1, figsize=(5,5), dpi=150)
|
206
210
|
# Adding a scale bar to the upper-right corner of the axis, in the same projection as whatever geodata you plotted
|
207
211
|
# Here, we change the boxes to "ticks"
|
@@ -237,6 +241,38 @@ This will create an output like the following:
|
|
237
241
|
|
238
242
|
Refer to `docs\howto_scale_bar` for details on how to customize each facet of the scale bar.
|
239
243
|
|
244
|
+
#### Specifying Length
|
245
|
+
|
246
|
+
There are three main ways of specifying the length of a scale bar:
|
247
|
+
|
248
|
+
- `length` is used to set the total length of the bar, either in _inches_ (for values >= 1) or as a _fraction of the axis_ (for values < 1).
|
249
|
+
- The default value of the scale bar utilizes this method, with a `length` value of `0.25` (meaning 25% of the axis).
|
250
|
+
- It will automatically orient itself against the horizontal or vertical axis when calculating its fraction, based on the value supplied for `rotation`.
|
251
|
+
- Note that any values here will be rounded to a "nice" whole integer, so the length will *always be approximate*; ex., if two inches is 9,128 units, your scale bar will end up being 9,000 units, and therefore a little less than two inches.
|
252
|
+
- Values `major_div` and `minor_div` are ignored, while a value for `max` will _override_ `length`.
|
253
|
+
|
254
|
+
- `max` is used to define the total length of the bar, _in the same units as your map_, as determined by the value of `projection` and `unit`.
|
255
|
+
- Ex: If you are using a projection in feet, and give a `max` of `1000`, your scale bar will be representative of 1,000 feet.
|
256
|
+
- Ex: If you are using a projection in feet, but provide a value of `meter` to `unit`, and give a `max` of `1000`, your scale bar will be representative of 1,000 meters.
|
257
|
+
- Will _override_ any value provided for `length`, and give a warning that it is doing so!
|
258
|
+
- Values can be optionally be provided for `major_div` and `minor_div`, to subdivide the bar into major or minor segments as you desire; if left blank, values for these will be calculated automatically (see `preferred_divs` in `validation/scale_bar.py` for the values used).
|
259
|
+
|
260
|
+
- `major_mult` can be used alongside `major_div` to _derive_ the total length: `major_mult` is the _length of a **single** major division_, in the _same units as your map_ (as determined by the value of `projection` and `unit`), which is then multiplied out by `major_div` to arrive at the desired length of the bar.
|
261
|
+
- Ex: If you set `major_mult` to 1,000, and `major_div` to 3, your bar will be 3,000 units long, divided into three 1,000 segments.
|
262
|
+
- This is the _only_ use case for `major_mult` - using it anywhere else will result in warnings and/or errors!
|
263
|
+
- Specifying either `max` or `length` will override this method!
|
264
|
+
- `minor_div` can still be _optionally_ provided.
|
265
|
+
|
266
|
+
All of the above cases expect a valid CRS to be supplied to the `projection` parameter, to correctly calculate the relative size of the bar with respect to the map's underlying units. However, three _additional_ values may be passed to `projection`, to override this behavior entirely:
|
267
|
+
|
268
|
+
- If `projection` is set to `px`, `pixel`, or `pixels`, then values for `max` and `major_mult` are interpreted as being in _pixels_ (so a `max` of 1,000 will result in a bar 1,000 pixels long)
|
269
|
+
|
270
|
+
- If `projection` is set to `pt`, `point`, or `points`, then values for `max` and `major_mult` are interpreted as being in _points_ (so a `max` of 1,000 will result in a bar 1,000 points long (a point is 1/72 of an inch))
|
271
|
+
|
272
|
+
- If `projection` is set to `dx`, `custom`, or `axis`, then values for `max` and `major_mult` are interpreted as being in _the units of the x or y axis_ (so a `max` of 1,000 will result in a bar equal to 1,000 units of the x-axis (if orientated horizontally))
|
273
|
+
|
274
|
+
The intent of these additional methods is to provide an alternative interface for defining the bar, in the case of non-standard projections, or for non-cartographic use cases (in particular, this is inspired by the `dx` implementation of `matplotlib-scalebar`). However, this puts the onus on the user to know how big their bar should be - you also cannot pass a value to `unit` to convert! Note you can provide custom label text to the bar via the `labels` and `units` arguments (ex. if you need to label "inches" or something).
|
275
|
+
|
240
276
|
</details>
|
241
277
|
|
242
278
|
---
|
@@ -324,7 +360,7 @@ usa = USA()
|
|
324
360
|
# Getting a list FIPS codes for US States
|
325
361
|
usa.filter(states=True, to_return="fips")
|
326
362
|
# Getting a list of State Names for states in the South and Midwest regions
|
327
|
-
usa.filter(region=["South","
|
363
|
+
usa.filter(region=["South","Midwest"], to_return="name")
|
328
364
|
```
|
329
365
|
|
330
366
|
Refer to `docs\howto_utils` for details on how to use this class, including with `pandas.apply()`.
|
@@ -333,7 +369,7 @@ Refer to `docs\howto_utils` for details on how to use this class, including with
|
|
333
369
|
|
334
370
|
---
|
335
371
|
|
336
|
-
### Development Notes
|
372
|
+
### 📝 Development Notes
|
337
373
|
|
338
374
|
#### Inspiration and Thanks
|
339
375
|
|
@@ -347,6 +383,9 @@ Two more projects assisted with the creation of this script:
|
|
347
383
|
|
348
384
|
#### Releases
|
349
385
|
|
386
|
+
<details>
|
387
|
+
<summary><i>See prior release notes</i></summary>
|
388
|
+
|
350
389
|
- `v1.0.x`: Initial releases featuring the North Arrow element, along with some minor bug fixes.
|
351
390
|
|
352
391
|
- `v2.0.0`: Initial release of the Scale Bar element.
|
@@ -357,13 +396,21 @@ Two more projects assisted with the creation of this script:
|
|
357
396
|
|
358
397
|
- `v2.1.0`: Added a utility class, `USA`, for filtering subsets of US states and territories based on FIPS code, name, abbreviation, region, division, and more. This is considered a beta release, and might be subject to change later on.
|
359
398
|
|
399
|
+
</details>
|
400
|
+
<br>
|
401
|
+
|
360
402
|
- `v3.0.0`: Release of inset map and extent and detail indicator classes and functions.
|
361
403
|
|
404
|
+
- `v3.0.1`: Fixed a bug that led to an incorrect Scale Bar being rendered when using the function method (`scale_bar()`) on a plot containing raster data (see [here](https://github.com/moss-xyz/matplotlib-map-utils/issues/10) for details).
|
405
|
+
|
406
|
+
- `v3.1.0`: Overhauled the functionality for specifying the the length of a scale bar, including support for custom units/projections (similar to `matplotlib-scalebar`'s `dx` argument) and to specify the length of a major division instead of the entire scale bar, as requested [here](https://github.com/moss-xyz/matplotlib-map-utils/issues/10). Added ability to set artist-level `zorder` variables for all elements, with both the function and class method approaches, as requested [here](https://github.com/moss-xyz/matplotlib-map-utils/issues/9) and [here](https://github.com/moss-xyz/matplotlib-map-utils/issues/10). Also fixed a bug related to custom division labels on the scale bar.
|
407
|
+
|
362
408
|
#### Future Roadmap
|
363
409
|
|
364
410
|
With the release of `v3.x`, this project has achieved full coverage of the "main" map elements I think are necessary.
|
365
411
|
|
366
|
-
|
412
|
+
<details>
|
413
|
+
<summary><i>If I continue development of this project, I will be looking to add or fix the following features:</i></summary>
|
367
414
|
|
368
415
|
* For all: switch to a system based on Pydantic for easier type validation
|
369
416
|
|
@@ -399,14 +446,18 @@ If I continue development of this project, I will be looking to add or fix the f
|
|
399
446
|
|
400
447
|
Future releases (if the project is continued) will probably focus on other functions that I have created myself that give more control in the formatting of maps. I am also open to ideas for other extensions to create!
|
401
448
|
|
449
|
+
</details>
|
450
|
+
|
402
451
|
#### Support and Contributions
|
403
452
|
|
404
453
|
If you notice something is not working as intended or if you'd like to add a feature yourself, I welcome PRs - just be sure to be descriptive as to what you are changing and why, including code examples!
|
405
454
|
|
406
455
|
If you are having issues using this script, feel free to leave a post explaining your issue, and I will try and assist, though I have no guaranteed SLAs as this is just a hobby project.
|
407
456
|
|
457
|
+
I am open to contributions, especially to help tackle the roadmap above!
|
458
|
+
|
408
459
|
---
|
409
460
|
|
410
|
-
### License
|
461
|
+
### ⚖️ License
|
411
462
|
|
412
463
|
I know nothing about licensing, so I went with the GPL license. If that is incompatible with any of the dependencies, please let me know.
|
{matplotlib_map_utils-3.0.0 → matplotlib_map_utils-3.1.0}/matplotlib_map_utils/core/inset_map.py
RENAMED
@@ -46,6 +46,7 @@ class InsetMap(matplotlib.artist.Artist):
|
|
46
46
|
coords: imt._TYPE_INSET["coords"]=None,
|
47
47
|
transform=None,
|
48
48
|
to_plot=None,
|
49
|
+
zorder: int=99,
|
49
50
|
**kwargs):
|
50
51
|
# Starting up the object with the base properties of a matplotlib Artist
|
51
52
|
matplotlib.artist.Artist.__init__(self)
|
@@ -56,6 +57,7 @@ class InsetMap(matplotlib.artist.Artist):
|
|
56
57
|
self._pad = imf._validate(imt._VALIDATE_INSET, "pad", pad)
|
57
58
|
self._coords = imf._validate(imt._VALIDATE_INSET, "coords", coords)
|
58
59
|
self._to_plot = imf._validate(imt._VALIDATE_INSET, "to_plot", to_plot)
|
60
|
+
self._zorder = imf._validate(imt._VALIDATE_INSET, "zorder", zorder)
|
59
61
|
|
60
62
|
# Checking if we need to override values for size and pad
|
61
63
|
if self._size is None:
|
@@ -65,11 +67,6 @@ class InsetMap(matplotlib.artist.Artist):
|
|
65
67
|
|
66
68
|
self._transform = transform # not validated!
|
67
69
|
self._kwargs = kwargs # not validated!
|
68
|
-
|
69
|
-
# We do set the zorder for our objects individually,
|
70
|
-
# but we ALSO set it for the entire artist, here
|
71
|
-
# Thank you to matplotlib-scalebar for this tip
|
72
|
-
zorder = 99
|
73
70
|
|
74
71
|
## INTERNAL PROPERTIES ##
|
75
72
|
# This allows for easy-updating of properties
|
@@ -162,6 +159,16 @@ class InsetMap(matplotlib.artist.Artist):
|
|
162
159
|
def to_plot(self, val):
|
163
160
|
val = imf._validate(imt._VALIDATE_INSET, "to_plot", val)
|
164
161
|
self._to_plot = val
|
162
|
+
|
163
|
+
# zorder
|
164
|
+
@property
|
165
|
+
def zorder(self):
|
166
|
+
return self._zorder
|
167
|
+
|
168
|
+
@zorder.setter
|
169
|
+
def zorder(self, val):
|
170
|
+
val = imf._validate(imt._VALIDATE_INSET, "zorder", val)
|
171
|
+
self._zorder = val
|
165
172
|
|
166
173
|
## COPY FUNCTION ##
|
167
174
|
# This is solely to get around matplotlib's restrictions around re-using an artist across multiple axes
|
@@ -176,7 +183,7 @@ class InsetMap(matplotlib.artist.Artist):
|
|
176
183
|
def create(self, pax, **kwargs):
|
177
184
|
# Can re-use the drawing function we already established, but return the object instead
|
178
185
|
iax = inset_map(ax=pax, location=self._location, size=self._size,
|
179
|
-
pad=self._pad, coords=self._coords, transform=self._transform,
|
186
|
+
pad=self._pad, coords=self._coords, transform=self._transform, zorder=self._zorder,
|
180
187
|
**self._kwargs, **kwargs)
|
181
188
|
|
182
189
|
# If data is passed to to_plot, then we plot that on the newly created axis as well
|
@@ -226,6 +233,7 @@ class ExtentIndicator(matplotlib.artist.Artist):
|
|
226
233
|
linecolor: imt._TYPE_EXTENT["linecolor"]="red",
|
227
234
|
alpha: imt._TYPE_EXTENT["alpha"]=0.5,
|
228
235
|
linewidth: imt._TYPE_EXTENT["linewidth"]=1,
|
236
|
+
zorder: int=99,
|
229
237
|
**kwargs):
|
230
238
|
# Starting up the object with the base properties of a matplotlib Artist
|
231
239
|
matplotlib.artist.Artist.__init__(self)
|
@@ -239,13 +247,9 @@ class ExtentIndicator(matplotlib.artist.Artist):
|
|
239
247
|
self._linecolor = imf._validate(imt._VALIDATE_EXTENT, "linecolor", linecolor)
|
240
248
|
self._alpha = imf._validate(imt._VALIDATE_EXTENT, "alpha", alpha)
|
241
249
|
self._linewidth = imf._validate(imt._VALIDATE_EXTENT, "linewidth", linewidth)
|
250
|
+
self._zorder = imf._validate(imt._VALIDATE_EXTENT, "zorder", zorder)
|
242
251
|
|
243
252
|
self._kwargs = kwargs # not validated!
|
244
|
-
|
245
|
-
# We do set the zorder for our objects individually,
|
246
|
-
# but we ALSO set it for the entire artist, here
|
247
|
-
# Thank you to matplotlib-scalebar for this tip
|
248
|
-
zorder = 99
|
249
253
|
|
250
254
|
## INTERNAL PROPERTIES ##
|
251
255
|
# This allows for easy-updating of properties
|
@@ -332,6 +336,16 @@ class ExtentIndicator(matplotlib.artist.Artist):
|
|
332
336
|
def linewidth(self, val):
|
333
337
|
val = imf._validate(imt._VALIDATE_EXTENT, "linewidth", val)
|
334
338
|
self._linewidth = val
|
339
|
+
|
340
|
+
# zorder
|
341
|
+
@property
|
342
|
+
def zorder(self):
|
343
|
+
return self._zorder
|
344
|
+
|
345
|
+
@zorder.setter
|
346
|
+
def zorder(self, val):
|
347
|
+
val = imf._validate(imt._VALIDATE_EXTENT, "zorder", val)
|
348
|
+
self._zorder = val
|
335
349
|
|
336
350
|
# kwargs
|
337
351
|
@property
|
@@ -366,7 +380,7 @@ class ExtentIndicator(matplotlib.artist.Artist):
|
|
366
380
|
to_return=self._to_return, straighten=self._straighten,
|
367
381
|
pad=self._pad, plot=self._plot,
|
368
382
|
facecolor=self._facecolor, linecolor=self._linecolor,
|
369
|
-
alpha=self._alpha, linewidth=self._linewidth,
|
383
|
+
alpha=self._alpha, linewidth=self._linewidth, zorder=self._zorder,
|
370
384
|
**self._kwargs, **kwargs)
|
371
385
|
|
372
386
|
# The indicator will be drawn automatically if plot is True
|
@@ -389,6 +403,7 @@ class DetailIndicator(matplotlib.artist.Artist):
|
|
389
403
|
linewidth: imt._TYPE_EXTENT["linewidth"]=1,
|
390
404
|
connector_color: imt._TYPE_DETAIL["connector_color"]="black",
|
391
405
|
connector_width: imt._TYPE_DETAIL["connector_width"]=1,
|
406
|
+
zorder: int=99,
|
392
407
|
**kwargs):
|
393
408
|
# Starting up the object with the base properties of a matplotlib Artist
|
394
409
|
matplotlib.artist.Artist.__init__(self)
|
@@ -404,13 +419,9 @@ class DetailIndicator(matplotlib.artist.Artist):
|
|
404
419
|
self._to_return = imf._validate(imt._VALIDATE_DETAIL, "to_return", to_return)
|
405
420
|
self._connector_color = imf._validate(imt._VALIDATE_DETAIL, "connector_color", connector_color)
|
406
421
|
self._connector_width = imf._validate(imt._VALIDATE_DETAIL, "connector_width", connector_width)
|
422
|
+
self._zorder = imf._validate(imt._VALIDATE_DETAIL, "zorder", zorder)
|
407
423
|
|
408
424
|
self._kwargs = kwargs # not validated!
|
409
|
-
|
410
|
-
# We do set the zorder for our objects individually,
|
411
|
-
# but we ALSO set it for the entire artist, here
|
412
|
-
# Thank you to matplotlib-scalebar for this tip
|
413
|
-
zorder = 99
|
414
425
|
|
415
426
|
## INTERNAL PROPERTIES ##
|
416
427
|
# This allows for easy-updating of properties
|
@@ -517,6 +528,16 @@ class DetailIndicator(matplotlib.artist.Artist):
|
|
517
528
|
def connector_width(self, val):
|
518
529
|
val = imf._validate(imt._VALIDATE_DETAIL, "connector_width", val)
|
519
530
|
self._connector_width = val
|
531
|
+
|
532
|
+
# zorder
|
533
|
+
@property
|
534
|
+
def zorder(self):
|
535
|
+
return self._zorder
|
536
|
+
|
537
|
+
@zorder.setter
|
538
|
+
def zorder(self, val):
|
539
|
+
val = imf._validate(imt._VALIDATE_DETAIL, "zorder", val)
|
540
|
+
self._zorder = val
|
520
541
|
|
521
542
|
# kwargs
|
522
543
|
@property
|
@@ -544,7 +565,8 @@ class DetailIndicator(matplotlib.artist.Artist):
|
|
544
565
|
pax: imt._TYPE_EXTENT["pax"],
|
545
566
|
iax: imt._TYPE_EXTENT["bax"],
|
546
567
|
pcrs: imt._TYPE_EXTENT["pcrs"],
|
547
|
-
icrs: imt._TYPE_EXTENT["bcrs"],
|
568
|
+
icrs: imt._TYPE_EXTENT["bcrs"],
|
569
|
+
**kwargs):
|
548
570
|
|
549
571
|
# Can re-use the drawing function we already established, but return the object instead
|
550
572
|
dti = indicate_detail(pax=pax, iax=iax, pcrs=pcrs, icrs=icrs,
|
@@ -554,6 +576,7 @@ class DetailIndicator(matplotlib.artist.Artist):
|
|
554
576
|
alpha=self._alpha, linewidth=self._linewidth,
|
555
577
|
connector_color=self._connector_color,
|
556
578
|
connector_width=self._connector_width,
|
579
|
+
zorder=self._zorder,
|
557
580
|
**self._kwargs, **kwargs)
|
558
581
|
|
559
582
|
# The indicator will be drawn automatically if plot is True
|
@@ -573,6 +596,7 @@ def inset_map(ax,
|
|
573
596
|
pad: imt._TYPE_INSET["pad"]=None,
|
574
597
|
coords: imt._TYPE_INSET["coords"]=None,
|
575
598
|
transform=None,
|
599
|
+
zorder: int=99,
|
576
600
|
**kwargs):
|
577
601
|
|
578
602
|
## VALIDATION ##
|
@@ -580,6 +604,7 @@ def inset_map(ax,
|
|
580
604
|
size = imf._validate(imt._VALIDATE_INSET, "size", size)
|
581
605
|
pad = imf._validate(imt._VALIDATE_INSET, "pad", pad)
|
582
606
|
coords = imf._validate(imt._VALIDATE_INSET, "coords", coords)
|
607
|
+
zorder = imf._validate(imt._VALIDATE_INSET, "zorder", zorder)
|
583
608
|
|
584
609
|
if size is None:
|
585
610
|
size = _DEFAULT_INSET_MAP["size"]
|
@@ -671,7 +696,7 @@ def inset_map(ax,
|
|
671
696
|
## DRAWING ##
|
672
697
|
# Creating the new inset map with the specified height, width, and location
|
673
698
|
# by default, inset_axes requires everything to be in ax.transAxes coordinates
|
674
|
-
iax = ax.inset_axes([x, y, inset_width, inset_height], **kwargs)
|
699
|
+
iax = ax.inset_axes([x, y, inset_width, inset_height], zorder=zorder, **kwargs)
|
675
700
|
|
676
701
|
# We also set the anchor here, such that it stays fixed when any resizing takes place
|
677
702
|
loc_anchors = {
|
@@ -701,6 +726,7 @@ def indicate_extent(pax: imt._TYPE_EXTENT["pax"],
|
|
701
726
|
linecolor: imt._TYPE_EXTENT["linecolor"]="red",
|
702
727
|
alpha: imt._TYPE_EXTENT["alpha"]=0.5,
|
703
728
|
linewidth: imt._TYPE_EXTENT["linewidth"]=1,
|
729
|
+
zorder: int=99,
|
704
730
|
**kwargs):
|
705
731
|
|
706
732
|
## VALIDATION ##
|
@@ -716,6 +742,7 @@ def indicate_extent(pax: imt._TYPE_EXTENT["pax"],
|
|
716
742
|
linecolor = imf._validate(imt._VALIDATE_EXTENT, "linecolor", linecolor)
|
717
743
|
alpha = imf._validate(imt._VALIDATE_EXTENT, "alpha", alpha)
|
718
744
|
linewidth = imf._validate(imt._VALIDATE_EXTENT, "linewidth", linewidth)
|
745
|
+
zorder = imf._validate(imt._VALIDATE_EXTENT, "zorder", zorder)
|
719
746
|
|
720
747
|
# Make sure the figure layout is calculated
|
721
748
|
fig = pax.get_figure()
|
@@ -748,15 +775,13 @@ def indicate_extent(pax: imt._TYPE_EXTENT["pax"],
|
|
748
775
|
# Straightening the points if desired
|
749
776
|
if straighten == True:
|
750
777
|
extent_shape = shapely.envelope(extent_shape)
|
751
|
-
|
752
|
-
# return extent_shape
|
753
|
-
|
778
|
+
|
754
779
|
# Plotting, if desired
|
755
780
|
if plot == True:
|
756
781
|
# Note that the alpha ONLY applies to the facecolor!
|
757
782
|
extent_patch = matplotlib.patches.Polygon(list(extent_shape.exterior.coords), transform=pax.transData,
|
758
783
|
facecolor=matplotlib.colors.to_rgba(facecolor, alpha=alpha),
|
759
|
-
edgecolor=linecolor, linewidth=linewidth, **kwargs)
|
784
|
+
edgecolor=linecolor, linewidth=linewidth, zorder=zorder, **kwargs)
|
760
785
|
pax.add_artist(extent_patch)
|
761
786
|
|
762
787
|
# Deciding what we need to return
|
@@ -789,8 +814,7 @@ def indicate_detail(pax: imt._TYPE_EXTENT["pax"],
|
|
789
814
|
alpha: imt._TYPE_EXTENT["alpha"]=1,
|
790
815
|
linecolor: imt._TYPE_EXTENT["linecolor"]="black",
|
791
816
|
linewidth: imt._TYPE_EXTENT["linewidth"]=1,
|
792
|
-
|
793
|
-
# connector_width: imt._TYPE_DETAIL["connector_width"]=1,
|
817
|
+
zorder: int=99,
|
794
818
|
**kwargs):
|
795
819
|
|
796
820
|
fig = pax.get_figure()
|
@@ -809,8 +833,7 @@ def indicate_detail(pax: imt._TYPE_EXTENT["pax"],
|
|
809
833
|
alpha = imf._validate(imt._VALIDATE_EXTENT, "alpha", alpha)
|
810
834
|
linecolor = imf._validate(imt._VALIDATE_EXTENT, "linecolor", linecolor)
|
811
835
|
linewidth = imf._validate(imt._VALIDATE_EXTENT, "linewidth", linewidth)
|
812
|
-
|
813
|
-
# connector_width = imf._validate(imt._VALIDATE_DETAIL, "connector_width", connector_width)
|
836
|
+
zorder = imf._validate(imt._VALIDATE_EXTENT, "zorder", zorder)
|
814
837
|
|
815
838
|
# Drawing the extent indicator on the main map
|
816
839
|
# Setting to_return="ax" gets us the corners of the patch in pax.transAxes coordinates
|
@@ -819,7 +842,7 @@ def indicate_detail(pax: imt._TYPE_EXTENT["pax"],
|
|
819
842
|
straighten=straighten, pad=pad, plot=plot,
|
820
843
|
facecolor=facecolor, linecolor=linecolor,
|
821
844
|
alpha=alpha, linewidth=linewidth*1.25,
|
822
|
-
to_return="ax", **kwargs)[:4]
|
845
|
+
to_return="ax", zorder=zorder, **kwargs)[:4]
|
823
846
|
|
824
847
|
# Getting the inset axis points and transforming them to the parent axis CRS
|
825
848
|
corners_inset = _inset_corners_to_parent(pax, iax)
|
@@ -873,12 +896,13 @@ def indicate_detail(pax: imt._TYPE_EXTENT["pax"],
|
|
873
896
|
for c in connections:
|
874
897
|
# This is listed as [extent_x, inset_x], [extent_y, inset_y]
|
875
898
|
pax.plot([c[0][0], c[1][0]], [c[0][1], c[1][1]],
|
876
|
-
color=linecolor, linewidth=linewidth, transform=pax.transAxes)
|
899
|
+
color=linecolor, linewidth=linewidth, transform=pax.transAxes, zorder=zorder+1)
|
877
900
|
|
878
|
-
# Also updating the linewidth and color of the inset map
|
879
|
-
|
880
|
-
|
881
|
-
|
901
|
+
# Also updating the linewidth and color of the inset map itself, to match
|
902
|
+
iax.spines[:].set_linewidth(linewidth*1.2) # making this slightly thicker
|
903
|
+
iax.spines[:].set_edgecolor(linecolor)
|
904
|
+
iax.set_zorder(zorder+2)
|
905
|
+
iax.spines[:].set_zorder(zorder+2)
|
882
906
|
|
883
907
|
# Returning as requested
|
884
908
|
if to_return is None:
|
@@ -893,37 +917,37 @@ def indicate_detail(pax: imt._TYPE_EXTENT["pax"],
|
|
893
917
|
# This is a top-level helping function
|
894
918
|
# that will return an axis with inset maps drawn for Alaska, Hawaii, DC, and/or Puerto Rico
|
895
919
|
# NOTE that as of this initial release, it assumes your map is in CRS 3857 for positioning
|
896
|
-
def inset_usa(ax, alaska=True, hawaii=True, dc=True, puerto_rico=True, size=None, pad=None, **kwargs):
|
920
|
+
def inset_usa(ax, alaska=True, hawaii=True, dc=True, puerto_rico=True, size=None, pad=None, zorder: int=99, **kwargs):
|
897
921
|
# This will return all of the axes we create
|
898
922
|
to_return = []
|
899
923
|
|
900
924
|
# Alaska and Hawaii are positioned relative to each other
|
901
925
|
if alaska == True and hawaii == True:
|
902
|
-
aax = inset_map(ax, "lower left", size, pad, **kwargs)
|
926
|
+
aax = inset_map(ax, "lower left", size, pad, zorder=zorder, **kwargs)
|
903
927
|
to_return.append(aax)
|
904
928
|
# Need to shift over the hawaii axis by the size of the alaska axis
|
905
929
|
# Note that we add xmax and xmin together here, to account for the padding (xmin is the amount of padding)
|
906
930
|
shift_right = float(aax.get_window_extent().transformed(ax.transAxes.inverted()).xmax) + float(aax.get_window_extent().transformed(ax.transAxes.inverted()).xmin)
|
907
931
|
# also need to shift it up, by the amount of the padding (which we can crib from ymin)
|
908
932
|
shift_up = float(aax.get_window_extent().transformed(ax.transAxes.inverted()).ymin)
|
909
|
-
hax = inset_map(ax, "lower left", size, pad, coords=(shift_right, shift_up), **kwargs)
|
933
|
+
hax = inset_map(ax, "lower left", size, pad, zorder=zorder, coords=(shift_right, shift_up), **kwargs)
|
910
934
|
to_return.append(hax)
|
911
935
|
else:
|
912
936
|
if alaska == True:
|
913
|
-
aax = inset_map(ax, "lower_left", size, pad, **kwargs)
|
937
|
+
aax = inset_map(ax, "lower_left", size, pad, zorder=zorder, **kwargs)
|
914
938
|
to_return.append(aax)
|
915
939
|
if hawaii == True:
|
916
|
-
hax = inset_map(ax, "lower left", size, pad, **kwargs)
|
940
|
+
hax = inset_map(ax, "lower left", size, pad, zorder=zorder, **kwargs)
|
917
941
|
to_return.append(hax)
|
918
942
|
|
919
943
|
# Puerto Rico is positioned off the coast of Florida
|
920
944
|
if puerto_rico == True:
|
921
|
-
pax = inset_map(ax, "lower right", size, pad, **kwargs)
|
945
|
+
pax = inset_map(ax, "lower right", size, pad, zorder=zorder, **kwargs)
|
922
946
|
to_return.append(pax)
|
923
947
|
|
924
948
|
# DC is off the coast of DC
|
925
949
|
if dc == True:
|
926
|
-
dax = inset_map(ax, "center right", size, pad, **kwargs)
|
950
|
+
dax = inset_map(ax, "center right", size, pad, zorder=zorder, **kwargs)
|
927
951
|
to_return.append(dax)
|
928
952
|
|
929
953
|
# Finally, returning everything
|