matplotlib-map-utils 2.1.0__tar.gz → 3.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.
Files changed (31) hide show
  1. {matplotlib_map_utils-2.1.0 → matplotlib_map_utils-3.0.1}/PKG-INFO +121 -20
  2. {matplotlib_map_utils-2.1.0 → matplotlib_map_utils-3.0.1}/README.md +119 -19
  3. matplotlib_map_utils-3.0.1/matplotlib_map_utils/__init__.py +21 -0
  4. matplotlib_map_utils-3.0.1/matplotlib_map_utils/core/__init__.py +8 -0
  5. matplotlib_map_utils-3.0.1/matplotlib_map_utils/core/inset_map.py +952 -0
  6. {matplotlib_map_utils-2.1.0 → matplotlib_map_utils-3.0.1}/matplotlib_map_utils/core/north_arrow.py +0 -4
  7. {matplotlib_map_utils-2.1.0 → matplotlib_map_utils-3.0.1}/matplotlib_map_utils/core/scale_bar.py +16 -11
  8. matplotlib_map_utils-3.0.1/matplotlib_map_utils/defaults/inset_map.py +67 -0
  9. {matplotlib_map_utils-2.1.0 → matplotlib_map_utils-3.0.1}/matplotlib_map_utils/validation/functions.py +51 -15
  10. matplotlib_map_utils-3.0.1/matplotlib_map_utils/validation/inset_map.py +88 -0
  11. {matplotlib_map_utils-2.1.0 → matplotlib_map_utils-3.0.1}/matplotlib_map_utils/validation/north_arrow.py +1 -1
  12. {matplotlib_map_utils-2.1.0 → matplotlib_map_utils-3.0.1}/matplotlib_map_utils/validation/scale_bar.py +3 -5
  13. {matplotlib_map_utils-2.1.0 → matplotlib_map_utils-3.0.1}/matplotlib_map_utils.egg-info/PKG-INFO +121 -20
  14. {matplotlib_map_utils-2.1.0 → matplotlib_map_utils-3.0.1}/matplotlib_map_utils.egg-info/SOURCES.txt +3 -0
  15. {matplotlib_map_utils-2.1.0 → matplotlib_map_utils-3.0.1}/pyproject.toml +2 -1
  16. matplotlib_map_utils-2.1.0/matplotlib_map_utils/__init__.py +0 -6
  17. matplotlib_map_utils-2.1.0/matplotlib_map_utils/core/__init__.py +0 -4
  18. {matplotlib_map_utils-2.1.0 → matplotlib_map_utils-3.0.1}/LICENSE +0 -0
  19. {matplotlib_map_utils-2.1.0 → matplotlib_map_utils-3.0.1}/matplotlib_map_utils/defaults/__init__.py +0 -0
  20. {matplotlib_map_utils-2.1.0 → matplotlib_map_utils-3.0.1}/matplotlib_map_utils/defaults/north_arrow.py +0 -0
  21. {matplotlib_map_utils-2.1.0 → matplotlib_map_utils-3.0.1}/matplotlib_map_utils/defaults/scale_bar.py +0 -0
  22. {matplotlib_map_utils-2.1.0 → matplotlib_map_utils-3.0.1}/matplotlib_map_utils/scratch/map_utils.py +0 -0
  23. {matplotlib_map_utils-2.1.0 → matplotlib_map_utils-3.0.1}/matplotlib_map_utils/scratch/north_arrow_old_classes.py +0 -0
  24. {matplotlib_map_utils-2.1.0 → matplotlib_map_utils-3.0.1}/matplotlib_map_utils/utils/__init__.py +0 -0
  25. {matplotlib_map_utils-2.1.0 → matplotlib_map_utils-3.0.1}/matplotlib_map_utils/utils/usa.json +0 -0
  26. {matplotlib_map_utils-2.1.0 → matplotlib_map_utils-3.0.1}/matplotlib_map_utils/utils/usa.py +0 -0
  27. {matplotlib_map_utils-2.1.0 → matplotlib_map_utils-3.0.1}/matplotlib_map_utils/validation/__init__.py +0 -0
  28. {matplotlib_map_utils-2.1.0 → matplotlib_map_utils-3.0.1}/matplotlib_map_utils.egg-info/dependency_links.txt +0 -0
  29. {matplotlib_map_utils-2.1.0 → matplotlib_map_utils-3.0.1}/matplotlib_map_utils.egg-info/requires.txt +0 -0
  30. {matplotlib_map_utils-2.1.0 → matplotlib_map_utils-3.0.1}/matplotlib_map_utils.egg-info/top_level.txt +0 -0
  31. {matplotlib_map_utils-2.1.0 → matplotlib_map_utils-3.0.1}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: matplotlib-map-utils
