Esempio n. 1
0
    def test_recurrence_collapse_branches(self):
        '''
        Tests the recurrence model generated by collapsing branches
        '''

        self.fault = mtkActiveFault('001',
                                    'A Fault',
                                    self.simple_fault, [(5., 0.5), (7., 0.5)],
                                    0.,
                                    None,
                                    aseismic=0.,
                                    msr_sigma=[(0.0, 1.0)],
                                    neotectonic_fault=None,
                                    scale_rel=[(WC1994(), 1.0)],
                                    aspect_ratio=1.0,
                                    shear_modulus=[(30., 1.0)],
                                    disp_length_ratio=[(1.25E-5, 1.0)])
        mfd_config = [{
            'MFD_spacing': 0.1,
            'Maximum_Magnitude': None,
            'Minimum_Magnitude': 5.0,
            'Model_Name': 'AndersonLucoArbitrary',
            'Model_Weight': 0.7,
            'Model_Type': 'First',
            'b_value': [0.8, 0.05]
        }, {
            'MFD_spacing': 0.1,
            'Maximum_Magnitude': None,
            'Maximum_Magnitude_Uncertainty': None,
            'Minimum_Magnitude': 5.0,
            'Model_Name': 'YoungsCoppersmithExponential',
            'Model_Weight': 0.3,
            'b_value': [0.8, 0.05]
        }]

        # Enumerated branches should have four models
        self.fault.generate_recurrence_models(collapse=True,
                                              rendered_msr=WC1994(),
                                              config=mfd_config)

        expected_rates = 0.
        expected_weights = np.array([0.35, 0.15, 0.35, 0.15])
        for iloc in range(0, 4):
            expected_rates = expected_rates + (expected_weights[iloc] *
                                               10.**FAULT_RATE_DATA[iloc, :])
        np.testing.assert_array_almost_equal(
            np.log10(self.fault.mfd[0][0].occur_rates),
            np.log10(expected_rates))
Esempio n. 2
0
 def __init__(self,
              source_file,
              id,
              investigation_time,
              start_date,
              min_mag,
              npd=NPD,
              hdd=HDD,
              aspect=1.5,
              upper_seismogenic_depth=0.0,
              lower_seismogenic_depth=15.0,
              msr=WC1994(),
              mesh_spacing=1.0,
              trt="Active Shallow Crust",
              integration_distance=1000):
     assert os.path.exists(source_file), source_file
     self.source_file = source_file
     self.source_id = id
     self.inv_time = investigation_time
     self.start_date = start_date
     self.tom = self._get_tom()
     self.min_mag = min_mag
     self.npd = npd
     self.hdd = hdd
     self.aspect = aspect
     self.usd = upper_seismogenic_depth
     self.lsd = lower_seismogenic_depth
     self.msr = msr
     self.mesh_spacing = mesh_spacing
     self.tectonic_region_type = trt
     self.num_ruptures = 0  # not set yet
Esempio n. 3
0
 def __init__(self, magnitude, dip, aspect,
              tectonic_region='Active Shallow Crust', rake=0., ztor=0.,
              strike=0., msr=WC1994(), initial_point=DEFAULT_POINT,
              hypocentre_location=None):
     """
     Instantiate the rupture - requires a minimum of a magnitude, dip
     and aspect ratio
     """
     self.magnitude = magnitude
     self.dip = dip
     self.aspect = aspect
     self.rake = rake
     self.strike = strike
     self.location = initial_point
     self.ztor = ztor
     self.trt = tectonic_region
     self.hypo_loc = hypocentre_location
     # If the top of rupture depth in the initial
     if fabs(self.location.depth - self.ztor) > 1E-9:
         self.location.depth = ztor
     self.msr = msr
     self.area = self.msr.get_median_area(self.magnitude, self.rake)
     self.surface = create_planar_surface(self.location,
                                          self.strike,
                                          self.dip,
                                          self.area,
                                          self.aspect)
     self.hypocentre = get_hypocentre_on_planar_surface(self.surface,
                                                        self.hypo_loc)
     self.rupture = self.get_rupture()
     self.target_sites_config = None
     self.target_sites = None
Esempio n. 4
0
 def __init__(self,
              source_file,
              investigation_time,
              start_date,
              min_mag,
              npd,
              hdd,
              aspect=1.5,
              upper_seismogenic_depth=0.0,
              lower_seismogenic_depth=15.0,
              msr=WC1994(),
              mesh_spacing=1.0,
              trt="Active Shallow Crust",
              integration_distance=1000):
     assert os.path.exists(source_file), source_file
     self.source_file = source_file
     self.source_id = None  # unset until .new is called
     self.inv_time = investigation_time
     self.start_date = start_date
     self.temporal_occurrence_model = PoissonTOM(self.inv_time)
     self.min_mag = min_mag
     self.npd = npd
     self.hdd = hdd
     self.aspect = aspect
     self.usd = upper_seismogenic_depth
     self.lsd = lower_seismogenic_depth
     self.msr = msr
     self.mesh_spacing = mesh_spacing
     self.tectonic_region_type = trt
     self.stop = None
     self.start = None
Esempio n. 5
0
 def setUp(self):
     '''
     '''
     self.fault = None
     self.regionalisation = None
     self.msr = [(WC1994(), 1.0)]
     self.msr_sigma = [(-1.5, 0.15), (0.0, 0.7), (1.5, 0.15)]
     self.shear_mod = [(30.0, 0.8), (35.0, 0.2)]
     self.dlr = [(1.25E-5, 1.0)]
     self.config = [{}]
     self.slip = [(10.0, 1.0)]
     x0 = Point(30., 30., 0.)
     x1 = x0.point_at(30., 0., 30.)
     x2 = x1.point_at(30., 0., 60.)
     # Total length is 60 km
     self.trace = Line([x0, x1, x2])
     self.dip = 90.
     self.upper_depth = 0.
     self.lower_depth = 20.
     self.simple_fault = SimpleFaultGeometry(self.trace,
                                             self.dip,
                                             self.upper_depth,
                                             self.lower_depth)
             # Creates a trace ~60 km long made of 3 points
     upper_edge = Line([x0, x1, x2])
     lower_edge = Line([x0.point_at(40., 20., 130.),
                        x1.point_at(42., 25., 130.),
                        x2.point_at(41., 22., 130.)])
     self.complex_fault = ComplexFaultGeometry([upper_edge, lower_edge],
                                               2.0)
