matplotlib-map-utils 3.1.0__tar.gz → 3.1.2__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {matplotlib_map_utils-3.1.0 → matplotlib_map_utils-3.1.2}/PKG-INFO +10 -7
- {matplotlib_map_utils-3.1.0 → matplotlib_map_utils-3.1.2}/README.md +9 -6
- {matplotlib_map_utils-3.1.0 → matplotlib_map_utils-3.1.2}/matplotlib_map_utils/core/scale_bar.py +68 -11
- {matplotlib_map_utils-3.1.0 → matplotlib_map_utils-3.1.2}/matplotlib_map_utils/defaults/scale_bar.py +31 -6
- {matplotlib_map_utils-3.1.0 → matplotlib_map_utils-3.1.2}/matplotlib_map_utils/validation/scale_bar.py +11 -1
- {matplotlib_map_utils-3.1.0 → matplotlib_map_utils-3.1.2}/matplotlib_map_utils.egg-info/PKG-INFO +10 -7
- {matplotlib_map_utils-3.1.0 → matplotlib_map_utils-3.1.2}/pyproject.toml +12 -1
- {matplotlib_map_utils-3.1.0 → matplotlib_map_utils-3.1.2}/LICENSE +0 -0
- {matplotlib_map_utils-3.1.0 → matplotlib_map_utils-3.1.2}/matplotlib_map_utils/__init__.py +0 -0
- {matplotlib_map_utils-3.1.0 → matplotlib_map_utils-3.1.2}/matplotlib_map_utils/core/__init__.py +0 -0
- {matplotlib_map_utils-3.1.0 → matplotlib_map_utils-3.1.2}/matplotlib_map_utils/core/inset_map.py +0 -0
- {matplotlib_map_utils-3.1.0 → matplotlib_map_utils-3.1.2}/matplotlib_map_utils/core/north_arrow.py +0 -0
- {matplotlib_map_utils-3.1.0 → matplotlib_map_utils-3.1.2}/matplotlib_map_utils/defaults/__init__.py +0 -0
- {matplotlib_map_utils-3.1.0 → matplotlib_map_utils-3.1.2}/matplotlib_map_utils/defaults/inset_map.py +0 -0
- {matplotlib_map_utils-3.1.0 → matplotlib_map_utils-3.1.2}/matplotlib_map_utils/defaults/north_arrow.py +0 -0
- {matplotlib_map_utils-3.1.0 → matplotlib_map_utils-3.1.2}/matplotlib_map_utils/scratch/map_utils.py +0 -0
- {matplotlib_map_utils-3.1.0 → matplotlib_map_utils-3.1.2}/matplotlib_map_utils/scratch/north_arrow_old_classes.py +0 -0
- {matplotlib_map_utils-3.1.0 → matplotlib_map_utils-3.1.2}/matplotlib_map_utils/utils/__init__.py +0 -0
- {matplotlib_map_utils-3.1.0 → matplotlib_map_utils-3.1.2}/matplotlib_map_utils/utils/usa.json +0 -0
- {matplotlib_map_utils-3.1.0 → matplotlib_map_utils-3.1.2}/matplotlib_map_utils/utils/usa.py +0 -0
- {matplotlib_map_utils-3.1.0 → matplotlib_map_utils-3.1.2}/matplotlib_map_utils/validation/__init__.py +0 -0
- {matplotlib_map_utils-3.1.0 → matplotlib_map_utils-3.1.2}/matplotlib_map_utils/validation/functions.py +0 -0
- {matplotlib_map_utils-3.1.0 → matplotlib_map_utils-3.1.2}/matplotlib_map_utils/validation/inset_map.py +0 -0
- {matplotlib_map_utils-3.1.0 → matplotlib_map_utils-3.1.2}/matplotlib_map_utils/validation/north_arrow.py +0 -0
- {matplotlib_map_utils-3.1.0 → matplotlib_map_utils-3.1.2}/matplotlib_map_utils.egg-info/SOURCES.txt +0 -0
- {matplotlib_map_utils-3.1.0 → matplotlib_map_utils-3.1.2}/matplotlib_map_utils.egg-info/dependency_links.txt +0 -0
- {matplotlib_map_utils-3.1.0 → matplotlib_map_utils-3.1.2}/matplotlib_map_utils.egg-info/requires.txt +0 -0
- {matplotlib_map_utils-3.1.0 → matplotlib_map_utils-3.1.2}/matplotlib_map_utils.egg-info/top_level.txt +0 -0
- {matplotlib_map_utils-3.1.0 → matplotlib_map_utils-3.1.2}/setup.cfg +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: matplotlib-map-utils
|
|
3
|
-
Version: 3.1.
|
|
3
|
+
Version: 3.1.2
|
|
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/
|
|
@@ -179,7 +179,9 @@ This will create an output like the following:
|
|
|
179
179
|
|
|
180
180
|

