def test_get_rupture_enclosing_polygon(self):
        source, _ = self.make_non_parametric_source()

        poly = source.get_rupture_enclosing_polygon(dilation=0)
        expected_poly = Polygon(
            [Point(-1, -1),
             Point(-1, 1),
             Point(1, 1),
             Point(1, -1)])
        numpy.testing.assert_equal(poly.lons, expected_poly.lons)
        numpy.testing.assert_equal(poly.lats, expected_poly.lats)

        poly = source.get_rupture_enclosing_polygon(dilation=200)
        poly._init_polygon2d()
        expected_poly = expected_poly.dilate(200)
        expected_poly._init_polygon2d()

        # we check that the percent difference between the two polygons is
        # almost zero
        # in this case the area of the difference is ~ 8 km**2, with
        # respect to area of the computed polygon (~ 352795 km**2) and the area
        # of the predicted polygon (~ 352803 km**2)
        diff = 100 * poly._polygon2d.\
            symmetric_difference(expected_poly._polygon2d).area
        diff /= expected_poly._polygon2d.area
        self.assertAlmostEqual(diff, 0, places=2)
Example #2
0
    def _get_limits_maximum_rjb(self, maximum_distance):
        """
        Returns the bounding box of a polyon representing the locations of
        maximum distance from the rupture
        """
        top_left = deepcopy(self.surface.top_left)
        top_left.depth = 0.

        top_right = deepcopy(self.surface.top_right)
        top_right.depth = 0.

        bottom_left = deepcopy(self.surface.bottom_left)
        bottom_left.depth = 0.

        bottom_right = deepcopy(self.surface.bottom_right)
        bottom_right.depth = 0.

        surface_projection = Polygon([top_left,
                                      top_right,
                                      bottom_right,
                                      bottom_left])
        dilated_projection = surface_projection.dilate(maximum_distance)
        return (np.min(dilated_projection.lons),
                np.max(dilated_projection.lons),
                np.min(dilated_projection.lats),
                np.max(dilated_projection.lats))
Example #3
0
    def _get_limits_maximum_rjb(self, maximum_distance):
        """
        Returns the bounding box of a polyon representing the locations of
        maximum distance from the rupture
        """
        top_left = deepcopy(self.surface.top_left)
        top_left.depth = 0.

        top_right = deepcopy(self.surface.top_right)
        top_right.depth = 0.

        bottom_left = deepcopy(self.surface.bottom_left)
        bottom_left.depth = 0.

        bottom_right = deepcopy(self.surface.bottom_right)
        bottom_right.depth = 0.

        surface_projection = Polygon([top_left,
                                      top_right,
                                      bottom_right,
                                      bottom_left])
        dilated_projection = surface_projection.dilate(maximum_distance)
        return (np.min(dilated_projection.lons),
                np.max(dilated_projection.lons),
                np.min(dilated_projection.lats),
                np.max(dilated_projection.lats))
Example #4
0
 def test_implied_point_sources(self):
     source = self.make_area_source(Polygon([Point(-2, -2), Point(0, -2),
                                             Point(0, 0), Point(-2, 0)]),
                                    discretization=66.7,
                                    rupture_mesh_spacing=5)
     ruptures = list(source.iter_ruptures())
     self.assertEqual(
         len(ruptures), source.count_ruptures())  # 9 * 2 ruptures
     # resulting 3x3 mesh has points in these coordinates:
     lons = [-1.4, -0.8, -0.2]
     lats = [-0.6, -1.2, -1.8]
     depths = [4.0, 8.0]
     ruptures_iter = iter(ruptures)
     for lat in lats:
         for lon in lons:
             r1 = next(ruptures_iter)
             r2 = next(ruptures_iter)
             r3 = next(ruptures_iter)
             r4 = next(ruptures_iter)
             for iloc, rupture in enumerate([r1, r2]):
                 self.assertAlmostEqual(rupture.hypocenter.longitude,
                                        lon, delta=1e-3)
                 self.assertAlmostEqual(rupture.hypocenter.latitude,
                                        lat, delta=1e-3)
                 self.assertAlmostEqual(rupture.hypocenter.depth,
                                        depths[iloc], delta=1e-3)
             self.assertEqual(r1.mag, 5.5)
             self.assertEqual(r2.mag, 5.5)
             self.assertEqual(r3.mag, 6.5)
             self.assertEqual(r4.mag, 6.5)
     self.assertEqual(len(ruptures), 9 * 4)
