Beispiel #1
0
import obspy
import glob
import numpy as np
import matplotlib.pyplot as plt
import os

startDay = obspy.UTCDateTime("2012-01-01T00:00:00")
endDay = obspy.UTCDateTime("2014-01-01T00:00:00")
numDays = int((endDay - startDay) / 86400)
network = "PIG"
networkID = "XC"
stat = "PIG5"

pathSAC = "/home/setholinger/Data/" + network + "/" + stat + "/"
pathRESP = "/home/setholinger/Data/" + network + "/RESP/"

#create file with all days in time range
days = np.zeros(numDays)
for n in range(numDays):
    days[n] = startDay + n * 86400

# get list of all files in current directory
files = glob.glob(pathSAC + "*HHE.M.SAC")
files.sort()

#loop through all files
for i in range(np.size(files)):

    flag = 0

    #read in a day of data
Beispiel #2
0
    def test_reading_network_file(self):
        """
        Test reading a file at the network level.
        """
        # Manually create an expected Inventory object.
        expected_inv = Inventory(
            source=None,
            networks=[
                Network(
                    code="TA",
                    total_number_of_stations=1700,
                    start_date=obspy.UTCDateTime("2003-01-01T00:00:00"),
                    end_date=obspy.UTCDateTime("2500-12-31T23:59:59"),
                    description="USArray Transportable Array (NSF EarthScope "
                    "Project)"),
                Network(code="TC",
                        total_number_of_stations=0,
                        start_date=obspy.UTCDateTime("2011-01-01T00:00:00"),
                        end_date=obspy.UTCDateTime("2500-12-31T23:59:59"),
                        description="Red Sismologica Nacional")
            ])

        # Read from a filename.
        filename = os.path.join(self.data_dir, "network_level_fdsn.txt")
        inv = read_fdsn_station_text_file(filename)
        inv_obs = obspy.read_inventory(filename)

        # Copy creation date as it will be slightly different otherwise.
        inv.created = expected_inv.created
        inv_obs.created = expected_inv.created
        self.assertEqual(inv, expected_inv)
        self.assertEqual(inv_obs, expected_inv)

        # Read from open file in text mode.
        with open(filename, "rt", encoding="utf8") as fh:
            inv = read_fdsn_station_text_file(fh)
            fh.seek(0, 0)
            inv_obs = obspy.read_inventory(fh)
        inv.created = expected_inv.created
        inv_obs.created = expected_inv.created
        self.assertEqual(inv, expected_inv)
        self.assertEqual(inv_obs, expected_inv)

        # Read from open file in binary mode.
        with open(filename, "rb") as fh:
            inv = read_fdsn_station_text_file(fh)
            fh.seek(0, 0)
            inv_obs = obspy.read_inventory(fh)
        inv.created = expected_inv.created
        inv_obs.created = expected_inv.created
        self.assertEqual(inv, expected_inv)
        self.assertEqual(inv_obs, expected_inv)

        # Read from StringIO.
        with open(filename, "rt", encoding="utf8") as fh:
            with io.StringIO(fh.read()) as buf:
                buf.seek(0, 0)
                inv = read_fdsn_station_text_file(buf)
                buf.seek(0, 0)
                inv_obs = obspy.read_inventory(buf)
        inv.created = expected_inv.created
        inv_obs.created = expected_inv.created
        self.assertEqual(inv, expected_inv)
        self.assertEqual(inv_obs, expected_inv)

        # Read from BytesIO.
        with open(filename, "rb") as fh:
            with io.BytesIO(fh.read()) as buf:
                buf.seek(0, 0)
                inv = read_fdsn_station_text_file(buf)
                buf.seek(0, 0)
                inv_obs = obspy.read_inventory(buf)
        inv.created = expected_inv.created
        inv_obs.created = expected_inv.created
        self.assertEqual(inv, expected_inv)
        self.assertEqual(inv_obs, expected_inv)
Beispiel #3
0
    def test_reading_channel_file(self):
        """
        Test reading a file at the channel level.
        """

        resp_1 = Response(
            instrument_sensitivity=InstrumentSensitivity(frequency=0.02,
                                                         input_units="M/S",
                                                         output_units=None,
                                                         value=4.88233E8))
        resp_2 = Response(
            instrument_sensitivity=InstrumentSensitivity(frequency=0.03,
                                                         input_units="M/S",
                                                         output_units=None,
                                                         value=4.98112E8))
        resp_3 = Response(
            instrument_sensitivity=InstrumentSensitivity(frequency=0.03,
                                                         input_units="M/S",
                                                         output_units=None,
                                                         value=6.27252E8))

        # Manually create an expected Inventory object.
        expected_inv = Inventory(
            source=None,
            networks=[
                Network(
                    code="AK",
                    stations=[
                        Station(
                            code="BAGL",
                            latitude=60.4896,
                            longitude=-142.0915,
                            elevation=1470,
                            channels=[
                                Channel(
                                    code="LHZ",
                                    location_code="",
                                    latitude=60.4896,
                                    longitude=-142.0915,
                                    elevation=1470,
                                    depth=0.0,
                                    azimuth=0.0,
                                    dip=-90.0,
                                    sample_rate=1.0,
                                    sensor=Equipment(
                                        type="Nanometrics Trillium 240 Sec "
                                        "Response sn 400 and a"),
                                    start_date=obspy.UTCDateTime(
                                        "2013-01-01T00:00:00"),
                                    end_date=obspy.UTCDateTime(
                                        "2599-12-31T23:59:59"),
                                    response=resp_1)
                            ]),
                        Station(
                            code="BWN",
                            latitude=64.1732,
                            longitude=-149.2991,
                            elevation=356.0,
                            channels=[
                                Channel(
                                    code="LHZ",
                                    location_code="",
                                    latitude=64.1732,
                                    longitude=-149.2991,
                                    elevation=356.0,
                                    depth=0.0,
                                    azimuth=0.0,
                                    dip=-90.0,
                                    sample_rate=1.0,
                                    sensor=Equipment(
                                        type="Nanometrics Trillium 240 Sec "
                                        "Response sn 400 and a"),
                                    start_date=obspy.UTCDateTime(
                                        "2010-07-23T00:00:00"),
                                    end_date=obspy.UTCDateTime(
                                        "2014-05-28T23:59:59"),
                                    response=resp_1),
                                Channel(
                                    code="LHZ",
                                    location_code="",
                                    latitude=64.1732,
                                    longitude=-149.2991,
                                    elevation=356.0,
                                    depth=1.5,
                                    azimuth=0.0,
                                    dip=-90.0,
                                    sample_rate=1.0,
                                    sensor=Equipment(
                                        type="Nanometrics Trillium 120 Sec "
                                        "Response/Quanterra 33"),
                                    start_date=obspy.UTCDateTime(
                                        "2014-08-01T00:00:00"),
                                    end_date=obspy.UTCDateTime(
                                        "2599-12-31T23:59:59"),
                                    response=resp_2)
                            ])
                    ]),
                Network(
                    code="AZ",
                    stations=[
                        Station(
                            code="BZN",
                            latitude=33.4915,
                            longitude=-116.667,
                            elevation=1301.0,
                            channels=[
                                Channel(
                                    code="LHZ",
                                    location_code="",
                                    latitude=33.4915,
                                    longitude=-116.667,
                                    elevation=1301.0,
                                    depth=0.0,
                                    azimuth=0.0,
                                    dip=-90.0,
                                    sample_rate=1.0,
                                    sensor=Equipment(
                                        type=
                                        "Streckeisen STS-2 G1/Quanterra 330 "
                                        "Linear Phase Be"),
                                    start_date=obspy.UTCDateTime(
                                        "2010-07-26T17:22:00"),
                                    end_date=obspy.UTCDateTime(
                                        "2013-07-15T21:22:23"),
                                    response=resp_3),
                                Channel(
                                    code="LHZ",
                                    location_code="",
                                    latitude=33.4915,
                                    longitude=-116.667,
                                    elevation=1301.0,
                                    depth=0.0,
                                    azimuth=0.0,
                                    dip=-90.0,
                                    sample_rate=1.0,
                                    sensor=Equipment(
                                        type=
                                        "Streckeisen STS-2 G1/Quanterra 330 "
                                        "Linear Phase Be"),
                                    start_date=obspy.UTCDateTime(
                                        "2013-07-15T21:22:23"),
                                    end_date=obspy.UTCDateTime(
                                        "2013-10-22T19:30:00"),
                                    response=resp_3),
                                Channel(
                                    code="LHZ",
                                    location_code="",
                                    latitude=33.4915,
                                    longitude=-116.667,
                                    elevation=1301.0,
                                    depth=0.0,
                                    azimuth=0.0,
                                    dip=-90.0,
                                    sample_rate=1.0,
                                    sensor=Equipment(
                                        type=
                                        "Streckeisen STS-2 G1/Quanterra 330 "
                                        "Linear Phase Be"),
                                    start_date=obspy.UTCDateTime(
                                        "2013-10-22T19:30:00"),
                                    end_date=obspy.UTCDateTime(
                                        "2599-12-31T23:59:59"),
                                    response=resp_3)
                            ])
                    ])
            ])

        # Read from a filename.
        filename = os.path.join(self.data_dir, "channel_level_fdsn.txt")
        inv = read_fdsn_station_text_file(filename)
        inv_obs = obspy.read_inventory(filename)

        # Copy creation date as it will be slightly different otherwise.
        inv.created = expected_inv.created
        inv_obs.created = expected_inv.created
        self.assertEqual(inv, expected_inv)
        self.assertEqual(inv_obs, expected_inv)

        # Read from open file in text mode.
        with open(filename, "rt", encoding="utf8") as fh:
            inv = read_fdsn_station_text_file(fh)
            fh.seek(0, 0)
            inv_obs = obspy.read_inventory(fh)
        inv.created = expected_inv.created
        inv_obs.created = expected_inv.created
        self.assertEqual(inv, expected_inv)
        self.assertEqual(inv_obs, expected_inv)

        # Read from open file in binary mode.
        with open(filename, "rb") as fh:
            inv = read_fdsn_station_text_file(fh)
            fh.seek(0, 0)
            inv_obs = obspy.read_inventory(fh)
        inv.created = expected_inv.created
        inv_obs.created = expected_inv.created
        self.assertEqual(inv, expected_inv)
        self.assertEqual(inv_obs, expected_inv)

        # Read from StringIO.
        with open(filename, "rt", encoding="utf8") as fh:
            with io.StringIO(fh.read()) as buf:
                buf.seek(0, 0)
                inv = read_fdsn_station_text_file(buf)
                buf.seek(0, 0)
                inv_obs = obspy.read_inventory(buf)
        inv.created = expected_inv.created
        inv_obs.created = expected_inv.created
        self.assertEqual(inv, expected_inv)
        self.assertEqual(inv_obs, expected_inv)

        # Read from BytesIO.
        with open(filename, "rb") as fh:
            with io.BytesIO(fh.read()) as buf:
                buf.seek(0, 0)
                inv = read_fdsn_station_text_file(buf)
                buf.seek(0, 0)
                inv_obs = obspy.read_inventory(buf)
        inv.created = expected_inv.created
        inv_obs.created = expected_inv.created
        self.assertEqual(inv, expected_inv)
        self.assertEqual(inv_obs, expected_inv)
Beispiel #4
0
    elif op == "-D":
        isdelete = True
    elif op == "-K":
        isstack = True
        stack_path = value
    else:
        Usage()
        sys.exit(1)

