Ejemplo n.º 1
0
    def getWaveform(self, network, station, location, channel, starttime,
                    endtime, format="MSEED"):
        """
        Retrieves waveform data from the NERIES Web service and returns a ObsPy
        Stream object.

        :type network: str
        :param network: Network code, e.g. ``'BW'``.
        :type station: str
        :param station: Station code, e.g. ``'MANZ'``.
        :type location: str
        :param location: Location code, e.g. ``'01'``. Location code may
            contain wild cards.
        :type channel: str
        :param channel: Channel code, e.g. ``'EHE'``. . Channel code may
            contain wild cards.
        :type starttime: :class:`~obspy.core.utcdatetime.UTCDateTime`
        :param starttime: Start date and time.
        :type endtime: :class:`~obspy.core.utcdatetime.UTCDateTime`
        :param endtime: End date and time.
        :type format: ``'FSEED'`` or ``'MSEED'``, optional
        :param format: Output format. Either as full SEED (``'FSEED'``) or
            Mini-SEED (``'MSEED'``) volume. Defaults to ``'MSEED'``.
        :return: ObsPy :class:`~obspy.core.stream.Stream` object.

        .. rubric:: Example

        >>> from obspy.neries import Client
        >>> client = Client(user='******')
        >>> dt = UTCDateTime("2009-04-01T00:00:00")
        >>> st = client.getWaveform("NL", "WIT", "", "BH*", dt, dt+30)
        >>> print st  # doctest: +ELLIPSIS
        3 Trace(s) in Stream:
        NL.WIT..BHZ | 2009-04-01T00:00:00.010200Z - ... | 40.0 Hz, 1201 samples
        NL.WIT..BHN | 2009-04-01T00:00:00.010200Z - ... | 40.0 Hz, 1201 samples
        NL.WIT..BHE | 2009-04-01T00:00:00.010200Z - ... | 40.0 Hz, 1201 samples
        """
        tf = NamedTemporaryFile()
        self.saveWaveform(tf._fileobj, network, station, location, channel,
                          starttime, endtime, format=format)
        # read stream using obspy.mseed
        tf.seek(0)
        try:
            stream = read(tf.name, 'MSEED')
        except:
            stream = Stream()
        tf.close()
        # remove temporary file:
        try:
            os.remove(tf.name)
        except:
            pass
        # trim stream
        stream.trim(starttime, endtime)
        return stream
Ejemplo n.º 2
0
 def test_read_and_write(self):
     """
     Writes, reads and compares files created via libgse2.
     """
     gse2file = os.path.join(self.path, 'loc_RNON20040609200559.z')
     with open(gse2file, 'rb') as f:
         header, data = libgse2.read(f)
     with NamedTemporaryFile() as f:
         # raises "UserWarning: Bad value in GSE2 header field"
         with warnings.catch_warnings():
             warnings.simplefilter('ignore', UserWarning)
             libgse2.write(header, data, f)
         f.flush()
         with open(f.name, 'rb') as f2:
             newheader, newdata = libgse2.read(f2)
     self.assertEqual(header, newheader)
     np.testing.assert_equal(data, newdata)
Ejemplo n.º 3
0
    def test_merge_sac_obspy_headers(self):
        """
        Test that manually setting a set of SAC headers not related
        to validity or reference time on Trace.stats.sac is properly merged
        with the Trace.stats header. Issue 1285.
        """
        tr = Trace(data=np.arange(30))
        o = 10.0
        tr.stats.sac = {'o': o}

        with NamedTemporaryFile() as tf:
            tempfile = tf.name
            tr.write(tempfile, format='SAC')
            tr1 = read(tempfile)[0]

        self.assertEqual(tr1.stats.starttime, tr.stats.starttime)
        self.assertEqual(tr1.stats.sac.o, o)