3
- Version: 2.1.0
3
+ Version: 3.0.1
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/
@@ -8,6 +8,7 @@ Project-URL: Bug Tracker, https://github.com/moss-xyz/matplotlib-map-utils/issue
8
8
  Classifier: Programming Language :: Python :: 3
9
9
  Classifier: License :: OSI Approved :: GNU General Public License (GPL)
10
10
  Classifier: Operating System :: OS Independent
11
+ Classifier: Framework :: Matplotlib
11
12
  Requires-Python: >=3.10
12
13
  Description-Content-Type: text/markdown
13
14
  License-File: LICENSE
@@ -16,13 +17,15 @@ Requires-Dist: cartopy>=0.23.0
16
17
  Requires-Dist: great-circle-calculator>=1.3.1
17
18
  Dynamic: license-file
18
19
 
19
- # matplotlib-map-utils
20
+ ![matplotlib_map_utils logo](matplotlib_map_utils/docs/assets/mmu_logo_w_elements.png)
20
21
 
21
22
  ---
22
23
 
23
- **Documentation**: See `docs` folder
24
+ **Documentation:** See `docs` folder
24
25
 
25
- **Source Code**: [Available on GitHub](https://github.com/moss-xyz/matplotlib-map-utils)
26
+ **Source Code:** [Available on GitHub](https://github.com/moss-xyz/matplotlib-map-utils)
27
+
28
+ **Feedback:** I welcome any and all feedback! See the *Development Notes* below for more details.
26
29
 
27
30
  ---
28
31
 
@@ -30,15 +33,23 @@ Dynamic: license-file
30
33
 
31
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/).
32
35
 
33
- As of `v2.x` (the current version), this includes two tools and one utility:
36
+ As of `v3.x` (the current version), this includes three-ish elements:
37
+
38
+ * `north_arrow.py`, for adding a north arrow to a given plot.
39
+
40
+ * `scale_bar.py`, for adding a scale bar to a given plot.
41
+
42
+ * `inset_map.py`, for adding inset maps and detail/extent indicators to a given plot.
34
43
 
35
- * `north_arrow.py`, which generates a high quality, context-aware north arrow for a given plot.
44
+ The three elements listed above are all intended to be high-resolution, easily modifiable, and context-aware, relative to your specific plot.
36
45
 
37
- * `scale_bar.py`, which generates a high quality, context-aware scale bar to a given plot.
46
+ This package also contains a single utility object:
38
47
 
39
48
  * `usa.py`, which contains a class that helps filter for states and territories within the USA based on given characteristics.
40
49
 
41
- Future releases (if the project is continued) might provide a similar tool inset maps, or other functions that I have created myself that give more control in the formatting of maps.
50
+ Together, these allow for the easy creation of a map such as the following:
51
+
52
+ ![Map with all common elements added](matplotlib_map_utils/docs/assets/readme_bigmap.png)
42
53
 
43
54
  ---
44
55
 
@@ -62,7 +73,8 @@ The requirements for this package are:
62
73
 
63
74
  ### Package Structure
64
75
 
65
- The package is arrayed in the following way:
76
+ <details>
77
+ <summary><i>The package is arrayed in the following way:</i></summary>
66
78
 
67
79
  ```bash
68
80
  package_name/
@@ -70,17 +82,20 @@ package_name/
70
82
 
71
83
  ├── core/
72
84
  │ ├── __init__.py
85
+ │ ├── inset_map.py
73
86
  │ ├── north_arrow.py
74
87
  │ ├── scale_bar.py
75
88
  ├── validation/
76
89
  │ ├── __init__.py
77
90
  │ ├── functions.py
91
+ │ └── inset_map.py
78
92
  │ ├── north_arrow.py
79
93
  │ └── scale_bar.py
80
94
  ├── defaults/
81
95
  │ ├── __init__.py
82
96
  │ ├── north_arrow.py
83
97
  │ └── scale_bar.py
98
+ │ └── inset_map.py
84
99
  ├── utils/
85
100
  │ ├── __init__.py
86
101
  │ ├── usa.py
@@ -95,9 +110,13 @@ Where:
95
110
 
96
111
  * `defaults` contains default settings for each object at different paper sizes
97
112
 
113
+ * `utils` contains utility functions and objects
114
+
115
+ </details>
116
+
98
117
  ---
99
118
 
100
- ### North Arrow
119
+ ### 🧭 North Arrow
101
120
 
102
121
  <details>
103
122
  <summary><i>Expand instructions</i></summary>
@@ -108,6 +127,8 @@ Importing the North Arrow functions and classes can be done like so:
108
127
 
109
128
  ```py
110
129
  from matplotlib_map_utils.core.north_arrow import NorthArrow, north_arrow
130
+ from matplotlib_map_utils.core import NorthArrow, north_arrow # also valid
131
+ from matplotlib_map_utils import NorthArrow, north_arrow # also valid
111
132
  ```
112
133
 
113
134
  The quickest way to add a single north arrow to a single plot is to use the `north_arrow` function:
@@ -171,7 +192,7 @@ Instructions for how to do so can be found in `docs\howto_north_arrow`.
171
192
 
172
193
  ---
173
194
 
174
- ### Scale Bar
195
+ ### 📏 Scale Bar
175
196
 
176
197
  <details>
177
198
  <summary><i>Expand instructions</i></summary>
@@ -182,12 +203,16 @@ Importing the Scale Bar functions and classes can be done like so:
182
203
 
183
204
  ```py
184
205
  from matplotlib_map_utils.core.scale_bar import ScaleBar, scale_bar
206
+ from matplotlib_map_utils.core import ScaleBar, scale_bar # also valid
207
+ from matplotlib_map_utils import ScaleBar, scale_bar # also valid
185
208
  ```
186
209
 
187
210
  There are two available styles for the scale bars: `boxes` and `ticks`. The quickest way to add one to a single plot is to use the `scale_bar` function:
188
211
 
189
212
  ```python
190
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!
191
216
  fig, ax = matplotlib.pyplot.subplots(1,1, figsize=(5,5), dpi=150)
192
217
  # Adding a scale bar to the upper-right corner of the axis, in the same projection as whatever geodata you plotted
193
218
  # Here, this scale bar will have the "boxes" style
@@ -198,10 +223,12 @@ An object-oriented approach is also supported:
198
223
 
199
224
  ```python
200
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!
201
228
  fig, ax = matplotlib.pyplot.subplots(1,1, figsize=(5,5), dpi=150)
202
229
  # Adding a scale bar to the upper-right corner of the axis, in the same projection as whatever geodata you plotted
203
230
  # Here, we change the boxes to "ticks"
204
- sb = ScaleBar(location="upper right", style="boxes", bar={"projection":3857})
231
+ sb = ScaleBar(location="upper right", style="ticks", bar={"projection":3857})
205
232
  # Adding the artist to the plot
206
233
  ax.add_artist(sb)
207
234
  ```
@@ -237,7 +264,67 @@ Refer to `docs\howto_scale_bar` for details on how to customize each facet of th
237
264
 
238
265
  ---
239
266
 
240
- ### Utilities
267
+ ### 🗺️ Inset Map
268
+
269
+ <details>
270
+ <summary><i>Expand instructions</i></summary>
271
+
272
+ #### Quick Start
273
+
274
+ Importing the Inset Map functions and classes can be done like so:
275
+
276
+ ```py
277
+ from matplotlib_map_utils.core.inset_map import InsetMap, inset_map, ExtentIndicator, indicate_extent, DetailIndicator, indicate_detail
278
+ from matplotlib_map_utils.core import InsetMap, inset_map, ExtentIndicator, indicate_extent, DetailIndicator, indicate_detail # also valid
279
+ from matplotlib_map_utils import InsetMap, inset_map, ExtentIndicator, indicate_extent, DetailIndicator, indicate_detail # also valid
280
+ ```
281
+
282
+ The quickest way to add a single inset map to an existing plot is the `inset_map` function:
283
+
284
+ ```python
285
+ # Setting up a plot
286
+ fig, ax = matplotlib.pyplot.subplots(1,1, figsize=(5,5), dpi=150)
287
+ # Adding an inset map to the upper-right corner of the axis
288
+ iax = inset_map(ax=ax, location="upper right", size=0.75, pad=0, xticks=[], yticks=[])
289
+ # You can now plot additional data to iax as desired
290
+ ```
291
+
292
+ An object-oriented approach is also supported:
293
+
294
+ ```python
295
+ # Setting up a plot
296
+ fig, ax = matplotlib.pyplot.subplots(1,1, figsize=(5,5), dpi=150)
297
+ # Creating an object for the inset map
298
+ im = InsetMap(location="upper right", size=0.75, pad=0, xticks=[], yticks=[])
299
+ # Adding the inset map template to the plot
300
+ iax = im.create(ax=ax)
301
+ # You can now plot additional data to iax as desired
302
+ ```
303
+
304
+ Both of these will create an output like the following:
305
+
306
+ ![Example inset map](matplotlib_map_utils/docs/assets/readme_insetmap.png)
307
+
308
+ #### Extent and Detail Indicators
309
+
310
+ Inset maps can be paired with either an extent or detail indicator, to provide additional geographic context to the inset map
311
+
312
+ ```python
313
+ indicate_extent(inset_axis, parent_axis, inset_crs, parent_crs, ...)
314
+ indicate_detail(parent_axis, inset_axis, parent_crs, inset_crs, ...)
315
+ ```
316
+
317
+ This will create an output like the following (extent indicator on the left, detail indicator on the right):
318
+
319
+ ![Customized scale bar](matplotlib_map_utils/docs/assets/readme_indicators.png)
320
+
321
+ Refer to `docs\howto_inset_map` for details on how to customize the inset map and indicators to your liking.
322
+
323
+ </details>
324
+
325
+ ---
326
+
327
+ ### 🛠️ Utilities
241
328
 
242
329
  <details>
243
330
  <summary><i>Expand instructions</i></summary>
@@ -283,23 +370,33 @@ Two more projects assisted with the creation of this script:
283
370
 
284
371
  #### Releases
285
372
 
286
- - `v2.0.1`: Fixed a bug in the `dual_bars()` function that prevented empty dictionaries to be passed. Also added a warning when auto-calculated bar widths appear to be exceeding the dimension of the axis (usually occurs when the axis is <2 kilometeres or miles long, depending on the units selected).
373
+ - `v1.0.x`: Initial releases featuring the North Arrow element, along with some minor bug fixes.
374
+
375
+ - `v2.0.0`: Initial release of the Scale Bar element.
376
+
377
+ - `v2.0.1`: Fixed a bug in the `dual_bars()` function that prevented empty dictionaries to be passed. Also added a warning when auto-calculated bar widths appear to be exceeding the dimension of the axis (usually occurs when the axis is <2 kilometers or miles long, depending on the units selected).
287
378
 
288
379
  - `v2.0.2`: Changed f-string formatting to alternate double and single quotes, so as to maintain compatibility with versions of Python before 3.12 (see [here](https://github.com/moss-xyz/matplotlib-map-utils/issues/3)). However, this did reveal that another aspect of the code, namely concatenating `type` in function arguments, requires 3.10, and so the minimum python version was incremented.
289
380
 
290
381
  - `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.
291
382
 
383
+ - `v3.0.0`: Release of inset map and extent and detail indicator classes and functions.
384
+
385
+ - `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).
386
+
292
387
  #### Future Roadmap
293
388
 
294
- With the release of `v2.x`, and the addition of **Scale Bar** tools, this project has achieved the two main objectives that I set out to.
389
+ With the release of `v3.x`, this project has achieved full coverage of the "main" map elements I think are necessary.
295
390
 
296
391
  If I continue development of this project, I will be looking to add or fix the following features:
297
392
 
393
+ * For all: switch to a system based on Pydantic for easier type validation
394
+
298
395
  * **North Arrow:**
299
396
 
300
397
  * Copy the image-rendering functionality of the Scale Bar to allow for rotation of the entire object, label and arrow together
301
398
 
302
- * Create more styles for the arrow, potentiallly including a compass rose and a line-only arrow
399
+ * Create more styles for the arrow, potentially including a compass rose and a line-only arrow
303
400
 
304
401
  * **Scale Bar:**
305
402
 
@@ -309,7 +406,13 @@ If I continue development of this project, I will be looking to add or fix the f
309
406
 
310
407
  * Clean up the variable naming scheme (consistency on `loc` vs `position`, `style` vs `type`, etc.)
311
408
 
312
- * Create more styles for the bar, potentiallly including dual boxes and a sawtooth bar
409
+ * Create more styles for the bar, potentially including dual boxes and a sawtooth bar
410
+
411
+ * **Inset Map:**
412
+
413
+ * Clean up the way that connectors are drawn for detail indicators
414
+
415
+ * New functionality for placing multiple inset maps at once (with context-aware positioning to prevent overlap with each other)
313
416
 
314
417
  * **Utils:**
315
418
 
@@ -319,9 +422,7 @@ If I continue development of this project, I will be looking to add or fix the f
319
422
 
320
423
  * (USA): Stronger typing options, so you don't have to recall which `region` or `division` types are available, etc.
321
424
 
322
- If that goes well, `v3` can then either create a tool for generating inset maps (which `matplotlib` has *some* support for), or the various functions that I have created in the past that assist with formatting a map "properly", such as centering on a given object.
323
-
324
- I am also open to ideas for other extensions to create!
425
+ 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!
325
426
 
326
427
  #### Support and Contributions
327
428
 
@@ -1,10 +1,12 @@
1
- # matplotlib-map-utils
1
+ ![matplotlib_map_utils logo](matplotlib_map_utils/docs/assets/mmu_logo_w_elements.png)
2
2
 
3
3
  ---
4
4
 
5
- **Documentation**: See `docs` folder
5
+ **Documentation:** See `docs` folder
6
6
 
7
- **Source Code**: [Available on GitHub](https://github.com/moss-xyz/matplotlib-map-utils)
7
+ **Source Code:** [Available on GitHub](https://github.com/moss-xyz/matplotlib-map-utils)
8
+
9
+ **Feedback:** I welcome any and all feedback! See the *Development Notes* below for more details.
8
10
 
9
11
  ---
10
12
 
@@ -12,15 +14,23 @@
12
14
 
13
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/).
14
16
 
15
- As of `v2.x` (the current version), this includes two tools and one utility:
17
+ As of `v3.x` (the current version), this includes three-ish elements:
18
+
19
+ * `north_arrow.py`, for adding a north arrow to a given plot.
20
+
21
+ * `scale_bar.py`, for adding a scale bar to a given plot.
22
+
23
+ * `inset_map.py`, for adding inset maps and detail/extent indicators to a given plot.
16
24
 
17
- * `north_arrow.py`, which generates a high quality, context-aware north arrow for a given plot.
25
+ The three elements listed above are all intended to be high-resolution, easily modifiable, and context-aware, relative to your specific plot.
18
26
 
19
- * `scale_bar.py`, which generates a high quality, context-aware scale bar to a given plot.
27
+ This package also contains a single utility object:
20
28
 
21
29
  * `usa.py`, which contains a class that helps filter for states and territories within the USA based on given characteristics.
22
30
 
23
- Future releases (if the project is continued) might provide a similar tool inset maps, or other functions that I have created myself that give more control in the formatting of maps.
31
+ Together, these allow for the easy creation of a map such as the following:
32
+
33
+ ![Map with all common elements added](matplotlib_map_utils/docs/assets/readme_bigmap.png)
24
34
 
25
35
  ---
26
36
 
@@ -44,7 +54,8 @@ The requirements for this package are:
44
54
 
45
55
  ### Package Structure
46
56
 
47
- The package is arrayed in the following way:
57
+ <details>
58
+ <summary><i>The package is arrayed in the following way:</i></summary>
48
59
 
49
60
  ```bash
50
61
  package_name/
@@ -52,17 +63,20 @@ package_name/
52
63
 
53
64
  ├── core/
54
65
  │ ├── __init__.py
66
+ │ ├── inset_map.py
55
67
  │ ├── north_arrow.py
56
68
  │ ├── scale_bar.py
57
69
  ├── validation/
58
70
  │ ├── __init__.py
59
71
  │ ├── functions.py
72
+ │ └── inset_map.py
60
73
  │ ├── north_arrow.py
61
74
  │ └── scale_bar.py
62
75
  ├── defaults/
63
76
  │ ├── __init__.py
64
77
  │ ├── north_arrow.py
65
78
  │ └── scale_bar.py
79
+ │ └── inset_map.py
66
80
  ├── utils/
67
81
  │ ├── __init__.py
68
82
  │ ├── usa.py
@@ -77,9 +91,13 @@ Where:
77
91
 
78
92
  * `defaults` contains default settings for each object at different paper sizes
79
93
 
94
+ * `utils` contains utility functions and objects
95
+
96
+ </details>
97
+
80
98
  ---
81
99
 
82
- ### North Arrow
100
+ ### 🧭 North Arrow
83
101
 
84
102
  <details>
85
103
  <summary><i>Expand instructions</i></summary>
@@ -90,6 +108,8 @@ Importing the North Arrow functions and classes can be done like so:
90
108
 
91
109
  ```py
92
110
  from matplotlib_map_utils.core.north_arrow import NorthArrow, north_arrow
111
+ from matplotlib_map_utils.core import NorthArrow, north_arrow # also valid
112
+ from matplotlib_map_utils import NorthArrow, north_arrow # also valid
93
113
  ```
94
114
 
95
115
  The quickest way to add a single north arrow to a single plot is to use the `north_arrow` function:
@@ -153,7 +173,7 @@ Instructions for how to do so can be found in `docs\howto_north_arrow`.
153
173
 
154
174
  ---
155
175
 
156
- ### Scale Bar
176
+ ### 📏 Scale Bar
157
177
 
158
178
  <details>
159
179
  <summary><i>Expand instructions</i></summary>
@@ -164,12 +184,16 @@ Importing the Scale Bar functions and classes can be done like so:
164
184
 
165
185
  ```py
166
186
  from matplotlib_map_utils.core.scale_bar import ScaleBar, scale_bar
187
+ from matplotlib_map_utils.core import ScaleBar, scale_bar # also valid
188
+ from matplotlib_map_utils import ScaleBar, scale_bar # also valid
167
189
  ```
168
190
 
169
191
  There are two available styles for the scale bars: `boxes` and `ticks`. The quickest way to add one to a single plot is to use the `scale_bar` function:
170
192
 
171
193
  ```python
172
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!
173
197
  fig, ax = matplotlib.pyplot.subplots(1,1, figsize=(5,5), dpi=150)
174
198
  # Adding a scale bar to the upper-right corner of the axis, in the same projection as whatever geodata you plotted
175
199
  # Here, this scale bar will have the "boxes" style
@@ -180,10 +204,12 @@ An object-oriented approach is also supported:
180
204
 
181
205
  ```python
182
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!
183
209
  fig, ax = matplotlib.pyplot.subplots(1,1, figsize=(5,5), dpi=150)
184
210
  # Adding a scale bar to the upper-right corner of the axis, in the same projection as whatever geodata you plotted
185
211
  # Here, we change the boxes to "ticks"
186
- sb = ScaleBar(location="upper right", style="boxes", bar={"projection":3857})
212
+ sb = ScaleBar(location="upper right", style="ticks", bar={"projection":3857})
187
213
  # Adding the artist to the plot
188
214
  ax.add_artist(sb)
189
215
  ```
@@ -219,7 +245,67 @@ Refer to `docs\howto_scale_bar` for details on how to customize each facet of th
219
245
 
220
246
  ---
221
247
 
222
- ### Utilities
248
+ ### 🗺️ Inset Map
249
+
250
+ <details>
251
+ <summary><i>Expand instructions</i></summary>
252
+
253
+ #### Quick Start
254
+
255
+ Importing the Inset Map functions and classes can be done like so:
256
+
257
+ ```py
258
+ from matplotlib_map_utils.core.inset_map import InsetMap, inset_map, ExtentIndicator, indicate_extent, DetailIndicator, indicate_detail
259
+ from matplotlib_map_utils.core import InsetMap, inset_map, ExtentIndicator, indicate_extent, DetailIndicator, indicate_detail # also valid
260
+ from matplotlib_map_utils import InsetMap, inset_map, ExtentIndicator, indicate_extent, DetailIndicator, indicate_detail # also valid
261
+ ```
262
+
263
+ The quickest way to add a single inset map to an existing plot is the `inset_map` function:
264
+
265
+ ```python
266
+ # Setting up a plot
267
+ fig, ax = matplotlib.pyplot.subplots(1,1, figsize=(5,5), dpi=150)
268
+ # Adding an inset map to the upper-right corner of the axis
269
+ iax = inset_map(ax=ax, location="upper right", size=0.75, pad=0, xticks=[], yticks=[])
270
+ # You can now plot additional data to iax as desired
271
+ ```
272
+
273
+ An object-oriented approach is also supported:
274
+
275
+ ```python
276
+ # Setting up a plot
277
+ fig, ax = matplotlib.pyplot.subplots(1,1, figsize=(5,5), dpi=150)
278
+ # Creating an object for the inset map
279
+ im = InsetMap(location="upper right", size=0.75, pad=0, xticks=[], yticks=[])
280
+ # Adding the inset map template to the plot
281
+ iax = im.create(ax=ax)
282
+ # You can now plot additional data to iax as desired
283
+ ```
284
+
285
+ Both of these will create an output like the following:
286
+
287
+ ![Example inset map](matplotlib_map_utils/docs/assets/readme_insetmap.png)
288
+
289
+ #### Extent and Detail Indicators
290
+
291
+ Inset maps can be paired with either an extent or detail indicator, to provide additional geographic context to the inset map
292
+
293
+ ```python
294
+ indicate_extent(inset_axis, parent_axis, inset_crs, parent_crs, ...)
295
+ indicate_detail(parent_axis, inset_axis, parent_crs, inset_crs, ...)
296
+ ```
297
+
298
+ This will create an output like the following (extent indicator on the left, detail indicator on the right):
299
+
300
+ ![Customized scale bar](matplotlib_map_utils/docs/assets/readme_indicators.png)
301
+
302
+ Refer to `docs\howto_inset_map` for details on how to customize the inset map and indicators to your liking.
303
+
304
+ </details>
305
+
306
+ ---
307
+
308
+ ### 🛠️ Utilities
223
309
 
224
310
  <details>
225
311
  <summary><i>Expand instructions</i></summary>
@@ -265,23 +351,33 @@ Two more projects assisted with the creation of this script:
265
351
 
266
352
  #### Releases
267
353
 
268
- - `v2.0.1`: Fixed a bug in the `dual_bars()` function that prevented empty dictionaries to be passed. Also added a warning when auto-calculated bar widths appear to be exceeding the dimension of the axis (usually occurs when the axis is <2 kilometeres or miles long, depending on the units selected).
354
+ - `v1.0.x`: Initial releases featuring the North Arrow element, along with some minor bug fixes.
355
+
356
+ - `v2.0.0`: Initial release of the Scale Bar element.
357
+
358
+ - `v2.0.1`: Fixed a bug in the `dual_bars()` function that prevented empty dictionaries to be passed. Also added a warning when auto-calculated bar widths appear to be exceeding the dimension of the axis (usually occurs when the axis is <2 kilometers or miles long, depending on the units selected).
269
359
 
270
360
  - `v2.0.2`: Changed f-string formatting to alternate double and single quotes, so as to maintain compatibility with versions of Python before 3.12 (see [here](https://github.com/moss-xyz/matplotlib-map-utils/issues/3)). However, this did reveal that another aspect of the code, namely concatenating `type` in function arguments, requires 3.10, and so the minimum python version was incremented.
271
361
 
272
362
  - `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.
273
363
 
364
+ - `v3.0.0`: Release of inset map and extent and detail indicator classes and functions.
365
+
366
+ - `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).
367
+
274
368
  #### Future Roadmap
275
369
 
276
- With the release of `v2.x`, and the addition of **Scale Bar** tools, this project has achieved the two main objectives that I set out to.
370
+ With the release of `v3.x`, this project has achieved full coverage of the "main" map elements I think are necessary.
277
371
 
278
372
  If I continue development of this project, I will be looking to add or fix the following features:
279
373
 
374
+ * For all: switch to a system based on Pydantic for easier type validation
375
+
280
376
  * **North Arrow:**
281
377
 
282
378
  * Copy the image-rendering functionality of the Scale Bar to allow for rotation of the entire object, label and arrow together
283
379
 
284
- * Create more styles for the arrow, potentiallly including a compass rose and a line-only arrow
380
+ * Create more styles for the arrow, potentially including a compass rose and a line-only arrow
285
381
 
286
382
  * **Scale Bar:**
287
383
 
@@ -291,7 +387,13 @@ If I continue development of this project, I will be looking to add or fix the f
291
387
 
292
388
  * Clean up the variable naming scheme (consistency on `loc` vs `position`, `style` vs `type`, etc.)
293
389
 
294
- * Create more styles for the bar, potentiallly including dual boxes and a sawtooth bar
390
+ * Create more styles for the bar, potentially including dual boxes and a sawtooth bar
391
+
392
+ * **Inset Map:**
393
+
394
+ * Clean up the way that connectors are drawn for detail indicators
395
+
396
+ * New functionality for placing multiple inset maps at once (with context-aware positioning to prevent overlap with each other)
295
397
 
296
398
  * **Utils:**
297
399
 
@@ -301,9 +403,7 @@ If I continue development of this project, I will be looking to add or fix the f
301
403
 
302
404
  * (USA): Stronger typing options, so you don't have to recall which `region` or `division` types are available, etc.
303
405
 
304
- If that goes well, `v3` can then either create a tool for generating inset maps (which `matplotlib` has *some* support for), or the various functions that I have created in the past that assist with formatting a map "properly", such as centering on a given object.
305
-
306
- I am also open to ideas for other extensions to create!
406
+ 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!
307
407
 
308
408
  #### Support and Contributions
309
409
 
@@ -0,0 +1,21 @@
1
+ # This handles importing of all the functions and classes
2
+ from .core.north_arrow import NorthArrow, north_arrow
3
+ from .core.scale_bar import ScaleBar, scale_bar, dual_bars
4
+ from .core.inset_map import InsetMap, inset_map, ExtentIndicator, indicate_extent, DetailIndicator, indicate_detail, inset_usa
5
+ from typing import Literal
6
+
7
+ # This defines what wildcard imports should import
8
+ __all__ = ["NorthArrow", "north_arrow",
9
+ "ScaleBar", "scale_bar", "dual_bars",
10
+ "InsetMap","inset_map", "ExtentIndicator","indicate_extent", "DetailIndicator","indicate_detail", "inset_usa",
11
+ "set_size"]
12
+
13
+ def set_size(size: Literal["xs","xsmall","x-small",
14
+ "sm","small",
15
+ "md","medium",
16
+ "lg","large",
17
+ "xl","xlarge","x-large"]):
18
+
19
+ NorthArrow.set_size(size)
20
+ ScaleBar.set_size(size)
21
+ InsetMap.set_size(size)
@@ -0,0 +1,8 @@
1
+ from typing import Literal
2
+ from .north_arrow import NorthArrow, north_arrow
3
+ from .scale_bar import ScaleBar, scale_bar, dual_bars
4
+ from .inset_map import InsetMap, inset_map, ExtentIndicator, indicate_extent, DetailIndicator, indicate_detail, inset_usa
5
+
6
+ __all__ = ["NorthArrow", "north_arrow",
7
+ "ScaleBar", "scale_bar", "dual_bars",
8
+ "InsetMap","inset_map", "ExtentIndicator","indicate_extent", "DetailIndicator","indicate_detail", "inset_usa"]