Example #5
0
 def test_implied_point_sources(self):
     source = self.make_area_source(Polygon([Point(-2, -2), Point(0, -2),
                                             Point(0, 0), Point(-2, 0)]),
                                    discretization=66.7,
                                    rupture_mesh_spacing=5)
     ruptures = list(source.iter_ruptures(PoissonTOM(50)))
     self.assertEqual(len(ruptures), 9 * 2)
     # resulting 3x3 mesh has points in these coordinates:
     lons = [-1.4, -0.8, -0.2]
     lats = [-0.6, -1.2, -1.8]
     ruptures_iter = iter(ruptures)
     for lat in lats:
         for lon in lons:
             r1 = next(ruptures_iter)
             r2 = next(ruptures_iter)
             for rupture in [r1, r2]:
                 self.assertAlmostEqual(rupture.hypocenter.longitude,
                                        lon, delta=1e-3)
                 self.assertAlmostEqual(rupture.hypocenter.latitude,
                                        lat, delta=1e-3)
                 self.assertEqual(rupture.surface.mesh_spacing, 5)
                 self.assertIs(rupture.source_typology, AreaSource)
             self.assertEqual(r1.mag, 5.5)
             self.assertEqual(r2.mag, 6.5)
     self.assertEqual(len(ruptures), 9 * 2)
Example #6
0
class _BaseSeismicSourceTestCase(unittest.TestCase):
    POLYGON = Polygon([Point(0, 0), Point(0, 0.001),
                       Point(0.001, 0.001), Point(0.001, 0)])
    SITES = [
        Site(Point(0.0005, 0.0005, -0.5), 0.1, 3, 4),  # inside, middle
        Site(Point(0.0015, 0.0005), 1, 3, 4),  # outside, middle-east
        Site(Point(-0.0005, 0.0005), 2, 3, 4),  # outside, middle-west
        Site(Point(0.0005, 0.0015), 3, 3, 4),  # outside, north-middle
        Site(Point(0.0005, -0.0005), 4, 3, 4),  # outside, south-middle
        Site(Point(0., 0.), 5, 3, 4),  # south-west corner
        Site(Point(0., 0.001), 6, 3, 4),  # north-west corner
        Site(Point(0.001, 0.001), 7, 3, 4),  # north-east corner
        Site(Point(0.001, 0.), 8, 3, 4),  # south-east corner
        Site(Point(0., -0.01), 9, 3, 4),  # 1.1 km away
        Site(Point(0.3, 0.3), 10, 3, 4),  # 47 km away
        Site(Point(0., -1), 11, 3, 4),  # 111.2 km away
    ]

    def setUp(self):
        self.source_class = FakeSource
        mfd = EvenlyDiscretizedMFD(min_mag=3, bin_width=1,
                                   occurrence_rates=[5, 6, 7])
        self.source = FakeSource('source_id', 'name', const.TRT.VOLCANIC,
                                 mfd=mfd, rupture_mesh_spacing=2,
                                 magnitude_scaling_relationship=PeerMSR(),
                                 rupture_aspect_ratio=1,
                                 temporal_occurrence_model=PoissonTOM(50.))
        self.sitecol = SiteCollection(self.SITES)
