matplotlib-map-utils 2.0.2__tar.gz → 3.0.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 (31) hide show
  1. {matplotlib_map_utils-2.0.2 → matplotlib_map_utils-3.0.0}/PKG-INFO +163 -19
  2. {matplotlib_map_utils-2.0.2 → matplotlib_map_utils-3.0.0}/README.md +159 -17
  3. matplotlib_map_utils-3.0.0/matplotlib_map_utils/__init__.py +21 -0
  4. matplotlib_map_utils-3.0.0/matplotlib_map_utils/core/__init__.py +8 -0
  5. matplotlib_map_utils-3.0.0/matplotlib_map_utils/core/inset_map.py +952 -0
  6. {matplotlib_map_utils-2.0.2 → matplotlib_map_utils-3.0.0}/matplotlib_map_utils/core/north_arrow.py +0 -4
  7. {matplotlib_map_utils-2.0.2 → matplotlib_map_utils-3.0.0}/matplotlib_map_utils/core/scale_bar.py +0 -6
  8. matplotlib_map_utils-3.0.0/matplotlib_map_utils/defaults/inset_map.py +67 -0
  9. matplotlib_map_utils-3.0.0/matplotlib_map_utils/utils/__init__.py +3 -0
  10. matplotlib_map_utils-3.0.0/matplotlib_map_utils/utils/usa.json +1038 -0
  11. matplotlib_map_utils-3.0.0/matplotlib_map_utils/utils/usa.py +336 -0
  12. {matplotlib_map_utils-2.0.2 → matplotlib_map_utils-3.0.0}/matplotlib_map_utils/validation/functions.py +51 -15
  13. matplotlib_map_utils-3.0.0/matplotlib_map_utils/validation/inset_map.py +88 -0
  14. {matplotlib_map_utils-2.0.2 → matplotlib_map_utils-3.0.0}/matplotlib_map_utils/validation/north_arrow.py +1 -1
  15. {matplotlib_map_utils-2.0.2 → matplotlib_map_utils-3.0.0}/matplotlib_map_utils/validation/scale_bar.py +3 -5
  16. {matplotlib_map_utils-2.0.2 → matplotlib_map_utils-3.0.0}/matplotlib_map_utils.egg-info/PKG-INFO +163 -19
  17. {matplotlib_map_utils-2.0.2 → matplotlib_map_utils-3.0.0}/matplotlib_map_utils.egg-info/SOURCES.txt +6 -0
  18. {matplotlib_map_utils-2.0.2 → matplotlib_map_utils-3.0.0}/pyproject.toml +5 -1
  19. matplotlib_map_utils-2.0.2/matplotlib_map_utils/__init__.py +0 -6
  20. matplotlib_map_utils-2.0.2/matplotlib_map_utils/core/__init__.py +0 -4
  21. {matplotlib_map_utils-2.0.2 → matplotlib_map_utils-3.0.0}/LICENSE +0 -0
  22. {matplotlib_map_utils-2.0.2 → matplotlib_map_utils-3.0.0}/matplotlib_map_utils/defaults/__init__.py +0 -0
  23. {matplotlib_map_utils-2.0.2 → matplotlib_map_utils-3.0.0}/matplotlib_map_utils/defaults/north_arrow.py +0 -0
  24. {matplotlib_map_utils-2.0.2 → matplotlib_map_utils-3.0.0}/matplotlib_map_utils/defaults/scale_bar.py +0 -0
  25. {matplotlib_map_utils-2.0.2 → matplotlib_map_utils-3.0.0}/matplotlib_map_utils/scratch/map_utils.py +0 -0
  26. {matplotlib_map_utils-2.0.2 → matplotlib_map_utils-3.0.0}/matplotlib_map_utils/scratch/north_arrow_old_classes.py +0 -0
  27. {matplotlib_map_utils-2.0.2 → matplotlib_map_utils-3.0.0}/matplotlib_map_utils/validation/__init__.py +0 -0
  28. {matplotlib_map_utils-2.0.2 → matplotlib_map_utils-3.0.0}/matplotlib_map_utils.egg-info/dependency_links.txt +0 -0
  29. {matplotlib_map_utils-2.0.2 → matplotlib_map_utils-3.0.0}/matplotlib_map_utils.egg-info/requires.txt +0 -0
  30. {matplotlib_map_utils-2.0.2 → matplotlib_map_utils-3.0.0}/matplotlib_map_utils.egg-info/top_level.txt +0 -0
  31. {matplotlib_map_utils-2.0.2 → matplotlib_map_utils-3.0.0}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
