# Filled contour plot - diverging, asymmetric data

**URL:** <https://forum.generic-mapping-tools.org/t/filled-contour-plot-diverging-asymmetric-data/4268>\
**Category:** PyGMT Q&A\
**Created:** [September 19, 2023, 3:02pm UTC](https://forum.generic-mapping-tools.org/t/filled-contour-plot-diverging-asymmetric-data/4268 "2023-09-19T15:02:44Z")\
**Posts on this page:** 17\
**Page:** 1

<div class="post-metadata">

**Author:** ![emmaworthington](https://yyz1.discourse-cdn.com/flex047/user_avatar/forum.generic-mapping-tools.org/emmaworthington/32/3092_2.png) [@emmaworthington](https://forum.generic-mapping-tools.org/u/emmaworthington)\
**Post date:** [September 19, 2023, 3:02pm UTC](https://forum.generic-mapping-tools.org/t/filled-contour-plot-diverging-asymmetric-data/4268/1 "2023-09-19T15:02:44Z")

</div>

Hi,

I’m trying to reproduce a cartesian matplotlib plot of a velocity section in pygmt, as I want to combine several of these with a pygmt map. This was produced using contourf(), but I’m struggled to get the same result with pygmt.

[iceland\_basin\_velocity\_section.pdf](https://forum.generic-mapping-tools.org/uploads/short-url/hTADoW8qcNkwsSut9KtkhLcbi9g.pdf) (47.8 KB)

I’ve tried grdimage(), which gives a gradient rather than the same color between contours. Can I use grdcontour() and a CPT? The data are diverging, and are asymmetric around zero. Do I need to make a diverging, asymmetric CPT? The GMT API shows a ‘-N’ option, which sounds like it might do what I want, but I’m not sure how to use this with the pygmt function, which doesn’t list an equivalent option.

If it’s not possible, please do let me know and I’ll use Inkscape to combine plots instead, as I’m new to PyGMT, it’s a very steep learning curve, and I’m very pressed for time at the moment!

many thanks for any help in advance,

Emma

---

<div class="post-metadata">

**Author:** ![PlanetGus](https://yyz1.discourse-cdn.com/flex047/user_avatar/forum.generic-mapping-tools.org/planetgus/32/303_2.png) [@PlanetGus](https://forum.generic-mapping-tools.org/u/PlanetGus)\
**Post date:** [September 19, 2023, 4:06pm UTC](https://forum.generic-mapping-tools.org/t/filled-contour-plot-diverging-asymmetric-data/4268/2 "2023-09-19T16:06:47Z")

</div>

What do your data look like ? grd[…] are for gridded data. If not, I believe [“contour” documentation](https://docs.generic-mapping-tools.org/dev/contour.html) is probably a good start/

---

<div class="post-metadata">

**Author:** ![emmaworthington](https://yyz1.discourse-cdn.com/flex047/user_avatar/forum.generic-mapping-tools.org/emmaworthington/32/3092_2.png) [@emmaworthington](https://forum.generic-mapping-tools.org/u/emmaworthington)\
**Post date:** [September 19, 2023, 4:27pm UTC](https://forum.generic-mapping-tools.org/t/filled-contour-plot-diverging-asymmetric-data/4268/3 "2023-09-19T16:27:31Z")

</div>

Hi, the data are an xarray DataArray, so velocity is 2-dimensional, with distance and depth as the x- and y-dimension.

```auto
<xarray.DataArray 'v_trans' (depth: 151, distance: 147)>
array([[nan, nan, nan, ..., nan, nan, nan],
       [nan, nan, nan, ..., nan, nan, nan],
       [nan, nan, nan, ..., nan, nan, nan],
       ...,
       [nan, nan, nan, ..., nan, nan, nan],
       [nan, nan, nan, ..., nan, nan, nan],
       [nan, nan, nan, ..., nan, nan, nan]])
Coordinates:
  * distance (distance) float64 0.0 2.26 4.52 6.78 ... 323.2 325.4 327.7 330.0
  * depth (depth) int64 1170 1182 1194 1206 1218 ... 2934 2946 2958 2970

```

If I use grdimage like this, with vel\_da as the DataArray:

```auto
fig = pygmt.Figure()

fig.grdimage(
    vel_da,
    projection='X5i/-3i',
    region=[0, 330, 1000, 3000],
    cmap='vik',
    frame=True)

```

I get this plot:

 ![pygmt_iceland_basin](https://canada1.discourse-cdn.com/flex047/uploads/gmt/original/2X/3/34272304afa6ab2fd8ba032fc2eea72fe756ebfb.png)

The white contour line shows the zero value, the data are not symmetrical around zero, there’s a minimum of around -0.11 and max of 0.05.

In an ideal world, I’d like the same color between contours (e.g. like contourf from matplotlib), but if I can’t get that, then the colormap to correctly represent positive and negative values, i.e., all positive values as red, all negative as blue.

thanks,

Emma

---

<div class="post-metadata">

**Author:** ![PlanetGus](https://yyz1.discourse-cdn.com/flex047/user_avatar/forum.generic-mapping-tools.org/planetgus/32/303_2.png) [@PlanetGus](https://forum.generic-mapping-tools.org/u/PlanetGus)\
**Post date:** [September 19, 2023, 4:40pm UTC](https://forum.generic-mapping-tools.org/t/filled-contour-plot-diverging-asymmetric-data/4268/4 "2023-09-19T16:40:23Z")

</div>

You can modify it indeed (from makecpt):

> If given a master CPT with soft-hinges then you can enable the hinge at data value _hinge_ [0] via **+h** , whereas for hard-hinge CPTs you can adjust the location of the hinge [0].

---

<div class="post-metadata">

**Author:** ![Joaquim](https://yyz1.discourse-cdn.com/flex047/user_avatar/forum.generic-mapping-tools.org/joaquim/32/16_2.png) [@Joaquim](https://forum.generic-mapping-tools.org/u/Joaquim)\
**Post date:** [September 19, 2023, 4:43pm UTC](https://forum.generic-mapping-tools.org/t/filled-contour-plot-diverging-asymmetric-data/4268/5 "2023-09-19T16:43:41Z")

</div>

A `contourf` like behavior is obtained with `grdview -Wc ...` (plain GMT CLI. Don´t know about PyGMT).

---

<div class="post-metadata">

**Author:** ![emmaworthington](https://yyz1.discourse-cdn.com/flex047/user_avatar/forum.generic-mapping-tools.org/emmaworthington/32/3092_2.png) [@emmaworthington](https://forum.generic-mapping-tools.org/u/emmaworthington)\
**Post date:** [September 19, 2023, 4:58pm UTC](https://forum.generic-mapping-tools.org/t/filled-contour-plot-diverging-asymmetric-data/4268/6 "2023-09-19T16:58:23Z")

</div>

Thanks - I thought grdview created 3d contours, not 2d?

---

<div class="post-metadata">

**Author:** ![emmaworthington](https://yyz1.discourse-cdn.com/flex047/user_avatar/forum.generic-mapping-tools.org/emmaworthington/32/3092_2.png) [@emmaworthington](https://forum.generic-mapping-tools.org/u/emmaworthington)\
**Post date:** [September 19, 2023, 5:01pm UTC](https://forum.generic-mapping-tools.org/t/filled-contour-plot-diverging-asymmetric-data/4268/7 "2023-09-19T17:01:12Z")

</div>

Okay, thanks. There’s no alias for ‘+h’ in pygmt.makecpt. How do I do that, for example if I want to use the ‘vik’ colormap but with the hinge (I assume that’s what hinge means) at zero?

---

<div class="post-metadata">

**Author:** ![Joaquim](https://yyz1.discourse-cdn.com/flex047/user_avatar/forum.generic-mapping-tools.org/joaquim/32/16_2.png) [@Joaquim](https://forum.generic-mapping-tools.org/u/Joaquim)\
**Post date:** [September 19, 2023, 5:15pm UTC](https://forum.generic-mapping-tools.org/t/filled-contour-plot-diverging-asymmetric-data/4268/8 "2023-09-19T17:15:10Z")

</div>

Default elevation in `grdview` is 90 degrees, so 2D.

This was made with `grdview`.  
[https://www.generic-mapping-tools.org/GMTjl\_doc/examples/contours/01\_contour\_examples/#contourf\_examples](https://www.generic-mapping-tools.org/GMTjl_doc/examples/contours/01_contour_examples/#contourf_examples)

---

<div class="post-metadata">

**Author:** ![emmaworthington](https://yyz1.discourse-cdn.com/flex047/user_avatar/forum.generic-mapping-tools.org/emmaworthington/32/3092_2.png) [@emmaworthington](https://forum.generic-mapping-tools.org/u/emmaworthington)\
**Post date:** [September 19, 2023, 5:27pm UTC](https://forum.generic-mapping-tools.org/t/filled-contour-plot-diverging-asymmetric-data/4268/9 "2023-09-19T17:27:24Z")

</div>

Okay. Grdview looks okay using surf type=‘s’:

```auto
fig.grdview(
    vel_da,
    projection='X6c/-4c',
    region=[0, 210, 0, 4000],
    surftype='s',
    cmap='vik',
    frame=True)

```

 ![pygmt_grdview_iceland_basin](https://canada1.discourse-cdn.com/flex047/uploads/gmt/original/2X/8/85bec454271ef6c51f3d102ac5b6f6348a309d8e.png)

But if I add the contourpen option (which is the alias for Wc), it looks very bad

```auto
fig.grdview(
    vel_da,
    projection='X6c/-4c',
    region=[0, 210, 0, 4000],
    surftype='s',
    cmap='vik',
    contourpen='05p,white',
    frame=True)

```

 ![pygmt_grdview_contourpen_iceland_basin](https://canada1.discourse-cdn.com/flex047/uploads/gmt/original/2X/6/6adc3172e9629c1b71dd67af86e632634600e2e8.png)

Am I missing an option?

thanks

---

<div class="post-metadata">

**Author:** ![Joaquim](https://yyz1.discourse-cdn.com/flex047/user_avatar/forum.generic-mapping-tools.org/joaquim/32/16_2.png) [@Joaquim](https://forum.generic-mapping-tools.org/u/Joaquim)\
**Post date:** [September 19, 2023, 5:52pm UTC](https://forum.generic-mapping-tools.org/t/filled-contour-plot-diverging-asymmetric-data/4268/10 "2023-09-19T17:52:56Z")

</div>

Sorry, can’t help with the PyGMT side.

---

<div class="post-metadata">

**Author:** ![PlanetGus](https://yyz1.discourse-cdn.com/flex047/user_avatar/forum.generic-mapping-tools.org/planetgus/32/303_2.png) [@PlanetGus](https://forum.generic-mapping-tools.org/u/PlanetGus)\
**Post date:** [September 19, 2023, 5:56pm UTC](https://forum.generic-mapping-tools.org/t/filled-contour-plot-diverging-asymmetric-data/4268/11 "2023-09-19T17:56:28Z")

</div>

Can’t help either, I’m sure @yvonnefroehlich will be greater of an help

---

<div class="post-metadata">

**Author:** ![yvonnefroehlich](https://yyz1.discourse-cdn.com/flex047/user_avatar/forum.generic-mapping-tools.org/yvonnefroehlich/32/5064_2.png) [@yvonnefroehlich](https://forum.generic-mapping-tools.org/u/yvonnefroehlich)\
**Post date:** [September 19, 2023, 6:14pm UTC](https://forum.generic-mapping-tools.org/t/filled-contour-plot-diverging-asymmetric-data/4268/12 "2023-09-19T18:14:50Z")

</div>

Hello @emmaworthington,

I feel you need to set up a specific CPT via `pygmt.makecpt`. Two important aspects are:  
(i) Giving a step via the `series` parameter to not have a continuous colormap  
(ii) Using the `truncate` parameter to only show the desired value range

```python
import pygmt as gmt

size = 5

# Make figure
fig = gmt.Figure()

# Set up colormap
# First, make a symmetric colormap
gmt.makecpt(
    cmap="vik",
    series=[-12, 12, 2], # min, max, step
    output="vik_symmetric.cpt", # write to a file
)
# Then cut it to the desired value range
gmt.makecpt(
    cmap="vik_symmetric.cpt",
    truncate=[-12, 6], # min, max
)

fig.basemap(
    region=[-size, size, -size, size],
    projection="X" + str(size*2) + "c",
    frame=True,
)

fig.colorbar(position="JMC", frame="a2")

fig.show()
#fig.savefig(fname="div_asym_cmap.png")

```

_Output figure_:

 ![div_asym_cmap](https://canada1.discourse-cdn.com/flex047/uploads/gmt/original/2X/1/1a9ba0930558536c750044cf9f9f4eef8a3767a6.png)

---

<div class="post-metadata">

**Author:** ![yvonnefroehlich](https://yyz1.discourse-cdn.com/flex047/user_avatar/forum.generic-mapping-tools.org/yvonnefroehlich/32/5064_2.png) [@yvonnefroehlich](https://forum.generic-mapping-tools.org/u/yvonnefroehlich)\
**Post date:** [September 19, 2023, 6:25pm UTC](https://forum.generic-mapping-tools.org/t/filled-contour-plot-diverging-asymmetric-data/4268/13 "2023-09-19T18:25:54Z")

</div>

And here is an example how to use the **+h** modifiier with the `cmap` parameter of `pygmt.makecpt`:

```auto
import pygmt as gmt

size = 5

# Make figure
fig = gmt.Figure()

# Set up colormap
gmt.makecpt(
    # append +h to set the hinge of the colormap to the given value
    cmap="vik+h0",
    series=[-12, 6, 2], # min, max, step
)

fig.basemap(
    region=[-size, size, -size, size],
    projection="X" + str(size*2) + "c",
    frame=True,
)

fig.colorbar(position="JMC", frame="a2")

fig.show()
# fig.savefig(fname="div_asym_cmap_allcolors.png")

```

_Output figure_:

 ![div_asym_cmap02](https://canada1.discourse-cdn.com/flex047/uploads/gmt/original/2X/3/395a0e4645545184576a918d57f8cf956af20ebe.png)

---

<div class="post-metadata">

**Author:** ![emmaworthington](https://yyz1.discourse-cdn.com/flex047/user_avatar/forum.generic-mapping-tools.org/emmaworthington/32/3092_2.png) [@emmaworthington](https://forum.generic-mapping-tools.org/u/emmaworthington)\
**Post date:** [September 19, 2023, 7:41pm UTC](https://forum.generic-mapping-tools.org/t/filled-contour-plot-diverging-asymmetric-data/4268/14 "2023-09-19T19:41:56Z")

</div>

Thank you so much @yvonnefroehlich! I think I was missing the ‘truncate’ option. For completeness and future reference, here is my code:

```auto
# First, make a symmetric colormap
gmt.makecpt(
    cmap="vik",
    series=[-12, 12, 1], # min, max, step
    output="vik_symmetric.cpt", # write to a file
)

# Then cut it to the desired value range
gmt.makecpt(
    cmap="vik_symmetric.cpt",
    truncate=[-12, 5] # min, max
)

fig.grdimage(
    vel_da,
    projection='X6c/-4c',
    region=[0, 330, 1200, 3000],
    cmap="vik_symmetric.cpt",
    frame=['xaf', 'yaf'])

fig.grdcontour(
    vel_da,
    projection='X6c/-4c',
    region=[0, 330, 1200, 3000],
    interval=2,
    pen='1p,white',
    annotation="+0"
    )

fig.colorbar(
    cmap="vik_symmetric.cpt",
    truncate=[-12, 5],
    position='JMR',
    frame='a2'
    )

```

And here is the resulting figure:

 ![pygmt_iceland_basin](https://canada1.discourse-cdn.com/flex047/uploads/gmt/original/2X/e/e8b3bbe30aa6fed2a1bf313e227994cba18403c4.png)

My only other questions is - can the frame thickness be reduced? It’s a bit chunky. I’ve tried the global config option MAP\_FRAME\_WIDTH, but that doesn’t make any difference.

Many thanks again,

Emma

---

<div class="post-metadata">

**Author:** ![yvonnefroehlich](https://yyz1.discourse-cdn.com/flex047/user_avatar/forum.generic-mapping-tools.org/yvonnefroehlich/32/5064_2.png) [@yvonnefroehlich](https://forum.generic-mapping-tools.org/u/yvonnefroehlich)\
**Post date:** [September 19, 2023, 7:57pm UTC](https://forum.generic-mapping-tools.org/t/filled-contour-plot-diverging-asymmetric-data/4268/15 "2023-09-19T19:57:40Z")

</div>

> My only other questions is - can the frame thickness be reduced? It’s a bit chunky. I’ve tried the global config option MAP\_FRAME\_WIDTH, but that doesn’t make any difference.

I think you need to adjust `MAP_FRAME_PEN`, e.g.,:

```auto
pygmt.config(MAP_FRAME_PEN="0.5p")
fig.colorbar(position="JMC", frame="a2")

```

---

<div class="post-metadata">

**Author:** ![emmaworthington](https://yyz1.discourse-cdn.com/flex047/user_avatar/forum.generic-mapping-tools.org/emmaworthington/32/3092_2.png) [@emmaworthington](https://forum.generic-mapping-tools.org/u/emmaworthington)\
**Post date:** [September 19, 2023, 8:25pm UTC](https://forum.generic-mapping-tools.org/t/filled-contour-plot-diverging-asymmetric-data/4268/16 "2023-09-19T20:25:54Z")

</div>

> [@yvonnefroehlich](#):
>
> `MAP_FRAME_PEN="0.5p"`

Perfect! Thank you again.

---

<div class="post-metadata">

**Author:** ![yvonnefroehlich](https://yyz1.discourse-cdn.com/flex047/user_avatar/forum.generic-mapping-tools.org/yvonnefroehlich/32/5064_2.png) [@yvonnefroehlich](https://forum.generic-mapping-tools.org/u/yvonnefroehlich)\
**Post date:** [September 21, 2023, 8:47am UTC](https://forum.generic-mapping-tools.org/t/filled-contour-plot-diverging-asymmetric-data/4268/17 "2023-09-21T08:47:34Z")

</div>

Happy that you have the figure you wanted 🙂!

Just two comments for completeness:

I personally think the first version, e.g., cutting a symmetric colormap to a desired value range, is the better solution / colormap. In this case, the values with the same absolute value (e.g., -2 and 2) have the same “darkness”. When using **+h** to shift the hinge of the colormap this is not the case. This may be misleading when comparing the negative and positive values.

`MAP_FRAME_WIDTH` sets the thickness of the map frame for a fancy `MAP_FRAME_TYPE` (looks like train tracks).