logging.basicConfig(filename=folder_lst + '.log', level=logging.INFO)
with open(folder_lst) as flst:
    for folder in flst.readlines():
        folder = folder.strip()
        print(folder)
        folder_name = folder.split()[0]
        reftime = obspy.UTCDateTime(folder.split()[1])
        nt = int(np.floor((cuttime2 - cuttime1) / dt))
        if istransf:
            print("\t1st transfering instromental reponse...")
            if dformat == "seed":
                transf(folder_name, suffix, dt, ch=ch)
            elif dformat == "hinet":
                transf_hinet(folder_name, suffix, dt, ch=ch)
            else:
                print("wrong option in \"-F\" argument...")
                sys.exit(1)
        print("\t2nd perwhiten...")
        ev_num = perwhiten(folder_name,
                           dt,
                           wlen,
                           cuttime1,
Beispiel #5
0
    def filter_waveforms(self, queries):
        """
        """
        wfs = []

        for wf in [_i for _i in self.list() if _i != "StationXML"]:
            # Location and channel codes.
            if queries["location"] or queries["channel"]:
                _, _, loc_code, cha_code = wf_name2seed_codes(wf)
                if queries["location"] is not None:
                    if queries["location"](loc_code) is False:
                        continue
                if queries["channel"] is not None:
                    if queries["channel"](cha_code) is False:
                        continue
            # Tag
            if queries["tag"]:
                tag = wf_name2tag(wf)
                if queries["tag"](tag) is False:
                    continue

            # Any of the other queries requires parsing the attribute path.
            if queries["starttime"] or queries["endtime"] or \
                    queries["sampling_rate"] or queries["npts"] or \
                    queries["event"] or queries["magnitude"] or \
                    queries["origin"] or queries["focal_mechanism"] or \
                    queries["labels"]:

                group = self.__hdf5_group
                try:
                    attrs = group[wf].attrs

                    if queries["sampling_rate"]:
                        if queries["sampling_rate"](attrs["sampling_rate"]) \
                                is False:
                            continue

                    if queries["npts"]:
                        if queries["npts"](len(group[wf])) is False:
                            continue

                    if queries["starttime"] or queries["endtime"]:
                        starttime = obspy.UTCDateTime(
                            float(attrs["starttime"]) / 1.0E9)
                        endtime = starttime + (len(group[wf]) - 1) * \
                            1.0 / float(attrs["sampling_rate"])

                        if queries["starttime"]:
                            if queries["starttime"](starttime) is False:
                                continue

                        if queries["endtime"]:
                            if queries["endtime"](endtime) is False:
                                continue

                    if queries["labels"]:
                        if "labels" in attrs:
                            labels = labelstring2list(attrs["labels"])
                        else:
                            labels = None
                        if queries["labels"](labels) is False:
                            continue

                    if queries["event"] or queries["magnitude"] or \
                            queries["origin"] or queries["focal_mechanism"]:
                        any_fails = False
                        for id in ["event", "origin", "magnitude",
                                   "focal_mechanism"]:
                            if queries[id]:
                                key = id + "_id"

                                # Defaults to an empty id.
                                if key in attrs:
                                    value = attrs[key].tostring().decode()
                                else:
                                    value = None

                                if queries[id](value) is False:
                                    any_fails = True
                                    break
                        if any_fails is True:
                            continue

                finally:
                    del group
            wfs.append(wf)

        return wfs
    def test_get_waveforms_bulk(self):
        # Some mock routing response.
        content = """
http://example1.com/fdsnws/station/1/query
AA B1 -- DD 2017-01-01T00:00:00 2017-01-02T00:10:00

http://example2.com/fdsnws/station/1/query
AA B2 -- DD 2017-01-01T00:00:00 2017-01-02T00:10:00
"""
        if hasattr(content, "encode"):
            content = content.encode()

        with mock.patch(self._cls + "._download") as p1, \
                mock.patch(self._cls + "._download_waveforms") as p2, \
                mock.patch(self._cls + ".get_stations_bulk") as p3:
            p1.return_value = _DummyResponse(content=content)
            p2.return_value = "1234"

            # For the underlying get_stations_bulk() call.
            _dummy_inv = mock.MagicMock()
            _dummy_inv.get_contents.return_value = {
                "channels": ["AA.BB.CC.DD", "AA.BB.CC.DD"]
            }
            p3.return_value = _dummy_inv

            st = self.client.get_waveforms_bulk([[
                "AA", "B*", "", "DD",
                obspy.UTCDateTime(2017, 1, 1),
                obspy.UTCDateTime(2017, 1, 2)
            ]],
                                                longestonly=True,
                                                minimumlength=2)
        self.assertEqual(st, "1234")

        self.assertEqual(p1.call_count, 1)
        self.assertEqual(p1.call_args[0][0],
                         "http://www.orfeus-eu.org/eidaws/routing/1/query")
        # This has been modified by our mocked call to get_stations_bulk().
        self.assertEqual(p1.call_args[1]["data"],
                         (b"service=dataselect\nformat=post\n"
                          b"AA BB CC DD 2017-01-01T00:00:00.000000 "
                          b"2017-01-02T00:00:00.000000"))

        # This is the final call to _download_waveforms() which is again
        # dependent on the dummy response to the _download() function.
        self.assertEqual(
            p2.call_args[0][0], {
                "http://example1.com":
                "AA B1 -- DD 2017-01-01T00:00:00 2017-01-02T00:10:00",
                "http://example2.com":
                "AA B2 -- DD 2017-01-01T00:00:00 2017-01-02T00:10:00"
            })
        self.assertEqual(p2.call_args[1], {
            "longestonly": True,
            "minimumlength": 2
        })

        # Call to this only dependent on the original bulk request.
        self.assertEqual(p3.call_count, 1)
        self.assertEqual(p3.call_args[0][0][0], [
            "AA", "B*", "--", "DD",
            str(obspy.UTCDateTime(2017, 1, 1))[:-1],
            str(obspy.UTCDateTime(2017, 1, 2))[:-1]
        ])
        # Everything should be passed on.
        self.assertEqual(
            p3.call_args[1], {
                "format": "text",
                "level": "channel",
                "longestonly": True,
                "minimumlength": 2
            })
Beispiel #7
0
                        freq2,
                        int(1 / dt),
                        corners=4,
                        zerophase=True)
        if norm_flag:
            tref = tref / np.max(np.abs(tref))

        # loop through each cur waveforms and do filtering
        igood = 0
        for ii in range(nwin):
            try:
                cur[igood] = ds.auxiliary_data[substacks[ii +
                                                         2]][ccomp].data[:]
            except Exception:
                continue
            timestamp[igood] = obspy.UTCDateTime(
                np.float(substacks[ii + 2][1:]))
            tcur[igood] = bandpass(cur[igood],
                                   freq1,
                                   freq2,
                                   int(1 / dt),
                                   corners=4,
                                   zerophase=True)
            if norm_flag:
                tcur[igood] /= np.max(np.abs(tcur[igood]))

            # get cc coeffient
            pcor_cc[igood] = np.corrcoef(tref[pwin_indx],
                                         tcur[igood, pwin_indx])[0, 1]
            ncor_cc[igood] = np.corrcoef(tref[nwin_indx],
                                         tcur[igood, nwin_indx])[0, 1]
            igood += 1
Beispiel #8
0
    def prepare_detection_stream(self, stream):
        ''' Prepare the data stream used for the detection run.

        Use the data in :attr:`stream` to compute self.detect_stream. 
        The :attr:`DelaunayDetector.detect_stream` contains at least the data of the 
        timespan with length :attr:`DelaunayDetector.window_length`. For computation, the data with the 
        length :attr:`DelaunayDetector.max_time_window` is prepended. So the passed data stream has 
        to contain a period of :attr:`DelaunayDetector.window_length` + :attr:`DelaunayDetector.max_time_window`, otherwise
        the detect stream will not be initialized.

        Parameters
        ----------
        stream: :class:`obspy.Stream`
            The stream containing the PGV that should be used for the detection.
        '''
        self.logger.debug("passed stream: %s", stream.__str__(extended=True))
        max_end_time = np.max([x.stats.endtime for x in stream])
        # Assume, that all traces have the same sampling rate.
        # TODO: Add a check to validate that the sampling rate of all traces is
        # the same.
        sps = stream[0].stats.sampling_rate
        if self.last_detection_end is None:
            detect_win_start = np.min([x.stats.starttime
                                       for x in stream]) + self.max_time_window
            #detect_win_start = np.max([x.stats.starttime for x in stream]) + self.max_time_window
        else:
            detect_win_start = self.last_detection_end + 1 / sps

        min_delta = np.min([x.stats.delta for x in stream])
        detect_win_end = (
            (max_end_time.timestamp + min_delta) -
            self.safety_time) // self.window_length * self.window_length
        detect_win_end = obspy.UTCDateTime(detect_win_end) - min_delta
        self.logger.debug("max_time_window: %s", self.max_time_window)
        self.logger.debug("detect_win_start: %s", detect_win_start)
        self.logger.debug("detect_win_end: %s", detect_win_end)

        if detect_win_end <= detect_win_start:
            self.logger.warning(
                "The detection window end is smaller than the detection window start. Skipping the preparation of the detection stream."
            )
            self.detect_stream = None
        elif (detect_win_end - detect_win_start) < (self.window_length -
                                                    1 / sps):
            self.logger.warning(
                "The length of the available data is smaller than the detection window length %f. Skipping the preparation of the detection stream.",
                (self.window_length - 1 / sps))
            self.detect_stream = None
        else:
            self.detect_stream = stream.slice(starttime=detect_win_start -
                                              self.max_time_window,
                                              endtime=detect_win_end,
                                              nearest_sample=False)
            self.logger.debug("detect_stream: %s",
                              self.detect_stream.__str__(extended=True))
            # Set the last detection end time.
            self.last_detection_start = detect_win_start
            self.last_detection_end = detect_win_end

            self.detect_stations = []
            self.unused_stations = []
            for cur_trace in self.detect_stream:
                cur_station = [
                    x for x in self.network_stations
                    if x.name == cur_trace.stats.station
                ]
                if cur_station:
                    self.detect_stations.append(cur_station[0])
            self.unused_stations = [
                x for x in self.network_stations
                if x not in self.detect_stations
            ]
Beispiel #9
0
# http://docs.obspy.org/archive/0.10.2/_modules/obspy/station/station.html#Station
inv = get_base_inventory()
NV = inv[0]
#Comment=obspy.station.util.Comment('This is a comment.')
#NV.comments.append(Comment)
description = """Broadband seismometer, current meter, and bottom pressure
    recorder installed close by ODP borehole 1026B, Cascadia Basin, eastern 
    flank of the Juan de Fuca Ridge."""

NC27 = obspy.station.Station('NC27',
                             latitude=47.7623,
                             longitude=-127.7579,
                             elevation=-2656.0,
                             vault='burried caisson',
                             geology='pelagic sediments',
                             creation_date=obspy.UTCDateTime('2009-09-14'),
                             termination_date=None,
                             description=description,
                             start_date=obspy.UTCDateTime('2009-09-14'),
                             end_date=None,
                             restricted_status='open')

NC27.site = obspy.station.util.Site(
    name='Cascadia Basin',
    description='NEPTUNE Observatory Cascadia Basin ' +
    'site near ODP borehole 1026B.',
    town=None,
    county=None,
    region='Northeast Pacific, off Vancouver Island',
    country='Canada')
#NC27.equipments.append(obspy.station.util.Equipment(...))
Beispiel #10
0
def path_to_utc(p):
    return obspy.UTCDateTime(*list(map(int, p.split(".")[1:])))
Beispiel #11
0
def _getPick(row, ph):
    pick = obspy.core.event.Pick()
    pick.time = obspy.UTCDateTime(ph.TimeStamp)
    pick.phase_hint = ph.Phase
    return pick
Beispiel #12
0
def keith2utc(row):
    return obspy.UTCDateTime((*list(map(int, cat2kstyle(row).split(".")))))
Beispiel #13
0
    def get_window_obspy(self, seis_traces, epi, depth, or_time, npts):
        tt_P = self.get_P(
            epi, depth
        )  # Estimated P-wave arrival, based on the known velocity model
        tt_S = self.get_S(
            epi, depth
        )  # Estimated S-wave arrival, based on the known velocity model
        sec_per_sample = 1 / (seis_traces[0].meta.sampling_rate)

        total_stream = Stream()
        s_stream = Stream()
        p_stream = Stream()

        p_time = or_time.timestamp + tt_P
        s_time = or_time.timestamp + tt_S
        start_time_p = obspy.UTCDateTime(
            p_time - 5)  # -10 , + 44.2 --> PAPER: STAHLER & SIGLOCH
        end_time_p = obspy.UTCDateTime(p_time + 20)
        start_time_s = obspy.UTCDateTime(s_time - 15)
        end_time_s = obspy.UTCDateTime(s_time + 35)

        for i, trace in enumerate(seis_traces.traces):
            P_trace = Trace.slice(trace, start_time_p, end_time_p)
            # P_trace.detrend(type='demean')
            S_trace = Trace.slice(trace, start_time_s, end_time_s)
            # S_trace.detrend(type='demean')
            stream_add = P_trace.__add__(S_trace,
                                         fill_value=0,
                                         sanity_checks=True)
            zero_trace = Trace(np.zeros(npts),
                               header={
                                   "starttime": start_time_p,
                                   'delta': trace.meta.delta,
                                   "station": trace.meta.station,
                                   "network": trace.meta.network,
                                   "location": trace.meta.location,
                                   "channel": trace.meta.channel
                               })
            if 'T' in trace.meta.channel:
                total_trace = zero_trace.__add__(S_trace,
                                                 method=0,
                                                 interpolation_samples=0,
                                                 fill_value=S_trace.data,
                                                 sanity_checks=True)
                total_s_trace = total_trace.copy()
            else:
                total_trace = zero_trace.__add__(stream_add,
                                                 method=0,
                                                 interpolation_samples=0,
                                                 fill_value=stream_add.data,
                                                 sanity_checks=True)
                total_s_trace = zero_trace.__add__(S_trace,
                                                   method=0,
                                                   interpolation_samples=0,
                                                   fill_value=S_trace.data,
                                                   sanity_checks=True)
                total_p_trace = zero_trace.__add__(P_trace,
                                                   method=0,
                                                   interpolation_samples=0,
                                                   fill_value=P_trace.data,
                                                   sanity_checks=True)
                p_stream.append(total_p_trace)
            s_stream.append(total_s_trace)
            total_stream.append(total_trace)
            s_stream = self.BW_filter(s_stream)
            p_stream = self.BW_filter(p_stream)
            total_stream = self.BW_filter(total_stream)
        return total_stream, p_stream, s_stream, start_time_p, start_time_s
