Subplotting

I know I’m doing something silly here but I just can’t seem to figure it out, possibly it’s the end of the day or I just an idiot. Probably a bit of column ‘a’ and ‘b’. Nonetheless, any insight would be most appreciated.

I’d like to plot a geographic vertical cross-section gridded contour dataset above it’s horizontally sliced ‘surface’ map. My attempts are nearly there but the horizontal map is not filling out it’s bounding box – see figure below. Can anyone see where I’m going wrong?

Here is my figure:

I’m generating using this code:

     fig = pygmt.Figure()
        pygmt.makecpt(cmap="imola", reverse=True, series=[minval,maxval,stpval])
        with fig.subplot(nrows=2, ncols=1, figsize=("20c", "20c"), margins=["0.1c","0.2c"] ,
                         frame="WSne", title="{} at {}".format(tit_str_left,tit_str_right) ):
            with fig.set_panel(panel=0):
                fig.grdimage( grid=den_tm , frame=["Wsne","yaf+lDepth"] , projection="X?", region=reg_den , cmap=True , transparency=20 )
            fig.colorbar( position="JMR+o0.5c/0c+w20c" , frame=["x+ldensity","y+lkg/m^3"] )
            with fig.set_panel(panel=1):
                den_h = self.slice_dataset_horizontally(ds=ds.dens.sel(zc=0,method='nearest'),ds_name=ds_name)
                den_t = self.slice_dataset_temporally( ds=den_h , ds_name=ds_name , ext=[d] , by_index=False )
                fig.basemap(region=map_extent,frame="WSne")
                fig.grdimage(grid=den_t, projection="M?",cmap=True,transparency=20)
                fig.coast(shorelines=".5p",land="#666666")
            fig.image(self.FUNIT_BADGE,position="JTL+w3c")
            fig.logo(position='JBL')

Partially answering my own question here. Still have the horizontal data oddly ballooning out the domain and now getting the map bounds the same width as the vertical cross-section.

Any feedback is welcome.

fig = pygmt.Figure()
pygmt.makecpt(cmap=“imola”, reverse=True, series=[minmap,maxmap,stpmap])
with fig.subplot(nrows=2, ncols=1, figsize=(“20c”, “20c”), sharex=True , margins=[“0.1c”,“0.1c”] ,
frame=“WSne”, title="{} at {}".format(tit_str_left,tit_str_right) ):
fig.grdimage( grid=den_tm , frame=[“Wsne”,“yaf+lDepth”] , projection=“X?”, region=reg_den , cmap=True , transparency=20 , panel=[0,0] )
fig.colorbar( position=“JMR+o0.5c/0c+w9c” , frame=[“x+ldensity”,“y+lkg/m^3”] )
fig.basemap(region=map_extent,projection=“M?”,frame=‘WSne’,panel=[1,0])
fig.grdimage(grid=den_t,cmap=True,transparency=20,panel=[1,0])
fig.coast(shorelines=".5p",land="#666666",panel=[1,0])

specify manually:

  1. projection with the same horizontal size for both subplots (instead of automatic size selection)
    projection="X6c" for cartesian depth/density plot
    projection="M6c" for Mercator lat/lon map
    (6c means 6 cm)
  2. region with the same horizontal range
    region=[148, 152, -500, 0] for cartesian depth/density plot (instead of region=reg_den)
    region=[148, 152, -42, -36] for Mercator lat/lon map (instead of region=map_extent)

PS 6 cm can be increased to 12 or larger, just noticed your figsize=("20c", "20c")

Hi Mikhail, thanks for your suggestion. In fact, that did not have the desired result, as it ended up overlapping the vertical cross-section and the map. So, for now, I’m going to leave the following as the a ‘good enough’ result, as the figure is intended for situational awareness tool and not a product for publishing. Figure and code below. Also, FWIIW, I’m pretty sure they vertical cross-section and map x-axis are not lining because of the underlying datasets which I’m slicing differently for each subplot needs to be brought under the same slicing routine. I think this is resulting in the different sizes.

            fig           = pygmt.Figure()
        pygmt.makecpt(cmap="imola", reverse=True, series=[minmap,maxmap,stpmap])
        with fig.subplot(nrows=2, ncols=1, figsize=("20c","20c"), sharex=True, margins=["0.1c","0.1c"],#, sharex=True,
                         frame="WSne", title="{} at {}".format(tit_str_left,tit_str_right) ):
            fig.grdimage( grid=den_tm, frame=["Wsne","yaf+lDepth"], projection="X?", region=reg_den, cmap=True, transparency=20, panel=[0,0] )
            fig.colorbar( position="JMR+o0.5c/0c+w9c", frame=["x+ldensity","y+lkg/m^3"] )
            fig.basemap( region=map_extent, projection="M?", frame='WSne', panel=[1,0] )
            fig.grdcontour( BATH.elevation , pen=".5p,black" , interval=100 , annotation="-" , panel=[1,0] )
            fig.grdimage( grid=den_t, cmap=True, transparency=20, panel=[1,0] )
            fig.coast( shorelines=".5p", land="#666666", panel=[1,0] )
            fig.text(text="Cross-Section", x=np.median(den_tm.lon.values), y=xsec+.1, font="12p,Helvetica,black")#, fill="white")
            if by_lat:
                fig.plot( x=[map_extent[0],map_extent[1]], y=[xsec,xsec], pen="1p,black")
            elif by_lon:
                fig.plot( x=[xsec,xsec], y=[map_extent[2],map_extent[3]], pen="1p,black")

vertical/horizontal size ratio for Mercator map is defined by the projection. Figure height is greater than width for the specified lon/lat range on the 2nd subplot.

vertical/horizontal size ratio for depth/longitude (I assumed X is longitude, Y is depth) subplot is not fixed. Height can be specified manually for Cartesian data, like X6c/2c to get height equal to 1/3 of width (your last example shows height ~1/2 of width)

and the 3rd factor, the total figure size, those figsize=("20c", "20c")

I was thinking about aligning horizontal subplot dimentions and ranges. I see it as a matter of choosing optimal sizes, height of the whole figure and height of the salinity lon/depth subplot). If the size choice is not optimal, the results may look funny (subplots overlapping or sitting too far away). Such subplot scaling and placement likely can be achieved manually, by trial/error.