Hi,
all these calculations are done by the engine in the background and the output is saved to hdf5 during the runs,
if you want to understand in more detail, you can study the code and/or calculate the rates using a sample script:
from openquake.hazardlib.source import PointSource
from openquake.hazardlib.mfd import TruncatedGRMFD
from openquake.hazardlib.scalerel import WC1994
from openquake.hazardlib.geo import Point, NodalPlane
from openquake.hazardlib.pmf import PMF
from openquake.hazardlib.tom import PoissonTOM
src = PointSource(
source_id='1',
name='point',
tectonic_region_type='Active Shallow Crust',
mfd=TruncatedGRMFD(min_mag=5., max_mag=6.5, bin_width=0.1, a_val=0.01, b_val=0.98),
rupture_mesh_spacing=2,
magnitude_scaling_relationship=WC1994(),
rupture_aspect_ratio=1,
temporal_occurrence_model=PoissonTOM(50.), #50 years investigation time
upper_seismogenic_depth=2.,
lower_seismogenic_depth=12.,
location=Point(9.1500, 45.1833,30),
nodal_plane_distribution=PMF([(1., NodalPlane(strike=45, dip=50, rake=0))]),
hypocenter_distribution=PMF([(1, 10.)]) #depth 10 km
)
ruptures = [r for r in src.iter_ruptures()] #sample the ruptures in 50 years
print(ruptures[0].mag) #gives 5.05 as magnitude of the first rupture
print(ruptures[0].occurrence_rate) #gives 2.6023325356665764e-06 as a corresponding occurrence rate
which is indeed the occurrence rate for magnitude 5.5:
print(TruncatedGRMFD(min_mag=5., max_mag=6.5, bin_width=0.1, a_val=0.01, b_val=0.98).get_annual_occurrence_rates()) #gives among others 5.05, 2.6023325356665764e-06
Hope this helps
Peter