-
Notifications
You must be signed in to change notification settings - Fork 1
cpt_layering
sjbrandenberg edited this page Dec 5, 2024
·
17 revisions
A function that uses the agglomerative clustering algorithm by Hudson et al. (2023) to automatically identify spatially contiguous soil layers with similar qc1Ncs and Ic values.
Hudson, K. S., Ulmer, K., Zimmaro, P., Kramer, S. L., Stewart, J. P., and Brandenberg, S. J. (2023). "Unsupervised Machine Learning for Detecting Soil Layer Boundaries from Cone Penetration Test Data." Earthquake Engineering and Structural Dynamics, 52(11). link
| argument | format | description |
|---|---|---|
| qc1Ncs | Numpy array, dtype=float | overburden- and fines-corrected cone tip resistance |
| Ic | Numpy array, dtype=float | soil behavior type index |
| depth | Numpy array, dtype=float | depth to cpt measurement point |
| dGWT | float | depth to groundwater table |
| <num_layers> | integer | number of layers. optional. default = None. |
| <tknob> | float | constant used to define layer thickness parameter in cost function. optional. default = 0.5 |
Note
arguments in <brackets> are optional. If num_layers = None, the optimal number of layers is selected automatically based on a cost function that balances the distortion score with the desired layer thickness specified by the tknob parameter.
| argument | format | description |
|---|---|---|
| ztop | Numpy array, dtype=float | depth to top of each layer |
| zbot | Numpy array, dtype=float | depth to bottom of each layer |
| qc1Ncs_lay | Numpy array, dtype=float | qc1Ncs values for each layer |
| Ic_lay | float | Ic values for each layer |
import numpy as np
import json
import pandas as pd
import requests
import io
import matplotlib.pyplot as plt
import ngl_tools.smt as smt
url = 'https://uclageo.com/coastal_database/conePenetrationTests'
headers = {'User-Agent':'XY', 'Accept':'application/json'}
r = requests.get(url,headers=headers)
cpt_df = pd.read_json(io.StringIO(r.text))
data = cpt_df['data'].values
dGWT = cpt_df['groundwater_measured'].values[0]
cpt_dict = json.loads(cpt_df.data.values[0])
depth = np.asarray(cpt_dict['depth'])
qc = np.asarray(cpt_dict['qc'])*1000
fs = np.asarray(cpt_dict['fs'])*1000
sigmav = 19 * depth
u = (depth - dGWT) * 9.81
u[u<0] = 0
sigmavp = sigmav - u
depth, qt_inv, fs_inv = smt.cpt_inverse_filter(qt=qc, z=depth, fs=fs, sigmav=sigmav, sigmavp=sigmavp)
Ic, Qtn, Fr = smt.get_Ic_Qtn_Fr(qc, fs, sigmav, sigmavp)
Ic_inv, Qtn_inv, Fr_inv = smt.get_Ic_Qtn_Fr(qt_inv, fs_inv, sigmav, sigmavp)
FC = smt.get_FC_from_Ic(Ic_inv, 0.0)
qc1N, qc1Ncs = smt.get_qc1N_qc1Ncs(qc, fs, sigmav, sigmavp, FC)
qc1N_inv, qc1Ncs_inv = smt.get_qc1N_qc1Ncs(qt_inv, fs_inv, sigmav, sigmavp, FC)
ztop, zbot, qc1Ncs_lay, Ic_lay = smt.cpt_layering(qc1Ncs_inv, Ic_inv, depth, dGWT)
fig, ax = plt.subplots(ncols=4, sharey='row')
ax[0].plot(qc, depth)
ax[0].plot(qt_inv, depth)
ax[1].plot(fs, depth)
ax[1].plot(fs_inv, depth)
ax[2].plot(Ic, depth)
ax[2].plot(Ic_inv, depth)
ax[3].plot(qc1Ncs, depth)
ax[3].plot(qc1Ncs_inv, depth)
ax[2].axvspan(1,1.31,alpha=0.3,color='darkorange')
ax[2].axvspan(1.31,2.05,alpha=0.3,color='peru')
ax[2].axvspan(2.05,2.6,alpha=0.3,color='palegreen')
ax[2].axvspan(2.6,2.95,alpha=0.3,color='mediumaquamarine')
ax[2].axvspan(2.95,3.6,alpha=0.3,color='navy')
ax[2].axvspan(3.6,4.0,alpha=0.3,color='saddlebrown')
ax[0].set_ylabel('depth [m]')
ax[0].set_xlabel(r'$q_c$ [kPa]')
ax[1].set_xlabel(r'$f_s$ [kPa]')
ax[2].set_xlabel(r'$I_c$ [-]')
ax[3].set_xlabel(r'$q_{c1Ncs}$ [-]')
for a in ax:
a.grid(True, alpha=0.5)
ax[0].invert_yaxis()
ax[2].hlines(ztop,1,4, color='black', linewidth=0.5)
ax[2].hlines(zbot,1,4, color='black', linewidth=0.5)
ax[3].hlines(ztop,0,400, color='black', linewidth=0.5)
ax[3].hlines(zbot,0,400, color='black', linewidth=0.5)
ax[2].set_xlim(1,4)