Beispiel #14
0
    def _convert_parameters(self, model, **kwargs):
        model = model.strip().lower()
        if not model:
            raise ValueError("Model must be given.")

        params = {"model": model}

        # Error handling is mostly delegated to the actual Syngine service.
        # Here we just check that the types are compatible.
        str_arguments = [
            "network", "station", "networkcode", "stationcode", "locationcode",
            "eventid", "label", "components", "units", "format"
        ]
        float_arguments = [
            "receiverlatitude", "receiverlongitude", "sourcelatitude",
            "sourcelongitude", "sourcedepthinmeters", "scale", "dt"
        ]
        int_arguments = ["kernelwidth"]
        time_arguments = ["origintime"]

        for keys, t in ((str_arguments, native_str), (float_arguments, float),
                        (int_arguments, int), (time_arguments,
                                               obspy.UTCDateTime)):
            for key in keys:
                try:
                    value = kwargs[key]
                except KeyError:
                    continue
                if value is None:
                    continue
                value = t(value)
                # String arguments are stripped and empty strings are not
                # allowed.
                if t is native_str:
                    value = value.strip()
                    if not value:
                        raise ValueError("String argument '%s' must not be "
                                         "an empty string." % key)
                params[key] = t(value)

        # These can be absolute times, relative times or phase relative times.
        temporal_bounds = ["starttime", "endtime"]
        for key in temporal_bounds:
            try:
                value = kwargs[key]
            except KeyError:
                continue
            if value is None:
                continue
            # If a number, convert to a float.
            elif isinstance(value, (int, float)):
                value = float(value)
            # If a string like object, attempt to parse it to a datetime
            # object, otherwise assume it`s a phase-relative time and let the
            # Syngine service deal with the error handling.
            elif isinstance(value, (str, native_str)):
                try:
                    value = obspy.UTCDateTime(value)
                except Exception:
                    pass
            # Last but not least just try to pass it to the datetime
            # constructor without catching the error.
            else:
                value = obspy.UTCDateTime(value)
            params[key] = native_str(value)

        # These all have to be lists of floats. Otherwise it fails.
        source_mecs = [
            "sourcemomenttensor", "sourcedoublecouple", "sourceforce"
        ]
        for key in source_mecs:
            try:
                value = kwargs[key]
            except KeyError:
                continue
            if value is None:
                continue
            value = ",".join(["%g" % float(_i) for _i in value])
            params[key] = value

        return params
Beispiel #15
0
def _loadStream(fetcher,
                filt,
                trim,
                decimate,
                station,
                dtype,
                temkey,
                stakey,
                enforceOrigin=False,
                phases=None):
    """
    loads all traces into stream object and applies filters and trims
    """
    StreamDict = {}  # Initialize dictionary for stream objects
    channelDict = {}
    stats = {}
    STlens = {}
    trLen = []  # trace length
    allzeros = []  # empty list to stuff all zero keys to remove later
    csta = stakey[stakey.STATION == station.split('.')[1]]

    # load waveforms
    for st, evename in fetcher.getTemData(temkey,
                                          csta,
                                          trim[0],
                                          trim[1],
                                          returnName=True,
                                          phases=phases):

        st = _applyFilter(st, filt, decimate, dtype)
        if st is None or len(st) < 1:
            continue  # skip if stream empty
        tem = temkey[temkey.NAME == evename]
        if len(tem) < 1:  # in theory this should never happen
            msg = '%s not in template key, skipping'
            detex.log(__name__, msg, pri=True)
            continue
        originTime = obspy.UTCDateTime(tem.iloc[0].TIME)
        Nc = len(set([x.stats.channel for x in st]))  # get number of channels
        if Nc != len(st) or len(st) == 0:
            msg = ('%s on %s is fractured or channels are missing, consider '
                   'setting fillZeros to True in ClusterStream to try to '
                   'make it usable, skipping') % (evename, station)
            detex.log(__name__, msg, pri=True)
            continue
        if enforceOrigin:  # if the waveforms should start at the origin
            st.trim(starttime=originTime, pad=True, fill_value=0.0)
        StreamDict[evename] = st
        channelDict[evename] = [x.stats.channel for x in st]
        pros = st[0].stats['processing']
        sr = st[0].stats.sampling_rate
        start = st[0].stats.starttime.timestamp
        statsdi = {
            'processing': pros,
            'sampling_rate': sr,
            'starttime': start,
            'Nc': Nc
        }
        stats[evename] = statsdi  # put stats in dict
        totalLength = np.sum([len(x) for x in st])
        if any([not np.any(x.data) for x in st]):
            allzeros.append(evename)
        trLen.append(totalLength)
        STlens[evename] = totalLength

    mlen = np.median(trLen)
    keysToRemove = [x for x in StreamDict.keys() if STlens[x] < mlen * .2]
    for key in keysToRemove:  # Remove fractured or very short waveforms
        msg = '%s is fractured or missing data, removing' % key
        detex.log(__name__, msg, level='warning', pri=True)
        StreamDict.pop(key, None)
        channelDict.pop(key, None)
        stats.pop(key, None)

    for key in set(allzeros):  # remove waveforms with channels filled with 0s
        msg = '%s has at least one channel that is all zeros, deleting' % key
        detex.log(__name__, msg, level='warning', pri=True)
        StreamDict.pop(key, None)
        channelDict.pop(key, None)
        stats.pop(key, None)

    if len(StreamDict.keys()) < 2:
        msg = ('Less than 2 events survived preprocessing for station'
               '%s Check input parameters, especially trim' % station)
        detex.log(__name__, msg, level='warning', pri=True)
        return None, None, None, None
    evlist = StreamDict.keys()
    evlist.sort()
    # if 'IMU' in station:
    return StreamDict, evlist, channelDict, stats
Beispiel #16
0
def find_noise_long_period_spectral_level_through_time(mseed_archive_dir, starttime, endtime, inventory_fname=None, daily_sample_hr=12, secs_to_sample=0.7, comp_to_use='Z', stations_not_to_use=[], out_fname=''):
    """Function to find noise long period spectral level through time.
    Note that the sampling starts at 1 minute past the chosen hour.
    Note that events still could occur within the noise window. This function does not deal with this,
    so bare it in minde when analysing the data output.
    Arguments:
    Required:
    mseed_archive_dir - The path to the mseed archive dir containing continuous mseed data for the time period.
                        Note that currently archive must be in archive/year/julday/*<component (Z,N,E,1,2,etc)>.m
                        format. (str)
    starttime - The start time of the period to process data for. (obspy UTCDateTime object)
    endtime - The end time of the period to process data for. (obspy UTCDateTime object)
    Optional:
    inventory_fname - The inventory filename (.dataless) that contains the instrument response data for the 
                        network. Default is None. (str)
    daily_sample_hr - The hour of the day to sample the data for, in UTC time. Note that the sampling actually
                        starts at 1 minute past this hour. Default is 12. (int)
    secs_to_sample - The duration of the window to calculate the noise spectrum over, in seconds. Note that 
                    secs_to_sample should be the same length as that used for the magnitudes analysis for which
                    this data is being compared to (so that the frequency bins match). Default is 0.7 s.
                    (float)
    comp_to_use - Seismic trace component to use. Selects this component using the filename in the mseed archive.
                    Therefore, only use a component label that exists in the archive. Default is Z. (str)
    stations_not_to_use - A list of stations not to process. Default is []. (list of strs)
    out_fname - The filename of the file to save the data to (as a python dict). Note that if it is not specified
                (i.e. empty string) then it will not save data out. Default is not to save data out. (str)

    Returns:
    time_labels - List of datetime objects labelling each noise level measurement. (list of python datetime objects)
    noise_LP_spectral_levels - The long-period spectral level of the noise. Units of noise_LP_spectral_levels are
                             m / Hz. (np array of floats)
    (will also return python dict to out_fname if out_fname specified).
    
    """
    # Loop over days from starttime to endtime:
    num_days = int((endtime - starttime) / (3600 * 24))
    noise_LP_spectral_levels = []
    time_labels = []
    for day in np.arange(num_days):
        # Get noise sample start time:
        noise_sample_starttime_curr = starttime + (day * 3600 * 24)
        noise_sample_starttime_curr = obspy.UTCDateTime(year=noise_sample_starttime_curr.year, month=noise_sample_starttime_curr.month, day=noise_sample_starttime_curr.day, hour=daily_sample_hr, minute=1, second=0)

        # Get stream:
        mseed_filename = os.path.join(mseed_archive_dir, str(noise_sample_starttime_curr.year).zfill(4), str(noise_sample_starttime_curr.julday).zfill(3), "*"+comp_to_use+".m")
        st = obspy.core.Stream()
        for fname in glob.glob(mseed_filename):
            try:
                st_tmp = obspy.read(fname).detrend('demean').trim(starttime=noise_sample_starttime_curr-60., endtime=noise_sample_starttime_curr+9.*60.) # Note that takes 10 minute window around data interested in (so that can remove instrument response correctly)
            except TypeError:
                continue
            if len(st_tmp) > 0:
                if st_tmp[0].stats.station in stations_not_to_use:
                    continue # Skip reading this stream if the station should not be used
            for i in range(len(st_tmp)):
                try:
                    st.append(st_tmp[i])
                    del st_tmp
                    gc.collect()
                except UnboundLocalError:
                    continue      
        # And check if obtaind data:
        if len(st) == 0:
            print('Found no data for year: ', noise_sample_starttime_curr.year, ' day: ', noise_sample_starttime_curr.julday, 'Therefore skipping day.')
            continue

        # Remove instrument response:
        st_instrument_resp_removed = moment.remove_instrument_response(st, inventory_fname=inventory_fname)

        # And trim data again to exact window to use:
        st_instrument_resp_removed.trim(starttime=noise_sample_starttime_curr, endtime=noise_sample_starttime_curr+secs_to_sample)
        
        # Calculate noise spectrum:
        Sigma_0s_curr = []
        for tr in st_instrument_resp_removed:
            Sigma_0, f_c, t_star, Sigma_0_stdev, f_c_stdev, t_star_stdev = moment.get_displacement_spectra_coeffs(tr)
            Sigma_0s_curr.append(Sigma_0)
        av_Sigma_0_curr = np.average(np.array(Sigma_0s_curr))

        # And append to data stores:
        noise_LP_spectral_levels.append(av_Sigma_0_curr)
        time_labels.append(noise_sample_starttime_curr.datetime)
    
    # And do any final processing:
    noise_LP_spectral_levels = np.array(noise_LP_spectral_levels)

    # And save data to file, if specified:
    if len(out_fname) > 0:
        LP_noise_spect_level_outdict = {}
        LP_noise_spect_level_outdict['noise_LP_spectral_levels'] = noise_LP_spectral_levels
        LP_noise_spect_level_outdict['time_labels'] = time_labels
        outfile = open(out_fname, 'wb')
        pickle.dump(LP_noise_spect_level_outdict, outfile)
        outfile.close()

    return time_labels, noise_LP_spectral_levels



        
Beispiel #17
0
wf_train = []  #np.ndarray(shape=(61))
phase_train = []  #np.ndarray(shape=(1),dtype=np.int32)
for eq_file in files:
    if (eq_file != "IRISDMC"):
        data = ob.read(earthquake_folder + "/" + eq_file)
        data.interpolate(60)

        if (i >= num_samples):
            break
        for event in arrival_data:
            if event["station"] == data[0].stats["station"]:
                rand_num = random.uniform(0, time_window / 1.3)
                time_start = event["time"] - time_window + rand_num
                time_end = event["time"] + time_window + rand_num
                arrival = data.slice(
                    ob.UTCDateTime(event["time"] - time_window),
                    ob.UTCDateTime(event["time"] + time_window))
                phase_array = np.array([0, 0])
                normalized_time = (rand_num) / (2 * time_window) + 0.5

                if (event["phase"] == 'S'):
                    phase_array = np.array([1, normalized_time])
                if (event["phase"] == 'P'):
                    phase_array = np.array([2, normalized_time])

                try:
                    print(arrival[0].data.shape)
                except:
                    print("index out of range")
                    break
                if arrival[0].data.shape == (361, ):
Beispiel #18
0
dnet = ["YX"]  # network
dsta = ["*"]  # station (do either one station or *)
start_date = ["2017_03_01_0_0_0"]  # start date of download
end_date = ["2017_03_03_0_0_0"]  # end date of download
inc_hours = 24  # length of data for each request (in hour)

