Source code for obspy.core.util.misc

# -*- coding: utf-8 -*-
"""
Various additional utilities for ObsPy.

:copyright:
    The ObsPy Development Team (devs@obspy.org)
:license:
    GNU Lesser General Public License, Version 3
    (http://www.gnu.org/copyleft/lesser.html)
"""
import warnings
import itertools
import numpy as np


# The following dictionary maps the first character of the channel_id to the
# lowest sampling rate this so called Band Code should be used for according
# to: SEED MANUAL p.124
# We use this e.g. in seihub.client.getWaveform to request two samples more on
# both start and end to cut to the samples that really are nearest to requested
# start/endtime afterwards.
BAND_CODE = {'F': 1000.0,
             'G': 1000.0,
             'D': 250.0,
             'C': 250.0,
             'E': 80.0,
             'S': 10.0,
             'H': 80.0,
             'B': 10.0,
             'M': 1.0,
             'L': 1.0,
             'V': 0.1,
             'U': 0.01,
             'R': 0.0001,
             'P': 0.000001,
             'T': 0.0000001,
             'Q': 0.00000001}


[docs]def guessDelta(channel): """ Estimate time delta in seconds between each sample from given channel name. :type channel: str :param channel: Channel name, e.g. ``'BHZ'`` or ``'H'`` :rtype: float :return: Returns ``0`` if band code is not given or unknown. .. rubric:: Example >>> print(guessDelta('BHZ')) 0.1 >>> print(guessDelta('H')) 0.0125 >>> print(guessDelta('XZY')) # doctest: +SKIP 0 """ try: return 1. / BAND_CODE[channel[0]] except: msg = "No or unknown channel id provided. Specifying a channel id " + \ "could lead to better selection of first/last samples of " + \ "fetched traces." warnings.warn(msg) return 0
[docs]def scoreatpercentile(a, per, limit=(), issorted=True): """ Calculates the score at the given per percentile of the sequence a. For example, the score at ``per=50`` is the median. If the desired quantile lies between two data points, we interpolate between them. If the parameter ``limit`` is provided, it should be a tuple (lower, upper) of two values. Values of ``a`` outside this (closed) interval will be ignored. .. rubric:: Examples >>> a = [1, 2, 3, 4] >>> scoreatpercentile(a, 25) 1.75 >>> scoreatpercentile(a, 50) 2.5 >>> scoreatpercentile(a, 75) 3.25 >>> a = [6, 47, 49, 15, 42, 41, 7, 39, 43, 40, 36] >>> scoreatpercentile(a, 25) 25.5 >>> scoreatpercentile(a, 50) 40 >>> scoreatpercentile(a, 75) 42.5 This function is taken from :func:`scipy.stats.scoreatpercentile`. Copyright (c) Gary Strangman """ if issorted: values = sorted(a) if limit: values = values[(limit[0] < a) & (a < limit[1])] else: values = a def _interpolate(a, b, fraction): return a + (b - a) * fraction idx = per / 100. * (len(values) - 1) if (idx % 1 == 0): return values[int(idx)] else: return _interpolate(values[int(idx)], values[int(idx) + 1], idx % 1)
[docs]def flatnotmaskedContiguous(a): """ Find contiguous unmasked data in a masked array along the given axis. This function is taken from :func:`numpy.ma.extras.flatnotmasked_contiguous`. Copyright (c) Pierre Gerard-Marchant """ np.ma.extras.flatnotmasked_contiguous m = np.ma.getmask(a) if m is np.ma.nomask: return slice(0, a.size, None) i = 0 result = [] for (k, g) in itertools.groupby(m.ravel()): n = len(list(g)) if not k: result.append(slice(i, i + n)) i += n return result or None
[docs]def complexifyString(line): """ Converts a string in the form "(real, imag)" into a complex type. :type line: str :param line: String in the form ``"(real, imag)"``. :rtype: complex :return: Complex number. .. rubric:: Example >>> complexifyString("(1,2)") (1+2j) >>> complexifyString(" ( 1 , 2 ) ") (1+2j) """ temp = line.split(',') return complex(float(temp[0].strip()[1:]), float(temp[1].strip()[:-1]))
[docs]def toIntOrZero(value): """ Converts given value to an integer or returns 0 if it fails. :param value: Arbitrary data type. :rtype: int numpy.version.version .. rubric:: Example >>> toIntOrZero("12") 12 >>> toIntOrZero("x") 0 """ try: return int(value) except ValueError: return 0 # import numpy loadtxt and check if ndlim parameter is available
try: from numpy import loadtxt loadtxt(np.array([]), ndlim=1) except TypeError: # otherwise redefine loadtxt
[docs] def loadtxt(*args, **kwargs): """ Replacement for older numpy.loadtxt versions not supporting ndlim parameter. """ if not 'ndlim' in kwargs: return np.loadtxt(*args, **kwargs) # ok we got a ndlim param if kwargs['ndlim'] != 1: # for now we support only one dimensional arrays raise NotImplementedError('Upgrade your NumPy version!') del kwargs['ndlim'] dtype = kwargs.get('dtype', None) # lets get the data try: data = np.loadtxt(*args, **kwargs) except IOError, e: # raises in older versions if no data could be read if 'reached before encountering data' in str(e): # return empty array return np.array([], dtype=dtype) # otherwise just raise raise # ensures that an array is returned return np.atleast_1d(data)
if __name__ == '__main__': import doctest doctest.testmod(exclude_empty=True)