basemap icon indicating copy to clipboard operation
basemap copied to clipboard

Bug in hammer projection with lon_0>0

Open William-gregory opened this issue 6 years ago • 15 comments
trafficstars

When using Basemap 'hammer' projection with lon_0 set to anything greater than 0 degrees, the map is plotted as the mirror image of reality. Setting lon_0 to negative values (like -180) works fine, but I don't want to do this as then none of my data would fit this projection and I would have to re-grid everything.

I've subsequently uninstalled & reinstalled anaconda3 (now have python 3.7) and have also reinstalled Basemap (v.1.2.0), and am still getting the same problem.

Here is the code:

import matplotlib as mpl from mpl_toolkits.basemap import Basemap import matplotlib.pyplot as plt

m = Basemap(projection='hammer', resolution = 'l', lon_0=180)

fig = plt.figure(figsize=(12,12)) m.drawcoastlines(linewidth=0.3) m.fillcontinents(color='lightgrey',lake_color='white') m.drawmapboundary(fill_color='white') plt.show()

hammer_proj

William-gregory avatar Jun 17 '19 12:06 William-gregory

I have the same problem in Basemap 'robin' projection. I had updated the basemap to 1.2.1 and matplotlib 3.1.

And I think there is another problem is relative to this problem. When lon_0 is not equal 0, all the background functions, like drawlsmask(), bluemarble(), ..., are useless.

ghzuo avatar Aug 10 '19 08:08 ghzuo

Same issue with eck4 using basemap 1.2.0, matplotlib 3.0.3, python 3.7.1.

@William-gregory / @ghzuo - were you able to use a different version to circumvent this issue?

pochedls avatar Aug 15 '19 23:08 pochedls

Most likely, the issue is related to pyproj4 or proj4 as most of the work for transforms are off-loaded to proj4.

On Thu, Aug 15, 2019 at 7:52 PM pochedls [email protected] wrote:

Same issue with eck4 using basemap 1.2.0, matplotlib 3.0.3, python 3.7.1.

@William-gregory https://github.com/William-gregory / @ghzuo https://github.com/ghzuo - were you able to use a different version to circumvent this issue?

— You are receiving this because you are subscribed to this thread. Reply to this email directly, view it on GitHub https://github.com/matplotlib/basemap/issues/463?email_source=notifications&email_token=AACHF6FVJSIHRPGOI5LZ6W3QEXT2NA5CNFSM4HYWK6GKYY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGOD4NJOIQ#issuecomment-521836322, or mute the thread https://github.com/notifications/unsubscribe-auth/AACHF6D3UOT3UOKJROGOCX3QEXT2NANCNFSM4HYWK6GA .

WeatherGod avatar Aug 16 '19 00:08 WeatherGod

I also find that, in order for the code to even run (in an anaconda environment), I need to preface it with:

import os import conda conda_file_dir = conda.file conda_dir = conda_file_dir.split('lib')[0] proj_lib = os.path.join(os.path.join(conda_dir, 'share'), 'proj') os.environ["PROJ_LIB"] = proj_lib

Previously, this preface was not needed. I do not know whether this is related to the bug the OP reported. The inverted images occur with many of the map projections, but not for 'cyl', which is just a lat-long projection.

gkvallis avatar Dec 13 '19 16:12 gkvallis

Any idea to solve this strange problem ? With lon_0 not equal to 0, my map is completely empty !

from mpl_toolkits.basemap import Basemap
import matplotlib.pyplot as plt
m = Basemap(projection='robin', lon_0=10, resolution='l')
m.etopo()
plt.show()
Capture d’écran 2020-11-08 à 08-11-20 00 08 27

sbonaime avatar Nov 07 '20 23:11 sbonaime

@sbonaime - I have largely transitioned to cartopy, but I recall using a negative value, e.g., lon_0=-180, gave me something that looked right.

pochedls avatar Nov 07 '20 23:11 pochedls

@pochedls I should update my old script ! with lon_0=0, my map is ok but I need lon_0=15... Any workaround like installling an "old" lib ?

sbonaime avatar Nov 07 '20 23:11 sbonaime

@sbonaime - I assume it would be possible to address this with an older library (perhaps just creating a conda environment with an older version of basemap would work). lon_0=-345 might work?

pochedls avatar Nov 07 '20 23:11 pochedls

@pochedls lon_0=-345 is not working... Maybe I should take some time to update to cartopy. Thanks

sbonaime avatar Nov 07 '20 23:11 sbonaime

So, I've hit a similar issue, code I've used to reproduce, blue-marble with robin projection

from mpl_toolkits.basemap import Basemap
import matplotlib.pyplot as plt

m = Basemap(projection="robin", lon_0=0, resolution=None)
m.bluemarble()
plt.show()

Expected output: image

It works on all tested base map versions - 1.1.0 - 1.3.4 only if I downgrade matplotlib to 3.4.3, 3.5.X release doesn't work with any version of base map I've tried.

TL;DR try downgrading matplotlib, ~3.4.3 worked for me

PhillCli avatar Aug 17 '22 12:08 PhillCli

@PhillCli Thanks for the feedback and the hint about the matplotlib version. Do you have the full traceback that you get when using matplotlib 3.5.x? Probably some deprecated matplotlib syntax was removed in 3.5.x and basemap is still using the old syntax. I will take a look to it when I get some free time.

molinav avatar Aug 17 '22 12:08 molinav

Do you have the full traceback that you get when using matplotlib 3.5.x?

