示例#1
0
def _setup_fault_source():
    """
    Builds a fault source using the PEER Bending Fault case.
    """
    point_order_dipping_east = [
        Point(-64.78365, -0.45236),
        Point(-64.80164, -0.45236),
        Point(-64.90498, -0.36564),
        Point(-65.0000, -0.16188),
        Point(-65.0000, 0.0000)
    ]
    trace_dip_east = Line(point_order_dipping_east)
    fault_surface1 = SimpleFaultSurface.from_fault_data(
        trace_dip_east, 0.0, 12.0, 60., 1.0)
    # Activity Rates
    # cm per km2
    area = 60. * 12.0 / np.sin(np.radians(60.))
    cm2perkm2 = (100. * 1000.)**2.
    mo1 = 3.0E11 * 0.2 * (area * cm2perkm2)
    mo_m6p75 = 10.0**(16.05 + 1.5 * 6.75)
    rate1 = mo1 / mo_m6p75
    mfd1 = EvenlyDiscretizedMFD(6.75, 0.01, [rate1])
    tom = PoissonTOM(1.0)
    aspect = 2.0
    rake = 90.0
    src = SimpleFaultSource("PEER_FLT_EAST", "PEER Bending Fault Dipping East",
                            "Active Shallow Crust", mfd1, 1.0, PeerMSR(), 2.0,
                            tom, 0.0, 12.0, trace_dip_east, 60.0, rake)
    src.num_ruptures = src.count_ruptures()
    return src
示例#2
0
 def test(self):
     sitecol = SiteCollection([Site(Point(-65.13490, 0.0),
                               vs30=760., z1pt0=48.0, z2pt5=0.607,
                               vs30measured=True)])
     mfd = ArbitraryMFD([6.0], [0.01604252])
     trace = Line([Point(-65.0000, -0.11240), Point(-65.000, 0.11240)])
     # 1.0 km Mesh Spacing
     mesh_spacing = 1.0
     msr = PeerMSR()
     sources = [SimpleFaultSource("001", "PEER Fault Set 2.5",
                                  "Active Shallow Crust", mfd,
                                  mesh_spacing,  msr, 2.0, PoissonTOM(1.0),
                                  0.0, 12., trace, 90., 0.)]
     imtls = {"PGA": [0.001, 0.01, 0.05, 0.1, 0.2, 0.4, 0.6, 0.8, 1.0,
                      1.25, 1.5, 2.0, 2.5, 3.0, 4.0, 5.0, 6.0, 7.0]}
     gmpe = ChiouYoungs2014PEER()
     gmpe.mixture_model = {"factors": [0.8, 1.2], "weights": [0.5, 0.5]}
     hcm = calc_hazard_curves(sources, sitecol, imtls,
                              {"Active Shallow Crust": gmpe})
     # Match against the benchmark is not exact - but differences in the
     # log space should be on the order of less than 0.04%
     expected = numpy.array([-4.140470001, -4.140913368, -4.259457496,
                             -4.724733842, -5.900747959, -7.734816415,
                             -9.019329629, -10.03864778, -10.90333404,
                             -11.83885783, -12.65826442, -14.05429951,
                             -15.22535996, -16.23988897, -17.94685518,
                             -19.36079032, -20.57460101, -21.64201335])
     expected = numpy.around(expected, 5)
     hcm_lnpga = numpy.around(numpy.log(hcm["PGA"].flatten()), 5)
     perc_diff = 100.0 * ((hcm_lnpga / expected) - 1.0)
     numpy.testing.assert_allclose(perc_diff, numpy.zeros(len(perc_diff)),
                                   atol=0.04)