|
|
181
181
|
|
|
182
|
-
Refer to `docs\howto_north_arrow` for details on how to customize each facet of the north arrow.
|
|
182
|
+
Refer to `docs\howto_north_arrow` for details on how to customize each facet of the north arrow.
|
|
183
|
+
|
|
184
|
+
_Note: only add a north arrow **after** adding all of your geodata and changing your axis limits!_
|
|
183
185
|
|
|
184
186
|
#### Rotation
|
|
185
187
|
|
|
@@ -260,6 +262,8 @@ This will create an output like the following:
|
|
|
260
262
|
|
|
261
263
|
Refer to `docs\howto_scale_bar` for details on how to customize each facet of the scale bar.
|
|
262
264
|
|
|
265
|
+
_Note: only add a scale bar **after** adding all of your geodata and changing your axis limits!_
|
|
266
|
+
|
|
263
267
|
#### Specifying Length
|
|
264
268
|
|
|
265
269
|
There are three main ways of specifying the length of a scale bar:
|
|
@@ -291,7 +295,6 @@ All of the above cases expect a valid CRS to be supplied to the `projection` par
|
|
|
291
295
|
- 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
296
|
|
|
293
297
|
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
|
-
|
|
295
298
|
</details>
|
|
296
299
|
|
|
297
300
|
---
|
|
@@ -351,7 +354,6 @@ This will create an output like the following (extent indicator on the left, det
|
|
|
351
354
|

|
|
352
355
|
|
|
353
356
|
Refer to `docs\howto_inset_map` for details on how to customize the inset map and indicators to your liking.
|
|
354
|
-
|
|
355
357
|
</details>
|
|
356
358
|
|
|
357
359
|
---
|
|
@@ -383,7 +385,6 @@ usa.filter(region=["South","Midwest"], to_return="name")
|
|
|
383
385
|
```
|
|
384
386
|
|
|
385
387
|
Refer to `docs\howto_utils` for details on how to use this class, including with `pandas.apply()`.
|
|
386
|
-
|
|
387
388
|
</details>
|
|
388
389
|
|
|
389
390
|
---
|
|
@@ -414,9 +415,7 @@ Two more projects assisted with the creation of this script:
|
|
|
414
415
|
- `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.
|
|
415
416
|
|
|
416
417
|
- `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.
|
|
417
|
-
|
|
418
418
|
</details>
|
|
419
|
-
<br>
|
|
420
419
|
|
|
421
420
|
- `v3.0.0`: Release of inset map and extent and detail indicator classes and functions.
|
|
422
421
|
|
|
@@ -424,6 +423,10 @@ Two more projects assisted with the creation of this script:
|
|
|
424
423
|
|
|
425
424
|
- `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
425
|
|
|
426
|
+
- `v3.1.1`: Fixed a bug that led to errors when creating a `scale_bar` at resolutions below 5km or 1 mile, due to a bug in the backend configuration functions (namely, `_config_bar_dim()`), which was fixed by correctly instantiating the necessary variable `ax_units` in other cases via an `else` statement (see [here](https://github.com/moss-xyz/matplotlib-map-utils/issues/14) for details).
|
|
427
|
+
|
|
428
|
+
- `v3.1.2`: Fixed a compatibility issue with [Ultraplot](https://github.com/Ultraplot/UltraPlot), primarily affecting the `ScaleBar` element, where text would rasterize at a low resolution (see [here](https://github.com/moss-xyz/matplotlib-map-utils/issues/16) and [here](https://github.com/moss-xyz/matplotlib-map-utils/pull/17) for details). A big thank you to cvanelteren on the Ultraplot team for identifying and implementing the necessary fixes, as well as making adjustments to the Ultraplot package to improve compatibility!
|
|
429
|
+
|
|
427
430
|
#### Future Roadmap
|
|
428
431
|
|
|
429
432
|
With the release of `v3.x`, this project has achieved full coverage of the "main" map elements I think are necessary.
|
|
@@ -160,7 +160,9 @@ This will create an output like the following:
|
|
|
160
160
|
|
|
161
161
|

|
|
162
162
|
|
|
163
|
-
Refer to `docs\howto_north_arrow` for details on how to customize each facet of the north arrow.
|
|
163
|
+
Refer to `docs\howto_north_arrow` for details on how to customize each facet of the north arrow.
|
|
164
|
+
|
|
165
|
+
_Note: only add a north arrow **after** adding all of your geodata and changing your axis limits!_
|
|
164
166
|
|
|
165
167
|
#### Rotation
|
|
166
168
|
|
|
@@ -241,6 +243,8 @@ This will create an output like the following:
|
|
|
241
243
|
|
|
242
244
|
Refer to `docs\howto_scale_bar` for details on how to customize each facet of the scale bar.
|
|
243
245
|
|
|
246
|
+
_Note: only add a scale bar **after** adding all of your geodata and changing your axis limits!_
|
|
247
|
+
|
|
244
248
|
#### Specifying Length
|
|
245
249
|
|
|
246
250
|
There are three main ways of specifying the length of a scale bar:
|
|
@@ -272,7 +276,6 @@ All of the above cases expect a valid CRS to be supplied to the `projection` par
|
|
|
272
276
|
- 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
277
|
|
|
274
278
|
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
|
-
|
|
276
279
|
</details>
|
|
277
280
|
|
|
278
281
|
---
|
|
@@ -332,7 +335,6 @@ This will create an output like the following (extent indicator on the left, det
|
|
|
332
335
|

|
|
333
336
|
|
|
334
337
|
Refer to `docs\howto_inset_map` for details on how to customize the inset map and indicators to your liking.
|
|
335
|
-
|
|
336
338
|
</details>
|
|
337
339
|
|
|
338
340
|
---
|
|
@@ -364,7 +366,6 @@ usa.filter(region=["South","Midwest"], to_return="name")
|
|
|
364
366
|
```
|
|
365
367
|
|
|
366
368
|
Refer to `docs\howto_utils` for details on how to use this class, including with `pandas.apply()`.
|
|
367
|
-
|
|
368
369
|
</details>
|
|
369
370
|
|
|
370
371
|
---
|
|
@@ -395,9 +396,7 @@ Two more projects assisted with the creation of this script:
|
|
|
395
396
|
- `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.
|
|
396
397
|
|
|
397
398
|
- `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.
|
|
398
|
-
|
|
399
399
|
</details>
|
|
400
|
-
<br>
|
|
401
400
|
|
|
402
401
|
- `v3.0.0`: Release of inset map and extent and detail indicator classes and functions.
|
|
403
402
|
|
|
@@ -405,6 +404,10 @@ Two more projects assisted with the creation of this script:
|
|
|
405
404
|
|
|
406
405
|
- `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
406
|
|
|
407
|
+
- `v3.1.1`: Fixed a bug that led to errors when creating a `scale_bar` at resolutions below 5km or 1 mile, due to a bug in the backend configuration functions (namely, `_config_bar_dim()`), which was fixed by correctly instantiating the necessary variable `ax_units` in other cases via an `else` statement (see [here](https://github.com/moss-xyz/matplotlib-map-utils/issues/14) for details).
|
|
408
|
+
|
|
409
|
+
- `v3.1.2`: Fixed a compatibility issue with [Ultraplot](https://github.com/Ultraplot/UltraPlot), primarily affecting the `ScaleBar` element, where text would rasterize at a low resolution (see [here](https://github.com/moss-xyz/matplotlib-map-utils/issues/16) and [here](https://github.com/moss-xyz/matplotlib-map-utils/pull/17) for details). A big thank you to cvanelteren on the Ultraplot team for identifying and implementing the necessary fixes, as well as making adjustments to the Ultraplot package to improve compatibility!
|
|
410
|
+
|
|
408
411
|
#### Future Roadmap
|
|
409
412
|
|
|
410
413
|
With the release of `v3.x`, this project has achieved full coverage of the "main" map elements I think are necessary.
|
{matplotlib_map_utils-3.1.0 → matplotlib_map_utils-3.1.2}/matplotlib_map_utils/core/scale_bar.py
RENAMED
|
@@ -35,6 +35,7 @@ from ..validation import functions as sbf
|
|
|
35
35
|
|
|
36
36
|
_DEFAULT_BAR, _DEFAULT_LABELS, _DEFAULT_UNITS, _DEFAULT_TEXT, _DEFAULT_AOB = sbd._DEFAULTS_SB["md"]
|
|
37
37
|
|
|
38
|
+
|
|
38
39
|
### CLASSES ###
|
|
39
40
|
|
|
40
41
|
class ScaleBar(matplotlib.artist.Artist):
|
|
@@ -205,9 +206,17 @@ class ScaleBar(matplotlib.artist.Artist):
|
|
|
205
206
|
# THANK YOU to matplotlib-scalebar for figuring this out
|
|
206
207
|
# Note that we never specify the renderer - the axis takes care of it!
|
|
207
208
|
def draw(self, renderer, *args, **kwargs):
|
|
209
|
+
# Prefer renderer dpi for class-based artists so exports stay sharp
|
|
210
|
+
# when savefig(dpi=...) differs from the figure construction dpi.
|
|
211
|
+
_bar = copy.deepcopy(self._bar)
|
|
212
|
+
if _bar.get("raster_dpi", None) is None:
|
|
213
|
+
_raster_dpi, _ = _resolve_raster_dpi(
|
|
214
|
+
_bar, self.axes.get_figure(), renderer=renderer
|
|
215
|
+
)
|
|
216
|
+
_bar["raster_dpi"] = _raster_dpi
|
|
208
217
|
# Can re-use the drawing function we already established, but return the object instead
|
|
209
218
|
sb_artist = scale_bar(ax=self.axes, style=self._style, location=self._location, draw=False,
|
|
210
|
-
bar=
|
|
219
|
+
bar=_bar, units=self._units,
|
|
211
220
|
labels=self._labels, text=self._text, aob=self._aob,
|
|
212
221
|
zorder=self._zorder)
|
|
213
222
|
# This handles the actual drawing
|
|
@@ -251,6 +260,22 @@ def scale_bar(ax, draw=True, style: Literal["ticks","boxes"]="boxes",
|
|
|
251
260
|
aob: None | bool | sbt._TYPE_AOB=None,
|
|
252
261
|
zorder: int=99,
|
|
253
262
|
return_aob: bool=True,):
|
|
263
|
+
# For the default function mode, dispatch to the Artist class so final
|
|
264
|
+
# rasterization happens at draw-time with the active renderer dpi.
|
|
265
|
+
if draw == True and return_aob == True:
|
|
266
|
+
_ = ax.add_artist(
|
|
267
|
+
ScaleBar(
|
|
268
|
+
style=style,
|
|
269
|
+
location=location,
|
|
270
|
+
bar=bar,
|
|
271
|
+
units=units,
|
|
272
|
+
labels=labels,
|
|
273
|
+
text=text,
|
|
274
|
+
aob=aob,
|
|
275
|
+
zorder=zorder,
|
|
276
|
+
)
|
|
277
|
+
)
|
|
278
|
+
return
|
|
254
279
|
|
|
255
280
|
##### VALIDATION #####
|
|
256
281
|
_style = sbf._validate(sbt._VALIDATE_PRIMARY, "style", style)
|
|
@@ -272,6 +297,12 @@ def scale_bar(ax, draw=True, style: Literal["ticks","boxes"]="boxes",
|
|
|
272
297
|
_text = sbf._validate_dict(text, copy.deepcopy(_DEFAULT_TEXT), sbt._VALIDATE_TEXT, return_clean=True) # this one has to be a deepcopy due to dictionary immutability
|
|
273
298
|
_aob = sbf._validate_dict(aob, _DEFAULT_AOB, sbt._VALIDATE_AOB, return_clean=True)
|
|
274
299
|
|
|
300
|
+
# Raster controls for the temporary rendered image.
|
|
301
|
+
# These are kept explicit so output quality is not coupled to external rc state.
|
|
302
|
+
_fig = ax.get_figure()
|
|
303
|
+
_raster_dpi, _raster_dpi_scale = _resolve_raster_dpi(_bar, _fig)
|
|
304
|
+
_raster_dpi = _raster_dpi * _raster_dpi_scale
|
|
305
|
+
|
|
275
306
|
##### CONFIGURING TEXT #####
|
|
276
307
|
# First need to convert each string font size (if any) to a point size
|
|
277
308
|
for d in [_text, _labels, _units]:
|
|
@@ -290,7 +321,7 @@ def scale_bar(ax, draw=True, style: Literal["ticks","boxes"]="boxes",
|
|
|
290
321
|
# First, ensuring matplotlib knows the correct dimensions for everything
|
|
291
322
|
# as we need it to be accurate to calculate out the plots!
|
|
292
323
|
if draw:
|
|
293
|
-
|
|
324
|
+
_fig.draw_without_rendering()
|
|
294
325
|
|
|
295
326
|
# Getting the config for the bar (length, text, divs, etc.)
|
|
296
327
|
bar_max, bar_length, units_label, major_div, minor_div = _config_bar(ax, _bar)
|
|
@@ -308,7 +339,7 @@ def scale_bar(ax, draw=True, style: Literal["ticks","boxes"]="boxes",
|
|
|
308
339
|
units_label = _units["label"]
|
|
309
340
|
|
|
310
341
|
# Creating a temporary figure and axis for rendering later
|
|
311
|
-
fig_temp, ax_temp = _temp_figure(ax)
|
|
342
|
+
fig_temp, ax_temp = _temp_figure(ax, dpi=_raster_dpi)
|
|
312
343
|
|
|
313
344
|
##### BAR CONSTRUCTION #####
|
|
314
345
|
|
|
@@ -472,7 +503,14 @@ def scale_bar(ax, draw=True, style: Literal["ticks","boxes"]="boxes",
|
|
|
472
503
|
|
|
473
504
|
# Placing the image in an OffsetBox, while rotating if desired
|
|
474
505
|
# We have to set the zoom level to be relative to the DPI as well (image is in pixels)
|
|
475
|
-
offset_img = matplotlib.offsetbox.OffsetImage(
|
|
506
|
+
offset_img = matplotlib.offsetbox.OffsetImage(
|
|
507
|
+
img_scale_bar,
|
|
508
|
+
origin="upper",
|
|
509
|
+
zoom=72/fig_temp.dpi,
|
|
510
|
+
interpolation=_bar.get("interpolation", "none"),
|
|
511
|
+
dpi_cor=_bar.get("dpi_cor", True),
|
|
512
|
+
resample=_bar.get("resample", False),
|
|
513
|
+
)
|
|
476
514
|
# If desired, we can just return the rendered image in the final OffsetImage
|
|
477
515
|
# This will override any aob or draw selections! Only the OffsetImage is returned!
|
|
478
516
|
if return_aob==False:
|
|
@@ -771,7 +809,6 @@ def _config_bar_dim(ax, bar_vertical, bar_projection, bar_unit):
|
|
|
771
809
|
units_user = None
|
|
772
810
|
|
|
773
811
|
# Converting
|
|
774
|
-
|
|
775
812
|
# First, the case where the user doesn't provide any units
|
|
776
813
|
# In this instance, we just use the units from the projection
|
|
777
814
|
if units_user is None:
|
|
@@ -785,6 +822,9 @@ def _config_bar_dim(ax, bar_vertical, bar_projection, bar_unit):
|
|
|
785
822
|
elif units_proj == "ft" and ax_range > (5280*5):
|
|
786
823
|
ax_units = ax_range / 5280
|
|
787
824
|
units_label = "mi"
|
|
825
|
+
# Otherwise, if no scaling is necessary...
|
|
826
|
+
else:
|
|
827
|
+
ax_units = ax_range
|
|
788
828
|
|
|
789
829
|
# Otherwise, if the user supplied a unit of some sort, then handle conversion
|
|
790
830
|
else:
|
|
@@ -793,6 +833,9 @@ def _config_bar_dim(ax, bar_vertical, bar_projection, bar_unit):
|
|
|
793
833
|
if units_user != units_proj:
|
|
794
834
|
# This works by finding the ratios between the two units, using meters as the base
|
|
795
835
|
ax_units = ax_range * (sbt.convert_dict[units_proj] / sbt.convert_dict[units_user])
|
|
836
|
+
# Otherwise, if the units are the same
|
|
837
|
+
else:
|
|
838
|
+
ax_units = ax_range
|
|
796
839
|
|
|
797
840
|
return ax_inches, ax_units, units_label
|
|
798
841
|
|
|
@@ -1082,15 +1125,18 @@ def _format_numeric(val, fmt, integer_override=True):
|
|
|
1082
1125
|
return f"{val:{fmt}}"
|
|
1083
1126
|
|
|
1084
1127
|
# A small function for creating a temporary figure based on a provided axis
|
|
1085
|
-
def _temp_figure(ax, axis=False, visible=False):
|
|
1128
|
+
def _temp_figure(ax, axis=False, visible=False, dpi=None):
|
|
1086
1129
|
# Getting the figure of the provided axis
|
|
1087
1130
|
fig = ax.get_figure()
|
|
1131
|
+
# If no dpi is passed, fall back to the figure dpi
|
|
1132
|
+
if dpi is None:
|
|
1133
|
+
dpi = fig.dpi
|
|
1088
1134
|
# Getting the dimensions of the axis
|
|
1089
1135
|
ax_bbox = ax.patch.get_window_extent()
|
|
1090
1136
|
# Converting to inches and rounding up
|
|
1091
1137
|
ax_dim = math.ceil(max(ax_bbox.height, ax_bbox.width) / fig.dpi)
|
|
1092
1138
|
# Creating a new temporary figure
|
|
1093
|
-
fig_temp, ax_temp = matplotlib.pyplot.subplots(1,1, figsize=(ax_dim*1.5, ax_dim*1.5), dpi=
|
|
1139
|
+
fig_temp, ax_temp = matplotlib.pyplot.subplots(1,1, figsize=(ax_dim*1.5, ax_dim*1.5), dpi=dpi)
|
|
1094
1140
|
# Turning off the x and y labels if desired
|
|
1095
1141
|
if axis == False:
|
|
1096
1142
|
ax_temp.axis("off")
|
|
@@ -1265,9 +1311,9 @@ def _render_as_image(fig, ax, artist, rotation, add=True, remove=True, close=Tru
|
|
|
1265
1311
|
# If needed, adding the artist to the axis
|
|
1266
1312
|
if add == True:
|
|
1267
1313
|
ax.add_artist(artist)
|
|
1268
|
-
#
|
|
1269
|
-
|
|
1270
|
-
#
|
|
1314
|
+
# Render directly with Agg; a prior draw_without_rendering() can override
|
|
1315
|
+
# temporary figure DPI in some wrappers (e.g., UltraPlot), which makes
|
|
1316
|
+
# raster_dpi ineffective.
|
|
1271
1317
|
canvas = FigureCanvasAgg(fig)
|
|
1272
1318
|
# Draws the figure onto the canvas
|
|
1273
1319
|
canvas.draw()
|
|
@@ -1286,4 +1332,15 @@ def _render_as_image(fig, ax, artist, rotation, add=True, remove=True, close=Tru
|
|
|
1286
1332
|
if close == True:
|
|
1287
1333
|
matplotlib.pyplot.close(fig)
|
|
1288
1334
|
# Returning the image
|
|
1289
|
-
return img
|
|
1335
|
+
return img
|
|
1336
|
+
|
|
1337
|
+
|
|
1338
|
+
def _resolve_raster_dpi(bar, fig, renderer=None):
|
|
1339
|
+
"""
|
|
1340
|
+
Resolve base raster DPI and raster scale for temporary rendering.
|
|
1341
|
+
"""
|
|
1342
|
+
raster_dpi = bar.get("raster_dpi", None)
|
|
1343
|
+
if raster_dpi is None:
|
|
1344
|
+
raster_dpi = renderer.dpi if renderer is not None else fig.dpi
|
|
1345
|
+
raster_dpi_scale = bar.get("raster_dpi_scale", 1)
|
|
1346
|
+
return raster_dpi, raster_dpi_scale
|
{matplotlib_map_utils-3.1.0 → matplotlib_map_utils-3.1.2}/matplotlib_map_utils/defaults/scale_bar.py
RENAMED
|
@@ -35,7 +35,12 @@ _BAR_XS = {
|
|
|
35
35
|
"tick_loc":"above",
|
|
36
36
|
"basecolors":["black"],
|
|
37
37
|
"tickcolors":["black"],
|
|
38
|
-
"tickwidth":0.5 # changed
|
|
38
|
+
"tickwidth":0.5, # changed
|
|
39
|
+
"interpolation":"none",
|
|
40
|
+
"dpi_cor":True,
|
|
41
|
+
"resample":False,
|
|
42
|
+
"raster_dpi":None,
|
|
43
|
+
"raster_dpi_scale":1,
|
|
39
44
|
}
|
|
40
45
|
|
|
41
46
|
# Labels
|
|
@@ -107,7 +112,12 @@ _BAR_SM = {
|
|
|
107
112
|
"tick_loc":"above",
|
|
108
113
|
"basecolors":["black"],
|
|
109
114
|
"tickcolors":["black"],
|
|
110
|
-
"tickwidth":0.75 # changed
|
|
115
|
+
"tickwidth":0.75, # changed
|
|
116
|
+
"interpolation":"none",
|
|
117
|
+
"dpi_cor":True,
|
|
118
|
+
"resample":False,
|
|
119
|
+
"raster_dpi":None,
|
|
120
|
+
"raster_dpi_scale":1,
|
|
111
121
|
}
|
|
112
122
|
|
|
113
123
|
# Labels
|
|
@@ -179,7 +189,12 @@ _BAR_MD = {
|
|
|
179
189
|
"tick_loc":"above",
|
|
180
190
|
"basecolors":["black"],
|
|
181
191
|
"tickcolors":["black"],
|
|
182
|
-
"tickwidth":1.5 # changed
|
|
192
|
+
"tickwidth":1.5, # changed
|
|
193
|
+
"interpolation":"none",
|
|
194
|
+
"dpi_cor":True,
|
|
195
|
+
"resample":False,
|
|
196
|
+
"raster_dpi":None,
|
|
197
|
+
"raster_dpi_scale":1,
|
|
183
198
|
}
|
|
184
199
|
|
|
185
200
|
# Labels
|
|
@@ -251,7 +266,12 @@ _BAR_LG = {
|
|
|
251
266
|
"tick_loc":"above",
|
|
252
267
|
"basecolors":["black"],
|
|
253
268
|
"tickcolors":["black"],
|
|
254
|
-
"tickwidth":3 # changed
|
|
269
|
+
"tickwidth":3, # changed
|
|
270
|
+
"interpolation":"none",
|
|
271
|
+
"dpi_cor":True,
|
|
272
|
+
"resample":False,
|
|
273
|
+
"raster_dpi":None,
|
|
274
|
+
"raster_dpi_scale":1,
|
|
255
275
|
}
|
|
256
276
|
|
|
257
277
|
# Labels
|
|
@@ -323,7 +343,12 @@ _BAR_XL = {
|
|
|
323
343
|
"tick_loc":"above",
|
|
324
344
|
"basecolors":["black"],
|
|
325
345
|
"tickcolors":["black"],
|
|
326
|
-
"tickwidth":5 # changed
|
|
346
|
+
"tickwidth":5, # changed
|
|
347
|
+
"interpolation":"none",
|
|
348
|
+
"dpi_cor":True,
|
|
349
|
+
"resample":False,
|
|
350
|
+
"raster_dpi":None,
|
|
351
|
+
"raster_dpi_scale":1,
|
|
327
352
|
}
|
|
328
353
|
|
|
329
354
|
# Labels
|
|
@@ -379,4 +404,4 @@ _DEFAULTS_SB = {
|
|
|
379
404
|
"md":[_BAR_MD, _LABELS_MD, _UNITS_MD, _TEXT_MD, _AOB_MD],
|
|
380
405
|
"lg":[_BAR_LG, _LABELS_LG, _UNITS_LG, _TEXT_LG, _AOB_LG],
|
|
381
406
|
"xl":[_BAR_XL, _LABELS_XL, _UNITS_XL, _TEXT_XL, _AOB_XL],
|
|
382
|
-
}
|
|
407
|
+
}
|
|
@@ -99,6 +99,11 @@ class _TYPE_BAR(TypedDict, total=False):
|
|
|
99
99
|
basecolors: list | tuple | str # a color or list of colors to use for the bottom bar
|
|
100
100
|
tickcolors: list | tuple | str # a color or list of colors to use for the ticks
|
|
101
101
|
tickwidth: float | int # the line thickness of the bottom bar and ticks
|
|
102
|
+
interpolation: str | None # interpolation method used by OffsetImage; e.g. "none", "nearest", "bilinear"
|
|
103
|
+
dpi_cor: bool # whether OffsetImage should be corrected for renderer dpi (matplotlib default behavior)
|
|
104
|
+
resample: bool # whether OffsetImage should use image resampling during scaling
|
|
105
|
+
raster_dpi: float | int | None # explicit dpi for temporary rasterization step, None uses figure/renderer dpi
|
|
106
|
+
raster_dpi_scale: float | int # multiplier applied to raster_dpi for supersampling
|
|
102
107
|
|
|
103
108
|
|
|
104
109
|
class _TYPE_LABELS(TypedDict, total=False):
|
|
@@ -195,6 +200,11 @@ _VALIDATE_BAR = {
|
|
|
195
200
|
"basecolors":{"func":vf._validate_iterable, "kwargs":{"func":matplotlib.rcsetup.validate_color}}, # ticks only: any color value for matplotlib
|
|
196
201
|
"tickcolors":{"func":vf._validate_iterable, "kwargs":{"func":matplotlib.rcsetup.validate_color}}, # ticks only: any color value for matplotlib
|
|
197
202
|
"tickwidth":{"func":vf._validate_range, "kwargs":{"min":0, "max":None, "none_ok":True}}, # ticks only: between 0 and inf
|
|
203
|
+
"interpolation":{"func":vf._validate_type, "kwargs":{"match":str, "none_ok":True}},
|
|
204
|
+
"dpi_cor":{"func":vf._validate_type, "kwargs":{"match":bool}},
|
|
205
|
+
"resample":{"func":vf._validate_type, "kwargs":{"match":bool}},
|
|
206
|
+
"raster_dpi":{"func":vf._validate_range, "kwargs":{"min":1, "max":None, "none_ok":True}},
|
|
207
|
+
"raster_dpi_scale":{"func":vf._validate_range, "kwargs":{"min":0.0001, "max":None, "none_ok":True}},
|
|
198
208
|
}
|
|
199
209
|
|
|
200
210
|
_VALID_LABELS_STYLE = get_args(_TYPE_LABELS.__annotations__["style"])
|
|
@@ -272,4 +282,4 @@ _VALIDATE_AOB = {
|
|
|
272
282
|
"frameon":{"func":vf._validate_type, "kwargs":{"match":bool}}, # any bool
|
|
273
283
|
"bbox_to_anchor":{"func":vf._skip_validation}, # NOTE: currently unvalidated, use at your own risk!
|
|
274
284
|
"bbox_transform":{"func":vf._skip_validation}, # NOTE: currently unvalidated, use at your own risk!
|
|
275
|
-
}
|
|
285
|
+
}
|
{matplotlib_map_utils-3.1.0 → matplotlib_map_utils-3.1.2}/matplotlib_map_utils.egg-info/PKG-INFO
RENAMED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: matplotlib-map-utils
|
|
3
|
-
Version: 3.1.
|
|
3
|
+
Version: 3.1.2
|
|
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/
|
|
@@ -179,7 +179,9 @@ This will create an output like the following:
|
|
|
179
179
|
|
|
180
180
|

|
|
181
181
|
|
|
182
|
-
Refer to `docs\howto_north_arrow` for details on how to customize each facet of the north arrow.
|
|
182
|
+
Refer to `docs\howto_north_arrow` for details on how to customize each facet of the north arrow.
|
|
183
|
+
|
|
184
|
+
_Note: only add a north arrow **after** adding all of your geodata and changing your axis limits!_
|
|
183
185
|
|
|
184
186
|
#### Rotation
|
|
185
187
|
|
|
@@ -260,6 +262,8 @@ This will create an output like the following:
|
|
|
260
262
|
|
|
261
263
|
Refer to `docs\howto_scale_bar` for details on how to customize each facet of the scale bar.
|
|
262
264
|
|
|
265
|
+
_Note: only add a scale bar **after** adding all of your geodata and changing your axis limits!_
|
|
266
|
+
|
|
263
267
|
#### Specifying Length
|
|
264
268
|
|
|
265
269
|
There are three main ways of specifying the length of a scale bar:
|
|
@@ -291,7 +295,6 @@ All of the above cases expect a valid CRS to be supplied to the `projection` par
|
|
|
291
295
|
- 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
296
|
|
|
293
297
|
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
|
-
|
|
295
298
|
</details>
|
|
296
299
|
|
|
297
300
|
---
|
|
@@ -351,7 +354,6 @@ This will create an output like the following (extent indicator on the left, det
|
|
|
351
354
|

|
|
352
355
|
|
|
353
356
|
Refer to `docs\howto_inset_map` for details on how to customize the inset map and indicators to your liking.
|
|
354
|
-
|
|
355
357
|
</details>
|
|
356
358
|
|
|
357
359
|
---
|
|
@@ -383,7 +385,6 @@ usa.filter(region=["South","Midwest"], to_return="name")
|
|
|
383
385
|
```
|
|
384
386
|
|
|
385
387
|
Refer to `docs\howto_utils` for details on how to use this class, including with `pandas.apply()`.
|
|
386
|
-
|
|
387
388
|
</details>
|
|
388
389
|
|
|
389
390
|
---
|
|
@@ -414,9 +415,7 @@ Two more projects assisted with the creation of this script:
|
|
|
414
415
|
- `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.
|
|
415
416
|
|
|
416
417
|
- `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.
|
|
417
|
-
|
|
418
418
|
</details>
|
|
419
|
-
<br>
|
|
420
419
|
|
|
421
420
|
- `v3.0.0`: Release of inset map and extent and detail indicator classes and functions.
|
|
422
421
|
|
|
@@ -424,6 +423,10 @@ Two more projects assisted with the creation of this script:
|
|
|
424
423
|
|
|
425
424
|
- `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
425
|
|
|
426
|
+
- `v3.1.1`: Fixed a bug that led to errors when creating a `scale_bar` at resolutions below 5km or 1 mile, due to a bug in the backend configuration functions (namely, `_config_bar_dim()`), which was fixed by correctly instantiating the necessary variable `ax_units` in other cases via an `else` statement (see [here](https://github.com/moss-xyz/matplotlib-map-utils/issues/14) for details).
|
|
427
|
+
|
|
428
|
+
- `v3.1.2`: Fixed a compatibility issue with [Ultraplot](https://github.com/Ultraplot/UltraPlot), primarily affecting the `ScaleBar` element, where text would rasterize at a low resolution (see [here](https://github.com/moss-xyz/matplotlib-map-utils/issues/16) and [here](https://github.com/moss-xyz/matplotlib-map-utils/pull/17) for details). A big thank you to cvanelteren on the Ultraplot team for identifying and implementing the necessary fixes, as well as making adjustments to the Ultraplot package to improve compatibility!
|
|
429
|
+
|
|
427
430
|
#### Future Roadmap
|
|
428
431
|
|
|
429
432
|
With the release of `v3.x`, this project has achieved full coverage of the "main" map elements I think are necessary.
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "matplotlib-map-utils"
|
|
7
|
-
version = "3.1.
|
|
7
|
+
version = "3.1.2"
|
|
8
8
|
authors = [
|
|
9
9
|
{ name="David Moss", email="davidmoss1221@gmail.com" },
|
|
10
10
|
]
|
|
@@ -29,6 +29,17 @@ exclude = ["matplotlib_map_utils.scratch*"]
|
|
|
29
29
|
[tool.setuptools.package-data]
|
|
30
30
|
"matplotlib_map_utils.utils" = ["*.json"]
|
|
31
31
|
|
|
32
|
+
[dependency-groups]
|
|
33
|
+
dev = [
|
|
34
|
+
"contextily>=1.6.2",
|
|
35
|
+
"geopandas>=1.1.1",
|
|
36
|
+
"ipykernel>=6.30.1",
|
|
37
|
+
"jupyter>=1.1.1",
|
|
38
|
+
"notebook>=7.4.7",
|
|
39
|
+
"pip>=25.2",
|
|
40
|
+
"pygris>=0.2.0",
|
|
41
|
+
]
|
|
42
|
+
|
|
32
43
|
[project.urls]
|
|
33
44
|
"Homepage" = "https://github.com/moss-xyz/matplotlib-map-utils/"
|
|
34
45
|
"Bug Tracker" = "https://github.com/moss-xyz/matplotlib-map-utils/issues"
|
|
File without changes
|
|
File without changes
|
{matplotlib_map_utils-3.1.0 → matplotlib_map_utils-3.1.2}/matplotlib_map_utils/core/__init__.py
RENAMED
|
File without changes
|
{matplotlib_map_utils-3.1.0 → matplotlib_map_utils-3.1.2}/matplotlib_map_utils/core/inset_map.py
RENAMED
|
File without changes
|
{matplotlib_map_utils-3.1.0 → matplotlib_map_utils-3.1.2}/matplotlib_map_utils/core/north_arrow.py
RENAMED
|
File without changes
|
{matplotlib_map_utils-3.1.0 → matplotlib_map_utils-3.1.2}/matplotlib_map_utils/defaults/__init__.py
RENAMED
|
File without changes
|
{matplotlib_map_utils-3.1.0 → matplotlib_map_utils-3.1.2}/matplotlib_map_utils/defaults/inset_map.py
RENAMED
|
File without changes
|
|
File without changes
|
{matplotlib_map_utils-3.1.0 → matplotlib_map_utils-3.1.2}/matplotlib_map_utils/scratch/map_utils.py
RENAMED
|
File without changes
|
|
File without changes
|
{matplotlib_map_utils-3.1.0 → matplotlib_map_utils-3.1.2}/matplotlib_map_utils/utils/__init__.py
RENAMED
|
File without changes
|
{matplotlib_map_utils-3.1.0 → matplotlib_map_utils-3.1.2}/matplotlib_map_utils/utils/usa.json
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{matplotlib_map_utils-3.1.0 → matplotlib_map_utils-3.1.2}/matplotlib_map_utils.egg-info/SOURCES.txt
RENAMED
|
File without changes
|
|
File without changes
|
{matplotlib_map_utils-3.1.0 → matplotlib_map_utils-3.1.2}/matplotlib_map_utils.egg-info/requires.txt
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|