- Metadata-Version: 2.2
1
+ Metadata-Version: 2.4
2
2
  Name: matplotlib-map-utils
3
- Version: 2.0.2
3
+ Version: 3.0.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/
@@ -8,20 +8,24 @@ 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
14
15
  Requires-Dist: matplotlib>=3.9.0
15
16
  Requires-Dist: cartopy>=0.23.0
16
17
  Requires-Dist: great-circle-calculator>=1.3.1
18
+ Dynamic: license-file
17
19
 
18
- # matplotlib-map-utils
20
+ ![matplotlib_map_utils logo](matplotlib_map_utils/docs/assets/mmu_logo_w_elements.png)
19
21
 
20
22
  ---
21
23
 
22
- **Documentation**: See `docs` folder
24
+ **Documentation:** See `docs` folder
23
25
 
24
- **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.
25
29
 
26
30
  ---
27
31
 
@@ -29,13 +33,23 @@ Requires-Dist: great-circle-calculator>=1.3.1
29
33
 
30
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/).
31
35
 
32
- As of `v2.x` (the current version), this includes two tools:
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.
43
+
44
+ The three elements listed above are all intended to be high-resolution, easily modifiable, and context-aware, relative to your specific plot.
33
45
 
34
- * `north_arrow.py`, which generates a high quality, context-aware north arrow for a given plot.
46
+ This package also contains a single utility object:
35
47
 
36
- * `scale_bar.py`, which generates a high quality, context-aware scale bar to a given plot.
48
+ * `usa.py`, which contains a class that helps filter for states and territories within the USA based on given characteristics.
37
49
 
38
- 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)
39
53
 
40
54
  ---
41
55
 
@@ -59,7 +73,8 @@ The requirements for this package are:
59
73
 
60
74
  ### Package Structure
61
75
 
62
- The package is arrayed in the following way:
76
+ <details>
77
+ <summary><i>The package is arrayed in the following way:</i></summary>
63
78
 
64
79
  ```bash
65
80
  package_name/
@@ -67,17 +82,24 @@ package_name/
67
82
 
68
83
  ├── core/
69
84
  │ ├── __init__.py
85
+ │ ├── inset_map.py
70
86
  │ ├── north_arrow.py
71
87
  │ ├── scale_bar.py
72
88
  ├── validation/
73
89
  │ ├── __init__.py
74
90
  │ ├── functions.py
91
+ │ └── inset_map.py
75
92
  │ ├── north_arrow.py
76
93
  │ └── scale_bar.py
77
94
  ├── defaults/
78
95
  │ ├── __init__.py
79
96
  │ ├── north_arrow.py
80
97
  │ └── scale_bar.py
98
+ │ └── inset_map.py
99
+ ├── utils/
100
+ │ ├── __init__.py
101
+ │ ├── usa.py
102
+ │ └── usa.json
81
103
  ```
82
104
 
83
105
  Where:
@@ -88,9 +110,13 @@ Where:
88
110
 
89
111
  * `defaults` contains default settings for each object at different paper sizes
90
112
 
113
+ * `utils` contains utility functions and objects
114
+
115
+ </details>
116
+
91
117
  ---
92
118
 
93
- ### North Arrow
119
+ ### 🧭 North Arrow
94
120
 
95
121
  <details>
96
122
  <summary><i>Expand instructions</i></summary>
@@ -101,6 +127,8 @@ Importing the North Arrow functions and classes can be done like so:
101
127
 
102
128
  ```py
103
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
104
132
  ```
105
133
 
106
134
  The quickest way to add a single north arrow to a single plot is to use the `north_arrow` function:
@@ -164,7 +192,7 @@ Instructions for how to do so can be found in `docs\howto_north_arrow`.
164
192
 
165
193
  ---
166
194
 
167
- ### Scale Bar
195
+ ### 📏 Scale Bar
168
196
 
169
197
  <details>
170
198
  <summary><i>Expand instructions</i></summary>
@@ -175,6 +203,8 @@ Importing the Scale Bar functions and classes can be done like so:
175
203
 
176
204
  ```py
177
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
178
208
  ```
179
209
 
180
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:
@@ -194,7 +224,7 @@ An object-oriented approach is also supported:
194
224
  fig, ax = matplotlib.pyplot.subplots(1,1, figsize=(5,5), dpi=150)