Esempio n. 6
0
 def test_generate_branching_index(self):
     '''
     Simple test to check that a correct branching index is raised
     Slip - 2 values
     MSR - 1 value 
     Shear Modulus - 2 value
     DLR - 1 value
     MSR_Sigma - 3 Values
     Config - 1 value
     '''
     self.fault = mtkActiveFault('001',
                                 'A Fault',
                                 self.simple_fault, [(5., 0.5), (7., 0.5)],
                                 0.,
                                 None,
                                 msr_sigma=[(-1.5, 0.15), (0., 0.7),
                                            (1.5, 0.15)],
                                 neotectonic_fault=None,
                                 scale_rel=[(WC1994(), 1.0)],
                                 aspect_ratio=1.0,
                                 shear_modulus=[(28., 0.5), (30., 0.5)],
                                 disp_length_ratio=[(1.25E-5, 1.0)])
     # Set with only one config - no data input
     self.fault.generate_config_set({})
     expected_result = np.array(
         [[0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 1, 0], [0, 0, 0, 0, 2, 0],
          [0, 0, 1, 0, 0, 0], [0, 0, 1, 0, 1, 0], [0, 0, 1, 0, 2, 0],
          [1, 0, 0, 0, 0, 0], [1, 0, 0, 0, 1, 0], [1, 0, 0, 0, 2, 0],
          [1, 0, 1, 0, 0, 0], [1, 0, 1, 0, 1, 0], [1, 0, 1, 0, 2, 0]],
         dtype=int)
     branch_index, number_branches = \
         self.fault._generate_branching_index()
     np.testing.assert_array_equal(branch_index, expected_result)
     self.assertEqual(number_branches, 12)
Esempio n. 7
0
    def setUp(self):

        mfd = TruncatedGRMFD(min_mag=4.0, max_mag=6.0, bin_width=0.1,
                             a_val=2.0, b_val=1.0)
        msr = WC1994()
        tom = PoissonTOM(1.0)
        pol = Polygon([Point(longitude=0.0, latitude=0.0),
                       Point(longitude=1.0, latitude=0.0),
                       Point(longitude=1.0, latitude=1.0),
                       Point(longitude=0.0, latitude=1.0)])
        npd = PMF([(1.0, NodalPlane(0.0, 90.0, 0.0))])
        hpd = PMF([(0.7, 10.), (0.3, 20.0)])

        self.src1 = AreaSource(source_id='1',
                               name='1',
                               tectonic_region_type='Test',
                               mfd=mfd,
                               rupture_mesh_spacing=1,
                               magnitude_scaling_relationship=msr,
                               rupture_aspect_ratio=1.,
                               temporal_occurrence_model=tom,
                               upper_seismogenic_depth=0,
                               lower_seismogenic_depth=100.,
                               nodal_plane_distribution=npd,
                               hypocenter_distribution=hpd,
                               polygon=pol,
                               area_discretization=10.)
Esempio n. 8
0
    def build_fault_model(self,
                          collapse=False,
                          rendered_msr=WC1994(),
                          mfd_config=None):
        '''
        Constructs a full fault model with epistemic uncertainty by
        enumerating all the possible recurrence models of each fault as 
        separate faults, with the recurrence rates multiplied by the 
        corresponding weights. 
        :param bool collapse:
            Determines whether or not to collapse the branches
        :param rendered_msr:
            If the option is taken to collapse the branches then a recurrence
            model for rendering must be defined
        :param list/dict mfd_config:
            Universal list or dictionay of configuration parameters for the
            magnitude frequency distribution - will overwrite whatever is 
            previously defined for the fault!
        '''
        self.source_model = mtkSourceModel(self.id, self.name)
        for fault in self.faults:
            fault.generate_recurrence_models(collapse,
                                             config=mfd_config,
                                             rendered_msr=rendered_msr)
            src_model, src_weight = fault.generate_fault_source_model()
            for iloc, model in enumerate(src_model):

                new_model = deepcopy(model)
                new_model.id = str(model.id) + '_%g' % (iloc + 1)
                new_model.mfd.occurrence_rates = \
                    (np.array(new_model.mfd.occurrence_rates) *
                     src_weight[iloc]).tolist()
                self.source_model.sources.append(new_model)
Esempio n. 9
0
def prefilter_background_model(hdf5,
                               sites,
                               integration_distance,
                               msr=WC1994(),
                               aspect=1.5):
    """
    Identify those points within the integration distance
    :param sites:
        Sites for consideration (can be None!)
    :param float integration_distance:
        Maximum distance from rupture to site for consideration
    :param msr:
        Magnitude scaling relation
    :param float aspect:
        Aspect ratio
    :returns:
        Boolean vector indicating if sites are within (True) or outside (False)
        the integration distance
    """
    bg_locations = hdf5["Grid/Locations"][:].astype("float64")
    n_locations = bg_locations.shape[0]
    if not sites:
        # Apply no filtering - all sources valid
        return numpy.ones(n_locations, dtype=bool)
    distances = min_distance(sites.lons, sites.lats,
                             numpy.zeros_like(sites.lons), bg_locations[:, 0],
                             bg_locations[:, 1], numpy.zeros(n_locations))
    # Add buffer equal to half of length of median area from Mmax
    mmax_areas = msr.get_median_area(hdf5["Grid/MMax"][:], 0.0)
    mmax_lengths = numpy.sqrt(mmax_areas / aspect)
    return distances <= (0.5 * mmax_lengths + integration_distance)
