def generate_normal_ss_data(avg_strike, avg_dip, n=10, noise_std=5, porp=2):
    """Generate test data: several conjugate normal and s/s faults with noisy
    strike/dip"""
    def append(*args):
        return np.hstack(args)

    def filter(strike, dip):
        """Ensure strike & dip are in the correct ranges"""
        strike[dip > 90] -= 180
        dip[dip > 90] = 180 - dip[dip > 90]

        strike[dip < 0] -= 180
        dip[dip < 0] *= -1

        strike[strike < 0] += 360
        strike[strike > 360] -= 360

        return strike, dip

    # Generate conjugate normal faults
    norm_strike = avg_strike * np.ones(n)
    norm_strike[n // porp:] = avg_strike + 180
    norm_dip = avg_dip * np.ones(n)

    # Generate strike slip faults @ +- 30 deg of normal strike
    ss_strike = (avg_strike - 30) * np.ones(n)
    ss_strike[n // porp:] = avg_strike + 30
    ss_dip = 90 * np.ones(n)

    # Add noise
    for item in [norm_strike, norm_dip, ss_strike, ss_dip]:
        item += noise_std * np.random.randn(item.size)

    norm_strike, norm_dip = filter(norm_strike, norm_dip)
    ss_strike, ss_dip = filter(ss_strike, ss_dip)

    # Calculate slip
    norm_normal = geometric_functions.plane2normal(norm_strike, norm_dip)
    norm_slip = geometric_functions.normal_slip(*norm_normal)

    ll_ss_normal = geometric_functions.plane2normal(ss_strike[n // 2:],
                                                    ss_dip[n // 2:])
    ll_ss_slip = geometric_functions.left_slip(*ll_ss_normal)

    rl_ss_normal = geometric_functions.plane2normal(ss_strike[:n - n // 2],
                                                    ss_dip[:n - n // 2])
    rl_ss_slip = geometric_functions.left_slip(*rl_ss_normal)

    strike, dip = append(norm_strike, ss_strike), append(norm_dip, ss_dip)
    normal = append(norm_normal, rl_ss_normal, ll_ss_normal)
    slip = append(norm_slip, rl_ss_slip, ll_ss_slip)
    return strike, dip, normal, slip
def generate_normal_ss_data(avg_strike, avg_dip, n=10, noise_std=5, porp=2):
    """Generate test data: several conjugate normal and s/s faults with noisy
    strike/dip"""
    def append(*args):
        return np.hstack(args)
    def filter(strike, dip):
        """Ensure strike & dip are in the correct ranges"""
        strike[dip > 90] -= 180
        dip[dip > 90] = 180 - dip[dip>90]

        strike[dip < 0] -= 180
        dip[dip < 0] *= -1

        strike[strike < 0] += 360
        strike[strike > 360] -= 360

        return strike, dip

    # Generate conjugate normal faults
    norm_strike = avg_strike * np.ones(n)
    norm_strike[n//porp:] = avg_strike + 180
    norm_dip = avg_dip * np.ones(n)

    # Generate strike slip faults @ +- 30 deg of normal strike
    ss_strike = (avg_strike - 30) * np.ones(n)
    ss_strike[n//porp:] = avg_strike + 30
    ss_dip = 90 * np.ones(n)

    # Add noise
    for item in [norm_strike, norm_dip, ss_strike, ss_dip]:
        item += noise_std * np.random.randn(item.size)

    norm_strike, norm_dip = filter(norm_strike, norm_dip)
    ss_strike, ss_dip = filter(ss_strike, ss_dip)

    # Calculate slip
    norm_normal = geometric_functions.plane2normal(norm_strike, norm_dip)
    norm_slip = geometric_functions.normal_slip(*norm_normal)

    ll_ss_normal = geometric_functions.plane2normal(ss_strike[n//2:], ss_dip[n//2:])
    ll_ss_slip = geometric_functions.left_slip(*ll_ss_normal)

    rl_ss_normal = geometric_functions.plane2normal(ss_strike[:n-n//2], ss_dip[:n-n//2])
    rl_ss_slip = geometric_functions.left_slip(*rl_ss_normal)

    strike, dip = append(norm_strike, ss_strike), append(norm_dip, ss_dip)
    normal = append(norm_normal, rl_ss_normal, ll_ss_normal)
    slip = append(norm_slip, rl_ss_slip, ll_ss_slip)
    return strike, dip, normal, slip
def generate_normal_data(avg_strike, avg_dip, n=10, noise_std=5, porp=2):
    """Generate several conjugate normal faults with noisy s/d"""
    opp_strike = avg_strike + 180
    if opp_strike > 360: 
        opp_strike -= 360
    strike = avg_strike * np.ones(n)
    strike[n//porp:] = opp_strike
    dip = avg_dip * np.ones(n)
    
    # Add noise
    strike += noise_std * np.random.randn(n)
    dip += noise_std * np.random.randn(n)

    # Filter out things out of a reasonable range
    strike[dip > 90] -= 180
    dip[dip > 90] = 180 - dip[dip>90]

    strike[dip < 0] -= 180
    dip[dip < 0] *= -1

    strike[strike < 0] += 360
    strike[strike > 360] -= 360
    

    normal = geometric_functions.plane2normal(strike, dip)
    slip = geometric_functions.normal_slip(*normal)

    return strike, dip, normal, slip
def generate_normal_data(avg_strike, avg_dip, n=10, noise_std=5, porp=2):
    """Generate several conjugate normal faults with noisy s/d"""
    opp_strike = avg_strike + 180
    if opp_strike > 360:
        opp_strike -= 360
    strike = avg_strike * np.ones(n)
    strike[n // porp:] = opp_strike
    dip = avg_dip * np.ones(n)

    # Add noise
    strike += noise_std * np.random.randn(n)
    dip += noise_std * np.random.randn(n)

    # Filter out things out of a reasonable range
    strike[dip > 90] -= 180
    dip[dip > 90] = 180 - dip[dip > 90]

    strike[dip < 0] -= 180
    dip[dip < 0] *= -1

    strike[strike < 0] += 360
    strike[strike > 360] -= 360

    normal = geometric_functions.plane2normal(strike, dip)
    slip = geometric_functions.normal_slip(*normal)

    return strike, dip, normal, slip
def test_slip():
    strike, dip = 90, 45
    x, y, z = geometric_functions.plane2normal(strike, dip)
    print 'Should be ~ [0, 1, -1]'
    print[item * np.sqrt(2) for item in [x, y, z]]
    print 'Should be 090/45 (s/d)', geometric_functions.normal2plane(x, y, z)
    print 'Normal slip should be ~ [0, -1, -1]'
    print[
        item * np.sqrt(2) for item in geometric_functions.normal_slip(x, y, z)
    ]
    print 'Reverse slip should be ~ [0, 1, 1]'
    print[
        item * np.sqrt(2)
        for item in geometric_functions.reverse_slip(x, y, z)
    ]

    print 'Now testing normal2plane'
    print 'Should be 090/45 (s/d)', geometric_functions.normal2plane(0, -1, -1)
    print 'Should be 45/180 (p/b)', geometric_functions.normal2plunge_bearing(
        0, -1, -1)
def test_slip():
    strike, dip = 90, 45
    x,y,z = geometric_functions.plane2normal(strike, dip)
    print 'Should be ~ [0, 1, -1]'
    print [item * np.sqrt(2) for item in [x,y,z]]