Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Bug in hammer projection with lon_0>0 #463

Closed
William-gregory opened this issue Jun 17, 2019 · 20 comments
Closed

Bug in hammer projection with lon_0>0 #463

William-gregory opened this issue Jun 17, 2019 · 20 comments

Comments

@William-gregory
Copy link

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

@ghzuo
Copy link

ghzuo commented Aug 10, 2019

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.

@pochedls
Copy link

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?

@WeatherGod
Copy link
Member

WeatherGod commented Aug 16, 2019 via email

@gkvallis
Copy link

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.

@sbonaime
Copy link

sbonaime commented Nov 7, 2020

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

@pochedls
Copy link

pochedls commented Nov 7, 2020

@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.

@sbonaime
Copy link

sbonaime commented Nov 7, 2020

@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 ?

@pochedls
Copy link

pochedls commented Nov 7, 2020

@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?

@sbonaime
Copy link

sbonaime commented Nov 7, 2020

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

@PhillCli
Copy link

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

@molinav
Copy link
Member

molinav commented Aug 17, 2022

@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.

@PhillCli
Copy link

PhillCli commented Aug 17, 2022

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.

@molinav
Copy link
Member

molinav commented Aug 18, 2022

@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
Copy link
Member

molinav commented Aug 18, 2022

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.

@PhillCli
Copy link

@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
Copy link

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
Copy link

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
Copy link

YilongWang commented Jul 4, 2023

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.

@molinav
Copy link
Member

molinav commented Nov 21, 2023

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 added a commit that referenced this issue Nov 21, 2023
Solves GitHub issue #463.

The bug appears in the `pyproj` transition from version 1.9.6 to
2.0.0, which corresponds when `pyproj` migrated from PROJ 4.x to
PROJ 6.0.
@molinav
Copy link
Member

molinav commented Nov 21, 2023

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

9 participants