Skip to content

Compatibility issue with matplotlib-map-utils package #588

@chudlerk

Description

@chudlerk

Hi,

I've recently been making maps using the new(ish) matplotlib-map-utils package, referenced in the new geopandas documentation.

There appear to be some compatibility issues somewhere with ultraplot.

If I run this simple code:

from matplotlib_map_utils.core.scale_bar import ScaleBar, scale_bar
import matplotlib.pyplot as plt
import cartopy.crs as ccrs

bounds = [-122.3094136,   41.02776967, -121.65305008,   41.61986174]
c_lon = (bounds[0] + bounds[2]) / 2
c_lat = (bounds[1] + bounds[3]) / 2
plot_crs = ccrs.LambertConformal(central_longitude=c_lon, central_latitude=c_lat)

fig, ax = plt.subplots(subplot_kw={'projection': plot_crs}, dpi=150)
ax.set_extent((bounds[0], bounds[2], bounds[1], bounds[3]), crs=ccrs.PlateCarree())
scale_bar(ax, bar={"projection": plot_crs})
fig.savefig('test.png', dpi=150)

The code runs and the figure saves just fine.

However, if I do this with ultraplot instead..

from matplotlib_map_utils.core.scale_bar import ScaleBar, scale_bar
import matplotlib.pyplot as plt
import cartopy.crs as ccrs

bounds = [-122.3094136,   41.02776967, -121.65305008,   41.61986174]
c_lon = (bounds[0] + bounds[2]) / 2
c_lat = (bounds[1] + bounds[3]) / 2
plot_crs = ccrs.LambertConformal(central_longitude=c_lon, central_latitude=c_lat)

fig, ax = uplt.subplots(projection=plot_crs, dpi=150)
ax.set_extent((bounds[0], bounds[2], bounds[1], bounds[3]), crs=ccrs.PlateCarree())
scale_bar(ax, bar={"projection": plot_crs})
fig.savefig('C:/Users/kchudler/Downloads/ultraplot_test.png', dpi=150)

The numbers and text around the scale bar appear fuzzy in the saved image.
Image

Interestingly, if I then rove the first version of the code with mpl again, I get the fuzzy text in the re-saved figure. So it appears as if importing/making a figure with ultraplot monkeys around this the matplotlib settings in a way that impacts future calls to scale_bar

I brought this issue up in the matplotlib-map-utils repo, and this was the response:

Hmmm, I don't mind making changes to this package to work better with ultraplot, but given that this works fine with classic matplotlib, I would imagine this is an issue you should raise with ultraplot, to at least ask what is going on in their translation step between ultraplot and mpl that would cause this issue?

Interestingly, this seems specific to the ScaleBar object - the NorthArrow text renders fine! That points to a rather specific cause: while NorthArrows are kept as collections of (vector) artist objects, the composite ScaleBars (meaning text + the bar itself) are rasterized as images and then placed via an OffsetImage instead; I had to do things this way to handle some issues with rotation.

I don't know why Ultraplot would just be affecting the text though, and not pixelating the rest of the bar - or perhaps it is and we just can't tell?

Unfortunately, I don't really have a lot of time to dive into this myself right now (this is something I work on when I'm between jobs). If you wanted to fork a branch and start debugging yourself, you would probably only have to work in a single file: scale_bar.py in core/. You could follow the flow of the scale_bar() function within it, paying particular attention to _temp_figure() and _make_text() and _render_as_image() within it (mainly the first and last), and seeing what the intermediate outputs look like.

(I do know that _temp_figure() creates some new subplots using the mpl call so I wonder if that is the issue - perhaps that would be a worthwhile question to ask the ultraplot team.)

Let me know your thoughts!

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions