Beispiel #1
0
def computeZoneFMD(cls, feature, catalog=None):
    """Compute FMD for selected feature."""

    if catalog is None:
        # cut catalog to feature
        polylist, vertices = utils.polygonsQGS2Shapely((feature,))
        poly = polylist[0]
    
        # cut catalog with selected polygon
        catalog = QPCatalog.QPCatalog()
        catalog.merge(cls.catalog)
        catalog.cut(geometry=poly)
        
        # cut catalog with min/max depth according to UI spinboxes
        (mindepth, maxdepth) = eqcatalog.getMinMaxDepth(cls)
        catalog.cut(mindepth=mindepth, maxdepth=maxdepth)

    # Mc method
    if unicode(cls.comboBoxMcMethod.currentText()) == 'userDefined':
        mc = cls.spinboxFMDMcMethod.value()
    else:
        mc = unicode(cls.comboBoxMcMethod.currentText())
        
    return FMDMulti(catalog.eventParameters, Mc=mc, 
        minEventsGR=MIN_EVENTS_FOR_GR, time_span=cls.catalog_time_span[0])
Beispiel #2
0
def computeZoneFMD(cls, feature, catalog=None):
    """Compute FMD for selected feature."""

    if catalog is None:
        # cut catalog to feature
        polylist, vertices = utils.polygonsQGS2Shapely((feature, ))
        poly = polylist[0]

        # cut catalog with selected polygon
        catalog = QPCatalog.QPCatalog()
        catalog.merge(cls.catalog)
        catalog.cut(geometry=poly)

        # cut catalog with min/max depth according to UI spinboxes
        (mindepth, maxdepth) = eqcatalog.getMinMaxDepth(cls)
        catalog.cut(mindepth=mindepth, maxdepth=maxdepth)

    # Mc method
    if unicode(cls.comboBoxMcMethod.currentText()) == 'userDefined':
        mc = cls.spinboxFMDMcMethod.value()
    else:
        mc = unicode(cls.comboBoxMcMethod.currentText())

    return FMDMulti(catalog.eventParameters,
                    Mc=mc,
                    minEventsGR=MIN_EVENTS_FOR_GR,
                    time_span=cls.catalog_time_span[0])
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 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 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
Beispiel #6
0
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 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 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
Beispiel #11
0
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
Beispiel #12
0
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
Beispiel #13
0
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
Beispiel #14
0
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
Beispiel #15
0
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