def assignMmaxfromMelettiDataset(layer, mmax_data): """Assign Mmax from Meletti data set to area source zone layer.""" provider = layer.dataProvider() # create missing attributes (if required) for attribute_list in features.AREA_SOURCE_ATTRIBUTES_ALL: utils.getAttributeIndex(provider, attribute_list, create=True) values = {} attribute_map = utils.getAttributeIndex(provider, MMAX_ATTRIBUTES) id_idx, id_type = attribute_map[features.AREA_SOURCE_ATTR_ID['name']] mmax_idx, mmax_type = \ attribute_map[features.AREA_SOURCE_ATTR_MMAX['name']] provider.select() provider.rewind() for zone_idx, zone in utils.walkValidPolygonFeatures(provider): zone_id = int(zone[id_idx].toInt()[0]) # mmax from Meletti data set try: mmax = mmax_data[zone_id]['mmax'] except Exception: continue try: values[zone.id()] = {mmax_idx: QVariant(mmax)} except Exception, e: error_str = \ "error in attribute: zone_idx: %s, zone_id: %s, mmax: %s, %s" % ( zone_idx, zone.id(), mmax, e) raise RuntimeError, error_str
def assignAttributesFromBackgroundZones(layer, background_layer, attributes_in, ui_mode=True): """Copy attributes from background zone layer.""" provider = layer.dataProvider() provider_back = background_layer.dataProvider() # create missing attributes (if required) for attribute_list in features.AREA_SOURCE_ATTRIBUTES_ALL: utils.getAttributeIndex(provider, attribute_list, create=True) values = {} attribute_map = utils.getAttributeIndex(provider, attributes_in) provider.select() provider.rewind() for zone_idx, zone in utils.walkValidPolygonFeatures(provider): attributes = {} skipZone = False # get mmax and mcdist from background zones polygon, vertices = utils.polygonsQGS2Shapely((zone, )) centroid = polygon[0].centroid copy_attr = getAttributesFromBackgroundZones(centroid, provider_back, attributes_in, ui_mode=ui_mode) for attr_idx, attr_dict in enumerate(attributes_in): (curr_idx, curr_type) = attribute_map[attr_dict['name']] # if one of the attribute values is None, skip zone if copy_attr[attr_idx] is None: skipZone = True break try: # attributes are of type QVariant attributes[curr_idx] = copy_attr[attr_idx] except Exception, e: error_str = \ "error in attribute: curr_idx: %s, zone_idx: %s, attr_idx: %s, %s" % ( curr_idx, zone_idx, attr_idx, e) raise RuntimeError, error_str if skipZone is False: values[zone.id()] = attributes
def writeLayerAttributes(layer, feature_list, attributes_in): """Write attributes to layer.""" fts = layer.selectedFeatures() provider = layer.dataProvider() attribute_map = utils.getAttributeIndex(provider, feature_list, create=True) values = {} # loop over selected QGis features for zone_idx, zone in enumerate(fts): attribute_list = {} skipZone = False for attr_idx, attr_dict in enumerate(feature_list): (curr_idx, curr_type) = attribute_map[attr_dict['name']] try: attribute_list[curr_idx] = QVariant( attributes_in[zone_idx][attr_idx]) except Exception, e: skipZone = True break if skipZone is False: values[zone.id()] = attribute_list
def assignAttributesFromBackgroundZones(layer, background_layer, attributes_in, ui_mode=True): """Copy attributes from background zone layer.""" provider = layer.dataProvider() provider_back = background_layer.dataProvider() # create missing attributes (if required) for attribute_list in features.AREA_SOURCE_ATTRIBUTES_ALL: utils.getAttributeIndex(provider, attribute_list, create=True) values = {} attribute_map = utils.getAttributeIndex(provider, attributes_in) provider.select() provider.rewind() for zone_idx, zone in utils.walkValidPolygonFeatures(provider): attributes = {} skipZone = False # get mmax and mcdist from background zones polygon, vertices = utils.polygonsQGS2Shapely((zone,)) centroid = polygon[0].centroid copy_attr = getAttributesFromBackgroundZones(centroid, provider_back, attributes_in, ui_mode=ui_mode) for attr_idx, attr_dict in enumerate(attributes_in): (curr_idx, curr_type) = attribute_map[attr_dict['name']] # if one of the attribute values is None, skip zone if copy_attr[attr_idx] is None: skipZone = True break try: # attributes are of type QVariant attributes[curr_idx] = copy_attr[attr_idx] except Exception, e: error_str = \ "error in attribute: curr_idx: %s, zone_idx: %s, attr_idx: %s, %s" % ( curr_idx, zone_idx, attr_idx, e) raise RuntimeError, error_str if skipZone is False: values[zone.id()] = attributes
def assignActivityAtticIvy(layer, catalog, mmin=ATTICIVY_MMIN, mindepth=eqcatalog.CUT_DEPTH_MIN, maxdepth=eqcatalog.CUT_DEPTH_MAX, ui_mode=True): """Compute activity with Roger Musson's AtticIvy code and assign a and b values to each area source zone. Input: layer QGis layer with area zone features catalog earthquake catalog as QuakePy object """ # get attribute indexes provider = layer.dataProvider() zone_attribute_map = utils.getAttributeIndex(provider, ZONE_ATTRIBUTES, create=False) mmax_name = features.AREA_SOURCE_ATTR_MMAX['name'] mmax_idx = zone_attribute_map[mmax_name][0] mcdist_name = features.AREA_SOURCE_ATTR_MCDIST['name'] mcdist_idx = zone_attribute_map[mcdist_name][0] fts = layer.selectedFeatures() polygons, vertices = utils.polygonsQGS2Shapely(fts) # get mmax and mcdist from layer zone attributes mmax = [] mcdist = [] for zone_idx, zone in enumerate(fts): try: mmax_value = float(zone[mmax_idx].toDouble()[0]) except KeyError: mmax_value = None error_msg = "AtticIvy: no Mmax value in zone %s" % zone_idx if ui_mode is True: QMessageBox.warning(None, "AtticIvy Error", error_msg) else: print error_msg try: mcdist_value = str(zone[mcdist_idx].toString()) except KeyError: mcdist_value = None error_msg = "AtticIvy: no Mc value in zone %s" % zone_idx if ui_mode is True: QMessageBox.warning(None, "AtticIvy Error", error_msg) else: print error_msg mmax.append(mmax_value) mcdist.append(mcdist_value) activity = computeActivityAtticIvy(polygons, mmax, mcdist, catalog, mmin, mindepth, maxdepth, ui_mode=ui_mode) attributes.writeLayerAttributes(layer, features.AREA_SOURCE_ATTRIBUTES_AB_RM, activity)
def getAttributesFromBackgroundZones(point, provider_back, attributes, ui_mode=True): """Get attribute list (from mmax and mcdist) from background zone at a given Shapely point.""" attribute_map = utils.getAttributeIndex(provider_back, attributes) # identify matching background zone (background_zone, bgz_poly, bgz_area) = utils.findBackgroundZone( point, provider_back, ui_mode=ui_mode) if background_zone is not None: # leave values as QVariant background_attrs = [background_zone[attribute_map[x['name']][0]] \ for x in attributes] else: background_attrs = [None] * len(attributes) return background_attrs
def getAttributesFromBackgroundZones(point, provider_back, attributes, ui_mode=True): """Get attribute list (from mmax and mcdist) from background zone at a given Shapely point.""" attribute_map = utils.getAttributeIndex(provider_back, attributes) # identify matching background zone (background_zone, bgz_poly, bgz_area) = utils.findBackgroundZone(point, provider_back, ui_mode=ui_mode) if background_zone is not None: # leave values as QVariant background_attrs = [background_zone[attribute_map[x['name']][0]] \ for x in attributes] else: background_attrs = [None] * len(attributes) return background_attrs
def updateDataFaultBackgr(cls, feature, m_threshold=recurrence.FAULT_BACKGROUND_MAG_THRESHOLD): """Update or compute moment rates for selected feature of fault background zone layer. Input: feature QGis polygon feature from fault background zone layer Output: parameters dict of computed parameters """ provider = cls.fault_background_layer.dataProvider() provider_fault = cls.fault_source_layer.dataProvider() provider_area = cls.area_source_layer.dataProvider() provider_back = cls.background_zone_layer.dataProvider() parameters = {} # get Shapely polygon from feature geometry polylist, vertices = utils.polygonsQGS2Shapely((feature,)) poly = polylist[0] # get polygon area in square kilometres parameters['area_background_sqkm'] = \ utils.polygonAreaFromWGS84(poly) * 1.0e-6 # get mmax and mcdist for FBZ from background zone (mcdist_qv, mmax_qv) = areasource.getAttributesFromBackgroundZones( poly.centroid, provider_back, areasource.MCDIST_MMAX_ATTRIBUTES) mmax = float(mmax_qv.toDouble()[0]) mcdist = str(mcdist_qv.toString()) parameters['mmax'] = mmax ## moment rate from EQs # get quakes from catalog (cut with fault background zone polygon) poly_cat = QPCatalog.QPCatalog() poly_cat.merge(cls.catalog) poly_cat.cut(geometry=poly) # cut catalog with min/max depth according to UI spinboxes (mindepth, maxdepth) = eqcatalog.getMinMaxDepth(cls) poly_cat.cut(mindepth=mindepth, maxdepth=maxdepth) parameters['eq_count'] = poly_cat.size() # sum up moment from quakes (converted from Mw with Kanamori eq.) magnitudes = [] for ev in poly_cat.eventParameters.event: mag = ev.getPreferredMagnitude() magnitudes.append(mag.mag.value) moment = numpy.array(momentrate.magnitude2moment(magnitudes)) # scale moment: per year and area (in km^2) parameters['mr_eq'] = moment.sum() / ( parameters['area_background_sqkm'] * cls.catalog_time_span[0]) ## moment rate from activity (RM) parameters['activity_mmin'] = atticivy.ATTICIVY_MMIN activity = atticivy.computeActivityAtticIvy( (poly, ), (mmax, ), (mcdist, ), cls.catalog, mmin=parameters['activity_mmin']) # get RM (a, b) values from feature attribute activity_str_a = activity[0][3] activity_arr_a = activity_str_a.strip().split() activity_str_b = activity[0][4] activity_arr_b = activity_str_b.strip().split() # ignore weights activity_a = [float(x) for x in activity_arr_a] activity_b = [float(x) for x in activity_arr_b] parameters['activity_a'] = activity_a parameters['activity_b'] = activity_b a_values = activity_a momentrates_arr = numpy.array(momentrate.momentrateFromActivity( a_values, activity_b, mmax)) / cls.catalog_time_span[0] parameters['mr_activity'] = momentrates_arr.tolist() # get separate catalogs below and above magnitude threshold cat_below_threshold = QPCatalog.QPCatalog() cat_below_threshold.merge(poly_cat) cat_below_threshold.cut(maxmag=m_threshold, maxmag_excl=True) parameters['eq_count_below'] = cat_below_threshold.size() cat_above_threshold = QPCatalog.QPCatalog() cat_above_threshold.merge(poly_cat) cat_above_threshold.cut(minmag=m_threshold, maxmag_excl=False) parameters['eq_count_above'] = cat_above_threshold.size() activity_below_threshold = atticivy.computeActivityAtticIvy( (poly,), (mmax,), (mcdist,), cat_below_threshold, mmin=parameters['activity_mmin']) activity_above_threshold = atticivy.computeActivityAtticIvy( (poly,), (mmax,), (mcdist,), cat_above_threshold, mmin=parameters['activity_mmin']) # get RM (weight, a, b) values from feature attribute activity_below_str_a = activity_below_threshold[0][3] activity_below_arr_a = activity_below_str_a.strip().split() activity_below_str_b = activity_below_threshold[0][4] activity_below_arr_b = activity_below_str_b.strip().split() activity_above_str_a = activity_above_threshold[0][3] activity_above_arr_a = activity_above_str_a.strip().split() activity_above_str_b = activity_above_threshold[0][4] activity_above_arr_b = activity_above_str_b.strip().split() # ignore weights activity_below_a = [float(x) for x in activity_below_arr_a] activity_below_b = [float(x) for x in activity_below_arr_b] activity_above_a = [float(x) for x in activity_above_arr_a] activity_above_b = [float(x) for x in activity_above_arr_b] a_values_below = activity_below_a momentrates_below_arr = numpy.array(momentrate.momentrateFromActivity( a_values_below, activity_below_b, mmax)) / cls.catalog_time_span[0] a_values_above = activity_above_a momentrates_above_arr = numpy.array(momentrate.momentrateFromActivity( a_values_above, activity_above_b, mmax)) / cls.catalog_time_span[0] parameters['activity_below_a'] = activity_below_a parameters['activity_below_b'] = activity_below_b parameters['activity_above_a'] = activity_above_a parameters['activity_above_b'] = activity_above_b parameters['mr_activity_below'] = momentrates_below_arr.tolist() parameters['mr_activity_above'] = momentrates_above_arr.tolist() parameters['activity_m_threshold'] = m_threshold # FMD from quakes in FBZ cls.feature_data_fault_background['fmd'] = fmd.computeZoneFMD(cls, feature, poly_cat) (parameters['ml_a'], parameters['ml_b'], parameters['ml_mc'], parameters['ml_magctr']) = fmd.getFMDValues( cls.feature_data_fault_background['fmd']) ## moment rate from slip rate sliprate_min_name = features.FAULT_SOURCE_ATTR_SLIPRATE_MIN['name'] sliprate_max_name = features.FAULT_SOURCE_ATTR_SLIPRATE_MAX['name'] attribute_map = utils.getAttributeIndex(provider_fault, (features.FAULT_SOURCE_ATTR_SLIPRATE_MIN, features.FAULT_SOURCE_ATTR_SLIPRATE_MAX), create=False) moment_rate_min = 0.0 moment_rate_max = 0.0 parameters['area_fault_sqkm'] = 0.0 parameters['fault_count'] = 0 provider_fault.rewind() for fault in provider_fault: fault_poly, vertices = utils.polygonsQGS2Shapely((fault,)) if fault_poly[0].intersects(poly): parameters['fault_count'] += 1 sliprate_min = \ fault[attribute_map[sliprate_min_name][0]].toDouble()[0] sliprate_max = \ fault[attribute_map[sliprate_max_name][0]].toDouble()[0] area_fault = utils.polygonAreaFromWGS84(fault_poly[0]) # TODO(fab): correct scaling of moment rate from slip rate (rate_min, rate_max) = momentrate.momentrateFromSlipRate( sliprate_min, sliprate_max, area_fault) moment_rate_min += rate_min moment_rate_max += rate_max parameters['area_fault_sqkm'] += area_fault moment_rate_min /= cls.catalog_time_span[0] moment_rate_max /= cls.catalog_time_span[0] parameters['mr_slip'] = [moment_rate_min, moment_rate_max] parameters['area_fault_sqkm'] *= 1.0e-6 ## moment rate from geodesy (strain) momentrate_strain_barba = momentrate.momentrateFromStrainRateBarba( poly, cls.data.strain_rate_barba, cls.data.deformation_regimes_bird) parameters['mr_strain_barba'] = momentrate_strain_barba / ( cls.catalog_time_span[0]) momentrate_strain_bird = momentrate.momentrateFromStrainRateBird(poly, cls.data.strain_rate_bird, cls.data.deformation_regimes_bird) parameters['mr_strain_bird'] = momentrate_strain_bird / ( cls.catalog_time_span[0]) return parameters
def updateDataArea(cls, feature): """Update or compute moment rates for selected feature of area source zone layer. Input: feature QGis polygon feature from area source layer Output: parameters dict of computed parameters """ provider = cls.area_source_layer.dataProvider() parameters = {} # get Shapely polygon from feature geometry polylist, vertices = utils.polygonsQGS2Shapely((feature, )) poly = polylist[0] # get polygon area in square kilometres parameters['area_sqkm'] = utils.polygonAreaFromWGS84(poly) * 1.0e-6 # zone ID and title (feature_id, feature_title, feature_name) = utils.getFeatureAttributes( cls.area_source_layer, feature, features.AREA_SOURCE_ATTRIBUTES_ID) if feature_title.toString() == '' and feature_name.toString() == '': zone_name_str = "" elif feature_title.toString() == '' and feature_name.toString() != '': zone_name_str = feature_name.toString() elif feature_title.toString() != '' and feature_name.toString() == '': zone_name_str = feature_title.toString() else: zone_name_str = "%s, %s" % (feature_title.toString(), feature_name.toString()) parameters['plot_title_fmd'] = 'Zone %s, %s' % (feature_id.toInt()[0], zone_name_str) ## moment rate from EQs # get quakes from catalog (cut with polygon) poly_cat = QPCatalog.QPCatalog() poly_cat.merge(cls.catalog) poly_cat.cut(geometry=poly) # cut catalog with min/max depth according to UI spinboxes (mindepth, maxdepth) = eqcatalog.getMinMaxDepth(cls) poly_cat.cut(mindepth=mindepth, maxdepth=maxdepth) parameters['eq_count'] = poly_cat.size() # sum up moment from quakes (converted from Mw with Kanamori eq.) magnitudes = [] for ev in poly_cat.eventParameters.event: mag = ev.getPreferredMagnitude() magnitudes.append(mag.mag.value) moment = numpy.array(momentrate.magnitude2moment(magnitudes)) # scale moment: per year and area (in km^2) parameters['mr_eq'] = moment.sum() / (parameters['area_sqkm'] * cls.catalog_time_span[0]) ## moment rate from activity (RM) # get attribute index of AtticIvy result attribute_map = utils.getAttributeIndex( provider, (features.AREA_SOURCE_ATTR_ACT_RM_A, features.AREA_SOURCE_ATTR_ACT_RM_B, features.AREA_SOURCE_ATTR_MMAX)) attribute_act_a_name = features.AREA_SOURCE_ATTR_ACT_RM_A['name'] attribute_act_a_idx = attribute_map[attribute_act_a_name][0] attribute_act_b_name = features.AREA_SOURCE_ATTR_ACT_RM_B['name'] attribute_act_b_idx = attribute_map[attribute_act_b_name][0] attribute_mmax_name = features.AREA_SOURCE_ATTR_MMAX['name'] attribute_mmax_idx = attribute_map[attribute_mmax_name][0] # get RM (a, b) values from feature attributes try: activity_a_str = str(feature[attribute_act_a_idx].toString()) activity_a_arr = activity_a_str.strip().split() except KeyError: activity_a_arr = 3 * [numpy.nan] error_msg = "Moment balancing: no valid activity a parameter in %s" % ( parameters['plot_title_fmd']) QMessageBox.warning(None, "Moment balancing warning", error_msg) try: activity_b_str = str(feature[attribute_act_b_idx].toString()) activity_b_arr = activity_b_str.strip().split() except KeyError: activity_b_arr = 3 * [numpy.nan] error_msg = "Moment balancing: no valid activity b parameter in %s" % ( parameters['plot_title_fmd']) QMessageBox.warning(None, "Moment balancing warning", error_msg) # ignore weights parameters['activity_mmin'] = atticivy.ATTICIVY_MMIN activity_a = [float(x) for x in activity_a_arr] activity_b = [float(x) for x in activity_b_arr] mmax = float(feature[attribute_mmax_idx].toDouble()[0]) parameters['activity_a'] = activity_a parameters['activity_b'] = activity_b parameters['mmax'] = mmax ## Maximum likelihood a/b values if poly_cat.size() == 0: cls.feature_data_area_source['fmd'] = None (parameters['ml_a'], parameters['ml_b'], parameters['ml_mc'], parameters['ml_magctr']) = 4 * [numpy.nan] error_msg = "Moment balancing: no EQs in %s" % ( parameters['plot_title_fmd']) QMessageBox.warning(None, "Moment balancing warning", error_msg) else: cls.feature_data_area_source['fmd'] = fmd.computeZoneFMD( cls, feature, poly_cat) (parameters['ml_a'], parameters['ml_b'], parameters['ml_mc'], parameters['ml_magctr']) = fmd.getFMDValues( cls.feature_data_area_source['fmd']) ## moment rate from activity a_values = activity_a momentrates_arr = numpy.array( momentrate.momentrateFromActivity(a_values, activity_b, mmax)) / cls.catalog_time_span[0] parameters['mr_activity'] = momentrates_arr.tolist() ## moment rate from geodesy (strain) momentrate_strain_barba = momentrate.momentrateFromStrainRateBarba( poly, cls.data.strain_rate_barba, cls.data.deformation_regimes_bird) parameters['mr_strain_barba'] = momentrate_strain_barba / ( cls.catalog_time_span[0]) momentrate_strain_bird = momentrate.momentrateFromStrainRateBird( poly, cls.data.strain_rate_bird, cls.data.deformation_regimes_bird) parameters['mr_strain_bird'] = momentrate_strain_bird / ( cls.catalog_time_span[0]) return parameters
def getAttributesFromRecurrence(provider, feature): """Read recurrence attributes from fault layer.""" parameters = {} attribute_map_fault = utils.getAttributeIndex( provider, features.FAULT_SOURCE_ATTRIBUTES_RECURRENCE, create=False) # get fault background zone ID id_name = features.FAULT_SOURCE_ATTR_ID_FBZ['name'] try: parameters['fbz_id'] = str( feature[attribute_map_fault[id_name][0]].toString()) except KeyError: error_msg = "No recurrence data for zone %s" % (feature.id()) QMessageBox.warning(None, "Missing Data", error_msg) return None # a and b value from FBZ (fault layer attributes) a_fbz_name = features.FAULT_SOURCE_ATTR_A_FBZ['name'] b_fbz_name = features.FAULT_SOURCE_ATTR_B_FBZ['name'] parameters['activity_fbz_a'] = \ feature[attribute_map_fault[a_fbz_name][0]].toDouble()[0] parameters['activity_fbz_b'] = \ feature[attribute_map_fault[b_fbz_name][0]].toDouble()[0] act_fbz_a_name = features.FAULT_SOURCE_ATTR_ACT_FBZ_A['name'] act_fbz_b_name = features.FAULT_SOURCE_ATTR_ACT_FBZ_B['name'] parameters['activity_fbz_act_a'] = str( feature[attribute_map_fault[act_fbz_a_name][0]].toString()) parameters['activity_fbz_act_b'] = str( feature[attribute_map_fault[act_fbz_b_name][0]].toString()) # a and b value from buffer zone (fault layer attributes) a_bz_name = features.FAULT_SOURCE_ATTR_A_BUF['name'] b_bz_name = features.FAULT_SOURCE_ATTR_B_BUF['name'] parameters['activity_bz_a'] = \ feature[attribute_map_fault[a_bz_name][0]].toDouble()[0] parameters['activity_bz_b'] = \ feature[attribute_map_fault[b_bz_name][0]].toDouble()[0] act_bz_a_name = features.FAULT_SOURCE_ATTR_ACT_BUF_A['name'] act_bz_b_name = features.FAULT_SOURCE_ATTR_ACT_BUF_B['name'] parameters['activity_bz_act_a'] = str( feature[attribute_map_fault[act_bz_a_name][0]].toString()) parameters['activity_bz_act_b'] = str( feature[attribute_map_fault[act_bz_b_name][0]].toString()) # a and b value from FBZ, above magnitude threshold a_fbz_at_name = features.FAULT_SOURCE_ATTR_A_FBZ_AT['name'] b_fbz_at_name = features.FAULT_SOURCE_ATTR_B_FBZ_AT['name'] parameters['activity_fbz_at_a'] = \ feature[attribute_map_fault[a_fbz_at_name][0]].toDouble()[0] parameters['activity_fbz_at_b'] = \ feature[attribute_map_fault[b_fbz_at_name][0]].toDouble()[0] act_fbz_at_a_name = features.FAULT_SOURCE_ATTR_ACT_FBZ_AT_A['name'] act_fbz_at_b_name = features.FAULT_SOURCE_ATTR_ACT_FBZ_AT_B['name'] parameters['activity_fbz_at_act_a'] = str( feature[attribute_map_fault[act_fbz_at_a_name][0]].toString()) parameters['activity_fbz_at_act_b'] = str( feature[attribute_map_fault[act_fbz_at_b_name][0]].toString()) # a values from recurrence (fault layer attributes) a_rec_min_name = features.FAULT_SOURCE_ATTR_A_REC_MIN['name'] a_rec_max_name = features.FAULT_SOURCE_ATTR_A_REC_MAX['name'] parameters['activity_rec_a_min'] = \ feature[attribute_map_fault[a_rec_min_name][0]].toDouble()[0] parameters['activity_rec_a_max'] = \ feature[attribute_map_fault[a_rec_max_name][0]].toDouble()[0] sliprate_min_name = features.FAULT_SOURCE_ATTR_SLIPRATE_MIN['name'] sliprate_max_name = features.FAULT_SOURCE_ATTR_SLIPRATE_MAX['name'] mmax_fault_name = features.FAULT_SOURCE_ATTR_MAGNITUDE_MAX['name'] parameters['sliprate_min'] = \ feature[attribute_map_fault[sliprate_min_name][0]].toDouble()[0] parameters['sliprate_max'] = \ feature[attribute_map_fault[sliprate_max_name][0]].toDouble()[0] parameters['mmax_fault'] = \ feature[attribute_map_fault[mmax_fault_name][0]].toDouble()[0] return parameters
def computeRecurrence(layer_fault, layer_fault_background=None, layer_background=None, catalog=None, catalog_time_span=None, b_value=None, mmin=atticivy.ATTICIVY_MMIN, m_threshold=FAULT_BACKGROUND_MAG_THRESHOLD, mindepth=eqcatalog.CUT_DEPTH_MIN, maxdepth=eqcatalog.CUT_DEPTH_MAX, ui_mode=True): """Compute recurrence parameters according to Bungum paper. Parameters from Jochen's Matlab implementation: % rParams.fBvalue : b-value % rParams.fS : Slip rate (mm/year) % rParams.fD : Average slip (m) % rParams.fLength : Fault length (m) % rParams.fWidth : Fault width (m) % rParams.fM00 : M0(0) for Ms = 0, c in logM0=c-dM % rParams.fMmin : Minimum magnitude % rParams.fBinM : magnitude binnning % rParams.fMmax : Maximum magnitude % rParams.fDmoment : d in logM0=c-dM % rParams.fRigid : Rgidity in Pascal rParams.fBvalue = 1; rParams.fS = 1e-3; rParams.fD = 1; rParams.fLength = 100000; rParams.fWidth = 50000; rParams.fM00 = 16.05; rParams.fMmin = 5; rParams.fBinM = 0.1; rParams.fMmax = 8; rParams.fDmoment = 1.5; rParams.fRigid = 30e+6; """ result_values = [] provider_fault = layer_fault.dataProvider() fts = layer_fault.selectedFeatures() # loop over fault polygons for zone_idx, feature in enumerate(fts): # collect the following attribute data: # - FBZ zone ID # - (a, b, act_a, act_b) for FBZ # - (a, b, act_a, act_b) for buffer zone # - m_threshold # - (a, b, act_a, act_b) for FBZ, below magnitude threshold # - (a, b, act_a, act_b) for FBZ, above magnitude threshold # - (a, b, Mc) from maximum likelihood G-R # - Mmax from background # - a from slip rate (min/max) # - activity rate (min/max) # - moment rate (min/max) zone_data_string_min = "" zone_data_string_max = "" if ui_mode is False: print "\n=== Processing FSZ feature, id %s ===" % feature.id() # get parameters from background zones activity_back = computeActivityFromBackground(feature, layer_fault_background, layer_background, catalog, mmin, m_threshold, mindepth, maxdepth, ui_mode=ui_mode) if activity_back is None: result_values.append(None) continue # get attribute values of zone: # - MAXMAG, SLIPRATEMI, SLIPRATEMA attribute_map_fault = utils.getAttributeIndex( provider_fault, features.FAULT_SOURCE_ATTRIBUTES_RECURRENCE, create=True) # get maximum magnitude (Note: it's int in feature attributes) maxmag_name = features.FAULT_SOURCE_ATTR_MAGNITUDE_MAX['name'] maxmag = feature[attribute_map_fault[maxmag_name][0]].toDouble()[0] # get minimum of annual slip rate slipratemi_name = features.FAULT_SOURCE_ATTR_SLIPRATE_MIN['name'] slipratemi = \ feature[attribute_map_fault[slipratemi_name][0]].toDouble()[0] # get maximum of annual slip rate slipratema_name = features.FAULT_SOURCE_ATTR_SLIPRATE_MAX['name'] slipratema = \ feature[attribute_map_fault[slipratema_name][0]].toDouble()[0] # get area of fault zone polylist, vertices = utils.polygonsQGS2Shapely((feature, )) fault_poly = polylist[0] fault_area = utils.polygonAreaFromWGS84(fault_poly) # determine b value that is used in further computations # - use b value computed on fault background zone if b_value is None: b_value = activity_back['fbz']['activity'][atticivy.ATTICIVY_B_IDX] # equidistant magnitude array on which activity rates are computed # from global Mmin to zone-dependent Mmax mag_arr = numpy.arange(MAGNITUDE_MIN, maxmag, MAGNITUDE_BINNING) if len(mag_arr) == 0: result_values.append(None) continue cumulative_number_min = cumulative_occurrence_model_2( mag_arr, maxmag, slipratemi, b_value, fault_area) / catalog_time_span cumulative_number_max = cumulative_occurrence_model_2( mag_arr, maxmag, slipratema, b_value, fault_area) / catalog_time_span # use a value computed with max of slip rate a_value_min = computeAValueFromOccurrence( numpy.log10(cumulative_number_min[0]), b_value, MAGNITUDE_MIN) a_value_max = computeAValueFromOccurrence( numpy.log10(cumulative_number_max[0]), b_value, MAGNITUDE_MIN) # compute contribution to total seismic moment # TODO(fab): double-check scaling with Laurentiu! # shear modulus: Pa = N / m^2 = kg / (m * s^2) = kg / (10^-3 km * s^2) # 1 kg / (km * s^2) = 10^3 N # slip rate: mm / year # area: m^2 # moment rate unit: Nm / (year * km^2) # kg * 10^-3 m * m^2 / (m * s^2 * 365.25*24*60*60 s) # = 10^3 N * 10^-3 m^3 / (10^-3 * [year] s)) # = 10^3 Nm * m^2 / [year] s <- divide this by area in metres (?) # kg m^3 / (m s^3) = kg m^2 / s^3 (seismic_moment_rate_min, seismic_moment_rate_max) = \ momentrate.momentrateFromSlipRate(slipratemi, slipratema, fault_area) # serialize activity rate FMD for value_pair_idx in xrange(mag_arr.shape[0]): zone_data_string_min = "%s %.1f %.2e" % ( zone_data_string_min, mag_arr[value_pair_idx], cumulative_number_min[value_pair_idx]) zone_data_string_max = "%s %.1f %.2e" % ( zone_data_string_max, mag_arr[value_pair_idx], cumulative_number_max[value_pair_idx]) attribute_list = [] if activity_back['fbz']['ID'] is None: fbz_id = activity_back['fbz']['ID'] else: fbz_id = str(activity_back['fbz']['ID']) attribute_list.append(fbz_id) attribute_list.extend( checkAndCastActivityResult(activity_back['fbz']['activity'])) attribute_list.extend( checkAndCastActivityResult(activity_back['bz']['activity'])) attribute_list.append(float(m_threshold)) attribute_list.extend( checkAndCastActivityResult(activity_back['fbz_below']['activity'])) attribute_list.extend( checkAndCastActivityResult(activity_back['fbz_above']['activity'])) attribute_list.extend([numpy.nan] * 4) # ML, Mmax attribute_list.extend([float(a_value_min), float(a_value_max)]) attribute_list.extend([numpy.nan] * 3) # three momentrate components attribute_list.extend([ float(seismic_moment_rate_min), float(seismic_moment_rate_max), zone_data_string_min.lstrip(), zone_data_string_max.lstrip() ]) result_values.append(attribute_list) return result_values
def computeActivityFromBackground(feature, layer_fault_background, layer_background, catalog, mmin=atticivy.ATTICIVY_MMIN, m_threshold=FAULT_BACKGROUND_MAG_THRESHOLD, mindepth=eqcatalog.CUT_DEPTH_MIN, maxdepth=eqcatalog.CUT_DEPTH_MAX, ui_mode=True): """Compute activity parameters a and b for (i) fault background zone, and (ii) from buffer zone around fault zone. Input: feature fault source zone layer_fault_background layer_background catalog mmin Output: TODO(fab) """ activity = {} provider_fault_back = layer_fault_background.dataProvider() provider_back = layer_background.dataProvider() # get Shapely polygon from fault zone feature geometry polylist, vertices = utils.polygonsQGS2Shapely((feature, )) try: fault_poly = polylist[0] except IndexError: error_msg = "Background activity: invalid FSZ geometry, id %s" % ( feature.id()) if ui_mode is True: QMessageBox.warning(None, "FSZ Warning", error_msg) else: print error_msg return None # get buffer zone around fault zone (convert buffer distance to degrees) (bz_poly, bz_area) = utils.computeBufferZone(fault_poly, momentrate.BUFFER_AROUND_FAULT_ZONE_KM) # find fault background zone in which centroid of fault zone lies # NOTE: this can yield a wrong background zone if the fault zone # is curved and at the edge of background zone. # TODO(fab): use GIS "within" function instead, but note that fault # zone can overlap several BG zones (fbz, fbz_poly, fbz_area) = utils.findBackgroundZone(fault_poly.centroid, provider_fault_back, ui_mode=ui_mode) if fbz is None: error_msg = "Recurrence: could not determine FBZ for zone %s" % ( feature.id()) if ui_mode is True: QMessageBox.warning(None, "Recurrence Warning", error_msg) else: print error_msg fbz_id = None else: attribute_map_fbz = utils.getAttributeIndex( provider_fault_back, (features.FAULT_BACKGROUND_ATTR_ID, ), create=False) # get fault background zone ID id_name = features.FAULT_BACKGROUND_ATTR_ID['name'] fbz_id = int(fbz[attribute_map_fbz[id_name][0]].toDouble()[0]) # get mmax and mcdist for FBZ from background zone (mcdist_qv, mmax_qv) = areasource.getAttributesFromBackgroundZones( fbz_poly.centroid, provider_back, areasource.MCDIST_MMAX_ATTRIBUTES, ui_mode=ui_mode) if mcdist_qv is None or mmax_qv is None: error_msg = "Recurrence: could not determine mcdist or mmax for "\ "zone %s" % (feature.id()) if ui_mode is True: QMessageBox.warning(None, "Recurrence Warning", error_msg) else: print error_msg return None else: mmax = float(mmax_qv.toDouble()[0]) mcdist = str(mcdist_qv.toString()) ## moment rate from activity (RM) # a and b value from FBZ # cut catalog with depth constraint cat_cut = QPCatalog.QPCatalog() cat_cut.merge(catalog) cat_cut.cut(mindepth=mindepth, maxdepth=maxdepth) activity_fbz = atticivy.computeActivityAtticIvy((fbz_poly, ), (mmax, ), (mcdist, ), cat_cut, mmin=mmin, ui_mode=ui_mode) activity['fbz'] = { 'ID': fbz_id, 'area': fbz_area, 'activity': activity_fbz[0] } # get separate catalogs below and above magnitude threshold cat_below_threshold = QPCatalog.QPCatalog() cat_below_threshold.merge(cat_cut) cat_below_threshold.cut(maxmag=m_threshold, maxmag_excl=True) cat_above_threshold = QPCatalog.QPCatalog() cat_above_threshold.merge(cat_cut) cat_above_threshold.cut(minmag=m_threshold, maxmag_excl=False) activity_below_threshold = atticivy.computeActivityAtticIvy( (fbz_poly, ), (mmax, ), (mcdist, ), cat_below_threshold, mmin=mmin, ui_mode=ui_mode) activity['fbz_below'] = { 'ID': fbz_id, 'area': fbz_area, 'activity': activity_below_threshold[0] } activity_above_threshold = atticivy.computeActivityAtticIvy( (fbz_poly, ), (mmax, ), (mcdist, ), cat_above_threshold, mmin=mmin, ui_mode=ui_mode) activity['fbz_above'] = { 'ID': fbz_id, 'area': fbz_area, 'activity': activity_above_threshold[0] } # a and b value on buffer zone activity_bz = atticivy.computeActivityAtticIvy((bz_poly, ), (mmax, ), (mcdist, ), cat_cut, mmin, ui_mode=ui_mode) activity['bz'] = {'area': bz_area, 'activity': activity_bz[0]} activity['background'] = {'mmax': mmax, 'mcdist': mcdist} return activity
def computeRecurrence(layer_fault, layer_fault_background=None, layer_background=None, catalog=None, catalog_time_span=None, b_value=None, mmin=atticivy.ATTICIVY_MMIN, m_threshold=FAULT_BACKGROUND_MAG_THRESHOLD, mindepth=eqcatalog.CUT_DEPTH_MIN, maxdepth=eqcatalog.CUT_DEPTH_MAX, ui_mode=True): """Compute recurrence parameters according to Bungum paper. Parameters from Jochen's Matlab implementation: % rParams.fBvalue : b-value % rParams.fS : Slip rate (mm/year) % rParams.fD : Average slip (m) % rParams.fLength : Fault length (m) % rParams.fWidth : Fault width (m) % rParams.fM00 : M0(0) for Ms = 0, c in logM0=c-dM % rParams.fMmin : Minimum magnitude % rParams.fBinM : magnitude binnning % rParams.fMmax : Maximum magnitude % rParams.fDmoment : d in logM0=c-dM % rParams.fRigid : Rgidity in Pascal rParams.fBvalue = 1; rParams.fS = 1e-3; rParams.fD = 1; rParams.fLength = 100000; rParams.fWidth = 50000; rParams.fM00 = 16.05; rParams.fMmin = 5; rParams.fBinM = 0.1; rParams.fMmax = 8; rParams.fDmoment = 1.5; rParams.fRigid = 30e+6; """ result_values = [] provider_fault = layer_fault.dataProvider() fts = layer_fault.selectedFeatures() # loop over fault polygons for zone_idx, feature in enumerate(fts): # collect the following attribute data: # - FBZ zone ID # - (a, b, act_a, act_b) for FBZ # - (a, b, act_a, act_b) for buffer zone # - m_threshold # - (a, b, act_a, act_b) for FBZ, below magnitude threshold # - (a, b, act_a, act_b) for FBZ, above magnitude threshold # - (a, b, Mc) from maximum likelihood G-R # - Mmax from background # - a from slip rate (min/max) # - activity rate (min/max) # - moment rate (min/max) zone_data_string_min = "" zone_data_string_max = "" if ui_mode is False: print "\n=== Processing FSZ feature, id %s ===" % feature.id() # get parameters from background zones activity_back = computeActivityFromBackground(feature, layer_fault_background, layer_background, catalog, mmin, m_threshold, mindepth, maxdepth, ui_mode=ui_mode) if activity_back is None: result_values.append(None) continue # get attribute values of zone: # - MAXMAG, SLIPRATEMI, SLIPRATEMA attribute_map_fault = utils.getAttributeIndex(provider_fault, features.FAULT_SOURCE_ATTRIBUTES_RECURRENCE, create=True) # get maximum magnitude (Note: it's int in feature attributes) maxmag_name = features.FAULT_SOURCE_ATTR_MAGNITUDE_MAX['name'] maxmag = feature[attribute_map_fault[maxmag_name][0]].toDouble()[0] # get minimum of annual slip rate slipratemi_name = features.FAULT_SOURCE_ATTR_SLIPRATE_MIN['name'] slipratemi = \ feature[attribute_map_fault[slipratemi_name][0]].toDouble()[0] # get maximum of annual slip rate slipratema_name = features.FAULT_SOURCE_ATTR_SLIPRATE_MAX['name'] slipratema = \ feature[attribute_map_fault[slipratema_name][0]].toDouble()[0] # get area of fault zone polylist, vertices = utils.polygonsQGS2Shapely((feature,)) fault_poly = polylist[0] fault_area = utils.polygonAreaFromWGS84(fault_poly) # determine b value that is used in further computations # - use b value computed on fault background zone if b_value is None: b_value = activity_back['fbz']['activity'][atticivy.ATTICIVY_B_IDX] # equidistant magnitude array on which activity rates are computed # from global Mmin to zone-dependent Mmax mag_arr = numpy.arange(MAGNITUDE_MIN, maxmag, MAGNITUDE_BINNING) if len(mag_arr) == 0: result_values.append(None) continue cumulative_number_min = cumulative_occurrence_model_2(mag_arr, maxmag, slipratemi, b_value, fault_area) / catalog_time_span cumulative_number_max = cumulative_occurrence_model_2(mag_arr, maxmag, slipratema, b_value, fault_area) / catalog_time_span # use a value computed with max of slip rate a_value_min = computeAValueFromOccurrence( numpy.log10(cumulative_number_min[0]), b_value, MAGNITUDE_MIN) a_value_max = computeAValueFromOccurrence( numpy.log10(cumulative_number_max[0]), b_value, MAGNITUDE_MIN) # compute contribution to total seismic moment # TODO(fab): double-check scaling with Laurentiu! # shear modulus: Pa = N / m^2 = kg / (m * s^2) = kg / (10^-3 km * s^2) # 1 kg / (km * s^2) = 10^3 N # slip rate: mm / year # area: m^2 # moment rate unit: Nm / (year * km^2) # kg * 10^-3 m * m^2 / (m * s^2 * 365.25*24*60*60 s) # = 10^3 N * 10^-3 m^3 / (10^-3 * [year] s)) # = 10^3 Nm * m^2 / [year] s <- divide this by area in metres (?) # kg m^3 / (m s^3) = kg m^2 / s^3 (seismic_moment_rate_min, seismic_moment_rate_max) = \ momentrate.momentrateFromSlipRate(slipratemi, slipratema, fault_area) # serialize activity rate FMD for value_pair_idx in xrange(mag_arr.shape[0]): zone_data_string_min = "%s %.1f %.2e" % (zone_data_string_min, mag_arr[value_pair_idx], cumulative_number_min[value_pair_idx]) zone_data_string_max = "%s %.1f %.2e" % (zone_data_string_max, mag_arr[value_pair_idx], cumulative_number_max[value_pair_idx]) attribute_list = [] if activity_back['fbz']['ID'] is None: fbz_id = activity_back['fbz']['ID'] else: fbz_id = str(activity_back['fbz']['ID']) attribute_list.append(fbz_id) attribute_list.extend(checkAndCastActivityResult( activity_back['fbz']['activity'])) attribute_list.extend(checkAndCastActivityResult( activity_back['bz']['activity'])) attribute_list.append(float(m_threshold)) attribute_list.extend(checkAndCastActivityResult( activity_back['fbz_below']['activity'])) attribute_list.extend(checkAndCastActivityResult( activity_back['fbz_above']['activity'])) attribute_list.extend([numpy.nan] * 4) # ML, Mmax attribute_list.extend([float(a_value_min), float(a_value_max)]) attribute_list.extend([numpy.nan] * 3) # three momentrate components attribute_list.extend([ float(seismic_moment_rate_min), float(seismic_moment_rate_max), zone_data_string_min.lstrip(), zone_data_string_max.lstrip()]) result_values.append(attribute_list) return result_values
def computeActivityFromBackground(feature, layer_fault_background, layer_background, catalog, mmin=atticivy.ATTICIVY_MMIN, m_threshold=FAULT_BACKGROUND_MAG_THRESHOLD, mindepth=eqcatalog.CUT_DEPTH_MIN, maxdepth=eqcatalog.CUT_DEPTH_MAX, ui_mode=True): """Compute activity parameters a and b for (i) fault background zone, and (ii) from buffer zone around fault zone. Input: feature fault source zone layer_fault_background layer_background catalog mmin Output: TODO(fab) """ activity = {} provider_fault_back = layer_fault_background.dataProvider() provider_back = layer_background.dataProvider() # get Shapely polygon from fault zone feature geometry polylist, vertices = utils.polygonsQGS2Shapely((feature,)) try: fault_poly = polylist[0] except IndexError: error_msg = "Background activity: invalid FSZ geometry, id %s" % ( feature.id()) if ui_mode is True: QMessageBox.warning(None, "FSZ Warning", error_msg) else: print error_msg return None # get buffer zone around fault zone (convert buffer distance to degrees) (bz_poly, bz_area) = utils.computeBufferZone(fault_poly, momentrate.BUFFER_AROUND_FAULT_ZONE_KM) # find fault background zone in which centroid of fault zone lies # NOTE: this can yield a wrong background zone if the fault zone # is curved and at the edge of background zone. # TODO(fab): use GIS "within" function instead, but note that fault # zone can overlap several BG zones (fbz, fbz_poly, fbz_area) = utils.findBackgroundZone(fault_poly.centroid, provider_fault_back, ui_mode=ui_mode) if fbz is None: error_msg = "Recurrence: could not determine FBZ for zone %s" % ( feature.id()) if ui_mode is True: QMessageBox.warning(None, "Recurrence Warning", error_msg) else: print error_msg fbz_id = None else: attribute_map_fbz = utils.getAttributeIndex(provider_fault_back, (features.FAULT_BACKGROUND_ATTR_ID,), create=False) # get fault background zone ID id_name = features.FAULT_BACKGROUND_ATTR_ID['name'] fbz_id = int(fbz[attribute_map_fbz[id_name][0]].toDouble()[0]) # get mmax and mcdist for FBZ from background zone (mcdist_qv, mmax_qv) = areasource.getAttributesFromBackgroundZones( fbz_poly.centroid, provider_back, areasource.MCDIST_MMAX_ATTRIBUTES, ui_mode=ui_mode) if mcdist_qv is None or mmax_qv is None: error_msg = "Recurrence: could not determine mcdist or mmax for "\ "zone %s" % (feature.id()) if ui_mode is True: QMessageBox.warning(None, "Recurrence Warning", error_msg) else: print error_msg return None else: mmax = float(mmax_qv.toDouble()[0]) mcdist = str(mcdist_qv.toString()) ## moment rate from activity (RM) # a and b value from FBZ # cut catalog with depth constraint cat_cut = QPCatalog.QPCatalog() cat_cut.merge(catalog) cat_cut.cut(mindepth=mindepth, maxdepth=maxdepth) activity_fbz = atticivy.computeActivityAtticIvy((fbz_poly,), (mmax,), (mcdist,), cat_cut, mmin=mmin, ui_mode=ui_mode) activity['fbz'] = {'ID': fbz_id, 'area': fbz_area, 'activity': activity_fbz[0]} # get separate catalogs below and above magnitude threshold cat_below_threshold = QPCatalog.QPCatalog() cat_below_threshold.merge(cat_cut) cat_below_threshold.cut(maxmag=m_threshold, maxmag_excl=True) cat_above_threshold = QPCatalog.QPCatalog() cat_above_threshold.merge(cat_cut) cat_above_threshold.cut(minmag=m_threshold, maxmag_excl=False) activity_below_threshold = atticivy.computeActivityAtticIvy( (fbz_poly,), (mmax,), (mcdist,), cat_below_threshold, mmin=mmin, ui_mode=ui_mode) activity['fbz_below'] = {'ID': fbz_id, 'area': fbz_area, 'activity': activity_below_threshold[0]} activity_above_threshold = atticivy.computeActivityAtticIvy( (fbz_poly,), (mmax,), (mcdist,), cat_above_threshold, mmin=mmin, ui_mode=ui_mode) activity['fbz_above'] = {'ID': fbz_id, 'area': fbz_area, 'activity': activity_above_threshold[0]} # a and b value on buffer zone activity_bz = atticivy.computeActivityAtticIvy((bz_poly,), (mmax,), (mcdist,), cat_cut, mmin, ui_mode=ui_mode) activity['bz'] = {'area': bz_area, 'activity': activity_bz[0]} activity['background'] = {'mmax': mmax, 'mcdist': mcdist} return activity
def updateDataArea(cls, feature): """Update or compute moment rates for selected feature of area source zone layer. Input: feature QGis polygon feature from area source layer Output: parameters dict of computed parameters """ provider = cls.area_source_layer.dataProvider() parameters = {} # get Shapely polygon from feature geometry polylist, vertices = utils.polygonsQGS2Shapely((feature,)) poly = polylist[0] # get polygon area in square kilometres parameters["area_sqkm"] = utils.polygonAreaFromWGS84(poly) * 1.0e-6 # zone ID and title (feature_id, feature_title, feature_name) = utils.getFeatureAttributes( cls.area_source_layer, feature, features.AREA_SOURCE_ATTRIBUTES_ID ) if feature_title.toString() == "" and feature_name.toString() == "": zone_name_str = "" elif feature_title.toString() == "" and feature_name.toString() != "": zone_name_str = feature_name.toString() elif feature_title.toString() != "" and feature_name.toString() == "": zone_name_str = feature_title.toString() else: zone_name_str = "%s, %s" % (feature_title.toString(), feature_name.toString()) parameters["plot_title_fmd"] = "Zone %s, %s" % (feature_id.toInt()[0], zone_name_str) ## moment rate from EQs # get quakes from catalog (cut with polygon) poly_cat = QPCatalog.QPCatalog() poly_cat.merge(cls.catalog) poly_cat.cut(geometry=poly) # cut catalog with min/max depth according to UI spinboxes (mindepth, maxdepth) = eqcatalog.getMinMaxDepth(cls) poly_cat.cut(mindepth=mindepth, maxdepth=maxdepth) parameters["eq_count"] = poly_cat.size() # sum up moment from quakes (converted from Mw with Kanamori eq.) magnitudes = [] for ev in poly_cat.eventParameters.event: mag = ev.getPreferredMagnitude() magnitudes.append(mag.mag.value) moment = numpy.array(momentrate.magnitude2moment(magnitudes)) # scale moment: per year and area (in km^2) parameters["mr_eq"] = moment.sum() / (parameters["area_sqkm"] * cls.catalog_time_span[0]) ## moment rate from activity (RM) # get attribute index of AtticIvy result attribute_map = utils.getAttributeIndex( provider, (features.AREA_SOURCE_ATTR_ACT_RM_A, features.AREA_SOURCE_ATTR_ACT_RM_B, features.AREA_SOURCE_ATTR_MMAX), ) attribute_act_a_name = features.AREA_SOURCE_ATTR_ACT_RM_A["name"] attribute_act_a_idx = attribute_map[attribute_act_a_name][0] attribute_act_b_name = features.AREA_SOURCE_ATTR_ACT_RM_B["name"] attribute_act_b_idx = attribute_map[attribute_act_b_name][0] attribute_mmax_name = features.AREA_SOURCE_ATTR_MMAX["name"] attribute_mmax_idx = attribute_map[attribute_mmax_name][0] # get RM (a, b) values from feature attributes try: activity_a_str = str(feature[attribute_act_a_idx].toString()) activity_a_arr = activity_a_str.strip().split() except KeyError: activity_a_arr = 3 * [numpy.nan] error_msg = "Moment balancing: no valid activity a parameter in %s" % (parameters["plot_title_fmd"]) QMessageBox.warning(None, "Moment balancing warning", error_msg) try: activity_b_str = str(feature[attribute_act_b_idx].toString()) activity_b_arr = activity_b_str.strip().split() except KeyError: activity_b_arr = 3 * [numpy.nan] error_msg = "Moment balancing: no valid activity b parameter in %s" % (parameters["plot_title_fmd"]) QMessageBox.warning(None, "Moment balancing warning", error_msg) # ignore weights parameters["activity_mmin"] = atticivy.ATTICIVY_MMIN activity_a = [float(x) for x in activity_a_arr] activity_b = [float(x) for x in activity_b_arr] mmax = float(feature[attribute_mmax_idx].toDouble()[0]) parameters["activity_a"] = activity_a parameters["activity_b"] = activity_b parameters["mmax"] = mmax ## Maximum likelihood a/b values if poly_cat.size() == 0: cls.feature_data_area_source["fmd"] = None (parameters["ml_a"], parameters["ml_b"], parameters["ml_mc"], parameters["ml_magctr"]) = 4 * [numpy.nan] error_msg = "Moment balancing: no EQs in %s" % (parameters["plot_title_fmd"]) QMessageBox.warning(None, "Moment balancing warning", error_msg) else: cls.feature_data_area_source["fmd"] = fmd.computeZoneFMD(cls, feature, poly_cat) (parameters["ml_a"], parameters["ml_b"], parameters["ml_mc"], parameters["ml_magctr"]) = fmd.getFMDValues( cls.feature_data_area_source["fmd"] ) ## moment rate from activity a_values = activity_a momentrates_arr = ( numpy.array(momentrate.momentrateFromActivity(a_values, activity_b, mmax)) / cls.catalog_time_span[0] ) parameters["mr_activity"] = momentrates_arr.tolist() ## moment rate from geodesy (strain) momentrate_strain_barba = momentrate.momentrateFromStrainRateBarba( poly, cls.data.strain_rate_barba, cls.data.deformation_regimes_bird ) parameters["mr_strain_barba"] = momentrate_strain_barba / (cls.catalog_time_span[0]) momentrate_strain_bird = momentrate.momentrateFromStrainRateBird( poly, cls.data.strain_rate_bird, cls.data.deformation_regimes_bird ) parameters["mr_strain_bird"] = momentrate_strain_bird / (cls.catalog_time_span[0]) return parameters
def updateDataFaultBackgr(cls, feature, m_threshold=recurrence.FAULT_BACKGROUND_MAG_THRESHOLD ): """Update or compute moment rates for selected feature of fault background zone layer. Input: feature QGis polygon feature from fault background zone layer Output: parameters dict of computed parameters """ provider = cls.fault_background_layer.dataProvider() provider_fault = cls.fault_source_layer.dataProvider() provider_area = cls.area_source_layer.dataProvider() provider_back = cls.background_zone_layer.dataProvider() parameters = {} # get Shapely polygon from feature geometry polylist, vertices = utils.polygonsQGS2Shapely((feature, )) poly = polylist[0] # get polygon area in square kilometres parameters['area_background_sqkm'] = \ utils.polygonAreaFromWGS84(poly) * 1.0e-6 # get mmax and mcdist for FBZ from background zone (mcdist_qv, mmax_qv) = areasource.getAttributesFromBackgroundZones( poly.centroid, provider_back, areasource.MCDIST_MMAX_ATTRIBUTES) mmax = float(mmax_qv.toDouble()[0]) mcdist = str(mcdist_qv.toString()) parameters['mmax'] = mmax ## moment rate from EQs # get quakes from catalog (cut with fault background zone polygon) poly_cat = QPCatalog.QPCatalog() poly_cat.merge(cls.catalog) poly_cat.cut(geometry=poly) # cut catalog with min/max depth according to UI spinboxes (mindepth, maxdepth) = eqcatalog.getMinMaxDepth(cls) poly_cat.cut(mindepth=mindepth, maxdepth=maxdepth) parameters['eq_count'] = poly_cat.size() # sum up moment from quakes (converted from Mw with Kanamori eq.) magnitudes = [] for ev in poly_cat.eventParameters.event: mag = ev.getPreferredMagnitude() magnitudes.append(mag.mag.value) moment = numpy.array(momentrate.magnitude2moment(magnitudes)) # scale moment: per year and area (in km^2) parameters['mr_eq'] = moment.sum() / (parameters['area_background_sqkm'] * cls.catalog_time_span[0]) ## moment rate from activity (RM) parameters['activity_mmin'] = atticivy.ATTICIVY_MMIN activity = atticivy.computeActivityAtticIvy( (poly, ), (mmax, ), (mcdist, ), cls.catalog, mmin=parameters['activity_mmin']) # get RM (a, b) values from feature attribute activity_str_a = activity[0][3] activity_arr_a = activity_str_a.strip().split() activity_str_b = activity[0][4] activity_arr_b = activity_str_b.strip().split() # ignore weights activity_a = [float(x) for x in activity_arr_a] activity_b = [float(x) for x in activity_arr_b] parameters['activity_a'] = activity_a parameters['activity_b'] = activity_b a_values = activity_a momentrates_arr = numpy.array( momentrate.momentrateFromActivity(a_values, activity_b, mmax)) / cls.catalog_time_span[0] parameters['mr_activity'] = momentrates_arr.tolist() # get separate catalogs below and above magnitude threshold cat_below_threshold = QPCatalog.QPCatalog() cat_below_threshold.merge(poly_cat) cat_below_threshold.cut(maxmag=m_threshold, maxmag_excl=True) parameters['eq_count_below'] = cat_below_threshold.size() cat_above_threshold = QPCatalog.QPCatalog() cat_above_threshold.merge(poly_cat) cat_above_threshold.cut(minmag=m_threshold, maxmag_excl=False) parameters['eq_count_above'] = cat_above_threshold.size() activity_below_threshold = atticivy.computeActivityAtticIvy( (poly, ), (mmax, ), (mcdist, ), cat_below_threshold, mmin=parameters['activity_mmin']) activity_above_threshold = atticivy.computeActivityAtticIvy( (poly, ), (mmax, ), (mcdist, ), cat_above_threshold, mmin=parameters['activity_mmin']) # get RM (weight, a, b) values from feature attribute activity_below_str_a = activity_below_threshold[0][3] activity_below_arr_a = activity_below_str_a.strip().split() activity_below_str_b = activity_below_threshold[0][4] activity_below_arr_b = activity_below_str_b.strip().split() activity_above_str_a = activity_above_threshold[0][3] activity_above_arr_a = activity_above_str_a.strip().split() activity_above_str_b = activity_above_threshold[0][4] activity_above_arr_b = activity_above_str_b.strip().split() # ignore weights activity_below_a = [float(x) for x in activity_below_arr_a] activity_below_b = [float(x) for x in activity_below_arr_b] activity_above_a = [float(x) for x in activity_above_arr_a] activity_above_b = [float(x) for x in activity_above_arr_b] a_values_below = activity_below_a momentrates_below_arr = numpy.array( momentrate.momentrateFromActivity(a_values_below, activity_below_b, mmax)) / cls.catalog_time_span[0] a_values_above = activity_above_a momentrates_above_arr = numpy.array( momentrate.momentrateFromActivity(a_values_above, activity_above_b, mmax)) / cls.catalog_time_span[0] parameters['activity_below_a'] = activity_below_a parameters['activity_below_b'] = activity_below_b parameters['activity_above_a'] = activity_above_a parameters['activity_above_b'] = activity_above_b parameters['mr_activity_below'] = momentrates_below_arr.tolist() parameters['mr_activity_above'] = momentrates_above_arr.tolist() parameters['activity_m_threshold'] = m_threshold # FMD from quakes in FBZ cls.feature_data_fault_background['fmd'] = fmd.computeZoneFMD( cls, feature, poly_cat) (parameters['ml_a'], parameters['ml_b'], parameters['ml_mc'], parameters['ml_magctr']) = fmd.getFMDValues( cls.feature_data_fault_background['fmd']) ## moment rate from slip rate sliprate_min_name = features.FAULT_SOURCE_ATTR_SLIPRATE_MIN['name'] sliprate_max_name = features.FAULT_SOURCE_ATTR_SLIPRATE_MAX['name'] attribute_map = utils.getAttributeIndex( provider_fault, (features.FAULT_SOURCE_ATTR_SLIPRATE_MIN, features.FAULT_SOURCE_ATTR_SLIPRATE_MAX), create=False) moment_rate_min = 0.0 moment_rate_max = 0.0 parameters['area_fault_sqkm'] = 0.0 parameters['fault_count'] = 0 provider_fault.rewind() for fault in provider_fault: fault_poly, vertices = utils.polygonsQGS2Shapely((fault, )) if fault_poly[0].intersects(poly): parameters['fault_count'] += 1 sliprate_min = \ fault[attribute_map[sliprate_min_name][0]].toDouble()[0] sliprate_max = \ fault[attribute_map[sliprate_max_name][0]].toDouble()[0] area_fault = utils.polygonAreaFromWGS84(fault_poly[0]) # TODO(fab): correct scaling of moment rate from slip rate (rate_min, rate_max) = momentrate.momentrateFromSlipRate( sliprate_min, sliprate_max, area_fault) moment_rate_min += rate_min moment_rate_max += rate_max parameters['area_fault_sqkm'] += area_fault moment_rate_min /= cls.catalog_time_span[0] moment_rate_max /= cls.catalog_time_span[0] parameters['mr_slip'] = [moment_rate_min, moment_rate_max] parameters['area_fault_sqkm'] *= 1.0e-6 ## moment rate from geodesy (strain) momentrate_strain_barba = momentrate.momentrateFromStrainRateBarba( poly, cls.data.strain_rate_barba, cls.data.deformation_regimes_bird) parameters['mr_strain_barba'] = momentrate_strain_barba / ( cls.catalog_time_span[0]) momentrate_strain_bird = momentrate.momentrateFromStrainRateBird( poly, cls.data.strain_rate_bird, cls.data.deformation_regimes_bird) parameters['mr_strain_bird'] = momentrate_strain_bird / ( cls.catalog_time_span[0]) return parameters
def getAttributesFromRecurrence(provider, feature): """Read recurrence attributes from fault layer.""" parameters = {} attribute_map_fault = utils.getAttributeIndex(provider, features.FAULT_SOURCE_ATTRIBUTES_RECURRENCE, create=False) # get fault background zone ID id_name = features.FAULT_SOURCE_ATTR_ID_FBZ['name'] try: parameters['fbz_id'] = str( feature[attribute_map_fault[id_name][0]].toString()) except KeyError: error_msg = "No recurrence data for zone %s" % (feature.id()) QMessageBox.warning(None, "Missing Data", error_msg) return None # a and b value from FBZ (fault layer attributes) a_fbz_name = features.FAULT_SOURCE_ATTR_A_FBZ['name'] b_fbz_name = features.FAULT_SOURCE_ATTR_B_FBZ['name'] parameters['activity_fbz_a'] = \ feature[attribute_map_fault[a_fbz_name][0]].toDouble()[0] parameters['activity_fbz_b'] = \ feature[attribute_map_fault[b_fbz_name][0]].toDouble()[0] act_fbz_a_name = features.FAULT_SOURCE_ATTR_ACT_FBZ_A['name'] act_fbz_b_name = features.FAULT_SOURCE_ATTR_ACT_FBZ_B['name'] parameters['activity_fbz_act_a'] = str( feature[attribute_map_fault[act_fbz_a_name][0]].toString()) parameters['activity_fbz_act_b'] = str( feature[attribute_map_fault[act_fbz_b_name][0]].toString()) # a and b value from buffer zone (fault layer attributes) a_bz_name = features.FAULT_SOURCE_ATTR_A_BUF['name'] b_bz_name = features.FAULT_SOURCE_ATTR_B_BUF['name'] parameters['activity_bz_a'] = \ feature[attribute_map_fault[a_bz_name][0]].toDouble()[0] parameters['activity_bz_b'] = \ feature[attribute_map_fault[b_bz_name][0]].toDouble()[0] act_bz_a_name = features.FAULT_SOURCE_ATTR_ACT_BUF_A['name'] act_bz_b_name = features.FAULT_SOURCE_ATTR_ACT_BUF_B['name'] parameters['activity_bz_act_a'] = str( feature[attribute_map_fault[act_bz_a_name][0]].toString()) parameters['activity_bz_act_b'] = str( feature[attribute_map_fault[act_bz_b_name][0]].toString()) # a and b value from FBZ, above magnitude threshold a_fbz_at_name = features.FAULT_SOURCE_ATTR_A_FBZ_AT['name'] b_fbz_at_name = features.FAULT_SOURCE_ATTR_B_FBZ_AT['name'] parameters['activity_fbz_at_a'] = \ feature[attribute_map_fault[a_fbz_at_name][0]].toDouble()[0] parameters['activity_fbz_at_b'] = \ feature[attribute_map_fault[b_fbz_at_name][0]].toDouble()[0] act_fbz_at_a_name = features.FAULT_SOURCE_ATTR_ACT_FBZ_AT_A['name'] act_fbz_at_b_name = features.FAULT_SOURCE_ATTR_ACT_FBZ_AT_B['name'] parameters['activity_fbz_at_act_a'] = str( feature[attribute_map_fault[act_fbz_at_a_name][0]].toString()) parameters['activity_fbz_at_act_b'] = str( feature[attribute_map_fault[act_fbz_at_b_name][0]].toString()) # a values from recurrence (fault layer attributes) a_rec_min_name = features.FAULT_SOURCE_ATTR_A_REC_MIN['name'] a_rec_max_name = features.FAULT_SOURCE_ATTR_A_REC_MAX['name'] parameters['activity_rec_a_min'] = \ feature[attribute_map_fault[a_rec_min_name][0]].toDouble()[0] parameters['activity_rec_a_max'] = \ feature[attribute_map_fault[a_rec_max_name][0]].toDouble()[0] sliprate_min_name = features.FAULT_SOURCE_ATTR_SLIPRATE_MIN['name'] sliprate_max_name = features.FAULT_SOURCE_ATTR_SLIPRATE_MAX['name'] mmax_fault_name = features.FAULT_SOURCE_ATTR_MAGNITUDE_MAX['name'] parameters['sliprate_min'] = \ feature[attribute_map_fault[sliprate_min_name][0]].toDouble()[0] parameters['sliprate_max'] = \ feature[attribute_map_fault[sliprate_max_name][0]].toDouble()[0] parameters['mmax_fault'] = \ feature[attribute_map_fault[mmax_fault_name][0]].toDouble()[0] return parameters