Esempio n. 10
0
    def _parse_event_data(self, metadata):
        """
        Read in the distance related metadata and return an instance of the
        :class: smtk.sm_database.Earthquake

        """
        metadata["MODY"] = metadata["MODY"].zfill(4)
        metadata["HRMN"] = metadata["HRMN"].zfill(4)
        # Date and Time
        year = get_int(metadata["YEAR"])
        month = get_int(metadata["MODY"][:2])
        day = get_int(metadata["MODY"][2:])
        hour = get_int(metadata["HRMN"][:2])
        minute = get_int(metadata["HRMN"][2:])
        eq_datetime = datetime(year, month, day, hour, minute)
        # Event ID and Name
        eq_id = metadata["EQID"]
        eq_name = metadata["Earthquake Name"]
        # Focal Mechanism
        focal_mechanism = self._get_focal_mechanism(eq_id, eq_name, metadata)
        focal_mechanism.scalar_moment = get_float(metadata["Mo (dyne.cm)"]) *\
            1E-7
        # Read magnitude
        pref_mag = Magnitude(get_float(metadata["Earthquake Magnitude"]),
                             metadata["Magnitude Type"],
                             sigma=get_float(metadata["Uncertainty"]))
        # Create Earthquake Class
        eqk = Earthquake(eq_id, eq_name, eq_datetime,
                         get_float(metadata["Hypocenter Longitude (deg)"]),
                         get_float(metadata["Hypocenter Latitude (deg)"]),
                         get_float(metadata["Hypocenter Depth (km)"]),
                         pref_mag, focal_mechanism, metadata["Country"])
        hypo_loc = (0.5, 0.7)  # Hypocentre Location
        msr = WC1994()
        # Warning rake set to 0.0 in scaling relationship
        area = msr.get_median_area(pref_mag.value, 0.0)
        aspect_ratio = 1.5  # Assumed Fixed
        width_model = np.sqrt(area / aspect_ratio)
        length_model = aspect_ratio * width_model
        ztor_model = eqk.depth - width_model / 2.
        if ztor_model < 0:
            ztor_model = 0.0

        length = get_float(metadata["Fault Rupture Length (km)"])
        if length is None:
            length = length_model
        width = get_float(metadata["Fault Rupture Width (km)"])
        if width is None:
            width = width_model
        ztor = get_float(metadata["Depth to Top Of Fault Rupture Model"])
        if ztor is None:
            ztor = ztor_model
        # Rupture
        eqk.rupture = Rupture(eq_id, eq_name, pref_mag, length, width, ztor)
        #    get_float(metadata["Fault Rupture Length (km)"]),
        #    get_float(metadata["Fault Rupture Width (km)"]),
        #    get_float(metadata["Depth to Top Of Fault Rupture Model"]))
        eqk.rupture.get_area()
        return eqk
Esempio n. 11
0
def sample_background_model(
        hdf5, branch_key, tom, eff_num_ses, seed, filter_idx, min_mag, npd,
        hdd, upper_seismogenic_depth, lower_seismogenic_depth, msr=WC1994(),
        aspect=1.5, trt=DEFAULT_TRT):
    """
    Generates a rupture set from a sample of the background model

    :param branch_key:
        Key to indicate the branch for selecting the background model
    :param tom:
        Temporal occurrence model as instance of :class:
        openquake.hazardlib.tom.TOM
    :param seed:
        Random seed to use in the call to tom.sample_number_of_occurrences
    :param filter_idx:
        Sites for consideration (can be None!)
    :param float min_mag:
        Minimim magnitude for consideration of background sources
    :param npd:
        Nodal plane distribution as instance of :class:
        openquake.hazardlib.pmf.PMF
    :param hdd:
        Hypocentral depth distribution as instance of :class:
        openquake.hazardlib.pmf.PMF
    :param float aspect:
        Aspect ratio
    :param float upper_seismogenic_depth:
        Upper seismogenic depth (km)
    :param float lower_seismogenic_depth:
        Lower seismogenic depth (km)
    :param msr:
        Magnitude scaling relation
    :param float integration_distance:
        Maximum distance from rupture to site for consideration
    """
    bg_magnitudes = hdf5["/".join(["Grid", branch_key, "Magnitude"])][()]
    # Select magnitudes above the minimum magnitudes
    mag_idx = bg_magnitudes >= min_mag
    mags = bg_magnitudes[mag_idx]
    rates = hdf5["/".join(["Grid", branch_key, "RateArray"])][filter_idx, :]
    rates = rates[:, mag_idx]
    valid_locs = hdf5["Grid/Locations"][filter_idx, :]
    # Sample remaining rates
    sampler = tom.sample_number_of_occurrences(rates * eff_num_ses, seed)
    background_ruptures = []
    background_n_occ = []
    for i, mag in enumerate(mags):
        rate_idx = numpy.where(sampler[:, i])[0]
        rate_cnt = sampler[rate_idx, i]
        occurrence = rates[rate_idx, i]
        locations = valid_locs[rate_idx, :]
        ruptures = generate_background_ruptures(
            tom, locations, occurrence,
            mag, npd, hdd, upper_seismogenic_depth,
            lower_seismogenic_depth, msr, aspect, trt)
        background_ruptures.extend(ruptures)
        background_n_occ.extend(rate_cnt.tolist())
    return background_ruptures, background_n_occ
Esempio n. 12
0
def plot_planes_at(x,
                   y,
                   strikes,
                   dips,
                   magnitudes,
                   strike_cs,
                   dip_cs,
                   aratio=1.0,
                   msr=None,
                   ax=None,
                   zorder=20,
                   color='None',
                   linewidth=1,
                   axis=None):
    """
    This plots a cross-section and number of rupture planes defined in terms
    of a strike and a dip.

    :parameter x:
        Coordinates x on the cross-section
    :parameter y:
        Coordinates y on the cross-section (it corresponds to a depth)
    :parameter strikes:
        Strike values of the planes
    :parameter dips:
        Dip values of the planes
    :parameter strike_cs:
        Strike angle of the cross-section plane [in degrees]
    :parameter dip_cs:
        Dip angle of the cross-section plane [in degrees]
    """

    if axis is None:
        ax = plt.gca()
    else:
        plt.sca(axis)

    if msr is None:
        msr = WC1994()

    cols = ['red', 'blue', 'green']

    for strike, dip, col, mag in zip(strikes, dips, cols, magnitudes):

        area = msr.get_median_area(mag, None)
        width = (area / aratio)**.5
        t = np.arange(-width / 2, width / 2, 0.1)

        inter = get_line_of_intersection(strike, dip, strike_cs, dip_cs)
        xl = t * inter[0]
        yl = t * inter[1]
        zl = t * inter[2]
        ds = -np.sign(t) * (xl**2 + yl**2)**.5 + x

        if color is not None:
            col = color

        plt.plot(ds, zl + y, zorder=zorder, color=col, linewidth=linewidth)
