diff --git a/tests/test_realisation.py b/tests/test_realisation.py index 287f4559..204e8191 100644 --- a/tests/test_realisation.py +++ b/tests/test_realisation.py @@ -567,6 +567,35 @@ def test_seeds() -> None: ) +def test_seeds_from_random(tmp_path: Path) -> None: + """Test read from realisation or random""" + realisation_file = tmp_path / "test_realisation.json" + # Create a file with unrelated content + initial_content = {"other_key": "some_value"} + with open(realisation_file, "w") as f: + json.dump(initial_content, f) + + seeds = realisations.Seeds.read_from_realisation_or_random(realisation_file) + assert all( + 0 <= seed <= 2 ** (struct.Struct("i").size * 8 - 1) - 1 + for seed in seeds.to_dict().values() + ) + + realisation_file = tmp_path / "test_realisation_1.json" + # Create a file with unrelated content + seeds = realisations.Seeds( + nshm_to_realisation_seed=0, + rupture_propagation_seed=0, + genslip_seed=0, + srfgen_seed=0, + hf_seed=0, + ) + seeds.write_to_realisation(realisation_file) + + seeds_read = realisations.Seeds.read_from_realisation_or_random(realisation_file) + assert seeds == seeds_read + + def test_velocity_model_1d(tmp_path: Path) -> None: velocity_model_1d = realisations.VelocityModel1D( model=pd.DataFrame( diff --git a/workflow/realisations.py b/workflow/realisations.py index 59fe25dd..73ec3ee0 100644 --- a/workflow/realisations.py +++ b/workflow/realisations.py @@ -242,8 +242,8 @@ class Seeds(RealisationConfiguration): """HF seed.""" @classmethod - def read_from_realisation_or_defaults( - cls, realisation_ffp: Path, *args: list[Any] + def read_from_realisation_or_random( + cls, realisation_ffp: Path ) -> Self: # *args is to maintain compat with superclass (remove this and see the error in mypy). """Read seeds configuration from a realisation file or generate random seeds if not present. @@ -256,8 +256,6 @@ def read_from_realisation_or_defaults( ---------- realisation_ffp : Path The realisation filepath to read from. - *args : list - Ignored arguments. Returns ------- diff --git a/workflow/scripts/bb_sim.py b/workflow/scripts/bb_sim.py index bcb71200..93da85da 100644 --- a/workflow/scripts/bb_sim.py +++ b/workflow/scripts/bb_sim.py @@ -154,9 +154,11 @@ def combine_hf_and_lf( ) hf = hf.sel(station=common_stations) lf = lf.sel(station=common_stations) - vs30_df = pd.read_csv( - station_vs30_ffp, sep=r"\s+", header=None, names=["station", "vsite"] + station_vs30_ffp, + sep=r"\s+", + header=None, + names=["station", "vsite"], # type: ignore[invalid-argument-type] ).set_index("station") vs30_df["vsite"] = vs30_df["vsite"].astype(np.float32) vs30_df = vs30_df.loc[common_stations] @@ -218,8 +220,6 @@ def combine_hf_and_lf( engine="h5netcdf", encoding={ "waveform": { - "compression": "zlib", # Use zlib compression. - "complevel": 5, # Compress to level 5 (of 9). "fletcher32": True, # Add Fletcher-32 checksums for long-term storage. } }, diff --git a/workflow/scripts/check_srf.py b/workflow/scripts/check_srf.py index 240d06bf..9be27573 100644 --- a/workflow/scripts/check_srf.py +++ b/workflow/scripts/check_srf.py @@ -83,7 +83,11 @@ def check_srf( ) mu = velocity_model["mu"].iloc[indices].values srf_magnitude = mag_scaling.mom2mag( - (srf_file.points["area"].values * srf_file.points["slip"].values * mu).sum() + ( + np.array(srf_file.points["area"].values) + * np.array(srf_file.points["slip"].values) + * mu + ).sum() ) logger = log_utils.get_logger("__name__") diff --git a/workflow/scripts/gcmt_to_realisation.py b/workflow/scripts/gcmt_to_realisation.py index 42fca7d2..d250e75a 100644 --- a/workflow/scripts/gcmt_to_realisation.py +++ b/workflow/scripts/gcmt_to_realisation.py @@ -161,17 +161,24 @@ def gcmt_to_realisation( ].set_index("PublicID") if gcmt_event_id in gcmt_solutions.index: - solution = gcmt_solutions.loc[gcmt_event_id] - latitude = solution["Latitude"] - longitude = solution["Longitude"] - centroid_depth = solution["CD"] - magnitude = solution["Mw"] - nodal_plane_1 = NodalPlane( - solution["strike1"], solution["dip1"], solution["rake1"] - ) - nodal_plane_2 = NodalPlane( - solution["strike2"], solution["dip2"], solution["rake2"] - ) + latitude = gcmt_solutions.at[gcmt_event_id, "Latitude"] + longitude = gcmt_solutions.at[gcmt_event_id, "Longitude"] + centroid_depth = gcmt_solutions.at[gcmt_event_id, "CD"] + magnitude = gcmt_solutions.at[gcmt_event_id, "Mw"] + strike1 = gcmt_solutions.at[gcmt_event_id, "strike1"] + dip1 = gcmt_solutions.at[gcmt_event_id, "dip1"] + rake1 = gcmt_solutions.at[gcmt_event_id, "rake1"] + strike2 = gcmt_solutions.at[gcmt_event_id, "strike2"] + dip2 = gcmt_solutions.at[gcmt_event_id, "dip2"] + rake2 = gcmt_solutions.at[gcmt_event_id, "rake2"] + assert isinstance(strike1, float | int) + assert isinstance(dip1, float | int) + assert isinstance(rake1, float | int) + assert isinstance(strike2, float | int) + assert isinstance(dip2, float | int) + assert isinstance(rake2, float | int) + nodal_plane_1 = NodalPlane(strike1, dip1, rake1) + nodal_plane_2 = NodalPlane(strike2, rake2, dip2) elif gcmt_event_id in automated_gcmt_solutions: solution = automated_gcmt_solutions[gcmt_event_id] latitude = solution["location"]["latitude"] @@ -203,6 +210,7 @@ def gcmt_to_realisation( # Calculate dip direction from strike (strike + 90 degrees for right-hand rule) dip_direction = (selected_nodal_plane.strike + 90) % 360 + assert isinstance(magnitude, float) length, width = magnitude_scaling.magnitude_to_length_width( scaling_relation, magnitude, rake ) @@ -217,6 +225,7 @@ def gcmt_to_realisation( length_m = length_km * 1000 # Convert km to meters width_m = width_km * 1000 # Convert km to meters + assert isinstance(centroid_depth, float) source_geometry = sources.Point.from_lat_lon_depth( point_coordinates=np.array( [latitude, longitude, centroid_depth * 1000] diff --git a/workflow/scripts/generate_rupture_propagation.py b/workflow/scripts/generate_rupture_propagation.py index 6e9c069f..4cba7ff7 100644 --- a/workflow/scripts/generate_rupture_propagation.py +++ b/workflow/scripts/generate_rupture_propagation.py @@ -81,7 +81,7 @@ def generate_rupture_propagation( strategy : RuptureStrategy The rupture propagation strategy to use. Default is `RuptureStrategy.RANDOM`. """ - seeds = realisations.Seeds.read_from_realisation_or_defaults(realisation_ffp) + seeds = realisations.Seeds.read_from_realisation_or_random(realisation_ffp) source_config = realisations.SourceConfig.read_from_realisation(realisation_ffp) faults = source_config.source_geometries diff --git a/workflow/scripts/generate_station_coordinates.py b/workflow/scripts/generate_station_coordinates.py index f366bf21..19ca6891 100644 --- a/workflow/scripts/generate_station_coordinates.py +++ b/workflow/scripts/generate_station_coordinates.py @@ -75,7 +75,10 @@ def generate_fd_files( # retrieve in station names, latitudes and longitudes stations = pd.read_csv( - stat_file, delimiter=r"\s+", comment="#", names=["lon", "lat", "name"] + stat_file, + delimiter=r"\s+", + comment="#", + names=["lon", "lat", "name"], # type: ignore[invalid-argument-type] ) x, y = proj(lat=stations["lat"].values, lon=stations["lon"].values).T diff --git a/workflow/scripts/generate_velocity_model_parameters.py b/workflow/scripts/generate_velocity_model_parameters.py index c5273dd7..6a5417f1 100644 --- a/workflow/scripts/generate_velocity_model_parameters.py +++ b/workflow/scripts/generate_velocity_model_parameters.py @@ -387,10 +387,12 @@ def pgv_target( for magnitude in magnitudes.magnitudes.values() ) ) - return np.interp( - total_magnitude, - velocity_model_parameters.pgv_interpolants[:, 0], - velocity_model_parameters.pgv_interpolants[:, 1], + return float( + np.interp( + total_magnitude, + velocity_model_parameters.pgv_interpolants[:, 0], + velocity_model_parameters.pgv_interpolants[:, 1], + ) ) diff --git a/workflow/scripts/hf_sim.py b/workflow/scripts/hf_sim.py index ad09641c..201831cb 100644 --- a/workflow/scripts/hf_sim.py +++ b/workflow/scripts/hf_sim.py @@ -279,7 +279,7 @@ def run_hf( None The function does not return any value. It writes the HF output directly to `out_file`. """ - seeds = Seeds.read_from_realisation_or_defaults(realisation_ffp) + seeds = Seeds.read_from_realisation_or_random(realisation_ffp) domain_parameters = DomainParameters.read_from_realisation(realisation_ffp) metadata = RealisationMetadata.read_from_realisation(realisation_ffp) @@ -294,7 +294,7 @@ def run_hf( station_file, delimiter=r"\s+", header=None, - names=["longitude", "latitude", "name"], + names=["longitude", "latitude", "name"], # type: ignore[invalid-argument-type] ).set_index("name") station_hashes = np.array( [stable_hash(name) for name in stations.index], dtype=np.int32 @@ -306,7 +306,9 @@ def run_hf( stations["seed"] = np.int32(seeds.hf_seed) ^ station_hashes velocity_model_path = work_directory / "velocity_model" velocity_model.write_velocity_model(velocity_model_path) - nt = int(np.float32(domain_parameters.duration) / np.float32(hf_config.dt)) # Match Fortran's single-precision for consistent nt calculation + nt = int( + np.float32(domain_parameters.duration) / np.float32(hf_config.dt) + ) # Match Fortran's single-precision for consistent nt calculation waveform = np.empty((3, len(stations), nt), dtype=np.float32) hf_input_template = build_hf_input( diff --git a/workflow/scripts/nshm2022_to_realisation.py b/workflow/scripts/nshm2022_to_realisation.py index c1e0e872..ab9d5339 100755 --- a/workflow/scripts/nshm2022_to_realisation.py +++ b/workflow/scripts/nshm2022_to_realisation.py @@ -329,7 +329,7 @@ def generate_realisation( ) raise typer.Exit(code=1) faults_info = db.get_rupture_fault_info(rupture_id) - seeds = Seeds.read_from_realisation_or_defaults(realisation_ffp) + seeds = Seeds.read_from_realisation_or_random(realisation_ffp) np.random.seed(seed=seeds.nshm_to_realisation_seed) source_config = SourceConfig(faults) diff --git a/workflow/scripts/realisation_to_srf.py b/workflow/scripts/realisation_to_srf.py index 1dfbd8e2..3150ae1b 100644 --- a/workflow/scripts/realisation_to_srf.py +++ b/workflow/scripts/realisation_to_srf.py @@ -666,7 +666,7 @@ def generate_srf( realisation_ffp, metadata.defaults_version ) - seeds = Seeds.read_from_realisation_or_defaults(realisation_ffp) + seeds = Seeds.read_from_realisation_or_random(realisation_ffp) rupture_propagation = RupturePropagationConfig.read_from_realisation( realisation_ffp )