# get rough estimate of memory needs to ensure it now below up in S1
cc_len = 1800  # basic unit of data length for fft (s)
step = 450  # overlapping between each cc_len (s)
MAX_MEM = 5.0  # maximum memory allowed per core in GB

##################################################
# we expect no parameters need to be changed below

# time tags
starttime = obspy.UTCDateTime(start_date[0])
endtime = obspy.UTCDateTime(end_date[0])
if flag:
    print(
        'station.list selected [%s] for data from %s to %s with %sh interval' %
        (down_list, starttime, endtime, inc_hours))

# assemble parameters used for pre-processing
prepro_para = {'rm_resp':rm_resp,'respdir':respdir,'freqmin':freqmin,'freqmax':freqmax,'samp_freq':samp_freq,'start_date':\
    start_date,'end_date':end_date,'inc_hours':inc_hours,'cc_len':cc_len,'step':step,'MAX_MEM':MAX_MEM}
metadata = os.path.join(direc, 'download_info.txt')

# prepare station info (existing station list vs. fetching from client)
if down_list:
    if not os.path.isfile(dlist):
        raise IOError('file %s not exist! double check!' % dlist)
Beispiel #19
0
def test_finite_source_retrieval(reciprocal_clients, usgs_param):
    """
    Tests if the finite sources requested from the server are identical to
    the one requested with the local instaseis client with some required
    tweaks.
    """
    client = reciprocal_clients

    db = instaseis.open_db(client.filepath)

    basic_parameters = {
        "receiverlongitude": 11,
        "receiverlatitude": 22,
        "receiverdepthinmeters": 0,
        "format": "miniseed"
    }

    with io.open(usgs_param, "rb") as fh:
        body = fh.read()

    # default parameters
    params = copy.deepcopy(basic_parameters)
    request = client.fetch(_assemble_url('finite_source', **params),
                           method="POST",
                           body=body)
    assert request.code == 200
    st_server = obspy.read(request.buffer)
    for tr in st_server:
        assert tr.stats._format == "MSEED"

    # Parse the finite source.
    fs = _parse_finite_source(usgs_param)
    rec = instaseis.Receiver(latitude=22,
                             longitude=11,
                             network="XX",
                             station="SYN",
                             location="SE")

    st_db = db.get_seismograms_finite_source(sources=fs, receiver=rec)
    # The origin time is the time of the first sample in the route.
    for tr in st_db:
        # Cut away the first ten samples as they have been previously added.
        tr.data = tr.data[10:]
        tr.stats.starttime = obspy.UTCDateTime(1900, 1, 1)

    for tr_db, tr_server in zip(st_db, st_server):
        # Sample spacing is very similar but not equal due to floating point
        # accuracy.
        np.testing.assert_allclose(tr_server.stats.delta, tr_db.stats.delta)
        tr_server.stats.delta = tr_db.stats.delta
        del tr_server.stats._format
        del tr_server.stats.mseed

        assert tr_db.stats == tr_server.stats
        np.testing.assert_allclose(tr_db.data, tr_server.data)

    # Once again but this time request a SAC file.
    params = copy.deepcopy(basic_parameters)
    params["format"] = "saczip"
    request = client.fetch(_assemble_url('finite_source', **params),
                           method="POST",
                           body=body)
    assert request.code == 200
    st_server = obspy.Stream()
    zip_obj = zipfile.ZipFile(request.buffer)
    for name in zip_obj.namelist():
        st_server += obspy.read(io.BytesIO(zip_obj.read(name)))
    for tr in st_server:
        assert tr.stats._format == "SAC"

    for tr_db, tr_server in zip(st_db, st_server):
        # Sample spacing is very similar but not equal due to floating point
        # accuracy.
        np.testing.assert_allclose(tr_server.stats.delta, tr_db.stats.delta)
        tr_server.stats.delta = tr_db.stats.delta
        del tr_server.stats._format
        del tr_server.stats.sac

        assert tr_db.stats == tr_server.stats
        np.testing.assert_allclose(tr_db.data, tr_server.data)

    # One with a label.
    params = copy.deepcopy(basic_parameters)
    params["label"] = "random_things"
    request = client.fetch(_assemble_url('finite_source', **params),
                           method="POST",
                           body=body)
    assert request.code == 200

    cd = request.headers["Content-Disposition"]
    assert cd.startswith("attachment; filename=random_things_")
    assert cd.endswith(".mseed")

    # One simulating a crash in the underlying function.
    params = copy.deepcopy(basic_parameters)

    with mock.patch("instaseis.database_interfaces.base_instaseis_db"
                    ".BaseInstaseisDB.get_seismograms_finite_source") as p:
        p.side_effect = ValueError("random crash")
        request = client.fetch(_assemble_url('finite_source', **params),
                               method="POST",
                               body=body)

    assert request.code == 400
    assert request.reason == ("Could not extract finite source seismograms. "
                              "Make sure, the parameters are valid, and the "
                              "depth settings are correct.")

    # Simulating a logic error that should not be able to happen.
    params = copy.deepcopy(basic_parameters)
    with mock.patch("instaseis.database_interfaces.base_instaseis_db"
                    ".BaseInstaseisDB.get_seismograms_finite_source") as p:
        # Longer than the database returned stream thus the endtime is out
        # of bounds.
        st = obspy.read()

        p.return_value = st
        request = client.fetch(_assemble_url('finite_source', **params),
                               method="POST",
                               body=body)

    assert request.code == 500
    assert request.reason.startswith("Endtime larger than the extracted "
                                     "endtime")

    # One more with resampling parameters and different units.
    params = copy.deepcopy(basic_parameters)
    # We must have a sampling rate that cleanly fits in the existing one,
    # otherwise we cannot fake the cutting.
    dt_new = 24.724845445855724 / 10
    params["dt"] = dt_new
    params["kernelwidth"] = 2
    params["units"] = "acceleration"

    st_db = db.get_seismograms_finite_source(sources=fs,
                                             receiver=rec,
                                             dt=dt_new,
                                             kernelwidth=2,
                                             kind="acceleration")
    # The origin time is the time of the first sample in the route.
    for tr in st_db:
        # Cut away the first ten samples as they have been previously added.
        tr.data = tr.data[100:]
        tr.stats.starttime = obspy.UTCDateTime(1900, 1, 1)

    request = client.fetch(_assemble_url('finite_source', **params),
                           method="POST",
                           body=body)
    assert request.code == 200
    st_server = obspy.read(request.buffer)

    # Cut some parts in the middle to avoid any potential boundary effects.
    st_db.trim(obspy.UTCDateTime(1900, 1, 1, 0, 4),
               obspy.UTCDateTime(1900, 1, 1, 0, 14))
    st_server.trim(obspy.UTCDateTime(1900, 1, 1, 0, 4),
                   obspy.UTCDateTime(1900, 1, 1, 0, 14))

    for tr_db, tr_server in zip(st_db, st_server):
        # Sample spacing and times are very similar but not identical due to
        # floating point inaccuracies in the arithmetics.
        np.testing.assert_allclose(tr_server.stats.delta, tr_db.stats.delta)
        np.testing.assert_allclose(tr_server.stats.starttime.timestamp,
                                   tr_db.stats.starttime.timestamp)
        tr_server.stats.delta = tr_db.stats.delta
        tr_server.stats.starttime = tr_db.stats.starttime
        del tr_server.stats._format
        del tr_server.stats.mseed
        del tr_server.stats.processing
        del tr_db.stats.processing

        np.testing.assert_allclose(tr_server.stats.delta, tr_db.stats.delta)

        assert tr_db.stats == tr_server.stats
        np.testing.assert_allclose(tr_db.data,
                                   tr_server.data,
                                   rtol=1E-7,
                                   atol=tr_db.data.ptp() * 1E-7)

    # Testing network and station code parameters.
    # Default values.
    params = copy.deepcopy(basic_parameters)
    request = client.fetch(_assemble_url('finite_source', **params),
                           method="POST",
                           body=body)
    assert request.code == 200
    st_server = obspy.read(request.buffer)
    for tr in st_server:
        assert tr.stats.network == "XX"
        assert tr.stats.station == "SYN"
        assert tr.stats.location == "SE"

    # Setting all three.
    params = copy.deepcopy(basic_parameters)
    params["networkcode"] = "AA"
    params["stationcode"] = "BB"
    params["locationcode"] = "CC"
    request = client.fetch(_assemble_url('finite_source', **params),
                           method="POST",
                           body=body)
    assert request.code == 200
    st_server = obspy.read(request.buffer)
    for tr in st_server:
        assert tr.stats.network == "AA"
        assert tr.stats.station == "BB"
        assert tr.stats.location == "CC"

    # Setting only the location code.
    params = copy.deepcopy(basic_parameters)
    params["locationcode"] = "AA"
    request = client.fetch(_assemble_url('finite_source', **params),
                           method="POST",
                           body=body)
    assert request.code == 200
    st_server = obspy.read(request.buffer)
    for tr in st_server:
        assert tr.stats.network == "XX"
        assert tr.stats.station == "SYN"
        assert tr.stats.location == "AA"

    # Test the scale parameter.
    params = copy.deepcopy(basic_parameters)
    params["scale"] = 33.33
    request = client.fetch(_assemble_url('finite_source', **params),
                           method="POST",
                           body=body)
    assert request.code == 200
    st_server = obspy.read(request.buffer)
    for tr in st_server:
        assert tr.stats._format == "MSEED"

    # Parse the finite source.
    fs = _parse_finite_source(usgs_param)
    rec = instaseis.Receiver(latitude=22,
                             longitude=11,
                             network="XX",
                             station="SYN",
                             location="SE")

    st_db = db.get_seismograms_finite_source(sources=fs, receiver=rec)
    # The origin time is the time of the first sample in the route.
    for tr in st_db:
        # Multiply with scale parameter.
        tr.data *= 33.33
        # Cut away the first ten samples as they have been previously added.
        tr.data = tr.data[10:]
        tr.stats.starttime = obspy.UTCDateTime(1900, 1, 1)

    for tr_db, tr_server in zip(st_db, st_server):
        # Sample spacing is very similar but not equal due to floating point
        # accuracy.
        np.testing.assert_allclose(tr_server.stats.delta, tr_db.stats.delta)
        tr_server.stats.delta = tr_db.stats.delta
        del tr_server.stats._format
        del tr_server.stats.mseed

        assert tr_db.stats == tr_server.stats
        np.testing.assert_allclose(tr_db.data,
                                   tr_server.data,
                                   atol=1E-6 * tr_db.data.ptp())
