def calculate(self, catalogue, config=None, completeness=None): """ Calculation of b-value and its uncertainty for a given catalogue, using the maximum likelihood method of Aki (1965), with a correction for discrete bin width (Bender, 1983). :param catalogue: See :class:`openquake.hmtk.seismicity.occurrence.base.py` for further explanation :param config: The configuration in this case do not contains specific information :keyword float completeness: Completeness magnitude :return float bval: b-value of the Gutenberg-Richter relationship :return float sigma_b: Standard deviation of the GR b-value """ # Input checks _cmag, _ctime, _ref_mag, dmag, config = input_checks( catalogue, config, completeness) rt = recurrence_table(catalogue.data['magnitude'], dmag, catalogue.data['year']) bval, sigma_b = self._aki_ml(rt[:, 0], rt[:, 1]) return bval, sigma_b
def _b_ml(self, catalogue, config, cmag, ctime, ref_mag, dmag): end_year = float(catalogue.end_year) catalogue = catalogue.data ival = 0 mag_eq_tolerance = 1E-5 aki_ml = AkiMaxLikelihood() while ival < np.shape(ctime)[0]: id0 = np.abs(ctime - ctime[ival]) < mag_eq_tolerance m_c = np.min(cmag[id0]) print('--- ctime', ctime[ival], ' m_c', m_c) # Find events later than cut-off year, and with magnitude # greater than or equal to the corresponding completeness # magnitude. m_c - mag_eq_tolerance is required to correct # floating point differences. id1 = np.logical_and( catalogue['year'] >= ctime[ival], catalogue['magnitude'] >= (m_c - mag_eq_tolerance)) # Get a- and b- value for the selected events temp_rec_table = recurrence_table(catalogue['magnitude'][id1], dmag, catalogue['year'][id1], end_year - ctime[ival] + 1) bval, sigma_b = aki_ml._aki_ml(temp_rec_table[:, 0], temp_rec_table[:, 1], dmag, m_c) if ival == 0: gr_pars = np.array([np.hstack([bval, sigma_b])]) neq = np.sum(id1) # Number of events else: gr_pars = np.vstack([gr_pars, np.hstack([bval, sigma_b])]) neq = np.hstack([neq, np.sum(id1)]) ival = ival + np.sum(id0) # Get average GR parameters bval, sigma_b = self._average_parameters(gr_pars, neq, config['Average Type']) aval = self._calculate_a_value(bval, np.float(np.sum(neq)), cmag, ctime, catalogue['magnitude'], end_year, dmag) sigma_a = self._calculate_a_value(bval + sigma_b, np.float(np.sum(neq)), cmag, ctime, catalogue['magnitude'], end_year, dmag) if not config['reference_magnitude']: return bval,\ sigma_b,\ aval,\ sigma_a - aval else: rate = 10.**(aval - bval * config['reference_magnitude']) sigma_rate = 10.**(sigma_a - bval * config['reference_magnitude']) - rate return bval,\ sigma_b,\ rate,\ sigma_rate
def calculate(self, catalogue, config=None, completeness=None): """ Calculation of b-value and its uncertainty for a given catalogue, using the maximum likelihood method of Aki (1965), with a correction for discrete bin width (Bender, 1983). :param catalogue: See :class:`openquake.hmtk.seismicity.occurrence.base.py` for further explanation :param config: The configuration in this case do not contains specific information :keyword float completeness: Completeness magnitude :return float bval: b-value of the Gutenberg-Richter relationship :return float sigma_b: Standard deviation of the GR b-value """ # Input checks _cmag, _ctime, _ref_mag, dmag, config = input_checks(catalogue, config, completeness) rt = recurrence_table( catalogue.data['magnitude'], dmag, catalogue.data['year']) bval, sigma_b = self._aki_ml(rt[:, 0], rt[:, 1]) return bval, sigma_b
def calculate(self, catalogue, config, completeness=None): """ Main function to calculate the a- and b-value """ # Input checks cmag, ctime, ref_mag, dmag, config = input_checks(catalogue, config, completeness) ival = 0 tolerance = 1E-7 number_intervals = np.shape(ctime)[0] b_est = np.zeros(number_intervals, dtype=float) neq = np.zeros(number_intervals, dtype=float) nyr = np.zeros(number_intervals, dtype=float) for ival in range(0, number_intervals): id0 = np.abs(ctime - ctime[ival]) < tolerance m_c = np.min(cmag[id0]) if ival == 0: id1 = np.logical_and( catalogue.data['year'] >= (ctime[ival] - tolerance), catalogue.data['magnitude'] >= (m_c - tolerance)) nyr[ival] = float(catalogue.end_year) - ctime[ival] + 1. elif ival == number_intervals - 1: id1 = np.logical_and( catalogue.data['year'] < (ctime[ival - 1] - tolerance), catalogue.data['magnitude'] >= (m_c - tolerance)) nyr[ival] = ctime[ival - 1] - ctime[ival] else: id1 = np.logical_and( catalogue.data['year'] >= (ctime[ival] - tolerance), catalogue.data['year'] < (ctime[ival - 1] - tolerance)) id1 = np.logical_and( id1, catalogue.data['magnitude'] > (m_c - tolerance)) nyr[ival] = ctime[ival - 1] - ctime[ival] neq[ival] = np.sum(id1) # Get a- and b- value for the selected events temp_rec_table = recurrence_table(catalogue.data['magnitude'][id1], dmag, catalogue.data['year'][id1]) aki_ml = AkiMaxLikelihood() b_est[ival] = aki_ml._aki_ml(temp_rec_table[:, 0], temp_rec_table[:, 1], dmag, m_c)[0] ival += 1 total_neq = np.float(np.sum(neq)) bval = self._harmonic_mean(b_est, neq) sigma_b = bval / np.sqrt(total_neq) aval = self._calculate_a_value(bval, total_neq, nyr, cmag, ref_mag) sigma_a = self._calculate_a_value(bval + sigma_b, total_neq, nyr, cmag, ref_mag) if not config['reference_magnitude']: aval = np.log10(aval) sigma_a = np.log10(sigma_a) - aval else: sigma_a = sigma_a - aval return bval, sigma_b, aval, sigma_a
def test_recurrence_table_A(self): """ Basic recurrence table test """ magnitude_interval = 0.1 self.assertTrue(np.allclose(self.true_tableA, rec_utils.recurrence_table(self.catalogueA.data['magnitude'], magnitude_interval, self.catalogueA.data['year'])))
def test_recurrence_table_A(self): """ Basic recurrence table test """ magnitude_interval = 0.1 self.assertTrue( np.allclose(self.true_tableA, rec_utils.recurrence_table(self.catalogueA.data['magnitude'], magnitude_interval, self.catalogueA.data['year'])) )
def _b_ml(self, catalogue, config, cmag, ctime, ref_mag, dmag): end_year = float(catalogue.end_year) catalogue = catalogue.data ival = 0 mag_eq_tolerance = 1E-5 aki_ml = AkiMaxLikelihood() while ival < np.shape(ctime)[0]: id0 = np.abs(ctime - ctime[ival]) < mag_eq_tolerance m_c = np.min(cmag[id0]) print('--- ctime', ctime[ival], ' m_c', m_c) # Find events later than cut-off year, and with magnitude # greater than or equal to the corresponding completeness # magnitude. m_c - mag_eq_tolerance is required to correct # floating point differences. id1 = np.logical_and( catalogue['year'] >= ctime[ival], catalogue['magnitude'] >= (m_c - mag_eq_tolerance)) # Get a- and b- value for the selected events temp_rec_table = recurrence_table(catalogue['magnitude'][id1], dmag, catalogue['year'][id1], end_year-ctime[ival]+1) bval, sigma_b = aki_ml._aki_ml(temp_rec_table[:, 0], temp_rec_table[:, 1], dmag, m_c) if ival == 0: gr_pars = np.array([np.hstack([bval, sigma_b])]) neq = np.sum(id1) # Number of events else: gr_pars = np.vstack([gr_pars, np.hstack([bval, sigma_b])]) neq = np.hstack([neq, np.sum(id1)]) ival = ival + np.sum(id0) # Get average GR parameters bval, sigma_b = self._average_parameters( gr_pars, neq, config['Average Type']) aval = self._calculate_a_value(bval, np.float(np.sum(neq)), cmag, ctime, catalogue['magnitude'], end_year, dmag) sigma_a = self._calculate_a_value(bval + sigma_b, np.float(np.sum(neq)), cmag, ctime, catalogue['magnitude'], end_year, dmag) if not config['reference_magnitude']: return bval,\ sigma_b,\ aval,\ sigma_a - aval else: rate = 10. ** (aval - bval * config['reference_magnitude']) sigma_rate = 10. ** (sigma_a - bval * config['reference_magnitude']) - rate return bval,\ sigma_b,\ rate,\ sigma_rate