Ejemplo n.º 1
0
def updateLabelZoneIDFault(cls, feature):
    """Update UI with ID and name of selected FSZ."""
    (feature_id, feature_name) = utils.getFeatureAttributes(
        cls.fault_source_layer, feature, features.FAULT_SOURCE_ATTRIBUTES_ID)
    
    cls.labelMomentRateFaultID.setText("ID: %s Name: %s (%s)" % (
        feature_id.toString(), feature_name.toString(), feature.id()))
Ejemplo n.º 2
0
def updateLabelZoneIDFault(cls, feature):
    """Update UI with ID and name of selected FSZ."""
    (feature_id, feature_name) = utils.getFeatureAttributes(
        cls.fault_source_layer, feature, features.FAULT_SOURCE_ATTRIBUTES_ID)

    cls.labelMomentRateFaultID.setText(
        "ID: %s Name: %s (%s)" %
        (feature_id.toString(), feature_name.toString(), feature.id()))
Ejemplo n.º 3
0
def updateLabelZoneIDArea(cls, feature):
    """Update UI with ID and name of selected ASZ."""
    (feature_id, feature_title, feature_name) = utils.getFeatureAttributes(
        cls.area_source_layer, feature, features.AREA_SOURCE_ATTRIBUTES_ID)
    
    cls.labelMomentRateAreaID.setText("ID: %s Title: %s Name: %s (%s)" % (
        feature_id.toInt()[0], feature_title.toString(), 
        feature_name.toString(), feature.id()))
Ejemplo n.º 4
0
def updateLabelZoneIDFaultBackgr(cls, feature):
    """Update UI with ID and name of selected FBZ."""
    (feature_id, feature_name) = utils.getFeatureAttributes(
        cls.fault_background_layer, feature, 
        features.FAULT_BACKGROUND_ATTRIBUTES_ID)
    
    cls.labelMomentRateFaultBackgrID.setText("ID: %s Name: %s (%s)" % (
        int(feature_id.toDouble()[0]), feature_name.toString(), feature.id()))
Ejemplo n.º 5
0
def updateLabelZoneIDArea(cls, feature):
    """Update UI with ID and name of selected ASZ."""
    (feature_id, feature_title, feature_name) = utils.getFeatureAttributes(
        cls.area_source_layer, feature, features.AREA_SOURCE_ATTRIBUTES_ID)

    cls.labelMomentRateAreaID.setText(
        "ID: %s Title: %s Name: %s (%s)" %
        (feature_id.toInt()[0], feature_title.toString(),
         feature_name.toString(), feature.id()))
Ejemplo n.º 6
0
def updateLabelZoneIDFaultBackgr(cls, feature):
    """Update UI with ID and name of selected FBZ."""
    (feature_id, feature_name) = utils.getFeatureAttributes(
        cls.fault_background_layer, feature,
        features.FAULT_BACKGROUND_ATTRIBUTES_ID)

    cls.labelMomentRateFaultBackgrID.setText(
        "ID: %s Name: %s (%s)" %
        (int(feature_id.toDouble()[0]), feature_name.toString(), feature.id()))
Ejemplo n.º 7
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
Ejemplo n.º 8
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
Ejemplo n.º 9
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
Ejemplo n.º 10
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