예제 #1
0
def get_quad_slip(q, rake):
    """
    Compute the unit slip vector in ECEF space for a quad and rake angle.

    Args:
        q (list): A quadrilateral; list of four points.
        rake (float): Direction of motion of the hanging wall relative to
        the foot wall, as measured by the angle (deg) from the strike vector.

    Returns:
        Vector: Unit slip vector in ECEF space.

    """
    P0, P1, P2 = q[0:3]
    strike = P0.azimuth(P1)
    dip = get_quad_dip(q)
    s1_local = get_local_unit_slip_vector(strike, dip, rake)
    s0_local = Vector(0, 0, 0)
    qlats = [a.latitude for a in q]
    qlons = [a.longitude for a in q]
    proj = OrthographicProjection(
        np.min(qlons), np.max(qlons), np.min(qlats), np.max(qlats))
    s1_ll = proj(np.array([s1_local.x]), np.array([s1_local.y]), reverse=True)
    s0_ll = proj(np.array([s0_local.x]), np.array([s0_local.y]), reverse=True)
    s1_ecef = Vector.fromTuple(latlon2ecef(s1_ll[1], s1_ll[0], s1_local.z))
    s0_ecef = Vector.fromTuple(latlon2ecef(s0_ll[1], s0_ll[0], s0_local.z))
    slp_ecef = (s1_ecef - s0_ecef).norm()
    return slp_ecef
예제 #2
0
def test_ss3_m4p5():
    magnitude = 4.5
    dip = np.array([90])
    rake = 180.0
    width = np.array([15])
    rupx = np.array([0, 0])
    rupy = np.array([0, 80])
    zp = np.array([0])
    epix = np.array([0])
    epiy = np.array([0.2 * rupy[1]])

    # Convert to lat/lon
    proj = OrthographicProjection(-122, -120, 39, 37)
    tlon, tlat = proj(rupx, rupy, reverse=True)
    epilon, epilat = proj(epix, epiy, reverse=True)

    # Origin
    origin = Origin({'lat': epilat[0],
                     'lon': epilon[0],
                     'depth': 10,
                     'mag': magnitude,
                     'id': 'ss3',
                     'netid': '',
                     'network': '',
                     'locstring': '',
                     'rake': rake,
                     'time': HistoricTime.utcfromtimestamp(int(time.time()))})

    rup = QuadRupture.fromTrace(
        np.array([tlon[0]]), np.array([tlat[0]]),
        np.array([tlon[1]]), np.array([tlat[1]]),
        zp, width, dip, origin, reference='ss3')

    x = np.linspace(0, 20, 6)
    y = np.linspace(0, 90, 11)
    site_x, site_y = np.meshgrid(x, y)
    slon, slat = proj(site_x, site_y, reverse=True)
    deps = np.zeros_like(slon)

    test1 = Bayless2013(origin, rup, slat, slon, deps, T=1.0)

    # Test fd
    fd = test1.getFd()
    fd_test = np.array(
        [[0.,  0.,  0.,  0.,  0.,  0.],
         [0.,  0.,  0.,  0.,  0.,  0.],
            [0.,  0.,  0.,  0.,  0.,  0.],
            [0.,  0.,  0.,  0.,  0.,  0.],
            [0.,  0.,  0.,  0.,  0.,  0.],
            [0.,  0.,  0.,  0.,  0.,  0.],
            [0.,  0.,  0.,  0.,  0.,  0.],
            [0.,  0.,  0.,  0.,  0.,  0.],
            [0.,  0.,  0.,  0.,  0.,  0.],
            [0.,  0.,  0.,  0.,  0.,  0.],
            [0.,  0.,  0.,  0.,  0.,  0.]])
    np.testing.assert_allclose(
        fd, fd_test, rtol=1e-4)
예제 #3
0
def check_intersections(cs, css):
    """
    Fixes the cross section trace 'cs' given a set of pre-existing cross
    section traces in 'css'.

    :param cs:
        A cross section trace i.e. an instance of
        :class:`openquake.sub.cross_section.CrossSection`
    :param css:
        A list of pre-existing cross sections
    """

    # Get min and max
    mm = cs.get_mm()
    lngs = []
    for icc, cc in enumerate(css):
        cmm = cc.get_mm()
        intersect = check_bboxes_overlap(mm, cmm)
        if intersect:
            prj = OrthographicProjection(min(mm[0], cmm[0]),
                                         max(mm[1], cmm[1]),
                                         min(mm[2], cmm[2]),
                                         min(mm[3], cmm[3]))
            ox, oy = prj(cs.plo, cs.pla)
            cx, cy = prj(cc.plo, cc.pla)

            for i in range(len(ox)-1):
                pa = numpy.array([ox[i], oy[i]])
                pb = numpy.array([ox[i+1], oy[i+1]])
                for j in range(len(cx)-1):
                    pc = numpy.array([cx[j], cy[j]])
                    pd = numpy.array([cx[j+1], cy[j+1]])
                    chk = check_segments_intersection(pa, pb, pc, pd)
                    if chk:
                        # Calculate intersection point
                        den = (pa[0]-pb[0])
                        a1 = (pa[1]-pb[1])/den if abs(den) > 1e-10 else 1e100
                        den = (pc[0]-pd[0])
                        a2 = (pc[1]-pd[1])/den if abs(den) > 1e-10 else 1e100
                        b1 = pa[1] - a1*pa[0]
                        b2 = pc[1] - a2*pc[0]
                        den = (a1 - a2)
                        xp = (b2 - b1) / den if abs(den) > 1e-10 else 1e100
                        yp = a1 * xp + b1
                        lng = ((ox[i]-xp)**2 + (oy[i]-yp)**2)**0.5
                        lngs.append(lng)
    if len(lngs):
        return numpy.min(numpy.array(lngs))
    else:
        return None
예제 #4
0
def _computeGC2(rupture, lon, lat, depth):
    """
    Method for computing GC2 from a ShakeMap Rupture instance.

    Args:
        rupture (Rupture): ShakeMap rupture object.
        lon (array): Numpy array of site longitudes.
        lat (array): Numpy array of site latitudes.
        depth (array): Numpy array of site depths.

    Returns:
        dict: Dictionary of GC2 distances. Keys include "T", "U", "rx"
            "ry", "ry0".
    """

    quadlist = rupture.getQuadrilaterals()
    quadgc2 = copy.deepcopy(quadlist)

    oldshape = lon.shape

    if len(oldshape) == 2:
        newshape = (oldshape[0] * oldshape[1], 1)
    else:
        newshape = (oldshape[0], 1)

    # -------------------------------------------------------------------------
    # Define a projection that spans sites and rupture
    # -------------------------------------------------------------------------

    all_lat = np.append(lat, rupture.lats)
    all_lon = np.append(lon, rupture.lons)

    west = np.nanmin(all_lon)
    east = np.nanmax(all_lon)
    south = np.nanmin(all_lat)
    north = np.nanmax(all_lat)
    proj = OrthographicProjection(west, east, north, south)

    totweight = np.zeros(newshape, dtype=lon.dtype)
    GC2T = np.zeros(newshape, dtype=lon.dtype)
    GC2U = np.zeros(newshape, dtype=lon.dtype)

    # -------------------------------------------------------------------------
    # First sort out strike discordance and nominal strike prior to
    # starting the loop if there is more than one group/trace.
    # -------------------------------------------------------------------------
    group_ind = rupture._getGroupIndex()

    # Need group_ind as numpy array for sensible indexing...
    group_ind_np = np.array(group_ind)
    uind = np.unique(group_ind_np)
    n_groups = len(uind)

    if n_groups > 1:
        # ---------------------------------------------------------------------
        # The first thing we need to worry about is finding the coordinate
        # shift. U's origin is "selected from the two endpoints most
        # distant from each other."
        # ---------------------------------------------------------------------

        # Need to get index of first and last quad
        # for each segment
        iq0 = np.zeros(n_groups, dtype='int16')
        iq1 = np.zeros(n_groups, dtype='int16')
        for k in uind:
            ii = [i for i, j in enumerate(group_ind) if j == uind[k]]
            iq0[k] = int(np.min(ii))
            iq1[k] = int(np.max(ii))

        # ---------------------------------------------------------------------
        # This is an iterator for each possible combination of traces
        # including trace orientations (i.e., flipped).
        # ---------------------------------------------------------------------

        it_seg = it.product(it.combinations(uind, 2), it.product([0, 1],
                                                                 [0, 1]))

        # Placeholder for the trace pair/orientation that gives the
        # largest distance.
        dist_save = 0

        for k in it_seg:
            s0ind = k[0][0]
            s1ind = k[0][1]
            p0ind = k[1][0]
            p1ind = k[1][1]
            if p0ind == 0:
                P0 = quadlist[iq0[s0ind]][0]
            else:
                P0 = quadlist[iq1[s0ind]][1]
            if p1ind == 0:
                P1 = quadlist[iq1[s1ind]][0]
            else:
                P1 = quadlist[iq0[s1ind]][1]

            dist = geodetic.distance(P0.longitude, P0.latitude, 0.0,
                                     P1.longitude, P1.latitude, 0.0)
            if dist > dist_save:
                dist_save = dist
                A0 = P0
                A1 = P1

        # ---------------------------------------------------------------------
        # A0 and A1 are the furthest two segment endpoints, but we still
        # need to sort out which one is the "origin".
        # ---------------------------------------------------------------------

        # This goofy while-loop is to adjust the side of the rupture where the
        # origin is located
        dummy = -1
        while dummy < 0:
            A0.depth = 0
            A1.depth = 0
            p_origin = Vector.fromPoint(A0)
            a0 = Vector.fromPoint(A0)
            a1 = Vector.fromPoint(A1)
            ahat = (a1 - a0).norm()

            # Loop over traces
            e_j = np.zeros(n_groups)
            b_prime = [None] * n_groups
            for j in range(n_groups):
                P0 = quadlist[iq0[j]][0]
                P1 = quadlist[iq1[j]][1]
                P0.depth = 0
                P1.depth = 0
                p0 = Vector.fromPoint(P0)
                p1 = Vector.fromPoint(P1)
                b_prime[j] = p1 - p0
                e_j[j] = ahat.dot(b_prime[j])
            E = np.sum(e_j)

            # List of discordancy
            dc = [np.sign(a) * np.sign(E) for a in e_j]
            b = Vector(0, 0, 0)
            for j in range(n_groups):
                b.x = b.x + b_prime[j].x * dc[j]
                b.y = b.y + b_prime[j].y * dc[j]
                b.z = b.z + b_prime[j].z * dc[j]
            bhat = b.norm()
            dummy = bhat.dot(ahat)
            if dummy < 0:
                tmpA0 = copy.deepcopy(A0)
                A0 = copy.deepcopy(A1)
                A1 = tmpA0

        # ---------------------------------------------------------------------
        # To fix discordancy, need to flip quads and rearrange
        # the order of quadgc2
        # ---------------------------------------------------------------------

        # 1) flip quads
        for i in range(len(quadgc2)):
            if dc[group_ind[i]] < 0:
                quadgc2[i] = reverse_quad(quadgc2[i])

        # 2) rearrange quadlist order
        qind = np.arange(len(quadgc2))
        for i in range(n_groups):
            qsel = qind[group_ind_np == uind[i]]
            if dc[i] < 0:
                qrev = qsel[::-1]
                qind[group_ind_np == uind[i]] = qrev

        quadgc2old = copy.deepcopy(quadgc2)
        for i in range(len(qind)):
            quadgc2[i] = quadgc2old[qind[i]]

        # End of if-statement for adjusting group discordancy

    s_i = 0.0
    l_i = np.zeros(len(quadgc2))

    for i in range(len(quadgc2)):
        G0, G1, G2, G3 = quadgc2[i]

        # Compute u_i and t_i for this quad
        t_i = __calc_t_i(G0, G1, lat, lon, proj)
        u_i = __calc_u_i(G0, G1, lat, lon, proj)

        # Quad length (top edge)
        l_i[i] = get_quad_length(quadgc2[i])

        # ---------------------------------------------------------------------
        # Weight of segment, three cases
        # ---------------------------------------------------------------------

        # Case 3: t_i == 0 and 0 <= u_i <= l_i
        w_i = np.zeros_like(t_i)

        # To avoid division by zero in totweight later on:
        ix = (t_i == 0) & (0 <= u_i) & (u_i <= l_i[i])
        totweight[ix] = 1.0

        # Case 1:
        ix = t_i != 0
        w_i[ix] = (1.0 / t_i[ix]) * (np.arctan(
            (l_i[i] - u_i[ix]) / t_i[ix]) - np.arctan(-u_i[ix] / t_i[ix]))

        # Case 2:
        ix = (t_i == 0) & ((u_i < 0) | (u_i > l_i[i]))
        w_i[ix] = 1 / (u_i[ix] - l_i[i]) - 1 / u_i[ix]

        totweight = totweight + w_i
        GC2T = GC2T + w_i * t_i

        if n_groups == 1:
            GC2U = GC2U + w_i * (u_i + s_i)
        else:
            if i == 0:
                qind = np.array(range(len(quadgc2)))
                l_kj = 0
                s_ij_1 = 0
            else:
                l_kj = l_i[(group_ind_np == group_ind_np[i]) & (qind < i)]
                s_ij_1 = np.sum(l_kj)

            # First endpoint in the current 'group' (or 'trace' in GC2 terms)
            p1 = Vector.fromPoint(quadgc2[iq0[group_ind[i]]][0])
            s_ij_2 = (p1 - p_origin).dot(np.sign(E) * ahat) / 1000.0

            # Above is GC2N, for GC2T use:
            # s_ij_2 = (p1 - p_origin).dot(bhat) / 1000.0

            s_ij = s_ij_1 + s_ij_2
            GC2U = GC2U + w_i * (u_i + s_ij)

        s_i = s_i + l_i[i]

    GC2T = GC2T / totweight
    GC2U = GC2U / totweight

    # Dictionary for holding the distances
    distdict = dict()

    distdict['T'] = copy.deepcopy(GC2T).reshape(oldshape)
    distdict['U'] = copy.deepcopy(GC2U).reshape(oldshape)

    # Take care of Rx
    Rx = copy.deepcopy(GC2T)  # preserve sign (no absolute value)
    Rx = Rx.reshape(oldshape)
    distdict['rx'] = Rx

    # Ry
    Ry = GC2U - s_i / 2.0
    Ry = Ry.reshape(oldshape)
    distdict['ry'] = Ry

    # Ry0
    Ry0 = np.zeros_like(GC2U)
    ix = GC2U < 0
    Ry0[ix] = np.abs(GC2U[ix])
    if n_groups > 1:
        s_i = s_ij + l_i[-1]
    ix = GC2U > s_i
    Ry0[ix] = GC2U[ix] - s_i
    Ry0 = Ry0.reshape(oldshape)
    distdict['ry0'] = Ry0

    return distdict
