Reputation: 9
I would like to plot some drilling data with python. As these are drilled at different levels above sea, I would like to align that all three subplots are aligned with the main plot Y-axis. I prepared a sketch how I imagined to look at at the end.
The issue I encounter right now is, that I can not generate different sized subplotboxes which are the same scale and the that they are not aligned with the Y-Axis zero.
If you have any suggestions or alternatives approaches, I really appreciate.
I hope my given Information are enough, as this is my first post here.
As I am just having mediatae experience in python, I have no issues in loading in data or generating plots in the past but this case is different. I asked colleagues and ChatGPT. I tried using matplotlib and GridSpec.
Upvotes: 0
Views: 80
Reputation: 44
Online I found a solution with the insert_axes
function. This however makes it very difficult to align the extra axes of the borehole boxes with the original y axis, and results in boxes all over the place. A simpler (though less elegant) solution would be to just draw rectangles manually on an x and y axis with a function.
Try running this code to see if it works:
import matplotlib.pyplot as plt
import numpy as np
import matplotlib.patches as patches
# Simulated borehole data
depth1 = np.linspace(-50, 300, 100)
values1 = np.sin(np.linspace(0, 3, 100)) * 20 # You would need to alter this to be the proper function for the boreholes.
depth2 = np.linspace(-400, 200, 100)
values2 = np.sin(np.linspace(0, 2, 100)) * 20
depth3 = np.linspace(-250, 250, 100)
values3 = np.sin(np.linspace(0, 4, 100)) * 20
fig, ax = plt.subplots(figsize=(6, 8))
# Set main Y-axis (not sure what the limits should be here)
ax.set_ylim(-500, 400)
ax.set_xlim(-100, 120)
ax.set_yticks(np.arange(-500, 450, 100))
ax.set_xticks([])
ax.set_ylabel("Elevation (m)")
# Function to draw borehole boxes and data with depth labels. Will draw a borehole box based on the information you define above
def draw_borehole(ax, x_center, depth, values, label):
top, bottom = depth[0], depth[-1]
width = 40 # Box width
# Draw borehole box
rect = patches.Rectangle((x_center - width / 2, bottom), width, top - bottom,
linewidth=2, edgecolor='black', facecolor='none')
ax.add_patch(rect)
# Plot borehole data within the box
ax.plot(x_center + values, depth, 'r')
# Add borehole label
ax.text(x_center, top + 10, label, ha='center', fontsize=10)
# Add depth labels (top and bottom). They stick out a bit as of now, but you could fiddle around with the size and location of the borehole boxes to make them fit better
ax.text(x_center + width / 2 + 5, top, f"{top:.0f} m", va='center', fontsize=8, color='black')
ax.text(x_center + width / 2 + 5, bottom, f"{bottom:.0f} m", va='center', fontsize=8, color='black')
# Draw boreholes at different X positions, they have a width of 40 now, but you can alter all that.
draw_borehole(ax, -50, depth1, values1, "Borehole 1")
draw_borehole(ax, 10, depth2, values2, "Borehole 2")
draw_borehole(ax, 70, depth3, values3, "Borehole 3")
plt.show()
This should give you a plot like this: .
Let me know if this works for you.
Upvotes: -1
Reputation: 3896
I would use inset_axes
. Note the use of the transform keyword: setting this to transData
means the inset axes get placed in data coordinates rather than the default axes fraction.
import matplotlib.pyplot as plt
fig, ax = plt.subplots()
ax.set_ylim(-500, 300)
ax.set_xlim(0.4, 4)
# Only show the left-hand y-axis
ax.xaxis.set_visible(False)
ax.spines.right.set_visible(False)
ax.spines.bottom.set_visible(False)
ax.spines.top.set_visible(False)
borehole_tops = [300, 200, 250]
borehole_bottoms = [-50, -400, -250]
for i, (bottom, top) in enumerate(zip(borehole_bottoms, borehole_tops), 1):
ax_ins = ax.inset_axes([i, bottom, 0.6, top - bottom], transform=ax.transData)
ax_ins.set_ylim(bottom, top)
ax_ins.set_title(f'Borehole {i}')
ax_ins.plot([0, 1], [bottom, top], color='red')
plt.show()
Upvotes: 1