Ejemplo n.º 4
0
    def test_valid_sac_from_minimal_existing_sac_header(self):
        """
        An incomplete manually-produced SAC header should still produce a
        valid SAC file, including values from the ObsPy header.  Issue 1204.
        """
        tr = Trace(np.arange(100))
        t = UTCDateTime()
        tr.stats.starttime = t
        tr.stats.station = 'AAA'
        tr.stats.network = 'XX'
        tr.stats.channel = 'BHZ'
        tr.stats.location = '00'

        tr.stats.sac = AttribDict()
        tr.stats.sac.iztype = 9
        tr.stats.sac.nvhdr = 6
        tr.stats.sac.leven = 1
        tr.stats.sac.lovrok = 1
        tr.stats.sac.iftype = 1
        tr.stats.sac.stla = 1.
        tr.stats.sac.stlo = 2.

        with NamedTemporaryFile() as tf:
            tempfile = tf.name
            tr.write(tempfile, format='SAC')
            tr1 = read(tempfile)[0]

        # starttime made its way to SAC file
        nztimes, microsecond = utcdatetime_to_sac_nztimes(t)
        self.assertEqual(tr1.stats.sac.nzyear, nztimes['nzyear'])
        self.assertEqual(tr1.stats.sac.nzjday, nztimes['nzjday'])
        self.assertEqual(tr1.stats.sac.nzhour, nztimes['nzhour'])
        self.assertEqual(tr1.stats.sac.nzmin, nztimes['nzmin'])
        self.assertEqual(tr1.stats.sac.nzsec, nztimes['nzsec'])
        self.assertEqual(tr1.stats.sac.nzmsec, nztimes['nzmsec'])
        self.assertEqual(tr1.stats.sac.kstnm, 'AAA')
        self.assertEqual(tr1.stats.sac.knetwk, 'XX')
        self.assertEqual(tr1.stats.sac.kcmpnm, 'BHZ')
        self.assertEqual(tr1.stats.sac.khole, '00')
        self.assertEqual(tr1.stats.sac.iztype, 9)
        self.assertEqual(tr1.stats.sac.nvhdr, 6)
        self.assertEqual(tr1.stats.sac.leven, 1)
        self.assertEqual(tr1.stats.sac.lovrok, 1)
        self.assertEqual(tr1.stats.sac.iftype, 1)
        self.assertEqual(tr1.stats.sac.stla, 1.0)
        self.assertEqual(tr1.stats.sac.stlo, 2.0)
Ejemplo n.º 5
0
    def test_write_with_date_time_before_1970(self):
        """
        Write an stream via libmseed with a datetime before 1970.

        This test depends on the platform specific localtime()/gmtime()
        function.
        """
        # create trace
        tr = Trace(data=np.empty(1000))
        tr.stats.starttime = UTCDateTime("1969-01-01T00:00:00")
        # write file
        with NamedTemporaryFile() as tf:
            tempfile = tf.name
            _write_mseed(Stream([tr]), tempfile, format="MSEED")
            # read again
            stream = _read_mseed(tempfile)
            stream.verify()
Ejemplo n.º 6
0
 def test_saveWaveform(self):
     """
     Testing simple waveform file save method.
     """
     # file identical to file retrieved via web interface
     client = Client()
     start = UTCDateTime("2010-02-27T06:30:00")
     end = UTCDateTime("2010-02-27T06:31:00")
     origfile = os.path.join(self.path, 'data', 'IU.ANMO.00.BHZ.mseed')
     with NamedTemporaryFile() as tf:
         tempfile = tf.name
         client.saveWaveform(tempfile, "IU", "ANMO", "00", "BHZ", start,
                             end)
         self.assertTrue(filecmp.cmp(origfile, tempfile))
     # no data raises an exception
     self.assertRaises(Exception, client.saveWaveform, "YY", "XXXX", "00",
                       "BHZ", start, end)
Ejemplo n.º 7
0
 def test_invalidEncoding(self):
     """
     An invalid encoding should raise an exception.
     """
     npts = 6000
     np.random.seed(815)  # make test reproducible
     with NamedTemporaryFile() as tf:
         tempfile = tf.name
         data = np.random.randint(-1000, 1000, npts).astype(np.int32)
         st = Stream([Trace(data=data)])
         # Writing should fail with invalid record lengths.
         # Wrong number.
         self.assertRaises(ValueError, _write_mseed, st, tempfile,
                           format="MSEED", encoding=2)
         # Wrong Text.
         self.assertRaises(ValueError, _write_mseed, st, tempfile,
                           format="MSEED", encoding='FLOAT_64')