Esempio n. 13
0
def generate_background_ruptures(tom,
                                 locations,
                                 occurrence,
                                 mag,
                                 npd,
                                 hdd,
                                 upper_seismogenic_depth,
                                 lower_seismogenic_depth,
                                 msr=WC1994(),
                                 aspect=1.5,
                                 trt=DEFAULT_TRT):
    """
    :param tom:
        Temporal occurrence model as instance of :class:
        openquake.hazardlib.tom.TOM
    :param numpy.ndarray locations:
        Array of locations [Longitude, Latitude] of the point sources
    :param numpy.ndarray occurrence:
        Annual rates of occurrence
    :param float mag:
        Magnitude
    :param npd:
        Nodal plane distribution as instance of :class:
        openquake.hazardlib.pmf.PMF
    :param hdd:
        Hypocentral depth distribution as instance of :class:
        openquake.hazardlib.pmf.PMF
    :param float upper_seismogenic_depth:
        Upper seismogenic depth (km)
    :param float lower_seismogenic_depth:
        Lower seismogenic depth (km)
    :param msr:
        Magnitude scaling relation
    :param float aspect:
        Aspect ratio
    :param str trt:
        Tectonic region type
    :returns:
        List of ruptures
    """
    ruptures = []
    n_vals = len(locations)
    depths = hdd.sample_pairs(n_vals)
    nodal_planes = npd.sample_pairs(n_vals)
    for i, (x, y) in enumerate(locations):
        hypocentre = Point(x, y, depths[i][1])
        surface = get_rupture_surface(mag, nodal_planes[i][1], hypocentre, msr,
                                      aspect, upper_seismogenic_depth,
                                      lower_seismogenic_depth)
        rupture_probability = (occurrence[i] * nodal_planes[i][0] *
                               depths[i][0])
        ruptures.append(
            ParametricProbabilisticRupture(mag, nodal_planes[i][1].rake, trt,
                                           hypocentre, surface, PointSource,
                                           rupture_probability, tom))
    return ruptures
Esempio n. 14
0
def example_calc(apply):
    sitecol = SiteCollection([
        Site(Point(30.0, 30.0), 760., True, 1.0, 1.0),
        Site(Point(30.25, 30.25), 760., True, 1.0, 1.0),
        Site(Point(30.4, 30.4), 760., True, 1.0, 1.0)])
    mfd_1 = TruncatedGRMFD(4.5, 8.0, 0.1, 4.0, 1.0)
    mfd_2 = TruncatedGRMFD(4.5, 7.5, 0.1, 3.5, 1.1)
    sources = [PointSource('001', 'Point1', 'Active Shallow Crust',
                           mfd_1, 1.0, WC1994(), 1.0, PoissonTOM(50.0),
                           0.0, 30.0, Point(30.0, 30.5),
                           PMF([(1.0, NodalPlane(0.0, 90.0, 0.0))]),
                           PMF([(1.0, 10.0)])),
               PointSource('002', 'Point2', 'Active Shallow Crust',
                           mfd_2, 1.0, WC1994(), 1.0, PoissonTOM(50.0),
                           0.0, 30.0, Point(30.0, 30.5),
                           PMF([(1.0, NodalPlane(0.0, 90.0, 0.0))]),
                           PMF([(1.0, 10.0)]))]
    imtls = {'PGA': [0.01, 0.1, 0.2, 0.5, 0.8],
             'SA(0.5)': [0.01, 0.1, 0.2, 0.5, 0.8]}
    gsims = {'Active Shallow Crust': akkar_bommer_2010.AkkarBommer2010()}
    return calc_hazard_curves(sources, sitecol, imtls, gsims, apply=apply)
Esempio n. 15
0
    def test_parse_region_list_to_tuples(self):
        '''
        Tests the function to parse a region list to a set of tuples
        '''
        self.data = {
            'Shear_Modulus': {
                'Value': [30.],
                'Weight': [1.0]
            },
            'Displacement_Length_Ratio': {
                'Value': [1.25E-5],
                'Weight': [1.0]
            },
            'Magnitude_Scaling_Relation': {
                'Value': [WC1994()],
                'Weight': [1.0]
            }
        }
        expected_output = {
            'Shear_Modulus': [(30., 1.0)],
            'Displacement_Length_Ratio': [(1.25E-5, 1.0)],
            'Magnitude_Scaling_Relation': [(WC1994(), 1.0)]
        }
        output = parse_tect_region_dict_to_tuples([self.data])
        self.assertAlmostEqual(expected_output['Shear_Modulus'][0][0],
                               output[0]['Shear_Modulus'][0][0])
        self.assertAlmostEqual(expected_output['Shear_Modulus'][0][1],
                               output[0]['Shear_Modulus'][0][1])
        self.assertAlmostEqual(
            expected_output['Displacement_Length_Ratio'][0][0],
            output[0]['Displacement_Length_Ratio'][0][0])
        self.assertAlmostEqual(
            expected_output['Displacement_Length_Ratio'][0][1],
            output[0]['Displacement_Length_Ratio'][0][1])

        self.assertTrue(
            isinstance(output[0]['Magnitude_Scaling_Relation'][0][0], WC1994))
        self.assertAlmostEqual(
            expected_output['Magnitude_Scaling_Relation'][0][1],
            output[0]['Shear_Modulus'][0][1])
Esempio n. 16
0
def nrml_from_shapefile(shapefile, shapefile_faultname_attribute,
                        shapefile_dip_attribute, shapefile_sliprate_attribute,
                        source_model_name, simple_fault_tectonic_region,
                        magnitude_scaling_relation, rupture_aspect_ratio,
                        upper_depth, lower_depth, a_value, b_value, min_mag,
                        max_mag, rake, output_dir, quiet):
    """Driver routine to convert nrml to shapefile
     
    """
    # Get geometry
    fault_traces, faultnames, dips, \
    sliprate, fault_lengths = parse_line_shapefile(shapefile,
                                                  shapefile_faultname_attribute,
                                                  shapefile_dip_attribute,
                                                  shapefile_sliprate_attribute)

    # Output is written line-by-line to this list
    output_xml = []

    append_xml_header(output_xml, source_model_name)

    # Loop through each fault and add source specific info
    for i in range(len(fault_traces)):
        simple_fault_id = i
        A = fault_lengths[i] * (float(lower_depth) - float(upper_depth))
        # Calculate M_max from scaling relations
        scalrel = WC1994()
        max_mag = scalrel.get_median_mag(A, float(rake))
        #        print A
        # Calculate GR a values from slip rate
        if sliprate[i] != '""':
            print sliprate[i]
            a_value, moment_rate = fault_slip_rate_GR_conversion.slip2GR(
                sliprate[i], A, float(b_value), float(max_mag), M_min=0.0)
        append_rupture_geometry(output_xml, fault_traces[i], dips[i],
                                simple_fault_id, faultnames[i], upper_depth,
                                lower_depth, simple_fault_tectonic_region)

        append_earthquake_information(output_xml, magnitude_scaling_relation,
                                      rupture_aspect_ratio, a_value, b_value,
                                      min_mag, max_mag, rake)

    # Close xml
    output_xml.append('  </sourceModel>')
    output_xml.append('</nrml>')

    # Add newlines
    output_xml = [oxml + '\n' for oxml in output_xml]

    return output_xml
 def test_collapse_fault_model(self):
     input_file = os.path.join(
         BASE_DATA_PATH, "collapse_test_simple_fault_example_4branch.yml")
     mesh_spacing = 1.0
     reader = FaultYmltoSource(input_file)
     fault_model, tectonic_region = reader.read_file(mesh_spacing)
     fault_model.build_fault_model(collapse=True,
                                   bin_width=0.05,
                                   rendered_msr=WC1994())
     expected_mfd = self.src.incrementalMFD
     model_mfd = fault_model.faults[0].mfd[0][0]
     self.assertAlmostEqual(expected_mfd["binWidth"], model_mfd.bin_width,
                            7)
     self.assertAlmostEqual(expected_mfd["minMag"], model_mfd.min_mag, 7)
     expected_rates = np.array(expected_mfd.occurRates.text)
     np.testing.assert_array_almost_equal(model_mfd.occur_rates,
                                          expected_rates, 7)
