Home > Net >  Stratigraphic column in matplotlib
Stratigraphic column in matplotlib

Time:10-29

My goal is to create a stratigraphic column (colored stacked rectangles) using matplotlib like the example below. enter image description here

Data is in this format:

depth = [1,2,3,4,5,6,7,8,9,10] #depth (feet) below ground surface    
lithotype = [4,4,4,5,5,5,6,6,6,2] #lithology type. 4 = clay, 6 = sand, 2 = silt

I tried matplotlib.patches.Rectangle but it's cumbersome. Wondering if someone has another suggestion.

CodePudding user response:

Imho using Rectangle is not so difficult nor cumbersome.

enter image description here

from numpy import ones
from matplotlib.pyplot import show, subplots
from matplotlib.cm import get_cmap
from matplotlib.patches import Rectangle as r

# a simplification is to use, for the lithology types, a qualitative colormap
# here I use Paired, but other qualitative colormaps are displayed in
# https://matplotlib.org/stable/tutorials/colors/colormaps.html#qualitative

qcm = get_cmap('Paired')

# the data, augmented with type descriptions
# note that depths start from zero
depth = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10] # depth (feet) below ground surface    
lithotype = [4, 4, 4, 5, 5, 5, 6, 1, 6, 2] # lithology type.
types = {1:'swiss cheese', 2:'silt', 4:'clay', 5:'silty sand', 6:'sand'}

# prepare the figure
fig, ax = subplots(figsize = (4, 8))
w = 2 # a conventional width, used to size the x-axis and the rectangles
ax.set(xlim=(0,2), xticks=[]) # size the x-axis, no x ticks
ax.set_ylim(ymin=0, ymax=depth[-1])
ax.invert_yaxis()
fig.suptitle('Soil Behaviour Type')
fig.subplots_adjust(right=0.5)

# plot a series of dots, that eventually will be covered by the Rectangle\s
# so that we can draw a legend
for lt in set(lithotype):
    ax.scatter(lt, depth[1], color=qcm(lt), label=types[lt], zorder=0)
fig.legend(loc='center right')
ax.plot((1,1), (0,depth[-1]), lw=0)

# do the rectangles
for d0, d1, lt in zip(depth, depth[1:], lithotype):
    ax.add_patch(
        r( (0, d0), # coordinates of upper left corner
          2, d1-d0, # conventional width on x, thickness of the layer
          facecolor=qcm(lt), edgecolor='k'))

# That's all, folks!
show()

As you can see, placing the rectangles is not complicated, what is indeed cumbersome is to properly prepare the Figure and the Axes.

I know that I omitted part of the qualifying details from my solution, but I hope these omissions won't stop you from profiting from my answer.

CodePudding user response:

I made a package called The result of plotting our striplog

Admittedly the plotting is a little limited, but it's just matplotlib so you can always add more code. To be honest, if I were to build this tool today, I think I'd probably leave the plotting out entirely; it's often easier for the user to do their own thing.

Why go to all this trouble? Fair question. striplog lets you merge zones, make thickness or lithology histograms, make queries ("show me sandstone beds thicker than 2 m"), make 'flags', export LAS or CSV, and even do Markov chain sequence analysis. But even if it's not what you're looking for, maybe you can recycle some of the plotting code! Good luck.

  • Related