Ejemplo n.º 8
0
 def test_writing_new_sampling_rate(self):
     """
     Setting a new sample rate works.
     """
     file = os.path.join(self.path, '1.sgy_first_trace')
     segy = _read_segy(file)
     segy.stats.textual_file_header = \
         _patch_header(segy.stats.textual_file_header)
     segy[0].stats.sampling_rate = 20
     with NamedTemporaryFile() as tf:
         outfile = tf.name
         _write_segy(segy, outfile)
         new_segy = _read_segy(outfile)
     self.assertEqual(new_segy[0].stats.sampling_rate, 20)
     # The same with the Seismic Unix file.
     file = os.path.join(self.path, '1.su_first_trace')
     _read_su(file)
    def process_GET(self, request):
        """
        Function that will be called upon receiving a GET request for the
        aforementioned URL.
        """
        # Parse the given parameters.
        event_id = request.args0.get("event", None)
        channel_id = request.args0.get("channel_id", None)
        station_id = request.args0.get("station_id", None)
        tag = request.args0.get("tag", "")
        format = request.args0.get("format", None)

        # An event id is obviously needed.
        if event_id is None:
            msg = ("No event parameter passed. Every waveform "
                "is bound to an existing event.")
            raise InvalidParameterError(msg)

        if event_id is not None and not event_exists(event_id, self.env):
            msg = "The given event resource name '%s' " % event_id
            msg += "is not known to SeisHub."
            raise InvalidParameterError(msg)

        # Returns different things based on parameter combinations.
        # Return all waveforms available for a given event.
        if channel_id is None and station_id is None and event_id is not None:
            return self.getListForEvent(event_id, request)
        # Return all waveforms available for a given event and station id.
        elif station_id is not None and event_id is not None:
            return self.getListForStationAndEvent(event_id, station_id,
                request)

        # At this step format will mean a waveform output format.
        acceptable_formats = ["mseed", "sac", "gse2", "segy", "raw", "json"]
        if format and format.lower() not in acceptable_formats:
            msg = "'%s' is an unsupported format. Supported formats: %s" % \
                (format, ", ".join(acceptable_formats))
            raise InvalidParameterError(msg)

        if channel_id is None:
            msg = ("To download a waveform, 'channel_id' to be specified.")
            raise InvalidParameterError(msg)

        split_channel = channel_id.split(".")
        if len(split_channel) != 4:
            msg = "Invalid 'channel_id'. Needs to be NET.STA.LOC.CHAN."
            raise InvalidParameterError(msg)

        network, station, location, channel = split_channel

        session = self.env.db.session(bind=self.env.db.engine)
        station_id = get_station_id(network, station, session)
        if station_id is False:
            session.close()
            msg = "Could not find station %s.%s in the database" % \
                (network, station)
            raise InvalidParameterError(msg)

        query = session.query(WaveformChannelObject)\
            .join(ChannelObject)\
            .filter(WaveformChannelObject.event_resource_id == event_id)\
            .filter(WaveformChannelObject.tag == tag)\
            .filter(ChannelObject.location == location)\
            .filter(ChannelObject.channel == channel)\
            .filter(ChannelObject.station_id == station_id)

        try:
            result = query.one()
        except sqlalchemy.orm.exc.NoResultFound:
            session.close()
            msg = "No matching data found in the database."
            raise NotFoundError(msg)

        if format and format.lower() == "raw":
            with open(result.filepath.filepath, "rb") as open_file:
                data = open_file.read()
            # Set the corresponding headers.
            request.setHeader("content-type", "application/octet-stream")
            filename = os.path.basename(result.filepath.filepath)\
                .encode("utf-8")
            request.setHeader("content-disposition", "attachment; filename=%s"
                % filename)
            return data

        chan = result.channel
        stat = chan.station
        network = stat.network
        station = stat.station
        location = chan.location
        channel = chan.channel
        starttime = UTCDateTime(result.starttime) if result.starttime else None
        endtime = UTCDateTime(result.endtime) if result.endtime else None
        default_format = result.format

        # Read and filter the file.
        st = read(result.filepath.filepath).select(network=network,
            station=station, location=location, channel=channel)
        session.close()

        # Now attempt to find the correct trace in case of more then one trace.
        # This should enable multicomponent files.
        selected_trace = None
        for tr in st:
            if (starttime and abs(tr.stats.starttime - starttime) > 1) or \
                    (endtime and abs(tr.stats.endtime - endtime) > 1):
                continue
            selected_trace = tr
            break

        if selected_trace is None:
            msg = "Could not find the corresponding waveform file."
            raise InternalServerError(msg)

        # Deal with json format conversion.
        if format and format == "json":
            output = {
                "channel": selected_trace.id,
                "sampling_rate": selected_trace.stats.sampling_rate,
                "npts": selected_trace.stats.npts,
                "data": []
            }
            time = selected_trace.stats.starttime
            delta = selected_trace.stats.delta
            for value in selected_trace.data:
                output["data"].append([time.isoformat(), float(value)])
                time += delta
            request.setHeader('content-type',
                'application/json; charset=UTF-8')
            return json.dumps(output)

        # XXX: Fix some ObsPy modules to be able to write to memory files.
        tempfile = NamedTemporaryFile()
        if format:
            default_format = format
        selected_trace.write(tempfile.name, format=default_format)
        with open(tempfile.name, "rb") as open_file:
            data = open_file.read()
        tempfile.close()
        os.remove(tempfile.name)

        # Set the corresponding headers.
        request.setHeader("content-type", "application/octet-stream")
        filename = "%s.%s" % (selected_trace.id, default_format.lower())
        filename = filename.encode("utf-8")
        request.setHeader("content-disposition", "attachment; filename=%s" %
            filename)
        return data