Esempio n. 18
0
    def test_generate_recurrence_models_no_collapse(self):
        '''
        Tests the generate recurrence models option without collapsing
        branches: simple example with two slip rates and two mfd configurations
        '''
        self.fault = mtkActiveFault(
            '001',
            'A Fault',
            self.simple_fault,
            [(5., 0.5), (7., 0.5)],
            0.,
            None,
            aseismic=0.,
            msr_sigma=[(0.0, 1.0)],
            neotectonic_fault=None,
            scale_rel=[(WC1994(), 1.0)],
            aspect_ratio=1.0,
            shear_modulus=[(30., 1.0)],
            disp_length_ratio=[(1.25E-5, 1.0)])
        mfd_config = [{'MFD_spacing': 0.1,
                       'Maximum_Magnitude': None,
                       'Minimum_Magnitude': 5.0,
                        'Model_Name': 'AndersonLucoArbitrary',
                        'Model_Weight': 0.7,
                        'Model_Type': 'First',
                        'b_value': [0.8, 0.05]},
                       {'MFD_spacing': 0.1,
                        'Maximum_Magnitude': None,
                        'Maximum_Magnitude_Uncertainty': None,
                        'Minimum_Magnitude': 5.0,
                        'Model_Name': 'YoungsCoppersmithExponential',
                        'Model_Weight': 0.3,
                        'b_value': [0.8, 0.05]}]

        # Enumerates branches should have four models
        self.fault.generate_recurrence_models(config=mfd_config)
        mfds = self.fault.mfd[0]
        weights = self.fault.mfd[1]
        np.testing.assert_array_almost_equal(
            weights,
            np.array([0.35, 0.15, 0.35, 0.15]))
        for (iloc, occur) in enumerate(mfds):
            np.testing.assert_array_almost_equal(
                np.log10(occur.occur_rates),
                FAULT_RATE_DATA[iloc, :])
Esempio n. 19
0
 def test_rupture_close_to_south_pole(self):
     # data taken from real example and causing "surface's angles are not
     # right" error
     mfd = EvenlyDiscretizedMFD(
         min_mag=5., bin_width=0.1, occurrence_rates=[2.180e-07]
     )
     nodal_plane_dist = PMF([(1., NodalPlane(135., 20., 90.))])
     src = PointSource(source_id='1', name='pnt', tectonic_region_type='asc',
              mfd=mfd, rupture_mesh_spacing=1,
              magnitude_scaling_relationship=WC1994(),
              rupture_aspect_ratio=1.,
              temporal_occurrence_model=PoissonTOM(50.),
              upper_seismogenic_depth=0, lower_seismogenic_depth=26,
              location=Point(-165.125, -83.600),
              nodal_plane_distribution=nodal_plane_dist,
              hypocenter_distribution=PMF([(1., 9.)]))
     ruptures = list(src.iter_ruptures())
     self.assertEqual(len(ruptures), 1)
def mag_scale_rel_to_hazardlib(mag_scale_rel, use_default=False):
    """
    Returns the magnitude scaling relation in a format readable by
    openquake.hazardlib
    """
    if isinstance(mag_scale_rel, BaseMSR):
        return mag_scale_rel
    elif isinstance(mag_scale_rel, str):
        if not mag_scale_rel in SCALE_RELS.keys():
            raise ValueError('Magnitude scaling relation %s not supported!'
                             % mag_scale_rel)
        else:
            return SCALE_RELS[mag_scale_rel]()
    else:
        if use_default:
            # Returns the Wells and Coppersmith string
            return WC1994()
        else:
            raise ValueError('Magnitude Scaling Relation Not Defined!')
Esempio n. 21
0
 def setUp(self):
     """
     """
     #
     # coordinates of point sources
     lons = [10.00, 10.10, 10.20, 10.00, 10.10, 10.20, 10.00, 10.10, 10.20]
     lats = [45.10, 45.10, 45.10, 45.05, 45.05, 45.05, 45.00, 45.00, 45.00]
     deps = [10.00, 10.00, 10.00, 10.00, 10.00, 10.00, 10.00, 10.00, 10.00]
     self.lons = lons
     self.lats = lats
     #
     # set main parameters
     mfd = TruncatedGRMFD(min_mag=4.0,
                          max_mag=6.0,
                          bin_width=0.1,
                          a_val=2.0,
                          b_val=1.0)
     msr = WC1994()
     tom = PoissonTOM(1.0)
     npd = PMF([(1.0, NodalPlane(0.0, 90.0, 0.0))])
     hdd = PMF([(0.7, 4.), (0.3, 8.0)])
     #
     # create the list of sources
     srcs = []
     for idx, (lon, lat, dep) in enumerate(zip(lons, lats, deps)):
         src = PointSource(source_id='1',
                           name='Test',
                           tectonic_region_type=TRT.ACTIVE_SHALLOW_CRUST,
                           mfd=mfd,
                           rupture_mesh_spacing=5.0,
                           magnitude_scaling_relationship=msr,
                           rupture_aspect_ratio=1.0,
                           temporal_occurrence_model=tom,
                           upper_seismogenic_depth=0,
                           lower_seismogenic_depth=10.,
                           location=Point(lon, lat, dep),
                           nodal_plane_distribution=npd,
                           hypocenter_distribution=hdd)
         srcs.append(src)
     self.points = srcs