示例#3
0
    def test_case_5(self):
        # only mfd differs from case 2
        sources = [SimpleFaultSource(source_id='fault1', name='fault1',
            tectonic_region_type=const.TRT.ACTIVE_SHALLOW_CRUST,
            mfd=test_data.SET1_CASE5_MFD,
            rupture_mesh_spacing=1.0,
            magnitude_scaling_relationship=PeerMSR(),
            rupture_aspect_ratio=test_data.SET1_RUPTURE_ASPECT_RATIO,
            temporal_occurrence_model=PoissonTOM(1.),
            upper_seismogenic_depth=test_data.SET1_CASE1TO9_UPPER_SEISMOGENIC_DEPTH,
            lower_seismogenic_depth=test_data.SET1_CASE1TO9_LOWER_SEISMOGENIC_DEPTH,
            fault_trace=test_data.SET1_CASE1TO9_FAULT_TRACE,
            dip=test_data.SET1_CASE1TO9_DIP,
            rake=test_data.SET1_CASE1TO9_RAKE
        )]
        sites = SiteCollection([
            test_data.SET1_CASE1TO9_SITE1, test_data.SET1_CASE1TO9_SITE2,
            test_data.SET1_CASE1TO9_SITE3, test_data.SET1_CASE1TO9_SITE4,
            test_data.SET1_CASE1TO9_SITE5, test_data.SET1_CASE1TO9_SITE6,
            test_data.SET1_CASE1TO9_SITE7
        ])
        gsims = {const.TRT.ACTIVE_SHALLOW_CRUST: SadighEtAl1997()}
        truncation_level = 0
        imts = {str(test_data.IMT): test_data.SET1_CASE5_IMLS}

        curves = calc_hazard_curves(
            sources, sites, imts, gsims, truncation_level)
        s1hc, s2hc, s3hc, s4hc, s5hc, s6hc, s7hc = curves[str(test_data.IMT)]

        assert_hazard_curve_is(self, s1hc, test_data.SET1_CASE5_SITE1_POES,
                               atol=1e-3, rtol=1e-5)
        assert_hazard_curve_is(self, s2hc, test_data.SET1_CASE5_SITE2_POES,
                               atol=1e-3, rtol=1e-5)
        assert_hazard_curve_is(self, s3hc, test_data.SET1_CASE5_SITE3_POES,
                               atol=1e-3, rtol=1e-5)
        assert_hazard_curve_is(self, s4hc, test_data.SET1_CASE5_SITE4_POES,
                               atol=1e-3, rtol=1e-5)
        assert_hazard_curve_is(self, s5hc, test_data.SET1_CASE5_SITE5_POES,
                               atol=1e-3, rtol=1e-5)
        assert_hazard_curve_is(self, s6hc, test_data.SET1_CASE5_SITE6_POES,
                               atol=1e-3, rtol=1e-5)
        assert_hazard_curve_is(self, s7hc, test_data.SET1_CASE5_SITE7_POES,
                               atol=1e-3, rtol=1e-5)