195
225
  # Adding a scale bar to the upper-right corner of the axis, in the same projection as whatever geodata you plotted
196
226
  # Here, we change the boxes to "ticks"
197
- sb = ScaleBar(location="upper right", style="boxes", bar={"projection":3857})
227
+ sb = ScaleBar(location="upper right", style="ticks", bar={"projection":3857})
198
228
  # Adding the artist to the plot
199
229
  ax.add_artist(sb)
200
230
  ```
@@ -230,6 +260,98 @@ Refer to `docs\howto_scale_bar` for details on how to customize each facet of th
230
260
 
231
261
  ---
232
262
 
263
+ ### 🗺️ Inset Map
264
+
265
+ <details>
266
+ <summary><i>Expand instructions</i></summary>
267
+
268
+ #### Quick Start
269
+
270
+ Importing the Inset Map functions and classes can be done like so:
271
+
272
+ ```py
273
+ from matplotlib_map_utils.core.inset_map import InsetMap, inset_map, ExtentIndicator, indicate_extent, DetailIndicator, indicate_detail
274
+ from matplotlib_map_utils.core import InsetMap, inset_map, ExtentIndicator, indicate_extent, DetailIndicator, indicate_detail # also valid
275
+ from matplotlib_map_utils import InsetMap, inset_map, ExtentIndicator, indicate_extent, DetailIndicator, indicate_detail # also valid
276
+ ```
277
+
278
+ The quickest way to add a single inset map to an existing plot is the `inset_map` function:
279
+
280
+ ```python
281
+ # Setting up a plot
282
+ fig, ax = matplotlib.pyplot.subplots(1,1, figsize=(5,5), dpi=150)
283
+ # Adding an inset map to the upper-right corner of the axis
284
+ iax = inset_map(ax=ax, location="upper right", size=0.75, pad=0, xticks=[], yticks=[])
285
+ # You can now plot additional data to iax as desired
286
+ ```
287
+
288
+ An object-oriented approach is also supported:
289
+
290
+ ```python
291
+ # Setting up a plot
292
+ fig, ax = matplotlib.pyplot.subplots(1,1, figsize=(5,5), dpi=150)
293
+ # Creating an object for the inset map
294
+ im = InsetMap(location="upper right", size=0.75, pad=0, xticks=[], yticks=[])
295
+ # Adding the inset map template to the plot
296
+ iax = im.create(ax=ax)
297
+ # You can now plot additional data to iax as desired
298
+ ```
299
+
300
+ Both of these will create an output like the following:
301
+
302
+ ![Example inset map](matplotlib_map_utils/docs/assets/readme_insetmap.png)
303
+
304
+ #### Extent and Detail Indicators
305
+
306
+ Inset maps can be paired with either an extent or detail indicator, to provide additional geographic context to the inset map
307
+
308
+ ```python
309
+ indicate_extent(inset_axis, parent_axis, inset_crs, parent_crs, ...)
310
+ indicate_detail(parent_axis, inset_axis, parent_crs, inset_crs, ...)
311
+ ```
312
+
313
+ This will create an output like the following (extent indicator on the left, detail indicator on the right):
314
+
315
+ ![Customized scale bar](matplotlib_map_utils/docs/assets/readme_indicators.png)
316
+
317
+ Refer to `docs\howto_inset_map` for details on how to customize the inset map and indicators to your liking.
318
+
319
+ </details>
320
+
321
+ ---
322
+
323
+ ### 🛠️ Utilities
324
+
325
+ <details>
326
+ <summary><i>Expand instructions</i></summary>
327
+
328
+ #### Quick Start
329
+
330
+ Importing the bundled utility functions and classes can be done like so:
331
+
332
+ ```py
333
+ from matplotlib_map_utils.utils import USA
334
+ ```
335
+
336
+ As of `v2.1.0`, there is only one utility class available: `USA`, an object to help quickly filter for subsets of US states and territories. This utility class is still in beta, and might change.
337
+
338
+ An example:
339
+
340
+ ```python
341
+ # Loading the object
342
+ usa = USA()
343
+ # Getting a list FIPS codes for US States
344
+ usa.filter(states=True, to_return="fips")
345
+ # Getting a list of State Names for states in the South and Midwest regions
346
+ usa.filter(region=["South","Midtwest"], to_return="name")
347
+ ```
348
+
349
+ Refer to `docs\howto_utils` for details on how to use this class, including with `pandas.apply()`.
350
+
351
+ </details>
352
+
353
+ ---
354
+
233
355
  ### Development Notes
234
356
 
235
357
  #### Inspiration and Thanks
@@ -244,21 +366,31 @@ Two more projects assisted with the creation of this script:
244
366
 
245
367
  #### Releases
246
368
 
247
- - `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).
369
+ - `v1.0.x`: Initial releases featuring the North Arrow element, along with some minor bug fixes.
370
+
371
+ - `v2.0.0`: Initial release of the Scale Bar element.
372
+
373
+ - `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).
248
374
 
249
375
  - `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.