Esempio n. 22
0
 def test(self):
     sitecol = SiteCollection([Site(Point(30.0, 30.0), 760., 1.0, 1.0)])
     mfd = TruncatedGRMFD(4.5, 8.0, 0.1, 4.0, 1.0)
     sources = [
         PointSource('001', 'Point1', 'Active Shallow Crust', mfd, 1.0,
                     WC1994(), 1.0, PoissonTOM(50.0), 0.0, 30.0,
                     Point(30.0, 30.5),
                     PMF([(1.0, NodalPlane(0.0, 90.0, 0.0))]),
                     PMF([(1.0, 10.0)]))
     ]
     imtls = {'PGA': [0.01, 0.1, 0.2, 0.5, 0.8]}
     hc1 = calc_hazard_curves(
         sources, sitecol, imtls,
         {'Active Shallow Crust': AkkarBommer2010()})['PGA']
     hc2 = calc_hazard_curves(
         sources, sitecol, imtls,
         {'Active Shallow Crust': SadighEtAl1997()})['PGA']
     hc = .6 * hc1 + .4 * hc2
     ag = AvgGMPE(b1=dict(AkkarBommer2010={'weight': .6}),
                  b2=dict(SadighEtAl1997={'weight': .4}))
     hcm = calc_hazard_curves(sources, sitecol, imtls,
                              {'Active Shallow Crust': ag})['PGA']
     # the AvgGMPE is not producing real means!!
     numpy.testing.assert_almost_equal(hc, hcm, decimal=3)
Esempio n. 23
0
def nrml_from_shapefile(shapefile, shapefile_faultname_attribute,
                        shapefile_dip_attribute, shapefile_sliprate_attribute,
                        source_model_name, simple_fault_tectonic_region,
                        magnitude_scaling_relation, rupture_aspect_ratio,
                        upper_depth, lower_depth, a_value, b_value, min_mag,
                        max_mag, rake, output_dir, incremental_mfd, quiet):
    """Driver routine to convert nrml to shapefile
     
    """
    # Get geometry
    fault_traces, faultnames, dips, \
    sliprate, fault_lengths = parse_line_shapefile(shapefile,
                                                  shapefile_faultname_attribute,
                                                  shapefile_dip_attribute,
                                                  shapefile_sliprate_attribute)

    # Output is written line-by-line to this list
    output_xml = []

    append_xml_header(output_xml, source_model_name)

    # Loop through each fault and add source specific info
    for i in range(len(fault_traces)):
        simple_fault_id = i
        A = fault_lengths[i] * (float(lower_depth) - float(upper_depth))
        # Calculate M_max from scaling relations
        scalrel = WC1994()
        bin_width = 0.1
        max_mag = scalrel.get_median_mag(A, float(rake))
        char_mag = max_mag - 0.25  #characteristic magnitude for OQ def
        #        print A
        # Calculate characteristic incremental occurrence rates from slip rate
        if sliprate[i] != '""':
            print sliprate[i]
            # just to calculate the moment rate, need to fix this function
            a_value, moment_rate = fault_slip_rate_GR_conversion.slip2GR(
                sliprate[i], A, float(b_value), float(max_mag), M_min=0.0)
            a_value = None  # We aren't using the a value

#            mfd = YoungsCoppersmith1985MFD.from_total_moment_rate(min_mag=min_mag,
#                                                                  b_val=float(b_value),
#                                                                  char_mag=float(max_mag),
#                                                                  total_moment_rate=moment_rate,
#                                                                  bin_width=0.1)
#            mags,rates=zip(*mfd.get_annual_occurrence_rates())

        append_rupture_geometry(output_xml, fault_traces[i], dips[i],
                                simple_fault_id, faultnames[i], upper_depth,
                                lower_depth, simple_fault_tectonic_region)

        if incremental_mfd:
            append_earthquake_information_inc(output_xml,
                                              magnitude_scaling_relation,
                                              rupture_aspect_ratio, char_mag,
                                              b_value, min_mag, max_mag, rake,
                                              moment_rate, bin_width)
        else:
            append_earthquake_information_YC(output_xml,
                                             magnitude_scaling_relation,
                                             rupture_aspect_ratio, char_mag,
                                             b_value, min_mag, max_mag, rake,
                                             moment_rate, bin_width)

    # Close xml
    output_xml.append('  </sourceModel>')
    output_xml.append('</nrml>')

    # Add newlines
    output_xml = [oxml + '\n' for oxml in output_xml]

    return output_xml
Esempio n. 24
0
# Get a list of the available GSIMs
AVAILABLE_GSIMS = gsim.get_available_gsims()

# Generic dictionary of parameters needed for a trellis calculation
PARAM_DICT = {
    'magnitudes': [],
    'distances': [],
    'distance_type': 'rjb',
    'vs30': [],
    'strike': None,
    'dip': None,
    'rake': None,
    'ztor': None,
    'hypocentre_location': (0.5, 0.5),
    'hypo_loc': (0.5, 0.5),
    'msr': WC1994()
}

# Defines the plotting units for given intensitiy measure type
PLOT_UNITS = {
    'PGA': 'g',
    'PGV': 'cm/s',
    'SA': 'g',
    'IA': 'm/s',
    'CSV': 'g-sec',
    'RSD': 's',
    'MMI': ''
}