示例#4
0
 def setUp(self):
     """
     """
     mspa = 2.5
     #
     # Simple fault source
     mfd = EvenlyDiscretizedMFD(6.0, 0.1, [1.])
     msr = WC1994()
     tom = PoissonTOM(1.0)
     trace = Line([Point(10, 45.), Point(10., 45.2)])
     sfs = SimpleFaultSource(source_id='1',
                             name='1',
                             tectonic_region_type='none',
                             mfd=mfd,
                             rupture_mesh_spacing=mspa,
                             magnitude_scaling_relationship=msr,
                             rupture_aspect_ratio=1.0,
                             temporal_occurrence_model=tom,
                             upper_seismogenic_depth=0.,
                             lower_seismogenic_depth=10.,
                             fault_trace=trace,
                             dip=90.,
                             rake=90)
     self.srcs = [sfs]
     #
     #
     mfd = EvenlyDiscretizedMFD(6.0, 0.1, [1.])
     msr = WC1994()
     tom = PoissonTOM(1.0)
     trace = Line([Point(10.2, 45.), Point(10.2, 45.2)])
     sfs = SimpleFaultSource(source_id='2',
                             name='2',
                             tectonic_region_type='none',
                             mfd=mfd,
                             rupture_mesh_spacing=mspa,
                             magnitude_scaling_relationship=msr,
                             rupture_aspect_ratio=1.0,
                             temporal_occurrence_model=tom,
                             upper_seismogenic_depth=0.,
                             lower_seismogenic_depth=10.,
                             fault_trace=trace,
                             dip=90.,
                             rake=90)
     self.srcs.append(sfs)
     #
     #
     mfd = EvenlyDiscretizedMFD(6.0, 0.1, [1.])
     msr = WC1994()
     tom = PoissonTOM(1.0)
     trace = Line([Point(10.4, 45.), Point(10.4, 45.2)])
     sfs = SimpleFaultSource(source_id='3',
                             name='3',
                             tectonic_region_type='none',
                             mfd=mfd,
                             rupture_mesh_spacing=mspa,
                             magnitude_scaling_relationship=msr,
                             rupture_aspect_ratio=1.0,
                             temporal_occurrence_model=tom,
                             upper_seismogenic_depth=0.,
                             lower_seismogenic_depth=10.,
                             fault_trace=trace,
                             dip=90.,
                             rake=90)
     self.srcs.append(sfs)
     #
     #
     mfd = EvenlyDiscretizedMFD(6.0, 0.1, [1.])
     msr = WC1994()
     tom = PoissonTOM(1.0)
     trace = Line([Point(10.5, 45.), Point(10.6, 45.2)])
     sfs = SimpleFaultSource(source_id='4',
                             name='4',
                             tectonic_region_type='none',
                             mfd=mfd,
                             rupture_mesh_spacing=mspa,
                             magnitude_scaling_relationship=msr,
                             rupture_aspect_ratio=1.0,
                             temporal_occurrence_model=tom,
                             upper_seismogenic_depth=0.,
                             lower_seismogenic_depth=10.,
                             fault_trace=trace,
                             dip=90.,
                             rake=90)
     self.srcs.append(sfs)
