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 updateDataFault(cls, feature, m_threshold=recurrence.FAULT_BACKGROUND_MAG_THRESHOLD): """Update or compute moment rates for selected feature of fault source zone layer. Input: feature QGis polygon feature from fault source layer Output: parameters dict of computed parameters """ provider = cls.fault_source_layer.dataProvider() provider_fault_back = cls.fault_background_layer.dataProvider() provider_back = cls.background_zone_layer.dataProvider() parameters = {} # zone ID and title (feature_id, feature_name) = utils.getFeatureAttributes( cls.fault_background_layer, feature, features.FAULT_BACKGROUND_ATTRIBUTES_ID) if feature_name.toString() != '': zone_name_str = feature_name.toString() else: zone_name_str = "" parameters['plot_title_recurrence'] = 'Zone %s, %s' % ( feature_id.toString(), zone_name_str) # get Shapely polygon from feature geometry polylist, vertices = utils.polygonsQGS2Shapely((feature, )) fault_poly = polylist[0] # fault zone polygon area in square kilometres parameters['area_fault_sqkm'] = utils.polygonAreaFromWGS84( fault_poly) * 1.0e-6 # get buffer zone around fault zone (convert buffer distance to degrees) (bz_poly, parameters['area_bz_sqkm']) = 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, parameters['area_fbz_sqkm']) = utils.findBackgroundZone( fault_poly.centroid, provider_fault_back) recurrence_attributes = attributes.getAttributesFromRecurrence( provider, feature) if recurrence_attributes is not None: parameters.update(recurrence_attributes) else: return None # get mmax and mcdist for FBZ from background zone (mcdist_qv, mmax_qv) = areasource.getAttributesFromBackgroundZones( fbz_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 polygon) # cut catalog with min/max depth according to UI spinboxes (mindepth, maxdepth) = eqcatalog.getMinMaxDepth(cls) fbz_cat = QPCatalog.QPCatalog() fbz_cat.merge(cls.catalog) fbz_cat.cut(geometry=fbz_poly) fbz_cat.cut(mindepth=mindepth, maxdepth=maxdepth) bz_cat = QPCatalog.QPCatalog() bz_cat.merge(cls.catalog) bz_cat.cut(geometry=bz_poly) bz_cat.cut(mindepth=mindepth, maxdepth=maxdepth) parameters['eq_count_fbz'] = fbz_cat.size() parameters['eq_count_bz'] = bz_cat.size() # sum up moment from quakes (converted from Mw with Kanamori eq.) # use quakes in buffer zone magnitudes = [] for ev in bz_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_bz_sqkm'] * cls.catalog_time_span[0]) ## moment rate from activity (RM) # moment rates from activity: use a and b values from buffer zone act_bz_arr_a = parameters['activity_bz_act_a'].strip().split() act_bz_arr_b = parameters['activity_bz_act_b'].strip().split() a_bz_arr = [float(x) for x in act_bz_arr_a] b_bz_arr = [float(x) for x in act_bz_arr_b] a_values = a_bz_arr momentrates_arr = numpy.array( momentrate.momentrateFromActivity(a_values, b_bz_arr, mmax)) / cls.catalog_time_span[0] parameters['mr_activity'] = momentrates_arr.tolist() # moment rates from activity: use a and b values from FBZ # (above threshold) act_fbz_at_arr_a = parameters['activity_fbz_at_act_a'].strip().split() act_fbz_at_arr_b = parameters['activity_fbz_at_act_b'].strip().split() a_fbz_at_arr = [float(x) for x in act_fbz_at_arr_a] b_fbz_at_arr = [float(x) for x in act_fbz_at_arr_b] a_values = a_fbz_at_arr momentrates_fbz_at_arr = numpy.array( momentrate.momentrateFromActivity(a_values, b_fbz_at_arr, mmax)) / cls.catalog_time_span[0] parameters['mr_activity_fbz_at'] = momentrates_fbz_at_arr.tolist() parameters['activity_m_threshold'] = m_threshold # FMD from quakes in FBZ cls.feature_data_fault_source['fmd'] = fmd.computeZoneFMD( cls, feature, fbz_cat) (parameters['ml_a'], parameters['ml_b'], parameters['ml_mc'], parameters['ml_magctr']) = fmd.getFMDValues( cls.feature_data_fault_source['fmd']) ## moment rate from slip rate # TODO(fab): check correct scaling of moment rate from slip rate (moment_rate_min, moment_rate_max) = \ momentrate.momentrateFromSlipRate(parameters['sliprate_min'], parameters['sliprate_max'], parameters['area_fault_sqkm'] * 1.0e6) parameters['mr_slip'] = [moment_rate_min, moment_rate_max] return parameters
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 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 updateDataFault(cls, feature, m_threshold=recurrence.FAULT_BACKGROUND_MAG_THRESHOLD): """Update or compute moment rates for selected feature of fault source zone layer. Input: feature QGis polygon feature from fault source layer Output: parameters dict of computed parameters """ provider = cls.fault_source_layer.dataProvider() provider_fault_back = cls.fault_background_layer.dataProvider() provider_back = cls.background_zone_layer.dataProvider() parameters = {} # zone ID and title (feature_id, feature_name) = utils.getFeatureAttributes( cls.fault_background_layer, feature, features.FAULT_BACKGROUND_ATTRIBUTES_ID) if feature_name.toString() != '': zone_name_str = feature_name.toString() else: zone_name_str = "" parameters['plot_title_recurrence'] = 'Zone %s, %s' % ( feature_id.toString(), zone_name_str) # get Shapely polygon from feature geometry polylist, vertices = utils.polygonsQGS2Shapely((feature,)) fault_poly = polylist[0] # fault zone polygon area in square kilometres parameters['area_fault_sqkm'] = utils.polygonAreaFromWGS84( fault_poly) * 1.0e-6 # get buffer zone around fault zone (convert buffer distance to degrees) (bz_poly, parameters['area_bz_sqkm']) = 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, parameters['area_fbz_sqkm']) = utils.findBackgroundZone( fault_poly.centroid, provider_fault_back) recurrence_attributes = attributes.getAttributesFromRecurrence(provider, feature) if recurrence_attributes is not None: parameters.update(recurrence_attributes) else: return None # get mmax and mcdist for FBZ from background zone (mcdist_qv, mmax_qv) = areasource.getAttributesFromBackgroundZones( fbz_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 polygon) # cut catalog with min/max depth according to UI spinboxes (mindepth, maxdepth) = eqcatalog.getMinMaxDepth(cls) fbz_cat = QPCatalog.QPCatalog() fbz_cat.merge(cls.catalog) fbz_cat.cut(geometry=fbz_poly) fbz_cat.cut(mindepth=mindepth, maxdepth=maxdepth) bz_cat = QPCatalog.QPCatalog() bz_cat.merge(cls.catalog) bz_cat.cut(geometry=bz_poly) bz_cat.cut(mindepth=mindepth, maxdepth=maxdepth) parameters['eq_count_fbz'] = fbz_cat.size() parameters['eq_count_bz'] = bz_cat.size() # sum up moment from quakes (converted from Mw with Kanamori eq.) # use quakes in buffer zone magnitudes = [] for ev in bz_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_bz_sqkm'] * cls.catalog_time_span[0]) ## moment rate from activity (RM) # moment rates from activity: use a and b values from buffer zone act_bz_arr_a = parameters['activity_bz_act_a'].strip().split() act_bz_arr_b = parameters['activity_bz_act_b'].strip().split() a_bz_arr = [float(x) for x in act_bz_arr_a] b_bz_arr = [float(x) for x in act_bz_arr_b] a_values = a_bz_arr momentrates_arr = numpy.array(momentrate.momentrateFromActivity( a_values, b_bz_arr, mmax)) / cls.catalog_time_span[0] parameters['mr_activity'] = momentrates_arr.tolist() # moment rates from activity: use a and b values from FBZ # (above threshold) act_fbz_at_arr_a = parameters['activity_fbz_at_act_a'].strip().split() act_fbz_at_arr_b = parameters['activity_fbz_at_act_b'].strip().split() a_fbz_at_arr = [float(x) for x in act_fbz_at_arr_a] b_fbz_at_arr = [float(x) for x in act_fbz_at_arr_b] a_values = a_fbz_at_arr momentrates_fbz_at_arr = numpy.array(momentrate.momentrateFromActivity( a_values, b_fbz_at_arr, mmax)) / cls.catalog_time_span[0] parameters['mr_activity_fbz_at'] = momentrates_fbz_at_arr.tolist() parameters['activity_m_threshold'] = m_threshold # FMD from quakes in FBZ cls.feature_data_fault_source['fmd'] = fmd.computeZoneFMD(cls, feature, fbz_cat) (parameters['ml_a'], parameters['ml_b'], parameters['ml_mc'], parameters['ml_magctr']) = fmd.getFMDValues( cls.feature_data_fault_source['fmd']) ## moment rate from slip rate # TODO(fab): check correct scaling of moment rate from slip rate (moment_rate_min, moment_rate_max) = \ momentrate.momentrateFromSlipRate(parameters['sliprate_min'], parameters['sliprate_max'], parameters['area_fault_sqkm'] * 1.0e6) parameters['mr_slip'] = [moment_rate_min, moment_rate_max] return parameters