source_modelling.scripts.plot_srf_moment
Utility script to plot moment over time for an SRF.
1"""Utility script to plot moment over time for an SRF.""" 2 3from pathlib import Path 4from typing import Annotated, Optional 5 6import typer 7from matplotlib import pyplot as plt 8 9from source_modelling import moment, rupture_propagation, srf 10 11app = typer.Typer() 12 13 14@app.command(help="Plot released moment for an SRF over time.") 15def plot_srf_moment( 16 srf_ffp: Annotated[ 17 Path, 18 typer.Argument( 19 help="SRF filepath to plot", exists=True, readable=True, dir_okay=False 20 ), 21 ], 22 output_png_ffp: Annotated[ 23 Path, typer.Argument(help="Output plot path", writable=True, dir_okay=False) 24 ], 25 dpi: Annotated[ 26 int, typer.Option(help="Plot image pixel density (higher = better)", min=300) 27 ] = 300, 28 realisation_ffp: Annotated[ 29 Optional[Path], 30 typer.Option( 31 help="Path to realisation, used to plot individual fault contribution." 32 ), 33 ] = None, 34) -> None: 35 """Plot released moment for an SRF over time. 36 37 Parameters 38 ---------- 39 srf_ffp : Path 40 SRF filepath to plot. 41 output_png_ffp : Path 42 Output plot path. 43 dpi : float, default 300 44 Plot image pixel density (higher = better). 45 realisation_ffp : Optional[Path], default None 46 Path to realisation, used to plot individual fault contribution. 47 """ 48 srf_data = srf.read_srf(srf_ffp) 49 50 magnitude = moment.moment_to_magnitude( 51 moment.MU * (srf_data.points["area"] * srf_data.points["slip"] / (100**3)).sum() 52 ) 53 54 dt = srf_data.points["dt"].iloc[0] 55 56 overall_moment_rate = moment.moment_rate_over_time_from_slip( 57 srf_data.points["area"], srf_data.slip, dt, srf_data.nt 58 ) 59 fig, ax = plt.subplots() 60 ax.plot( 61 overall_moment_rate.index.values, 62 overall_moment_rate["moment_rate"], 63 label="Overall Moment Rate", 64 ) 65 66 if realisation_ffp: # pragma: no cover 67 # NOTE: this import is here because the workflow is, as yet, 68 # not ready to be installed along-side source modelling. 69 from workflow.realisations import RupturePropagationConfig, SourceConfig 70 71 source_config = SourceConfig.read_from_realisation(realisation_ffp) 72 rupture_propogation_config = RupturePropagationConfig.read_from_realisation( 73 realisation_ffp 74 ) 75 segment_counter = 0 76 point_counter = 0 77 for fault_name in rupture_propagation.tree_nodes_in_order( 78 rupture_propogation_config.rupture_causality_tree 79 ): 80 plane_count = len(source_config.source_geometries[fault_name].planes) 81 segments = srf_data.header.iloc[ 82 segment_counter : segment_counter + plane_count 83 ] 84 num_points = (segments["nstk"] * segments["ndip"]).sum() 85 individual_moment_rate = moment.moment_rate_over_time_from_slip( 86 srf_data.points["area"] 87 .iloc[point_counter : point_counter + num_points] 88 .to_numpy(), 89 srf_data.slip[point_counter : point_counter + num_points], 90 dt, 91 srf_data.nt, 92 ) 93 ax.plot( 94 individual_moment_rate.index.values, 95 individual_moment_rate["moment_rate"], 96 label=fault_name, 97 ) 98 segment_counter += plane_count 99 point_counter += num_points 100 101 ax.set_ylabel("Moment Rate (Nm/s)") 102 ax.set_xlabel("Time (s)") 103 ax.legend() 104 ax.set_title(f"Moment over Time (Total Mw: {magnitude:.2f})") 105 106 fig.savefig(output_png_ffp, dpi=dpi) 107 108 109if __name__ == "__main__": 110 app()
app =
<typer.main.Typer object>
@app.command(help='Plot released moment for an SRF over time.')
def
plot_srf_moment( srf_ffp: Annotated[pathlib.Path, <typer.models.ArgumentInfo object>], output_png_ffp: Annotated[pathlib.Path, <typer.models.ArgumentInfo object>], dpi: Annotated[int, <typer.models.OptionInfo object>] = 300, realisation_ffp: Annotated[Optional[pathlib.Path], <typer.models.OptionInfo object>] = None) -> None:
15@app.command(help="Plot released moment for an SRF over time.") 16def plot_srf_moment( 17 srf_ffp: Annotated[ 18 Path, 19 typer.Argument( 20 help="SRF filepath to plot", exists=True, readable=True, dir_okay=False 21 ), 22 ], 23 output_png_ffp: Annotated[ 24 Path, typer.Argument(help="Output plot path", writable=True, dir_okay=False) 25 ], 26 dpi: Annotated[ 27 int, typer.Option(help="Plot image pixel density (higher = better)", min=300) 28 ] = 300, 29 realisation_ffp: Annotated[ 30 Optional[Path], 31 typer.Option( 32 help="Path to realisation, used to plot individual fault contribution." 33 ), 34 ] = None, 35) -> None: 36 """Plot released moment for an SRF over time. 37 38 Parameters 39 ---------- 40 srf_ffp : Path 41 SRF filepath to plot. 42 output_png_ffp : Path 43 Output plot path. 44 dpi : float, default 300 45 Plot image pixel density (higher = better). 46 realisation_ffp : Optional[Path], default None 47 Path to realisation, used to plot individual fault contribution. 48 """ 49 srf_data = srf.read_srf(srf_ffp) 50 51 magnitude = moment.moment_to_magnitude( 52 moment.MU * (srf_data.points["area"] * srf_data.points["slip"] / (100**3)).sum() 53 ) 54 55 dt = srf_data.points["dt"].iloc[0] 56 57 overall_moment_rate = moment.moment_rate_over_time_from_slip( 58 srf_data.points["area"], srf_data.slip, dt, srf_data.nt 59 ) 60 fig, ax = plt.subplots() 61 ax.plot( 62 overall_moment_rate.index.values, 63 overall_moment_rate["moment_rate"], 64 label="Overall Moment Rate", 65 ) 66 67 if realisation_ffp: # pragma: no cover 68 # NOTE: this import is here because the workflow is, as yet, 69 # not ready to be installed along-side source modelling. 70 from workflow.realisations import RupturePropagationConfig, SourceConfig 71 72 source_config = SourceConfig.read_from_realisation(realisation_ffp) 73 rupture_propogation_config = RupturePropagationConfig.read_from_realisation( 74 realisation_ffp 75 ) 76 segment_counter = 0 77 point_counter = 0 78 for fault_name in rupture_propagation.tree_nodes_in_order( 79 rupture_propogation_config.rupture_causality_tree 80 ): 81 plane_count = len(source_config.source_geometries[fault_name].planes) 82 segments = srf_data.header.iloc[ 83 segment_counter : segment_counter + plane_count 84 ] 85 num_points = (segments["nstk"] * segments["ndip"]).sum() 86 individual_moment_rate = moment.moment_rate_over_time_from_slip( 87 srf_data.points["area"] 88 .iloc[point_counter : point_counter + num_points] 89 .to_numpy(), 90 srf_data.slip[point_counter : point_counter + num_points], 91 dt, 92 srf_data.nt, 93 ) 94 ax.plot( 95 individual_moment_rate.index.values, 96 individual_moment_rate["moment_rate"], 97 label=fault_name, 98 ) 99 segment_counter += plane_count 100 point_counter += num_points 101 102 ax.set_ylabel("Moment Rate (Nm/s)") 103 ax.set_xlabel("Time (s)") 104 ax.legend() 105 ax.set_title(f"Moment over Time (Total Mw: {magnitude:.2f})") 106 107 fig.savefig(output_png_ffp, dpi=dpi)
Plot released moment for an SRF over time.
Parameters
- srf_ffp (Path): SRF filepath to plot.
- output_png_ffp (Path): Output plot path.
- dpi (float, default 300): Plot image pixel density (higher = better).
- realisation_ffp (Optional[Path], default None): Path to realisation, used to plot individual fault contribution.