def get_fault_sources(filename,
                      slip_rate_class,
                      bin_width=0.1,
                      m_low=6.5,
                      b_gr=1.0,
                      rupture_mesh_spacing=2.0,
                      upper_seismogenic_depth=0.0,
                      lower_seismogenic_depth=10.0,
                      msr=WC1994(),
                      rupture_aspect_ratio=2.0,
                      temporal_occurrence_model=PoissonTOM(1.0),
                      aseismic_coeff=0.9,
                      oqsource=False):
    """
    :parameter filename:
        The name of the .geojson file with fault data
    :parameter slip_rate_class:

    TODO: so far works only for slip_rate_class = "suggested/preferred"
    """

    logging.info('Reading %s and slip_type = %s' % (filename, slip_rate_class))
    with open(filename, 'r') as data_file:
        data = json.load(data_file)

    print('---------------------------------------'
          '---------------------------------------')

    # Configuration parameters to create the sources
    # TODO:
    # use b_gr values from the area_sources and not a generic value
    # to test the whole processing

    # LOOP over the faults/traces
    srcl = []
    for idf, feature in enumerate(data['features']):

        source_id = '{0:d}'.format(idf)
        tectonic_region_type = TRT.ACTIVE_SHALLOW_CRUST

        fs_name = ''
        ns_name = ''

        # get fault name[s] - id
        if feature['properties']['fs_name'] is not None:
            fs_name = feature['properties']['fs_name']
        if feature['properties']['fs_name'] is not None:
            ns_name = feature['properties']['fs_name']
        name = '{0:s} | {1:s}'.format(fs_name, ns_name)
        if 'ogc_fid' in feature['properties']:
            id_fault = feature['properties']['ogc_fid']
        else:
            id_fault = '%d' % (idf)

        # get fault slip type
        if feature['properties']['slip_type'] is not None:
            slipt = feature['properties']['slip_type']
            msg = 'Slip type value is [%s] for fault with name' % slipt
            msg += '%s and id %s' % (name, id_fault)
            logging.info(msg)
        else:
            msg = 'Slip type value is missing for fault with name'
            msg += '%s and id %s' % (name, id_fault)
            logging.warning(msg)

        # get dip direction
        if feature['properties']['ns_dip_dir'] is not None:
            dip_dir = feature['properties']['ns_dip_dir']
            print("'dip_dir'= ", dip_dir)
        else:
            msg = 'Dip direction value is missing for fault with name'
            msg += '%s and id %s' % (name, id_fault)
            logging.warning(msg)
            # JUST FOR TESTING REASONS
            dip_dir = "N"
            print("dip_dir fazzula= ", dip_dir)
            # continue

        # Get the tuples
        dipt = get_tples(feature['properties']['ns_average_dip'])
        print("dipt= ", dipt)
        raket = get_tples(feature['properties']['ns_average_rake'])
        print("raket= ", raket)
        sliprt = get_tples(feature['properties']['ns_net_slip_rate'])
        print("sliprt= ", sliprt)
        shor_rd = get_tples(feature['properties']['ns_shortening_rate'])
        print("shortening_rate= ", shor_rd)
        vert_rd = get_tples(feature['properties']['ns_vert_slip_rate'])
        print("vertical_slip_rate= ", vert_rd)
        stk_rd = get_tples(feature['properties']['ns_strike_slip_rate'])
        print("strike_slip_rate= ", stk_rd)

        # Set the value to be used [suggested, min, max]
        if slip_rate_class is 'suggested':
            valid_dip = False
            # Dip values
            dip = dipt[0]
            if dip is not None:
                valid_dip = _is_valid_dip(dip)
                if valid_dip:
                    print("Dip value = ", dip)
                    msg = 'Dip value is [%s] for fault with name' % (dip)
                    msg += '%s and id %s' % (name, id_fault)
                    logging.info(msg)
            # if dip is None, but slip_type is available
            elif (dip) is None and (slipt) is not None:
                dip = get_dip_from_slip_type(slipt)
                print('Dip value for id= %s is missing and was computed using '
                      'slipt= %s, new dip= %s ' % (id_fault, slipt, dip))
            # if dip is None, but slip_type is available
            elif (dip) is None and (slipt) is None:
                msg = ('Dip value is missing and could not be computed for'
                       ' fault with name ')
                msg += '%s and id %s' % (name, id_fault)
                logging.warning(msg)
                continue

            valid_rake = False
            # Rake values
            rake = raket[0]
            if rake is not None:
                valid_rake = _is_valid_rake(rake)
                if valid_rake:
                    print("Rake value = ", dip)
                    msg = 'Rake value is [%s] for fault with name' % rake
                    msg += '%s and id %s' % (name, id_fault)
                    logging.info(msg)
            # if rake is None, but slip_type is available
            elif (rake) is None and (slipt) is not None:
                rake = get_rake_from_rup_type(RAKE_CLASS, slipt)
                print('Rake value for id= %s is missing and was computed using'
                      ' slipt= %s, new rake= %s ' % (id_fault, slipt, rake))
                msg = ('Rake value is [%s] for slip_type= %s for fault with'
                       ' name' % (rake, slipt))
                msg += '%s and id %s' % (name, id_fault)
                logging.info(msg)
            # if rake and slip_type are not available
            elif (rake) is None and (slipt) is None:
                msg = ('Rake value is missing or could not be computed for'
                       ' fault with name ')
                msg += '%s and id %s' % (name, id_fault)
                logging.warning(msg)
                continue

            # Slip rate values [shortening, vertical, strike_slip, net_slip]
            # If net_slip value is not available, a value is computed when
            # other component are present in the database
            slipr = sliprt[0]
            shor_rv = shor_rd[0]
            stk_rv = stk_rd[0]
            vert_rv = vert_rd[0]

            msg = ('slipr= %s,  shor_rv= %s , stk_rv= %s, vert_rv= %s  for'
                   ' fault with name ' % (slipr, shor_rv, stk_rv, vert_rv))
            msg += '%s and id %s' % (name, id_fault)
            logging.info(msg)

            if (slipr) is None and (shor_rv, stk_rv, vert_rv):
                print('slipr= %s' % slipr)
                print('shor_rv= %s , stk_rv= %s, vert_rv= %s ' %
                      (shor_rv, stk_rv, vert_rv))
                slipr = get_net_slip(dip, rake, shor_rv, stk_rv, vert_rv)

            if slipr is None:
                msg = 'net_slip  value is missing or can not be computed'
                msg += 'for fault with name %s and id %s' % (name, id_fault)
                logging.warning(msg)
                continue

            # Finally the net_slip is penalized using the aseismic_coeff
            net_slip = aseismic_coeff * float(slipr)
            print('net_slip value for id= %s is net_slip= %s [slipr = %s] ' %
                  (id_fault, net_slip, slipt))

            msg = ('net_slip value [%.2f] computed for fault with name ' %
                   (net_slip))
            msg += ' %s and id %s' % (name, id_fault)
            logging.info(msg)

        elif slip_rate_class is 'min':

            # Dip values
            dip = dipt[1]
            if (dip) is None and (slipt):
                # MN: get_dip_from_slip_dir UNDEFINED, probably the
                #     method name is changed
                dip = get_dip_from_slip_dir(slipt)
                print('Dip value for id= %s is missing and was computed using'
                      ' slipt= %s, new dip= %s ' % (id_fault, slipt, dip))
            else:
                msg = 'Dip value is missing for fault with name '
                msg += '%s and id %s' % (name, id_fault)
                logging.warning(msg)
                # continue

            # Rake values
            rake = raket[1]
            if (rake) is None and (slipt):
                rake = get_rake_from_rup_type(RAKE_CLASS, slipt)
                print('Rake value for id= %s is missing and was computed using'
                      ' slipt= %s, new rake= %s ' % (id_fault, slipt, rake))
            else:
                msg = 'Rake value is missing for fault with name '
                msg += '%s and id %s' % (name, id_fault)
                logging.warning(msg)
                # continue
            # Slip rate values [shortening, vertical, strike_slip, net_slip]
            # If net_slip value is not available, a value is computed when
            # other component are present in the database
            slipr = sliprt[1]
            shor_rd = shor_rv[1]
            stk_rd = stk_rv[1]
            vert_rv = vert_rd[1]

            if (slipr) is None and (shor_rv, stk_rv, vert_rv):
                slipr = get_net_slip(shor_rv, stk_rv, vert_rv)
            else:
                msg = 'net_slip  value is missing or not can be computed'
                msg += 'for fault with name %s and id %s' % (name, id_fault)
                logging.warning(msg)
                continue
            # Finally the net_slip is penalized using the aseismic_coeff
            net_slip = aseismic_coeff * float(slipr)

        elif slip_rate_class is 'max':

            # Dip values
            dip = dipt[2]
            if (dip) is None and (slipt):
                # MN: get_dip_from_slip_dir undefined
                dip = get_dip_from_slip_dir(slipt)
                print('Dip value for id= %s is missing and was computed using '
                      'slipt= %s, new dip= %s ' % (id_fault, slipt, dip))
            else:
                msg = 'Dip value is missing for fault with name '
                msg += '%s and id %s' % (name, id_fault)
                logging.warning(msg)
                # continue

            # Rake values
            rake = raket[2]
            if (rake) is None and (slipt):
                rake = get_rake_from_rup_type(RAKE_CLASS, slipt)
                print('Rake value for id= %s is missing and was computed '
                      'using slipt= %s, new rake= %s ' %
                      (id_fault, slipt, rake))
            else:
                msg = 'Rake value is missing for fault with name '
                msg += '%s and id %s' % (name, id_fault)
                logging.warning(msg)
                # continue

            # Slip rate values [shortening, vertical, strike_slip, net_slip]
            # If net_slip value is not available, a value is computed when
            # other component are present in the database
            slipr = sliprt[2]
            shor_rd = shor_rv[2]
            stk_rd = stk_rv[2]
            vert_rv = vert_rd[0]

            if (slipr) is None and (shor_rv, stk_rv, vert_rv):
                slipr = get_net_slip(shor_rv, stk_rv, vert_rv)
            else:
                msg = 'net_slip  value is missing or not can be computed'
                msg += 'for fault with name %s and id %s' % (name, id_fault)
                logging.warning(msg)
                continue

            # Finally the net_slip is penalized using the aseismic_coeff
            net_slip = aseismic_coeff * float(slipr)

        else:
            raise ValueError('Invalid slip_rate_class')

        # Get fault trace geometry
        fault_trace = get_line(numpy.array(feature['geometry']['coordinates']))

        # Get dip direction angle from literal and strike from trace geometry
        mean_az_from_trace = _get_mean_az_from_trace(fault_trace)
        valid_az = False
        valid_az = _is_valid_strike(mean_az_from_trace)
        if valid_az:
            # print("Mean azimuth value from trace = ", mean_az_from_trace)
            msg = ('Mean azimuth value is [%s] for fault with name' %
                   (mean_az_from_trace))
            msg += '%s and id %s' % (name, id_fault)
            logging.info(msg)

        dip_dir_angle = _get_dip_dir_from_literal(dip_dir)

        # Check if it's necessary to revert the fault trace
        if (dip_dir_angle is not None
                and _need_to_revert(mean_az_from_trace, dip_dir_angle)):
            new_fault_trace = _revert_fault_trace(fault_trace)
            logging.info('The fault trace for id= %s was reverted' % id_fault)
        else:
            new_fault_trace = fault_trace

        if new_fault_trace:
            fault_trace = new_fault_trace

        # Get L from srl - See Table 5 of Leonard 2010
        # SRL: surface rupture length [km]
        # RLD: Subsurface horizontal rupture length [km]
        # IF SRL/RLD < 5. km the fault will be exclused
        srl = fault_trace.get_length()
        rld = 10**((numpy.log10(srl) + 0.275) / 1.1)

        if rld < 5.0:
            msg = 'SRL/RLD value is < 5.0 km for fault with name '
            msg += '%s and id %s' % (name, id_fault)
            logging.warning(msg)
            continue

        # Witdh
        width, cl = get_width_from_length(rld, slipt)
        # print("id=, %s, srl=, %.2f,  rld=, %.2f, width=, %.2f,
        # slipt=, %s, cl=,%s "%(id_fault, srl, rld, width, slipt,cl))
        msg = ("id=, %s, srl=, %.2f,  rld=, %.2f, width=, %.2f, slipt=, %s,"
               " cl=,%s " % (id_fault, srl, rld, width, slipt, cl))
        logging.info(msg)

        # Get lower seismogenic depth from length
        lsd = width * numpy.sin(numpy.radians(float(dip)))
        lower_seismogenic_depth = lsd

        # create the surface from fault data
        sfce = SimpleFaultSurface.from_fault_data(fault_trace,
                                                  upper_seismogenic_depth,
                                                  lower_seismogenic_depth, dip,
                                                  rupture_mesh_spacing)
        # compute the area of the surface
        area = sfce.get_area()

        # compute the Mmax
        m_upp = msr.get_median_mag(sfce.get_area(), rake)
        if m_upp < m_low:
            msg = 'Mx [%.2f] is lesser than Mmin [%.2f] for fault with name '\
                  % (m_upp, m_low)
            msg += '%s and id %s' % (name, id_fault)
            logging.warning(msg)

        tstr = '%3s - %-40s %5.2f' % (id_fault, name, m_upp)
        logging.info(tstr)

        if net_slip is not None:
            slip_rate = net_slip
            print("slip_rate= ", slip_rate)
        else:
            continue

        # constrainig the computation
        # Mx > Mmin=m_low
        # slip_rate >= 1e-10
        if slip_rate is not None and slip_rate >= 1e-10 and m_upp > m_low:

            # compute rates
            rates = rates_for_double_truncated_mfd(area, slip_rate, m_low,
                                                   m_upp, b_gr, bin_width)
            # MFD
            mfd = EvenlyDiscretizedMFD(m_low + bin_width / 2, bin_width, rates)

            # Source
            if oqsource:
                src = SimpleFaultSource(
                    source_id, name, tectonic_region_type, mfd,
                    rupture_mesh_spacing, msr, rupture_aspect_ratio,
                    temporal_occurrence_model, upper_seismogenic_depth,
                    lower_seismogenic_depth, fault_trace, dip, rake)
            else:
                src = OQtSource(source_id, source_type='SimpleFaultSource')
                src.name = name
                src.tectonic_region_type = tectonic_region_type
                src.mfd = mfd
                src.rupture_mesh_spacing = rupture_mesh_spacing
                src.slip_rate = slip_rate
                src.msr = msr
                src.rupture_aspect_ratio = rupture_aspect_ratio
                src.temporal_occurrence_model = temporal_occurrence_model
                src.upper_seismogenic_depth = upper_seismogenic_depth
                src.lower_seismogenic_depth = lower_seismogenic_depth
                src.trace = fault_trace
                src.dip = dip
                src.rake = rake
                print('right')

            srcl.append(src)

    return srcl