Beispiel #20
0
class InstaseisTimeSeriesHandler(with_metaclass(ABCMeta,
                                                InstaseisRequestHandler)):
    arguments = None
    connection_closed = False
    default_label = ""
    default_origin_time = obspy.UTCDateTime(0)

    def __init__(self, *args, **kwargs):
        super(InstaseisTimeSeriesHandler, self).__init__(*args, **kwargs)

    def on_connection_close(self):  # pragma: no cover
        """
        Called when the client cancels the connection. Then the loop
        requesting seismograms will stop.
        """
        InstaseisRequestHandler.on_connection_close(self)
        self.__connection_closed = True

    def parse_arguments(self):
        # Make sure that no additional arguments are passed.
        unknown_arguments = set(self.request.arguments.keys()).difference(set(
            self.arguments.keys()))

        # Remove the body arguments as they don't count.
        unknown_arguments = unknown_arguments.difference(set(
            self.request.body_arguments.keys()))

        if unknown_arguments:
            msg = "The following unknown parameters have been passed: %s" % (
                ", ".join("'%s'" % _i for _i in sorted(unknown_arguments)))
            raise tornado.web.HTTPError(400, log_message=msg,
                                        reason=msg)

        # Check for duplicates.
        duplicates = []
        for key, value in self.request.arguments.items():
            if len(value) == 1:
                continue
            else:
                duplicates.append(key)
        if duplicates:
            msg = "Duplicate parameters: %s" % (
                ", ".join("'%s'" % _i for _i in sorted(duplicates)))
            raise tornado.web.HTTPError(400, log_message=msg,
                                        reason=msg)

        args = obspy.core.AttribDict()
        for name, properties in self.arguments.items():
            if "required" in properties:
                try:
                    value = self.get_argument(name)
                except Exception:
                    msg = "Required parameter '%s' not given." % name
                    raise tornado.web.HTTPError(400, log_message=msg,
                                                reason=msg)
            else:
                if "default" in properties:
                    default = properties["default"]
                else:
                    default = None
                value = self.get_argument(name, default=default)
            if value is not None:
                try:
                    value = properties["type"](value)
                except Exception:
                    if "format" in properties:
                        msg = "Parameter '%s' must be formatted as: '%s'" % (
                            name, properties["format"])
                    else:
                        msg = ("Parameter '%s' could not be converted to "
                               "'%s'.") % (
                            name, str(properties["type"].__name__))
                    raise tornado.web.HTTPError(400, log_message=msg,
                                                reason=msg)
            setattr(args, name, value)

        # Validate some of them right here.
        self.validate_common_parameters(args)
        self.validate_parameters(args)

        return args

    def validate_common_parameters(self, args):
        """
        Also ensures some consistency across the routes.
        """
        info = self.application.db.info

        if "components" in self.arguments:
            if len(args.components) > 5:
                msg = "A maximum of 5 components can be requested."
                raise tornado.web.HTTPError(400, log_message=msg, reason=msg)

            if not args.components:
                msg = ("A request with no components will not return "
                       "anything...")
                raise tornado.web.HTTPError(400, log_message=msg, reason=msg)

        # Make sure the unit arguments is valid.
        if "units" in self.arguments:
            args.units = args.units.lower()
            if args.units not in ["displacement", "velocity", "acceleration"]:
                msg = ("Unit must be one of 'displacement', 'velocity', "
                       "or 'acceleration'")
                raise tornado.web.HTTPError(400, log_message=msg, reason=msg)

        # Make sure the output format is valid.
        if "format" in self.arguments:
            args.format = args.format.lower()
            if args.format not in ("miniseed", "saczip"):
                msg = ("Format must either be 'miniseed' or 'saczip'.")
                raise tornado.web.HTTPError(400, log_message=msg, reason=msg)

        # If its essentially equal to the internal sampling rate just set it
        # to equal to ease the following comparisons.
        if "dt" in self.arguments:
            if args.dt and abs(args.dt - info.dt) / args.dt < 1E-7:
                args.dt = info.dt

            # Make sure that dt, if given is larger then 0.01. This should
            # still be plenty for any use case but prevents the server from
            # having to send massive amounts of data in the case of user
            # errors.
            if args.dt is not None and args.dt < 0.01:
                msg = ("The smallest possible dt is 0.01. Please choose a "
                       "smaller value and resample locally if needed.")
                raise tornado.web.HTTPError(400, log_message=msg, reason=msg)

            # Also make sure it does not downsample.
            if args.dt is not None and args.dt > info.dt:
                msg = ("Cannot downsample. The sampling interval of the "
                       "database is %.5f seconds. Make sure to choose a "
                       "smaller or equal one." % info.dt)
                raise tornado.web.HTTPError(400, log_message=msg, reason=msg)

        if "kernelwidth" in self.arguments:
            # Make sure the interpolation kernel width is sensible. Don't allow
            # values smaller than 1 or larger than 20.
            if not (1 <= args.kernelwidth <= 20):
                msg = ("`kernelwidth` must not be smaller than 1 or larger "
                       "than 20.")
                raise tornado.web.HTTPError(400, log_message=msg, reason=msg)

    @abstractmethod
    def validate_parameters(self, args):
        """
        Implement this function to make checks not already performed in
        validate_common_parameters().
        """
        raise NotImplementedError

    def parse_time_settings(self, args):
        """
        Attempt to figure out the time settings.

        This is pretty messy unfortunately. After this method has been
        called, args.origintime will always be set to an absolute time.

        args.starttime and args.endtime will either be set to absolute times
        or dictionaries describing phase relative offsets.

        Returns the minium possible start- and the maximum possible endtime.
        """
        if args.origintime is None:
            args.origintime = self.default_origin_time

        # The origin time will be always set. If the starttime is not set,
        # set it to the origin time.
        if args.starttime is None:
            args.starttime = args.origintime

        # Now it becomes a bit ugly. If the starttime is a float, treat it
        # relative to the origin time.
        if isinstance(args.starttime, float):
            args.starttime = args.origintime + args.starttime

        # Now deal with the endtime.
        if isinstance(args.endtime, float):
            # If the start time is already known as an absolute time,
            # just add it.
            if isinstance(args.starttime, obspy.UTCDateTime):
                args.endtime = args.starttime + args.endtime
            # Otherwise the start time has to be a phase relative time and
            # is dealt with later.
            else:
                assert isinstance(args.starttime, obspy.core.AttribDict)

        # Figure out the maximum temporal range of the seismograms.
        ti = _get_seismogram_times(
            info=self.application.db.info, origin_time=args.origintime,
            dt=args.dt, kernelwidth=args.kernelwidth,
            remove_source_shift=False, reconvolve_stf=False)

        # If the endtime is not set, do it here.
        if args.endtime is None:
            args.endtime = ti["endtime"]

        # Do a couple of sanity checks here.
        if isinstance(args.starttime, obspy.UTCDateTime):
            # The desired seismogram start time must be before the end time of
            # the seismograms.
            if args.starttime >= ti["endtime"]:
                msg = ("The `starttime` must be before the seismogram ends.")
                raise tornado.web.HTTPError(400, log_message=msg, reason=msg)
            # Arbitrary limit: The starttime can be at max one hour before the
            # origin time.
            if args.starttime < (ti["starttime"] - 3600):
                msg = ("The seismogram can start at the maximum one hour "
                       "before the origin time.")
                raise tornado.web.HTTPError(400, log_message=msg, reason=msg)

        if isinstance(args.endtime, obspy.UTCDateTime):
            # The endtime must be within the seismogram window
            if not (ti["starttime"] <= args.endtime <= ti["endtime"]):
                msg = ("The end time of the seismograms lies outside the "
                       "allowed range.")
                raise tornado.web.HTTPError(400, log_message=msg, reason=msg)

        return ti["starttime"], ti["endtime"]

    def set_headers(self, args):
        if "format" not in args:
            format = "miniseed"
        else:
            format = args.format

        if format == "miniseed":
            content_type = "application/vnd.fdsn.mseed"
        elif format == "saczip":
            content_type = "application/zip"
        self.set_header("Content-Type", content_type)

        file_endings_map = {
            "miniseed": "mseed",
            "saczip": "zip"}

        if "label" in args and args.label:
            label = args.label
        else:
            label = self.default_label

        filename = "%s_%s.%s" % (
            label,
            str(obspy.UTCDateTime()).replace(":", "_"),
            file_endings_map[format])

        self.set_header("Content-Disposition",
                        "attachment; filename=%s" % filename)

    def get_ttime(self, source, receiver, phase):
        if self.application.travel_time_callback is None:
            msg = "Server does not support travel time calculations."
            raise tornado.web.HTTPError(
                404, log_message=msg, reason=msg)

        # Finite sources will perform these calculations with the hypocenter.
        if isinstance(source, FiniteSource):
            src_latitude = source.hypocenter_latitude
            src_longitude = source.hypocenter_longitude
            src_depth_in_m = source.hypocenter_depth_in_m
        # or any single source.
        else:
            src_latitude = source.latitude
            src_longitude = source.longitude
            src_depth_in_m = source.depth_in_m

        try:
            tt = self.application.travel_time_callback(
                sourcelatitude=src_latitude,
                sourcelongitude=src_longitude,
                sourcedepthinmeters=src_depth_in_m,
                receiverlatitude=receiver.latitude,
                receiverlongitude=receiver.longitude,
                receiverdepthinmeters=receiver.depth_in_m,
                phase_name=phase,
                db_info=self.application.db.info)
        except ValueError as e:
            err_msg = str(e)
            if err_msg.lower().startswith("invalid phase name"):
                msg = "Invalid phase name: %s" % phase
            # This is just a safeguard - its save to not coverage test it.
            else:  # pragma: no cover
                msg = "Failed to calculate travel time due to: %s" % err_msg
            raise tornado.web.HTTPError(400, log_message=msg, reason=msg)
        return tt

    def validate_geometry(self, source, receiver):
        """
        Validate the source-receiver geometry.
        """
        info = self.application.db.info

        # Any single...
        if hasattr(source, "latitude"):
            src_depth_in_m = source.depth_in_m
        # Or a finite source...
        else:
            src_depth_in_m = source.hypocenter_depth_in_m

        # XXX: Will have to be changed once we have a database recorded for
        # example on the ocean bottom.
        if info.is_reciprocal:
            # Receiver must be at the surface.
            if receiver.depth_in_m is not None:
                if receiver.depth_in_m != 0.0:
                    msg = "Receiver must be at the surface for reciprocal " \
                          "databases."
                    raise tornado.web.HTTPError(400, log_message=msg,
                                                reason=msg)
            # Source depth must be within the allowed range.
            if not ((info.planet_radius - info.max_radius) <=
                    src_depth_in_m <=
                    (info.planet_radius - info.min_radius)):
                msg = ("Source depth must be within the database range: %.1f "
                       "- %.1f meters.") % (
                        info.planet_radius - info.max_radius,
                        info.planet_radius - info.min_radius)
                raise tornado.web.HTTPError(400, log_message=msg,
                                            reason=msg)
        else:
            # The source depth must coincide with the one in the database.
            if src_depth_in_m != info.source_depth * 1000:
                    msg = "Source depth must be: %.1f km" % info.source_depth
                    raise tornado.web.HTTPError(400, log_message=msg,
                                                reason=msg)

    def get_phase_relative_times(self, args, source, receiver, min_starttime,
                                 max_endtime):
        """
        Helper function getting the times for each receiver for
        phase-relative offsets.

        Returns None in case there either is no phase at the
        requested distance or it arrives too late, early for other settings.
        """
        if isinstance(args.starttime, obspy.core.AttribDict):
            tt = self.get_ttime(source=source, receiver=receiver,
                                phase=args.starttime["phase"])
            if tt is None:
                return
            starttime = args.origintime + tt + args.starttime["offset"]
        else:
            starttime = args.starttime

        if starttime < min_starttime - 3600.0:
            return

        if isinstance(args.endtime, obspy.core.AttribDict):
            tt = self.get_ttime(source=source, receiver=receiver,
                                phase=args.endtime["phase"])
            if tt is None:
                return
            endtime = args.origintime + tt + args.endtime["offset"]
        # Endtime relative to phase relative starttime.
        elif isinstance(args.endtime, float):
            endtime = starttime + args.endtime
        else:
            endtime = args.endtime

        if endtime > max_endtime:
            return

        return starttime, endtime

    def get_receivers(self, args):
        # Already checked before - just make sure the settings are valid.
        assert (args.receiverlatitude is not None and
                args.receiverlongitude is not None) or \
               (args.network and args.station)

        receivers = []

        rec_depth = args.receiverdepthinmeters

        # Construct either a single receiver object.
        if args.receiverlatitude is not None:
            try:
                receiver = Receiver(latitude=args.receiverlatitude,
                                    longitude=args.receiverlongitude,
                                    network=args.networkcode,
                                    station=args.stationcode,
                                    location=args.locationcode,
                                    depth_in_m=rec_depth)
            except Exception:
                msg = ("Could not construct receiver with passed parameters. "
                       "Check parameters for sanity.")
                raise tornado.web.HTTPError(400, log_message=msg, reason=msg)
            receivers.append(receiver)
        # Or a list of receivers.
        elif args.network is not None and args.station is not None:
            networks = args.network.split(",")
            stations = args.station.split(",")

            coordinates = self.application.station_coordinates_callback(
                networks=networks, stations=stations)

            if not coordinates:
                msg = "No coordinates found satisfying the query."
                raise tornado.web.HTTPError(
                    404, log_message=msg, reason=msg)

            for station in coordinates:
                try:
                    receivers.append(Receiver(
                        latitude=station["latitude"],
                        longitude=station["longitude"],
                        network=station["network"],
                        station=station["station"],
                        depth_in_m=0))
                except Exception:
                    msg = ("Station coordinate query returned invalid "
                           "coordinates.")
                    raise tornado.web.HTTPError(400, log_message=msg,
                                                reason=msg)
        return receivers

    def validate_receiver_parameters(self, args):
        """
        Useful for routes that use single receivers.
        """
        # The networkcode and stationcode parameters have a maximum number
        # of letters.
        if args.stationcode and len(args.stationcode) > 5:
            msg = "'stationcode' must have 5 or fewer letters."
            raise tornado.web.HTTPError(400, log_message=msg, reason=msg)

        if args.networkcode and len(args.networkcode) > 2:
            msg = "'networkcode' must have 2 or fewer letters."
            raise tornado.web.HTTPError(400, log_message=msg, reason=msg)

        # The location code as well.
        if args.locationcode and len(args.locationcode) > 2:
            msg = "'locationcode' must have 2 or fewer letters."
            raise tornado.web.HTTPError(400, log_message=msg, reason=msg)

        # Figure out who the station coordinates are specified.
        direct_receiver_settings = [
            i is not None
            for i in (args.receiverlatitude, args.receiverlongitude)]
        query_receivers = [i is not None for i in (args.network, args.station)]
        if any(direct_receiver_settings) and any(query_receivers):
            msg = ("Receiver coordinates can either be specified by passing "
                   "the coordinates, or by specifying query parameters, "
                   "but not both.")
            raise tornado.web.HTTPError(400, log_message=msg, reason=msg)
        elif not(all(direct_receiver_settings) or all(query_receivers)):
            msg = ("Must specify a full set of coordinates or a full set of "
                   "receiver parameters.")
            raise tornado.web.HTTPError(400, log_message=msg, reason=msg)

        # Should not happen.
        assert not (all(direct_receiver_settings) and all(query_receivers))

        # Make sure that the station coordinates callback is available if
        # needed. Otherwise raise a 404.
        if all(query_receivers) and \
                not self.application.station_coordinates_callback:
            msg = ("Server does not support station coordinates and thus no "
                   "station queries.")
            raise tornado.web.HTTPError(404, log_message=msg, reason=msg)