예제 #5
0
def test_so6():
    magnitude = 7.2
    dip = np.array([70])
    rake = 135
    width = np.array([15])
    L = 80
    rupx = np.array([0, 0])
    rupy = np.array([0, L])
    zp = np.array([0])

    # Convert to lat/lon
    proj = OrthographicProjection(-122, -120, 39, 37)
    tlon, tlat = proj(rupx, rupy, reverse=True)

    # Dummy origin
    origin = Origin({'lat': 0,
                     'lon': 0,
                     'depth': 0,
                     'mag': 0,
                     'id': 'so6',
                     'netid': 'us',
                     'network': '',
                     'locstring': '',
                     'rake': rake,
                     'time': HistoricTime.utcfromtimestamp(int(time.time()))})

    # Rupture
    rup = QuadRupture.fromTrace(
        np.array([tlon[0]]), np.array([tlat[0]]),
        np.array([tlon[1]]), np.array([tlat[1]]),
        zp, width, dip, origin, reference='rv4')

    # Sites
    x = np.linspace(-80, 80, 21)
    y = np.linspace(-50, 130, 21)
    site_x, site_y = np.meshgrid(x, y)
    slon, slat = proj(site_x, site_y, reverse=True)
    sdepth = np.zeros_like(slon)

    # Fix origin
    tmp = rup.getQuadrilaterals()[0]
    pp0 = Vector.fromPoint(point.Point(
        tmp[0].longitude, tmp[0].latitude, tmp[0].depth))
    pp1 = Vector.fromPoint(point.Point(
        tmp[1].longitude, tmp[1].latitude, tmp[1].depth))
    pp2 = Vector.fromPoint(point.Point(
        tmp[2].longitude, tmp[2].latitude, tmp[2].depth))
    pp3 = Vector.fromPoint(point.Point(
        tmp[3].longitude, tmp[3].latitude, tmp[3].depth))
    dxp = 10 / L
    dyp = (width - 5) / width
    mp0 = pp0 + (pp1 - pp0) * dxp
    mp1 = pp3 + (pp2 - pp3) * dxp
    rp = mp0 + (mp1 - mp0) * dyp
    epilat, epilon, epidepth = ecef2latlon(rp.x, rp.y, rp.z)
    epix, epiy = proj(epilon, epilat, reverse=False)

    origin = Origin({'lat': epilat,
                     'lon': epilon,
                     'depth': epidepth,
                     'mag': magnitude,
                     'id': 'so6',
                     'netid': 'us',
                     'network': '',
                     'locstring': '',
                     'rake': rake,
                     'time': HistoricTime.utcfromtimestamp(int(time.time()))})

    ruplat = [a.latitude for a in rup.getQuadrilaterals()[0]]
    ruplon = [a.longitude for a in rup.getQuadrilaterals()[0]]
    ruplat = np.append(ruplat, ruplat[0])
    ruplon = np.append(ruplon, ruplon[0])
    rupx, rupy = proj(ruplon, ruplat, reverse=False)

    test1 = Bayless2013(origin, rup, slat, slon, sdepth, T=5)
    fd = test1.getFd()
    fd_test = np.array(
        [[0.00000000e+00,   0.00000000e+00,   0.00000000e+00,
          -8.92879772e-03,  -1.74526918e-02,  -2.22981746e-02,
          -2.34350450e-02,  -2.13620062e-02,  -1.72712346e-02,
          -1.29509613e-02,  -1.02545064e-02,  -1.03010185e-02,
          -1.28847597e-02,  -1.66274727e-02,  -1.96984070e-02,
          -2.05377743e-02,  -1.81831337e-02,  -1.21881814e-02,
          -2.64862879e-03,   0.00000000e+00,   0.00000000e+00],
         [0.00000000e+00,   0.00000000e+00,  -8.73221519e-03,
          -2.21421374e-02,  -3.18438939e-02,  -3.71488270e-02,
          -3.76239913e-02,  -3.35015951e-02,  -2.61748968e-02,
          -1.83864728e-02,  -1.34793002e-02,  -1.36687799e-02,
          -1.85727143e-02,  -2.55527671e-02,  -3.14227568e-02,
          -3.38933995e-02,  -3.19289607e-02,  -2.53396980e-02,
          -1.45943649e-02,  -3.71405488e-04,   0.00000000e+00],
            [0.00000000e+00,  -2.54621422e-03,  -2.11428566e-02,
             -3.68609103e-02,  -4.87464747e-02,  -5.56539037e-02,
             -5.64419387e-02,  -5.05331157e-02,  -3.52919381e-02,
             -2.18782050e-02,  -1.40858125e-02,  -1.47354546e-02,
             -2.35727189e-02,  -3.74838465e-02,  -4.75915414e-02,
             -5.13000399e-02,  -4.87882409e-02,  -4.05716321e-02,
             -2.77368254e-02,  -1.13542729e-02,   0.00000000e+00],
            [0.00000000e+00,  -1.21642958e-02,  -3.33747360e-02,
             -5.21661817e-02,  -6.74724509e-02,  -7.77628842e-02,
             -8.00243748e-02,  -6.42496853e-02,  -4.38124530e-02,
             -1.97027426e-02,  -1.45897731e-02,  -1.07427056e-02,
             -3.08235222e-02,  -4.82656988e-02,  -6.67692677e-02,
             -7.35152908e-02,  -6.85574283e-02,  -5.71811573e-02,
             -4.12138780e-02,  -2.20396726e-02,  -6.24121310e-04],
            [0.00000000e+00,  -2.00643401e-02,  -4.39827328e-02,
             -6.62722434e-02,  -8.60268414e-02,  -1.01730306e-01,
             -9.86277741e-02,  -9.82914922e-02,  -5.22335876e-02,
             -1.54622435e-02,  -1.57487554e-02,  -3.06190808e-03,
             -4.81481586e-02,  -8.92480491e-02,  -8.63776477e-02,
             -9.98130440e-02,  -8.95491230e-02,  -7.33553695e-02,
             -5.34401725e-02,  -3.11601812e-02,  -7.33715103e-03],
            [0.00000000e+00,  -2.50053614e-02,  -5.11695772e-02,
             -7.65997026e-02,  -1.00809054e-01,  -1.22877573e-01,
             -1.18738178e-01,  -1.55236782e-01,  -7.45388001e-02,
             1.92779182e-03,  -1.94380016e-02,   1.94922939e-02,
             -7.66669920e-02,  -1.53909722e-01,  -1.10846875e-01,
             -1.19746768e-01,  -1.07680300e-01,  -8.59905101e-02,
             -6.22042294e-02,  -3.71802472e-02,  -1.13867485e-02],
            [0.00000000e+00,  -2.63645827e-02,  -5.37984901e-02,
             -8.11337022e-02,  -1.08298371e-01,  -1.35146441e-01,
             -1.34825430e-01,  -1.85836050e-01,  -1.10730875e-01,
             -3.18861095e-02,   4.14395701e-02,  -1.52711946e-02,
             -1.31840763e-01,  -1.96794707e-01,  -1.33453212e-01,
             -1.34989129e-01,  -1.17922385e-01,  -9.21637323e-02,
             -6.58369237e-02,  -3.91646838e-02,  -1.22685698e-02],
            [0.00000000e+00,  -2.64622244e-02,  -5.40483999e-02,
             -8.16190336e-02,  -1.09162854e-01,  -1.36656677e-01,
             -1.37081504e-01,  -1.89522811e-01,  -1.17723634e-01,
             -4.88765748e-02,  -5.04529015e-03,  -5.76414497e-02,
             -1.45712183e-01,  -2.03062804e-01,  -1.36859828e-01,
             -1.37107390e-01,  -1.19124650e-01,  -9.28263279e-02,
             -6.61800709e-02,  -3.93088682e-02,  -1.22842049e-02],
            [0.00000000e+00,  -2.58466495e-02,  -5.24858827e-02,
             -7.86086164e-02,  -1.03856343e-01,  -1.27529509e-01,
             -1.23794779e-01,  -1.68810613e-01,  -8.22602627e-02,
             1.74236964e-02,   9.38708725e-02,   4.23208284e-02,
             -8.46343723e-02,  -1.70476759e-01,  -1.17547884e-01,
             -1.24569752e-01,  -1.11518670e-01,  -8.84736806e-02,
             -6.38037151e-02,  -3.81874381e-02,  -1.19867610e-02],
            [0.00000000e+00,  -2.42186547e-02,  -4.84175525e-02,
             -7.09428614e-02,  -9.07754575e-02,  -1.06117824e-01,
             -9.50228292e-02,  -1.29781980e-01,  -3.08573454e-02,
             7.39058739e-02,   1.30478117e-01,   8.28181149e-02,
             -2.70389535e-02,  -1.20837502e-01,  -8.02081725e-02,
             -9.70274506e-02,  -9.35853383e-02,  -7.77422806e-02,
             -5.77817530e-02,  -3.53067886e-02,  -1.12414659e-02],
            [0.00000000e+00,  -2.16818717e-02,  -4.22363856e-02,
             -5.96909893e-02,  -7.24805224e-02,  -7.81867829e-02,
             -6.11838569e-02,  -9.05679744e-02,   9.95934969e-03,
             1.07503875e-01,   1.52073917e-01,   1.05894634e-01,
             8.68652263e-03,  -7.98571818e-02,  -4.16548658e-02,
             -6.40511838e-02,  -6.99337160e-02,  -6.26305633e-02,
             -4.89098800e-02,  -3.09284566e-02,  -1.00919381e-02],
            [0.00000000e+00,  -1.84940182e-02,  -3.47054606e-02,
             -4.65278129e-02,  -5.22037664e-02,  -4.93977115e-02,
             -2.95395230e-02,  -5.82421092e-02,   3.91025654e-02,
             1.29337956e-01,   1.67436703e-01,   1.21969296e-01,
             3.20823547e-02,  -5.00287386e-02,  -9.22993907e-03,
             -3.27186625e-02,  -4.52706958e-02,  -4.57409325e-02,
             -3.84701291e-02,  -2.55751405e-02,  -8.64950254e-03],
            [0.00000000e+00,  -1.49431380e-02,  -2.65887341e-02,
             -3.29162158e-02,  -3.22994323e-02,  -2.29081781e-02,
             -2.60259636e-03,  -3.29856530e-02,   6.02631314e-02,
             1.45003704e-01,   1.79361264e-01,   1.34292814e-01,
             4.88007115e-02,  -2.82328554e-02,   1.64212421e-02,
             -5.72391847e-03,  -2.23438861e-02,  -2.90246794e-02,
             -2.76054402e-02,  -1.97779758e-02,  -7.03945406e-03],
            [0.00000000e+00,  -1.12771143e-02,  -1.84737590e-02,
             -1.98228664e-02,  -1.40092305e-02,   1.84580818e-04,
             1.95817303e-02,  -1.32608487e-02,   7.62783168e-02,
             1.57076433e-01,   1.89083905e-01,   1.44259188e-01,
             6.15722813e-02,  -1.17505212e-02,   3.65938109e-02,
             1.66937711e-02,  -2.18970818e-03,  -1.35507683e-02,
             -1.70890527e-02,  -1.39519424e-02,  -5.37036892e-03],
            [0.00000000e+00,  -7.67615215e-03,  -1.07348257e-02,
             -7.75276739e-03,   2.22351695e-03,   1.98662250e-02,
             3.77611177e-02,   2.42018661e-03,   8.89036172e-02,
             1.66855206e-01,   1.97260700e-01,   1.52590263e-01,
             7.17981256e-02,   1.18005972e-03,   5.26852303e-02,
             3.51638855e-02,   1.51012176e-02,   2.69654076e-04,
             -7.33815554e-03,  -8.36639665e-03,  -3.72176313e-03],
            [0.00000000e+00,  -4.50552324e-03,  -4.32262850e-03,
             1.73559158e-03,   1.42670366e-02,   3.35040699e-02,
             4.97279358e-02,   1.85410528e-02,   9.39950666e-02,
             1.46646579e-01,   9.13474746e-02,   1.37004651e-01,
             7.74648339e-02,   1.59777072e-02,   6.25334939e-02,
             4.74577418e-02,   2.72155518e-02,   1.06174952e-02,
             3.94103899e-04,  -3.68465400e-03,  -2.19830733e-03],
            [0.00000000e+00,  -1.74629916e-03,   5.44471813e-04,
             8.22933499e-03,   2.15699287e-02,   4.04232250e-02,
             5.69678048e-02,   5.52408259e-02,   9.04381272e-02,
             1.08204635e-01,   9.14439984e-02,   1.06884511e-01,
             8.17241884e-02,   5.55282924e-02,   6.78528399e-02,
             5.47188925e-02,   3.35251483e-02,   1.69615982e-02,
             5.72048628e-03,  -8.81437278e-05,  -7.36518436e-04],
            [0.00000000e+00,   4.07838765e-05,   3.63933766e-03,
             1.20080876e-02,   2.51274691e-02,   4.25687176e-02,
             6.25685606e-02,   7.33480475e-02,   8.37515545e-02,
             9.52500287e-02,   9.15135660e-02,   9.66442834e-02,
             8.66659913e-02,   8.10325633e-02,   7.18836713e-02,
             5.45548434e-02,   3.55884875e-02,   2.00142359e-02,
             8.71200201e-03,   2.04407846e-03,  -6.53680674e-06],
            [0.00000000e+00,   2.40054729e-04,   4.44975227e-03,
             1.27572519e-02,   2.49362989e-02,   4.03831326e-02,
             5.80039988e-02,   7.61280192e-02,   8.37404162e-02,
             8.89634569e-02,   9.15651607e-02,   9.13586235e-02,
             8.83589144e-02,   8.27804032e-02,   6.75666471e-02,
             5.00483249e-02,   3.36733366e-02,   1.96758691e-02,
             9.00603204e-03,   2.18370401e-03,   0.00000000e+00],
            [0.00000000e+00,   0.00000000e+00,   2.78776980e-03,
             1.05086036e-02,   2.13238822e-02,   3.45577738e-02,
             4.91570145e-02,   6.36787133e-02,   7.63710088e-02,
             8.54072310e-02,   8.92960200e-02,   8.75702197e-02,
             8.07095447e-02,   6.97999389e-02,   5.63787286e-02,
             4.20734776e-02,   2.83073312e-02,   1.61614525e-02,
             6.56194125e-03,   1.00721924e-04,   0.00000000e+00],
            [0.00000000e+00,   0.00000000e+00,   0.00000000e+00,
             5.49667845e-03,   1.47563319e-02,   2.57955743e-02,
             3.76689418e-02,   4.91861917e-02,   5.90108907e-02,
             6.58478416e-02,   6.87018515e-02,   6.73174642e-02,
             6.20270643e-02,   5.35456385e-02,   4.29400416e-02,
             3.14129728e-02,   2.00795162e-02,   9.84001885e-03,
             1.53992995e-03,   0.00000000e+00,   0.00000000e+00]]
    )
    np.testing.assert_allclose(fd, fd_test, rtol=1e-4)
예제 #6
0
def test_rv4():
    magnitude = 7.0
    rake = 90.0
    width = np.array([28])
    rupx = np.array([0, 0])
    rupy = np.array([0, 32])
    zp = np.array([0])
    dip = np.array([30])

    # Convert to lat/lon
    proj = OrthographicProjection(-122, -120, 39, 37)
    tlon, tlat = proj(rupx, rupy, reverse=True)

    # Dummy Origin
    origin = Origin({'lat': 0,
                     'lon': 0,
                     'depth': 0,
                     'mag': 0,
                     'id': 'rv4',
                     'netid': 'us',
                     'network': '',
                     'locstring': '',
                     'rake': rake,
                     'time': HistoricTime.utcfromtimestamp(int(time.time()))})

    # Rupture
    rup = QuadRupture.fromTrace(
        np.array([tlon[0]]), np.array([tlat[0]]),
        np.array([tlon[1]]), np.array([tlat[1]]),
        zp, width, dip, origin, reference='')
    L = rup.getLength()

    # Figure out epicenter
    tmp = rup.getQuadrilaterals()[0]
    pp0 = Vector.fromPoint(point.Point(
        tmp[0].longitude, tmp[0].latitude, tmp[0].depth))
    pp1 = Vector.fromPoint(point.Point(
        tmp[1].longitude, tmp[1].latitude, tmp[1].depth))
    pp2 = Vector.fromPoint(point.Point(
        tmp[2].longitude, tmp[2].latitude, tmp[2].depth))
    pp3 = Vector.fromPoint(point.Point(
        tmp[3].longitude, tmp[3].latitude, tmp[3].depth))
    dxp = 6 / L
    dyp = (width - 8) / width
    mp0 = pp0 + (pp1 - pp0) * dxp
    mp1 = pp3 + (pp2 - pp3) * dxp
    rp = mp0 + (mp1 - mp0) * dyp
    epilat, epilon, epidepth = ecef2latlon(rp.x, rp.y, rp.z)

    # Fix Origin:
    origin = Origin({'lat': epilat,
                     'lon': epilon,
                     'depth': epidepth,
                     'mag': magnitude,
                     'id': 'rv4',
                     'netid': 'us',
                     'network': '',
                     'locstring': '',
                     'rake': rake,
                     'time': HistoricTime.utcfromtimestamp(int(time.time()))})

    x = np.linspace(-50, 50, 11)
    y = np.linspace(-50, 50, 11)
    site_x, site_y = np.meshgrid(x, y)
    slon, slat = proj(site_x, site_y, reverse=True)
    deps = np.zeros_like(slon)

    test1 = Bayless2013(origin, rup, slat, slon, deps, T=2.0)

    # Test fd
    fd = test1.getFd()
    fd_test = np.array(
        [[0.00000000e+00,   0.00000000e+00,   0.00000000e+00,
          1.72143257e-03,   1.34977260e-03,   4.33616224e-15,
          1.24446253e-03,   1.16142357e-03,   2.25464716e-03,
          7.05281751e-04,   0.00000000e+00],
         [0.00000000e+00,   0.00000000e+00,   7.62610242e-03,
          1.25133844e-02,   5.61896104e-03,   7.63126014e-15,
          4.52266194e-03,   4.67970900e-03,   1.02820316e-02,
          5.13160096e-03,  -6.13926251e-03],
            [0.00000000e+00,   4.00495234e-03,   2.37608386e-02,
             2.37139333e-02,   9.55224050e-03,   5.66364910e-15,
             7.70344813e-03,   7.36466362e-03,   1.48239704e-02,
             8.40388145e-03,  -1.58592485e-02],
            [8.08385547e-19,   9.38150101e-03,   3.38610620e-02,
             3.85351492e-02,   1.91044918e-02,   3.98697802e-15,
             1.54321666e-02,   1.21913760e-02,   2.04435166e-02,
             1.04931859e-02,  -1.85935894e-02],
            [2.12025421e-18,   1.37316085e-02,   4.40193799e-02,
             6.16562477e-02,   4.77612496e-02,   2.60257085e-15,
             3.86322888e-02,   1.97965887e-02,   2.64882038e-02,
             1.23335908e-02,  -2.07389932e-02],
            [2.64338576e-18,   1.45898292e-02,   4.89104213e-02,
             7.70703166e-02,   9.55225258e-02,   1.01875104e-01,
             7.73459329e-02,   2.50275508e-02,   2.93537540e-02,
             1.30949577e-02,  -2.15685454e-02],
            [2.64330042e-18,   1.45898262e-02,   4.89104186e-02,
             7.70703146e-02,   9.55225248e-02,   1.01910945e-01,
             7.74050835e-02,   2.52307946e-02,   2.92970736e-02,
             1.30880504e-02,  -2.15685424e-02],
            [2.64318867e-18,   1.45898259e-02,   4.89104184e-02,
             7.70703144e-02,   9.55225247e-02,   1.01933432e-01,
             7.74421258e-02,   2.53572923e-02,   2.92615130e-02,
             1.30837284e-02,  -2.15685422e-02],
            [2.64305117e-18,   1.45898284e-02,   4.89104206e-02,
             7.70703161e-02,   9.55225256e-02,   1.01942593e-01,
             7.74571359e-02,   2.54081640e-02,   2.92472117e-02,
             1.30819985e-02,  -2.15685446e-02],
            [2.30141673e-18,   1.40210825e-02,   4.56205547e-02,
             6.63109661e-02,   5.79266964e-02,   2.33044622e-15,
             4.69672564e-02,   2.18401553e-02,   2.72864925e-02,
             1.25728575e-02,  -2.10227772e-02],
            [1.10672535e-18,   1.04777076e-02,   3.59041065e-02,
             4.24614318e-02,   2.24217216e-02,   3.66914762e-15,
             1.81728517e-02,   1.39301504e-02,   2.14956836e-02,
             1.08711460e-02,  -1.90802849e-02]]
    )
    np.testing.assert_allclose(fd, fd_test, rtol=2e-4)
예제 #7
0
def test_ss3_move_hypo1():
    magnitude = 7.2
    dip = np.array([90])
    rake = 180.0
    width = np.array([15])
    rupx = np.array([0, 0])
    rupy = np.array([0, 80])
    zp = np.array([0.0])
    epix = np.array([1.0])
    epiy = np.array([-1.0])

    # Convert to lat/lon
    proj = OrthographicProjection(-122, -120, 39, 37)
    tlon, tlat = proj(rupx, rupy, reverse=True)
    epilon, epilat = proj(epix, epiy, reverse=True)

    # Origin
    origin = Origin({'lat': epilat[0],
                     'lon': epilon[0],
                     'depth': -1,
                     'mag': magnitude,
                     'id': 'ss3',
                     'netid': '',
                     'network': '',
                     'locstring': '',
                     'rake': rake,
                     'time': HistoricTime.utcfromtimestamp(int(time.time()))})

    rup = QuadRupture.fromTrace(
        np.array([tlon[0]]), np.array([tlat[0]]),
        np.array([tlon[1]]), np.array([tlat[1]]),
        zp, width, dip, origin, reference='ss3')

    x = np.linspace(0, 20, 6)
    y = np.linspace(0, 90, 11)
    site_x, site_y = np.meshgrid(x, y)
    slon, slat = proj(site_x, site_y, reverse=True)
    deps = np.zeros_like(slon)

    test1 = Bayless2013(origin, rup, slat, slon, deps, T=1.0)
    phyp = copy.deepcopy(test1.phyp[0])
    plat, plon, pdep = ecef2latlon(phyp.x, phyp.y, phyp.z)

    px, py = proj(plon, plat, reverse=False)

    np.testing.assert_allclose(plat, 38.004233219183604, rtol=1e-4)
    np.testing.assert_allclose(plon, -120.98636122402166, rtol=1e-4)
    np.testing.assert_allclose(pdep, 7.4999999989205968, rtol=1e-4)

    # --------------------------------------------------------------------------
    # Also for multiple segments
    # --------------------------------------------------------------------------
    dip = np.array([90., 90., 90.])
    rake = 180.0
    width = np.array([15., 15., 10.])
    rupx = np.array([0., 0., 10., 20.])
    rupy = np.array([0., 20., 60., 80.])
    zp = np.array([0., 0., 0.])
    epix = np.array([0.])
    epiy = np.array([0.])

    # Convert to lat/lon
    proj = OrthographicProjection(-122, -120, 39, 37)
    tlon, tlat = proj(rupx, rupy, reverse=True)
    epilon, epilat = proj(epix, epiy, reverse=True)

    rup = QuadRupture.fromTrace(
        np.array(tlon[0:3]), np.array(tlat[0:3]),
        np.array(tlon[1:4]), np.array(tlat[1:4]),
        zp, width, dip, origin, reference='')

    event = {'lat': epilat[0],
             'lon': epilon[0],
             'depth': 1.0,
             'mag': magnitude,
             'id': '',
             'netid': '',
             'network': '',
             'locstring': 'test',
             'mech': 'SS'}
    event['time'] = HistoricTime.utcfromtimestamp(int(time.time()))
    x = np.linspace(0, 20, 6)
    y = np.linspace(0, 90, 11)
    site_x, site_y = np.meshgrid(x, y)
    slon, slat = proj(site_x, site_y, reverse=True)
    deps = np.zeros_like(slon)
    origin = Origin(event)
    origin.rake = rake
    test1 = Bayless2013(origin, rup, slat, slon, deps, T=1.0)

    # 1st pseudo-hyp
    phyp = copy.deepcopy(test1.phyp[0])
    plat, plon, pdep = ecef2latlon(phyp.x, phyp.y, phyp.z)
    px, py = proj(plon, plat, reverse=False)
    np.testing.assert_allclose(plat, 38.004233219183604, rtol=1e-4)
    np.testing.assert_allclose(plon, -120.98636122402166, rtol=1e-4)
    np.testing.assert_allclose(pdep, 7.4999999989205968, rtol=1e-4)

    # 2nd pseudo-hyp
    phyp = copy.deepcopy(test1.phyp[1])
    plat, plon, pdep = ecef2latlon(phyp.x, phyp.y, phyp.z)
    px, py = proj(plon, plat, reverse=False)
    np.testing.assert_allclose(plat, 38.184097835787796, rtol=1e-4)
    np.testing.assert_allclose(plon, -120.98636122402166, rtol=1e-4)
    np.testing.assert_allclose(pdep, 7.4999999989103525, rtol=1e-4)

    # 3rd pseudo-hyp
    phyp = copy.deepcopy(test1.phyp[2])
    plat, plon, pdep = ecef2latlon(phyp.x, phyp.y, phyp.z)
    px, py = proj(plon, plat, reverse=False)
    np.testing.assert_allclose(plat, 38.543778594535752, rtol=1e-4)
    np.testing.assert_allclose(plon, -120.87137783362499, rtol=1e-4)
    np.testing.assert_allclose(pdep, 4.9999999995063993, rtol=1e-4)
예제 #8
0
def test_ss3_m6():
    magnitude = 6.0
    dip = np.array([90])
    rake = 180.0
    width = np.array([15])
    rupx = np.array([0, 0])
    rupy = np.array([0, 80])
    zp = np.array([0])
    epix = np.array([0])
    epiy = np.array([0.2 * rupy[1]])

    # Convert to lat/lon
    proj = OrthographicProjection(-122, -120, 39, 37)
    tlon, tlat = proj(rupx, rupy, reverse=True)
    epilon, epilat = proj(epix, epiy, reverse=True)

    # Origin:
    origin = Origin({'lat': epilat[0],
                     'lon': epilon[0],
                     'depth': 10,
                     'mag': magnitude,
                     'id': 'ss3',
                     'netid': '',
                     'network': '',
                     'locstring': '',
                     'rake': rake,
                     'time': HistoricTime.utcfromtimestamp(int(time.time()))})

    rup = QuadRupture.fromTrace(
        np.array([tlon[0]]), np.array([tlat[0]]),
        np.array([tlon[1]]), np.array([tlat[1]]),
        zp, width, dip, origin, reference='ss3')

    x = np.linspace(0, 20, 6)
    y = np.linspace(0, 90, 11)
    site_x, site_y = np.meshgrid(x, y)
    slon, slat = proj(site_x, site_y, reverse=True)
    deps = np.zeros_like(slon)

    test1 = Bayless2013(origin, rup, slat, slon, deps, T=1.0)

    # Test fd
    fd = test1.getFd()
    fd_test = np.array(
        [[0.05853668,  0.05032323,  0.0306438,  0.00839635, -0.01102162,
          -0.02621319],
         [0.01720501, -0.00687296, -0.03804823, -0.05547473, -0.0644932,
            -0.06947135],
            [-0.03000065, -0.07006634, -0.07708165, -0.07865941, -0.0792369,
             -0.07950887],
            [0.0398062,  0.02571145, -0.0018651, -0.0255418, -0.04176278,
             -0.05235095],
            [0.0696989,  0.06389524,  0.04890304,  0.02983134,  0.01098535,
             -0.00545921],
            [0.088278,  0.08511069,  0.07628596,  0.06350294,  0.04875897,
             0.03373495],
            [0.10179334,  0.09978475,  0.09401676,  0.0851842,  0.07422509,
             0.06210369],
            [0.11242209,  0.11102701,  0.10696056,  0.10055471,  0.09229027,
             0.08271454],
            [0.12118279,  0.12015315,  0.11712653,  0.11228058,  0.10588323,
             0.09825795],
            [0.12785957,  0.12706892,  0.12473264,  0.12095384,  0.11589197,
             0.10974684],
            [0.12785908,  0.12724852,  0.12543819,  0.12249026,  0.11850249,
             0.11360047]])
    np.testing.assert_allclose(
        fd, fd_test, rtol=1e-4)
예제 #9
0
def test_multisegment_discordant():
    # The one thing that isn't check above is discordancy for segments
    # with multiple quads. For this, we need a synthetic example.
    x0 = np.array([0, 1, -1, 10, 9, 7])
    y0 = np.array([0, 10, 20, 40, 35, 30])
    z0 = np.array([0, 0, 0, 0, 0, 0])
    x1 = np.array([1, -1, 0, 9, 7, 6])
    y1 = np.array([10, 20, 30, 35, 30, 25])
    z1 = np.array([0, 0, 0, 0, 0, 0])
    x2 = np.array([3, 1, 2, 7, 5, 4])
    y2 = np.array([10, 20, 30, 35, 30, 25])
    z2 = np.array([10, 10, 10, 10, 10, 10])
    x3 = np.array([2, 3, 1, 8, 7, 5])
    y3 = np.array([0, 10, 20, 40, 35, 30])
    z3 = np.array([10, 10, 10, 10, 10, 10])

    epilat = 32.15270
    epilon = -115.30500
    proj = OrthographicProjection(epilon - 1, epilon + 1, epilat + 1,
                                  epilat - 1)
    lon0, lat0 = proj(x0, y0, reverse=True)
    lon1, lat1 = proj(x1, y1, reverse=True)
    lon2, lat2 = proj(x2, y2, reverse=True)
    lon3, lat3 = proj(x3, y3, reverse=True)

    # Make an Origin object; most of the 'event' values don't matter for
    # this example
    origin = Origin({
        'lat': 0,
        'lon': 0,
        'depth': 0,
        'mag': 7.2,
        'id': '',
        'netid': '',
        'network': '',
        'locstring': '',
        'time': HistoricTime.utcfromtimestamp(time.time())
    })
    rup = QuadRupture.fromVertices(lon0,
                                   lat0,
                                   z0,
                                   lon1,
                                   lat1,
                                   z1,
                                   lon2,
                                   lat2,
                                   z2,
                                   lon3,
                                   lat3,
                                   z3,
                                   origin,
                                   group_index=[0, 0, 0, 1, 1, 1])

    # Sites
    buf = 0.25
    lat = np.linspace(np.nanmin(rup.lats) - buf, np.nanmax(rup.lats) + buf, 20)
    lon = np.linspace(np.nanmin(rup.lons) - buf, np.nanmax(rup.lons) + buf, 20)
    lons, lats = np.meshgrid(lon, lat)
    dep = np.zeros_like(lons)
    x, y = proj(lon, lat)
    rupx, rupy = proj(rup.lons, rup.lats)
    # Calculate U and T
    dtypes = ['U', 'T']
    dists = get_distance(dtypes, lats, lons, dep, rup)

    targetU = np.array(
        [[
            -28.53228275, -28.36479713, -28.20139732, -28.0407734,
            -27.88135558, -27.72144153, -27.55935946, -27.39362017,
            -27.22300147, -27.04653062, -26.86338215, -26.67275638,
            -26.47381287, -26.26569449, -26.04762427, -25.81902477,
            -25.57961136, -25.32943282, -25.06885791, -24.79852214
        ],
         [
             -23.53750292, -23.3748086, -23.21793537, -23.06521934,
             -22.91449689, -22.76331684, -22.60928211, -22.45042208,
             -22.28542121, -22.11355532, -21.93435402, -21.74720475,
             -21.55115107, -21.34497916, -21.12749377, -20.89781118,
             -20.6555466, -20.40086149, -20.13439948, -19.85716145
         ],
         [
             -18.53499939, -18.37689929, -18.22732841, -18.08427516,
             -17.94468687, -17.80472632, -17.66045115, -17.50880802,
             -17.3484421, -17.17963435, -17.0032098, -16.81921732,
             -16.62638972, -16.42258419, -16.20564846, -15.9741218,
             -15.72753538, -15.4663671, -15.19180844, -14.9054813
         ],
         [
             -13.52283359, -13.36797542, -13.22589288, -13.09466537,
             -12.97028551, -12.84653536, -12.71591089, -12.57212088,
             -12.41335561, -12.24319318, -12.06681006, -11.88598424,
             -11.69798166, -11.49796348, -11.28169605, -11.04691388,
             -10.79343174, -10.52262594, -10.23677602, -9.93851158
         ],
         [
             -8.49936685, -8.34357094, -8.20650964, -8.08786858, -7.98403171,
             -7.88628837, -7.78005273, -7.64833307, -7.48359988, -7.29992491,
             -7.11862682, -6.94410189, -6.76618701, -6.5727842, -6.35634881,
             -6.11465447, -5.84925708, -5.56369035, -5.26212482, -4.94857454
         ],
         [
             -3.46638168, -3.30047216, -3.15914418, -3.04618465, -2.96252939,
             -2.90194067, -2.84436315, -2.75029014, -2.56983592, -2.33744275,
             -2.1512136, -1.99833104, -1.84066354, -1.6541107, -1.43071517,
             -1.17252753, -0.88592286, -0.57817222, -0.25582315, 0.07585567
         ],
         [
             1.56416954, 1.75393848, 1.9183586, 2.04909316, 2.13723278,
             2.17776584, 2.18272501, 2.20967639, 2.37405656, 2.65073289,
             2.80205222, 2.90973407, 3.05124404, 3.2505182, 3.50336116,
             3.7967575, 4.11742779, 4.45465822, 4.80070204, 5.15033407
         ],
         [
             6.5633489, 6.78740885, 6.99419348, 7.17551069, 7.31963558,
             7.4113505, 7.43666779, 7.40177458, 7.40517136, 7.58520044,
             7.62013169, 7.71596777, 7.90558457, 8.17213015, 8.49008681,
             8.83763176, 9.19937294, 9.56556659, 9.9305469, 10.29132309
         ],
         [
             11.48996073, 11.74301446, 11.99016964, 12.22782156, 12.44984059,
             12.6446727, 12.78798484, 12.82584849, 12.61992833, 12.26579742,
             12.32166685, 12.54665462, 12.86628045, 13.23578462, 13.62571822,
             14.01882924, 14.40617707, 14.78388296, 15.15089889, 15.5076165
         ],
         [
             16.31383216, 16.57376544, 16.83189511, 17.08626411, 17.33309437,
             17.56429108, 17.76005623, 17.85853532, 17.57101025, 17.32637346,
             17.45075419, 17.77199513, 18.16933168, 18.58284635, 18.9891851,
             19.37985879, 19.75324557, 20.11079653, 20.4549905, 20.78837053
         ],
         [
             21.03975749, 21.28450315, 21.5243142, 21.75603974, 21.97469496,
             22.17298057, 22.34310053, 22.49668569, 22.73940191, 22.70030633,
             22.95351405, 23.35967832, 23.75891016, 24.14867803, 24.51536915,
             24.85878249, 25.18398203, 25.49615514, 25.79932964, 26.09638269
         ],
         [
             25.70484089, 25.92709225, 26.14280395, 26.35119497, 26.55363501,
             26.75827099, 26.9915523, 27.31779086, 27.77993211, 27.71070831,
             28.13624949, 28.723482, 29.25285078, 29.66404032, 30.00169474,
             30.30044315, 30.57916576, 30.84804427, 31.1126134, 31.37586841
         ],
         [
             30.35406633, 30.5585145, 30.75843356, 30.95627127, 31.15811912,
             31.3763124, 31.63114968, 31.94156189, 32.23691802, 32.38759301,
             32.86915665, 33.83467935, 34.46125278, 34.89905345, 35.25111257,
             35.55095664, 35.82150686, 36.07720619, 36.32643896, 36.57385362
         ],
         [
             35.0222379, 35.21734711, 35.41081942, 35.60589495, 35.80774808,
             36.02313791, 36.25826988, 36.51619168, 36.81025966, 37.21777129,
             37.86674108, 38.66578072, 39.25203723, 39.78060643, 40.20815617,
             40.5606039, 40.86634527, 41.14457482, 41.40732554, 41.66197722
         ],
         [
             39.73046099, 39.92514041, 40.12152415, 40.32316112, 40.5350467,
             40.76393316, 41.01937758, 41.3172128, 41.68596492, 42.16604148,
             42.77622755, 43.447503, 44.03771478, 44.55012468, 45.00551259,
             45.40376857, 45.75505135, 46.07204699, 46.36554362, 46.64361367
         ],
         [
             44.4876174, 44.68959464, 44.89710008, 45.11420443, 45.34646809,
             45.60143197, 45.88932906, 46.22363997, 46.61975585, 47.0884227,
             47.62307543, 48.1913408, 48.74937117, 49.26945799, 49.74327902,
             50.17123158, 50.55810895, 50.91098842, 51.23731582, 51.54375617
         ],
         [
             49.29279265, 49.50696882, 49.73006999, 49.96625305, 50.22080319,
             50.50022572, 50.81209441, 51.1642666, 51.56290694, 52.00913021,
             52.49553006, 53.00565389, 53.51861282, 54.01614414, 54.48672101,
             54.9254339, 55.33212663, 55.70951516, 56.06170563, 56.39317058
         ],
         [
             54.13906629, 54.3671694, 54.60643024, 54.86053563, 55.13377911,
             55.43088558, 55.75658576, 56.1148189, 56.50752978, 56.93329478,
             57.38640012, 57.85715119, 58.33367994, 58.80451404, 59.26065475,
             59.69644542, 60.10938419, 60.49940252, 60.86803179, 61.21767916
         ],
         [
             59.01741908, 59.25887491, 59.51248349, 59.78119592, 60.06816694,
             60.37651862, 60.70895927, 61.0672529, 61.45160192, 61.86010542,
             62.28853397, 62.73062937, 63.17894547, 63.62598375, 64.06523791,
             64.49185106, 64.90281064, 65.2967858, 65.67377362, 66.03469546
         ],
         [
             63.9193099, 64.17236414, 64.4376317, 64.71732366, 65.01362255,
             65.32847988, 65.66334836, 66.0188704, 66.39457546, 66.7886684,
             67.19800022, 67.61828012, 68.04451487, 68.47157851, 68.89476917,
             69.31022713, 69.71515194, 70.10782673, 70.4875021, 70.85420436
         ]])
    np.testing.assert_allclose(targetU, dists['U'], atol=0.01)
    targetT = np.array([
        [
            -2.27427469e+01, -1.97498544e+01, -1.67512900e+01, -1.37464632e+01,
            -1.07350712e+01, -7.71715083e+00, -4.69305811e+00, -1.66336318e+00,
            1.37131605e+00, 4.41047613e+00, 7.45381136e+00, 1.05011799e+01,
            1.35524779e+01, 1.66074913e+01, 1.96657949e+01, 2.27267294e+01,
            2.57894503e+01, 2.88530154e+01, 3.19164798e+01, 3.49789747e+01
        ],
        [
            -2.30778766e+01, -2.00896906e+01, -1.70950973e+01, -1.40931667e+01,
            -1.10834219e+01, -8.06600712e+00, -5.04171582e+00, -2.01179123e+00,
            1.02248614e+00, 4.06025218e+00, 7.10129626e+00, 1.01459367e+01,
            1.31946312e+01, 1.62475702e+01, 1.93044511e+01, 2.23644788e+01,
            2.54265185e+01, 2.84892997e+01, 3.15515954e+01, 3.46123426e+01
        ],
        [
            -2.33971472e+01, -2.04144525e+01, -1.74245193e+01, -1.44256870e+01,
            -1.14169177e+01, -8.39830615e+00, -5.37141115e+00, -2.33902937e+00,
            6.95823925e-01, 3.73133431e+00, 6.76769593e+00, 9.80663091e+00,
            1.28500821e+01, 1.58991008e+01, 1.89534737e+01, 2.20119662e+01,
            2.50728111e+01, 2.81341606e+01, 3.11943854e+01, 3.42522163e+01
        ],
        [
            -2.36965870e+01, -2.07206976e+01, -1.77370901e+01, -1.47426715e+01,
            -1.17347885e+01, -8.71247709e+00, -5.67801094e+00, -2.63761285e+00,
            4.00625914e-01, 3.43182302e+00, 6.45782532e+00, 9.48491128e+00,
            1.25187545e+01, 1.55616657e+01, 1.86127822e+01, 2.16694756e+01,
            2.47286680e+01, 2.77876297e+01, 3.08443066e+01, 3.38973527e+01
        ],
        [
            -2.39698399e+01, -2.10022612e+01, -1.80281475e+01, -1.50423801e+01,
            -1.20388157e+01, -9.01204040e+00, -5.96160398e+00, -2.89867328e+00,
            1.52194374e-01, 3.17268218e+00, 6.17334725e+00, 9.17699572e+00,
            1.21964990e+01, 1.52330975e+01, 1.82821226e+01, 2.13375815e+01,
            2.43943933e+01, 2.74490375e+01, 3.04994435e+01, 3.35446330e+01
        ],
        [
            -2.42070742e+01, -2.12471979e+01, -1.82855675e+01, -1.53163304e+01,
            -1.23296744e+01, -9.31127857e+00, -6.24535210e+00, -3.12882361e+00,
            -2.24460581e-02, 2.95354485e+00, 5.89215412e+00, 8.86387424e+00,
            1.18748249e+01, 1.49128245e+01, 1.79640055e+01, 2.10182501e+01,
            2.40696313e+01, 2.71153177e+01, 3.01543919e+01, 3.31869788e+01
        ],
        [
            -2.43971375e+01, -2.14368866e+01, -1.84826148e+01, -1.55321207e+01,
            -1.25786621e+01, -9.60654678e+00, -6.58612151e+00, -3.48118311e+00,
            -3.16555025e-01, 2.61618307e+00, 5.53740540e+00, 8.52666510e+00,
            1.15623361e+01, 1.46149780e+01, 1.76674294e+01, 2.07125025e+01,
            2.37483764e+01, 2.67756033e+01, 2.97955606e+01, 3.28097430e+01
        ],
        [
            -2.45384925e+01, -2.15583842e+01, -1.85874288e+01, -1.56290738e+01,
            -1.26867853e+01, -9.76140655e+00, -6.84407754e+00, -3.90089971e+00,
            -8.41806596e-01, 2.14754495e+00, 5.18583472e+00, 8.26271822e+00,
            1.13266091e+01, 1.43684333e+01, 1.73916223e+01, 2.04017469e+01,
            2.34034936e+01, 2.64002111e+01, 2.93941282e+01, 3.23866586e+01
        ],
        [
            -2.46576775e+01, -2.16355610e+01, -1.86129545e+01, -1.55919156e+01,
            -1.25763765e+01, -9.57306672e+00, -6.59044329e+00, -3.62352541e+00,
            -5.92041388e-01, 2.33255341e+00, 5.29498494e+00, 8.24834463e+00,
            1.11833819e+01, 1.41167617e+01, 1.70571082e+01, 2.00065102e+01,
            2.29645946e+01, 2.59302937e+01, 2.89023967e+01, 3.18797332e+01
        ],
        [
            -2.48161623e+01, -2.17489533e+01, -1.86651328e+01, -1.55589864e+01,
            -1.24224388e+01, -9.24466730e+00, -6.01521475e+00, -2.75148770e+00,
            3.89519039e-01, 2.99589525e+00, 5.45696689e+00, 8.01247078e+00,
            1.07291540e+01, 1.35565782e+01, 1.64461360e+01, 1.93723515e+01,
            2.23222250e+01, 2.52881249e+01, 2.82650171e+01, 3.12494172e+01
        ],
        [
            -2.50857405e+01, -2.20002811e+01, -1.88926336e+01, -1.57550887e+01,
            -1.25770789e+01, -9.34497451e+00, -6.04430316e+00, -2.67290100e+00,
            5.40854953e-01, 2.30509492e+00, 3.58183843e+00, 6.23701436e+00,
            9.28727128e+00, 1.23205706e+01, 1.53428945e+01, 1.83666035e+01,
            2.13934954e+01, 2.44218171e+01, 2.74496472e+01, 3.04757209e+01
        ],
        [
            -2.55082697e+01, -2.24454912e+01, -1.93710045e+01, -1.62824768e+01,
            -1.31767102e+01, -1.00469827e+01, -6.86985653e+00, -3.54681638e+00,
            1.07062999e-01, 3.34891657e-01, -1.70694750e-01, 3.57896940e+00,
            7.17013928e+00, 1.05232789e+01, 1.37976070e+01, 1.70230221e+01,
            2.02076136e+01, 2.33576919e+01, 2.64794914e+01, 2.95785985e+01
        ],
        [
            -2.60778515e+01, -2.30695744e+01, -2.00684150e+01, -1.70790651e+01,
            -1.41074315e+01, -1.11587507e+01, -8.23273307e+00, -5.33306966e+00,
            -2.80144302e+00, -1.84760416e+00, -1.05368779e+00, 1.26163211e+00,
            4.90086292e+00, 8.53883059e+00, 1.20996577e+01, 1.55589098e+01,
            1.89237978e+01, 2.22114952e+01, 2.54390313e+01, 2.86203790e+01
        ],
        [
            -2.67537229e+01, -2.38123298e+01, -2.08964272e+01, -1.80168638e+01,
            -1.51896230e+01, -1.24401995e+01, -9.81536176e+00, -7.41008520e+00,
            -5.38073414e+00, -3.78262975e+00, -2.29669890e+00, -3.53057240e-01,
            3.13642477e+00, 6.97021789e+00, 1.07026969e+01, 1.42945488e+01,
            1.77655640e+01, 2.11406146e+01, 2.44409375e+01, 2.76832489e+01
        ],
        [
            -2.74832153e+01, -2.46028623e+01, -2.17593854e+01, -1.89653378e+01,
            -1.62381218e+01, -1.36022404e+01, -1.10914555e+01, -8.74572618e+00,
            -6.58963863e+00, -4.58336507e+00, -2.57607747e+00, -2.67233150e-01,
            2.82788692e+00, 6.36737407e+00, 9.93334021e+00, 1.34440609e+01,
            1.68846862e+01, 2.02577163e+01, 2.35710668e+01, 2.68337230e+01
        ],
        [
            -2.82199728e+01, -2.53838486e+01, -2.25869234e+01, -1.98388981e+01,
            -1.71512612e+01, -1.45365893e+01, -1.20059297e+01, -9.56220853e+00,
            -7.18799023e+00, -4.83006994e+00, -2.39120744e+00, 2.51308627e-01,
            3.17331949e+00, 6.33022626e+00, 9.61428455e+00, 1.29426788e+01,
            1.62705993e+01, 1.95770961e+01, 2.28539081e+01, 2.60992146e+01
        ],
        [
            -2.89332200e+01, -2.61222251e+01, -2.33461951e+01, -2.06105222e+01,
            -1.79200485e+01, -1.52776479e+01, -1.26817390e+01, -1.01225741e+01,
            -7.57801870e+00, -5.01122873e+00, -2.37434916e+00, 3.78303328e-01,
            3.27093827e+00, 6.29527723e+00, 9.41912399e+00, 1.26046423e+01,
            1.58204753e+01, 1.90448689e+01, 2.22643265e+01, 2.54712657e+01
        ],
        [
            -2.96082809e+01, -2.68067500e+01, -2.40331802e+01, -2.12894659e+01,
            -1.85760763e+01, -1.58910124e+01, -1.32284735e+01, -1.05774862e+01,
            -7.92111801e+00, -5.23724922e+00, -2.50179068e+00, 3.05790568e-01,
            3.19666197e+00, 6.16975035e+00, 9.21353475e+00, 1.23109519e+01,
            1.54443017e+01, 1.85982825e+01, 2.17611016e+01, 2.49243957e+01
        ],
        [
            -3.02420504e+01, -2.74395034e+01, -2.46578094e+01, -2.18967353e+01,
            -1.91546206e+01, -1.64278219e+01, -1.37101816e+01, -1.09927140e+01,
            -8.26378719e+00, -5.51007519e+00, -2.71836365e+00, 1.22111758e-01,
            3.01754598e+00, 5.96851903e+00, 8.97043180e+00, 1.20150997e+01,
            1.50927299e+01, 1.81935916e+01, 2.13090724e+01, 2.44321477e+01
        ],
        [
            -3.08377073e+01, -2.80281994e+01, -2.52335334e+01, -2.24524366e+01,
            -1.96825082e+01, -1.69199811e+01, -1.41595768e+01, -1.13945492e+01,
            -8.61701306e+00, -5.81861191e+00, -2.99148017e+00, -1.29317230e-01,
            2.77170749e+00, 5.71249079e+00, 8.69110042e+00, 1.17033684e+01,
            1.47437429e+01, 1.78061436e+01, 2.08846464e+01, 2.39739290e+01
        ]
    ])
    np.testing.assert_allclose(targetT, dists['T'], atol=0.01)
예제 #10
0
def get_extent(rupture=None, config=None):
    """
    Method to compute map extent from rupture. There are numerous methods for
    getting the extent:
        - It can be specified directly in the config file,
        - it can be hard coded for specific magnitude ranges in the config
          file, or
        - it can be based on the MultiGMPE for the event.

    All methods except for the first requires a rupture object.

    If no config is provided then a rupture is required and the extent is based
    on a generic set of active/stable.

    Args:
        rupture (Rupture): A ShakeMap Rupture instance.
        config (ConfigObj): ShakeMap config object.

    Returns:
        tuple: lonmin, lonmax, latmin, latmax rounded to the nearest
        arc-minute..

    """

    # -------------------------------------------------------------------------
    # Check to see what parameters are specified in the extent config
    # -------------------------------------------------------------------------
    spans = {}
    bounds = []
    if config is not None:
        if 'extent' in config:
            if 'magnitude_spans' in config['extent']:
                if len(config['extent']['magnitude_spans']):
                    if isinstance(config['extent']['magnitude_spans'], dict):
                        spans = config['extent']['magnitude_spans']
            if 'bounds' in config['extent']:
                if 'extent' in config['extent']['bounds']:
                    if config['extent']['bounds']['extent'][0] != -999.0:
                        bounds = config['extent']['bounds']['extent']

    # -------------------------------------------------------------------------
    # Simplest option: extent was specified in the config, use that and exit.
    # -------------------------------------------------------------------------
    if len(bounds):
        xmin, ymin, xmax, ymax = bounds
        return (xmin, xmax, ymin, ymax)

    if not rupture or not isinstance(rupture, Rupture):
        raise TypeError('get_extent() requires a rupture object if the extent '
                        'is not specified in the config object.')

    # Find the central point
    origin = rupture.getOrigin()
    if isinstance(rupture, (QuadRupture, EdgeRupture)):
        # For an extended rupture, it is the midpoint between the extent of the
        # verticies
        lats = rupture.lats
        lons = rupture.lons

        # Remove nans
        lons = lons[~np.isnan(lons)]
        lats = lats[~np.isnan(lats)]

        clat = 0.5 * (np.nanmax(lats) + np.nanmin(lats))
        clon = 0.5 * (np.nanmax(lons) + np.nanmin(lons))
    else:
        # For a point source, it is just the epicenter
        clat = origin.lat
        clon = origin.lon

    mag = origin.mag

    # -------------------------------------------------------------------------
    # Second simplest option: spans are hardcoded based on magnitude
    # -------------------------------------------------------------------------
    if len(spans):
        xmin = None
        xmax = None
        ymin = None
        ymax = None
        for spankey, span in spans.items():
            if mag > span[0] and mag <= span[1]:
                ymin = clat - span[2] / 2
                ymax = clat + span[2] / 2
                xmin = clon - span[3] / 2
                xmax = clon + span[3] / 2
                break
        if xmin is not None:
            return (xmin, xmax, ymin, ymax)

    # -------------------------------------------------------------------------
    # Use MultiGMPE to get spans
    # -------------------------------------------------------------------------
    if config is not None:
        gmpe = MultiGMPE.from_config(config)
        gmice = get_object_from_config('gmice', 'modeling', config)
    else:
        # Put in some default values for conf
        config = {
            'extent': {
                'mmi': {
                    'threshold': 4.5,
                    'mindist': 100,
                    'maxdist': 1000
                }
            }
        }

        # Generic GMPEs choices based only on active vs stable
        # as defaults...
        stable = is_stable(origin.lon, origin.lat)
        if not stable:
            ASK14 = AbrahamsonEtAl2014()
            CB14 = CampbellBozorgnia2014()
            CY14 = ChiouYoungs2014()
            gmpes = [ASK14, CB14, CY14]
            site_gmpes = None
            weights = [1 / 3.0, 1 / 3.0, 1 / 3.0]
            gmice = WGRW12()
        else:
            Fea96 = FrankelEtAl1996MwNSHMP2008()
            Tea97 = ToroEtAl1997MwNSHMP2008()
            Sea02 = SilvaEtAl2002MwNSHMP2008()
            C03 = Campbell2003MwNSHMP2008()
            TP05 = TavakoliPezeshk2005MwNSHMP2008()
            AB06p = AtkinsonBoore2006Modified2011()
            Pea11 = PezeshkEtAl2011()
            Atk08p = Atkinson2008prime()
            Sea01 = SomervilleEtAl2001NSHMP2008()
            gmpes = [
                Fea96, Tea97, Sea02, C03, TP05, AB06p, Pea11, Atk08p, Sea01
            ]
            site_gmpes = [AB06p]
            weights = [0.16, 0.0, 0.0, 0.17, 0.17, 0.3, 0.2, 0.0, 0.0]
            gmice = AK07()

        gmpe = MultiGMPE.from_list(gmpes,
                                   weights,
                                   default_gmpes_for_site=site_gmpes)

    min_mmi = config['extent']['mmi']['threshold']
    default_imt = imt.SA(1.0)
    sd_types = [const.StdDev.TOTAL]

    # Distance context
    dx = DistancesContext()
    # This imposes minimum/ maximum distances of:
    #   80 and 800 km; could make this configurable
    d_min = config['extent']['mmi']['mindist']
    d_max = config['extent']['mmi']['maxdist']
    dx.rjb = np.logspace(np.log10(d_min), np.log10(d_max), 2000)
    # Details don't matter for this; assuming vertical surface rupturing fault
    # with epicenter at the surface.
    dx.rrup = dx.rjb
    dx.rhypo = dx.rjb
    dx.repi = dx.rjb
    dx.rx = np.zeros_like(dx.rjb)
    dx.ry0 = np.zeros_like(dx.rjb)
    dx.rvolc = np.zeros_like(dx.rjb)

    # Sites context
    sx = SitesContext()
    # Set to soft soil conditions
    sx.vs30 = np.full_like(dx.rjb, 180)
    sx = MultiGMPE.set_sites_depth_parameters(sx, gmpe)
    sx.vs30measured = np.full_like(sx.vs30, False, dtype=bool)
    sx = Sites._addDepthParameters(sx)
    sx.backarc = np.full_like(sx.vs30, False, dtype=bool)

    # Rupture context
    rx = RuptureContext()
    rx.mag = origin.mag
    rx.rake = 0.0
    # From WC94...
    rx.width = 10**(-0.76 + 0.27 * rx.mag)
    rx.dip = 90.0
    rx.ztor = origin.depth
    rx.hypo_depth = origin.depth

    gmpe_imt_mean, _ = gmpe.get_mean_and_stddevs(sx, rx, dx, default_imt,
                                                 sd_types)

    # Convert to MMI
    gmpe_to_mmi, _ = gmice.getMIfromGM(gmpe_imt_mean, default_imt)

    # Minimum distance that exceeds threshold MMI?
    dists_exceed_mmi = dx.rjb[gmpe_to_mmi > min_mmi]
    if len(dists_exceed_mmi):
        mindist_km = np.max(dists_exceed_mmi)
    else:
        mindist_km = d_min

    # Get a projection
    proj = OrthographicProjection(clon - 4, clon + 4, clat + 4, clat - 4)
    if isinstance(rupture, (QuadRupture, EdgeRupture)):
        ruptx, rupty = proj(lons, lats)
    else:
        ruptx, rupty = proj(clon, clat)

    xmin = np.nanmin(ruptx) - mindist_km
    ymin = np.nanmin(rupty) - mindist_km
    xmax = np.nanmax(ruptx) + mindist_km
    ymax = np.nanmax(rupty) + mindist_km

    # Put a limit on range of aspect ratio
    dx = xmax - xmin
    dy = ymax - ymin
    ar = dy / dx
    if ar > 1.2:
        # Inflate x
        dx_target = dy / 1.2
        ddx = dx_target - dx
        xmax = xmax + ddx / 2
        xmin = xmin - ddx / 2
    if ar < 0.83:
        # Inflate y
        dy_target = dx * 0.83
        ddy = dy_target - dy
        ymax = ymax + ddy / 2
        ymin = ymin - ddy / 2

    lonmin, latmin = proj(np.array([xmin]), np.array([ymin]), reverse=True)
    lonmax, latmax = proj(np.array([xmax]), np.array([ymax]), reverse=True)

    #
    # Round coordinates to the nearest minute -- that should make the
    # output grid register with common grid resolutions (60c, 30c,
    # 15c, 7.5c)
    #
    logging.debug("Extent: %f, %f, %f, %f" % (lonmin, lonmax, latmin, latmax))
    return _round_coord(lonmin[0]), _round_coord(lonmax[0]), \
        _round_coord(latmin[0]), _round_coord(latmax[0])
예제 #11
0
def _get_extent_from_multigmpe(rupture, config=None):
    """
    Use MultiGMPE to determine extent
    """
    (clon, clat) = _rupture_center(rupture)
    origin = rupture.getOrigin()
    if config is not None:
        gmpe = MultiGMPE.from_config(config)
        gmice = get_object_from_config('gmice', 'modeling', config)
        if imt.SA in gmice.DEFINED_FOR_INTENSITY_MEASURE_TYPES:
            default_imt = imt.SA(1.0)
        elif imt.PGV in gmice.DEFINED_FOR_INTENSITY_MEASURE_TYPES:
            default_imt = imt.PGV()
        else:
            default_imt = imt.PGA()
    else:
        # Put in some default values for conf
        config = {
            'extent': {
                'mmi': {
                    'threshold': 4.5,
                    'mindist': 100,
                    'maxdist': 1000
                }
            }
        }

        # Generic GMPEs choices based only on active vs stable
        # as defaults...
        stable = is_stable(origin.lon, origin.lat)
        if not stable:
            ASK14 = AbrahamsonEtAl2014()
            CB14 = CampbellBozorgnia2014()
            CY14 = ChiouYoungs2014()
            gmpes = [ASK14, CB14, CY14]
            site_gmpes = None
            weights = [1/3.0, 1/3.0, 1/3.0]
            gmice = WGRW12()
        else:
            Fea96 = FrankelEtAl1996MwNSHMP2008()
            Tea97 = ToroEtAl1997MwNSHMP2008()
            Sea02 = SilvaEtAl2002MwNSHMP2008()
            C03 = Campbell2003MwNSHMP2008()
            TP05 = TavakoliPezeshk2005MwNSHMP2008()
            AB06p = AtkinsonBoore2006Modified2011()
            Pea11 = PezeshkEtAl2011()
            Atk08p = Atkinson2008prime()
            Sea01 = SomervilleEtAl2001NSHMP2008()
            gmpes = [Fea96, Tea97, Sea02, C03,
                     TP05, AB06p, Pea11, Atk08p, Sea01]
            site_gmpes = [AB06p]
            weights = [0.16, 0.0, 0.0, 0.17, 0.17, 0.3, 0.2, 0.0, 0.0]
            gmice = AK07()

        gmpe = MultiGMPE.from_list(
            gmpes, weights, default_gmpes_for_site=site_gmpes)
        default_imt = imt.SA(1.0)

    min_mmi = config['extent']['mmi']['threshold']
    sd_types = [const.StdDev.TOTAL]

    # Distance context
    dx = DistancesContext()
    # This imposes minimum/ maximum distances of:
    #   80 and 800 km; could make this configurable
    d_min = config['extent']['mmi']['mindist']
    d_max = config['extent']['mmi']['maxdist']
    dx.rjb = np.logspace(np.log10(d_min), np.log10(d_max), 2000)
    # Details don't matter for this; assuming vertical surface rupturing fault
    # with epicenter at the surface.
    dx.rrup = dx.rjb
    dx.rhypo = dx.rjb
    dx.repi = dx.rjb
    dx.rx = np.zeros_like(dx.rjb)
    dx.ry0 = np.zeros_like(dx.rjb)
    dx.rvolc = np.zeros_like(dx.rjb)

    # Sites context
    sx = SitesContext()
    # Set to soft soil conditions
    sx.vs30 = np.full_like(dx.rjb, 180)
    sx = MultiGMPE.set_sites_depth_parameters(sx, gmpe)
    sx.vs30measured = np.full_like(sx.vs30, False, dtype=bool)
    sx = Sites._addDepthParameters(sx)
    sx.backarc = np.full_like(sx.vs30, False, dtype=bool)

    # Rupture context
    rx = RuptureContext()
    rx.mag = origin.mag
    rx.rake = 0.0
    # From WC94...
    rx.width = 10**(-0.76 + 0.27*rx.mag)
    rx.dip = 90.0
    rx.ztor = origin.depth
    rx.hypo_depth = origin.depth

    gmpe_imt_mean, _ = gmpe.get_mean_and_stddevs(
        sx, rx, dx, default_imt, sd_types)

    # Convert to MMI
    gmpe_to_mmi, _ = gmice.getMIfromGM(gmpe_imt_mean, default_imt)

    # Minimum distance that exceeds threshold MMI?
    dists_exceed_mmi = dx.rjb[gmpe_to_mmi > min_mmi]
    if len(dists_exceed_mmi):
        mindist_km = np.max(dists_exceed_mmi)
    else:
        mindist_km = d_min

    # Get a projection
    proj = OrthographicProjection(clon - 4, clon + 4, clat + 4, clat - 4)
    if isinstance(rupture, (QuadRupture, EdgeRupture)):
        ruptx, rupty = proj(
            rupture.lons[~np.isnan(rupture.lons)],
            rupture.lats[~np.isnan(rupture.lats)]
        )
    else:
        ruptx, rupty = proj(clon, clat)

    xmin = np.nanmin(ruptx) - mindist_km
    ymin = np.nanmin(rupty) - mindist_km
    xmax = np.nanmax(ruptx) + mindist_km
    ymax = np.nanmax(rupty) + mindist_km

    # Put a limit on range of aspect ratio
    dx = xmax - xmin
    dy = ymax - ymin
    ar = dy / dx
    if ar > 1.2:
        # Inflate x
        dx_target = dy / 1.2
        ddx = dx_target - dx
        xmax = xmax + ddx / 2
        xmin = xmin - ddx / 2
    if ar < 0.83:
        # Inflate y
        dy_target = dx * 0.83
        ddy = dy_target - dy
        ymax = ymax + ddy / 2
        ymin = ymin - ddy / 2

    lonmin, latmin = proj(np.array([xmin]), np.array([ymin]), reverse=True)
    lonmax, latmax = proj(np.array([xmax]), np.array([ymax]), reverse=True)

    #
    # Round coordinates to the nearest minute -- that should make the
    # output grid register with common grid resolutions (60c, 30c,
    # 15c, 7.5c)
    #
    logging.debug("Extent: %f, %f, %f, %f" %
                  (lonmin, lonmax, latmin, latmax))
    return _round_coord(lonmin[0]), _round_coord(lonmax[0]), \
        _round_coord(latmin[0]), _round_coord(latmax[0])
예제 #12
0
    def getDepthAtPoint(self, lat, lon):
        SMALL_DISTANCE = 2e-03  # 2 meters
        depth = np.nan

        tmp, _ = self.computeRjb(np.array([lon]), np.array([lat]),
                                 np.array([0]))
        if tmp > SMALL_DISTANCE:
            return depth

        i = 0
        imin = -1
        dmin = 9999999999999999
        for quad in self.getQuadrilaterals():
            pX = Vector.fromPoint(Point(lon, lat, 0))
            points = np.reshape(np.array([pX.x, pX.y, pX.z]), (1, 3))
            rjb = utils._quad_distance(quad, points, horizontal=True)
            if rjb[0][0] < dmin:
                dmin = rjb[0][0]
                imin = i
            i += 1

        quad = self._quadrilaterals[imin]
        P0, P1, P2, P3 = quad
        # project the quad and the point in question to orthographic defined by
        # quad
        xmin = np.min([P0.x, P1.x, P2.x, P3.x])
        xmax = np.max([P0.x, P1.x, P2.x, P3.x])
        ymin = np.min([P0.y, P1.y, P2.y, P3.y])
        ymax = np.max([P0.y, P1.y, P2.y, P3.y])
        proj = OrthographicProjection(xmin, xmax, ymax, ymin)

        # project each vertex of quad (at 0 depth)
        s0x, s0y = proj(P0.x, P0.y)
        s1x, s1y = proj(P1.x, P1.y)
        s2x, s2y = proj(P2.x, P2.y)
        s3x, s3y = proj(P3.x, P3.y)
        sxx, sxy = proj(lon, lat)

        # turn these to vectors
        s0 = Vector(s0x, s0y, 0)
        s1 = Vector(s1x, s1y, 0)
        s3 = Vector(s3x, s3y, 0)
        sx = Vector(sxx, sxy, 0)

        # Compute vector from s0 to s1
        s0s1 = s1 - s0
        # Compute the vector from s0 to s3
        s0s3 = s3 - s0
        # Compute the vector from s0 to sx
        s0sx = sx - s0

        # cross products
        s0normal = s0s3.cross(s0s1)
        dd = s0s1.cross(s0normal)
        # normalize dd (down dip direction)
        ddn = dd.norm()
        # dot product
        sxdd = ddn.dot(s0sx)

        # get width of quad (convert from km to m)
        w = utils.get_quad_width(quad) * 1000

        # Get weights for top and bottom edge depths
        N = utils.get_quad_normal(quad)
        V = utils.get_vertical_vector(quad)
        dip = np.degrees(np.arccos(Vector.dot(N, V)))
        ws = (w * np.cos(np.radians(dip)))
        wtt = (ws - sxdd) / ws
        wtb = sxdd / ws

        # Compute the depth of of the plane at Px:
        depth = wtt * P0.z + wtb * P3.z * 1000

        return depth
예제 #13
0
    def fromTrace(cls,
                  xp0,
                  yp0,
                  xp1,
                  yp1,
                  zp,
                  widths,
                  dips,
                  origin,
                  strike=None,
                  group_index=None,
                  reference=""):
        """
        Create a QuadRupture instance from a set of vertices that define the
        top of the rupture, and an array of widths/dips.

        Each rupture quadrilaterial is defined by specifying the latitude,
        longitude, and depth of the two vertices on the top edges, which must
        have the dame depths. The other verticies are then constructed from
        the top edges and the width and dip of the quadrilateral.

        Args:
            xp0 (array): Array or list of longitudes (floats) of p0.
            yp0 (array): Array or list of latitudes (floats) of p0.
            xp1 (array): Array or list of longitudes (floats) of p1.
            yp1 (array): Array or list of latitudes (floats) of p1.
            zp (array): Array or list of depths for each of the top of rupture
                rectangles (km).
            widths (array): Array of widths for each of rectangle (km).
            dips (array): Array of dips for each of rectangle (degrees).
            origin (Origin): Reference to a ShakeMap origin object.
            strike (array): If None then strike is computed from verticies of
                top edge of each quadrilateral. If the array has only a
                single value, then all
                quadrilaterals are constructed assuming this strike direction.
                If an array with the same length as the trace coordinates then
                it specifies the strike for each quadrilateral.
            group_index (list): List of integers to indicate group index. If
                None then each quadrilateral is assumed to be in a different
                group since there is no guarantee that any of them are
                continuous.
            reference (str): String explaining where the rupture definition
                came from (publication style reference, etc.).

        Returns:
            QuadRupture instance.

        Raises:
            ShakeLibException: if the input arrays are not all the same
                length, or if the strike array is not length 1 or the same
                length as the input arrays.

        """
        if not (len(xp0) == len(yp0) == len(xp1) == len(yp1) == len(zp) ==
                len(dips) == len(widths)):
            raise ShakeLibException(
                'Number of xp0,yp0,xp1,yp1,zp,widths,dips points must be '
                'equal.')
        if strike is not None and len(xp0) != len(strike) and len(strike) != 1:
            raise ShakeLibException(
                'Strike must be None or an array of one value or the '
                'same length as trace coordinates.')

        if group_index is None:
            group_index = np.array(range(len(xp0)))

        # Convert dips to radians
        dips = np.radians(dips)

        # Ensure that all input sequences are numpy arrays
        xp0 = np.array(xp0, dtype='d')
        xp1 = np.array(xp1, dtype='d')
        yp0 = np.array(yp0, dtype='d')
        yp1 = np.array(yp1, dtype='d')
        zp = np.array(zp, dtype='d')
        widths = np.array(widths, dtype='d')
        dips = np.array(dips, dtype='d')

        # Get a projection object
        west = np.min((xp0.min(), xp1.min()))
        east = np.max((xp0.max(), xp1.max()))
        south = np.min((yp0.min(), yp1.min()))
        north = np.max((yp0.max(), yp1.max()))

        # Projected coordinates are in km
        proj = OrthographicProjection(west, east, north, south)
        xp2 = np.zeros_like(xp0)
        xp3 = np.zeros_like(xp0)
        yp2 = np.zeros_like(xp0)
        yp3 = np.zeros_like(xp0)
        zpdown = np.zeros_like(zp)
        for i in range(0, len(xp0)):
            # Project the top edge coordinates
            p0x, p0y = proj(xp0[i], yp0[i])
            p1x, p1y = proj(xp1[i], yp1[i])

            # Get the rotation angle defined by these two points
            if strike is None:
                dx = p1x - p0x
                dy = p1y - p0y
                theta = np.arctan2(dx, dy)  # theta is angle from north
            elif len(strike) == 1:
                theta = np.radians(strike[0])
            else:
                theta = np.radians(strike[i])

            R = np.array([[np.cos(theta), -np.sin(theta)],
                          [np.sin(theta), np.cos(theta)]])

            # Rotate the top edge points into a new coordinate system (vertical
            # line)
            p0 = np.array([p0x, p0y])
            p1 = np.array([p1x, p1y])
            p0p = np.dot(R, p0)
            p1p = np.dot(R, p1)

            # Get right side coordinates in project, rotated system
            dz = np.sin(dips[i]) * widths[i]
            dx = np.cos(dips[i]) * widths[i]
            p3xp = p0p[0] + dx
            p3yp = p0p[1]
            p2xp = p1p[0] + dx
            p2yp = p1p[1]

            # Get right side coordinates in un-rotated projected system
            p3p = np.array([p3xp, p3yp])
            p2p = np.array([p2xp, p2yp])
            Rback = np.array([[np.cos(-theta), -np.sin(-theta)],
                              [np.sin(-theta), np.cos(-theta)]])
            p3 = np.dot(Rback, p3p)
            p2 = np.dot(Rback, p2p)
            p3x = np.array([p3[0]])
            p3y = np.array([p3[1]])
            p2x = np.array([p2[0]])
            p2y = np.array([p2[1]])

            # project lower edge points back to lat/lon coordinates
            lon3, lat3 = proj(p3x, p3y, reverse=True)
            lon2, lat2 = proj(p2x, p2y, reverse=True)

            xp2[i] = lon2
            xp3[i] = lon3
            yp2[i] = lat2
            yp3[i] = lat3
            zpdown[i] = zp[i] + dz

        # ---------------------------------------------------------------------
        # Create GeoJSON object
        # ---------------------------------------------------------------------

        coords = []
        u_groups = np.unique(group_index)
        n_groups = len(u_groups)
        for i in range(n_groups):
            ind = np.where(u_groups[i] == group_index)[0]
            lons = np.concatenate([
                xp0[ind[0]].reshape((1, )), xp1[ind], xp2[ind][::-1],
                xp3[ind][::-1][-1].reshape((1, )), xp0[ind[0]].reshape((1, ))
            ])
            lats = np.concatenate([
                yp0[ind[0]].reshape((1, )), yp1[ind], yp2[ind][::-1],
                yp3[ind][::-1][-1].reshape((1, )), yp0[ind[0]].reshape((1, ))
            ])
            deps = np.concatenate([
                zp[ind[0]].reshape((1, )), zp[ind], zpdown[ind][::-1],
                zpdown[ind][::-1][-1].reshape((1, )), zp[ind[0]].reshape((1, ))
            ])

            poly = []
            for lon, lat, dep in zip(lons, lats, deps):
                poly.append([lon, lat, dep])
            coords.append(poly)

        d = {
            "type":
            "FeatureCollection",
            "metadata": {
                "reference": reference
            },
            "features": [{
                "type": "Feature",
                "properties": {
                    "rupture type": "rupture extent"
                },
                "geometry": {
                    "type": "MultiPolygon",
                    "coordinates": [coords]
                }
            }]
        }

        # Add origin information to metadata
        odict = origin.__dict__
        for k, v in odict.items():
            if isinstance(v, HistoricTime):
                d['metadata'][k] = v.strftime(constants.TIMEFMT)
            else:
                d['metadata'][k] = v

        return cls(d, origin)
예제 #14
0
    def createGeoJSON(self):
        """
        Create the GeoJSON for the segment grid cells and earthquake point.

        Returns:
            dictionary: GeoJSON formatted dictionary.
        """
        segment_cells = []

        slips = np.asarray([])
        for segment in self.segments:
            slips = np.append(slips, segment['slip'].flatten())
        max_slip = np.ceil(np.max(slips))
        COLORS.vmax = max_slip

        for num in range(self.getNumSegments()):
            # Get segment
            segment = self.getSegment(num)
            arr_size = len(segment['lat'].flatten())
            dx = [self.event['dx'] / 2] * arr_size
            dy = [self.event['dz'] / 2] * arr_size
            length = [self.event['dx']] * arr_size
            width = [self.event['dz']] * arr_size
            strike = [segment['strike']] * arr_size
            dip = [segment['dip']] * arr_size
            optional_properties = copy.deepcopy(segment)
            for key in [
                    'dip', 'strike', 'lon', 'depth', 'slip', 'lat', 'length',
                    'width'
            ]:
                del optional_properties[key]
            for key in optional_properties:
                optional_properties[key] = optional_properties[key].flatten()

            px = segment['lon'].flatten()
            py = segment['lat'].flatten()
            pz = segment['depth'].flatten()
            slips = segment['slip'].flatten()

            # Verify that all are numpy arrays
            px = np.array(px, dtype='d')
            py = np.array(py, dtype='d')
            # depth should be in meters not in km
            pz = np.array(pz, dtype='d') * 1000
            dx = np.array(dx, dtype='d')
            dy = np.array(dy, dtype='d')
            length = np.array(length, dtype='d')
            width = np.array(width, dtype='d')
            strike = np.array(strike, dtype='d')
            dip = np.array(dip, dtype='d')

            # Get P1 and P2 (top horizontal points)
            theta = np.rad2deg(np.arctan((dy * np.cos(np.deg2rad(dip))) / dx))
            P1_direction = strike + 180 + theta
            P1_distance = np.sqrt(dx**2 + (dy * np.cos(np.deg2rad(dip)))**2)
            P2_direction = strike
            P2_distance = length
            P1_lon = np.asarray([])
            P1_lat = np.asarray([])
            P2_lon = np.asarray([])
            P2_lat = np.asarray([])
            for idx, value in enumerate(px):
                P1_points = point_at(px[idx], py[idx], P1_direction[idx],
                                     P1_distance[idx])
                P1_lon = np.append(P1_lon, P1_points[0])
                P1_lat = np.append(P1_lat, P1_points[1])
                P2_points = point_at(P1_points[0], P1_points[1],
                                     P2_direction[idx], P2_distance[idx])
                P2_lon = np.append(P2_lon, P2_points[0])
                P2_lat = np.append(P2_lat, P2_points[1])

            # Get top depth
            top_horizontal_depth = pz - 1000 * np.abs(
                dy * np.sin(np.deg2rad(dip)))

            group_index = np.array(range(len(P1_lon)))

            # Convert dip to radians
            dip = np.radians(dip)

            # Get a projection object
            west = np.min((P1_lon.min(), P2_lon.min()))
            east = np.max((P1_lon.max(), P2_lon.max()))
            south = np.min((P1_lat.min(), P2_lat.min()))
            north = np.max((P1_lat.max(), P2_lat.max()))

            # Projected coordinates are in km
            proj = OrthographicProjection(west, east, north, south)
            xp2 = np.zeros_like(P1_lon)
            xp3 = np.zeros_like(P1_lon)
            yp2 = np.zeros_like(P1_lon)
            yp3 = np.zeros_like(P1_lon)
            zpdown = np.zeros_like(top_horizontal_depth)
            for i, p1lon in enumerate(P1_lon):
                # Project the top edge coordinates
                p0x, p0y = proj(p1lon, P1_lat[i])
                p1x, p1y = proj(P2_lon[i], P2_lat[i])

                # Get the rotation angle defined by these two points
                if strike is None:
                    dx = p1x - p0x
                    dy = p1y - p0y
                    theta = np.arctan2(dx, dy)  # theta is angle from north
                elif len(strike) == 1:
                    theta = np.radians(strike[0])
                else:
                    theta = np.radians(strike[i])

                R = np.array([[np.cos(theta), -np.sin(theta)],
                              [np.sin(theta), np.cos(theta)]])

                # Rotate the top edge points into a new coordinate system (vertical
                # line)
                p0 = np.array([p0x, p0y])
                p1 = np.array([p1x, p1y])
                p0p = np.dot(R, p0)
                p1p = np.dot(R, p1)

                # Get right side coordinates in project, rotated system
                dz = np.sin(dip[i]) * width[i] * 1000
                dx = np.cos(dip[i]) * width[i]
                p3xp = p0p[0] + dx
                p3yp = p0p[1]
                p2xp = p1p[0] + dx
                p2yp = p1p[1]

                # Get right side coordinates in un-rotated projected system
                p3p = np.array([p3xp, p3yp])
                p2p = np.array([p2xp, p2yp])
                Rback = np.array([[np.cos(-theta), -np.sin(-theta)],
                                  [np.sin(-theta),
                                   np.cos(-theta)]])
                p3 = np.dot(Rback, p3p)
                p2 = np.dot(Rback, p2p)
                p3x = np.array([p3[0]])
                p3y = np.array([p3[1]])
                p2x = np.array([p2[0]])
                p2y = np.array([p2[1]])

                # project lower edge points back to lat/lon coordinates
                lon3, lat3 = proj(p3x, p3y, reverse=True)
                lon2, lat2 = proj(p2x, p2y, reverse=True)

                xp2[i] = lon2
                xp3[i] = lon3
                yp2[i] = lat2
                yp3[i] = lat3
                zpdown[i] = top_horizontal_depth[i] + dz

            # ---------------------------------------------------------------------
            # Create GeoJSON object
            # ---------------------------------------------------------------------

            u_groups = np.unique(group_index)
            n_groups = len(u_groups)
            polygons = []

            for i in range(n_groups):
                ind = np.where(u_groups[i] == group_index)[0]
                lons = np.concatenate([
                    P1_lon[ind[0]].reshape((1, )), P2_lon[ind], xp2[ind][::-1],
                    xp3[ind][::-1][-1].reshape((1, )), P1_lon[ind[0]].reshape(
                        (1, ))
                ])
                lats = np.concatenate([
                    P1_lat[ind[0]].reshape((1, )), P2_lat[ind], yp2[ind][::-1],
                    yp3[ind][::-1][-1].reshape((1, )), P1_lat[ind[0]].reshape(
                        (1, ))
                ])
                deps = np.concatenate([
                    top_horizontal_depth[ind[0]].reshape(
                        (1, )), top_horizontal_depth[ind], zpdown[ind][::-1],
                    zpdown[ind][::-1][-1].reshape(
                        (1, )), top_horizontal_depth[ind[0]].reshape((1, ))
                ])

                poly = []
                for lon, lat, dep in zip(lons, lats, deps):
                    lon = np.around(lon, decimals=4)
                    lat = np.around(lat, decimals=4)
                    deps = np.around(deps, decimals=4)
                    coordinates = np.around(np.asarray([lon, lat, dep]),
                                            decimals=5)
                    poly.append(coordinates.tolist())

                properties = {}
                for property in optional_properties:
                    properties[property] = optional_properties[property][i]
                h = COLORS.getDataColor(slips[i], color_format='hex')
                properties["slip"] = slips[i]
                properties["fill"] = h
                properties["stroke-width"] = 1.5
                properties["fill-opacity"] = 1
                d = {
                    "type": "Feature",
                    "properties": properties,
                    "geometry": {
                        "type": "Polygon",
                        "coordinates": [poly]
                    }
                }
                polygons += [d]
            segment_cells += polygons
        features = {
            "type": "FeatureCollection",
            "metadata": {
                'epicenter': {
                    'location': self.event['location'],
                    'date':
                    self.event['date'].strftime('%Y-%m-%dT%H:%M:%S.%fZ'),
                    'depth': self.event['depth'],
                    'moment': self.event['moment'],
                    'mag': self.event['mag'],
                    'lon': self.event['lon'],
                    'lat': self.event['lat']
                }
            },
            "features": segment_cells
        }
        self.corners = features
예제 #15
0
    def __computeLD(self):
        """
        Computes LD -- the rupture length de-normalization term.
        """
        # Use an orthographic projection
        latmin = self._lat.min()
        latmax = self._lat.max()
        lonmin = self._lon.min()
        lonmax = self._lon.max()
        proj = OrthographicProjection(lonmin, lonmax, latmax, latmin)

        # Get epi projection
        epi_x, epi_y = proj(self._hyp.longitude, self._hyp.latitude)

        # Get the lines for the top edge of the rupture
        qds = self._rup.getQuadrilaterals()
        nq = len(qds)
        top_lat = np.array([[]])
        top_lon = np.array([[]])
        top_dep = np.array([[]])
        for j in range(0, nq):
            top_lat = np.append(top_lat, qds[j][0].latitude)
            top_lat = np.append(top_lat, qds[j][1].latitude)
            top_lon = np.append(top_lon, qds[j][0].longitude)
            top_lon = np.append(top_lon, qds[j][1].longitude)
            top_dep = np.append(top_dep, qds[j][0].depth)
            top_dep = np.append(top_dep, qds[j][1].depth)
        top_x, top_y = proj(top_lon, top_lat)

        Lrup_max = 400
        slat = self._lat
        slon = self._lon
        LD = np.zeros_like(slat)
        Ls = np.zeros_like(slat)

        ni, nj = LD.shape
        for i in range(ni):
            for j in range(nj):
                # -------------------------------------------------------------
                # Compute Ls
                # -------------------------------------------------------------
                # Convert to local orthographic
                site_x, site_y = proj(slon[i, j], slat[i, j])

                # Shift so center is at epicenter
                site_x2 = site_x - epi_x
                site_y2 = site_y - epi_y
                top_x2 = top_x - epi_x
                top_y2 = top_y - epi_y

                # Angle to rotate to put site on x-axis
                alpha = np.arctan2(site_y2, site_x2)
                axis = [0, 0, 1]
                rmat = _rotation_matrix(axis, -alpha)
                llr = [None] * len(top_lat)

                # Apply rotation to each point on trace
                for k in range(len(top_lat)):
                    llr[k] = np.dot(rmat, [top_x2[k], top_y2[k], 0])
                    site3 = np.dot(rmat, [site_x2, site_y2, 0])
                Li = np.min([np.max([a[0] for a in llr]), site3[0]])

                # -------------------------------------------------------------
                # Compute LD and save results into matrices
                # -------------------------------------------------------------

                Lrup = np.sqrt(Li * Li + self._Wrup * self._Wrup)
                LD[i, j] = np.log(Lrup) / np.log(Lrup_max)
                Ls[i, j] = Li
        self._LD = LD
        self._Ls = Ls
예제 #16
0
def test_ss3():
    magnitude = 7.2
    dip = np.array([90])
    rake = 180.0
    width = np.array([15])
    rupx = np.array([0, 0])
    rupy = np.array([0, 80])
    zp = np.array([0])
    epix = np.array([0])
    epiy = np.array([0.2 * rupy[1]])

    # Convert to lat/lon
    proj = OrthographicProjection(-122, -120, 39, 37)
    tlon, tlat = proj(rupx, rupy, reverse=True)
    epilon, epilat = proj(epix, epiy, reverse=True)

    # Origin:
    origin = Origin({'lat': epilat[0],
                     'lon': epilon[0],
                     'depth': 10,
                     'mag': magnitude,
                     'id': 'ss3',
                     'netid': 'us',
                     'network': '',
                     'locstring': '',
                     'rake': rake,
                     'time': HistoricTime.utcfromtimestamp(int(time.time()))})

    rup = QuadRupture.fromTrace(
        np.array([tlon[0]]), np.array([tlat[0]]),
        np.array([tlon[1]]), np.array([tlat[1]]),
        zp, width, dip, origin, reference='ss3')

    x = np.linspace(-60, 60, 21)
    y = np.linspace(-60, 138, 34)
    site_x, site_y = np.meshgrid(x, y)
    slon, slat = proj(site_x, site_y, reverse=True)
    deps = np.zeros_like(slon)

    test1 = Bayless2013(origin, rup, slat, slon, deps, T=1.0)

    # Test fd
    fd = test1.getFd()
    fd_test = np.array(
        [[0.00000000e+00, 0.00000000e+00, 2.14620746e-03,
          6.47899336e-03, 1.23119791e-02, 1.91676140e-02,
          2.64009788e-02, 3.32427846e-02, 3.88863288e-02,
          4.26104002e-02, 4.39120296e-02, 4.26104002e-02,
          3.88863288e-02, 3.32427846e-02, 2.64009788e-02,
          1.91676140e-02, 1.23119791e-02, 6.47899336e-03,
          2.14620746e-03, 0.00000000e+00, 0.00000000e+00],
         [0.00000000e+00, 8.57780996e-04, 3.99405791e-03,
          9.31948105e-03, 1.65406113e-02, 2.51316805e-02,
          3.43205435e-02, 4.31274592e-02, 5.04747209e-02,
          5.53634169e-02, 5.70796092e-02, 5.53634169e-02,
          5.04747209e-02, 4.31274592e-02, 3.43205435e-02,
          2.51316805e-02, 1.65406113e-02, 9.31948105e-03,
          3.99405791e-03, 8.57780996e-04, 0.00000000e+00],
            [-7.32594549e-04, 1.80425497e-04, 3.76908220e-03,
             1.00175179e-02, 1.86854835e-02, 2.92291145e-02,
             4.07487277e-02, 5.20057177e-02, 6.15509770e-02,
             6.79776087e-02, 7.02477931e-02, 6.79776087e-02,
             6.15509770e-02, 5.20057177e-02, 4.07487277e-02,
             2.92291145e-02, 1.86854835e-02, 1.00175179e-02,
             3.76908220e-03, 1.80425497e-04, -7.32594549e-04],
            [-3.29238561e-03, -2.60643191e-03, 1.16635260e-03,
             8.15185259e-03, 1.82290773e-02, 3.08983182e-02,
             4.51608038e-02, 5.94769126e-02, 7.18919113e-02,
             8.03888307e-02, 8.34165399e-02, 8.03888307e-02,
             7.18919113e-02, 5.94769126e-02, 4.51608038e-02,
             3.08983182e-02, 1.82290773e-02, 8.15185259e-03,
             1.16635260e-03, -2.60643191e-03, -3.29238561e-03],
            [-7.68543266e-03, -7.63179286e-03, -4.08866637e-03,
             3.27605236e-03, 1.45558215e-02, 2.94068040e-02,
             4.68176355e-02, 6.49397159e-02, 7.72066272e-02,
             8.50445368e-02, 8.77974692e-02, 8.50445368e-02,
             7.72066272e-02, 6.49397159e-02, 4.68176355e-02,
             2.94068040e-02, 1.45558215e-02, 3.27605236e-03,
             -4.08866637e-03, -7.63179286e-03, -7.68543266e-03],
            [-1.38078234e-02, -1.49011067e-02, -1.21731364e-02,
             -5.02168047e-03, 6.98177526e-03, 2.38268531e-02,
             4.30419205e-02, 6.00041964e-02, 7.44541603e-02,
             8.42939552e-02, 8.77989590e-02, 8.42939552e-02,
             7.44541603e-02, 6.00041964e-02, 4.30419205e-02,
             2.38268531e-02, 6.98177526e-03, -5.02168047e-03,
             -1.21731364e-02, -1.49011067e-02, -1.38078234e-02],
            [-2.13780396e-02, -2.42165379e-02, -2.30613142e-02,
             -1.70011475e-02, -5.15036128e-03, 1.25885635e-02,
             3.24536739e-02, 5.25619351e-02, 7.05100243e-02,
             8.31900906e-02, 8.78003567e-02, 8.31900906e-02,
             7.05100243e-02, 5.25619351e-02, 3.24536739e-02,
             1.25885635e-02, -5.15036128e-03, -1.70011475e-02,
             -2.30613142e-02, -2.42165379e-02, -2.13780396e-02],
            [-2.98882710e-02, -3.50862342e-02, -3.63793490e-02,
             -3.25716319e-02, -2.22546618e-02, -3.59274163e-03,
             1.83064517e-02, 4.20112440e-02, 6.46115966e-02,
             8.14746164e-02, 8.78016623e-02, 8.14746164e-02,
             6.46115966e-02, 4.20112440e-02, 1.83064517e-02,
             -3.59274163e-03, -2.22546618e-02, -3.25716319e-02,
             -3.63793490e-02, -3.50862342e-02, -2.98882710e-02],
            [-3.85810679e-02, -4.66488633e-02, -5.12430987e-02,
             -5.10089462e-02, -4.20856023e-02, -2.36905234e-02,
             -6.33876287e-04, 2.66765430e-02, 5.53289928e-02,
             7.86066125e-02, 8.78028757e-02, 7.86066125e-02,
             5.53289928e-02, 2.66765430e-02, -6.33876287e-04,
             -2.36905234e-02, -4.20856023e-02, -5.10089462e-02,
             -5.12430987e-02, -4.66488633e-02, -3.85810679e-02],
            [-4.64803335e-02, -5.76615888e-02, -6.61458422e-02,
             -7.06512643e-02, -6.38427394e-02, -4.77258398e-02,
             -2.55483969e-02, 4.05840724e-03, 3.98470070e-02,
             7.33053399e-02, 8.78039969e-02, 7.33053399e-02,
             3.98470070e-02, 4.05840724e-03, -2.55483969e-02,
             -4.77258398e-02, -6.38427394e-02, -7.06512643e-02,
             -6.61458422e-02, -5.76615888e-02, -4.64803335e-02],
            [-5.25038299e-02, -6.66129442e-02, -7.90147081e-02,
             -8.87629178e-02, -8.59653118e-02, -7.42828398e-02,
             -5.64316505e-02, -2.87083225e-02, 1.25945312e-02,
             6.19971667e-02, 8.78050260e-02, 6.19971667e-02,
             1.25945312e-02, -2.87083225e-02, -5.64316505e-02,
             -7.42828398e-02, -8.59653118e-02, -8.87629178e-02,
             -7.90147081e-02, -6.66129442e-02, -5.25038299e-02],
            [-5.69779111e-02, -7.36791817e-02, -8.97495345e-02,
             -1.04799583e-01, -1.07737239e-01, -1.02875880e-01,
             -9.46568471e-02, -7.95630162e-02, -4.96285112e-02,
             6.59954795e-03, 5.25569882e-02, 6.59954795e-03,
             -4.96285112e-02, -7.95630162e-02, -9.46568471e-02,
             -1.02875880e-01, -1.07737239e-01, -1.04799583e-01,
             -8.97495345e-02, -7.36791817e-02, -5.69779111e-02],
            [-5.90357675e-02, -7.69727119e-02, -9.48442826e-02,
             -1.12607620e-01, -1.18744885e-01, -1.18201834e-01,
             -1.17217017e-01, -1.15152899e-01, -1.09694433e-01,
             -8.82341332e-02, -1.61624035e-02, -8.82341332e-02,
             -1.09694433e-01, -1.15152899e-01, -1.17217017e-01,
             -1.18201834e-01, -1.18744885e-01, -1.12607620e-01,
             -9.48442826e-02, -7.69727119e-02, -5.90357675e-02],
            [-5.92189452e-02, -7.72680305e-02, -9.53051857e-02,
             -1.13322519e-01, -1.19770917e-01, -1.19670660e-01,
             -1.19486798e-01, -1.19092639e-01, -1.17989113e-01,
             -1.12555820e-01, -4.50009776e-02, -1.12555820e-01,
             -1.17989113e-01, -1.19092639e-01, -1.19486798e-01,
             -1.19670660e-01, -1.19770917e-01, -1.13322519e-01,
             -9.53051857e-02, -7.72680305e-02, -5.92189452e-02],
            [-5.79249958e-02, -7.51927112e-02, -9.20842554e-02,
             -1.08361430e-01, -1.12722790e-01, -1.09732675e-01,
             -1.04531672e-01, -9.44729544e-02, -7.23277773e-02,
             -2.05699911e-02, 3.58249631e-02, -2.05699911e-02,
             -7.23277773e-02, -9.44729544e-02, -1.04531672e-01,
             -1.09732675e-01, -1.12722790e-01, -1.08361430e-01,
             -9.20842554e-02, -7.51927112e-02, -5.79249958e-02],
            [-5.42527703e-02, -6.93641123e-02, -8.31684773e-02,
             -9.49114165e-02, -9.41989454e-02, -8.48645354e-02,
             -7.00894708e-02, -4.58286259e-02, -6.37563061e-03,
             4.68887998e-02, 7.77968419e-02, 4.68887998e-02,
             -6.37563061e-03, -4.58286259e-02, -7.00894708e-02,
             -8.48645354e-02, -9.41989454e-02, -9.49114165e-02,
             -8.31684773e-02, -6.93641123e-02, -5.42527703e-02],
            [-4.82490057e-02, -5.99997941e-02, -6.91786120e-02,
             -7.44891242e-02, -6.73705808e-02, -5.13001284e-02,
             -2.84188057e-02, 3.60143816e-03, 4.47470123e-02,
             8.58663851e-02, 1.04548354e-01, 8.58663851e-02,
             4.47470123e-02, 3.60143816e-03, -2.84188057e-02,
             -5.13001284e-02, -6.73705808e-02, -7.44891242e-02,
             -6.91786120e-02, -5.99997941e-02, -4.82490057e-02],
            [-4.03203010e-02, -4.79063206e-02, -5.16352259e-02,
             -4.98707253e-02, -3.67295509e-02, -1.57342058e-02,
             1.13668830e-02, 4.46551184e-02, 8.10450840e-02,
             1.11780747e-01, 1.24226598e-01, 1.11780747e-01,
             8.10450840e-02, 4.46551184e-02, 1.13668830e-02,
             -1.57342058e-02, -3.67295509e-02, -4.98707253e-02,
             -5.16352259e-02, -4.79063206e-02, -4.03203010e-02],
            [-3.10250239e-02, -3.40796094e-02, -3.22089254e-02,
             -2.37094100e-02, -5.85463114e-03, 1.77402761e-02,
             4.57786845e-02, 7.69637052e-02, 1.07537652e-01,
             1.30906328e-01, 1.39800436e-01, 1.30906328e-01,
             1.07537652e-01, 7.69637052e-02, 4.57786845e-02,
             1.77402761e-02, -5.85463114e-03, -2.37094100e-02,
             -3.22089254e-02, -3.40796094e-02, -3.10250239e-02],
            [-2.09301700e-02, -1.94475962e-02, -1.22970199e-02,
             2.07296407e-03, 2.31516868e-02, 4.74574033e-02,
             7.44743481e-02, 1.02380049e-01, 1.27776301e-01,
             1.46003379e-01, 1.52690015e-01, 1.46003379e-01,
             1.27776301e-01, 1.02380049e-01, 7.44743481e-02,
             4.74574033e-02, 2.31516868e-02, 2.07296407e-03,
             -1.22970199e-02, -1.94475962e-02, -2.09301700e-02],
            [-1.05257992e-02, -4.74329696e-03, 7.12107274e-03,
             2.63431361e-02, 4.93709790e-02, 7.31527220e-02,
             9.82233938e-02, 1.22728059e-01, 1.43894925e-01,
             1.58465026e-01, 1.63685984e-01, 1.58465026e-01,
             1.43894925e-01, 1.22728059e-01, 9.82233938e-02,
             7.31527220e-02, 4.93709790e-02, 2.63431361e-02,
             7.12107274e-03, -4.74329696e-03, -1.05257992e-02],
            [-1.89098657e-04, 9.52392382e-03, 2.54577716e-02,
             4.85730869e-02, 7.26048516e-02, 9.51726659e-02,
             1.17988523e-01, 1.39380421e-01, 1.57176612e-01,
             1.69076915e-01, 1.73274075e-01, 1.69076915e-01,
             1.57176612e-01, 1.39380421e-01, 1.17988523e-01,
             9.51726659e-02, 7.26048516e-02, 4.85730869e-02,
             2.54577716e-02, 9.52392382e-03, -1.89098657e-04],
            [9.81732797e-03, 2.30419581e-02, 4.24234701e-02,
             6.86213308e-02, 9.30164618e-02, 1.14050063e-01,
             1.34620894e-01, 1.53304069e-01, 1.68420867e-01,
             1.78321253e-01, 1.81774183e-01, 1.78321253e-01,
             1.68420867e-01, 1.53304069e-01, 1.34620894e-01,
             1.14050063e-01, 9.30164618e-02, 6.86213308e-02,
             4.24234701e-02, 2.30419581e-02, 9.81732797e-03],
            [1.93290725e-02, 3.56493099e-02, 5.79271157e-02,
             8.65611122e-02, 1.10914315e-01, 1.30317702e-01,
             1.48798006e-01, 1.65173224e-01, 1.78147031e-01,
             1.86513895e-01, 1.89408199e-01, 1.86513895e-01,
             1.78147031e-01, 1.65173224e-01, 1.48798006e-01,
             1.30317702e-01, 1.10914315e-01, 8.65611122e-02,
             5.79271157e-02, 3.56493099e-02, 1.93290725e-02],
            [2.68168937e-02, 4.52356810e-02, 6.92261217e-02,
             9.89630241e-02, 1.23093435e-01, 1.40640067e-01,
             1.56998943e-01, 1.71215219e-01, 1.82297185e-01,
             1.89360704e-01, 1.91789146e-01, 1.89360704e-01,
             1.82297185e-01, 1.71215219e-01, 1.56998943e-01,
             1.40640067e-01, 1.23093435e-01, 9.89630241e-02,
             6.92261217e-02, 4.52356810e-02, 2.68168937e-02],
            [3.19403269e-02, 5.15051953e-02, 7.61032066e-02,
             1.05705197e-01, 1.31722206e-01, 1.47466588e-01,
             1.61892450e-01, 1.74235616e-01, 1.83735386e-01,
             1.89735533e-01, 1.91788616e-01, 1.89735533e-01,
             1.83735386e-01, 1.74235616e-01, 1.61892450e-01,
             1.47466588e-01, 1.31722206e-01, 1.05705197e-01,
             7.61032066e-02, 5.15051953e-02, 3.19403269e-02],
            [3.48604070e-02, 5.49292382e-02, 7.94274234e-02,
             1.08149011e-01, 1.38923419e-01, 1.53070440e-01,
             1.65849067e-01, 1.76646162e-01, 1.84871647e-01,
             1.90029617e-01, 1.91787948e-01, 1.90029617e-01,
             1.84871647e-01, 1.76646162e-01, 1.65849067e-01,
             1.53070440e-01, 1.38923419e-01, 1.08149011e-01,
             7.94274234e-02, 5.49292382e-02, 3.48604070e-02],
            [3.53402022e-02, 5.53653759e-02, 7.91965502e-02,
             1.06486934e-01, 1.36563003e-01, 1.57713955e-01,
             1.69087164e-01, 1.78598269e-01, 1.85784340e-01,
             1.90264452e-01, 1.91787141e-01, 1.90264452e-01,
             1.85784340e-01, 1.78598269e-01, 1.69087164e-01,
             1.57713955e-01, 1.36563003e-01, 1.06486934e-01,
             7.91965502e-02, 5.53653759e-02, 3.53402022e-02],
            [3.32889822e-02, 5.28319225e-02, 7.55769079e-02,
             1.01077605e-01, 1.28592068e-01, 1.57023616e-01,
             1.71766715e-01, 1.80199729e-01, 1.86528091e-01,
             1.90454829e-01, 1.91786196e-01, 1.90454829e-01,
             1.86528091e-01, 1.80199729e-01, 1.71766715e-01,
             1.57023616e-01, 1.28592068e-01, 1.01077605e-01,
             7.55769079e-02, 5.28319225e-02, 3.32889822e-02],
            [2.87295370e-02, 4.74613283e-02, 6.88388861e-02,
             9.23568989e-02, 1.17254645e-01, 1.42483223e-01,
             1.66695764e-01, 1.81528776e-01, 1.87141877e-01,
             1.90611190e-01, 1.91785112e-01, 1.90611190e-01,
             1.87141877e-01, 1.81528776e-01, 1.66695764e-01,
             1.42483223e-01, 1.17254645e-01, 9.23568989e-02,
             6.88388861e-02, 4.74613283e-02, 2.87295370e-02],
            [2.17650266e-02, 3.94568191e-02, 5.93023344e-02,
             8.07720575e-02, 1.03124482e-01, 1.25394282e-01,
             1.46405870e-01, 1.64828303e-01, 1.79288925e-01,
             1.88553222e-01, 1.91747252e-01, 1.88553222e-01,
             1.79288925e-01, 1.64828303e-01, 1.46405870e-01,
             1.25394282e-01, 1.03124482e-01, 8.07720575e-02,
             5.93023344e-02, 3.94568191e-02, 2.17650266e-02],
            [1.25495284e-02, 2.90572166e-02, 4.72972116e-02,
             6.67423656e-02, 8.66951873e-02, 1.06290296e-01,
             1.24520131e-01, 1.40293247e-01, 1.52531693e-01,
             1.60303860e-01, 1.62970689e-01, 1.60303860e-01,
             1.52531693e-01, 1.40293247e-01, 1.24520131e-01,
             1.06290296e-01, 8.66951873e-02, 6.67423656e-02,
             4.72972116e-02, 2.90572166e-02, 1.25495284e-02],
            [1.26441934e-03, 1.65114811e-02, 3.31390978e-02,
             5.06407706e-02, 6.83765492e-02, 8.55839448e-02,
             1.01408074e-01, 1.14955639e-01, 1.25373662e-01,
             1.31946425e-01, 1.34193829e-01, 1.31946425e-01,
             1.25373662e-01, 1.14955639e-01, 1.01408074e-01,
             8.55839448e-02, 6.83765492e-02, 5.06407706e-02,
             3.31390978e-02, 1.65114811e-02, 1.26441934e-03],
            [0.00000000e+00, 2.06213867e-03, 1.71162845e-02,
             3.27888240e-02, 4.85026462e-02, 6.35932476e-02,
             7.73387997e-02, 8.90069217e-02, 9.79166934e-02,
             1.03509489e-01, 1.05416736e-01, 1.03509489e-01,
             9.79166934e-02, 8.90069217e-02, 7.73387997e-02,
             6.35932476e-02, 4.85026462e-02, 3.27888240e-02,
             1.71162845e-02, 2.06213867e-03, 0.00000000e+00]]
    )
    np.testing.assert_allclose(fd, fd_test, rtol=1e-4)