Example #7
0
 def test_dilated(self):
     source = make_area_source(Polygon(
         [Point(4, 6), Point(5, 6), Point(4, 5)]),
                               discretization=100)
     polygon = source.get_rupture_enclosing_polygon(dilation=5)
     elons = [
         3.8387562, 3.8395259, 3.8418396, 3.8456751, 3.8509956, 3.8577500,
         3.8658734, 3.8752878, 3.8859026, 3.8976158, 3.9103145, 3.9238767,
         3.9381718, 3.9530621, 3.9684044, 3.9840509, 3.9998509, 5.0001491,
         5.0159419, 5.0315815, 5.0469172, 5.0618016, 5.0760915, 5.0896495,
         5.1023453, 5.1140566, 5.1246711, 5.1340866, 5.1422127, 5.1489714,
         5.1542977, 5.1581407, 5.1604635, 5.1612438, 5.1604744, 5.1581627,
         5.1543311, 5.1490166, 5.1422703, 5.1341571, 5.1247551, 5.1141547,
         4.1141530, 4.1024651, 4.0897882, 4.0762448, 4.0619656, 4.0470884,
         4.0317568, 4.0161187, 4.0003251, 3.9845284, 3.9688809, 3.9535336,
         3.9386348, 3.9243281, 3.9107516, 3.8980364, 3.8863052, 3.8756714,
         3.8662375, 3.8580948, 3.8513218, 3.8459842, 3.8421334, 3.8398068,
         3.8390269
     ]
     elats = [
         5.9999784, 6.0156881, 6.0312472, 6.0465059, 6.0613173, 6.0755391,
         6.0890342, 6.1016728, 6.1133333, 6.1239034, 6.1332813, 6.1413768,
         6.1481120, 6.1534219, 6.1572555, 6.1595758, 6.1603605, 6.1603605,
         6.1595765, 6.1572583, 6.1534281, 6.1481229, 6.1413937, 6.1333052,
         6.1239352, 6.1133738, 6.1017226, 6.0890937, 6.0756085, 6.0613967,
         6.0465949, 6.0313455, 6.0157950, 6.0000929, 5.9843902, 5.9688377,
         5.9535850, 5.9387786, 5.9245607, 5.9110681, 5.8984302, 5.8867686,
         4.8869567, 4.8763401, 4.8669175, 4.8587797, 4.8520053, 4.8466598,
         4.8427945, 4.8404470, 4.8396398, 4.8403806, 4.8426625, 4.8464633,
         4.8517463, 4.8584606, 4.8665414, 4.8759108, 4.8864782, 4.8981417,
         4.9107887, 4.9242972, 4.9385367, 4.9533698, 4.9686533, 4.9842397,
         4.9999784
     ]
     numpy.testing.assert_allclose(polygon.lons, elons)
     numpy.testing.assert_allclose(polygon.lats, elats)
Example #8
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.)
Example #9
0
 def test_occurrence_rate_rescaling(self):
     mfd = EvenlyDiscretizedMFD(min_mag=4, bin_width=1,
                                occurrence_rates=[3])
     polygon = Polygon([Point(0, 0), Point(0, -0.2248),
                        Point(-0.2248, -0.2248), Point(-0.2248, 0)])
     source = self.make_area_source(polygon, discretization=10, mfd=mfd)
     self.assertIs(source.mfd, mfd)
     ruptures = list(source.iter_ruptures())
     self.assertEqual(len(ruptures), 8)
     for rupture in ruptures:
         self.assertNotEqual(rupture.occurrence_rate, 3)
         self.assertEqual(rupture.occurrence_rate, 3.0 / 8.0)
def source_shapefile_to_dictionary(filename):
    """
    """
    sf = shapefile.Reader(filename)
    fields = [fld[0] for fld in sf.fields[1:]]
    data = []
    for rec in sf.shapeRecords():
        zone = dict([(key, val) for key, val in zip(fields[1:], rec.record)])
        zone["geometry"] = Polygon(
            [Point(pnt[0], pnt[1]) for pnt in rec.shape.points])
        data.append(zone)
    return data
Example #11
0
def parse_sites(oqparam):
    if (oqparam.region is not None):
        assert oqparam.region.startswith('POLYGON')
        """
        raise ValueError('More than one site is specified (N={len(site_ctx)}). Although '
                     'technically faesible using OQ library, this is not reasonable '
                     'for VPSHA calculations')
        """
        # Convert region specifications to polygon:
        reg_lons = [
            float(x.split(' ')[0]) for x in oqparam.region[9:-2].split(', ')
        ]
        reg_lats = [
            float(x.split(' ')[1]) for x in oqparam.region[9:-2].split(', ')
        ]
        pts = [Point(lon, lat) for lon, lat in zip(reg_lons, reg_lats)]
        poly = Polygon(pts)
        # Convert polygon to sitecolllection:
        mesh = poly.discretize(oqparam.region_grid_spacing)
        sites = [
            Site(Point(lon, lat, depth),
                 vs30=oqparam.reference_vs30_value,
                 z1pt0=oqparam.reference_depth_to_1pt0km_per_sec,
                 z2pt5=oqparam.reference_depth_to_2pt5km_per_sec)
            for lon, lat, depth in zip(mesh.lons, mesh.lats, mesh.depths)
        ]
        sites_col = SiteCollection(sites)
    elif isinstance(oqparam.sites, list):
        sites = [
            Site(Point(s[0], s[1], s[2]),
                 vs30=oqparam.reference_vs30_value,
                 z1pt0=oqparam.reference_depth_to_1pt0km_per_sec,
                 z2pt5=oqparam.reference_depth_to_2pt5km_per_sec)
            for s in oqparam.sites
        ]
        sites_col = SiteCollection(sites)
    else:
        assert isinstance(oqparam.sites, SiteCollection)
        sites_col = oqparam.sites
    return sites_col
