diff --git a/.github/workflows/deptry.yml b/.github/workflows/deptry.yml index 5874abe0..d3e63efa 100644 --- a/.github/workflows/deptry.yml +++ b/.github/workflows/deptry.yml @@ -15,6 +15,6 @@ jobs: # Install deptry - run: uv venv - - run: uv pip install -e ".[test,dev]" + - run: uv sync --all-extras --dev # Run deptry to check that all dependencies are present. - - run: uv run deptry . + - run: uv run deptry . -ddg test,dev,types diff --git a/pyproject.toml b/pyproject.toml index aa466bfa..8553dcd2 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -49,6 +49,7 @@ dependencies = [ [project.optional-dependencies] test = ["pytest"] +types = ["pandas-stubs", "types-geopandas", "types-requests", "scipy-stubs"] dev = ["ruff", "deptry", "ty"] [tool.deptry] diff --git a/workflow/scripts/bb_sim.py b/workflow/scripts/bb_sim.py index 9006a2fd..bcb71200 100644 --- a/workflow/scripts/bb_sim.py +++ b/workflow/scripts/bb_sim.py @@ -181,6 +181,7 @@ def combine_hf_and_lf( vs30_df["pga"] = np.abs(temp_hf_padded).max(axis=1) * G + assert isinstance(vs30_df, pd.DataFrame) hf_amp_val = siteamp_models.cb_amp_multi(vs30_df) hf_amp_fas_vals = siteamp_models.cb2014_to_fas_amplification_factors( hf_amp_val, bb_dt, bb_nt diff --git a/workflow/scripts/generate_velocity_model_parameters.py b/workflow/scripts/generate_velocity_model_parameters.py index 5dcae8f5..c5273dd7 100644 --- a/workflow/scripts/generate_velocity_model_parameters.py +++ b/workflow/scripts/generate_velocity_model_parameters.py @@ -278,11 +278,13 @@ def estimate_rrup( >>> estimate_rrup(7.5, 90, 45, 10) 60.86630588572306 """ - return sp.optimize.minimize_scalar( - lambda rrup: np.abs(pgv_from_rrup(magnitude, rake, dip, rrup) - pgv_target), - bounds=(0, 1000), - method="bounded", - ).x + return float( + sp.optimize.minimize_scalar( + lambda rrup: np.abs(pgv_from_rrup(magnitude, rake, dip, rrup) - pgv_target), + bounds=(0, 1000), + method="bounded", + ).x + ) def find_rrup_bounding_polygon( @@ -317,7 +319,7 @@ def find_rrup_bounding_polygon( rrup = estimate_rrup( magnitude, rake, - np.mean([plane.dip for plane in fault.planes]), + fault.dip, pgv_target, ) logger = log_utils.get_logger(__name__) @@ -465,7 +467,7 @@ def generate_velocity_model_parameters( model_domain = bounding_box.minimum_area_bounding_box_for_polygons_masked( must_include=fault_buffer_polygons, may_include=rrup_bounding_polygons, - mask=utils.get_nz_outline_polygon(), + mask=utils.get_nz_outline_polygon(), # type: ignore ) sim_duration = estimate_simulation_duration( diff --git a/workflow/scripts/import_realisation.py b/workflow/scripts/import_realisation.py index a495af30..0568ab7c 100644 --- a/workflow/scripts/import_realisation.py +++ b/workflow/scripts/import_realisation.py @@ -52,24 +52,24 @@ def convert_realisation( Defaults version to use for the new realisation. """ old_realisation = pd.read_csv(old_realisation_path).iloc[0] - name = old_realisation["name"] + name = old_realisation["name"].item() metadata = RealisationMetadata( name=name, version="1", defaults_version=defaults_version ) planes: list[Plane] = [] - dip = old_realisation["dip"] - dip_dir = old_realisation["dip_dir"] - for i in range(old_realisation["plane_count"]): + dip = old_realisation["dip"].item() + dip_dir = old_realisation["dip_dir"].item() + for i in range(old_realisation["plane_count"].item()): centroid = np.array( [ - old_realisation[f"clat_subfault_{i}"], - old_realisation[f"clon_subfault_{i}"], + old_realisation[f"clat_subfault_{i}"].item(), + old_realisation[f"clon_subfault_{i}"].item(), ] ) - strike = old_realisation[f"strike_subfault_{i}"] - dtop = old_realisation[f"dtop_subfault_{i}"] - length = old_realisation[f"length_subfault_{i}"] - width = old_realisation[f"width_subfault_{i}"] + strike = old_realisation[f"strike_subfault_{i}"].item() + dtop = old_realisation[f"dtop_subfault_{i}"].item() + length = old_realisation[f"length_subfault_{i}"].item() + width = old_realisation[f"width_subfault_{i}"].item() planes.append( Plane.from_centroid_strike_dip( centroid, dip, length, width, dtop=dtop, strike=strike, dip_dir=dip_dir @@ -78,8 +78,8 @@ def convert_realisation( fault = Fault(planes) shypo = old_realisation["shypo"] / fault.length + 1 / 2 dhypo = old_realisation["dhypo"] / fault.width - magnitudes = Magnitudes({name: old_realisation["magnitude"]}) - rakes = Rakes({name: old_realisation["rake"]}) + magnitudes = Magnitudes({name: old_realisation["magnitude"].item()}) + rakes = Rakes({name: old_realisation["rake"].item()}) sources = SourceConfig(source_geometries={name: fault}) rupture_propagation_config = RupturePropagationConfig( rupture_causality_tree={name: None}, # Trivial rupture propagation tree diff --git a/workflow/scripts/merge_ts.py b/workflow/scripts/merge_ts.py index f61beb3f..3e37f82e 100644 --- a/workflow/scripts/merge_ts.py +++ b/workflow/scripts/merge_ts.py @@ -97,23 +97,23 @@ def merge_ts_xyts( # If output doesn't exist when we os.open it, we'll get an error. output.touch() merged_fd = os.open(output, os.O_WRONLY) - + # The following type: ignores can be removed once qcore updates xyts_header: bytes = ( - top_left.x0.tobytes() - + top_left.y0.tobytes() - + top_left.z0.tobytes() - + top_left.t0.tobytes() - + top_left.nx.tobytes() - + top_left.ny.tobytes() - + top_left.nz.tobytes() - + top_left.nt.tobytes() - + top_left.dx.tobytes() - + top_left.dy.tobytes() - + top_left.hh.tobytes() - + top_left.dt.tobytes() - + top_left.mrot.tobytes() - + top_left.mlat.tobytes() - + top_left.mlon.tobytes() + top_left.x0.tobytes() # type: ignore + + top_left.y0.tobytes() # type: ignore + + top_left.z0.tobytes() # type: ignore + + top_left.t0.tobytes() # type: ignore + + top_left.nx.tobytes() # type: ignore + + top_left.ny.tobytes() # type: ignore + + top_left.nz.tobytes() # type: ignore + + top_left.nt.tobytes() # type: ignore + + top_left.dx.tobytes() # type: ignore + + top_left.dy.tobytes() # type: ignore + + top_left.hh.tobytes() # type: ignore + + top_left.dt.tobytes() # type: ignore + + top_left.mrot.tobytes() # type: ignore + + top_left.mlat.tobytes() # type: ignore + + top_left.mlon.tobytes() # type: ignore ) written = os.write(merged_fd, xyts_header) diff --git a/workflow/scripts/nshm2022_to_realisation.py b/workflow/scripts/nshm2022_to_realisation.py index b75c00c1..c1e0e872 100755 --- a/workflow/scripts/nshm2022_to_realisation.py +++ b/workflow/scripts/nshm2022_to_realisation.py @@ -92,7 +92,9 @@ def a_to_mw_leonard(area: float, rake: float) -> float: def default_magnitude_estimation( faults: dict[str, Fault], - components: DisjointSet, + # NOTE: this must be in quotes because the runtime class DisjointSet is + # not generic, just the stub implementation. + components: "DisjointSet[str]", avg_rake: float, ) -> dict[str, float]: """Estimate the magnitudes for a set of faults based on their areas and average rake. diff --git a/workflow/scripts/plan_workflow.py b/workflow/scripts/plan_workflow.py index 8e71bd21..27df5fb5 100644 --- a/workflow/scripts/plan_workflow.py +++ b/workflow/scripts/plan_workflow.py @@ -143,7 +143,7 @@ class Stage: @property def parent(self) -> Self: # numpydoc ignore=RT01 """Stage: the parent stage of this stage.""" - return self.__class__(self.identifier, self.event, None) + return dataclasses.replace(self, sample=None) @property def directory(self) -> PurePath | None: # numpydoc ignore=RT01 diff --git a/workflow/scripts/realisation_to_srf.py b/workflow/scripts/realisation_to_srf.py index 4ba13b18..1dfbd8e2 100644 --- a/workflow/scripts/realisation_to_srf.py +++ b/workflow/scripts/realisation_to_srf.py @@ -54,7 +54,7 @@ from qcore import cli, coordinates from source_modelling import gsf, moment, rupture_propagation, srf -from source_modelling.sources import IsSource, Point +from source_modelling.sources import Fault, IsSource, Point from workflow import log_utils, realisations, utils from workflow.log_utils import log_call from workflow.realisations import ( @@ -327,18 +327,20 @@ def process_fault(fault_name: str) -> None: process_fault(fault_name) # Combine SRF file components + combined_slipt_array = concatenate_slip_values( + ( + fault_srf.slipt1_array + if fault_srf.slipt1_array is not None + else csr_array((len(fault_srf.points), 1)) + ) + for fault_srf in srf_file_map.values() + ) + assert combined_slipt_array is not None combined_srf = srf.SrfFile( version="1.0", header=pd.concat([fault_srf.header for fault_srf in srf_file_map.values()]), points=pd.concat([fault_srf.points for fault_srf in srf_file_map.values()]), - slipt1_array=concatenate_slip_values( - ( - fault_srf.slipt1_array - if fault_srf.slipt1_array is not None - else csr_array((len(fault_srf.points), 1)) - ) - for fault_srf in srf_file_map.values() - ), + slipt1_array=combined_slipt_array, ) # Write the combined SRF file @@ -417,8 +419,11 @@ def generate_fault_srf( resolution = params.srf_config.resolution - nx = sum(round(plane.length / resolution) for plane in fault.planes) - ny = round(fault.planes[0].width / resolution) + if isinstance(fault, Fault): + nx = sum(round(plane.length / resolution) for plane in fault.planes) + else: + nx = round(fault.length / resolution) + ny = round(fault.width / resolution) gsf_file_path = generate_fault_gsf( name, @@ -560,7 +565,10 @@ def generate_point_source_srf( # divide by 1000 to convert depth from meters to kilometers source_depth_km = params.source_config.source_geometries[name].centroid[2] / 1000 - fault_area_km2 = (params.source_config.source_geometries[name].length_m / 1000) ** 2 + fault_area_km2 = ( + params.source_config.source_geometries[name].length + * params.source_config.source_geometries[name].width + ) slip = moment.point_source_slip( moment_newton_metre, fault_area_km2, velocity_model_df, source_depth_km