pygmt
pygmt copied to clipboard
Allow for "makecpt" style colormap functionality in grdimage and colobar
In classic gmt the function makecpt
is used to create a "cpt" file that acts as a color map for plotting data in grdimage
and in plotting a colorbar.
In its present state, pygmt does not (to the best of my knowledge) allow for creating a custom colormap for use in both grdimage
and colorbar
, which greatly limits the utility of pygmt. Such functionality could be achieved in the following way:
fig.makecpt(limits=[min, max], cmap=..., transparency=False, cpt='name of temporary output cpt file')
fig.grdimage(cpt='name of temporary cpt file')
fig.colorbar(cpt='name of temporary cpt file')
In practice, a single image could have several cpt files associated with it.
It's not very well documented, but we do have a makecpt function as of #329. It actually works via pygmt.makecpt
rather than fig.makecpt
. Also GMT6 modern mode (which PyGMT uses) allows you to create a hidden Color Palette Table (CPT) and use it in subsequent commands automatically (see https://docs.generic-mapping-tools.org/6.0/makecpt.html#note-on-cpts-in-modern-mode) so we don't actually need to set the cpt in grdimage
/colorbar
(if this sounds confusing, let me know).
The way you would do this in your code snippet then is as follows:
pygmt.makecpt(series=[min, max], cmap=...)
fig.grdimage(...)
fig.colorbar(...)
After playing around with pygmt.makecpt
, I have run into two problems.
-
After you create a colormap with
makecpt
, it is not possible to change the session colormap to a different one. Creating a new colormap has no effect on any subsequent figure. The only way to make a new image with a different colormap is to kill the python kernel and start over again. This occurs with both the terminal and notebook environments. -
makecpt
gives you the option to save the generated colormap to a file, however, it would be more useful if you could instead save it to a python variable, and then specify this variable in subsequent calls to grdimage and colorbar. It is hard for me to imagine the case where you would want to save the cpt data to a file.
I agree that pygmt.makecpt
could definitely be a lot better, it's not intuitive the way things work.
Point 1: . Right now if you want to change to another colormap, you'll need to call makecpt
after fig = pygmt.Figure()
like so:
fig = pygmt.Figure()
pygmt.makecpt(cmap="geo")
fig.grdimage(,,,)
fig.show()
fig = pygmt.Figure()
pygmt.makecpt(cmap="oleron")
fig.grdimage(,,,)
fig.show()
rather than this:
pygmt.makecpt(cmap="geo")
fig = pygmt.Figure()
fig.grdimage(,,,)
fig.show()
pygmt.makecpt(cmap="oleron")
fig = pygmt.Figure()
fig.grdimage(,,,)
fig.show()
The first one creates a cpt specifically for the figure, whereas the second one creates a session colormap as you said that can't be overridden.
Point 2. This would definitely be a better way. and what you're asking for here I think is similar to what was tried in #126.
Here is my suggestion on how to resolve this problem:
-
pygmt.makecpt()
creates a default colormap, to be used when one is not specified. Regardless, you should have the option of changing the default (unlike the present behavior). -
Create the method
pygmt.Figure.makecpt()
which creates a custom colormap for the specified figure. This would be used as
fig = pygmt.Figure()
fig.makecpt()
fig.grdimage()
...
I have not yet tried the new modern mode in GMT 6, but I read the note that @weiji14 linked. It seems that GMT 6 uses "hidden" files to store potentially several colormaps with a hierarchy of scope for different parts of the figure. I understand that PyGMT is keeping things simple, so supporting a hierarchy of colormaps with different scope might be too much. It still seems like it is very confusing to not be able to change the session colormap for each figure, as Mark found.
I often plot several datasets in a single figure with different colormaps for each one, and it sounds like the present implementation of PyGMT would make that impossible. I am not clear whether creating a new figure object clears what was plotted before or overlays it in PyGMT. If I were to try to do the plots that I do with mulitple colormaps in one figure, it would be something like this:
fig = pygmt.Figure()
fig.colormap()
fig.grdimage(,,,)
fig.colormap()
fig.grdimage(,,,)
fig.show()
I'm so confused about the discussions above. Could you give some examples which don't work as expected?
To me, the following script works as expected:
import pygmt
fig = pygmt.Figure()
pygmt.makecpt(cmap="etopo1")
fig.grdimage("@earth_relief_10m", projection="H10c", frame=True)
fig.colorbar(frame=True)
fig.shift_origin(yshift="10c")
pygmt.makecpt(cmap="earth")
fig.grdimage("@earth_relief_10m", projection="H10c", frame=True)
fig.colorbar(frame=True)
fig.savefig("map.pdf")
try this!
import pygmt
earth = pygmt.datasets.load_earth_relief()
pygmt.makecpt(cmap="roma", series=[-8000, 5000])
fig = pygmt.Figure()
fig.grdimage(earth, projection="H10c", frame=True)
fig.colorbar(frame=True)
fig.savefig('test.pdf')
pygmt.makecpt(cmap="viridis", series=[-8000, 5000])
fig = pygmt.Figure()
fig.grdimage(earth, projection="H10c", frame=True)
fig.colorbar(frame=True)
fig.savefig('test2.pdf')
Both images look exactly the same.
Edit: Also the "Y" option is undocumented. It is good to know that this exists.
@MarkWieczorek Yes, your example doesn't work as expected to me. I believe it's an upstream (i.e. the core GMT) bug, and I've opened an issue in https://github.com/GenericMappingTools/gmt/issues/2006.
For your example, the current working solution is to put the pygmt.makecpt
after fig = pygmt.Figure()
.
As for the "Y" option, it's equivalent to the -Y
option for GMT command-line. Yes, it should be documented, but currently not. We also provide another function fig.shift_origin()
to shift the plot origins in X or Y directions.
Below is an example of the kind of map that I was talking about. I used one colormap for the topography data and a different colormap for the SAR interferometry data in the same map. I made this with an older version of GMT several years ago.
Maybe this is too complicated to support in PyGMT.
Hi I can not figure out like how to use custom colors for cmap in place of using the color master color palette? Is this possible? If yes then how one does that? I see that in gmt one can do that but how to do this in pygmt? Thanks.
Hi I can not figure out like how to use custom colors for cmap in place of using the color master color palette? Is this possible? If yes then how one does that? I see that in gmt one can do that but how to do this in pygmt?
Do you mean using a custom CPT file or custom colors?
If you already have a custom CPT file in your current directory, you should be able to use it like cmap="my-custom.cpt"
.
Or if you want to define a CPT from a series of colors, cmap="red,blue,yellow"
should work.
BTW, it would be better if you can ask further questions in the GMT Forum.
Thanks very much. It worked. It was the second one cmap="red,blue,yellow".