Example #12
0
    def test_end_to_end(self):
        """
        Tests PenalizedMLE with bootstrapping and increased sample size
        and asserts that the known b-value and (approx) rate
        are within a narrow range (0.4 - 0.6 quantiles)
        """
        poly1 = Polygon([
            Point(20.0, 30.0),
            Point(20.0, 40.0),
            Point(30.0, 40.0),
            Point(30.0, 30.0)
        ])
        self.config = {
            "b_prior": 0.9,
            "reference_magnitude": 3.0,
            "b_prior_weight": 25.0,
            "a_prior": 0.0,
            "a_prior_weight": 0.0,
            "area": area_of_polygon(poly1),
            "mmax": 8.0
        }

        sample_size = [5, 10, 20, 50, 100, 200, 500, 1000]
        expected_b = 0.9
        for sample in sample_size:
            outputs = []
            expected_rate = (float(sample) /
                             float(self.catalogue.get_number_events())) * 100.
            for i in range(1000):
                idx = np.arange(self.catalogue.get_number_events())
                np.random.shuffle(idx)
                idx = idx[:sample]
                new_cat = deepcopy(self.catalogue)
                new_cat.select_catalogue_events(np.sort(idx))
                mle = PenalizedMLE()
                bval, sigmab, rate, sigma_rate = mle.calculate(
                    new_cat, self.config, self.completeness)
                outputs.append([bval, sigmab, rate, sigma_rate])
            outputs = np.array(outputs)
            mean_b = np.mean(outputs[:, 0])
            mean_sigmab = np.mean(outputs[:, 1])
            mean_rate = np.mean(outputs[:, 2])
            mean_sigma_rate = np.mean(outputs[:, 3])
            # Assert that b-value is in the expected range
            l_b, u_b = (norm.ppf(0.4, loc=mean_b, scale=mean_sigmab),
                        norm.ppf(0.6, loc=mean_b, scale=mean_sigmab))
            self.assertTrue((0.9 >= l_b) and (0.9 <= u_b))
            # Assert that rate is in the expected range
            l_b, u_b = (norm.ppf(0.4, loc=mean_rate, scale=mean_sigma_rate),
                        norm.ppf(0.6, loc=mean_rate, scale=mean_sigma_rate))
            self.assertTrue((expected_rate >= l_b) and (expected_rate <= u_b))
    def test_get_rupture_enclosing_polygon(self):
        source, _ = self.make_non_parametric_source()

        poly = source.get_rupture_enclosing_polygon(dilation=0)
        expected_poly = Polygon(
            [Point(-1, -1), Point(-1, 1), Point(1, 1), Point(1, -1)]
        )
        numpy.testing.assert_equal(poly.lons, expected_poly.lons)
        numpy.testing.assert_equal(poly.lats, expected_poly.lats)

        poly = source.get_rupture_enclosing_polygon(dilation=200)
        poly._init_polygon2d()
        expected_poly = expected_poly.dilate(200)
        expected_poly._init_polygon2d()

        # we check that the percent difference between the two polygons is
        # almost zero
        # in this case the area of the difference is ~ 8 km**2, with
        # respect to area of the computed polygon (~ 352795 km**2) and the area
        # of the predicted polygon (~ 352803 km**2) 
        diff = 100 * poly._polygon2d.\
            symmetric_difference(expected_poly._polygon2d).area
        diff /= expected_poly._polygon2d.area
        self.assertAlmostEqual(diff, 0, places=2)