Beispiel #21
0
def get_ev_info(ev_info, iex):
    # ===============================================================
    # SilwalTape2016 example event (Anchorage) -- python run_getwaveform.py event_input 0
    if iex == 0:
        ev_info.use_catalog = 0  # do not use event catalog for source parameters
        ev_info.otime = obspy.UTCDateTime("2009-04-07T20:12:55.351")
        ev_info.min_dist = 0
        ev_info.max_dist = 300
        ev_info.tbefore_sec = 100
        ev_info.tafter_sec = 300

        # keep stations with missing components and fill the missing component with a null trace (MPEN)
        #ev_info.icreateNull = 1

        # RAW and ENZ files can be used when checking if you are receiving all possible data (example station: SOLD)
        ev_info.isave_raw = False
        ev_info.isave_raw_processed = False
        ev_info.isave_ENZ = False

        #ev_info.min_lat = 59
        #ev_info.max_lat = 62
        #ev_info.min_lon = -152
        #ev_info.max_lon = -147

        # default list of Alaska networks
        # note 1: cannot use '*' because of IM
        # note 2: may want to exclude the mid-band AV network
        # note 3: these are temporary:
        # XE BEAAR 1999
        # XR ARCTIC 2004
        # XZ STEEP 2005
        # YV MOOS 2006
        # XV FLATS 2014
        # ZE SALMON 2015
        # XG WVF 2016
        # [7C MMEP 2015]
        # TA
        #ev_info.network = 'AK,AT,AV,CN,II,IU,US,XM,XV,XZ,YV'
        #ev_info.network = 'AK' # for testing
        ev_info.network = 'AK,AT,AV,CN,II,IU,US,XM,TA,XE,XR,XZ,YV,XV,ZE,XG'

        ev_info.channel = 'BH?'
        ev_info.use_catalog = 0
        ev_info.elat = 61.45420
        ev_info.elon = -149.7428
        ev_info.edep = 33033.60
        # ev_info.rlat = 61.45420
        # ev_info.rlon = -149.7428
        # ev_info.rtime = obspy.UTCDateTime("2009-04-07T20:12:55.351")
        ev_info.emag = 4.6
        # scaling and resampling needed for CAP
        ev_info.resample_TF = True
        ev_info.resample_freq = 50
        ev_info.scale_factor = 100
        #ev_info.phase_window = False
        #-------for specfem------------
        #ev_info.tbefore_sec = 0
        #ev_info.resample_TF = False
        #ev_info.scale_factor = 1
        #ev_info.outformat = 'DISP'
        #------------------------------

# Iniskin earthquake
    if iex == 1:
        ev_info.use_catalog = 0  # do not use event catalog for source parameters
        # GCMT source parameters
        # the otime is the centroid time and accounts for tshift
        ev_info.otime = obspy.UTCDateTime("2016-01-24T10:30:37.400")
        ev_info.elat = 59.75
        ev_info.elon = -153.27
        ev_info.edep = 110700
        ev_info.emag = 7.1
        # subset of stations
        ev_info.min_dist = 0
        ev_info.max_dist = 800
        ev_info.tbefore_sec = 100
        ev_info.tafter_sec = 600
        ev_info.network = 'AV,CN,ZE,AT,TA,AK,XV,II,IU,US'  # IM will probably crash it
        ev_info.channel = 'BH?,HH?'
        #ev_info.resample_freq = 0        # no resampling
        #ev_info.resample_TF = False
        #ev_info.scale_factor = 1         # no scale factor

        # parameters for examining step response (causal low-pass filter on raw waveforms)
        # delete AUQ, SPCP, SPBG
        ev_info.rotateRTZ = False
        ev_info.ifFilter = True
        ev_info.filter_type = 'lowpass'
        ev_info.f1 = 1 / 4
        ev_info.zerophase = False
        ev_info.remove_response = False
        ev_info.ipre_filt = 0
        ev_info.demean = False
        ev_info.detrend = False

        # For SALMON data
        #ev_info.user = None
        #ev_info.password = None

# MFFZ earthquakes for investigating the step response
# copied from event_input_flats
    if iex == 2:
        ev_info.use_catalog = 0
        # -------------------------------------------------
        ev_info.otime = obspy.UTCDateTime("2014-08-31T03:06:57.111")
        ev_info.elat = 65.1526
        ev_info.elon = -149.0398
        ev_info.edep = 16614.7
        ev_info.emag = 5.20
        # -------------------------------------------------

        ev_info.min_dist = 0
        ev_info.max_dist = 300
        ev_info.tbefore_sec = 200
        ev_info.tafter_sec = 600
        ev_info.network = 'AV,CN,AT,TA,AK,XV,II,IU,US'
        # ev_info.network = 'XV,AK'
        ev_info.channel = 'BH?,HH?'
        #ev_info.scale_factor = 1
        #ev_info.resample_freq = 0
        #ev_info.resample_TF = False
        # for CAP
        # ev_info.resample_TF = True
        # ev_info.scale_factor = 100
        # ev_info.resample_freq = 50

        # to investigate step response
        ev_info.rotateRTZ = True
        ev_info.rotateUVW = True
        ev_info.ifFilter = True
        ev_info.zerophase = False  # causal
        # filter_type = 'lowpass'
        ev_info.filter_type = 'bandpass'
        ev_info.f1 = 1 / 100  # fmin
        ev_info.f2 = 1 / 10  # fmax
        ev_info.corners = 4
        # ev_info.remove_response = False
        ev_info.remove_response = True
        ev_info.ipre_filt = 1
        ev_info.demean = True
        ev_info.detrend = True
        ev_info.output_cap_weight_file = False
        # ev_info.outformat = 'DISP'
        ev_info.ifsave_sacpaz = True
        ev_info.taper = 0.2

# Loop over multiple event
    if iex == 3:
        ev_info.use_catalog = 0
        # text file of source parameters
        ievent = 1
        events_file = "/home/ksmith/REPOSITORIES/manuscripts/kyle/papers/nenanabasin/data/nenanabasin_obspy.txt"
        eids, otimes, elons, elats, edeps, emags = reof.read_events_obspy_file(
            events_file)

        ev_info_list = []
        #for xx in range(len(eids)):
        #for xx in range(1,3):
        for xx in range(ievent - 1, ievent):
            ev_info_temp = ev_info.copy()
            ev_info_temp.otime = obspy.UTCDateTime(otimes[xx])
            ev_info_temp.elat = elats[xx]
            ev_info_temp.elon = elons[xx]
            ev_info_temp.edep = edeps[xx]
            ev_info_temp.emag = emags[xx]
            ev_info_temp.eid = eids[xx]

            # subset of stations
            ev_info_temp.min_dist = 0
            ev_info_temp.max_dist = 200
            ev_info_temp.tbefore_sec = 100
            ev_info_temp.tafter_sec = 500
            ev_info_temp.network = 'AV,CN,ZE,AT,TA,AK,XV,II,IU,US'
            #ev_info_temp.network = 'AK,AT,AV,CN,II,IU,US,XM,TA,XE,XR,XZ,YV,XV,ZE,XG'
            ev_info_temp.channel = 'BH?,HH?'
            #ev_info_temp.resample_freq = 40
            #ev_info_temp.scale_factor = 100
            #ev_info_temp.resample_TF = False

            # append getwaveform objects
            ev_info_list.append(ev_info_temp)

        # always return ev_info
        ev_info = ev_info_list

# Alaska data from far away event
    if iex == 4:
        ev_info.use_catalog = 0
        # Mariana Event observed by FLATS
        ev_info.otime = obspy.UTCDateTime("2016-07-29T21:18:26.000")
        ev_info.elat = 18.5439
        ev_info.elon = 145.541
        ev_info.edep = 207620.0
        ev_info.emag = 7.7
        ev_info.rtime = obspy.UTCDateTime("2016-07-29T21:28:19.000")
        # center at F3TN
        ev_info.rlat = 64.7716
        ev_info.rlon = -149.1465
        ev_info.min_dist = 0
        ev_info.max_dist = 150
        ev_info.tbefore_sec = 100
        ev_info.tafter_sec = 400
        ev_info.network = 'AK,AT,II,IU,US,XM,XV,XZ,TA'  # no CN,AV,YV,ZE
        ev_info.channel = 'BH?,HH?'

# doublet event near Manley
    if iex == 5:
        ev_info.rlat = 64.7716
        ev_info.rlon = -149.1465
        ev_info.scale_factor = 1
        ev_info.min_dist = 0
        ev_info.max_dist = 150
        ev_info.tbefore_sec = 100
        ev_info.tafter_sec = 200
        ev_info.network = 'XV,TA'
        ev_info.channel = 'BH?,HH?'
        ev_info.use_catalog = 0
        ev_info.station = 'I23K,F3TN'
        # AEC source parameters
        ev_info.otime = obspy.UTCDateTime("2015-11-06T01:20:12.712")
        ev_info.elat = 64.7552
        ev_info.elon = -151.3103
        ev_info.edep = 1502.1
        ev_info.emag = 3.35
        ev_info.rtime = ev_info.otime

# Illinois main event
    if iex == 6:
        ev_info.use_catalog = 0
        ev_info.otime = obspy.UTCDateTime("2008-04-18T09:36:59.110")
        ev_info.elon = -87.886
        ev_info.elat = 38.452
        ev_info.edep = 14.3
        ev_info.emag = 5.2
        ev_info.min_dist = 0
        ev_info.max_dist = 500
        ev_info.tbefore_sec = 100
        ev_info.tafter_sec = 300
        ev_info.network = 'IU,NM'
        ev_info.station = '*'
        ev_info.channel = 'LH?,BH?'

# Uturuncu main event, AlvizuriTape2016
    if iex == 7:
        ev_info.use_catalog = 0
        ev_info.otime = obspy.UTCDateTime("2010-05-16T06:34:54.464")
        ev_info.elon = -67.1856
        ev_info.elat = -22.2600
        ev_info.edep = -0.6
        ev_info.emag = 2.8
        ev_info.min_dist = 0
        ev_info.max_dist = 500
        ev_info.tbefore_sec = 100
        ev_info.tafter_sec = 300
        ev_info.network = 'XP'
        ev_info.station = '*'
        ev_info.channel = 'HH?'

# Manley earthquake (Kyle)
    if iex == 8:
        ev_info.use_catalog = 0
        ev_info.otime = obspy.UTCDateTime("2016-05-18T03:25:48.320")
        ev_info.elat = 65.2466
        ev_info.elon = -151.0651
        ev_info.edep = 15156.2
        ev_info.emag = 4.2
        ev_info.rtime = ev_info.otime
        ev_info.max_dist = 400
        ev_info.tbefore_sec = 50
        ev_info.tafter_sec = 600
        ev_info.network = 'AK,AT,AV,CN,II,IU,US,XM,TA,XE,XR,XZ,YV,XV,ZE,XG'
        ev_info.channel = 'BH?,HH?'
        # for CAP
        ev_info.resample_TF = True
        ev_info.resample_freq = 50
        ev_info.scale_factor = 100