It's a silent failure, the plot is generated but is completely empty except for an outline. Just like in this post comment

There is a warning, but it's also present in the working case:

Clipping input data to the valid range for imshow with RGB data ([0..1] for floats or [0..255] for integers).

EDIT: Another piece of hint is that it's related to projections, if the projection is removed background map is plotted correctly.

PhillCli avatar Aug 17 '22 13:08 PhillCli

@PhillCli Removing the projection argument is equivalent to setting projection="cyl".

From your code snippet, if you try to do the following with the Robin projection:

plt.imshow(m._bm_rgba_warped)

you can see that the transformed image is actually there and it is transformed correctly (note that the image will appear upside down in the figure, but this also occurs in matplotlib 3.4.x, so I assume it is the normal behaviour). When setting projection="cyl" (or not defining it), the underlying image is stored in a different hidden attribute:

plt.imshow(m._bm_rgba)

So the problem does not seem to be with the projection transformations but with the rendering of the image by matplotlib. Furthermore, if I just add one line to your code snippet then the image is shown (using matplotlib version 3.5.3):

from mpl_toolkits.basemap import Basemap
import matplotlib.pyplot as plt

m = Basemap(projection="robin", lon_0=0, resolution=None)
im1 = m.bluemarble()
im1.axes.add_image(im1)
plt.show()

bluemarble_robin

The problem that you described propagates to all the Basemap methods related to drawing image backgrounds, since all of them rely on Basemap.warpimage, which in the end is calling Basemap.imshow to show the image.

molinav avatar Aug 18 '22 00:08 molinav

Going a bit more into the im1 object from my line added, just a couple of outputs from an interactive session:

In [24]: type(im1.axes)
Out[24]: matplotlib.axes._subplots.AxesSubplot

In [25]: im1.axes.get_images()[0]
Out[25]: <matplotlib.image.AxesImage at 0x204343eaaf0>

In [26]: im1.axes.get_images()[0] is im1
Out[26]: True

so im1.axes actually has a list of images containing only im1, which is our rebel axes image. At least this looks normal to me.

molinav avatar Aug 18 '22 00:08 molinav

@molinav Thanks for the investigation, I'm not that familiar with the internals of Basemap.

Good to know the image is still properly transformed, and just a matter of explicitly adding it to Axes object.

That would make sense that something about rendering changed in 3.5.3 that breaks the default Basemap imshow, wonder if that was also the case for the @sbonaime issue.

It might be valuable to update the docs I think that's where the snippet I tried to fix originated from here.

PhillCli avatar Aug 18 '22 15:08 PhillCli

I have the similar issue with "moll" projection, and find a very rough solution. See if the steps described in #577 can solve your problem.

When using Basemap 'hammer' projection with lon_0 set to anything greater than 0 degrees, the map is plotted as the mirror image of reality. Setting lon_0 to negative values (like -180) works fine, but I don't want to do this as then none of my data would fit this projection and I would have to re-grid everything.

I've subsequently uninstalled & reinstalled anaconda3 (now have python 3.7) and have also reinstalled Basemap (v.1.2.0), and am still getting the same problem.

Here is the code:

import matplotlib as mpl from mpl_toolkits.basemap import Basemap import matplotlib.pyplot as plt

m = Basemap(projection='hammer', resolution = 'l', lon_0=180)

fig = plt.figure(figsize=(12,12)) m.drawcoastlines(linewidth=0.3) m.fillcontinents(color='lightgrey',lake_color='white') m.drawmapboundary(fill_color='white') plt.show()

hammer_proj

YilongWang avatar Jul 04 '23 13:07 YilongWang

I have the similar issue with "moll" projection, and find a very rough solution. See if the steps described in #577 can solve your problem.

Any idea to solve this strange problem ? With lon_0 not equal to 0, my map is completely empty !

from mpl_toolkits.basemap import Basemap
import matplotlib.pyplot as plt
m = Basemap(projection='robin', lon_0=10, resolution='l')
m.etopo()
plt.show()
Capture d’écran 2020-11-08 à 08-11-20 00 08 27

YilongWang avatar Jul 04 '23 13:07 YilongWang

I have the similar issue with "moll" projection, and find a very rough solution. See if the steps described in #577 can solve your problem. In basemap-1.3.7, Line 3206, you can add ",fill_color='none'" for limb2, the modified code looks like: # draw another filled patch, with no boundary. limb2 = self.drawmapboundary(linewidth=0, ax=ax,fill_color='none') self._mapboundarydrawn = limb2 If seems limb2 is not necessary any more in current version of basemap.

@molinav Thanks for the investigation, I'm not that familiar with the internals of Basemap.

Good to know the image is still properly transformed, and just a matter of explicitly adding it to Axes object.

That would make sense that something about rendering changed in 3.5.3 that breaks the default Basemap imshow, wonder if that was also the case for the @sbonaime issue.

It might be valuable to update the docs I think that's where the snippet I tried to fix originated from here.

YilongWang avatar Jul 04 '23 14:07 YilongWang

Tracing back with Python 3.7, the failure related to the flipped coastlines occurs in the transition of the pyproj dependency from version 1.9.6 into 2.0.0, when pyproj migrated from PROJ 4.x into PROJ 6.0. Something changed between these two PROJ versions.

molinav avatar Nov 21 '23 21:11 molinav

I close this issue as complete after applying the patch proposed by @YilongWang. If any problem persists, please free to reopen this issue or to create a new one.

molinav avatar Nov 21 '23 22:11 molinav