250
376
 
377
+ - `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
+
379
+ - `v3.0.0`: Release of inset map and extent and detail indicator classes and functions.
380
+
251
381
  #### Future Roadmap
252
382
 
253
- 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.
383
+ With the release of `v3.x`, this project has achieved full coverage of the "main" map elements I think are necessary.
254
384
 
255
385
  If I continue development of this project, I will be looking to add or fix the following features:
256
386
 
387
+ * For all: switch to a system based on Pydantic for easier type validation
388
+
257
389
  * **North Arrow:**
258
390
 
259
391
  * Copy the image-rendering functionality of the Scale Bar to allow for rotation of the entire object, label and arrow together
260
392
 
261
- * Create more styles for the arrow, potentiallly including a compass rose and a line-only arrow
393
+ * Create more styles for the arrow, potentially including a compass rose and a line-only arrow
262
394
 
263
395
  * **Scale Bar:**
264
396
 
@@ -268,11 +400,23 @@ If I continue development of this project, I will be looking to add or fix the f
268
400
 
269
401
  * Clean up the variable naming scheme (consistency on `loc` vs `position`, `style` vs `type`, etc.)
270
402
 
271
- * Create more styles for the bar, potentiallly including dual boxes and a sawtooth bar
403
+ * Create more styles for the bar, potentially including dual boxes and a sawtooth bar
404
+
405
+ * **Inset Map:**
406
+
407
+ * Clean up the way that connectors are drawn for detail indicators
408
+
409
+ * New functionality for placing multiple inset maps at once (with context-aware positioning to prevent overlap with each other)
410
+
411
+ * **Utils:**
412
+
413
+ * (USA): Stronger fuzzy search mechanics, so that it will accept flexible inputs for FIPS/abbr/name
414
+
415
+ * (USA): More integrated class types to allow for a more fully-formed object model (USA being a `Country`, with subclasses related to `State` and `Territory` that have their own classes of attributes, etc.)
272
416
 
273
- 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 and coverting FIPS codes.
417
+ * (USA): Stronger typing options, so you don't have to recall which `region` or `division` types are available, etc.
274
418
 
275
- I am also open to ideas for other extensions to create!
419
+ 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!
276
420
 
277
421
  #### Support and Contributions
278
422
 
@@ -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,13 +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:
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.
24
+
25
+ The three elements listed above are all intended to be high-resolution, easily modifiable, and context-aware, relative to your specific plot.
16
26
 
17
- * `north_arrow.py`, which generates a high quality, context-aware north arrow for a given plot.
27
+ This package also contains a single utility object:
18
28
 
19
- * `scale_bar.py`, which generates a high quality, context-aware scale bar to a given plot.
29
+ * `usa.py`, which contains a class that helps filter for states and territories within the USA based on given characteristics.
20
30
 
21
- 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)
22
34
 
23
35
  ---
24
36
 
@@ -42,7 +54,8 @@ The requirements for this package are:
42
54
 
43
55
  ### Package Structure
44
56
 
45
- The package is arrayed in the following way:
57
+ <details>
58
+ <summary><i>The package is arrayed in the following way:</i></summary>
46
59
 
47
60
  ```bash
48
61
  package_name/
@@ -50,17 +63,24 @@ package_name/
50
63
 
51
64
  ├── core/
52
65
  │ ├── __init__.py
66
+ │ ├── inset_map.py
53
67
  │ ├── north_arrow.py
54
68
  │ ├── scale_bar.py
55
69
  ├── validation/
56
70
  │ ├── __init__.py
57
71
  │ ├── functions.py
72
+ │ └── inset_map.py
58
73
  │ ├── north_arrow.py
59
74
  │ └── scale_bar.py
60
75
  ├── defaults/
61
76
  │ ├── __init__.py
62
77
  │ ├── north_arrow.py
63
78
  │ └── scale_bar.py
79
+ │ └── inset_map.py
80
+ ├── utils/
81
+ │ ├── __init__.py
82
+ │ ├── usa.py
83
+ │ └── usa.json
64
84
  ```
65
85
 
66
86
  Where:
@@ -71,9 +91,13 @@ Where:
71
91
 
72
92
  * `defaults` contains default settings for each object at different paper sizes
73
93
 
94
+ * `utils` contains utility functions and objects
95
+
96
+ </details>
97
+
74
98
  ---
75
99
 
76
- ### North Arrow
100
+ ### 🧭 North Arrow
77
101
 
78
102
  <details>
79
103
  <summary><i>Expand instructions</i></summary>
@@ -84,6 +108,8 @@ Importing the North Arrow functions and classes can be done like so:
84
108
 
85
109
  ```py
86
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
87
113
  ```
88
114
 
89
115
  The quickest way to add a single north arrow to a single plot is to use the `north_arrow` function:
@@ -147,7 +173,7 @@ Instructions for how to do so can be found in `docs\howto_north_arrow`.
147
173
 
148
174
  ---
149
175
 
150
- ### Scale Bar
176
+ ### 📏 Scale Bar
151
177
 
152
178
  <details>
153
179
  <summary><i>Expand instructions</i></summary>
@@ -158,6 +184,8 @@ Importing the Scale Bar functions and classes can be done like so:
158
184
 
159
185
  ```py
160
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
161
189
  ```
162
190
 
163
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:
@@ -177,7 +205,7 @@ An object-oriented approach is also supported:
177
205
  fig, ax = matplotlib.pyplot.subplots(1,1, figsize=(5,5), dpi=150)
178
206
  # Adding a scale bar to the upper-right corner of the axis, in the same projection as whatever geodata you plotted
179
207
  # Here, we change the boxes to "ticks"
180
- sb = ScaleBar(location="upper right", style="boxes", bar={"projection":3857})
208
+ sb = ScaleBar(location="upper right", style="ticks", bar={"projection":3857})
181
209
  # Adding the artist to the plot
182
210
  ax.add_artist(sb)
183
211
  ```
@@ -213,6 +241,98 @@ Refer to `docs\howto_scale_bar` for details on how to customize each facet of th
213
241
 
214
242
  ---
215
243
 
244
+ ### 🗺️ Inset Map
245
+
246
+ <details>
247
+ <summary><i>Expand instructions</i></summary>
248
+
249
+ #### Quick Start
250
+
251
+ Importing the Inset Map functions and classes can be done like so:
252
+
253
+ ```py
254
+ from matplotlib_map_utils.core.inset_map import InsetMap, inset_map, ExtentIndicator, indicate_extent, DetailIndicator, indicate_detail
255
+ from matplotlib_map_utils.core import InsetMap, inset_map, ExtentIndicator, indicate_extent, DetailIndicator, indicate_detail # also valid
256
+ from matplotlib_map_utils import InsetMap, inset_map, ExtentIndicator, indicate_extent, DetailIndicator, indicate_detail # also valid
257
+ ```
258
+
259
+ The quickest way to add a single inset map to an existing plot is the `inset_map` function:
260
+
261
+ ```python
262
+ # Setting up a plot
263
+ fig, ax = matplotlib.pyplot.subplots(1,1, figsize=(5,5), dpi=150)
264
+ # Adding an inset map to the upper-right corner of the axis
265
+ iax = inset_map(ax=ax, location="upper right", size=0.75, pad=0, xticks=[], yticks=[])
266
+ # You can now plot additional data to iax as desired
267
+ ```
268
+
269
+ An object-oriented approach is also supported:
270
+
271
+ ```python
272
+ # Setting up a plot
273
+ fig, ax = matplotlib.pyplot.subplots(1,1, figsize=(5,5), dpi=150)
274
+ # Creating an object for the inset map
275
+ im = InsetMap(location="upper right", size=0.75, pad=0, xticks=[], yticks=[])
276
+ # Adding the inset map template to the plot
277
+ iax = im.create(ax=ax)
278
+ # You can now plot additional data to iax as desired
279
+ ```
280
+
281
+ Both of these will create an output like the following:
282
+
283
+ ![Example inset map](matplotlib_map_utils/docs/assets/readme_insetmap.png)
284
+
285
+ #### Extent and Detail Indicators
286
+
287
+ Inset maps can be paired with either an extent or detail indicator, to provide additional geographic context to the inset map
288
+
289
+ ```python
290
+ indicate_extent(inset_axis, parent_axis, inset_crs, parent_crs, ...)
291
+ indicate_detail(parent_axis, inset_axis, parent_crs, inset_crs, ...)
292
+ ```
293
+
294
+ This will create an output like the following (extent indicator on the left, detail indicator on the right):
295
+
296
+ ![Customized scale bar](matplotlib_map_utils/docs/assets/readme_indicators.png)
297
+
298
+ Refer to `docs\howto_inset_map` for details on how to customize the inset map and indicators to your liking.
299
+
300
+ </details>
301
+
302
+ ---
303
+
304
+ ### 🛠️ Utilities
305
+
306
+ <details>
307
+ <summary><i>Expand instructions</i></summary>
308
+
309
+ #### Quick Start
310
+
311
+ Importing the bundled utility functions and classes can be done like so:
312
+
313
+ ```py
314
+ from matplotlib_map_utils.utils import USA
315
+ ```
316
+
317
+ As of `v2.1.0`, there is only one utility class available: `USA`, an object to help quickly filter for subsets of US states and territories. This utility class is still in beta, and might change.
318
+
319
+ An example:
320
+
321
+ ```python
322
+ # Loading the object
323
+ usa = USA()
324
+ # Getting a list FIPS codes for US States
325
+ usa.filter(states=True, to_return="fips")
326
+ # Getting a list of State Names for states in the South and Midwest regions
327
+ usa.filter(region=["South","Midtwest"], to_return="name")
328
+ ```
329
+
330
+ Refer to `docs\howto_utils` for details on how to use this class, including with `pandas.apply()`.
331
+
332
+ </details>
333
+
334
+ ---
335
+
216
336
  ### Development Notes
