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.
Files changed (29) hide show
  1. {matplotlib_map_utils-3.0.0 → matplotlib_map_utils-3.1.0}/PKG-INFO +59 -8
  2. {matplotlib_map_utils-3.0.0 → matplotlib_map_utils-3.1.0}/README.md +58 -7
  3. {matplotlib_map_utils-3.0.0 → matplotlib_map_utils-3.1.0}/matplotlib_map_utils/core/inset_map.py +64 -40
  4. {matplotlib_map_utils-3.0.0 → matplotlib_map_utils-3.1.0}/matplotlib_map_utils/core/north_arrow.py +24 -9
  5. {matplotlib_map_utils-3.0.0 → matplotlib_map_utils-3.1.0}/matplotlib_map_utils/core/scale_bar.py +265 -190
  6. {matplotlib_map_utils-3.0.0 → matplotlib_map_utils-3.1.0}/matplotlib_map_utils/defaults/scale_bar.py +5 -0
  7. {matplotlib_map_utils-3.0.0 → matplotlib_map_utils-3.1.0}/matplotlib_map_utils/validation/functions.py +3 -6
  8. {matplotlib_map_utils-3.0.0 → matplotlib_map_utils-3.1.0}/matplotlib_map_utils/validation/inset_map.py +3 -0
  9. {matplotlib_map_utils-3.0.0 → matplotlib_map_utils-3.1.0}/matplotlib_map_utils/validation/north_arrow.py +1 -0
  10. {matplotlib_map_utils-3.0.0 → matplotlib_map_utils-3.1.0}/matplotlib_map_utils/validation/scale_bar.py +7 -4
  11. {matplotlib_map_utils-3.0.0 → matplotlib_map_utils-3.1.0}/matplotlib_map_utils.egg-info/PKG-INFO +59 -8
  12. {matplotlib_map_utils-3.0.0 → matplotlib_map_utils-3.1.0}/matplotlib_map_utils.egg-info/top_level.txt +0 -1
  13. {matplotlib_map_utils-3.0.0 → matplotlib_map_utils-3.1.0}/pyproject.toml +1 -1
  14. {matplotlib_map_utils-3.0.0 → matplotlib_map_utils-3.1.0}/LICENSE +0 -0
  15. {matplotlib_map_utils-3.0.0 → matplotlib_map_utils-3.1.0}/matplotlib_map_utils/__init__.py +0 -0
  16. {matplotlib_map_utils-3.0.0 → matplotlib_map_utils-3.1.0}/matplotlib_map_utils/core/__init__.py +0 -0
  17. {matplotlib_map_utils-3.0.0 → matplotlib_map_utils-3.1.0}/matplotlib_map_utils/defaults/__init__.py +0 -0
  18. {matplotlib_map_utils-3.0.0 → matplotlib_map_utils-3.1.0}/matplotlib_map_utils/defaults/inset_map.py +0 -0
  19. {matplotlib_map_utils-3.0.0 → matplotlib_map_utils-3.1.0}/matplotlib_map_utils/defaults/north_arrow.py +0 -0
  20. {matplotlib_map_utils-3.0.0 → matplotlib_map_utils-3.1.0}/matplotlib_map_utils/scratch/map_utils.py +0 -0
  21. {matplotlib_map_utils-3.0.0 → matplotlib_map_utils-3.1.0}/matplotlib_map_utils/scratch/north_arrow_old_classes.py +0 -0
  22. {matplotlib_map_utils-3.0.0 → matplotlib_map_utils-3.1.0}/matplotlib_map_utils/utils/__init__.py +0 -0
  23. {matplotlib_map_utils-3.0.0 → matplotlib_map_utils-3.1.0}/matplotlib_map_utils/utils/usa.json +0 -0
  24. {matplotlib_map_utils-3.0.0 → matplotlib_map_utils-3.1.0}/matplotlib_map_utils/utils/usa.py +0 -0
  25. {matplotlib_map_utils-3.0.0 → matplotlib_map_utils-3.1.0}/matplotlib_map_utils/validation/__init__.py +0 -0
  26. {matplotlib_map_utils-3.0.0 → matplotlib_map_utils-3.1.0}/matplotlib_map_utils.egg-info/SOURCES.txt +0 -0
  27. {matplotlib_map_utils-3.0.0 → matplotlib_map_utils-3.1.0}/matplotlib_map_utils.egg-info/dependency_links.txt +0 -0
  28. {matplotlib_map_utils-3.0.0 → matplotlib_map_utils-3.1.0}/matplotlib_map_utils.egg-info/requires.txt +0 -0
  29. {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.0.0
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","Midtwest"], to_return="name")
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
- If I continue development of this project, I will be looking to add or fix the following features:
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","Midtwest"], to_return="name")
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
- If I continue development of this project, I will be looking to add or fix the following features:
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.
@@ -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"], **kwargs):
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
- # connector_color: imt._TYPE_DETAIL["connector_color"]="black",
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
- # connector_color = imf._validate(imt._VALIDATE_DETAIL, "connector_color", connector_color)
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 itsef, to match
879
- for a in ["top","bottom","left","right"]:
880
- iax.spines[a].set_linewidth(linewidth*1.2) # making this slightly thicker
881
- iax.spines[a].set_edgecolor(linecolor)
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