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).