217
337
 
218
338
  #### Inspiration and Thanks
@@ -227,21 +347,31 @@ Two more projects assisted with the creation of this script:
227
347
 
228
348
  #### Releases
229
349
 
230
- - `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).
350
+ - `v1.0.x`: Initial releases featuring the North Arrow element, along with some minor bug fixes.
351
+
352
+ - `v2.0.0`: Initial release of the Scale Bar element.
353
+
354
+ - `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).
231
355
 
232
356
  - `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.
233
357
 
358
+ - `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
+
360
+ - `v3.0.0`: Release of inset map and extent and detail indicator classes and functions.
361
+
234
362
  #### Future Roadmap
235
363
 
236
- 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.
364
+ With the release of `v3.x`, this project has achieved full coverage of the "main" map elements I think are necessary.
237
365
 
238
366
  If I continue development of this project, I will be looking to add or fix the following features:
239
367
 
368
+ * For all: switch to a system based on Pydantic for easier type validation
369
+
240
370
  * **North Arrow:**
241
371
 
242
372
  * Copy the image-rendering functionality of the Scale Bar to allow for rotation of the entire object, label and arrow together
243
373
 
244
- * Create more styles for the arrow, potentiallly including a compass rose and a line-only arrow
374
+ * Create more styles for the arrow, potentially including a compass rose and a line-only arrow
245
375
 
246
376
  * **Scale Bar:**
247
377
 
@@ -251,11 +381,23 @@ If I continue development of this project, I will be looking to add or fix the f
251
381
 
252
382
  * Clean up the variable naming scheme (consistency on `loc` vs `position`, `style` vs `type`, etc.)
253
383
 
254
- * Create more styles for the bar, potentiallly including dual boxes and a sawtooth bar
384
+ * Create more styles for the bar, potentially including dual boxes and a sawtooth bar
385
+
386
+ * **Inset Map:**
387
+
388
+ * Clean up the way that connectors are drawn for detail indicators
389
+
390
+ * New functionality for placing multiple inset maps at once (with context-aware positioning to prevent overlap with each other)
391
+
392
+ * **Utils:**
393
+
394
+ * (USA): Stronger fuzzy search mechanics, so that it will accept flexible inputs for FIPS/abbr/name
395
+
396
+ * (USA): More integrated class types to allow for a more fully-formed object model (USA being a `Country`, with subclasses related to `State` and `Territory` that have their own classes of attributes, etc.)
255
397
 
256
- 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 and coverting FIPS codes.
398
+ * (USA): Stronger typing options, so you don't have to recall which `region` or `division` types are available, etc.
257
399
 
258
- I am also open to ideas for other extensions to create!
400
+ 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!
259
401
 
260
402
  #### Support and Contributions
261
403
 
@@ -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"]