GenericMappingTools / pygmt

A Python interface for the Generic Mapping Tools.
https://www.pygmt.org
BSD 3-Clause "New" or "Revised" License
758 stars 220 forks source link

fig.plot or fig.grdimage ignores transparency instructions in color map #400

Closed firstkingofrome closed 4 years ago

firstkingofrome commented 4 years ago

Hello, I am trying to plot a grdimage over a hillside (another grid image). I normally would do this by using a color map with a transparency setting for the last grdimage (so that the hillside is visible underneath). It appears that the transparency instructions in my grdimage command are being ignored. I tried using a number of different outputs from the fig.savefig (pdf, png) with the same result. Thank You, any help is greatly appreciated!

The code below shows the issue (generates 2 fake xarrays and a color map with the specified transparency, plotting them over each other shows that the transparency instructions are ignored), you can just paste it into a blank jupyternotebook or ipython shell and it will run (it generates some fake data, and then attempts to plot one over the other using a transparent color map)

import pygmt 
import pandas as pd
import xarray as xr
import numpy as np
import os

### constants
sw4origin = (39.3058,-120.0052)
#sw4Xlength,sw4Ylength = 34000,34000 #in meters
#figure out the end of my region based on these dimenstions
#sw4OriginUTM = utm.from_latlon(sw4origin[0],sw4origin[1],11,"N")
#sw4EndX,sw4EndY = sw4OriginUTM[1]+sw4Xlength,sw4OriginUTM[0]+sw4Ylength
sw4EndLat,sw4EndLong = (39.62135044626656, -119.62277186293804)
region = [-120.0052,sw4EndLong,39.3058,sw4EndLat]
lat0,lon0=(39.310047, -119.999954)
latend,lonend = (39.610416, -119.61958)

### generate 2 fake xarrays
sampleXarray = np.zeros(shape=(128,145),dtype=np.float32)
for i in range(sampleXarray.shape[0]):
    for j in range(sampleXarray.shape[1]):
        sampleXarray[i,j] = i+j
underlayedXarray = np.copy(sampleXarray)
sampleXarray = np.abs(np.sin(sampleXarray))
#plt.imshow(sampleXarray)
#correctly georeference these fake xarray
xcoords = np.arange(lat0,latend,(latend-lat0)/sampleXarray.shape[0])
ycoords = np.arange(lon0,lonend,(lonend-lon0)/sampleXarray.shape[1])
dims = ['x','y']
coords = {"x":xcoords,"y":ycoords}
sampleXarray = xr.DataArray(sampleXarray,dims=dims,coords=coords)
underlayedXarray = xr.DataArray(underlayedXarray,dims=dims,coords=coords)

#attempt to plot, show that transparency is ignored
fig = pygmt.Figure()
fig.basemap(region=region,projection="M8i", frame=True)
#plot the underlying xarray (in my real problem this would be my hillshade)
fig.grdimage(underlayedXarray,C="gray")
#Now create a cpt file with the transparency option to plot over the last grdimage
os.system("gmt makecpt -A+60 -Cviridis"+" -T0.0/"+str(np.max(sampleXarray.data)) +" -Z > scaledCmap.cpt")
fig.grdimage(sampleXarray,C="scaledCmap.cpt")
fig.show()
#fig.savefig("test.pdf")
weiji14 commented 4 years ago

Hi @firstkingofrome,

Thanks for using PyGMT, and taking the time to writeup such a detailed issue! So the trick here is not to set the transparency in the makecpt command, but in the grdimage using the -ttransp option.

fig = pygmt.Figure()
fig.basemap(region=region, projection="M8i", frame=True)
# plot the underlying xarray (in my real problem this would be my hillshade)
fig.grdimage(underlayedXarray, C="gray")
# Now create a cpt file with the transparency option to plot over the last grdimage
pygmt.makecpt(cmap="viridis", series=[0.0, np.max(sampleXarray.data)], continuous=True)
fig.grdimage(sampleXarray, C=True, t=60)
fig.savefig("test.png")
fig.show()

You'll notice that it's possible to use pygmt.makecpt as of #329 (see also #372 as to why it's pygmt.makecpt and not fig.makecpt). Anyways, the code above should produce:

grdimage transparency test image

If this answers your question, feel free to close this issue.

firstkingofrome commented 4 years ago

Hello @weiji14 thank you for you're help! That solves my problem perfectly, also thanks for letting me know about the pygmt.makecpt support.

weiji14 commented 4 years ago

The 'transparency' (-t) long alias was added in #614, and should be available in the next PyGMT v0.2.1 release :wink:.