# Verbose label for each given distance type
DISTANCE_LABEL_MAP = {
Esempio n. 25
0
 def setUp(self):
     self.asr = WC1994()
Esempio n. 26
0
    def _parse_distance_data(self, event, site, metadata):
        """
        Read in the distance related metadata and return an instance of the
        :class: smtk.sm_database.RecordDistance
        """
        # Compute various distance metrics
        # Add calculation of Repi, Rhypo from event and station localizations
        # (latitudes, longitudes, depth, elevation)?
        target_site = Mesh(np.array([site.longitude]),
                           np.array([site.latitude]),
                           np.array([-site.altitude / 1000.0]))
        # Warning ratio fixed to 1.5
        ratio = 1.5
        if not event.rupture.area:
            event.rupture.area = WC1994().get_median_area(
                event.magnitude.value, None)
        surface_modeled = rcfg.create_planar_surface(
            Point(event.longitude, event.latitude, event.depth),
            event.mechanism.nodal_planes.nodal_plane_1['strike'],
            event.mechanism.nodal_planes.nodal_plane_1['dip'],
            event.rupture.area, ratio)
        hypocenter = rcfg.get_hypocentre_on_planar_surface(
            surface_modeled, event.rupture.hypo_loc)
        try:
            surface_modeled._create_mesh()
        except:
            dip = surface_modeled.get_dip()
            dip_dir = (surface_modeled.get_strike() - 90.) % 360.
            ztor = surface_modeled.top_left.depth
            d_x = ztor * np.tan(np.radians(90.0 - dip))
            top_left_surface = surface_modeled.top_left.point_at(
                d_x, -ztor, dip_dir)
            top_left_surface.depth = 0.
            top_right_surface = surface_modeled.top_right.point_at(
                d_x, -ztor, dip_dir)
            top_right_surface.depth = 0.
            surface_modeled = SimpleFaultSurface.from_fault_data(
                Line([top_left_surface,
                      top_right_surface]), surface_modeled.top_left.depth,
                surface_modeled.bottom_left.depth, surface_modeled.get_dip(),
                1.0)

        # Rhypo
        Rhypo, Repi, Rrup, Rjb, Ry0 = tuple(
            map(get_positive_float, [
                metadata[key] for key in [
                    "Hypocentral Distance (km)", "Epicentral Distance (km)",
                    "Rupture Distance (km)", "Joyner-Boore Distance (km)",
                    "Ry0 (km)"
                ]
            ]))
        Rx = get_float(metadata["Rx (km)"])  # Rx can be negative

        #Rhypo = get_float(metadata["Hypocentral Distance (km)"])
        if Rhypo is None or Rhypo < 0.0:
            Rhypo = hypocenter.distance_to_mesh(target_site)
        # Repi
        #Repi = get_float(metadata["Epicentral Distance (km)"])
        if Repi is None or Repi < 0.0:
            Repi = hypocenter.distance_to_mesh(target_site, with_depths=False)
        # Rrup
        #Rrup = get_float(metadata["Rupture Distance (km)"])
        if Rrup is None or Rrup < 0.0:
            Rrup = surface_modeled.get_min_distance(target_site)[0]
        # Rjb
        #Rjb = get_float(metadata["Joyner-Boore Distance (km)"])
        if Rjb is None or Rjb < 0.0:
            Rjb = surface_modeled.get_joyner_boore_distance(target_site)[0]
        # Need to check if Rx and Ry0 are consistant with the other metrics
        # when those are coming from the flatfile?
        # Rx
        #Rx = get_float(metadata["Rx (km)"])
        if Rx is None or Rx < 0.0:
            Rx = surface_modeled.get_rx_distance(target_site)[0]
        # Ry0
        Ry0 = get_float(metadata["Ry0 (km)"])
        if Ry0 is None or Ry0 < 0.0:
            Ry0 = surface_modeled.get_ry0_distance(target_site)[0]

        distance = RecordDistance(repi=Repi,
                                  rhypo=Rhypo,
                                  rjb=Rjb,
                                  rrup=Rrup,
                                  r_x=Rx,
                                  ry0=Ry0)
        distance.azimuth = get_float(metadata["Source to Site Azimuth (deg)"])
        #distance.hanging_wall = get_float(metadata["FW/HW Indicator"])
        if metadata["FW/HW Indicator"] == "HW":
            distance.hanging_wall = True
        elif metadata["FW/HW Indicator"] == "FW":
            distance.hanging_wall = False
        else:
            pass

        return distance

        return
Esempio n. 27
0
# The GEM Foundation, and the authors of the software, assume no
# liability for use of the software.
'''
:mod: hmtk.regionalisation.tectonic_regionalisation implements the 
hmtk.ancillary.tectonic_regionalisation.TectonicRegion :class:, defining
the methods and attributes associated with a region, and the 
hmtk.ancillary.tectonic_regionalisation.TectonicRegionalisation :class:
defining a regionalisation as a set of regions
'''
from math import fabs
import numpy as np
from openquake.hazardlib.scalerel.wc1994 import WC1994

DEFAULT_SHEAR_MODULUS = [(30.0, 1.0)]
DEFAULT_DLR = [(1.25E-5, 1.0)]
DEFAULT_MSR = [(WC1994(), 1.0)]


def _check_list_weights(parameter, name):
    '''
    Checks that the weights in a list of tuples sums to 1.0
    '''
    if not isinstance(parameter, list):
        raise ValueError('%s must be formulated with a list of tuples' % name)
    weight = np.sum([val[1] for val in parameter])
    if fabs(weight - 1.) > 1E-8:
        raise ValueError('%s weights do not sum to 1.0!' % name)
    return parameter

    #~ if isinstance(parameter, dict):
    #~ if isinstance(parameter['Model'], float):
Esempio n. 28
0
 def setUp(self):
     """
     """
     self.msr = WC1994()
Esempio n. 29
0
    def test_build_fault_model(self):
        # Tests the constuction of a fault model with two faults (1 simple,
        # 1 complex) each with two mfd rates - should produce four sources
        self.model = mtkActiveFaultModel('001', 'A Fault Model', faults=[])
        x0 = Point(30., 30., 0.)
        x1 = x0.point_at(30., 0., 30.)
        x2 = x1.point_at(30., 0., 60.)
        # Total length is 60 km
        trace = Line([x0, x1, x2])
        simple_fault = SimpleFaultGeometry(trace, 90., 0., 20.)
        # Creates a trace ~60 km long made of 3 points
        upper_edge = Line([x0, x1, x2])
        lower_edge = Line([
            x0.point_at(40., 20., 130.),
            x1.point_at(42., 25., 130.),
            x2.point_at(41., 22., 130.)
        ])
        complex_fault = ComplexFaultGeometry([upper_edge, lower_edge], 2.0)
        config = [{
            'MFD_spacing': 0.1,
            'Maximum_Magnitude': 7.0,
            'Maximum_Uncertainty': None,
            'Model_Name': 'Characteristic',
            'Model_Weight': 0.5,
            'Sigma': 0.1,
            'Lower_Bound': -1.,
            'Upper_Bound': 1.
        }, {
            'MFD_spacing': 0.1,
            'Maximum_Magnitude': 7.5,
            'Maximum_Uncertainty': None,
            'Model_Name': 'Characteristic',
            'Model_Weight': 0.5,
            'Sigma': 0.1,
            'Lower_Bound': -1.,
            'Upper_Bound': 1.
        }]
        fault1 = mtkActiveFault('001',
                                'Simple Fault 1',
                                simple_fault, [(10.0, 1.0)],
                                -90.,
                                None,
                                aspect_ratio=1.0,
                                scale_rel=[(WC1994(), 1.0)],
                                shear_modulus=[(30.0, 1.0)],
                                disp_length_ratio=[(1E-5, 1.0)])
        fault1.generate_config_set(config)
        fault2 = mtkActiveFault('002',
                                'Complex Fault 1',
                                complex_fault, [(10.0, 1.0)],
                                -90.,
                                None,
                                aspect_ratio=1.0,
                                scale_rel=[(WC1994(), 1.0)],
                                shear_modulus=[(30.0, 1.0)],
                                disp_length_ratio=[(1E-5, 1.0)])
        fault2.generate_config_set(config)
        self.model.faults = [fault1, fault2]

        # Generate source model
        self.model.build_fault_model()
        self.assertEqual(len(self.model.source_model.sources), 4)
        # First source should be an instance of a mtkSimpleFaultSource
        model1 = self.model.source_model.sources[0]
        self.assertTrue(isinstance(model1, mtkSimpleFaultSource))
        self.assertEqual(model1.id, '001_1')
        self.assertAlmostEqual(model1.mfd.min_mag, 6.9)
        np.testing.assert_array_almost_equal(
            np.log10(np.array(model1.mfd.occurrence_rates)),
            np.array([-2.95320041, -2.54583708, -2.953200413]))

        # Second source should be an instance of a mtkSimpleFaultSource
        model2 = self.model.source_model.sources[1]
        self.assertTrue(isinstance(model2, mtkSimpleFaultSource))
        self.assertEqual(model2.id, '001_2')
        self.assertAlmostEqual(model2.mfd.min_mag, 7.4)
        np.testing.assert_array_almost_equal(
            np.log10(np.array(model2.mfd.occurrence_rates)),
            np.array([-3.70320041, -3.29583708, -3.70320041]))

        # Third source should be an instance of a mtkComplexFaultSource
        model3 = self.model.source_model.sources[2]
        self.assertTrue(isinstance(model3, mtkComplexFaultSource))
        self.assertEqual(model3.id, '002_1')
        self.assertAlmostEqual(model3.mfd.min_mag, 6.9)
        np.testing.assert_array_almost_equal(
            np.log10(np.array(model3.mfd.occurrence_rates)),
            np.array([-2.59033387, -2.18297054, -2.59033387]))

        # Fourth source should be an instance of a mtkComplexFaultSource
        model4 = self.model.source_model.sources[3]
        self.assertTrue(isinstance(model4, mtkComplexFaultSource))
        self.assertEqual(model4.id, '002_2')
        self.assertAlmostEqual(model4.mfd.min_mag, 7.4)
        np.testing.assert_array_almost_equal(
            np.log10(np.array(model4.mfd.occurrence_rates)),
            np.array([-3.34033387, -2.93297054, -3.34033387]))
    def _parse_event_data(self, metadata):
        """
        Read in the distance related metadata and return an instance of the
        :class: smtk.sm_database.Earthquake

        """
        data_fields = ['Month', 'Day', 'Hour', 'Minute', 'Second']
        for f in data_fields:
            metadata[f] = metadata[f].zfill(2)

        # Date and Time
        year = get_int(metadata["Year"])
        month = get_int(metadata["Month"])
        day = get_int(metadata["Day"])
        hour = get_int(metadata["Hour"])
        minute = get_int(metadata["Minute"])
        second = get_int(metadata["Second"])
        eq_datetime = datetime(year, month, day, hour, minute, second)
        # Event ID and Name
        eq_id = metadata["EQID"]
        eq_name = metadata["Earthquake Name"]
        # Focal Mechanism
        focal_mechanism = self._get_focal_mechanism(eq_id, eq_name, metadata)
        
        focal_mechanism.scalar_moment = get_float(metadata["Mo (dyne.cm)"]) *\
            1E-7
        # Read magnitude
        pref_mag = Magnitude(get_float(metadata["Magnitude"]),
                             metadata["Magnitude type"],
                             sigma=get_float(metadata["Magnitude uncertainty"]))
        # Create Earthquake Class
        eqk = Earthquake(eq_id, eq_name, eq_datetime,
            get_float(metadata["Epicenter Longitude (deg; positive E)"]),
            get_float(metadata["Epicenter Latitude (deg; positive N)"]),
            get_float(metadata["Hypocenter Depth (km)"]),
            pref_mag,
            focal_mechanism,
            metadata["Country"])

        # hypocenter location
        f1 = get_float(metadata[
            "Along-strike Hypocenter location " +
            "on the fault (fraction between 0 and 1)"])
        f2 = get_float(metadata[
            "Along-width Hypocenter location " +
            "on the fault (fraction between 0 and 1)"])
        if f1 is None or f2 is None:
            hypo_loc = (0.5, 0.7)
        else:
            hypo_loc = (f1, f2)

        evt_tectonic_region = metadata["Tectonic environment (Crustal; Inslab; Interface; Stable; Geothermal; Volcanic; Oceanic_crust)"]
        if evt_tectonic_region == "Stable" or evt_tectonic_region == "Crustal":
            msr=WC1994()
        elif evt_tectonic_region == "Inslab":
            msr=StrasserIntraslab()
        elif evt_tectonic_region == "Interface":
            msr=StrasserInterface()

        # Warning rake set to 0.0 in scaling relationship - applies only
        # to WC1994
        area = msr.get_median_area(pref_mag.value, 0.0)
        aspect_ratio = 1.5
        width_model = np.sqrt(area / aspect_ratio)
        length_model = aspect_ratio * width_model
        ztor_model = eqk.depth - width_model / 2.
        if ztor_model < 0:
            ztor_model = 0.0

        length = get_float(metadata["Fault Rupture Length (km)"])
        if length is None:
            length = length_model
        width = get_float(metadata["Fault Rupture Width (km)"])
        if width is None:
            width = width_model
        ztor = get_float(metadata["Depth to Top Of Fault Rupture Model"])
        if ztor is None:
            ztor=ztor_model

        # Rupture
        eqk.rupture = Rupture(eq_id,
                              length,
                              width,
                              ztor,
                              hypo_loc=hypo_loc)
#            get_float(metadata["Fault Rupture Length (km)"]),
#            get_float(metadata["Fault Rupture Width (km)"]),
#            get_float(metadata["Depth to Top Of Fault Rupture Model"]),
#            hypo_loc=hypo_loc)
        eqk.rupture.get_area()
        return eqk