示例#6
0
    def test_case_2(self):
        sources = [
            SimpleFaultSource(
                source_id='fault1',
                name='fault1',
                tectonic_region_type=const.TRT.ACTIVE_SHALLOW_CRUST,
                mfd=test_data.SET1_CASE2_MFD,
                rupture_mesh_spacing=1.0,
                magnitude_scaling_relationship=PeerMSR(),
                rupture_aspect_ratio=test_data.SET1_RUPTURE_ASPECT_RATIO,
                upper_seismogenic_depth=test_data.
                SET1_CASE1TO9_UPPER_SEISMOGENIC_DEPTH,
                lower_seismogenic_depth=test_data.
                SET1_CASE1TO9_LOWER_SEISMOGENIC_DEPTH,
                fault_trace=test_data.SET1_CASE1TO9_FAULT_TRACE,
                dip=test_data.SET1_CASE1TO9_DIP,
                rake=test_data.SET1_CASE1TO9_RAKE)
        ]
        sites = SiteCollection([
            test_data.SET1_CASE1TO9_SITE1, test_data.SET1_CASE1TO9_SITE2,
            test_data.SET1_CASE1TO9_SITE3, test_data.SET1_CASE1TO9_SITE4,
            test_data.SET1_CASE1TO9_SITE5, test_data.SET1_CASE1TO9_SITE6,
            test_data.SET1_CASE1TO9_SITE7
        ])
        gsims = {const.TRT.ACTIVE_SHALLOW_CRUST: SadighEtAl1997()}
        truncation_level = 0
        time_span = 1.0
        imts = {test_data.IMT: test_data.SET1_CASE2_IMLS}

        curves = hazard_curves(sources, sites, imts, time_span, gsims,
                               truncation_level)
        s1hc, s2hc, s3hc, s4hc, s5hc, s6hc, s7hc = curves[test_data.IMT]

        assert_hazard_curve_is(self,
                               s1hc,
                               test_data.SET1_CASE2_SITE1_POES,
                               tolerance=3e-3)
        assert_hazard_curve_is(self,
                               s2hc,
                               test_data.SET1_CASE2_SITE2_POES,
                               tolerance=2e-5)
        assert_hazard_curve_is(self,
                               s3hc,
                               test_data.SET1_CASE2_SITE3_POES,
                               tolerance=2e-5)
        assert_hazard_curve_is(self,
                               s4hc,
                               test_data.SET1_CASE2_SITE4_POES,
                               tolerance=1e-3)
        assert_hazard_curve_is(self,
                               s5hc,
                               test_data.SET1_CASE2_SITE5_POES,
                               tolerance=1e-3)
        assert_hazard_curve_is(self,
                               s6hc,
                               test_data.SET1_CASE2_SITE6_POES,
                               tolerance=1e-3)
        assert_hazard_curve_is(self,
                               s7hc,
                               test_data.SET1_CASE2_SITE7_POES,
                               tolerance=2e-5)