codex/past-exam-of-the-year-2-of-the-earth-sciences-geology-course-of-the-university-of-oxford/2024/paper-3-q4-geomorphology.py

past-exam-of-the-year-2-of-the-earth-sciences-geology-course-of-the-university-of-oxford/2024/paper-3-q4-geomorphology.py
"""Original normal-fault geomorphology sketches, not copies of exam figures.
Python 3.14.4 / NumPy 2.3.5 / Matplotlib 3.10.7; opaque basename PNG to CWD.
"""
from pathlib import Path
import math
import numpy as np
import matplotlib
matplotlib.use('Agg')
import matplotlib.pyplot as plt
from matplotlib.patches import Polygon


def main():
    plt.rcParams.update({'font.size':10})
    fig,axes=plt.subplots(2,2,figsize=(10.5,6.9),layout='constrained')
    ax=axes[0,0]
    ax.fill_between([-3,0,.7,3],[-.2,.6,-.6,-.3],-1.8,color='#e7d8bd')
    ax.plot([-3,0,.7,3],[-.2,.6,-.6,-.3],'k',lw=2)
    ax.plot([0,1.5],[.6,-1.8],color='#a42f21',lw=2)
    ax.annotate('',xy=(1,-.9),xytext=(.65,-.35),arrowprops={'arrowstyle':'->','lw':2})
    ax.text(-2.8,.9,'Footwall relief');ax.text(1.2,.15,'Hanging-wall basin')
    ax.text(-2.8,-1.5,'Throw = slip × sin(dip)\nHeave = slip × cos(dip)')
    ax.set(title='Slip rate, dip, segmentation and surface slope',xlim=(-3.2,3.2),ylim=(-1.9,1.5));ax.axis('off')
    ax=axes[0,1];x=np.linspace(-3,3,601)
    for width,label,color in [(.08,'Fresh step','#a42f21'),(.45,'Younger scarp','#175b89'),(1.05,'Older / more diffused','#60723d')]:
        y=-.65*np.array([math.erf(a/width) for a in x]);ax.plot(x,y,color=color,label=label)
    ax.set(title='Weathering and hillslope transport round scarps',xlabel='Across fault (relative distance)',ylabel='Relative height');ax.legend(fontsize=8)
    ax=axes[1,0]
    ax.plot([0,0],[0,4],'#a42f21',lw=2)
    for y in (.5,1.7,2.9):
        ax.add_patch(Polygon([(-1.9,y+.45),(0,y),(0,y+.9)],facecolor='#d4d8c0',edgecolor='0.4'))
        ax.plot([-2.1,-.3,.7,2],[y+.45,y+.45,y+.1,y-.05],color='#175b89',lw=1.4)
        ax.plot([.2,1.1,1.8],[y-.1,y+.15,y+.4],color='#ae854d',lw=1)
    ax.text(-2.2,4.1,'Mountain front (plan view)');ax.text(-2.6,-.25,'Faceted spurs');ax.text(.3,4.1,'Fan deposition')
    ax.text(.3,-.25,'Deflected streams; fan / terrace offsets')
    ax.set(xlim=(-2.7,3.1),ylim=(-.55,4.5),title='Drainage incises the footwall; fans fill the basin');ax.axis('off')
    ax=axes[1,1]
    ax.fill_between([-3,0,.4,3],[.6,.6,-.5,-.5],-1.4,color='#e7d8bd')
    ax.plot([-3,0,.4,3],[.6,.6,-.5,-.5],color='0.4',ls='--')
    ax.fill_between([0,.4,3],[.7,.6,.1],[.6,-.5,-.5],color='#e4bd80')
    ax.plot([-3,0,.4,3],[.6,.7,.6,.1],'k',lw=2)
    ax.text(.6,.8,'Aggradation buries relief');ax.text(-2.9,-1.1,'A subdued scarp can conceal an active fault')
    ax.set(xlim=(-3.2,3.2),ylim=(-1.5,1.4),title='Climate, material strength, sediment supply');ax.axis('off')
    fig.suptitle('Active normal faults: landforms reflect both deformation and surface processes')
    fig.savefig(Path.cwd()/(Path(__file__).stem+'.png'),dpi=120,facecolor='white',transparent=False)
    plt.close(fig)


if __name__ == '__main__': main()