Example #14
0
 def test_no_dilation(self):
     source = make_area_source(Polygon(
         [Point(-4, -4), Point(-5, -4),
          Point(-4, -5)]),
                               discretization=100)
     polygon = source.get_rupture_enclosing_polygon()
     elons = [
         -3.8843265, -3.8841675, -3.8847229, -3.8863892, -3.8891507,
         -3.8929806, -3.8978421, -3.9036884, -3.9104632, -3.9181013,
         -3.9265289, -3.9356649, -3.9454212, -3.9557038, -3.9664135,
         -3.9774470, -3.9886980, -4.0000580, -4.0114174, -4.0226667,
         -4.0336974, -4.0444032, -4.0546808, -4.0644312, -4.0735603,
         -4.0819801, -5.0819794, -5.0895794, -5.0963177, -5.1021293,
         -5.1069586, -5.1107589, -5.1134939, -5.1151373, -5.1156733,
         -5.1150967, -5.1134133, -5.1106391, -5.1068010, -5.1019359,
         -5.0960906, -5.0893213, -5.0816932, -5.0732797, -5.0641616,
         -5.0544266, -5.0441683, -5.0334855, -5.0224807, -5.0112597,
         -4.9999306, -4.0000694, -3.9887278, -3.9774948, -3.9664787,
         -3.9557855, -3.9455184, -3.9357761, -3.9266527, -3.9182361,
         -3.9106073, -3.9038400, -3.8979993, -3.8931415, -3.8893136,
         -3.8865525, -3.8848847
     ]
     elats = [
         -3.9999909, -4.9999908, -5.0113054, -5.0225111, -5.0334999,
         -5.0441660, -5.0544065, -5.0641226, -5.0732208, -5.0816133,
         -5.0892192, -5.0959651, -5.1017861, -5.1066260, -5.1104381,
         -5.1131856, -5.1148422, -5.1153917, -5.1148289, -5.1131593,
         -5.1103988, -5.1065743, -5.1017224, -5.0958901, -5.0891335,
         -5.0815178, -4.0814048, -4.0730023, -4.0638977, -4.0541785,
         -4.0439382, -4.0332754, -4.0222926, -4.0110954, -3.9997916,
         -3.9884899, -3.9772990, -3.9663264, -3.9556777, -3.9454554,
         -3.9357577, -3.9266778, -3.9183031, -3.9107141, -3.9039838,
         -3.8981768, -3.8933490, -3.8895469, -3.8868069, -3.8851554,
         -3.8846083, -3.8846083, -3.8851566, -3.8868117, -3.8895577,
         -3.8933680, -3.8982061, -3.9040252, -3.9107693, -3.9183735,
         -3.9267644, -3.9358611, -3.9455761, -3.9558157, -3.9664812,
         -3.9774699, -3.9886758
     ]
     numpy.testing.assert_allclose(polygon.lons, elons)
     numpy.testing.assert_allclose(polygon.lats, elats)
Example #15
0
def _get_cluster_correction(dat, C, ctx, imt):
    """
    Get cluster correction. The use can specify various options through
    the cluster parameter. The available options are:
    - cluster = None
        In this case the code finds the most appropriate correction using
        the rupture position
    - cluster = 0
        No cluster correction
    - cluser = 1 or 4 or 5
        The code uses the correction for the given cluster
    """
    cluster = dat.cluster
    shape = ctx.sids.shape
    correction = np.zeros_like(shape)
    # st.dev.
    tau_L2L = np.zeros(shape)
    Bp_model = np.zeros(shape)
    phi_P2P = np.zeros(shape)

    # No cluster correction
    if cluster == 0:
        tau_L2L = C['tau_L2L']
        phi_P2P = C['phi_P2P']
        return correction, tau_L2L, Bp_model, phi_P2P
    # the code finds the most appropriate correction
    if cluster is None:
        mesh = Mesh(np.array([ctx.hypo_lon]), np.array([ctx.hypo_lat]))
        # midp = ctx.surface.get_middle_point()
        # mesh = Mesh(np.array([midp.longitude]),np.array([midp.latitude]))

        for key in REGIONS:
            coo = np.array(REGIONS[key])
            pnts = [Point(lo, la) for lo, la in zip(coo[:, 0], coo[:, 1])]
            poly = Polygon(pnts)
            within = poly.intersects(mesh)
            if all(within):
                cluster = int(key)
                break
    # if OUT clusters do not apply corrections
    if cluster is None:
        tau_L2L = C['tau_L2L']
        phi_P2P = C['phi_P2P']
        return correction, tau_L2L, Bp_model, phi_P2P
    else:
        # if IN clusters apply corrections
        # Cluster coefficients
        fname = 'P_model_cluster{:d}.csv'.format(cluster)
        fname = os.path.join(DATA_FOLDER, fname)
        data = np.loadtxt(fname, delimiter=",", skiprows=1)
        # for st.dev.
        fname2 = 'beta_dP2P_cluster{:d}.csv'.format(cluster)
        fname2 = os.path.join(DATA_FOLDER, fname2)
        data2 = np.loadtxt(fname2, delimiter=",", skiprows=1)
        # Compute the coefficients
        correction = np.zeros(shape)
        per = imt.period
        for idx in np.unique(dat.idxs):
            tmp = data[int(idx)]
            correction[dat.idxs == idx] = np.interp(per, dat.PERIODS, tmp[0:5])
        # Adding L2L correction
        label = "dL2L_cluster{:d}".format(cluster)
        correction += C[label]
        # compute st.dev.
        for idx in np.unique(dat.idxs):
            tmp2 = data2[int(idx)]
            Bp_model[dat.idxs == idx] = np.interp(per, dat.PERIODS, tmp2[0:5])
        return correction, tau_L2L, Bp_model, phi_P2P
Example #16
0
    def test_areasource(self):
        nodalplane = NodalPlane(strike=0.0, dip=90.0, rake=0.0)
        src = AreaSource(source_id='src_1',
                         name='area source',
                         tectonic_region_type='Active Shallow Crust',
                         mfd=TruncatedGRMFD(a_val=3.5,
                                            b_val=1.0,
                                            min_mag=5.0,
                                            max_mag=6.5,
                                            bin_width=0.1),
                         nodal_plane_distribution=PMF([(1.0, nodalplane)]),
                         hypocenter_distribution=PMF([(1.0, 5.0)]),
                         upper_seismogenic_depth=0.0,
                         lower_seismogenic_depth=10.0,
                         magnitude_scaling_relationship=WC1994(),
                         rupture_aspect_ratio=1.0,
                         polygon=Polygon([
                             Point(-0.5, -0.5),
                             Point(-0.5, 0.5),
                             Point(0.5, 0.5),
                             Point(0.5, -0.5)
                         ]),
                         area_discretization=9.0,
                         rupture_mesh_spacing=1.0,
                         temporal_occurrence_model=PoissonTOM(50.))
        site = Site(location=Point(0.0, 0.0),
                    vs30=800.0,
                    vs30measured=True,
                    z1pt0=500.0,
                    z2pt5=2.0)
        gsims = {'Active Shallow Crust': BooreAtkinson2008()}
        imt = SA(period=0.1, damping=5.0)
        iml = 0.2
        truncation_level = 3.0
        n_epsilons = 3
        mag_bin_width = 0.2
        # in km
        dist_bin_width = 10.0
        # in decimal degree
        coord_bin_width = 0.2

        # compute disaggregation
        bin_edges, diss_matrix = disagg.disaggregation(
            [src], site, imt, iml, gsims, truncation_level, n_epsilons,
            mag_bin_width, dist_bin_width, coord_bin_width)
        mag_bins, dist_bins, lon_bins, lat_bins, eps_bins, trt_bins = bin_edges
        numpy.testing.assert_almost_equal(
            mag_bins, [5., 5.2, 5.4, 5.6, 5.8, 6., 6.2, 6.4, 6.6])
        numpy.testing.assert_almost_equal(
            dist_bins, [0., 10., 20., 30., 40., 50., 60., 70., 80.])
        numpy.testing.assert_almost_equal(
            lat_bins, [-0.6, -0.4, -0.2, 0., 0.2, 0.4, 0.6])
        numpy.testing.assert_almost_equal(
            lon_bins, [-0.6, -0.4, -0.2, 0., 0.2, 0.4, 0.6])
        numpy.testing.assert_almost_equal(eps_bins, [-3., -1., 1., 3.])
        self.assertEqual(trt_bins, ['Active Shallow Crust'])

        expected_matrix = numpy.fromstring(
            codecs.decode(
                codecs.decode(
                    b"""\
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\
""", 'base64'), 'zip')).reshape((8, 8, 6, 6, 3, 1))
        numpy.testing.assert_almost_equal(diss_matrix, expected_matrix)
Example #17
0
 def polygon(self):
     """
     The underlying polygon
     `"""
     lons, lats = self.surface.surface_projection
     return Polygon([Point(lo, la) for lo, la in zip(lons, lats)])
Example #18
0
SET1_CASE10_SOURCE_POLYGON = SET1_CASE11_SOURCE_POLYGON = Polygon([
    Point(-122.000, 38.901),
    Point(-121.920, 38.899),
    Point(-121.840, 38.892),
    Point(-121.760, 38.881),
    Point(-121.682, 38.866),
    Point(-121.606, 38.846),
    Point(-121.532, 38.822),
    Point(-121.460, 38.794),
    Point(-121.390, 38.762),
    Point(-121.324, 38.727),
    Point(-121.261, 38.688),
    Point(-121.202, 38.645),
    Point(-121.147, 38.600),
    Point(-121.096, 38.551),
    Point(-121.050, 38.500),
    Point(-121.008, 38.446),
    Point(-120.971, 38.390),
    Point(-120.940, 38.333),
    Point(-120.913, 38.273),
    Point(-120.892, 38.213),
    Point(-120.876, 38.151),
    Point(-120.866, 38.089),
    Point(-120.862, 38.026),
    Point(-120.863, 37.963),
    Point(-120.869, 37.900),
    Point(-120.881, 37.838),
    Point(-120.899, 37.777),
    Point(-120.921, 37.717),
    Point(-120.949, 37.658),
    Point(-120.982, 37.601),
    Point(-121.020, 37.545),
    Point(-121.063, 37.492),
    Point(-121.110, 37.442),
    Point(-121.161, 37.394),
    Point(-121.216, 37.349),
    Point(-121.275, 37.308),
    Point(-121.337, 37.269),
    Point(-121.403, 37.234),
    Point(-121.471, 37.203),
    Point(-121.542, 37.176),
    Point(-121.615, 37.153),
    Point(-121.690, 37.133),
    Point(-121.766, 37.118),
    Point(-121.843, 37.108),
    Point(-121.922, 37.101),
    Point(-122.000, 37.099),
    Point(-122.078, 37.101),
    Point(-122.157, 37.108),
    Point(-122.234, 37.118),
    Point(-122.310, 37.133),
    Point(-122.385, 37.153),
    Point(-122.458, 37.176),
    Point(-122.529, 37.203),
    Point(-122.597, 37.234),
    Point(-122.663, 37.269),
    Point(-122.725, 37.308),
    Point(-122.784, 37.349),
    Point(-122.839, 37.394),
    Point(-122.890, 37.442),
    Point(-122.937, 37.492),
    Point(-122.980, 37.545),
    Point(-123.018, 37.601),
    Point(-123.051, 37.658),
    Point(-123.079, 37.717),
    Point(-123.101, 37.777),
    Point(-123.119, 37.838),
    Point(-123.131, 37.900),
    Point(-123.137, 37.963),
    Point(-123.138, 38.026),
    Point(-123.134, 38.089),
    Point(-123.124, 38.151),
    Point(-123.108, 38.213),
    Point(-123.087, 38.273),
    Point(-123.060, 38.333),
    Point(-123.029, 38.390),
    Point(-122.992, 38.446),
    Point(-122.950, 38.500),
    Point(-122.904, 38.551),
    Point(-122.853, 38.600),
    Point(-122.798, 38.645),
    Point(-122.739, 38.688),
    Point(-122.676, 38.727),
    Point(-122.610, 38.762),
    Point(-122.540, 38.794),
    Point(-122.468, 38.822),
    Point(-122.394, 38.846),
    Point(-122.318, 38.866),
    Point(-122.240, 38.881),
    Point(-122.160, 38.892),
    Point(-122.080, 38.899),
])
Example #19
0
 def setUp(self):
     self.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)])
Example #20
0
src = AreaSource(
    source_id='1',
    name='area',
    tectonic_region_type='Active Shallow Crust',
    mfd=TruncatedGRMFD(min_mag=5., max_mag=6.5, bin_width=0.2, a_val=3.45, b_val=0.98),
    rupture_mesh_spacing=2.,
    magnitude_scaling_relationship=WC1994(),
    rupture_aspect_ratio=1.,
    temporal_occurrence_model=PoissonTOM(50.),
    upper_seismogenic_depth=2.,
    lower_seismogenic_depth=12.,
    nodal_plane_distribution=PMF([(1, NodalPlane(strike=45, dip=30, rake=0))]),
    hypocenter_distribution=PMF([(1, 7.)]),
    polygon=Polygon([Point(133.5, -22.5), Point(133.5, -23.0), Point(130.75, -23.75), Point(130.75, -24.5),
                     Point(133.5, -26.0), Point(133.5, -27.0), Point(130.75, -27.0), Point(128.977, -25.065),
                     Point(128.425, -23.436), Point(126.082, -23.233), Point(125.669, -22.351), Point(125.4, -20.5),
                     Point(125.75, -20.25), Point(126.7, -21.25), Point(128.5, -21.25), Point(129.25, -20.6),
                     Point(130.0, -20.6), Point(130.9, -22.25), Point(133.0, -22.0), Point(133.5, -22.5)]),
    area_discretization=20.
)