예제 #17
0
def _get_quad_slip_ds_ss(q, rake, cp, p):
    """
    Compute the DIP SLIP and STRIKE SLIP components of the unit slip vector in
    ECEF coords for a quad and rake angle.
    :param q:
        A quadrilateral.
    :param rake:
        Direction of motion of the hanging wall relative to the
        foot wall, as measured by the angle (deg) from the strike vector.
    :param cp:
        A 3x(n sub rupture) array giving center points of each sub rupture
        in ECEF coords.
    :param p:
        A 3x(n sub rupture) array giving the unit vectors of the propagation
        vector on each sub rupture in ECEF coords.
    :returns:
        List of dip slip and strike slip components (each is a matrix)
        of the unit slip vector in ECEF space.
    """
    # Get quad vertices, strike, dip
    P0, P1 = q[0:2]
    strike = P0.azimuth(P1)
    dip = utils.get_quad_dip(q)

    # Slip unit vectors in 'local' (i.e., z-up, x-east) coordinates
    d1_local = utils.get_local_unit_slip_vector_DS(strike, dip, rake)
    s1_local = utils.get_local_unit_slip_vector_SS(strike, dip, rake)

    # Convert to a column array
    d1_col = np.array([[d1_local.x], [d1_local.y], [d1_local.z]])
    s1_col = np.array([[s1_local.x], [s1_local.y], [s1_local.z]])

    # Define 'local' coordinate system
    qlats = [a.latitude for a in q]
    qlons = [a.longitude for a in q]
    proj = OrthographicProjection(np.min(qlons), np.max(qlons), np.min(qlats),
                                  np.max(qlats))

    # Convert p and cp to geographic coords
    p0lat, p0lon, p0z = ecef2latlon(cp[0, ], cp[1, ], cp[2, ])
    p1lat, p1lon, p1z = ecef2latlon(cp[0, ] + p[0, ], cp[1, ] + p[1, ],
                                    cp[2, ] + p[2, ])

    # Convert p to 'local' coords
    p0x, p0y = proj(p0lon, p0lat)
    p1x, p1y = proj(p1lon, p1lat)
    px = p1x - p0x
    py = p1y - p0y
    pz = p1z - p0z

    # Apply sign changes in 'local' coords
    s1mat = np.array([[np.abs(s1_col[0]) * np.sign(px)],
                      [np.abs(s1_col[1]) * np.sign(py)],
                      [np.abs(s1_col[2]) * np.sign(pz)]])
    #                      [np.abs(s1_col[2])*np.ones_like(pz)]])

    dipsign = -np.sign(np.sin(np.radians(rake)))
    d1mat = np.array([[d1_col[0] * np.ones_like(px) * dipsign],
                      [d1_col[1] * np.ones_like(py) * dipsign],
                      [d1_col[2] * np.ones_like(pz) * dipsign]])

    # Need to track 'origin'
    s0 = np.array([[0], [0], [0]])

    # Convert from 'local' to geographic coords
    s1_ll = proj(s1mat[0, ], s1mat[1, ], reverse=True)
    d1_ll = proj(d1mat[0, ], d1mat[1, ], reverse=True)
    s0_ll = proj(s0[0], s0[1], reverse=True)

    # And then back to ECEF:
    s1_ecef = latlon2ecef(s1_ll[1], s1_ll[0], s1mat[2, ])
    d1_ecef = latlon2ecef(d1_ll[1], d1_ll[0], d1mat[2, ])
    s0_ecef = latlon2ecef(s0_ll[1], s0_ll[0], s0[2])
    s00 = s0_ecef[0].reshape(-1)
    s01 = s0_ecef[1].reshape(-1)
    s02 = s0_ecef[2].reshape(-1)
    d_mat = np.array([
        d1_ecef[0].reshape(-1) - s00, d1_ecef[1].reshape(-1) - s01,
        d1_ecef[2].reshape(-1) - s02
    ])
    s_mat = np.array([
        s1_ecef[0].reshape(-1) - s00, s1_ecef[1].reshape(-1) - s01,
        s1_ecef[2].reshape(-1) - s02
    ])
    return d_mat, s_mat
예제 #18
0
def test_san_fernando():
    # This is a challenging rupture due to overlapping and discordant
    # segments, as brought up by Graeme Weatherill. Our initial
    # implementation put the origin on the wrong side of the rupture.
    x0 = np.array([7.1845, 7.8693])
    y0 = np.array([-10.3793, -16.2096])
    z0 = np.array([3.0000, 0.0000])
    x1 = np.array([-7.8506, -7.5856])
    y1 = np.array([-4.9073, -12.0682])
    z1 = np.array([3.0000, 0.0000])
    x2 = np.array([-4.6129, -5.5149])
    y2 = np.array([3.9887, -4.3408])
    z2 = np.array([16.0300, 8.0000])
    x3 = np.array([10.4222, 9.9400])
    y3 = np.array([-1.4833, -8.4823])
    z3 = np.array([16.0300, 8.0000])

    epilat = 34.44000
    epilon = -118.41000
    proj = OrthographicProjection(epilon - 1, epilon + 1, epilat + 1,
                                  epilat - 1)
    lon0, lat0 = proj(x0, y0, reverse=True)
    lon1, lat1 = proj(x1, y1, reverse=True)
    lon2, lat2 = proj(x2, y2, reverse=True)
    lon3, lat3 = proj(x3, y3, reverse=True)

    # Rupture requires an origin even when not used:
    origin = Origin({
        'id': 'test',
        'lat': 0,
        'lon': 0,
        'depth': 5.0,
        'mag': 7.0,
        'netid': '',
        'network': '',
        'locstring': '',
        'time': HistoricTime.utcfromtimestamp(int(time.time()))
    })

    rup = QuadRupture.fromVertices(lon0, lat0, z0, lon1, lat1, z1, lon2, lat2,
                                   z2, lon3, lat3, z3, origin)
    # Make a origin object; most of the 'event' values don't matter
    event = {
        'lat': 0,
        'lon': 0,
        'depth': 0,
        'mag': 6.61,
        'id': '',
        'locstring': '',
        'type': 'ALL',
        'netid': '',
        'network': '',
        'time': HistoricTime.utcfromtimestamp(int(time.time()))
    }
    origin = Origin(event)

    # Grid of sites
    buf = 0.25
    lat = np.linspace(np.nanmin(rup._lat) - buf, np.nanmax(rup._lat) + buf, 10)
    lon = np.linspace(np.nanmin(rup._lon) - buf, np.nanmax(rup._lon) + buf, 10)
    lons, lats = np.meshgrid(lon, lat)
    dep = np.zeros_like(lons)
    x, y = proj(lon, lat)
    rupx, rupy = proj(rup._lon[~np.isnan(rup._lon)],
                      rup._lat[~np.isnan(rup._lat)])

    # Calculate U and T
    dtypes = ['U', 'T']
    dists = get_distance(dtypes, lats, lons, dep, rup)

    targetU = np.array(
        [[
            29.37395812, 22.56039569, 15.74545461, 8.92543078, 2.09723735,
            -4.73938823, -11.58093887, -18.42177264, -25.25743913, -32.08635501
        ],
         [
             31.84149137, 25.03129417, 18.22007124, 11.40292429, 4.57583886,
             -2.26009972, -9.09790123, -15.92911065, -22.75071243, -29.56450963
         ],
         [
             34.30623138, 27.49382948, 20.67774678, 13.85111535, 7.0115472,
             0.16942111, -6.65327488, -13.45181115, -20.24352643, -27.03530618
         ],
         [
             36.78170249, 29.96380633, 23.1270492, 16.23906653, 9.32934682,
             2.41729624, -4.2732657, -10.94940844, -17.703852, -24.4792072
         ],
         [
             39.29233805, 32.49155866, 25.68380903, 18.73823089, 12.08780156,
             5.99219619, -1.38387344, -8.28331275, -15.08759643, -21.87909368
         ],
         [
             41.84662959, 35.09745097, 28.42432401, 21.98993679, 15.2994003,
             8.38037254, 1.3900846, -5.5601922, -12.4250749, -19.24690137
         ],
         [
             44.41552101, 37.69652131, 31.0257236, 24.38573309, 17.67059825,
             10.84688716, 3.96604399, -2.920931, -9.78152208, -16.6132751
         ],
         [
             46.97201328, 40.2558351, 33.55821495, 26.85923974, 20.12416451,
             13.33640001, 6.50905851, -0.33349597, -7.17138975, -13.99568321
         ],
         [
             49.51154107, 42.79053584, 36.07536907, 29.35382731, 22.61099757,
             15.83894006, 9.04135415, 2.22928601, -4.58574545, -11.3959888
         ],
         [
             52.03832734, 45.31289877, 38.58842009, 31.85764151, 25.11309728,
             18.35066231, 11.57145669, 4.78070229, -2.01505508, -8.81029694
         ]])
    np.testing.assert_allclose(dists['U'], targetU, atol=0.01)

    targetT = np.array(
        [[
            -40.32654805, -38.14066537, -35.95781299, -33.79265063,
            -31.65892948, -29.56075203, -27.48748112, -25.41823592,
            -23.33452174, -21.22822801
        ],
         [
             -32.28894353, -30.06603457, -27.83163648, -25.61482279,
             -23.45367121, -21.36959238, -19.34738882, -17.33510593,
             -15.28949735, -13.20224592
         ],
         [
             -24.30254163, -22.03532096, -19.70590091, -17.35907062,
             -15.10840929, -13.02682541, -11.13554925, -9.25705749,
             -7.26675455, -5.19396824
         ],
         [
             -16.41306482, -14.1418547, -11.68888578, -8.9318195, -6.39939727,
             -4.10984325, -2.85061088, -1.29211846, 0.68929792, 2.78115216
         ],
         [
             -8.63784529, -6.5089946, -4.32108309, -1.44275161, -0.05102145,
             -0.20890633, 3.92700516, 6.36977183, 8.55572399, 10.72128633
         ],
         [
             -0.88135778, 1.06766314, 2.77955566, 3.8241835, 5.99212478,
             8.76823285, 11.54715599, 14.0961506, 16.4200502, 18.65346494
         ],
         [
             6.98140207, 8.91888936, 10.77724993, 12.6499521, 14.79454638,
             17.18482779, 19.63520498, 22.03525644, 24.35152986, 26.60592498
         ],
         [
             14.95635952, 16.95134069, 18.94768299, 20.99811237, 23.15975573,
             25.42700742, 27.74302905, 30.0547134, 32.33583361, 34.58421221
         ],
         [
             22.9921068, 25.0353212, 27.09829391, 29.20364631, 31.3678744,
             33.58684524, 35.8383652, 38.09736043, 40.34713771, 42.58152772
         ],
         [
             31.05186177, 33.1252095, 35.21960344, 37.34488267, 39.50633206,
             41.70076344, 43.91762786, 46.14415669, 48.37021739, 50.59029205
         ]])
    np.testing.assert_allclose(dists['T'], targetT, atol=0.01)

    # new method:
    ddict = _computeGC2(rup, lons, lats, dep)
    np.testing.assert_allclose(ddict['T'], targetT, atol=0.01)
    np.testing.assert_allclose(ddict['U'], targetU, atol=0.01)