def _parse_data(data, data_type): """ Simple function to read data contained in a StringIO object to a NumPy array. :type data: io.StringIO :param data: The actual data. :type data_type: str :param data_type: The data type of the expected data. Currently supported are 'INTEGER' and 'FLOAT'. """ if data_type == "INTEGER": dtype = np.int_ elif data_type == "FLOAT": dtype = np.float32 else: raise NotImplementedError # Seek to the beginning of the StringIO. data.seek(0) # Data will always be a StringIO. Avoid to send empty StringIOs to # numpy.readtxt() which raises a warning. if len(data.read(1)) == 0: return np.array([], dtype=dtype) data.seek(0) return loadtxt(data, dtype=dtype, ndmin=1)
def _parse_data(data, data_type): """ Simple function to read data contained in a StringIO object to a numpy array. :type data: StringIO.StringIO object. :param data: The actual data. :type data_type: String :param data_type: The data type of the expected data. Currently supported are 'INTEGER' and 'FLOAT'. """ if data_type == "INTEGER": dtype = "int" elif data_type == "FLOAT": dtype = "float32" else: raise NotImplementedError # Seek to the beginning of the StringIO. data.seek(0) # Data will always be a StringIO. Avoid to send empty StringIOs to # numpy.readtxt() which raises a warning. if len(data.read(1)) == 0: return np.array([], dtype=dtype) data.seek(0) return loadtxt(data, dtype=dtype, ndlim=1)
def _parse_data(data, data_type): """ Simple function to read data contained in a StringIO object to a numpy array. :type data: StringIO.StringIO object. :param data: The actual data. :type data_type: String :param data_type: The data type of the expected data. Currently supported are 'INTEGER' and 'FLOAT'. """ if data_type == "INTEGER": dtype = "int" elif data_type == "FLOAT": dtype = "float32" else: raise NotImplementedError # Seek to the beginning of the StringIO. data.seek(0) # Data will always be a StringIO. Avoid to send empty StringIOs to # numpy.readtxt() which raises a warning. if not data.buf: return np.array([], dtype=dtype) return loadtxt(data, dtype=dtype, ndlim=1)
def readSLIST(filename, headonly=False, **kwargs): # @UnusedVariable """ Reads a ASCII SLIST file and returns an ObsPy Stream object. .. warning:: This function should NOT be called directly, it registers via the ObsPy :func:`~obspy.core.stream.read` function, call this instead. :type filename: str :param filename: ASCII file to be read. :type headonly: bool, optional :param headonly: If set to True, read only the head. This is most useful for scanning available data in huge (temporary) data sets. :rtype: :class:`~obspy.core.stream.Stream` :return: A ObsPy Stream object. .. rubric:: Example >>> from obspy.core import read >>> st = read('/path/to/slist.ascii') """ fh = open(filename, 'rt') # read file and split text into channels headers = {} key = None for line in fh: if line.isspace(): # blank line continue elif line.startswith('TIMESERIES'): # new header line key = line headers[key] = StringIO() elif headonly: # skip data for option headonly continue elif key: # data entry - may be written in multiple columns headers[key].write(line.strip() + ' ') fh.close() # create ObsPy stream object stream = Stream() for header, data in headers.iteritems(): # create Stats stats = Stats() parts = header.replace(',', '').split() temp = parts[1].split('_') stats.network = temp[0] stats.station = temp[1] stats.location = temp[2] stats.channel = temp[3] stats.sampling_rate = parts[4] # quality only used in MSEED stats.mseed = AttribDict({'dataquality': temp[4]}) stats.ascii = AttribDict({'unit': parts[-1]}) stats.starttime = UTCDateTime(parts[6]) stats.npts = parts[2] if headonly: # skip data stream.append(Trace(header=stats)) else: # parse data data.seek(0) if parts[8] == 'INTEGER': data = loadtxt(data, dtype='int', ndlim=1) elif parts[8] == 'FLOAT': data = loadtxt(data, dtype='float32', ndlim=1) else: raise NotImplementedError stream.append(Trace(data=data, header=stats)) return stream
def readASC(filename, headonly=False, skip=0, delta=None, length=None, **kwargs): # @UnusedVariable """ Reads a Seismic Handler ASCII file and returns an ObsPy Stream object. .. warning:: This function should NOT be called directly, it registers via the ObsPy :func:`~obspy.core.stream.read` function, call this instead. :type filename: str :param filename: ASCII file to be read. :type headonly: bool, optional :param headonly: If set to True, read only the head. This is most useful for scanning available data in huge (temporary) data sets. :type skip: int, optional :param skip: Number of lines to be skipped from top of file. If defined only one trace is read from file. :type delta: float, optional :param delta: If "skip" is used, "delta" defines sample offset in seconds. :type length: int, optional :param length: If "skip" is used, "length" defines the number of values to be read. :rtype: :class:`~obspy.core.stream.Stream` :return: A ObsPy Stream object. .. rubric:: Example >>> from obspy.core import read >>> st = read("/path/to/QFILE-TEST-ASC.ASC") >>> st # doctest: +ELLIPSIS <obspy.core.stream.Stream object at 0x...> >>> print(st) # doctest: +ELLIPSIS 3 Trace(s) in Stream: .TEST..BHN | 2009-10-01T12:46:01.000000Z - ... | 20.0 Hz, 801 samples .TEST..BHE | 2009-10-01T12:46:01.000000Z - ... | 20.0 Hz, 801 samples .WET..HHZ | 2010-01-01T01:01:05.999000Z - ... | 100.0 Hz, 4001 samples """ fh = open(filename, 'rt') # read file and split text into channels channels = [] headers = {} data = StringIO() for line in fh.readlines()[skip:]: if line.isspace(): # blank line # check if any data fetched yet if len(headers) == 0 and data.len == 0: continue # append current channel data.seek(0) channels.append((headers, data)) # create new channel headers = {} data = StringIO() if skip: # if skip is set only one trace is read, everything else makes # no sense. break continue elif line[0].isalpha(): # header entry key, value = line.split(':', 1) key = key.strip() value = value.strip() headers[key] = value elif not headonly: # data entry - may be written in multiple columns data.write(line.strip() + ' ') fh.close() # create ObsPy stream object stream = Stream() # custom header custom_header = {} if delta: custom_header["delta"] = delta if length: custom_header["npts"] = length for headers, data in channels: # create Stats header = Stats(custom_header) header['sh'] = {} channel = [' ', ' ', ' '] # generate headers for key, value in headers.iteritems(): if key == 'DELTA': header['delta'] = float(value) elif key == 'LENGTH': header['npts'] = int(value) elif key == 'CALIB': header['calib'] = float(value) elif key == 'STATION': header['station'] = value elif key == 'COMP': channel[2] = value[0] elif key == 'CHAN1': channel[0] = value[0] elif key == 'CHAN2': channel[1] = value[0] elif key == 'START': # 01-JAN-2009_01:01:01.0 # 1-OCT-2009_12:46:01.000 header['starttime'] = toUTCDateTime(value) else: # everything else gets stored into sh entry if key in SH_KEYS_INT: header['sh'][key] = int(value) elif key in SH_KEYS_FLOAT: header['sh'][key] = float(value) else: header['sh'][key] = value # set channel code header['channel'] = ''.join(channel) if headonly: # skip data stream.append(Trace(header=header)) else: # read data data = loadtxt(data, dtype='float32', ndlim=1) # cut data if requested if skip and length: data = data[:length] # use correct value in any case header["npts"] = len(data) stream.append(Trace(data=data, header=header)) return stream
def evalresp(self, network, station, location, channel, time=UTCDateTime(), minfreq=0.00001, maxfreq=None, nfreq=200, units='def', width=800, height=600, annotate=True, output='plot', filename=None, **kwargs): """ Low-level interface for `evalresp` Web service of IRIS (http://service.iris.edu/irisws/evalresp/) - release 1.0.0 (2011-08-11). This method evaluates instrument response information stored at the IRIS DMC and outputs ASCII data or `Bode Plots <https://en.wikipedia.org/wiki/Bode_plots>`_. :type network: str :param network: Network code, e.g. ``'IU'``. :type station: str :param station: Station code, e.g. ``'ANMO'``. :type location: str :param location: Location code, e.g. ``'00'``. Use ``'--'`` for empty location codes. :type channel: str :param channel: Channel code, e.g. ``'BHZ'``. :type time: :class:`~obspy.core.utcdatetime.UTCDateTime` :param time: Evaluate the response at the given time. If not specified, the current time is used. :type minfreq: float, optional :param minfreq: The minimum frequency (Hz) at which response will be evaluated. Must be positive and less than the ``maxfreq`` value. Defaults to ``0.00001`` Hz (1/day ~ 0.000012 Hz). :type maxfreq: float, optional :param maxfreq: The maximum frequency (Hz) at which response will be evaluated. Must be positive and greater than the ``minfreq`` value. Defaults to the channel sample-rate or the frequency of sensitivity, which ever is larger. :type nfreq: int, optional :param nfreq: Number frequencies at which response will be evaluated. Must be a positive integer no greater than ``10000``. The instrument response is evaluated on a equally spaced logarithmic scale. Defaults to ``200``. :type units: str, optional :param units: Output Unit. Defaults to ``'def'``. ``'def'`` default units indicated in response metadata ``'dis'`` converts to units of displacement ``'vel'`` converts to units of velocity ``'acc'`` converts to units of acceleration If units are not specified, then the units will default to those indicated in the response metadata :type width: int, optional :param width: The width of the generated plot. Defaults to ``800``. Can only be used with the ``output='plot'``, ``output='plot-amp'`` and ``output='plot-phase'`` options. Cannot be larger than ``5000`` and the product of width and height cannot be larger than ``6,000,000``. :type height: int, optional :param height: The height of the generated plot. Defaults to ``600``. Can only be used with the ``output='plot'``, ``output='plot-amp'`` and ``output='plot-phase'`` options. Cannot be larger than ``5000`` and the product of width and height cannot be larger than ``6,000,000``. :type annotate: bool, optional :param annotate: Can be either ``True`` or ``False``. Defaults to ``True``. * Draws vertical lines at the Nyquist frequency (one half the sample rate). * Draw a vertical line at the stage-zero frequency of sensitivity. * Draws a horizontal line at the stage-zero gain. Can only be used with the ``output='plot'``, ``output='plot-amp'`` and ``output='plot-phase'`` options. :type output: str :param output: Output Options. Defaults to ``'plot'``. ``'fap'`` Three column ASCII (frequency, amplitude, phase) ``'cs'`` Three column ASCII (frequency, real, imaginary) ``'plot'`` Amplitude and phase plot ``'plot-amp'`` Amplitude only plot ``'plot-phase'`` Phase only plot Plots are stored to the file system if the parameter ``filename`` is set, otherwise it will try to use matplotlib to directly plot the returned image. :type filename: str, optional :param filename: Name of a output file. If this parameter is given nothing will be returned. Default is ``None``. :rtype: :class:`numpy.ndarray`, str or `None` :returns: Returns either a NumPy :class:`~numpy.ndarray`, image string or nothing, depending on the ``output`` parameter. .. rubric:: Examples (1) Returning frequency, amplitude, phase of first point. >>> from obspy.clients.iris import Client >>> client = Client() >>> dt = UTCDateTime("2005-01-01") >>> data = client.evalresp("IU", "ANMO", "00", "BHZ", dt, ... output='fap') >>> data[0] # frequency, amplitude, phase of first point array([ 1.00000000e-05, 1.05599900e+04, 1.79200700e+02]) (2) Returning amplitude and phase plot. >>> from obspy.clients.iris import Client >>> client = Client() >>> dt = UTCDateTime("2005-01-01") >>> client.evalresp("IU", "ANMO", "00", "BHZ", dt) # doctest: +SKIP .. plot:: from obspy import UTCDateTime from obspy.clients.iris import Client client = Client() dt = UTCDateTime("2005-01-01") client.evalresp("IU", "ANMO", "00", "BHZ", dt) """ kwargs['network'] = str(network) kwargs['station'] = str(station) if location: kwargs['location'] = str(location)[0:2] else: kwargs['location'] = '--' kwargs['channel'] = str(channel) try: kwargs['time'] = UTCDateTime(time).format_IRIS_web_service() except: kwargs['time'] = time kwargs['minfreq'] = float(minfreq) if maxfreq: kwargs['maxfreq'] = float(maxfreq) kwargs['nfreq'] = int(nfreq) if units in ['def', 'dis', 'vel', 'acc']: kwargs['units'] = units else: kwargs['units'] = 'def' if output in ['fap', 'cs', 'plot', 'plot-amp', 'plot-phase']: kwargs['output'] = output else: kwargs['output'] = 'plot' # height, width and annotate work only for plots if 'plot' in output: kwargs['width'] = int(width) kwargs['height'] = int(height) kwargs['annotate'] = bool(annotate) data = self._fetch("evalresp", **kwargs) # check output if 'plot' in output: # image if filename is None: # ugly way to show an image from matplotlib import image import matplotlib.pyplot as plt # create new figure fig = plt.figure() # new axes using full window ax = fig.add_axes([0, 0, 1, 1]) # need temporary file for reading into matplotlib with NamedTemporaryFile() as tf: tf.write(data) # force matplotlib to use internal PNG reader. image.imread # will use PIL if available img = image._png.read_png(native_str(tf.name)) # add image to axis ax.imshow(img) # hide axes ax.axison = False # show plot plt.show() else: self._to_file_or_data(filename, data, binary=True) else: # ASCII data if filename is None: return loadtxt(io.BytesIO(data), ndmin=1) else: return self._to_file_or_data(filename, data, binary=True)
def evalresp(self, network, station, location, channel, time=UTCDateTime(), minfreq=0.00001, maxfreq=None, nfreq=200, units='def', width=800, height=600, annotate=True, output='plot', filename=None, **kwargs): """ Low-level interface for `evalresp` Web service of IRIS (http://service.iris.edu/irisws/evalresp/) - release 1.0.0 (2011-08-11). This method evaluates instrument response information stored at the IRIS DMC and outputs ASCII data or `Bode Plots <http://en.wikipedia.org/wiki/Bode_plots>`_. :type network: str :param network: Network code, e.g. ``'IU'``. :type station: str :param station: Station code, e.g. ``'ANMO'``. :type location: str :param location: Location code, e.g. ``'00'``. Use ``'--'`` for empty location codes. :type channel: str :param channel: Channel code, e.g. ``'BHZ'``. :type time: :class:`~obspy.core.utcdatetime.UTCDateTime` :param time: Evaluate the response at the given time. If not specified, the current time is used. :type minfreq: float, optional :param minfreq: The minimum frequency (Hz) at which response will be evaluated. Must be positive and less than the ``maxfreq`` value. Defaults to ``0.00001`` Hz (1/day ~ 0.000012 Hz). :type maxfreq: float, optional :param maxfreq: The maximum frequency (Hz) at which response will be evaluated. Must be positive and greater than the ``minfreq`` value. Defaults to the channel sample-rate or the frequency of sensitivity, which ever is larger. :type nfreq: int, optional :param nfreq: Number frequencies at which response will be evaluated. Must be a positive integer no greater than ``10000``. The instrument response is evaluated on a equally spaced logarithmic scale. Defaults to ``200``. :type units: str, optional :param units: Output Unit. Defaults to ``'def'``. ``'def'`` default units indicated in response metadata ``'dis'`` converts to units of displacement ``'vel'`` converts to units of velocity ``'acc'`` converts to units of acceleration If units are not specified, then the units will default to those indicated in the response metadata :type width: int, optional :param width: The width of the generated plot. Defaults to ``800``. Can only be used with the ``output='plot'``, ``output='plot-amp'`` and ``output='plot-phase'`` options. Cannot be larger than ``5000`` and the product of width and height cannot be larger than ``6,000,000``. :type height: int, optional :param height: The height of the generated plot. Defaults to ``600``. Can only be used with the ``output='plot'``, ``output='plot-amp'`` and ``output='plot-phase'`` options. Cannot be larger than ``5000`` and the product of width and height cannot be larger than ``6,000,000``. :type annotate: bool, optional :param annotate: Can be either ``True`` or ``False``. Defaults to ``True``. * Draws vertical lines at the Nyquist frequency (one half the sample rate). * Draw a vertical line at the stage-zero frequency of sensitivity. * Draws a horizontal line at the stage-zero gain. Can only be used with the ``output='plot'``, ``output='plot-amp'`` and ``output='plot-phase'`` options. :type output: str :param output: Output Options. Defaults to ``'plot'``. ``'fap'`` Three column ASCII (frequency, amplitude, phase) ``'cs'`` Three column ASCII (frequency, real, imaginary) ``'plot'`` Amplitude and phase plot ``'plot-amp'`` Amplitude only plot ``'plot-phase'`` Phase only plot Plots are stored to the file system if the parameter ``filename`` is set, otherwise it will try to use matplotlib to directly plot the returned image. :type filename: str, optional :param filename: Name of a output file. If this parameter is given nothing will be returned. Default is ``None``. :rtype: :class:`numpy.ndarray`, str or `None` :returns: Returns either a NumPy :class:`~numpy.ndarray`, image string or nothing, depending on the ``output`` parameter. .. rubric:: Examples (1) Returning frequency, amplitude, phase of first point. >>> from obspy.iris import Client >>> client = Client() >>> dt = UTCDateTime("2005-01-01") >>> data = client.evalresp("IU", "ANMO", "00", "BHZ", dt, ... output='fap') >>> data[0] # frequency, amplitude, phase of first point array([ 1.00000000e-05, 1.05599900e+04, 1.79200700e+02]) (2) Returning amplitude and phase plot. >>> from obspy.iris import Client >>> client = Client() >>> dt = UTCDateTime("2005-01-01") >>> client.evalresp("IU", "ANMO", "00", "BHZ", dt) # doctest: +SKIP .. plot:: from obspy import UTCDateTime from obspy.iris import Client client = Client() dt = UTCDateTime("2005-01-01") client.evalresp("IU", "ANMO", "00", "BHZ", dt) """ kwargs['network'] = str(network) kwargs['station'] = str(station) if location: kwargs['location'] = str(location)[0:2] else: kwargs['location'] = '--' kwargs['channel'] = str(channel) try: kwargs['time'] = UTCDateTime(time).formatIRISWebService() except: kwargs['time'] = time kwargs['minfreq'] = float(minfreq) if maxfreq: kwargs['maxfreq'] = float(maxfreq) kwargs['nfreq'] = int(nfreq) if units in ['def', 'dis', 'vel', 'acc']: kwargs['units'] = units else: kwargs['units'] = 'def' if output in ['fap', 'cs', 'plot', 'plot-amp', 'plot-phase']: kwargs['output'] = output else: kwargs['output'] = 'plot' # height, width and annotate work only for plots if 'plot' in output: kwargs['width'] = int(width) kwargs['height'] = int(height) kwargs['annotate'] = bool(annotate) data = self._fetch("evalresp", **kwargs) # check output if 'plot' in output: # image if filename is None: # ugly way to show an image from matplotlib import image import matplotlib.pyplot as plt # create new figure fig = plt.figure() # new axes using full window ax = fig.add_axes([0, 0, 1, 1]) # need temporary file for reading into matplotlib with NamedTemporaryFile() as tf: tf.write(data) # force matplotlib to use internal PNG reader. image.imread # will use PIL if available img = image._png.read_png(native_str(tf.name)) # add image to axis ax.imshow(img) # hide axes ax.axison = False # show plot plt.show() else: self._toFileOrData(filename, data, binary=True) else: # ASCII data if filename is None: return loadtxt(io.BytesIO(data), ndmin=1) else: return self._toFileOrData(filename, data, binary=True)
def _read_asc(filename, headonly=False, skip=0, delta=None, length=None, **kwargs): # @UnusedVariable """ Reads a Seismic Handler ASCII file and returns an ObsPy Stream object. .. warning:: This function should NOT be called directly, it registers via the ObsPy :func:`~obspy.core.stream.read` function, call this instead. :type filename: str :param filename: ASCII file to be read. :type headonly: bool, optional :param headonly: If set to True, read only the head. This is most useful for scanning available data in huge (temporary) data sets. :type skip: int, optional :param skip: Number of lines to be skipped from top of file. If defined only one trace is read from file. :type delta: float, optional :param delta: If ``skip`` is used, ``delta`` defines sample offset in seconds. :type length: int, optional :param length: If ``skip`` is used, ``length`` defines the number of values to be read. :rtype: :class:`~obspy.core.stream.Stream` :return: A ObsPy Stream object. .. rubric:: Example >>> from obspy import read >>> st = read("/path/to/QFILE-TEST-ASC.ASC") >>> st # doctest: +ELLIPSIS <obspy.core.stream.Stream object at 0x...> >>> print(st) # doctest: +ELLIPSIS 3 Trace(s) in Stream: .TEST..BHN | 2009-10-01T12:46:01.000000Z - ... | 20.0 Hz, 801 samples .TEST..BHE | 2009-10-01T12:46:01.000000Z - ... | 20.0 Hz, 801 samples .WET..HHZ | 2010-01-01T01:01:05.999000Z - ... | 100.0 Hz, 4001 samples """ fh = open(filename, 'rt') # read file and split text into channels channels = [] headers = {} data = io.StringIO() for line in fh.readlines()[skip:]: if line.isspace(): # blank line # check if any data fetched yet if len(headers) == 0 and data.tell() == 0: continue # append current channel data.seek(0) channels.append((headers, data)) # create new channel headers = {} data = io.StringIO() if skip: # if skip is set only one trace is read, everything else makes # no sense. break continue elif line[0].isalpha(): # header entry key, value = line.split(':', 1) key = key.strip() value = value.strip() headers[key] = value elif not headonly: # data entry - may be written in multiple columns data.write(line.strip() + ' ') fh.close() # create ObsPy stream object stream = Stream() # custom header custom_header = {} if delta: custom_header["delta"] = delta if length: custom_header["npts"] = length for headers, data in channels: # create Stats header = Stats(custom_header) header['sh'] = {} channel = [' ', ' ', ' '] # generate headers for key, value in headers.items(): if key == 'DELTA': header['delta'] = float(value) elif key == 'LENGTH': header['npts'] = int(value) elif key == 'CALIB': header['calib'] = float(value) elif key == 'STATION': header['station'] = value elif key == 'COMP': channel[2] = value[0] elif key == 'CHAN1': channel[0] = value[0] elif key == 'CHAN2': channel[1] = value[0] elif key == 'START': # 01-JAN-2009_01:01:01.0 # 1-OCT-2009_12:46:01.000 header['starttime'] = to_utcdatetime(value) else: # everything else gets stored into sh entry if key in SH_KEYS_INT: header['sh'][key] = int(value) elif key in SH_KEYS_FLOAT: header['sh'][key] = float(value) else: header['sh'][key] = value # set channel code header['channel'] = ''.join(channel) if headonly: # skip data stream.append(Trace(header=header)) else: # read data data = loadtxt(data, dtype=np.float32, ndmin=1) # cut data if requested if skip and length: data = data[:length] # use correct value in any case header["npts"] = len(data) stream.append(Trace(data=data, header=header)) return stream