source_modelling.scripts.plot_mw_contributions

  1from pathlib import Path
  2from typing import Annotated
  3
  4import numpy as np
  5import typer
  6from matplotlib import pyplot as plt
  7
  8from source_modelling import moment, rupture_propagation, srf
  9from workflow.realisations import (
 10    RealisationMetadata,
 11    RupturePropagationConfig,
 12    SourceConfig,
 13)
 14
 15app = typer.Typer()
 16
 17
 18@app.command(help="Plot segment magnitudes against the Leonard scaling relation.")
 19def plot_mw_contributions(
 20    srf_ffp: Annotated[
 21        Path, typer.Argument(help="Path to SRF file", exists=True, dir_okay=False)
 22    ],
 23    realisation_ffp: Annotated[
 24        Path,
 25        typer.Argument(help="Realisation filepath", dir_okay=False, exists=True),
 26    ],
 27    output_ffp: Annotated[
 28        Path, typer.Argument(help="Output plot path.", writable=True, dir_okay=False)
 29    ],
 30    dpi: Annotated[
 31        float, typer.Option(help="Output plot DPI (higher is better).")
 32    ] = 300,
 33) -> None:
 34    """Plot segment magnitudes against the Leonard scaling relation.
 35
 36    Parameters
 37    ----------
 38    srf_ffp : Path
 39        Path to SRF file.
 40    realisation_ffp : Path
 41        Realisation filepath.
 42    output_ffp : Path
 43        Output plot path.
 44    dpi : float, default 300
 45        Output plot DPI (higher is better).
 46    """
 47    source_config = SourceConfig.read_from_realisation(realisation_ffp)
 48    rupture_propogation_config = RupturePropagationConfig.read_from_realisation(
 49        realisation_ffp
 50    )
 51    realisation_metadata = RealisationMetadata.read_from_realisation(realisation_ffp)
 52    total_area = sum(fault.area() for fault in source_config.source_geometries.values())
 53    smallest_area = min(
 54        fault.area() for fault in source_config.source_geometries.values()
 55    )
 56    area = np.linspace(smallest_area, total_area)
 57    fig, ax = plt.subplots()
 58    # Mw = log(area) + 3.995 is the Leonard2014 magnitude scaling relation
 59    # for average rake.
 60    ax.plot(
 61        area, np.log10(area) + 3.995, label="Leonard 2014 Interplate (Average Rake)"
 62    )
 63
 64    srf_data = srf.read_srf(srf_ffp)
 65    total_magnitude = moment.moment_to_magnitude(
 66        moment.MU * (srf_data.points["area"] * srf_data.points["slip"] / (100**3)).sum()
 67    )
 68    ax.scatter(total_area, total_magnitude, label="Total Magnitude")
 69
 70    segment_counter = 0
 71    point_counter = 0
 72    for fault_name in rupture_propagation.tree_nodes_in_order(
 73        rupture_propogation_config.rupture_causality_tree
 74    ):
 75        plane_count = len(source_config.source_geometries[fault_name].planes)
 76        segments = srf_data.header.iloc[segment_counter : segment_counter + plane_count]
 77
 78        num_points = (segments["nstk"] * segments["ndip"]).sum()
 79        individual_area = source_config.source_geometries[fault_name].area()
 80
 81        # get all points associated with all segments in the current fault
 82        segment_points = srf_data.points.iloc[
 83            point_counter : point_counter + num_points
 84        ]
 85        individual_magnitude = moment.moment_to_magnitude(
 86            (
 87                moment.MU * segment_points["area"] * segment_points["slip"] / (100**3)
 88            ).sum()
 89        )
 90        ax.scatter(individual_area, individual_magnitude, label=fault_name)
 91
 92        # advance segment counter and point counter to skip all points from the current point
 93        segment_counter += plane_count
 94        point_counter += num_points
 95
 96    ax.set_xlabel("Area (m^2)")
 97    ax.set_ylabel("Mw")
 98    ax.set_xscale("log")
 99    ax.legend()