# same as iex=11 but for the IRIS database
# GOAL: For LLNL events, we do NOT want to use the IRIS source parameters:
#       origin time, hypocenter, magnitude.
# --> THIS EXAMPLE IS NOT CURRENTLY WORKING WITH sln01
# ERROR: FileNotFoundError: [Errno 2] No such file or directory: '19910914190000000/19910914190000000_ev_info.obj'
    if iex == 9:
        ev_info.overwrite_ddir = 0  # do NOT overwrite the existing directory
        ev_info.client_name = 'IRIS'
        #ev_info.client_name = 'NCEDC'
        ev_info.use_catalog = 1
        #ev_info.idb = 1            # IRIS database
        # ev_info.resample_freq = 0  # no resampling
        # ev_info.otime = obspy.UTCDateTime("1991-09-14T19:00:00.000Z")   # Hoya actual
        ev_info.otime = obspy.UTCDateTime(
            "1991-09-14T19:00:08.031Z")  # Hoya target
        ev_info.min_dist = 0
        ev_info.max_dist = 1200
        ev_info.tbefore_sec = 100
        ev_info.tafter_sec = 600
        # needs to be run TWICE to get BK stations and IRIS stations
        #ev_info.network = 'BK'        # BK will go to NCEDC
        ev_info.network = '*'  # * will get all at IRIS DMC
        ev_info.channel = 'BH?,LH?'
        ev_info.overwrite_ddir = 0
        ev_info.ifsave_stationxml = False

    if iex == 10:
        ev_info.idb = 1
        ev_info.overwrite_ddir = 1  # delete data dir if it exists
        ev_info.use_catalog = 0  # do not use event catalog for source parameters
        sec_tol = 180
        events_file = "/home/ksmith/REPOSITORIES/manuscripts/kyle/papers/nenanabasin/data/nenanabasin_obspy.txt"
        eids, otimes, elons, elats, edeps, emags = reof.read_events_obspy_file(
            events_file)

        ev_info_list = []
        for xx in range(0, 1):
            ev_info_temp = ev_info.copy()
            ev_info_temp.otime = obspy.UTCDateTime(otimes[xx])
            ev_info_temp.elat = elats[xx]
            ev_info_temp.elon = elons[xx]
            ev_info_temp.edep = edeps[xx]
            ev_info_temp.emag = emags[xx]
            ev_info_temp.eid = eids[xx]
            # subset of stations
            ev_info_temp.min_dist = 0
            #ev_info_temp.max_dist = 50
            ev_info_temp.max_dist = 150
            ev_info_temp.rlat = 64.7716
            ev_info_temp.rlon = -149.1465
            ev_info_temp.rtime = ev_info_temp.otime
            saftcase = False
            ev_info_temp.phases = ["P", "S"]
            ev_info_temp.write_sac_phase = True  # put phase information in sac files
            ev_info_temp.network = 'AV,CN,ZE,AT,TA,AK,XV,II,IU,US'
            ev_info_temp.channel = 'BH?,HH?'
            ev_info_temp.resample_TF = True  # to be consistent with past past waveforms
            ev_info_temp.resample_freq = 50
            ev_info_temp.scale_factor = 1
            ev_info_temp.tbefore_sec = 150
            ev_info_temp.tafter_sec = 1000
            print("before sec = ", ev_info_temp.tbefore_sec)
            print("after sec = ", ev_info_temp.tafter_sec)

            # append getwaveform objects
            ev_info_list.append(ev_info_temp)

        # always return ev_info
        ev_info = ev_info_list

    if iex == 11:
        ev_info.use_catalog = 0
        ev_info.otime = obspy.UTCDateTime("2021-05-31T06:59:54.000")
        ev_info.min_dist = 0
        ev_info.max_dist = 300
        ev_info.tbefore_sec = 100
        ev_info.tafter_sec = 300

        # RAW and ENZ files can be used when checking if you are receiving all possible data (example station: SOLD)
        ev_info.isave_raw = True
        ev_info.isave_raw_processed = False
        ev_info.isave_ENZ = True

        ev_info.network = 'AK'  # for testing
        ev_info.channel = 'BH?'
        ev_info.use_catalog = 0
        ev_info.elat = 62.4469
        ev_info.elon = -148.2537
        ev_info.edep = 43900.0
        ev_info.emag = 6.1
        # scaling and resampling needed for CAP
        ev_info.resample_TF = True
        ev_info.resample_freq = 50
        ev_info.scale_factor = 100
        ev_info.remove_clipped = True

    return (ev_info)
Beispiel #22
0
 def correct(self):
     """compute monthly transfer function
     """
     targetdt    = 1./self.sps
     stime       = obspy.UTCDateTime('%04d%02d01' %(self.year, self.month))
     monthdir    = self.monthdir
     omonthdir   = self.outdir + '/%04d.%s' %(self.year, monthdict[self.month])
     if not os.path.isdir(monthdir):
         return False
     chan_type   = None
     while( (stime.year == self.year) and (stime.month == self.month)):
         daydir      = monthdir+'/%d.%s.%d' %(self.year, monthdict[self.month], stime.day)
         fpattern    = daydir+'/ft_%d.%s.%d.%s' %(self.year, monthdict[self.month], stime.day, self.staid)
         odaydir     = omonthdir+'/%d.%s.%d' %(self.year, monthdict[self.month], stime.day)
         if not os.path.isdir(odaydir):
             os.makedirs(odaydir)
         if chan_type is None:
             for chtype in self.chan_rank:
                 fname1  = fpattern+'.%sH1.SAC' %chtype
                 fname2  = fpattern+'.%sH2.SAC' %chtype
                 fnamez  = fpattern+'.%sHZ.SAC' %chtype
                 fnamep  = fpattern+'.%sDH.SAC' %chtype
                 if os.path.isfile(fname1) and os.path.isfile(fname2) and \
                     os.path.isfile(fnamez) and os.path.isfile(fnamep):
                     chan_type   = chtype
                     break
         if chan_type is None:
             stime   += 86400.
             continue
         fname1  = fpattern+'.%sH1.SAC' %chan_type
         fname2  = fpattern+'.%sH2.SAC' %chan_type
         fnamez  = fpattern+'.%sHZ.SAC' %chan_type
         fnamep  = fpattern+'.%sDH.SAC' %chan_type
         if not (os.path.isfile(fname1) and os.path.isfile(fname2) and \
                 os.path.isfile(fnamez) and os.path.isfile(fnamep)):
             stime   += 86400.
             continue
         tr1     = obspy.read(fname1)[0]
         stimetr = tr1.stats.starttime
         tr2     = obspy.read(fname2)[0]
         trZ     = obspy.read(fnamez)[0]
         trP     = obspy.read(fnamep)[0]
         
         if (np.all(tr1.data == 0.) or np.all(tr2.data == 0.)) and np.all(trP.data == 0.):
             stime   += 86400.
             continue
         
         if abs(tr1.stats.delta - targetdt) > 1e-3 or abs(tr2.stats.delta - targetdt) > 1e-3 or \
             abs(trZ.stats.delta - targetdt) > 1e-3 or abs(trP.stats.delta - targetdt) > 1e-3:
             raise ValueError('!!! CHECK fs :'+ self.staid)
         else:
             tr1.stats.delta     = targetdt
             tr2.stats.delta     = targetdt
             trP.stats.delta     = targetdt
             trZ.stats.delta     = targetdt
         
         outfnameZ   = odaydir+'/ft_%d.%s.%d.%s.%sHZ.SAC' %(self.year, monthdict[self.month], stime.day, self.staid, chan_type)
         # sliding window raw data
         StreamZ = obspy.Stream()
         overlap = 0.99
         for tmptr in trZ.slide(window_length = self.window-1, step = int((self.window-1)*overlap)):
             # print (tmptr.stats.npts)
             StreamZ += tmptr.copy()
         Stream1 = obspy.Stream()
         for tmptr in tr1.slide(window_length = self.window-1, step = int((self.window-1)*overlap)):
             Stream1 += tmptr.copy()
         Stream2 = obspy.Stream()
         for tmptr in tr2.slide(window_length = self.window-1, step = int((self.window-1)*overlap)):
             Stream2 += tmptr.copy()
         StreamP = obspy.Stream()
         for tmptr in trP.slide(window_length = self.window-1, step = int((self.window-1)*overlap)):
             StreamP += tmptr.copy()
         # remove tilt and compliance
         outStreamZ  = obspy.Stream()
         Ntraces     = len(StreamZ)
         for itr in range(Ntraces):
             sth     = obspy.Stream()
             if not (np.all(Stream1[itr].data == 0.) or np.all(Stream1[itr].data == 0.)):
                 sth     += Stream1[itr]
                 sth     += Stream2[itr]
             sth     += StreamZ[itr]
             stp     = obspy.Stream()
             if not np.all(StreamP[itr].data == 0.):
                 stp     += StreamP[itr]
             tmptime = StreamZ[itr].stats.starttime
             tstamp  = str(tmptime.year).zfill(4)+'.' + \
                 str(tmptime.julday).zfill(3)+'.'
             tstamp  = tstamp + str(tmptime.hour).zfill(2) + \
                         '.'+str(tmptime.minute).zfill(2)
             if self.out_dtype == 'ZP':
                 ncomp   = 2
             elif self.out_dtype == 'Z2-1':
                 ncomp   = 3
             elif self.out_dtype  == 'ZP-21':
                 ncomp   = 4
             
             eventstream = EventStream( sta = self.stdb_inv, sth = sth, stp = stp,\
                 tstamp = tstamp, lat = self.stla, lon = self.stlo, time = tmptime,\
                 window = self.window,
                 sampling_rate = 1., ncomp = ncomp)
             eventstream.correct_data(self.tfnoise)
             tmptr       = StreamZ[itr].copy()
             tmptr.data  = eventstream.correct[self.out_dtype].copy()
             outStreamZ  += tmptr
             # outStreamZ.data = 
         # merge data
         outStreamZ.merge(method = 1, fill_value = 'interpolate', interpolation_samples=2)
         outTrZ  = outStreamZ[0]
         if os.path.isfile(outfnameZ):
             shutil.copyfile(src = outfnameZ, dst = outfnameZ+'_old')
             os.remove(outfnameZ)
         outTrZ.write(outfnameZ, format = 'SAC')
         stime   += 86400.
Beispiel #23
0
 def event_origins(self, event_description):
     """Add an origin to the event"""
     event_description.origins.append(
         ev.Origin(time=obspy.UTCDateTime(), longitude=-111, latitude=37))
     return event_description
Beispiel #24
0
 def transfer_func(self):
     """compute monthly transfer function
     """
     targetdt    = 1./self.sps
     stime       = obspy.UTCDateTime('%04d%02d01' %(self.year, self.month))
     monthdir    = self.monthdir
     if not os.path.isdir(monthdir):
         return False
     chan_type   = None
     Nday        = 0
     while( (stime.year == self.year) and (stime.month == self.month)):
         daydir  = monthdir+'/%d.%s.%d' %(self.year, monthdict[self.month], stime.day)
         if not os.path.isdir(daydir):
             stime   += 86400.
             continue 
         fpattern= daydir+'/ft_%d.%s.%d.%s' %(self.year, monthdict[self.month], stime.day, self.staid)
         if chan_type is None:
             for chtype in self.chan_rank:
                 fname1  = fpattern+'.%sH1.SAC' %chtype
                 fname2  = fpattern+'.%sH2.SAC' %chtype
                 fnamez  = fpattern+'.%sHZ.SAC' %chtype
                 fnamep  = fpattern+'.%sDH.SAC' %chtype
                 if os.path.isfile(fname1) and os.path.isfile(fname1) and \
                     os.path.isfile(fnamez) and os.path.isfile(fnamep):
                     chan_type   = chtype
                     break
         if chan_type is None:
             stime   += 86400.
             continue
         fname1  = fpattern+'.%sH1.SAC' %chan_type
         fname2  = fpattern+'.%sH2.SAC' %chan_type
         fnamez  = fpattern+'.%sHZ.SAC' %chan_type
         fnamep  = fpattern+'.%sDH.SAC' %chan_type
         if not (os.path.isfile(fname1) and os.path.isfile(fname1) and \
                 os.path.isfile(fnamez) and os.path.isfile(fnamep)):
             stime   += 86400.
             continue
         tr1     = obspy.read(fname1)[0]
         stimetr = tr1.stats.starttime
         tr2     = obspy.read(fname2)[0]
         trZ     = obspy.read(fnamez)[0]
         trP     = obspy.read(fnamep)[0]
         
         if abs(tr1.stats.delta - targetdt) > 1e-3 or abs(tr2.stats.delta - targetdt) > 1e-3 or \
             abs(trZ.stats.delta - targetdt) > 1e-3 or abs(trP.stats.delta - targetdt) > 1e-3:
             raise ValueError('!!! CHECK fs :'+ self.staid)
         else:
             tr1.stats.delta     = targetdt
             tr2.stats.delta     = targetdt
             trP.stats.delta     = targetdt
             trZ.stats.delta     = targetdt
         # # # if np.all(tr1.data == 0.) or np.all(tr2.data == 0.) or np.all(trZ.data == 0.) or np.all(trP.data == 0.):
         # # #     stime   += 86400.
         # # #     continue
         tr1.trim(starttime = stimetr, endtime = stimetr + 8400.*10-1)
         tr2.trim(starttime = stimetr, endtime = stimetr + 8400.*10-1)
         trZ.trim(starttime = stimetr, endtime = stimetr + 8400.*10-1)
         trP.trim(starttime = stimetr, endtime = stimetr + 8400.*10-1)
         
         # # # print (self.staid)
         if np.all(trP.data == 0.) and not (np.all(tr1.data == 0.) or np.all(tr2.data == 0.)):
             self.stanoise   += DayNoise(tr1=tr1, tr2=tr2, trZ=trZ, trP=obspy.Trace(), overlap=self.overlap, window = self.window)
             self.out_dtype  = 'Z2-1'
         elif (np.all(tr1.data == 0.) or np.all(tr2.data == 0.)) and (not np.all(trP.data == 0.)):
             self.stanoise   += DayNoise(tr1=obspy.Trace(), tr2=obspy.Trace(), trZ=trZ, trP=trP, overlap=self.overlap, window = self.window)
             self.out_dtype  = 'ZP'
         elif (not (np.all(tr1.data == 0.) or np.all(tr2.data == 0.))) and (not np.all(trP.data == 0.)):
             self.stanoise   += DayNoise(tr1=tr1, tr2=tr2, trZ=trZ, trP=trP, overlap=self.overlap, window = self.window)
             self.out_dtype  = 'ZP-21'
         else:
             stime   += 86400.
             continue
         stime   += 86400.
         Nday    += 1
     if Nday <= 1:
         return False
     self.stanoise.QC_sta_spectra()
     self.stanoise.average_sta_spectra()
     self.tfnoise= TFNoise(self.stanoise)
     self.tfnoise.transfer_func()
     return True
