Repository navigation
One-layer Vs profiles crash HH parameter and damping calibration with IndexError #119
Description
Found while reviewing #74. Pre-existing on main (b764057); #74 does not change this code.
Problem
A one-layer Vs profile is accepted by Vs_Profile() and by check_Vs_profile_format(), then crashes HH parameter and damping calibration with IndexError.
hh_param_from_profile(), hh_param_from_curves(), and Damping_Calibration.get_damping_curves() always drop the last row as the halfspace (vs_profile[:-1, ...]) and then index that slice with [-1]. With one layer the slice is empty.
- One soil layer and no halfspace (
n_layer == 1) is discarded, so there is nothing left to calibrate. - A single halfspace (
n_layer == 0) has no soil layer. That should be aValueError, not anIndexError.
A two-row profile (one soil layer plus a halfspace) works.
PySeismoSoil/PySeismoSoil/helper_hh_calibration.py
Lines 136 to 146 in b764057
| hlp.check_Vs_profile_format(vs_profile) | |
| h = vs_profile[:-1, 0] | |
| Vs = vs_profile[:-1, 1] # exclude the last layer (i.e., half space) | |
| n_layer = len(Vs) | |
| if Tmax is not None: | |
| hlp.assert_array_length(Tmax, n_layer) | |
| rho = _calc_rho(h, Vs) | |
| Gmax = _calc_Gmax(Vs, rho) | |
| sigma_v0 = _calc_vertical_stress(h, rho) |
PySeismoSoil/PySeismoSoil/helper_hh_calibration.py
Lines 263 to 279 in b764057
| hlp.check_Vs_profile_format(vs_profile) | |
| h = vs_profile[:-1, 0] | |
| Vs = vs_profile[:-1, 1] # exclude the last layer (i.e., half space) | |
| n_layer = len(Vs) | |
| if vs_profile.shape[1] == hlp.NUM_COLUMNS_OF_FULL_VS_PROFILE: | |
| mat = vs_profile[:-1, -1] | |
| rho = vs_profile[:-1, 3] | |
| else: # only 2 columns | |
| mat = np.arange(1, n_layer + 1) | |
| rho = _calc_rho(h, Vs) | |
| if Tmax is not None: | |
| hlp.assert_array_length(Tmax, n_layer) | |
| Gmax = _calc_Gmax(Vs, rho) | |
| sigma_v0 = _calc_vertical_stress(h, rho) |
PySeismoSoil/PySeismoSoil/class_damping_calibration.py
Lines 62 to 73 in b764057
| h = self.vs_profile.vs_profile[:-1, 0] | |
| Vs = self.vs_profile.vs_profile[:-1, 1] | |
| n_layer = len(Vs) | |
| # there can only be 5 or 2 columns | |
| n_columns = self.vs_profile.vs_profile.shape[1] | |
| if n_columns == hlp.NUM_COLUMNS_OF_FULL_VS_PROFILE: | |
| rho = self.vs_profile.vs_profile[:-1, 3] | |
| else: # only 2 columns | |
| rho = hhc._calc_rho(h, Vs) # noqa: SLF001 | |
| sigma_v0 = hhc._calc_vertical_stress(h, rho) # noqa: SLF001 |
PySeismoSoil/PySeismoSoil/helper_site_response.py
Line 1221 in b764057
| if thk[-1] == 0: # if the last layer thickness is unknown |
import numpy as np
from PySeismoSoil.class_Vs_profile import Vs_Profile
from PySeismoSoil.class_damping_calibration import Damping_Calibration
import PySeismoSoil.helper_hh_calibration as hhc
one_layer = np.array([[10.0, 200.0]])
prof = Vs_Profile(one_layer)
print(prof.n_layer) # 1
Damping_Calibration(prof).get_damping_curves()
# IndexError in _calc_vertical_stress: h[-1] on an empty array
# (also a RuntimeWarning: Mean of empty slice)
hhc.hh_param_from_profile(one_layer, verbose=False)
# IndexError in thk2dep: thk[-1] on an empty array
hhc.hh_param_from_curves(one_layer, np.zeros((2, 4)), verbose=False)
# same IndexError in thk2depFix
After the halfspace is removed, if no soil layer remains, raise ValueError naming that case. If the profile is a single soil layer (last thickness > 0), keep that layer instead of dropping it. thk2dep() and _calc_vertical_stress() should also reject an empty thickness array with ValueError rather than indexing [-1].
Activity