100    ax.set_title(f"Log Area vs Magnitude ({realisation_metadata.name})")
101    fig.savefig(output_ffp, dpi=dpi)
102
103
104if __name__ == "__main__":
105    app()
app = <typer.main.Typer object>
@app.command(help='Plot segment magnitudes against the Leonard scaling relation.')
def plot_mw_contributions( srf_ffp: Annotated[pathlib.Path, <typer.models.ArgumentInfo object>], realisation_ffp: Annotated[pathlib.Path, <typer.models.ArgumentInfo object>], output_ffp: Annotated[pathlib.Path, <typer.models.ArgumentInfo object>], dpi: Annotated[float, <typer.models.OptionInfo object>] = 300) -> None:
 19@app.command(help="Plot segment magnitudes against the Leonard scaling relation.")
 20def plot_mw_contributions(
 21    srf_ffp: Annotated[
 22        Path, typer.Argument(help="Path to SRF file", exists=True, dir_okay=False)
 23    ],
 24    realisation_ffp: Annotated[
 25        Path,
 26        typer.Argument(help="Realisation filepath", dir_okay=False, exists=True),
 27    ],
 28    output_ffp: Annotated[
 29        Path, typer.Argument(help="Output plot path.", writable=True, dir_okay=False)
 30    ],
 31    dpi: Annotated[
 32        float, typer.Option(help="Output plot DPI (higher is better).")
 33    ] = 300,
 34) -> None:
 35    """Plot segment magnitudes against the Leonard scaling relation.
 36
 37    Parameters
 38    ----------
 39    srf_ffp : Path
 40        Path to SRF file.
 41    realisation_ffp : Path
 42        Realisation filepath.
 43    output_ffp : Path
 44        Output plot path.
 45    dpi : float, default 300
 46        Output plot DPI (higher is better).
 47    """
 48    source_config = SourceConfig.read_from_realisation(realisation_ffp)
 49    rupture_propogation_config = RupturePropagationConfig.read_from_realisation(
 50        realisation_ffp
 51    )
 52    realisation_metadata = RealisationMetadata.read_from_realisation(realisation_ffp)
 53    total_area = sum(fault.area() for fault in source_config.source_geometries.values())
 54    smallest_area = min(
 55        fault.area() for fault in source_config.source_geometries.values()
 56    )
 57    area = np.linspace(smallest_area, total_area)
 58    fig, ax = plt.subplots()
 59    # Mw = log(area) + 3.995 is the Leonard2014 magnitude scaling relation
 60    # for average rake.
 61    ax.plot(
 62        area, np.log10(area) + 3.995, label="Leonard 2014 Interplate (Average Rake)"
 63    )
 64
 65    srf_data = srf.read_srf(srf_ffp)
 66    total_magnitude = moment.moment_to_magnitude(
 67        moment.MU * (srf_data.points["area"] * srf_data.points["slip"] / (100**3)).sum()
 68    )
 69    ax.scatter(total_area, total_magnitude, label="Total Magnitude")
 70
 71    segment_counter = 0
 72    point_counter = 0
 73    for fault_name in rupture_propagation.tree_nodes_in_order(
 74        rupture_propogation_config.rupture_causality_tree
 75    ):
 76        plane_count = len(source_config.source_geometries[fault_name].planes)
 77        segments = srf_data.header.iloc[segment_counter : segment_counter + plane_count]
 78
 79        num_points = (segments["nstk"] * segments["ndip"]).sum()
 80        individual_area = source_config.source_geometries[fault_name].area()
 81
 82        # get all points associated with all segments in the current fault
 83        segment_points = srf_data.points.iloc[
 84            point_counter : point_counter + num_points
 85        ]
 86        individual_magnitude = moment.moment_to_magnitude(
 87            (
 88                moment.MU * segment_points["area"] * segment_points["slip"] / (100**3)
 89            ).sum()
 90        )
 91        ax.scatter(individual_area, individual_magnitude, label=fault_name)
 92
 93        # advance segment counter and point counter to skip all points from the current point
 94        segment_counter += plane_count
 95        point_counter += num_points
 96
 97    ax.set_xlabel("Area (m^2)")
 98    ax.set_ylabel("Mw")
 99    ax.set_xscale("log")
100    ax.legend()
101    ax.set_title(f"Log Area vs Magnitude ({realisation_metadata.name})")
102    fig.savefig(output_ffp, dpi=dpi)

Plot segment magnitudes against the Leonard scaling relation.

Parameters
  • srf_ffp (Path): Path to SRF file.
  • realisation_ffp (Path): Realisation filepath.
  • output_ffp (Path): Output plot path.
  • dpi (float, default 300): Output plot DPI (higher is better).