src = area_model

# loop over ruptures, extract rupture surface boundary and magnitude
min_lon, max_lon, min_lat, max_lat, m = get_map_projection(src)

boundaries = []
mags = []
for rup in src.iter_ruptures():
    surf = rup.surface
Example #21
0
    def test_areasource(self):
        nodalplane = NodalPlane(strike=0.0, dip=90.0, rake=0.0)
        src = AreaSource(source_id='src_1',
                         name='area source',
                         tectonic_region_type='Active Shallow Crust',
                         mfd=TruncatedGRMFD(a_val=3.5,
                                            b_val=1.0,
                                            min_mag=5.0,
                                            max_mag=6.5,
                                            bin_width=0.1),
                         nodal_plane_distribution=PMF([(1.0, nodalplane)]),
                         hypocenter_distribution=PMF([(1.0, 5.0)]),
                         upper_seismogenic_depth=0.0,
                         lower_seismogenic_depth=10.0,
                         magnitude_scaling_relationship=WC1994(),
                         rupture_aspect_ratio=1.0,
                         polygon=Polygon([
                             Point(-0.5, -0.5),
                             Point(-0.5, 0.5),
                             Point(0.5, 0.5),
                             Point(0.5, -0.5)
                         ]),
                         area_discretization=9.0,
                         rupture_mesh_spacing=1.0,
                         temporal_occurrence_model=PoissonTOM(50.))
        site = Site(location=Point(0.0, 0.0),
                    vs30=800.0,
                    vs30measured=True,
                    z1pt0=500.0,
                    z2pt5=2.0)
        gsims = {'Active Shallow Crust': BooreAtkinson2008()}
        imt = SA(period=0.1, damping=5.0)
        iml = 0.2
        truncation_level = 3.0
        n_epsilons = 3
        mag_bin_width = 0.2
        # in km
        dist_bin_width = 10.0
        # in decimal degree
        coord_bin_width = 0.2

        # compute disaggregation
        bin_edges, diss_matrix = disagg.disaggregation(
            [src], site, imt, iml, gsims, truncation_level, n_epsilons,
            mag_bin_width, dist_bin_width, coord_bin_width)
        mag_bins, dist_bins, lon_bins, lat_bins, eps_bins, trt_bins = bin_edges
        numpy.testing.assert_almost_equal(
            mag_bins, [5., 5.2, 5.4, 5.6, 5.8, 6., 6.2, 6.4, 6.6])
        numpy.testing.assert_almost_equal(
            dist_bins, [0., 10., 20., 30., 40., 50., 60., 70., 80.])
        numpy.testing.assert_almost_equal(lat_bins, [
            -6.5544231e-01, -4.9158173e-01, -3.2772115e-01, -1.6386058e-01,
            1.1102230e-16, 1.6386058e-01, 3.2772115e-01, 4.9158173e-01,
            6.5544231e-01
        ])
        numpy.testing.assert_almost_equal(lon_bins, [
            -6.5544231e-01, -4.9158173e-01, -3.2772115e-01, -1.6386058e-01,
            1.1102230e-16, 1.6386058e-01, 3.2772115e-01, 4.9158173e-01,
            6.5544231e-01
        ])
        numpy.testing.assert_almost_equal(eps_bins, [-3., -1., 1., 3.])
        self.assertEqual(trt_bins, ['Active Shallow Crust'])

        self.assertEqual(diss_matrix.shape, (8, 8, 8, 8, 3, 1))
        expected = [
            0.0245487, 0.0231275, 0.0210702, 0.0185196, 0.0157001, 0.0130175,
            0.0107099, 0.0045489
        ]
        numpy.testing.assert_almost_equal(
            diss_matrix.sum(axis=(1, 2, 3, 4, 5)), expected)