From 60d29eea2661adfd91faa26a2d0d19334616f3eb Mon Sep 17 00:00:00 2001 From: Jake Faulkner Date: Mon, 8 Jun 2026 15:42:27 +1200 Subject: [PATCH 01/12] apply basic sanity check to magnitude calculation --- source_modelling/moment.py | 11 ++++++++--- tests/test_moment.py | 11 +++++++++++ 2 files changed, 19 insertions(+), 3 deletions(-) diff --git a/source_modelling/moment.py b/source_modelling/moment.py index d9cc033..4933bd9 100644 --- a/source_modelling/moment.py +++ b/source_modelling/moment.py @@ -163,11 +163,16 @@ def moment_to_magnitude(moment: float, bold_m: bool = True) -> BoldM | Mw: doi:10.1029/JB084iB05p02348. """ + if bold_m: - return BoldM(2 / 3 * np.log10(moment) - EQUATION_7_COEFFICIENT) - + mag = BoldM(2 / 3 * np.log10(moment) - EQUATION_7_COEFFICIENT) else: - return Mw(2 / 3 * np.log10(moment) - EQUATION_4_COEFFICIENT) + mag = Mw(2 / 3 * np.log10(moment) - EQUATION_4_COEFFICIENT) + + if mag > 10.0: + raise ValueError('Magnitude for moment is unreasonably large, did you provide moment in dyne-cm instead of Nm?') + + return mag @typing.overload diff --git a/tests/test_moment.py b/tests/test_moment.py index 3cf9b0c..71dfb3c 100644 --- a/tests/test_moment.py +++ b/tests/test_moment.py @@ -58,6 +58,17 @@ def test_moment_to_magnitude(): assert moment.moment_to_magnitude(8.96e20) == pytest.approx(7.89, abs=5e-02) +def test_moment_to_magnitude_units(): + # Dusky sound earthquake, nominal magnitude ~ 8.0 but GCMT provides the moment in dyne-cm. + # Should throw error because the magnitude is too large to be physically plausible. + mom = 1.44e+28 + with pytest.raises(ValueError, match='Magnitude for moment is unreasonably large'): + moment.moment_to_magnitude() + + + + + # The following test involves some patching to make it feasible to test properly. From 5985c9adbf0a407ff4d64e2c7b69340affda55d1 Mon Sep 17 00:00:00 2001 From: Jake Faulkner Date: Mon, 8 Jun 2026 15:44:07 +1200 Subject: [PATCH 02/12] whitespace --- source_modelling/moment.py | 4 ++-- tests/test_moment.py | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/source_modelling/moment.py b/source_modelling/moment.py index 4933bd9..c0acace 100644 --- a/source_modelling/moment.py +++ b/source_modelling/moment.py @@ -163,7 +163,7 @@ def moment_to_magnitude(moment: float, bold_m: bool = True) -> BoldM | Mw: doi:10.1029/JB084iB05p02348. """ - + if bold_m: mag = BoldM(2 / 3 * np.log10(moment) - EQUATION_7_COEFFICIENT) else: @@ -171,7 +171,7 @@ def moment_to_magnitude(moment: float, bold_m: bool = True) -> BoldM | Mw: if mag > 10.0: raise ValueError('Magnitude for moment is unreasonably large, did you provide moment in dyne-cm instead of Nm?') - + return mag diff --git a/tests/test_moment.py b/tests/test_moment.py index 71dfb3c..6362fb5 100644 --- a/tests/test_moment.py +++ b/tests/test_moment.py @@ -63,10 +63,10 @@ def test_moment_to_magnitude_units(): # Should throw error because the magnitude is too large to be physically plausible. mom = 1.44e+28 with pytest.raises(ValueError, match='Magnitude for moment is unreasonably large'): - moment.moment_to_magnitude() - - - + moment.moment_to_magnitude(mom) + + + # The following test involves some patching to make it feasible to test properly. From 30b81ff6f4efe3d16670b64d87f7bbe26951493f Mon Sep 17 00:00:00 2001 From: Jake Faulkner Date: Mon, 8 Jun 2026 15:47:11 +1200 Subject: [PATCH 03/12] Update tests/test_moment.py Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com> --- tests/test_moment.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/tests/test_moment.py b/tests/test_moment.py index 6362fb5..973cc0c 100644 --- a/tests/test_moment.py +++ b/tests/test_moment.py @@ -67,8 +67,6 @@ def test_moment_to_magnitude_units(): - - # The following test involves some patching to make it feasible to test properly. From 25e4754b1bd23f3fdbcacb2cd31daa284fde52f3 Mon Sep 17 00:00:00 2001 From: Jake Faulkner Date: Mon, 8 Jun 2026 15:48:42 +1200 Subject: [PATCH 04/12] fix: formatting --- source_modelling/gc2_distances.py | 12 +++++++++--- source_modelling/moment.py | 7 ++++--- tests/test_moment.py | 5 ++--- 3 files changed, 15 insertions(+), 9 deletions(-) diff --git a/source_modelling/gc2_distances.py b/source_modelling/gc2_distances.py index b45afdd..51f1766 100644 --- a/source_modelling/gc2_distances.py +++ b/source_modelling/gc2_distances.py @@ -140,7 +140,9 @@ def segment_weights( @njit([float64[:](float64[:], uint64[:]), float64[:](float64[:], int64[:])], cache=True) -def cumulative_reduction(data: np.ndarray, indices: np.ndarray) -> np.ndarray: # pragma: no cover +def cumulative_reduction( + data: np.ndarray, indices: np.ndarray +) -> np.ndarray: # pragma: no cover """Calculate sum between indices. Parameters @@ -173,7 +175,9 @@ def cumulative_reduction(data: np.ndarray, indices: np.ndarray) -> np.ndarray: # [float64[:, :](float64[:, :], uint64[:]), float64[:, :](float64[:, :], int64[:])], cache=True, ) -def diff_reduction(points: np.ndarray, indices: np.ndarray) -> np.ndarray: # pragma: no cover +def diff_reduction( + points: np.ndarray, indices: np.ndarray +) -> np.ndarray: # pragma: no cover """Calculate a diff reduction points between the given indices. Parameters @@ -425,7 +429,9 @@ def multi_trace_rx_ry( b_hat = np.sum(direction_vectors, axis=0) b_hat_norm = np.linalg.norm(b_hat) if np.isclose(b_hat_norm, 0.0): - raise ValueError("Invalid direction vectors calculated: likely indicates degenerate trace or invalid geometry.") + raise ValueError( + "Invalid direction vectors calculated: likely indicates degenerate trace or invalid geometry." + ) b_hat /= b_hat_norm u_shift_origins = calculate_gc2_u_origins( diff --git a/source_modelling/moment.py b/source_modelling/moment.py index c0acace..02410ae 100644 --- a/source_modelling/moment.py +++ b/source_modelling/moment.py @@ -163,14 +163,15 @@ def moment_to_magnitude(moment: float, bold_m: bool = True) -> BoldM | Mw: doi:10.1029/JB084iB05p02348. """ - if bold_m: - mag = BoldM(2 / 3 * np.log10(moment) - EQUATION_7_COEFFICIENT) + mag = BoldM(2 / 3 * np.log10(moment) - EQUATION_7_COEFFICIENT) else: mag = Mw(2 / 3 * np.log10(moment) - EQUATION_4_COEFFICIENT) if mag > 10.0: - raise ValueError('Magnitude for moment is unreasonably large, did you provide moment in dyne-cm instead of Nm?') + raise ValueError( + "Magnitude for moment is unreasonably large, did you provide moment in dyne-cm instead of Nm?" + ) return mag diff --git a/tests/test_moment.py b/tests/test_moment.py index 973cc0c..c8066ea 100644 --- a/tests/test_moment.py +++ b/tests/test_moment.py @@ -61,12 +61,11 @@ def test_moment_to_magnitude(): def test_moment_to_magnitude_units(): # Dusky sound earthquake, nominal magnitude ~ 8.0 but GCMT provides the moment in dyne-cm. # Should throw error because the magnitude is too large to be physically plausible. - mom = 1.44e+28 - with pytest.raises(ValueError, match='Magnitude for moment is unreasonably large'): + mom = 1.44e28 + with pytest.raises(ValueError, match="Magnitude for moment is unreasonably large"): moment.moment_to_magnitude(mom) - # The following test involves some patching to make it feasible to test properly. From 5659ecfc0af8ca1937208acfa930fd049f9927b0 Mon Sep 17 00:00:00 2001 From: Jake Faulkner Date: Mon, 8 Jun 2026 15:50:57 +1200 Subject: [PATCH 05/12] add documentation of value error --- source_modelling/moment.py | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/source_modelling/moment.py b/source_modelling/moment.py index 02410ae..0406ea2 100644 --- a/source_modelling/moment.py +++ b/source_modelling/moment.py @@ -155,6 +155,13 @@ def moment_to_magnitude(moment: float, bold_m: bool = True) -> BoldM | Mw: BoldM | Mw Rupture moment magnitude in the convention specified by `bold_m`. + Raises + ------ + ValueError + If the provided moment corresponds to a physically implausible + magnitude. Likely this is because the user supplied moment is in dyne-cm + instead of Nm. + References ---------- .. [Hanks1979] Hanks, T. C., and H. Kanamori (1979), From fc9e47444fb656ecde7c53d91624fab33cfcccec Mon Sep 17 00:00:00 2001 From: Jake Faulkner Date: Tue, 9 Jun 2026 14:14:46 +1200 Subject: [PATCH 06/12] fix magnitude conversion --- source_modelling/magnitude_scaling.py | 115 +++++++++++--------------- source_modelling/moment.py | 45 +++++++++- tests/test_magnitude_scaling.py | 24 +++--- 3 files changed, 101 insertions(+), 83 deletions(-) diff --git a/source_modelling/magnitude_scaling.py b/source_modelling/magnitude_scaling.py index c123976..dcf75e5 100644 --- a/source_modelling/magnitude_scaling.py +++ b/source_modelling/magnitude_scaling.py @@ -1,15 +1,12 @@ """Magnitude scaling relationships for fault dimensions.""" - -import functools -import typing import warnings from enum import Enum, StrEnum, auto import numpy as np import scipy as sp -BoldM = typing.NewType("BoldM", float) -Mw = typing.NewType("Mw", float) +from source_modelling import moment +from source_modelling.moment import BoldM, Mw class RakeType(Enum): @@ -660,7 +657,7 @@ def contreras_slab_magnitude_to_length_width( def magnitude_to_length_width( scaling_relation: ScalingRelation, - magnitude: BoldM | Mw, + magnitude: BoldM, rake: float | None = None, random: bool = False, ) -> tuple[float, float]: @@ -683,32 +680,23 @@ def magnitude_to_length_width( tuple[float, float] Length and width of the fault estimated by the scaling relation. """ - - if scaling_relation == ScalingRelation.LEONARD2014 and rake is None: - raise ValueError("Rake must be specified for Leonard scaling.") - scaling_relations_map = { - ScalingRelation.LEONARD2014: functools.partial( - leonard_magnitude_to_length_width, - # Rake is checked earlier so ty warning is not required. - rake=rake, # ty: ignore[invalid-argument-type] - random=random, - ), - ScalingRelation.CONTRERAS_INTERFACE2017: functools.partial( - contreras_interface_magnitude_to_length_width, random=random - ), - ScalingRelation.CONTRERAS_SLAB2020: functools.partial( - contreras_slab_magnitude_to_length_width, random=random - ), - } - # The dispatched callable is a union of partials expecting either Mw or BoldM, - # so ty can't see that the scaling_relation key already determines which - # convention `magnitude` should be treated as. - return scaling_relations_map[scaling_relation](magnitude) # ty: ignore[invalid-argument-type] - + match scaling_relation: + case ScalingRelation.LEONARD2014 if rake is not None: + return leonard_magnitude_to_length_width( + moment.boldm_to_mw(magnitude), + rake=rake, + random=random + ) + case ScalingRelation.LEONARD2014: + raise ValueError('Rake must be specified for Leonard scaling.') + case ScalingRelation.CONTRERAS_INTERFACE2017: + return contreras_interface_magnitude_to_length_width(magnitude, random=random) + case ScalingRelation.CONTRERAS_SLAB2020: + return contreras_slab_magnitude_to_length_width(magnitude, random=random) def magnitude_to_area( scaling_relation: ScalingRelation, - magnitude: BoldM | Mw, + magnitude: BoldM, rake: float | None = None, random: bool = False, ) -> float: @@ -736,32 +724,26 @@ def magnitude_to_area( tuple[float, float] Area of the fault estimated by the scaling relation. """ - if scaling_relation == ScalingRelation.LEONARD2014 and rake is None: - raise ValueError("Rake must be specified for Leonard scaling.") - scaling_relations_map = { - ScalingRelation.LEONARD2014: functools.partial( - leonard_magnitude_to_area, - # Rake is checked earlier so ty warning is not required. - rake=rake, # ty: ignore[invalid-argument-type] - random=random, - ), - ScalingRelation.CONTRERAS_INTERFACE2017: functools.partial( - contreras_interface_magnitude_to_area, random=random - ), - ScalingRelation.CONTRERAS_SLAB2020: functools.partial( - strasser_slab_magnitude_to_area, random=random - ), - } - # See note in `magnitude_to_length_width` about why this is ignored. - return scaling_relations_map[scaling_relation](magnitude) # ty: ignore[invalid-argument-type] - + match scaling_relation: + case ScalingRelation.LEONARD2014 if rake is not None: + return leonard_magnitude_to_area( + moment.boldm_to_mw(magnitude), + rake=rake, + random=random + ) + case ScalingRelation.LEONARD2014: + raise ValueError('Rake must be specified for Leonard scaling.') + case ScalingRelation.CONTRERAS_INTERFACE2017: + return contreras_interface_magnitude_to_area(magnitude, random=random) + case ScalingRelation.CONTRERAS_SLAB2020: + return strasser_slab_magnitude_to_area(magnitude, random=random) def area_to_magnitude( scaling_relation: ScalingRelation, area: float, rake: float | None = None, random: bool = False, -) -> BoldM | Mw: +) -> BoldM: """Convert area to magnitude using a scaling relationship. Parameters @@ -778,24 +760,21 @@ def area_to_magnitude( Returns ------- - BoldM | Mw + BoldM Moment magnitude of the fault rupture estimated by the scaling relation. """ - if scaling_relation == ScalingRelation.LEONARD2014 and rake is None: - raise ValueError("Rake must be specified for Leonard scaling.") - - scaling_relations_map = { - ScalingRelation.LEONARD2014: functools.partial( - leonard_area_to_magnitude, - # Rake is checked earlier so ty warning is not required. - rake=rake, # ty: ignore[invalid-argument-type] - random=random, - ), - ScalingRelation.CONTRERAS_INTERFACE2017: functools.partial( - contreras_interface_area_to_magnitude, random=random - ), - ScalingRelation.CONTRERAS_SLAB2020: functools.partial( - strasser_slab_area_to_magnitude, random=random - ), - } - return scaling_relations_map[scaling_relation](area) + + match scaling_relation: + case ScalingRelation.LEONARD2014 if rake is not None: + mag = leonard_area_to_magnitude( + area, + rake=rake, + random=random + ) + return moment.mw_to_boldm(mag) + case ScalingRelation.LEONARD2014: + raise ValueError('Rake must be specified for Leonard scaling.') + case ScalingRelation.CONTRERAS_INTERFACE2017: + return contreras_interface_area_to_magnitude(area, random=random) + case ScalingRelation.CONTRERAS_SLAB2020: + return strasser_slab_area_to_magnitude(area, random=random) diff --git a/source_modelling/moment.py b/source_modelling/moment.py index 0406ea2..6590855 100644 --- a/source_modelling/moment.py +++ b/source_modelling/moment.py @@ -11,15 +11,18 @@ from scipy.sparse import csr_array from source_modelling import rupture_propagation, sources -from source_modelling.magnitude_scaling import BoldM, Mw from source_modelling.sources import Fault, Plane +BoldM = typing.NewType("BoldM", float) +Mw = typing.NewType("Mw", float) + + # Moment magnitude scale coefficients for seismic moment in Nm, from # equations 4 and 7 of Hanks and Kanamori (1979). See the [Hanks1979] reference # in the `moment_to_magnitude` docstring for the full citation. EQUATION_4_COEFFICIENT = 6.0667 # `Mw` convention EQUATION_7_COEFFICIENT = 6.0333 # `BoldM` convention - +BOLDM_TO_MW = EQUATION_7_COEFFICIENT - EQUATION_4_COEFFICIENT def find_connected_faults( faults: dict[str, Fault | Plane], @@ -214,6 +217,44 @@ def magnitude_to_moment(magnitude: BoldM | Mw, bold_m: bool = True) -> float: else: return 10 ** ((magnitude + EQUATION_4_COEFFICIENT) * 3 / 2) +def boldm_to_mw(magnitude: BoldM) -> Mw: + """Convert a BoldM convention magnitude to an Mw convention magnitude. + + Parameters + ---------- + magnitude : BoldM + A magnitude in the BoldM convention. + + Returns + ------- + Mw + A magnitude in the Mw convention. + + See Also + -------- + moment_to_magnitude : Introduces the different magnitude conventions. + """ + return Mw(magnitude + BOLDM_TO_MW) + +def mw_to_boldm(magnitude: Mw) -> BoldM: + """Convert a Mw convention magnitude to an BoldM convention magnitude. + + Parameters + ---------- + magnitude : Mw + A magnitude in the Mw convention. + + Returns + ------- + BoldM + A magnitude in the BoldM convention. + + See Also + -------- + moment_to_magnitude : Introduces the different magnitude conventions. + """ + return BoldM(magnitude - BOLDM_TO_MW) + def moment_over_time_from_moment_rate(moment_rate_df: pd.DataFrame) -> pd.DataFrame: """Integrate a moment rate dataframe into a cumulative moment dataframe. diff --git a/tests/test_magnitude_scaling.py b/tests/test_magnitude_scaling.py index 5c55bbb..f93f6d7 100644 --- a/tests/test_magnitude_scaling.py +++ b/tests/test_magnitude_scaling.py @@ -11,8 +11,8 @@ import scipy as sp from hypothesis import assume, given -from source_modelling import magnitude_scaling -from source_modelling.magnitude_scaling import BoldM, Mw +from source_modelling import magnitude_scaling, moment +from source_modelling.moment import BoldM, Mw MAGNITUDE_TO_AREA = { magnitude_scaling.ScalingRelation.LEONARD2014: magnitude_scaling.leonard_magnitude_to_area, @@ -154,8 +154,9 @@ def test_leonard_area(mw: Mw, rake: float, expected_area: float): """Test the Leonard 2014 area calculation against values from the old implementation in qcore. NOTE: this combined with the inversion test for leonard ensure that the area calculation is compatible with the old implementation as well.""" + boldm = moment.mw_to_boldm(mw) assert magnitude_scaling.magnitude_to_area( - magnitude_scaling.ScalingRelation.LEONARD2014, mw, rake + magnitude_scaling.ScalingRelation.LEONARD2014, boldm, rake ) == pytest.approx(expected_area) @@ -541,12 +542,10 @@ def test_magnitude_to_length_width_calls_correct_function( with patch(f"source_modelling.magnitude_scaling.{func_name}") as mock_func: magnitude_scaling.magnitude_to_length_width( - scaling_relation, magnitude, rake, random + # We are not testing outputs here so we can ignore the invalid magnitude convention. + scaling_relation, magnitude, rake, random # ty: ignore[invalid-argument-type] ) - if rake_required: - mock_func.assert_called_once_with(magnitude, rake=rake, random=random) - else: - mock_func.assert_called_once_with(magnitude, random=random) + mock_func.assert_called_once() @pytest.mark.parametrize( @@ -579,11 +578,10 @@ def test_magnitude_to_area_calls_correct_function( random = True with patch(f"source_modelling.magnitude_scaling.{func_name}") as mock_func: - magnitude_scaling.magnitude_to_area(scaling_relation, magnitude, rake, random) - if rake_required: - mock_func.assert_called_once_with(magnitude, rake=rake, random=random) - else: - mock_func.assert_called_once_with(magnitude, random=random) + # We are not checking outputs here, so it is ok to ignore the invalid magnitude convention + magnitude_scaling.magnitude_to_area(scaling_relation, magnitude, rake, random) # ty: ignore[invalid-argument-type] + + mock_func.assert_called_once() @pytest.mark.parametrize( From 1f42d26949c4818f83395dabca41f895f1afa88b Mon Sep 17 00:00:00 2001 From: Jake Faulkner Date: Tue, 9 Jun 2026 14:31:08 +1200 Subject: [PATCH 07/12] Potential fix for pull request finding Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> --- source_modelling/moment.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/source_modelling/moment.py b/source_modelling/moment.py index 6590855..b6d5eb2 100644 --- a/source_modelling/moment.py +++ b/source_modelling/moment.py @@ -237,8 +237,11 @@ def boldm_to_mw(magnitude: BoldM) -> Mw: return Mw(magnitude + BOLDM_TO_MW) def mw_to_boldm(magnitude: Mw) -> BoldM: - """Convert a Mw convention magnitude to an BoldM convention magnitude. + """Convert a Mw convention magnitude to a BoldM convention magnitude. + Parameters + ---------- + magnitude : Mw Parameters ---------- magnitude : Mw From 5fd77a784bb15468382537abf0d0b69f48e2d06c Mon Sep 17 00:00:00 2001 From: Jake Faulkner Date: Tue, 9 Jun 2026 14:31:46 +1200 Subject: [PATCH 08/12] Potential fix for pull request finding Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> --- source_modelling/magnitude_scaling.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source_modelling/magnitude_scaling.py b/source_modelling/magnitude_scaling.py index dcf75e5..90dae0f 100644 --- a/source_modelling/magnitude_scaling.py +++ b/source_modelling/magnitude_scaling.py @@ -721,7 +721,7 @@ def magnitude_to_area( Returns ------- - tuple[float, float] + float Area of the fault estimated by the scaling relation. """ match scaling_relation: From 949a6405c4745b442ecd15c305ba5580e602af31 Mon Sep 17 00:00:00 2001 From: Jake Faulkner Date: Tue, 9 Jun 2026 14:32:53 +1200 Subject: [PATCH 09/12] fix docs --- source_modelling/magnitude_scaling.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/source_modelling/magnitude_scaling.py b/source_modelling/magnitude_scaling.py index 90dae0f..e1cec47 100644 --- a/source_modelling/magnitude_scaling.py +++ b/source_modelling/magnitude_scaling.py @@ -667,7 +667,7 @@ def magnitude_to_length_width( ---------- scaling_relation : ScalingRelation Scaling relation to use. - magnitude : BoldM | Mw + magnitude : BoldM Moment magnitude of the fault rupture. rake : float, optional Rake of the fault (degrees). Required for Leonard scaling. @@ -706,7 +706,7 @@ def magnitude_to_area( ---------- scaling_relation : ScalingRelation Scaling relation to use. - magnitude : BoldM | Mw + magnitude : BoldM Moment magnitude of the fault rupture. rake : float, optional Rake of the fault (degrees). Required for Leonard scaling. From ad30b15cb6de891bcc2917611ed42d225d0b82d6 Mon Sep 17 00:00:00 2001 From: Jake Faulkner Date: Tue, 9 Jun 2026 14:33:26 +1200 Subject: [PATCH 10/12] ruff formatting --- source_modelling/magnitude_scaling.py | 27 ++++++++++++--------------- source_modelling/moment.py | 3 +++ tests/test_magnitude_scaling.py | 7 +++++-- 3 files changed, 20 insertions(+), 17 deletions(-) diff --git a/source_modelling/magnitude_scaling.py b/source_modelling/magnitude_scaling.py index e1cec47..324009b 100644 --- a/source_modelling/magnitude_scaling.py +++ b/source_modelling/magnitude_scaling.py @@ -1,4 +1,5 @@ """Magnitude scaling relationships for fault dimensions.""" + import warnings from enum import Enum, StrEnum, auto @@ -683,17 +684,18 @@ def magnitude_to_length_width( match scaling_relation: case ScalingRelation.LEONARD2014 if rake is not None: return leonard_magnitude_to_length_width( - moment.boldm_to_mw(magnitude), - rake=rake, - random=random + moment.boldm_to_mw(magnitude), rake=rake, random=random ) case ScalingRelation.LEONARD2014: - raise ValueError('Rake must be specified for Leonard scaling.') + raise ValueError("Rake must be specified for Leonard scaling.") case ScalingRelation.CONTRERAS_INTERFACE2017: - return contreras_interface_magnitude_to_length_width(magnitude, random=random) + return contreras_interface_magnitude_to_length_width( + magnitude, random=random + ) case ScalingRelation.CONTRERAS_SLAB2020: return contreras_slab_magnitude_to_length_width(magnitude, random=random) + def magnitude_to_area( scaling_relation: ScalingRelation, magnitude: BoldM, @@ -727,17 +729,16 @@ def magnitude_to_area( match scaling_relation: case ScalingRelation.LEONARD2014 if rake is not None: return leonard_magnitude_to_area( - moment.boldm_to_mw(magnitude), - rake=rake, - random=random + moment.boldm_to_mw(magnitude), rake=rake, random=random ) case ScalingRelation.LEONARD2014: - raise ValueError('Rake must be specified for Leonard scaling.') + raise ValueError("Rake must be specified for Leonard scaling.") case ScalingRelation.CONTRERAS_INTERFACE2017: return contreras_interface_magnitude_to_area(magnitude, random=random) case ScalingRelation.CONTRERAS_SLAB2020: return strasser_slab_magnitude_to_area(magnitude, random=random) + def area_to_magnitude( scaling_relation: ScalingRelation, area: float, @@ -766,14 +767,10 @@ def area_to_magnitude( match scaling_relation: case ScalingRelation.LEONARD2014 if rake is not None: - mag = leonard_area_to_magnitude( - area, - rake=rake, - random=random - ) + mag = leonard_area_to_magnitude(area, rake=rake, random=random) return moment.mw_to_boldm(mag) case ScalingRelation.LEONARD2014: - raise ValueError('Rake must be specified for Leonard scaling.') + raise ValueError("Rake must be specified for Leonard scaling.") case ScalingRelation.CONTRERAS_INTERFACE2017: return contreras_interface_area_to_magnitude(area, random=random) case ScalingRelation.CONTRERAS_SLAB2020: diff --git a/source_modelling/moment.py b/source_modelling/moment.py index b6d5eb2..f612864 100644 --- a/source_modelling/moment.py +++ b/source_modelling/moment.py @@ -24,6 +24,7 @@ EQUATION_7_COEFFICIENT = 6.0333 # `BoldM` convention BOLDM_TO_MW = EQUATION_7_COEFFICIENT - EQUATION_4_COEFFICIENT + def find_connected_faults( faults: dict[str, Fault | Plane], separation_distance: float = 2.0, @@ -217,6 +218,7 @@ def magnitude_to_moment(magnitude: BoldM | Mw, bold_m: bool = True) -> float: else: return 10 ** ((magnitude + EQUATION_4_COEFFICIENT) * 3 / 2) + def boldm_to_mw(magnitude: BoldM) -> Mw: """Convert a BoldM convention magnitude to an Mw convention magnitude. @@ -236,6 +238,7 @@ def boldm_to_mw(magnitude: BoldM) -> Mw: """ return Mw(magnitude + BOLDM_TO_MW) + def mw_to_boldm(magnitude: Mw) -> BoldM: """Convert a Mw convention magnitude to a BoldM convention magnitude. diff --git a/tests/test_magnitude_scaling.py b/tests/test_magnitude_scaling.py index f93f6d7..298686b 100644 --- a/tests/test_magnitude_scaling.py +++ b/tests/test_magnitude_scaling.py @@ -543,7 +543,10 @@ def test_magnitude_to_length_width_calls_correct_function( with patch(f"source_modelling.magnitude_scaling.{func_name}") as mock_func: magnitude_scaling.magnitude_to_length_width( # We are not testing outputs here so we can ignore the invalid magnitude convention. - scaling_relation, magnitude, rake, random # ty: ignore[invalid-argument-type] + scaling_relation, + magnitude, + rake, + random, # ty: ignore[invalid-argument-type] ) mock_func.assert_called_once() @@ -579,7 +582,7 @@ def test_magnitude_to_area_calls_correct_function( with patch(f"source_modelling.magnitude_scaling.{func_name}") as mock_func: # We are not checking outputs here, so it is ok to ignore the invalid magnitude convention - magnitude_scaling.magnitude_to_area(scaling_relation, magnitude, rake, random) # ty: ignore[invalid-argument-type] + magnitude_scaling.magnitude_to_area(scaling_relation, magnitude, rake, random) # ty: ignore[invalid-argument-type] mock_func.assert_called_once() From f76083e06358be2d80dfd6a1d704e9a576311696 Mon Sep 17 00:00:00 2001 From: Jake Faulkner Date: Tue, 9 Jun 2026 14:34:06 +1200 Subject: [PATCH 11/12] remove parameters --- source_modelling/moment.py | 3 --- 1 file changed, 3 deletions(-) diff --git a/source_modelling/moment.py b/source_modelling/moment.py index f612864..71ebc1b 100644 --- a/source_modelling/moment.py +++ b/source_modelling/moment.py @@ -242,9 +242,6 @@ def boldm_to_mw(magnitude: BoldM) -> Mw: def mw_to_boldm(magnitude: Mw) -> BoldM: """Convert a Mw convention magnitude to a BoldM convention magnitude. - Parameters - ---------- - magnitude : Mw Parameters ---------- magnitude : Mw From 7bc79592c7a3c416f6e7af7fad4444e547f7eedc Mon Sep 17 00:00:00 2001 From: Jake Faulkner Date: Tue, 9 Jun 2026 15:04:25 +1200 Subject: [PATCH 12/12] fix ty ignore --- tests/test_magnitude_scaling.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/test_magnitude_scaling.py b/tests/test_magnitude_scaling.py index 298686b..e701266 100644 --- a/tests/test_magnitude_scaling.py +++ b/tests/test_magnitude_scaling.py @@ -544,9 +544,9 @@ def test_magnitude_to_length_width_calls_correct_function( magnitude_scaling.magnitude_to_length_width( # We are not testing outputs here so we can ignore the invalid magnitude convention. scaling_relation, - magnitude, + magnitude, # ty: ignore[invalid-argument-type] rake, - random, # ty: ignore[invalid-argument-type] + random, ) mock_func.assert_called_once()