Beispiel #25
0
import obspy
from obspy.core.util.geodetics import gps2DistAzimuth
import numpy as np

from pyasdf import ASDFDataSet

ds = ASDFDataSet("./observed.h5")

event = ds.events[0]

origin = event.preferred_origin() or event.origins[0]
event_latitude = origin.latitude
event_longitude = origin.longitude

# Figure out these parameters somehonw!
starttime = obspy.UTCDateTime("2010-03-11T06:22:19.021324Z")
npts = 5708
sampling_rate = 1.0


# Loop over both period sets. This will result in two files. It could also be
# saved to the same file.
for min_period, max_period in [(27.0, 60.0)]:
    f2 = 1.0 / max_period
    f3 = 1.0 / min_period
    f1 = 0.8 * f2
    f4 = 1.2 * f3
    pre_filt = (f1, f2, f3, f4)

    def process_function(st, inv):
        st.detrend("linear")
import obspy
import sys
sys.path.append('FileSetObjects')
import fileSet as fs
import regularFileSet as rfs
import datetime as dt

# coefficients for spectrum and times of interest and channels of interest
secondsPerFile = 60
intervalWidthSec = 50  # 50 second intervals
intervalStartSpaceSec = 10  # new interval starts every 10 seconds
startTimeObspy = obspy.UTCDateTime("2016-09-03T12:00:54.932000Z")
startTime = dt.datetime(2016, 9, 3, 12, 0, 54, 932 * 1000)
endTimeObspy = obspy.UTCDateTime("2016-09-03T12:21:54.932000Z")
endTime = dt.datetime(2016, 9, 3, 12, 21, 54, 932 * 1000)
startPlotTime = dt.datetime(2016, 9, 3, 12, 2, 44)

# coefficients for channels of interest
nChannelsTotal = 620
startCh = 15
endCh = 305
ignoreChannels = [107, 280, 285]
# setup spectrum channel list with three sections of channels that don't have loud noises during any part of the earthquake record time
channelsSpec = range(30, 55)
for ch in range(80, 100):
    channelsSpec.append(ch)
for ch in range(165, 305):
    channelsSpec.append(ch)

# setup of filenames
parts = [
Beispiel #27
0
    def test_reading_station_file(self):
        """
        Test reading a file at the station level.
        """
        # Manually create an expected Inventory object.
        expected_inv = Inventory(
            source=None,
            networks=[
                Network(
                    code="TA",
                    stations=[
                        Station(
                            code="A04A",
                            latitude=48.7197,
                            longitude=-122.707,
                            elevation=23.0,
                            site=Site(name="Legoe Bay, Lummi Island, WA, USA"),
                            start_date=obspy.UTCDateTime(
                                "2004-09-19T00:00:00"),
                            end_date=obspy.UTCDateTime("2008-02-19T23:59:59")),
                        Station(
                            code="A04D",
                            latitude=48.7201,
                            longitude=-122.7063,
                            elevation=13.0,
                            site=Site(name="Lummi Island, WA, USA"),
                            start_date=obspy.UTCDateTime(
                                "2010-08-18T00:00:00"),
                            end_date=obspy.UTCDateTime("2599-12-31T23:59:59"))
                    ]),
                Network(
                    code="TR",
                    stations=[
                        Station(
                            code="ALNG",
                            latitude=10.1814,
                            longitude=-61.6883,
                            elevation=10.0,
                            site=Site(name="Trinidad, Point Fortin"),
                            start_date=obspy.UTCDateTime(
                                "2000-01-01T00:00:00"),
                            end_date=obspy.UTCDateTime("2599-12-31T23:59:59"))
                    ])
            ])

        # Read from a filename.
        filename = os.path.join(self.data_dir, "station_level_fdsn.txt")
        inv = read_fdsn_station_text_file(filename)
        inv_obs = obspy.read_inventory(filename)

        # Copy creation date as it will be slightly different otherwise.
        inv.created = expected_inv.created
        inv_obs.created = expected_inv.created
        self.assertEqual(inv, expected_inv)
        self.assertEqual(inv_obs, expected_inv)

        # Read from open file in text mode.
        with open(filename, "rt", encoding="utf8") as fh:
            inv = read_fdsn_station_text_file(fh)
            fh.seek(0, 0)
            inv_obs = obspy.read_inventory(fh)
        inv.created = expected_inv.created
        inv_obs.created = expected_inv.created
        self.assertEqual(inv, expected_inv)
        self.assertEqual(inv_obs, expected_inv)

        # Read from open file in binary mode.
        with open(filename, "rb") as fh:
            inv = read_fdsn_station_text_file(fh)
            fh.seek(0, 0)
            inv_obs = obspy.read_inventory(fh)
        inv.created = expected_inv.created
        inv_obs.created = expected_inv.created
        self.assertEqual(inv, expected_inv)
        self.assertEqual(inv_obs, expected_inv)

        # Read from StringIO.
        with open(filename, "rt", encoding="utf8") as fh:
            with io.StringIO(fh.read()) as buf:
                buf.seek(0, 0)
                inv = read_fdsn_station_text_file(buf)
                buf.seek(0, 0)
                inv_obs = obspy.read_inventory(buf)
        inv.created = expected_inv.created
        inv_obs.created = expected_inv.created
        self.assertEqual(inv, expected_inv)
        self.assertEqual(inv_obs, expected_inv)

        # Read from BytesIO.
        with open(filename, "rb") as fh:
            with io.BytesIO(fh.read()) as buf:
                buf.seek(0, 0)
                inv = read_fdsn_station_text_file(buf)
                buf.seek(0, 0)
                inv_obs = obspy.read_inventory(buf)
        inv.created = expected_inv.created
        inv_obs.created = expected_inv.created
        self.assertEqual(inv, expected_inv)
        self.assertEqual(inv_obs, expected_inv)
Beispiel #28
0
# with open(outfname, 'w') as fid:
#     while(stime <= etime):
#         fid.writelines(str(stime.year)+' '+str(stime.month)+'\n')
#         try:
#             stime.month += 1
#         except ValueError:
#             stime.year  += 1
#             stime.month = 1

import os
import obspy
import glob
datadir = '/backup/leon/COR_USCON_dir/seed_data'
start_date = '20130101'
end_date = '20151231'
stime = obspy.UTCDateTime(start_date)
etime = obspy.UTCDateTime(end_date)
monthdict = {
    1: 'JAN',
    2: 'FEB',
    3: 'MAR',
    4: 'APR',
    5: 'MAY',
    6: 'JUN',
    7: 'JUL',
    8: 'AUG',
    9: 'SEP',
    10: 'OCT',
    11: 'NOV',
    12: 'DEC'
}
Beispiel #29
0
    def test_reading_unicode_file(self):
        """
        Tests reading a file with non ASCII characters.
        """
        # Manually create an expected Inventory object.
        expected_inv = Inventory(
            source=None,
            networks=[
                Network(
                    code="PR",
                    stations=[
                        Station(
                            code="CTN1",
                            latitude=18.43718,
                            longitude=-67.1303,
                            elevation=10.0,
                            site=Site(name="CATA¿O DEFENSA CIVIL"),
                            start_date=obspy.UTCDateTime(
                                "2004-01-27T00:00:00"),
                            end_date=obspy.UTCDateTime("2599-12-31T23:59:59"))
                    ])
            ])

        # Read from a filename.
        filename = os.path.join(self.data_dir, "unicode_example_fdsn.txt")
        inv = read_fdsn_station_text_file(filename)
        inv_obs = obspy.read_inventory(filename)

        # Copy creation date as it will be slightly different otherwise.
        inv.created = expected_inv.created
        inv_obs.created = expected_inv.created
        self.assertEqual(inv, expected_inv)
        self.assertEqual(inv_obs, expected_inv)

        # Read from open file in text mode.
        with open(filename, "rt", encoding="utf8") as fh:
            inv = read_fdsn_station_text_file(fh)
            fh.seek(0, 0)
            inv_obs = obspy.read_inventory(fh)
        inv.created = expected_inv.created
        inv_obs.created = expected_inv.created
        self.assertEqual(inv, expected_inv)
        self.assertEqual(inv_obs, expected_inv)

        # Read from open file in binary mode.
        with open(filename, "rb") as fh:
            inv = read_fdsn_station_text_file(fh)
            fh.seek(0, 0)
            inv_obs = obspy.read_inventory(fh)
        inv.created = expected_inv.created
        inv_obs.created = expected_inv.created
        self.assertEqual(inv, expected_inv)
        self.assertEqual(inv_obs, expected_inv)

        # Read from StringIO.
        with open(filename, "rt", encoding="utf8") as fh:
            with io.StringIO(fh.read()) as buf:
                buf.seek(0, 0)
                inv = read_fdsn_station_text_file(buf)
                buf.seek(0, 0)
                inv_obs = obspy.read_inventory(buf)
        inv.created = expected_inv.created
        inv_obs.created = expected_inv.created
        self.assertEqual(inv, expected_inv)
        self.assertEqual(inv_obs, expected_inv)

        # Read from BytesIO.
        with open(filename, "rb") as fh:
            with io.BytesIO(fh.read()) as buf:
                buf.seek(0, 0)
                inv = read_fdsn_station_text_file(buf)
                buf.seek(0, 0)
                inv_obs = obspy.read_inventory(buf)
        inv.created = expected_inv.created
        inv_obs.created = expected_inv.created
        self.assertEqual(inv, expected_inv)
        self.assertEqual(inv_obs, expected_inv)
Beispiel #30
0
class TestFilterInventoryByAvailability:
    """Ensure that only times in the stations get used in get_bulk_args call."""

    t0 = obspy.UTCDateTime("2015-12-01")
    t1 = obspy.UTCDateTime("2016-01-01")
    t2 = obspy.UTCDateTime("2016-02-01")

    # fixtures
    @pytest.fixture
    def altered_inv(self):
        """ return an stations with one enddate changed to a later date """
        df = stations_to_df(obspy.read_inventory())
        df.loc[:, "start_date"] = self.t0
        df.loc[:, "end_date"] = self.t1
        df.loc[0, "end_date"] = self.t2
        return df

    @pytest.fixture
    def inv_with_none(self):
        """ return an stations with one enddate changed to None """
        df = stations_to_df(obspy.read_inventory())
        df.loc[:, "start_date"] = self.t0
        df.loc[:, "end_date"] = self.t1
        df.loc[0, "end_date"] = None
        return df

    @pytest.fixture
    def bulk_arg_later_time(self, altered_inv):
        """Return bulk args for latter time test."""
        fetcher = Fetcher(None, stations=altered_inv)
        return fetcher._get_bulk_args(starttime=self.t1 + 10, endtime=self.t2)

    @pytest.fixture
    def bulk_arg_none_end_date(self, inv_with_none):
        """ return the bulk args from an inv with None endate """
        fetcher = Fetcher(None, stations=inv_with_none)
        return fetcher._get_bulk_args(starttime=self.t0, endtime=self.t1)

    @pytest.fixture
    def fetcher(self, altered_inv, bing_fetcher):
        """ return a fetcher with the modified times """
        return Fetcher(bing_fetcher.waveform_client, stations=altered_inv)

    # tests
    def test_bulk_arg_is_limited(self, bulk_arg_later_time, altered_inv):
        """
        Ensure bulk arg doesn't include times the stations doesnt
        have data.
        """
        assert len(bulk_arg_later_time) == 1
        ba = bulk_arg_later_time[0]
        ser = altered_inv.iloc[0]
        assert ba[0] == ser.network
        assert ba[1] == ser.station
        assert ba[3] == ser.channel

    def test_none_endtimes_are_used(self, bulk_arg_none_end_date,
                                    inv_with_none):
        """ ensure any channels with enddates of None are not filtered out """
        assert len(bulk_arg_none_end_date) == len(inv_with_none)

    def test_empty_stream_from_before_start(self, fetcher):
        """
        Ensure when data is requested before stations starttime that an
        empty string is returned.
        """
        st = fetcher(obspy.UTCDateTime("1970-01-01"), 10, 40)
        assert isinstance(st, obspy.Stream)
        assert not len(st)