示例#1
0
def test_operators():
    d = _CoreTimeSeries(10)
    d1 = make_constant_data_ts(d, nsamp=10)
    dsave = _CoreTimeSeries(d1)
    d = _CoreTimeSeries(6)
    d2 = make_constant_data_ts(d, t0=-0.2, nsamp=6, val=2.0)
    dsave = _CoreTimeSeries(d1)
    d1 += d2
    assert np.allclose(d1.data, [3, 3, 3, 3, 1, 1, 1, 1, 1, 1])
    d1 = _CoreTimeSeries(dsave)
    d = d1 + d2
    assert np.allclose(d.data, [3, 3, 3, 3, 1, 1, 1, 1, 1, 1])
    d1 = _CoreTimeSeries(dsave)
    d1 *= 2.5
    assert np.allclose(d1.data,
                       [2.5, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5])
    d3 = TimeSeries(10)
    d4 = TimeSeries(6)
    d3 = make_constant_data_ts(d3, nsamp=10)
    d4 = make_constant_data_ts(d4, t0=-0.2, nsamp=6, val=2.0)
    dsave = _CoreTimeSeries(d3)
    d3 = TimeSeries(dsave)
    d3 += d4
    assert np.allclose(d3.data, [3, 3, 3, 3, 1, 1, 1, 1, 1, 1])
    d3 = TimeSeries(dsave)
    d = d3 + d4
    assert np.allclose(d.data, [3, 3, 3, 3, 1, 1, 1, 1, 1, 1])
    d1 = _CoreTimeSeries(dsave)
    d3 = TimeSeries(dsave)
    d3 *= 2.5
    assert np.allclose(d3.data,
                       [2.5, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5])
    x = np.linspace(-0.7, 1.2, 20)
    for t in x:
        d3 = TimeSeries(dsave)
        d4.t0 = t
        d3 += d4
    # These are selected asserts of the incremental test above
    # visually d4 moves through d3 as the t0 value advance. Assert
    # tests end member: skewed left, inside, and skewed right
    d3 = TimeSeries(dsave)
    d4.t0 = -0.7  # no overlap test
    d3 += d4
    assert np.allclose(d3.data, [1, 1, 1, 1, 1, 1, 1, 1, 1, 1])
    d3 = TimeSeries(dsave)
    d4.t0 = -0.3  # overlap left
    d3 += d4
    assert np.allclose(d3.data, [3, 3, 3, 1, 1, 1, 1, 1, 1, 1])
    d3 = TimeSeries(dsave)
    d4.t0 = 0.3  # d4 inside d3 test
    d3 += d4
    assert np.allclose(d3.data, [1, 1, 1, 3, 3, 3, 3, 3, 3, 1])
    d3 = TimeSeries(dsave)
    d4.t0 = 0.7  # partial overlap right
    d3 += d4
    assert np.allclose(d3.data, [1, 1, 1, 1, 1, 1, 1, 3, 3, 3])
    d3 = TimeSeries(dsave)
    d4.t0 = 1.0  # no overlap test right
    d3 += d4
    assert np.allclose(d3.data, [1, 1, 1, 1, 1, 1, 1, 1, 1, 1])
    # Repeat the same test for Seismogram objects
    # This section is edited cut-paste of above
    # Intentionally do not test _CoreSeismogram directly because
    # currently if it works for Seismogram it will for _CoreSeismogram

    d = _CoreSeismogram(10)
    d1 = make_constant_data_seis(d, nsamp=10)
    dsave = _CoreSeismogram(d1)
    d = _CoreSeismogram(6)
    d2 = make_constant_data_seis(d, t0=-0.2, nsamp=6, val=2.0)
    dsave = _CoreSeismogram(d1)
    d1 += d2
    assert np.allclose(
        d1.data,
        np.array([
            [3.0, 3.0, 3.0, 3.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0],
            [3.0, 3.0, 3.0, 3.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0],
            [3.0, 3.0, 3.0, 3.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0],
        ]),
    )
    d1 = _CoreSeismogram(dsave)
    d = d1 + d2
    assert np.allclose(
        d.data,
        np.array([
            [3.0, 3.0, 3.0, 3.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0],
            [3.0, 3.0, 3.0, 3.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0],
            [3.0, 3.0, 3.0, 3.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0],
        ]),
    )
    d1 = _CoreSeismogram(dsave)
    d1 *= 2.5
    assert np.allclose(
        d1.data,
        np.array([
            [2.5, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5],
            [2.5, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5],
            [2.5, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5],
        ]),
    )
    d3 = Seismogram(10)
    d4 = Seismogram(6)
    d3 = make_constant_data_seis(d3, nsamp=10)
    d4 = make_constant_data_seis(d4, t0=-0.2, nsamp=6, val=2.0)
    dsave = Seismogram(d3)
    d3 += d4
    assert np.allclose(
        d3.data,
        np.array([
            [3.0, 3.0, 3.0, 3.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0],
            [3.0, 3.0, 3.0, 3.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0],
            [3.0, 3.0, 3.0, 3.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0],
        ]),
    )
    d3 = Seismogram(dsave)
    d = d3 + d4
    assert np.allclose(
        d.data,
        np.array([
            [3.0, 3.0, 3.0, 3.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0],
            [3.0, 3.0, 3.0, 3.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0],
            [3.0, 3.0, 3.0, 3.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0],
        ]),
    )
    d3 = Seismogram(dsave)
    d3 *= 2.5
    assert np.allclose(
        d1.data,
        np.array([
            [2.5, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5],
            [2.5, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5],
            [2.5, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5],
        ]),
    )
    x = np.linspace(-0.7, 1.2, 20)
    for t in x:
        d3 = Seismogram(dsave)
        d4.t0 = t
        d3 += d4

    # These are selected asserts of the incremental test above
    # visually d4 moves through d3 as the t0 value advance. Assert
    # tests end member: skewed left, inside, and skewed right
    d3 = Seismogram(dsave)
    d4.t0 = -0.7  # no overlap test
    d3 += d4
    assert np.allclose(
        d3.data,
        np.array([
            [1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
            [1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
            [1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
        ]),
    )

    d3 = Seismogram(dsave)
    d4.t0 = -0.3  # overlap left
    d3 += d4
    assert np.allclose(
        d3.data,
        np.array([
            [3, 3, 3, 1, 1, 1, 1, 1, 1, 1],
            [3, 3, 3, 1, 1, 1, 1, 1, 1, 1],
            [3, 3, 3, 1, 1, 1, 1, 1, 1, 1],
        ]),
    )
    d3 = Seismogram(dsave)
    d4.t0 = 0.3  # d4 inside d3 test
    d3 += d4
    assert np.allclose(
        d3.data,
        np.array([
            [1, 1, 1, 3, 3, 3, 3, 3, 3, 1],
            [1, 1, 1, 3, 3, 3, 3, 3, 3, 1],
            [1, 1, 1, 3, 3, 3, 3, 3, 3, 1],
        ]),
    )
    d3 = Seismogram(dsave)
    d4.t0 = 0.7  # partial overlap right
    d3 += d4
    assert np.allclose(
        d3.data,
        np.array([
            [1, 1, 1, 1, 1, 1, 1, 3, 3, 3],
            [1, 1, 1, 1, 1, 1, 1, 3, 3, 3],
            [1, 1, 1, 1, 1, 1, 1, 3, 3, 3],
        ]),
    )
    d3 = Seismogram(dsave)
    d4.t0 = 1.0  # no overlap test right
    d3 += d4
    assert np.allclose(
        d3.data,
        np.array([
            [1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
            [1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
            [1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
        ]),
    )

    # Repeat exactly for - test but different numeric results
    # just omit *= tests
    d = _CoreTimeSeries(10)
    d1 = make_constant_data_ts(d, nsamp=10)
    dsave = _CoreTimeSeries(d1)
    d = _CoreTimeSeries(6)
    d2 = make_constant_data_ts(d, t0=-0.2, nsamp=6, val=2.0)
    dsave = _CoreTimeSeries(d1)
    d1 -= d2
    assert np.allclose(d1.data, [-1, -1, -1, -1, 1, 1, 1, 1, 1, 1])
    d1 = _CoreTimeSeries(dsave)
    d = d1 - d2
    assert np.allclose(d.data, [-1, -1, -1, -1, 1, 1, 1, 1, 1, 1])
    d3 = TimeSeries(10)
    d4 = TimeSeries(6)
    d3 = make_constant_data_ts(d3, nsamp=10)
    d4 = make_constant_data_ts(d4, t0=-0.2, nsamp=6, val=2.0)
    dsave = _CoreTimeSeries(d3)
    d3 = TimeSeries(dsave)
    d3 -= d4
    assert np.allclose(d3.data, [-1, -1, -1, -1, 1, 1, 1, 1, 1, 1])
    d3 = TimeSeries(dsave)
    d = d3 - d4
    assert np.allclose(d.data, [-1, -1, -1, -1, 1, 1, 1, 1, 1, 1])
    x = np.linspace(-0.7, 1.2, 20)
    for t in x:
        d3 = TimeSeries(dsave)
        d4.t0 = t
        d3 -= d4
    # These are selected asserts of the incremental test above
    # visually d4 moves through d3 as the t0 value advance. Assert
    # tests end member: skewed left, inside, and skewed right
    d3 = TimeSeries(dsave)
    d4.t0 = -0.7  # no overlap test
    d3 -= d4
    assert np.allclose(d3.data, [1, 1, 1, 1, 1, 1, 1, 1, 1, 1])
    d3 = TimeSeries(dsave)
    d4.t0 = -0.3  # overlap left
    d3 -= d4
    assert np.allclose(d3.data, [-1, -1, -1, 1, 1, 1, 1, 1, 1, 1])
    d3 = TimeSeries(dsave)
    d4.t0 = 0.3  # d4 inside d3 test
    d3 -= d4
    assert np.allclose(d3.data, [1, 1, 1, -1, -1, -1, -1, -1, -1, 1])
    d3 = TimeSeries(dsave)
    d4.t0 = 0.7  # partial overlap right
    d3 -= d4
    assert np.allclose(d3.data, [1, 1, 1, 1, 1, 1, 1, -1, -1, -1])
    d3 = TimeSeries(dsave)
    d4.t0 = 1.0  # no overlap test right
    d3 -= d4
    assert np.allclose(d3.data, [1, 1, 1, 1, 1, 1, 1, 1, 1, 1])

    # Repeat the same test for Seismogram objects
    # This section is edited cut-paste of above
    # Intentionally do not test _CoreSeismogram directly because
    # currently if it works for Seismogram it will for _CoreSeismogram
    d = _CoreSeismogram(10)
    d1 = make_constant_data_seis(d, nsamp=10)
    dsave = _CoreSeismogram(d1)
    d = _CoreSeismogram(6)
    d2 = make_constant_data_seis(d, t0=-0.2, nsamp=6, val=2.0)
    dsave = _CoreSeismogram(d1)
    d1 -= d2
    assert np.allclose(
        d1.data,
        np.array([
            [-1.0, -1.0, -1.0, -1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0],
            [-1.0, -1.0, -1.0, -1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0],
            [-1.0, -1.0, -1.0, -1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0],
        ]),
    )
    d1 = _CoreSeismogram(dsave)
    d = d1 - d2
    assert np.allclose(
        d.data,
        np.array([
            [-1.0, -1.0, -1.0, -1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0],
            [-1.0, -1.0, -1.0, -1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0],
            [-1.0, -1.0, -1.0, -1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0],
        ]),
    )

    d3 = Seismogram(10)
    d4 = Seismogram(6)
    d3 = make_constant_data_seis(d3, nsamp=10)
    d4 = make_constant_data_seis(d4, t0=-0.2, nsamp=6, val=2.0)
    dsave = Seismogram(d3)
    d3 -= d4
    assert np.allclose(
        d3.data,
        np.array([
            [-1.0, -1.0, -1.0, -1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0],
            [-1.0, -1.0, -1.0, -1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0],
            [-1.0, -1.0, -1.0, -1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0],
        ]),
    )
    d3 = Seismogram(dsave)
    d = d3 - d4
    assert np.allclose(
        d.data,
        np.array([
            [-1.0, -1.0, -1.0, -1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0],
            [-1.0, -1.0, -1.0, -1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0],
            [-1.0, -1.0, -1.0, -1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0],
        ]),
    )

    x = np.linspace(-0.7, 1.2, 20)
    for t in x:
        d3 = Seismogram(dsave)
        d4.t0 = t
        d3 -= d4

    # These are selected asserts of the incremental test above
    # visually d4 moves through d3 as the t0 value advance. Assert
    # tests end member: skewed left, inside, and skewed right
    d3 = Seismogram(dsave)
    d4.t0 = -0.7  # no overlap test
    d3 -= d4
    assert np.allclose(
        d3.data,
        np.array([
            [1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
            [1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
            [1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
        ]),
    )
    d3 = Seismogram(dsave)
    d4.t0 = -0.3  # overlap left
    d3 -= d4
    assert np.allclose(
        d3.data,
        np.array([
            [-1, -1, -1, 1, 1, 1, 1, 1, 1, 1],
            [-1, -1, -1, 1, 1, 1, 1, 1, 1, 1],
            [-1, -1, -1, 1, 1, 1, 1, 1, 1, 1],
        ]),
    )
    d3 = Seismogram(dsave)
    d4.t0 = 0.3  # d4 inside d3 test
    d3 -= d4
    assert np.allclose(
        d3.data,
        np.array([
            [1, 1, 1, -1, -1, -1, -1, -1, -1, 1],
            [1, 1, 1, -1, -1, -1, -1, -1, -1, 1],
            [1, 1, 1, -1, -1, -1, -1, -1, -1, 1],
        ]),
    )
    d3 = Seismogram(dsave)
    d4.t0 = 0.7  # partial overlap right
    d3 -= d4
    assert np.allclose(
        d3.data,
        np.array([
            [1, 1, 1, 1, 1, 1, 1, -1, -1, -1],
            [1, 1, 1, 1, 1, 1, 1, -1, -1, -1],
            [1, 1, 1, 1, 1, 1, 1, -1, -1, -1],
        ]),
    )
    d3 = Seismogram(dsave)
    d4.t0 = 1.0  # no overlap test right
    d3 -= d4
    assert np.allclose(
        d3.data,
        np.array([
            [1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
            [1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
            [1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
        ]),
    )
示例#2
0
def test_CoreSeismogram():
    md = Metadata()
    md["delta"] = 0.01
    md["starttime"] = 0.0
    md["npts"] = 100
    # test metadata constructor
    md["tmatrix"] = np.random.rand(3, 3)
    cseis = _CoreSeismogram(md, False)
    assert (cseis.tmatrix == md["tmatrix"]).all()
    md["tmatrix"] = dmatrix(np.random.rand(3, 3))
    cseis = _CoreSeismogram(md, False)
    assert (cseis.tmatrix == md["tmatrix"]).all()
    md["tmatrix"] = np.random.rand(9)
    cseis = _CoreSeismogram(md, False)
    assert (cseis.tmatrix == md["tmatrix"].reshape(3, 3)).all()
    md["tmatrix"] = np.random.rand(1, 9)
    cseis = _CoreSeismogram(md, False)
    assert (cseis.tmatrix == md["tmatrix"].reshape(3, 3)).all()
    md["tmatrix"] = np.random.rand(9, 1)
    cseis = _CoreSeismogram(md, False)
    assert (cseis.tmatrix == md["tmatrix"].reshape(3, 3)).all()

    md["tmatrix"] = np.random.rand(3, 3).tolist()
    cseis = _CoreSeismogram(md, False)
    assert np.isclose(cseis.tmatrix,
                      np.array(md["tmatrix"]).reshape(3, 3)).all()
    md["tmatrix"] = np.random.rand(9).tolist()
    cseis = _CoreSeismogram(md, False)
    assert np.isclose(cseis.tmatrix,
                      np.array(md["tmatrix"]).reshape(3, 3)).all()

    # test whether the setter of tmatrix updates metadata correctly
    tm = np.random.rand(1, 9)
    cseis.tmatrix = tm
    assert (cseis.tmatrix == tm.reshape(3, 3)).all()
    assert np.isclose(cseis.tmatrix,
                      np.array(cseis["tmatrix"]).reshape(3, 3)).all()
    tm = np.random.rand(9).tolist()
    cseis.tmatrix = tm
    assert np.isclose(cseis.tmatrix, np.array(tm).reshape(3, 3)).all()
    assert np.isclose(cseis.tmatrix,
                      np.array(cseis["tmatrix"]).reshape(3, 3)).all()

    # test exceptions
    md["tmatrix"] = np.random.rand(4, 2)
    with pytest.raises(MsPASSError, match="should be a 3x3 matrix"):
        _CoreSeismogram(md, False)
    md["tmatrix"] = dmatrix(np.random.rand(2, 4))
    with pytest.raises(MsPASSError, match="should be a 3x3 matrix"):
        _CoreSeismogram(md, False)
    md["tmatrix"] = 42
    with pytest.raises(MsPASSError, match="not recognized"):
        _CoreSeismogram(md, False)
    md.erase("tmatrix")
    # tmatrix not defined is taken to default to tmatrix being an identity
    # matrix.  We test that condition here
    cseis = _CoreSeismogram(md, False)
    assert np.isclose(cseis.tmatrix, np.eye(3)).all()
    md["tmatrix"] = {4: 2}
    with pytest.raises(MsPASSError, match="type is not recognized"):
        _CoreSeismogram(md, False)

    md["tmatrix"] = np.random.rand(9).tolist()
    md["tmatrix"][3] = "str"
    with pytest.raises(MsPASSError, match="should be float"):
        _CoreSeismogram(md, False)
    md["tmatrix"] = np.random.rand(3, 4).tolist()
    with pytest.raises(MsPASSError, match="should be a 3x3 list of list"):
        _CoreSeismogram(md, False)
    md["tmatrix"] = [1, 2, 3]
    with pytest.raises(MsPASSError, match="should be a 3x3 list of list"):
        _CoreSeismogram(md, False)
    md["tmatrix"] = np.random.rand(2, 2).tolist()
    with pytest.raises(
            MsPASSError,
            match="should be a list of 9 floats or a 3x3 list of list"):
        _CoreSeismogram(md, False)
    md["tmatrix"] = np.random.rand(3, 3).tolist()
    md["tmatrix"][1][1] = "str"
    with pytest.raises(MsPASSError, match="should be float"):
        _CoreSeismogram(md, False)
示例#3
0
def Stream2Seismogram(st,
                      master=0,
                      cardinal=False,
                      azimuth="azimuth",
                      dip="dip"):
    """
    Convert obspy Stream to a Seismogram.

    Convert an obspy Stream object with 3 components to a mspass::Seismogram
    (three-component data) object.  This implementation actually converts
    each component first to a TimeSeries and then calls a C++ function to
    assemble the complete Seismogram.   This has some inefficiencies, but
    the assumption is this function is called early on in a processing chain
    to build a raw data set.

    :param st: input obspy Stream object.  The object MUST have exactly 3 components
        or the function will throw a AssertionError exception.  The program is
        less dogmatic about start times and number of samples as these are
        handled by the C++ function this python script calls.  Be warned,
        however, that the C++ function can throw a MsPASSrror exception that
        should be handled separately.
    :param master: a Seismogram is an assembly of three channels composed created from
        three TimeSeries/Trace objects.   Each component may have different
        metadata (e.g. orientation data) and common metadata (e.g. station
        coordinates).   To assemble a Seismogram a decision has to be made on
        which component has the definitive common metadata.   We use a simple
        algorithm and clone the data from one component defined by this index.
        Must be 0,1, or 2 or the function wil throw a RuntimeError.  Default is 0.
    :param cardinal: boolean used to define one of two algorithms used to assemble the
        bundle.  When true the three input components are assumed to be in
        cardinal directions (x1=positive east, x2=positive north, and x3=positive up)
        AND in a fixed order of E,N,Z. Otherwise the Metadata fetched with
        the azimuth and dip keys are used for orientation.
    :param azimuth: defines the Metadata key used to fetch the azimuth angle
       used to define the orientation of each component Trace object.
       Default is 'azimuth' used by obspy.   Note azimuth=hang in css3.0.
       Cannot be aliased - must be present in obspy Stats unless cardinal is true
    :param dip:  defines the Metadata key used to fetch the vertical angle orientation
        of each data component.  Vertical angle (vang in css3.0) is exactly
        the same as theta in spherical coordinates.  Default is obspy 'dip'
        key. Cannot be aliased - must be defined in obspy Stats unless
        cardinal is true

    :raise: Can throw either an AssertionError or MsPASSrror(currently defaulted to
    pybind11's default RuntimeError.  Error message can be obtained by
    calling the what method of RuntimeError).
    """
    # First make sure we have exactly 3 components
    assert len(st) == 3, "Stream length must be EXACTLY 3 for 3-components"
    assert 0 <= master < 3, "master argument must be 0, 1, or 2"

    # if all traces are dead in a stream, it should be converted to a dead seismogram
    try:
        size = len(st)
        for i in range(len(st)):
            if st[i].dead_mspass:
                size -= 1
        if size == 0:
            res = Seismogram()
            res.live = False
            return res
    except AttributeError:
        pass

    # Complicated logic here, but the point is to make sure the azimuth
    # attribute is set. The cardinal part is to override the test if
    # we can assume he components are ENZ
    if not cardinal:
        if (azimuth not in st[0].stats or azimuth not in st[1].stats
                or azimuth not in st[2].stats):
            raise RuntimeError("Stream2Seismogram:  Required attribute " +
                               azimuth + " must be in mdother list")
    if not cardinal:
        if dip not in st[0].stats or dip not in st[1].stats or dip not in st[
                2].stats:
            raise RuntimeError("Stream2Seismogram:  Required attribute " +
                               dip + " must be in mdother list")
    # Outer exception handler to handle range of possible errors in
    # converting each component.  Note we pass an empty list for mdother
    # and aliases except the master
    bundle = []
    for i in range(3):
        bundle.append(Trace2TimeSeries(st[i]))
    # The constructor we use below has frozen names hang for azimuth and
    # vang for what obspy calls dip.   Copy to those names - should work
    # even if the hang and vang are the names although with some inefficiency
    # assume that would not be normal so avoid unnecessary code
    if cardinal:
        bundle[0].put(Keywords.channel_hang, 90.0)
        bundle[1].put(Keywords.channel_hang, 0.0)
        bundle[2].put(Keywords.channel_hang, 0.0)
        bundle[0].put(Keywords.channel_vang, 90.0)
        bundle[1].put(Keywords.channel_vang, 90.0)
        bundle[2].put(Keywords.channel_vang, 0.0)
    else:
        for i in range(3):
            hang = bundle[i].get_double(azimuth)
            bundle[i].put(Keywords.channel_hang, hang)
            vang = bundle[i].get_double(dip)
            bundle[i].put(Keywords.channel_vang, vang)
    # Assume now bundle contains all the pieces we need.   This constructor
    # for _CoreSeismogram should then do the job
    # This may throw an exception, but we require the caller to handle it
    # All errors returned by this constructor currenlty leave the data INVALID
    # so handler should discard anything with an error
    dout = _CoreSeismogram(bundle, master)
    res = Seismogram(dout, "INVALID")
    res.live = True
    return res
示例#4
0
def test_CoreSeismogram():
    md = Metadata()
    md['delta'] = 0.01
    md['starttime'] = 0.0
    md['npts'] = 100
    # test metadata constructor
    md['tmatrix'] = np.random.rand(3, 3)
    cseis = _CoreSeismogram(md, False)
    assert (cseis.transformation_matrix == md['tmatrix']).all()
    md['tmatrix'] = dmatrix(np.random.rand(3, 3))
    cseis = _CoreSeismogram(md, False)
    assert (cseis.transformation_matrix == md['tmatrix']).all()
    md['tmatrix'] = np.random.rand(9)
    cseis = _CoreSeismogram(md, False)
    assert (cseis.transformation_matrix == md['tmatrix'].reshape(3, 3)).all()
    md['tmatrix'] = np.random.rand(1, 9)
    cseis = _CoreSeismogram(md, False)
    assert (cseis.transformation_matrix == md['tmatrix'].reshape(3, 3)).all()
    md['tmatrix'] = np.random.rand(9, 1)
    cseis = _CoreSeismogram(md, False)
    assert (cseis.transformation_matrix == md['tmatrix'].reshape(3, 3)).all()

    md['tmatrix'] = np.random.rand(3, 3).tolist()
    cseis = _CoreSeismogram(md, False)
    assert np.isclose(cseis.transformation_matrix,
                      np.array(md['tmatrix']).reshape(3, 3)).all()
    md['tmatrix'] = np.random.rand(9).tolist()
    cseis = _CoreSeismogram(md, False)
    assert np.isclose(cseis.transformation_matrix,
                      np.array(md['tmatrix']).reshape(3, 3)).all()

    # test whether the setter of transformation_matrix updates metadata correctly
    tm = np.random.rand(1, 9)
    cseis.transformation_matrix = tm
    assert (cseis.transformation_matrix == tm.reshape(3, 3)).all()
    assert np.isclose(cseis.transformation_matrix,
                      np.array(cseis['tmatrix']).reshape(3, 3)).all()
    tm = np.random.rand(9).tolist()
    cseis.transformation_matrix = tm
    assert np.isclose(cseis.transformation_matrix,
                      np.array(tm).reshape(3, 3)).all()
    assert np.isclose(cseis.transformation_matrix,
                      np.array(cseis['tmatrix']).reshape(3, 3)).all()

    # test exceptions
    md['tmatrix'] = np.random.rand(4, 2)
    with pytest.raises(MsPASSError, match="should be a 3x3 matrix"):
        _CoreSeismogram(md, False)
    md['tmatrix'] = dmatrix(np.random.rand(2, 4))
    with pytest.raises(MsPASSError, match="should be a 3x3 matrix"):
        _CoreSeismogram(md, False)
    md['tmatrix'] = 42
    with pytest.raises(MsPASSError, match="not recognized"):
        _CoreSeismogram(md, False)
    md.erase('tmatrix')
    with pytest.raises(MsPASSError, match="Error trying to extract"):
        _CoreSeismogram(md, False)
    md['tmatrix'] = {4: 2}
    with pytest.raises(MsPASSError, match="type is not recognized"):
        _CoreSeismogram(md, False)

    md['tmatrix'] = np.random.rand(9).tolist()
    md['tmatrix'][3] = 'str'
    with pytest.raises(MsPASSError, match="should be float"):
        _CoreSeismogram(md, False)
    md['tmatrix'] = np.random.rand(3, 4).tolist()
    with pytest.raises(MsPASSError, match="should be a 3x3 list of list"):
        _CoreSeismogram(md, False)
    md['tmatrix'] = [1, 2, 3]
    with pytest.raises(MsPASSError, match="should be a 3x3 list of list"):
        _CoreSeismogram(md, False)
    md['tmatrix'] = np.random.rand(2, 2).tolist()
    with pytest.raises(
            MsPASSError,
            match="should be a list of 9 floats or a 3x3 list of list"):
        _CoreSeismogram(md, False)
    md['tmatrix'] = np.random.rand(3, 3).tolist()
    md['tmatrix'][1][1] = 'str'
    with pytest.raises(MsPASSError, match="should be float"):
        _CoreSeismogram(md, False)
示例#5
0
def test_scale():
    dts=_CoreTimeSeries(9)
    dir=setbasics(dts,9)
    d3c=_CoreSeismogram(5)
    setbasics(d3c,5)
    dts.data[0]=3.0
    dts.data[1]=2.0
    dts.data[2]=-4.0
    dts.data[3]=1.0
    dts.data[4]=-100.0
    dts.data[5]=-1.0
    dts.data[6]=5.0
    dts.data[7]=1.0
    dts.data[8]=-6.0
    # MAD o=f above should be 2
    # perf of 0.8 should be 4
    # rms should be just over 10=10.010993957
    print('Starting tests for time series data of amplitude functions')
    ampmad=MADAmplitude(dts)
    print('MAD amplitude estimate=',ampmad)
    assert(ampmad==3.0)
    amprms=RMSAmplitude(dts)
    print('RMS amplitude estimate=',amprms)
    assert(round(amprms,2)==100.46)
    amppeak=PeakAmplitude(dts)
    ampperf80=PerfAmplitude(dts,0.8)
    print('Peak amplitude=',amppeak)
    print('80% clip level amplitude=',ampperf80)
    assert(amppeak==100.0)
    assert(ampperf80==6.0)
    print('Starting comparable tests for 3c data')
    d3c.data[0,0]=3.0
    d3c.data[0,1]=2.0
    d3c.data[1,2]=-4.0
    d3c.data[2,3]=1.0
    d3c.data[0,4]=np.sqrt(2)*(100.0)
    d3c.data[1,4]=-np.sqrt(2)*(100.0)
    ampmad=MADAmplitude(d3c)
    print('MAD amplitude estimate=',ampmad)
    amprms=RMSAmplitude(d3c)
    print('RMS amplitude estimate=',amprms)
    amppeak=PeakAmplitude(d3c)
    ampperf60=PerfAmplitude(d3c,0.6)
    print('Peak amplitude=',amppeak)
    print('60% clip level amplitude=',ampperf60)
    assert(amppeak==200.0)
    assert(ampperf60==4.0)
    assert(ampmad==3.0)
    amptest=round(amprms,2)
    assert(amptest==89.48)
    print('Trying scaling functions for TimeSeries')
    # we need a deep copy here since scaling changes the data
    d2=TimeSeries(dts)
    amp=_scale(d2,ScalingMethod.Peak,1.0)
    print('Computed peak amplitude=',amp)
    print(d2.data)
    d2=TimeSeries(dts)
    amp=_scale(d2,ScalingMethod.Peak,10.0)
    print('Computed peak amplitude with peak set to 10=',amp)
    print(d2.data)
    assert(amp==100.0)
    assert(d2.data[4]==-10.0)
    print('verifying scale has modified and set calib correctly')
    calib=d2.get_double('calib')
    assert(calib==10.0)
    d2=TimeSeries(dts)
    d2.put('calib',6.0)
    print('test 2 with MAD metric and initial calib of 6')
    amp=_scale(d2,ScalingMethod.MAD,1.0)
    calib=d2.get_double('calib')
    print('New calib value set=',calib)
    assert(calib==18.0)
    print('Testing 3C scale functions')
    d=Seismogram(d3c)
    amp=_scale(d,ScalingMethod.Peak,1.0)
    print('Peak amplitude returned by scale funtion=',amp)
    calib=d.get_double('calib')
    print('Calib value retrieved (assumed inital 1.0)=',calib)
    print('Testing python scale function wrapper - first on a TimeSeries with defaults')
    d2=TimeSeries(dts)
    amp=scale(d2)
    print('peak amplitude returned =',amp[0])
    assert(amp[0]==100.0)
    d=Seismogram(d3c)
    amp=scale(d)
    print('peak amplitude returned test Seismogram=',amp[0])
    assert(amp[0]==200.0)
    print('starting tests of scale on ensembles')
    print('first test TimeSeriesEnemble with 5 scaled copies of same vector used earlier in this test')
    ens=TimeSeriesEnsemble()
    scls=[2.0,4.0,1.0,10.0,5.0]  # note 4 s the median of this vector
    npts=dts.npts
    for i in range(5):
        d=TimeSeries(dts)
        for k in range(npts):
            d.data[k]*=scls[i]
        d.put('calib',1.0)
        ens.member.append(d)

    # work on a copy because scaling alters data in place
    enscpy=TimeSeriesEnsemble(ens)
    amps=scale(enscpy)
    print('returned amplitudes for members scaled individually')
    for i in range(5):
        print(amps[i])
        assert(amps[i]==100.0*scls[i])
    enscpy=TimeSeriesEnsemble(ens)
    amp=scale(enscpy,scale_by_section=True)
    print('average amplitude=',amp[0])
    #assert(amp[0]==4.0)
    avgamp=amp[0]
    for i in range(5):
        calib=enscpy.member[i].get_double("calib")
        print('member number ',i,' calib is ',calib)
        assert(round(calib)==400.0)
        #print(enscpy.member[i].data)

    # similar test for SeismogramEnsemble
    npts=d3c.npts
    ens=SeismogramEnsemble()
    for i in range(5):
        d=Seismogram(d3c)
        for k in range(3):
            for j in range(npts):
                d.data[k,j]*=scls[i]
        d.put('calib',1.0)
        ens.member.append(d)
    print('Running comparable tests on SeismogramEnsemble')
    enscpy=SeismogramEnsemble(ens)
    amps=scale(enscpy)
    print('returned amplitudes for members scaled individually')
    for i in range(5):
        print(amps[i])
        assert(round(amps[i])==round(200.0*scls[i]))
    print('Trying section scaling of same data')
    enscpy=SeismogramEnsemble(ens)
    amp=scale(enscpy,scale_by_section=True)
    print('average amplitude=',amp[0])
    assert(round(amp[0])==800.0)
    avgamp=amp[0]
    for i in range(5):
        calib=enscpy.member[i].get_double("calib")
        print('member number ',i,' calib is ',calib)
        assert(round(calib)==800.0)