Example #1
0
def remove_clipped(stream, max_count=2000000):
    """
    Identify clipped waveforms having a count greater than the specified
    max count. This will remove any clipped waveforms from the stream.
    This is step 2 as found in the Rennolet et. al paper
    (https://doi.org/10.1193/101916EQS175DP)

    Args:
        stream (obspy.core.stream.Stream): Stream of raw data in counts.
        max_count (int): Maximum count for clipping.
            Default is 2 million.

    Returns:
        tuple of streams (obspy.core.stream.Stream): The first stream in the
            tuple has the clipped waveforms removed, while the second tuple in
            in the stream contains only the clipped waveforms.
    """
    clipped_st = Stream()
    for tr in stream:
        if abs(tr.max()) >= max_count:
            stream.traces.remove(tr)
            clipped_st.append(tr)
            warnings.warn('Clipped trace was removed from the stream')
            warnings.warn(tr.get_id())
    return stream, clipped_st
Example #2
0
def calculate_fas(stream, imcs, periods, smoothing, bandwidth):
    """
    Calculate the fourier amplitude spectra.

    This process requires getting the fourier amplitude spectra, applying
    the geometric mean to the horizontal traces, smoothing and returning the
    smoothed value for each requested period.

    Args:
        stream (obspy.core.stream.Stream): streams of strong ground motion.
            Traces in stream must be in units of g.
        imcs (list): list of imcs. (Currently only the geometric mean is
            supported and this is ignored. In the future it will account for
            channels and rotated channels.)

    Returns:
        dictionary: Dictionary of fas for the geometric mean.
            Units are in cm/s. The dictionary is structured as:
            fas_dict = {
                    <period> : <value,...
            }
    """
    fas_dict = {}
    sampling_rate = None
    # check units and add channel pga
    for trace in stream:
        if trace.stats['units'] != 'g' and trace.stats['units'] != 'cm/s/s':
            raise PGMException('Invalid units for sa: %r. '
                               'Units must be g (cm/s/s)' % trace.stats['units'])
        if 'Z' not in trace.stats['channel'].upper():
            sampling_rate = trace.stats.sampling_rate
    if sampling_rate is None:
        raise PGMException('No horizontal channels')

    spec_stream = Stream()
    for trace in stream:
        nfft = len(trace.data)
        # the fft scales so the factor of 1/nfft is applied
        spectra = abs(np.fft.rfft(trace.data, n=nfft)) / nfft
        spec_trace = Trace(data=spectra, header=trace.stats)
        spec_stream.append(spec_trace)

    ## The imc is always geometric mean. However, the combined stream is
    ## required rather than the single maximum value
    gm_trace = calculate_geometric_mean(spec_stream, return_combined=True)
    freqs = np.fft.rfftfreq(nfft, 1 / trace.stats.sampling_rate)

    fas_frequencies = 1 / np.asarray(list(periods))
    smoothed_values = np.empty_like(fas_frequencies)

    if smoothing.lower() == 'konno_ohmachi':
        konno_ohmachi_smooth(gm_trace.astype(np.double), freqs,
                fas_frequencies, smoothed_values, bandwidth)
    else:
        raise PGMException('Not a valid smoothing option: %r' % smoothing)

    for idx, freq in enumerate(fas_frequencies):
        fas_dict[1/freq] = smoothed_values[idx]

    return fas_dict
Example #3
0
def read_volume_one(filename, location=''):
    """Read channel data from USC volume 1 text file.

    Args:
        filename (str): Input DMG V1 filename.
    Returns:
        tuple: (list of obspy Trace, int line offset)
    """
    volume = VOLUMES['V1']
    # count the number of lines in the file
    with open(filename) as f:
        line_count = sum(1 for _ in f)
    # read as many channels as are present in the file
    line_offset = 0
    stream = Stream([])
    while line_offset < line_count:
        trace, line_offset = _read_channel(filename,
                                           line_offset,
                                           volume,
                                           location=location)
        # store the trace if the station type is in the valid_station_types list
        # or store the trace if there is no valid_station_types list
        if trace is not None:
            stream.append(trace)

    return stream
Example #4
0
    def filterpyrockoWaveform(self, Waveform):
        obspy_compat.plant()
        Logfile.red('Filter Waveform: ')
        cfg = FilterCfg(self.Config)

        new_frequence = (cfg.newFrequency())
        st = Stream()
        for i in Waveform:
            tr = obspy_compat.to_pyrocko_trace(i)
            tr.downsample_to(new_frequence)

            Logfile.red('Downsampling to %d: from %d' %
                        (new_frequence, i.stats.sampling_rate))

            if switch == 0:
                Logfile.add('bandpass filtered stream for station %s ' % (i))

                tr.bandpass(4, cfg.flo, cfg.fhi)
            elif switch == 1:
                Logfile.add('bandpass filtered stream for station %s ' % (i))
            j = obspy_compat.to_obspy_trace(tr)

            st.append(j)

        return st
    def filterWaveform(self, Waveform, cfg):

        Logfile.red('Filter Waveform: ')

        new_frequence = (cfg.config_filter.newFrequency)

        st = Stream()
        for i in Waveform:
                Logfile.red('Downsampling to %s: from %d' % (new_frequence,
                            i.stats.sampling_rate))
                j = i.resample(new_frequence)
                switch = cfg.config_filter.filterswitch

                Logfile.add('bandpass filtered \
                stream for station %s ' % (i))

                j.filter('bandpass',
                         freqmin=cfg.config_filter.flo[switch-1],
                         freqmax=cfg.config_filter.fhi[switch-1],
                         corners=cfg.config_filter.ns[switch-1],
                         zerophase=False)

                st.append(j)

        return st
def read_data(filename, **kwargs):
    """Read unknown csmip/dmg-like strong motion file.

    Args:
        filename (str): Path to data file.
        kwargs (ref):
            units (str): String determining which timeseries is return. Valid
                    options include 'acc', 'vel', 'disp'. Default is 'acc'.
            Other arguments will be ignored.
    Returns:
        Stream: Obspy Stream containing three channels of acceleration data
        (cm/s**2).
    """
    # Check for type
    units = kwargs.get('units', 'acc')
    if units not in UNITS:
        raise Exception('Not a valid choice of units.')

    # Count the number of lines in the file
    with open(filename) as f:
        line_count = sum(1 for _ in f)

    # Read as many channels as are present in the file
    line_offset = 0
    trace_list = []
    while line_offset < line_count:

        traces, line_offset = _read_volume(filename, line_offset)
        trace_list += traces

    stream = Stream([])
    for trace in trace_list:
        if trace.stats['units'] == units:
            stream.append(trace)
    return stream
Example #7
0
def read_dmg(filename, **kwargs):
    """Read DMG strong motion file.

    Notes:
        CSMIP is synonymous to as DMG in this reader.

    Args:
        filename (str): Path to possible DMG data file.
        kwargs (ref):
            units (str): String determining which timeseries is return. Valid
                    options include 'acc', 'vel', 'disp'. Default is 'acc'.
            Other arguments will be ignored.
    Returns:
        Stream: Obspy Stream containing three channels of acceleration data (cm/s**2).
    """
    if not is_dmg(filename):
        raise Exception('Not a DMG file format.')

    # Check for units and location
    units = kwargs.get('units', 'acc')
    location = kwargs.get('location', '')

    if units not in UNITS:
        raise Exception('Not a valid choice of units.')

    # Check for DMG format and determine volume type
    line = open(filename, 'rt').readline()
    if is_dmg(filename):
        if line.lower().find('uncorrected') >= 0:
            reader = 'V1'
        elif line.lower().find('corrected') >= 0:
            reader = 'V2'
        elif line.lower().find('response') >= 0:
            reader = 'V3'

    # Count the number of lines in the file
    with open(filename) as f:
        line_count = sum(1 for _ in f)

    # Read as many channels as are present in the file
    line_offset = 0
    trace_list = []
    while line_offset < line_count:
        if reader == 'V2':
            traces, line_offset = _read_volume_two(filename,
                                                   line_offset,
                                                   location=location)
            trace_list += traces
        else:
            raise AmptoolsException('Not a supported volume.')

    stream = Stream([])
    for trace in trace_list:
        if trace.stats['standard']['units'] == units:
            stream.append(trace)
    return stream
def join_NERT(a,b):

    new=Stream()

    for i in range(len(a)):
        if a[i].stats['station'] == b[i].stats['station'] and \
           a[i].stats['channel'] == b[i].stats['channel']:
           new.append(a[i])
        else:
           new.append(a[i])
           new.append(b[i])
    
    return new
def purgeListStation(st,args,ty):

    new=Stream()
    ra=args.radius.split()
    lii = []

    # select for distances
    if(ty=='d'):
      for i in range(len(st)):
          if(st[i].stats.gcarc >= eval(ra[0]) and st[i].stats.gcarc <= eval(ra[1])):
            new.append(st[i])

    return new
    def filter(self, stream, time_at_rec, la_s, lo_s, depth, Rayleigh=True):
        env_stream = Stream()
        dist, az, baz = gps2dist_azimuth(lat1=la_s,
                                         lon1=lo_s,
                                         lat2=self.prior['la_r'],
                                         lon2=self.prior['lo_r'],
                                         a=self.prior['radius'],
                                         f=0)
        if Rayleigh == True:
            phases = self.get_R_phases(time_at_rec)
        else:
            phases = self.get_L_phases(time_at_rec)
        for i, v in enumerate(stream.traces):
            npts = len(v.data)
            trace = stream.traces[i].copy()
            trace.detrend(type="demean")
            trace.interpolate(
                sampling_rate=10. / phases[i]['dt']
            )  # No method specified, so : 'weighted_average_slopes' is used
            trace.filter('highpass', freq=phases[i]['fmin'], zerophase=True)
            trace.filter('lowpass', freq=phases[i]['fmax'], zerophase=True)
            trace.detrend()
            trace.detrend(type="demean")
            env = envelope(trace.data)

            zero_trace = Trace(np.zeros(npts),
                               header={
                                   "starttime": phases[i]['starttime'](dist,
                                                                       depth),
                                   'delta': trace.meta.delta,
                                   "station": trace.meta.station,
                                   "network": trace.meta.network,
                                   "location": trace.meta.location,
                                   "channel": trace.meta.channel,
                                   "instaseis": trace.meta.instaseis
                               })
            env_trace = Trace(env,
                              header={
                                  "starttime": phases[i]['starttime'](dist,
                                                                      depth),
                                  'delta': trace.meta.delta,
                                  "station": trace.meta.station,
                                  "network": trace.meta.network,
                                  "location": trace.meta.location,
                                  "channel": trace.meta.channel,
                                  "instaseis": trace.meta.instaseis
                              })

            env_stream.append(env_trace)

        return env_stream
Example #11
0
 def saveData(self, filename = None):
     stream = Stream()
     for i in range(0,self.ntraces):
         curr_trace = self.data[:,i]
         curr_trace = np.require(curr_trace, dtype='float32')
         temp = Trace(data=curr_trace)
         # Attributes in trace.stats will overwrite everything in
         # trace.stats.segy.trace_header
         temp.stats.delta = 0.01
             # Add trace to stream
         stream.append(temp)
     print "Stream object before writing..."
     print stream
     stream.write(filename, format="SEGY", data_encoding=1,
                 byteorder=sys.byteorder)
Example #12
0
    def split_traces(self, d_syn, traces_obs, time_at_receiver):
        Stream_split = Stream()
        for i, trace in enumerate(traces_obs.traces):
            new_trace = Trace(d_syn[i * len(trace):i * len(trace) +
                                    len(trace)],
                              header={
                                  "starttime": time_at_receiver,
                                  'delta': trace.meta.delta,
                                  "station": trace.meta.station,
                                  "network": trace.meta.network,
                                  "location": trace.meta.location,
                                  "channel": trace.meta.channel,
                                  "instaseis": trace.meta.instaseis
                              })
            Stream_split.append(new_trace)

        return Stream_split
Example #13
0
 def saveData(self, filename=None):
     stream = Stream()
     for i in range(0, self.ntraces):
         curr_trace = self.data[:, i]
         curr_trace = np.require(curr_trace, dtype='float32')
         temp = Trace(data=curr_trace)
         # Attributes in trace.stats will overwrite everything in
         # trace.stats.segy.trace_header
         temp.stats.delta = 0.01
         # Add trace to stream
         stream.append(temp)
     print "Stream object before writing..."
     print stream
     stream.write(filename,
                  format="SEGY",
                  data_encoding=1,
                  byteorder=sys.byteorder)
Example #14
0
def poisson_segmenting(poisson_times, noise_trace, samp_rate, delta, st_event_2):
    """ Sets out the events at the poisson times (from poisson_interevent), and adds the noise onto the event at that point.
    """
    st_events_poisson = Stream()
    for i in range(0, len(poisson_times)):
        testnoise = np.array(noise_trace)
        noise_portion = testnoise[(poisson_times[i]*int(samp_rate)):
                                  (poisson_times[i]*int(samp_rate)) + len(st_event_2)]
        noise_plus_event_arr = noise_portion + np.array(st_event_2)
        noise_plus_event = Trace(noise_plus_event_arr)
        noise_plus_event.stats.sampling_rate = samp_rate
        noise_plus_event.stats.delta = delta
        noise_plus_event.stats.starttime =  noise_trace.stats.starttime + poisson_times[i]
        #plt.plot(noise_plus_event)
        st_events_poisson.append(noise_plus_event)
    st_events_poisson[-1].stats.endtime+100  

    return st_events_poisson
Example #15
0
def main():

    # Read acceleration data. If you want velocity units='vel',
    # Cdisplacement units='disp'
    data_dir = '/Users/tnye/PROJECTS/Duration/data/ci3144585/ground_motion'
    files = [
        '1994.c.017m30su.n0a', '1994.c.017m30su.n0b', '1994.c.017m30su.n0c'
    ]
    files = [os.path.join(data_dir, f) for f in files]

    stream = Stream()

    # Data for the trace we are working with
    # There are 3 traces (0, 1,  2), and i denotes trace we are working with
    for i in range(len(files)):
        cmp = processing.read_data(files[i], units='acc')[0]
        stream.append(cmp)

    durations = [(0.05, 0.75), (0.2, 0.8), (0.05, .95)]

    # Plots each boundary on the Norm Arias Intensity graph
    f, axes = plt.subplots(len(durations), 1, sharex=True, figsize=(6.5, 7.5))

    for i, trace in enumerate(stream):

        # Convert acceleration to m/s/s
        acc = np.multiply(0.01, trace.data)

        channel = trace.stats['channel']
        dt = trace.stats.delta

        Ia, NIa = arias_intensity.get_arias_intensity(acc, dt, 0)
        print("Arias Intensity (%s): %f" % (channel, np.amax(Ia)))

        if i == 2:
            xlab = True
        else:
            xlab = False

        arias_intensity.plot_durations(NIa, dt, durations, axes[i], xlab)
        axes[i].set_title(channel)

    plt.savefig('/Users/tnye/PROJECTS/Duration/figures/Afshari_Fig_1_tnye.png',
                dpi=300)
Example #16
0
def copy(orig):
    """
	True-copy a stream by creating a new stream and copying old attributes to it.
	This is necessary because the old stream accumulates *something* that causes
	CPU usage to increase over time as more data is added. This is a bug in obspy
	that I intend to find--or at the very least report--but until then this hack
	works fine and is plenty fast enough.

	In this example, we make a stream object with some RS 1Dv7 data and then copy it to a new stream:

	.. code-block:: python

		>>> import rsudp.raspberryshake as rs
		>>> from obspy.core.stream import Stream
		>>> rs.initRSlib(dport=8888, rsstn='R3BCF')
		>>> s = Stream()
		>>> d = rs.getDATA()
		>>> t = rs.make_trace(d)
		>>> s = rs.update_stream(s, d)
		>>> s
		1 Trace(s) in Stream:
		AM.R3BCF.00.EHZ | 2020-02-21T19:58:50.292000Z - 2020-02-21T19:58:50.532000Z | 100.0 Hz, 25 samples
		>>> s = rs.copy(s)
		>>> s
		1 Trace(s) in Stream:
		AM.R3BCF.00.EHZ | 2020-02-21T19:58:50.292000Z - 2020-02-21T19:58:50.532000Z | 100.0 Hz, 25 samples


	:param obspy.core.stream.Stream orig: The data stream to copy information from
	:rtype: obspy.core.stream.Stream
	:return: A low-memory copy of the passed data stream

	"""
    stream = Stream()
    for t in range(len(orig)):
        trace = Trace(data=orig[t].data)
        trace.stats.network = orig[t].stats.network
        trace.stats.location = orig[t].stats.location
        trace.stats.station = orig[t].stats.station
        trace.stats.channel = orig[t].stats.channel
        trace.stats.sampling_rate = orig[t].stats.sampling_rate
        trace.stats.starttime = orig[t].stats.starttime
        stream.append(trace).merge(fill_value=None)
    return stream.copy()
Example #17
0
def stream_stack_distance_intervals(st, interval):
    """ Stack average traces in a stream if their distance difference is
    smaller than interval.

    The stream containing a number of traces with given distance (e.g. from source)
    is used to create a number of equally spaced traces by averaging traces that fall
    into the same distance bin. If interval is a scalar the bins are equally spaced with
    a width of interval. If interval is a sequence its elements define the lower distance
    limit of the bins.

    :type st: :class:`~obspy.core.stream.Stream`
    :param st: Stream fo be used for stacking.
    :type interval: scalar os array like
    :param interval: width of bins in case of scalar or smaller edge of
        bins if interval is a sequence.
    :rtype sst: :class:`~obspy.core.stream.Stream`
    :return: **sst**: stacked stream
    """
    dist = []
    npts = []
    for tr in st:
        dist.append(tr.stats.sac['dist'])
        npts.append(tr.stats['npts'])
    
    if not hasattr(interval, "__len__"):
        bins = np.arange(min(dist), max(dist),interval)
    else:
        bins = np.array(interval)
    
    sst = Stream()
    for ii in bins:
        sst.append(Trace(data=np.zeros(max(npts),dtype=np.float64),header={
            'network':'stack','station':str(ii),'location':'',
            'channel':st[0].stats['channel'],'starttime':st[0].stats['starttime'],'sampling_rate':st[0].stats['sampling_rate'],
            'sac':{'dist':ii,'az':0,'evla':0.,'evlo':0.,'stla':ii/(np.pi*6371000)*180.,'stlo':0.}}))
    count = np.zeros_like(bins)
    for tr in st:
        ind = sum((tr.stats.sac['dist'] - bins)>=0)-1
        sst[ind].data[0:tr.stats['npts']] += tr.data
        count[ind] += 1
    for ind, tr in enumerate(sst):
        tr.data /= count[ind]
    
    return sst
Example #18
0
def copy(orig):
    """
	True copy a stream by creating a new stream and copying old attributes to it.
	This is necessary because the old stream accumulates *something* that causes
	CPU usage to increase over time as more data is added. This is a bug in obspy
	that I intend to find--or at the very least report--but until then this hack
	works fine.
	"""
    stream = Stream()
    for t in range(len(orig)):
        trace = Trace(data=orig[t].data)
        trace.stats.network = orig[t].stats.network
        trace.stats.location = orig[t].stats.location
        trace.stats.station = orig[t].stats.station
        trace.stats.channel = orig[t].stats.channel
        trace.stats.sampling_rate = orig[t].stats.sampling_rate
        trace.stats.starttime = orig[t].stats.starttime
        stream.append(trace).merge(fill_value=None)
    return stream.copy()
Example #19
0
def read_cosmos(filename, **kwargs):
    """Read COSMOS V1/V2 strong motion file.

    There is one extra key in the Stats object for each Trace - "process_level".
    This will be set to either "V1" or "V2".

    Args:
        filename (str): Path to possible COSMOS V1/V2 data file.
        kwargs (ref):
            valid_station_types (list): List of valid station types. See table
                6  in the COSMOS strong motion data format documentation for
                station type codes.
            Other arguments will be ignored.
    Returns:
        Stream: Obspy Stream containing three channels of acceleration data (cm/s**2).
    """
    # get list of valid stations
    valid_station_types = kwargs.get('valid_station_types', None)
    # get list of valid stations
    location = kwargs.get('location', '')

    # count the number of lines in the file
    with open(filename) as f:
        line_count = sum(1 for _ in f)

    # read as many channels as are present in the file
    line_offset = 0
    stream = Stream([])
    while line_offset < line_count:
        trace, line_offset = _read_channel(filename,
                                           line_offset,
                                           location=location)
        # store the trace if the station type is in the valid_station_types list
        # or store the trace if there is no valid_station_types list
        if valid_station_types is not None:
            if trace.stats['format_specific'][
                    'station_code'] in valid_station_types:
                stream.append(trace)
        else:
            stream.append(trace)

    return stream
Example #20
0
def dataclean(alltrigs, opt, flag=1):

    """
    Examine triggers and weed out spikes and calibration pulses using kurtosis and
    outlier ratios
    
    alltrigs: triggers output from triggering
    opt: opt from config
    flag: 1 if defining window to check, 0 if want to check whole waveform for spikes
        (note that different threshold values should be used for different window lengths)
    
    Returns good trigs (trigs) and junk (junk)
    """
    
    trigs=Stream()
    junk=Stream()
    for i in range(len(alltrigs)):
        #define data
        dat=alltrigs[i].data
        if flag==0:
            datcut=dat
        else:
            datcut=alltrigs[i].data[range(int((opt.ptrig-opt.kurtwin/2)*opt.samprate),
                int((opt.ptrig+opt.kurtwin/2)*opt.samprate))]
        
        #calculate kurtosis in window
        k = stats.kurtosis(datcut)
        #compute kurtosis of frequency amplitude spectrum next
        
        datf = np.absolute(fft(dat))
        kf = stats.kurtosis(datf)
        #calculate outlier ratio using z ((data-median)/mad), outliers have z>4.45
        mad = np.median(np.absolute(dat - np.median(dat)))
        z=(dat-np.median(dat))/mad
        orm = len(z[z>4.45])/len(z)
        if k<opt.kurtmax and orm<opt.oratiomax and kf<opt.kurtfmax:
            trigs.append(alltrigs[i])
        else:
            junk.append(alltrigs[i])
                
    return trigs, junk
Example #21
0
def corr_trace_to_obspy(corr_trace):
    """ Convert a correlation trace dictionary to an obspy trace.

    Convert a single correlation trace (or a list of) in an
    :class:`~obspy.core.trace.Trace` (or :class:`~obspy.core.stream.Stream`)
    object.

    :type corr_trace: dictionary of type correlation trace or list of these
    :param corr_trace: input date to be converted

    :rtype: :class:`~obspy.core.trace.Trace` if ``corr_trace`` is a dict
        and :class:`~obspy.core.stream.Stream` if ``corr_trace`` is a list of
        dicts
    :return: **st**: the obspy object containing the data
    """

    if isinstance(corr_trace, list):
        st = Stream()
        for tr in corr_trace:
            st.append(_single_corr_trace_to_obspy_trace(tr))
    else:
        st = _single_corr_trace_to_obspy_trace(corr_trace)
    return st
Example #22
0
def rotate_stream(D, orientation, reference):
    """
    """
    channels = []
    for trace in D:
        channels.append(trace.stats.channel)
    Drot = Stream()
    for (angle, trace) in zip(orientation, D):
        channel = trace.stats.channel
        trace_rot = trace.copy()
        if channel[2] in ['E', 'N', '1', '2']:
            az = angle['azimuth']
            az0 = reference[channel]['azimuth']
            if (az != az0):
                normal_dict = {'E': 'N', 'N': 'E', '1': '2', '2': '1'}
                normal = channel[0:2] + normal_dict[channel[2]]
                index = channels.index(normal)
                if channel[2] in ['E', '1']:
                    dE = angle['azimuth'] * pi / 180.0
                    dN = orientation[index]['azimuth'] * pi / 180.0
                    tE = reference[channel]['azimuth'] * pi / 180.0
                    tN = reference[normal]['azimuth'] * pi / 180.0
                    dataE = trace.data
                    dataN = D[index].data
                    trace_rot.data = cos(dE - tE) * dataE + cos(dN -
                                                                tE) * dataN
                else:
                    dE = orientation[index]['azimuth'] * pi / 180.0
                    dN = angle['azimuth'] * pi / 180.0
                    tE = reference[normal]['azimuth'] * pi / 180.0
                    tN = reference[channel]['azimuth'] * pi / 180.0
                    dataE = D[index].data
                    dataN = trace.data
                    trace_rot.data = cos(dE - tN) * dataE + cos(dN -
                                                                tN) * dataN
        Drot.append(trace_rot)
    return Drot
Example #23
0
def _calculate_channel_arias(stream):
    """Calculates Arias Intensity.
    Args:
        stream (obspy.core.stream.Stream): Stream of acceleration values
                in m/s/s.
    Returns:
        Ia (obspy.core.stream.Stream): Stream of Arias intensity values
                in m/s with respect to time.
        NIa (obspy.core.stream.Stream): Stream of normalized Arias intensity
                values with respect to time.
    Raises:
        PGMException: If the units are not valid. Units must be m/s/s.
    """
    Ia = Stream()
    NIa = Stream()
    for trace in stream:
        if trace.stats['units'] != 'm/s/s':
            raise PGMException('Invalid units for ARIAS: %r. '
                               'Units must be m/s/s' % trace.stats['units'])
        dt = trace.stats['delta']
        g = sp.g
        acc2 = trace.data

        # Calculate Arias intensity
        integration = integrate.cumtrapz(acc2 * acc2, dx=dt)
        arias_intensity = integration * np.pi / (2 * g)

        # Calculate normalized Arias intensity
        # divide arias intensity by its max value
        norm_arias_intensity = arias_intensity / np.amax(arias_intensity)
        stats_out = trace.stats.copy()
        stats_out['units'] = 'm/s'
        trace_ia = Trace(data=arias_intensity, header=stats_out)
        trace_nia = Trace(data=norm_arias_intensity, header=stats_out)
        Ia.append(trace_ia)
        NIa.append(trace_nia)
    return (Ia, NIa)
Example #24
0
    def filterWaveform(self, Waveform):

        Logfile.red('Filter Waveform: ')
        cfg = FilterCfg(self.Config)

        new_frequence = (cfg.newFrequency())

        st = Stream()
        for i in Waveform:
            Logfile.red('Downsampling to %s: from %d' %
                        (new_frequence, i.stats.sampling_rate))
            j = i.resample(new_frequence)
            switch = cfg.filterswitch()

            if switch == 1:
                Logfile.add('bandpass filtered \
                        stream for station %s ' % (i))

                j.filter('bandpass',
                         freqmin=cfg.flo(),
                         freqmax=cfg.fhi(),
                         corners=cfg.ns(),
                         zerophase=bool(self.Config['zph']))

            elif switch == 2:
                Logfile.add('bandpass filtered \
                        stream for station %s ' % (i))

                j.filter('bandpass',
                         freqmin=cfg.flo2(),
                         freqmax=cfg.fhi2(),
                         corners=cfg.ns2(),
                         zerophase=bool(self.Config['zph']))
            st.append(j)

        return st
Example #25
0
def main():

    # Read acceleration data. If you want velocity units='vel',
    # Cdisplacement units='disp'
    data_dir = '/Users/tnye/PROJECTS/Duration/data/ci3144585/ground_motion'
    files = [
        '1994.c.017m30su.n0a', '1994.c.017m30su.n0b', '1994.c.017m30su.n0c'
    ]
    files = [os.path.join(data_dir, f) for f in files]

    stream = Stream()

    # Data for the trace we are working with
    # There are 3 traces (0, 1,  2), and i denotes trace we are working with
    for i in range(len(files)):
        cmp = processing.read_data(files[i], units='acc')[0]
        stream.append(cmp)

    for i, trace in enumerate(stream):
        trace_stats = trace.stats
        channel = trace.stats['channel']
        print(channel)
        dt = trace_stats.delta
        cav = CAV.get_CAV(trace.data, dt, 0)
Example #26
0
    def split_BW_SW(self, BW_SW_stream, epi, depth, time_at_receiver, npts):
        BW_stream = Stream()
        R_stream = Stream()
        L_stream = Stream()
        for i in BW_SW_stream:
            if 'X' in i.id:
                BW_stream.append(i)

            elif 'R1' in i.id:
                R_stream.append(i)

            elif 'G1' in i.id:
                L_stream.append(i)

        P_S_syn, P_syn, S_syn = self.get_window_split_syn(
            BW_stream, epi, depth, time_at_receiver, npts)
        return P_S_syn, P_syn, S_syn, R_stream, L_stream
Example #27
0
def mergePreviews(stream):
    """
    Merges all preview traces in one Stream object. Does not change the
    original stream because the data needs to be copied anyway.

    :type stream: :class:`~obspy.core.stream.Stream`
    :param stream: Stream object to be merged
    :rtype: :class:`~obspy.core.stream.Stream`
    :return: Merged Stream object.
    """
    copied_traces = copy(stream.traces)
    stream.sort()
    # Group traces by id.
    traces = {}
    dtypes = []
    for trace in stream:
        # Throw away empty traces.
        if trace.stats.npts == 0:
            continue
        if not hasattr(trace.stats, 'preview') or not trace.stats.preview:
            msg = 'Trace\n%s\n is no preview file.' % str(trace)
            raise Exception(msg)
        traces.setdefault(trace.id, [])
        traces[trace.id].append(trace)
        dtypes.append(trace.data.dtype)
    if len(traces) == 0:
        return Stream()
    # Initialize new Stream object.
    new_stream = Stream()
    for value in traces.values():
        if len(value) == 1:
            new_stream.append(value[0])
            continue
        # All traces need to have the same delta value and also be on the same
        # grid spacing. It is enough to only check the sampling rate because
        # the algorithm that creates the preview assures that the grid spacing
        # is correct.
        sampling_rates = set([tr.stats.sampling_rate for tr in value])
        if len(sampling_rates) != 1:
            msg = 'More than one sampling rate for traces with id %s.' % \
                  value[0].id
            raise Exception(msg)
        delta = value[0].stats.delta
        # Check dtype.
        dtypes = set([native_str(tr.data.dtype) for tr in value])
        if len(dtypes) > 1:
            msg = 'Different dtypes for traces with id %s' % value[0].id
            raise Exception(msg)
        dtype = dtypes.pop()
        # Get the minimum start and maximum endtime for all traces.
        min_starttime = min([tr.stats.starttime for tr in value])
        max_endtime = max([tr.stats.endtime for tr in value])
        samples = int(round((max_endtime - min_starttime) / delta)) + 1
        data = np.empty(samples, dtype=dtype)
        # Fill with negative one values which corresponds to a gap.
        data[:] = -1
        # Create trace and give starttime.
        new_trace = Trace(data=data, header=value[0].stats)
        # Loop over all traces in value and add to data.
        for trace in value:
            start_index = int((trace.stats.starttime - min_starttime) / delta)
            end_index = start_index + len(trace.data)
            # Element-by-element comparison.
            data[start_index:end_index] = \
                np.maximum(data[start_index:end_index], trace.data)
        # set npts again, because data is changed in place
        new_trace.stats.npts = len(data)
        new_stream.append(new_trace)
    stream.traces = copied_traces
    return new_stream
Example #28
0
def dataClean(alltrigs, opt, flag=1):

    """
    Examine triggers and weed out spikes and calibration pulses using kurtosis and
    outlier ratios
    
    alltrigs: triggers output from triggering
    opt: opt from config
    flag: 1 if defining window to check, 0 if want to check whole waveform for spikes
        (note that different threshold values should be used for different window lengths)
    
    Returns good trigs (trigs) and several junk types (junk, junkFI, junkKurt)
    """
    
    trigs=Stream()
    junkFI=Stream()
    junkKurt=Stream()
    junk=Stream()
    for i in range(len(alltrigs)):
            
        njunk = 0
        ntele = 0
        
        for n in range(opt.nsta):
            
            dat = alltrigs[i].data[n*opt.wshape:(n+1)*opt.wshape]
            if flag == 1:
                datcut=dat[range(int((opt.ptrig-opt.kurtwin/2)*opt.samprate),
                    int((opt.ptrig+opt.kurtwin/2)*opt.samprate))]
            else:
                datcut=dat
            
            if np.sum(np.abs(dat))!=0.0:
                # Calculate kurtosis in window
                k = stats.kurtosis(datcut)
                # Compute kurtosis of frequency amplitude spectrum next
                datf = np.absolute(fft(dat))
                kf = stats.kurtosis(datf)
                # Calculate outlier ratio using z ((data-median)/mad)
                mad = np.nanmedian(np.absolute(dat - np.nanmedian(dat)))
                z = (dat-np.median(dat))/mad
                # Outliers have z > 4.45
                orm = len(z[z>4.45])/np.array(len(z)).astype(float)
            
                if k >= opt.kurtmax or orm >= opt.oratiomax or kf >= opt.kurtfmax:
                    njunk+=1
                
                winstart = int(opt.ptrig*opt.samprate - opt.winlen/10)
                winend = int(opt.ptrig*opt.samprate - opt.winlen/10 + opt.winlen)
                fftwin = np.reshape(fft(dat[winstart:winend]),(opt.winlen,))
                if np.median(np.abs(dat[winstart:winend]))!=0:
                    fi = np.log10(np.mean(np.abs(np.real(
                        fftwin[int(opt.fiupmin*opt.winlen/opt.samprate):int(
                        opt.fiupmax*opt.winlen/opt.samprate)])))/np.mean(np.abs(np.real(
                        fftwin[int(opt.filomin*opt.winlen/opt.samprate):int(
                        opt.filomax*opt.winlen/opt.samprate)]))))
                    if fi<opt.telefi:
                        ntele+=1
        
        # Allow if there are enough good stations to correlate
        if njunk <= (opt.nsta-opt.ncor) and ntele <= opt.teleok:
            trigs.append(alltrigs[i])
        else:
            if njunk > 0:
                if ntele > 0:
                    junk.append(alltrigs[i])
                else:
                    junkKurt.append(alltrigs[i])
            else:
                junkFI.append(alltrigs[i])
                
    return trigs, junk, junkFI, junkKurt
Example #29
0
def getData(tstart, tend, opt):

    """
    Download data from files in a folder, from IRIS, or a Earthworm waveserver
    
    A note on SAC/miniSEED files: as this makes no assumptions about the naming scheme of
    your data files, please ensure that your headers contain the correct SCNL information!

    tstart: UTCDateTime of beginning of period of interest
    tend: UTCDateTime of end of period of interest
    opt: Options object describing station/run parameters
    
    Returns ObsPy stream objects, one for cutting and the other for triggering
    """    
    
    nets = opt.network.split(',')
    stas = opt.station.split(',')
    locs = opt.location.split(',')
    chas = opt.channel.split(',')
    
    st = Stream()
    
    if opt.server == 'file':
    
        # Generate list of files
        if opt.server == 'file':
            flist = list(itertools.chain.from_iterable(glob.iglob(os.path.join(
                root,opt.filepattern)) for root, dirs, files in os.walk(opt.searchdir)))
                
        # Determine which subset of files to load based on start and end times and
        # station name; we'll fully deal with stations below
        flist_sub = []
        for f in flist:
            # Load header only
            stmp = obspy.read(f, headonly=True)
            # Check if station is contained in the stas list
            if stmp[0].stats.station in stas:
                # Check if contains either start or end time
                ststart = stmp[0].stats.starttime
                stend = stmp[-1].stats.endtime
                if (ststart<=tstart and tstart<=stend) or (ststart<=tend and
                    tend<=stend) or (tstart<=stend and ststart<=tend):
                    flist_sub.append(f)
        
        # Fully load data from file
        stmp = Stream()
        for f in flist_sub:
            tmp = obspy.read(f, starttime=tstart, endtime=tend+opt.maxdt)
            if len(tmp) > 0:
                stmp = stmp.extend(tmp)
    
        # Filter and merge
        stmp = stmp.filter('bandpass', freqmin=opt.fmin, freqmax=opt.fmax, corners=2,
            zerophase=True)
        stmp = stmp.taper(0.05,type='hann',max_length=opt.mintrig)
        for m in range(len(stmp)):
            if stmp[m].stats.sampling_rate != opt.samprate:
                stmp[m] = stmp[m].resample(opt.samprate)
        stmp = stmp.merge(method=1, fill_value=0)
        
        # Only grab stations/channels that we want and in order
        netlist = []
        stalist = []
        chalist = []
        loclist = []
        for s in stmp:
            stalist.append(s.stats.station)
            chalist.append(s.stats.channel)
            netlist.append(s.stats.network)
            loclist.append(s.stats.location)
            
        # Find match of SCNL in header or fill empty
        for n in range(len(stas)):
            for m in range(len(stalist)):
                if (stas[n] in stalist[m] and chas[n] in chalist[m] and nets[n] in
                    netlist[m] and locs[n] in loclist[m]):
                    st = st.append(stmp[m])
            if len(st) == n:
                print("Couldn't find "+stas[n]+'.'+chas[n]+'.'+nets[n]+'.'+locs[n])
                trtmp = Trace()
                trtmp.stats.sampling_rate = opt.samprate
                trtmp.stats.station = stas[n]
                st = st.append(trtmp.copy())
    
    else:   
     
        if '.' not in opt.server:
            client = Client(opt.server)
        else:
            client = EWClient(opt.server, opt.port)
        
        for n in range(len(stas)):
            try:
                stmp = client.get_waveforms(nets[n], stas[n], locs[n], chas[n],
                        tstart, tend+opt.maxdt)
                for m in range(len(stmp)):
                    stmp[m].data = np.where(stmp[m].data == -2**31, 0, stmp[m].data) # replace -2**31 (Winston NaN token) w 0
                stmp = stmp.filter('bandpass', freqmin=opt.fmin, freqmax=opt.fmax,
                    corners=2, zerophase=True)
                stmp = stmp.taper(0.05,type='hann',max_length=opt.mintrig)
                for m in range(len(stmp)):
                    if stmp[m].stats.sampling_rate != opt.samprate:
                        stmp[m] = stmp[m].resample(opt.samprate)
                stmp = stmp.merge(method=1, fill_value=0)
            except (obspy.clients.fdsn.header.FDSNException):
                try: # try again
                    stmp = client.get_waveforms(nets[n], stas[n], locs[n], chas[n],
                            tstart, tend+opt.maxdt)
                    for m in range(len(stmp)):
                        stmp[m].data = np.where(stmp[m].data == -2**31, 0, stmp[m].data) # replace -2**31 (Winston NaN token) w 0
                    stmp = stmp.filter('bandpass', freqmin=opt.fmin, freqmax=opt.fmax,
                        corners=2, zerophase=True)
                    stmp = stmp.taper(0.05,type='hann',max_length=opt.mintrig)
                    for m in range(len(stmp)):
                        if stmp[m].stats.sampling_rate != opt.samprate:
                            stmp[m] = stmp[m].resample(opt.samprate)
                    stmp = stmp.merge(method=1, fill_value=0)
                except (obspy.clients.fdsn.header.FDSNException):
                    print('No data found for {0}.{1}'.format(stas[n],nets[n]))
                    trtmp = Trace()
                    trtmp.stats.sampling_rate = opt.samprate
                    trtmp.stats.station = stas[n]
                    stmp = Stream().extend([trtmp.copy()])
                                            
            # Last check for length; catches problem with empty waveserver
            if len(stmp) != 1:
                print('No data found for {0}.{1}'.format(stas[n],nets[n]))
                trtmp = Trace()
                trtmp.stats.sampling_rate = opt.samprate
                trtmp.stats.station = stas[n]
                stmp = Stream().extend([trtmp.copy()])
                
            st.extend(stmp.copy()) 
    
    # Edit 'start' time if using offset option
    if opt.maxdt:
        dts = np.fromstring(opt.offset, sep=',')
        for n, tr in enumerate(st):
            tr.stats.starttime = tr.stats.starttime-dts[n]
    
    st = st.trim(starttime=tstart, endtime=tend, pad=True, fill_value=0)
    stC = st.copy()
    
    return st, stC
Example #30
0
def trigger(st, stC, rtable, opt):

    """
    Run triggering algorithm on a stream of data.

    st: OBSPy stream of data
    rtable: Repeater table contains reference time of previous trigger in samples
    opt: Options object describing station/run parameters

    Returns triggered traces as OBSPy trace object updates ptime for next run 
    """
    
    tr = st[0]
    t = tr.stats.starttime

    cft = coincidence_trigger(opt.trigalg, opt.trigon, opt.trigoff, stC, opt.nstaC,
        sta=opt.swin, lta=opt.lwin, details=True)
            
    if len(cft) > 0:
        
        ind = 0
        
        # Slice out the data from st and save the maximum STA/LTA ratio value for
        # use in orphan expiration
        
        # Convert ptime from time of last trigger to seconds before start time
        if rtable.attrs.ptime:
            ptime = (UTCDateTime(rtable.attrs.ptime) - t)
        else:
            ptime = -opt.mintrig
                
        for n in range(len(cft)):
                    
            ttime = cft[n]['time'] # This is a UTCDateTime, not samples
            
            if (ttime >= t + opt.atrig) and (ttime >= t + ptime +
                opt.mintrig) and (ttime < t + len(tr.data)/opt.samprate -
                2*opt.atrig):
                
                ptime = ttime - t
                
                # Cut out and append all data to first trace              
                tmp = st.slice(ttime - opt.ptrig, ttime + opt.atrig)
                ttmp = tmp.copy()
                ttmp = ttmp.trim(ttime - opt.ptrig, ttime + opt.atrig + 0.05, pad=True,
                    fill_value=0)
                ttmp[0].data = ttmp[0].data[0:opt.wshape] - np.mean(
                    ttmp[0].data[0:opt.wshape])
                for s in range(1,len(ttmp)):
                    ttmp[0].data = np.append(ttmp[0].data, ttmp[s].data[
                        0:opt.wshape] - np.mean(ttmp[s].data[0:opt.wshape]))
                ttmp[0].stats.maxratio = np.max(cft[n]['cft_peaks'])
                if ind is 0:
                    trigs = Stream(ttmp[0])
                    ind = ind+1
                else:
                    trigs = trigs.append(ttmp[0])
                                                         
        if ind is 0:
            return []
        else:
            rtable.attrs.ptime = (t + ptime).isoformat()
            return trigs
    else:
        return []
Example #31
0
def getData(tstart, tend, opt):

    """
    Download data from files in a folder, from IRIS, or a Earthworm waveserver
    
    A note on SAC/miniSEED files: as this makes no assumptions about the naming scheme of
    your data files, please ensure that your headers contain the correct SCNL information!

    tstart: UTCDateTime of beginning of period of interest
    tend: UTCDateTime of end of period of interest
    opt: Options object describing station/run parameters
    
    Returns ObsPy stream objects, one for cutting and the other for triggering
    """    
    
    nets = opt.network.split(',')
    stas = opt.station.split(',')
    locs = opt.location.split(',')
    chas = opt.channel.split(',')
    
    st = Stream()
    
    if opt.server == 'SAC' or opt.server == 'miniSEED':
    
        # Generate list of files
        if opt.server == 'SAC':
            flist = list(itertools.chain.from_iterable(glob.iglob(os.path.join(
                root,'*.sac')) for root, dirs, files in os.walk(opt.sacdir)))+list(
                itertools.chain.from_iterable(glob.iglob(os.path.join(
                root,'*.SAC')) for root, dirs, files in os.walk(opt.sacdir)))
        elif opt.server == 'miniSEED':
            flist = list(itertools.chain.from_iterable(glob.iglob(os.path.join(
                root,'*.mseed')) for root, dirs, files in os.walk(opt.mseeddir)))+list(
                itertools.chain.from_iterable(glob.iglob(os.path.join(
                root,'*.MSEED')) for root, dirs, files in os.walk(opt.mseeddir)))
                
        # Determine which subset of files to load based on start and end times and
        # station name; we'll fully deal with stations below
        flist_sub = []
        for f in flist:
            # Load header only
            stmp = obspy.read(f, headonly=True)
            # Check if station is contained in the stas list
            if stmp[0].stats.station in stas:
                # Check if contains either start or end time
                ststart = stmp[0].stats.starttime
                stend = stmp[0].stats.endtime
                if (ststart<=tstart and tstart<=stend) or (ststart<=tend and
                    tend<=stend) or (tstart<=stend and ststart<=tend):
                    flist_sub.append(f)
        
        # Fully load data from file
        stmp = Stream()
        for f in flist_sub:
            tmp = obspy.read(f, starttime=tstart, endtime=tend+opt.maxdt)
            if len(tmp) > 0:
                stmp = stmp.extend(tmp)
    
        # Filter and merge
        stmp = stmp.filter('bandpass', freqmin=opt.fmin, freqmax=opt.fmax, corners=2,
            zerophase=True)
        stmp = stmp.taper(0.05,type='hann',max_length=opt.mintrig)
        for m in range(len(stmp)):
            if stmp[m].stats.sampling_rate != opt.samprate:
                stmp[m] = stmp[m].resample(opt.samprate)
        stmp = stmp.merge(method=1, fill_value=0)
        
        # Only grab stations/channels that we want and in order
        netlist = []
        stalist = []
        chalist = []
        loclist = []
        for s in stmp:
            stalist.append(s.stats.station)
            chalist.append(s.stats.channel)
            netlist.append(s.stats.network)
            loclist.append(s.stats.location)
            
        # Find match of SCNL in header or fill empty
        for n in range(len(stas)):
            for m in range(len(stalist)):
                if (stas[n] in stalist[m] and chas[n] in chalist[m] and nets[n] in
                    netlist[m] and locs[n] in loclist[m]):
                    st = st.append(stmp[m])
            if len(st) == n:
                print("Couldn't find "+stas[n]+'.'+chas[n]+'.'+nets[n]+'.'+locs[n])
                trtmp = Trace()
                trtmp.stats.sampling_rate = opt.samprate
                trtmp.stats.station = stas[n]
                st = st.append(trtmp.copy())
    
    else:   
     
        if '.' not in opt.server:
            client = Client(opt.server)
        else:
            client = EWClient(opt.server, opt.port)
        
        for n in range(len(stas)):
            try:
                stmp = client.get_waveforms(nets[n], stas[n], locs[n], chas[n],
                        tstart, tend+opt.maxdt)
                stmp = stmp.filter('bandpass', freqmin=opt.fmin, freqmax=opt.fmax,
                    corners=2, zerophase=True)
                stmp = stmp.taper(0.05,type='hann',max_length=opt.mintrig)
                for m in range(len(stmp)):
                    if stmp[m].stats.sampling_rate != opt.samprate:
                        stmp[m] = stmp[m].resample(opt.samprate)
                stmp = stmp.merge(method=1, fill_value=0)
            except (obspy.clients.fdsn.header.FDSNException):
                try: # try again
                    stmp = client.get_waveforms(nets[n], stas[n], locs[n], chas[n],
                            tstart, tend+opt.maxdt)
                    stmp = stmp.filter('bandpass', freqmin=opt.fmin, freqmax=opt.fmax,
                        corners=2, zerophase=True)
                    stmp = stmp.taper(0.05,type='hann',max_length=opt.mintrig)
                    for m in range(len(stmp)):
                        if stmp[m].stats.sampling_rate != opt.samprate:
                            stmp[m] = stmp[m].resample(opt.samprate)
                    stmp = stmp.merge(method=1, fill_value=0)
                except (obspy.clients.fdsn.header.FDSNException):
                    print('No data found for {0}.{1}'.format(stas[n],nets[n]))
                    trtmp = Trace()
                    trtmp.stats.sampling_rate = opt.samprate
                    trtmp.stats.station = stas[n]
                    stmp = Stream().extend([trtmp.copy()])
                                            
            # Last check for length; catches problem with empty waveserver
            if len(stmp) != 1:
                print('No data found for {0}.{1}'.format(stas[n],nets[n]))
                trtmp = Trace()
                trtmp.stats.sampling_rate = opt.samprate
                trtmp.stats.station = stas[n]
                stmp = Stream().extend([trtmp.copy()])
                
            st.extend(stmp.copy()) 
    
    # Edit 'start' time if using offset option
    if opt.maxdt:
        dts = np.fromstring(opt.offset, sep=',')
        for n, tr in enumerate(st):
            tr.stats.starttime = tr.stats.starttime-dts[n]
    
    st = st.trim(starttime=tstart, endtime=tend, pad=True, fill_value=0)
    stC = st.copy()
    
    return st, stC
Example #32
0
 def get_preview(self,
                 trace_ids=[],
                 starttime=None,
                 endtime=None,
                 network=None,
                 station=None,
                 location=None,
                 channel=None,
                 pad=False):
     """
     Returns the preview trace.
     """
     # build up query
     session = self.session()
     query = session.query(WaveformChannel)
     # start and end time
     try:
         starttime = UTCDateTime(starttime)
     except Exception:
         starttime = UTCDateTime() - 60 * 20
     finally:
         query = query.filter(WaveformChannel.endtime > starttime.datetime)
     try:
         endtime = UTCDateTime(endtime)
     except Exception:
         # 10 minutes
         endtime = UTCDateTime()
     finally:
         query = query.filter(WaveformChannel.starttime < endtime.datetime)
     # process arguments
     if trace_ids:
         # filter over trace id list
         trace_filter = or_()
         for trace_id in trace_ids:
             temp = trace_id.split('.')
             if len(temp) != 4:
                 continue
             trace_filter.append(
                 and_(WaveformChannel.network == temp[0],
                      WaveformChannel.station == temp[1],
                      WaveformChannel.location == temp[2],
                      WaveformChannel.channel == temp[3]))
         if trace_filter.clauses:
             query = query.filter(trace_filter)
     else:
         # filter over network/station/location/channel id
         kwargs = {
             'network': network,
             'station': station,
             'location': location,
             'channel': channel
         }
         for key, value in kwargs.items():
             if value is None:
                 continue
             col = getattr(WaveformChannel, key)
             if '*' in value or '?' in value:
                 value = value.replace('?', '_')
                 value = value.replace('*', '%')
                 query = query.filter(col.like(value))
             else:
                 query = query.filter(col == value)
     # execute query
     results = query.all()
     session.close()
     # create Stream
     st = Stream()
     for result in results:
         preview = result.get_preview()
         st.append(preview)
     # merge and trim
     st = merge_previews(st)
     st.trim(starttime, endtime, pad=pad)
     return st
Example #33
0
 def get_preview(self, trace_ids=[], starttime=None, endtime=None,
                 network=None, station=None, location=None, channel=None,
                 pad=False):
     """
     Returns the preview trace.
     """
     # build up query
     session = self.session()
     query = session.query(WaveformChannel)
     # start and end time
     try:
         starttime = UTCDateTime(starttime)
     except:
         starttime = UTCDateTime() - 60 * 20
     finally:
         query = query.filter(WaveformChannel.endtime > starttime.datetime)
     try:
         endtime = UTCDateTime(endtime)
     except:
         # 10 minutes
         endtime = UTCDateTime()
     finally:
         query = query.filter(WaveformChannel.starttime < endtime.datetime)
     # process arguments
     if trace_ids:
         # filter over trace id list
         trace_filter = or_()
         for trace_id in trace_ids:
             temp = trace_id.split('.')
             if len(temp) != 4:
                 continue
             trace_filter.append(and_(
                 WaveformChannel.network == temp[0],
                 WaveformChannel.station == temp[1],
                 WaveformChannel.location == temp[2],
                 WaveformChannel.channel == temp[3]))
         if trace_filter.clauses:
             query = query.filter(trace_filter)
     else:
         # filter over network/station/location/channel id
         kwargs = {'network': network, 'station': station,
                   'location': location, 'channel': channel}
         for key, value in kwargs.items():
             if value is None:
                 continue
             col = getattr(WaveformChannel, key)
             if '*' in value or '?' in value:
                 value = value.replace('?', '_')
                 value = value.replace('*', '%')
                 query = query.filter(col.like(value))
             else:
                 query = query.filter(col == value)
     # execute query
     results = query.all()
     session.close()
     # create Stream
     st = Stream()
     for result in results:
         preview = result.get_preview()
         st.append(preview)
     # merge and trim
     st = merge_previews(st)
     st.trim(starttime, endtime, pad=pad)
     return st
Example #34
0
def mergePreviews(stream):
    """
    Merges all preview traces in one Stream object. Does not change the
    original stream because the data needs to be copied anyway.

    :type stream: :class:`~obspy.core.Stream`
    :param stream: Stream object to be merged
    :rtype: :class:`~obspy.core.Stream`
    :return: Merged Stream object.
    """
    copied_traces = copy(stream.traces)
    stream.sort()
    # Group traces by id.
    traces = {}
    dtypes = []
    for trace in stream:
        # Throw away empty traces.
        if trace.stats.npts == 0:
            continue
        if not hasattr(trace.stats, 'preview') or not trace.stats.preview:
            msg = 'Trace\n%s\n is no preview file.' % str(trace)
            raise Exception(msg)
        traces.setdefault(trace.id, [])
        traces[trace.id].append(trace)
        dtypes.append(trace.data.dtype)
    if len(traces) == 0:
        return Stream()
    # Initialize new Stream object.
    new_stream = Stream()
    for value in traces.values():
        if len(value) == 1:
            new_stream.append(value[0])
            continue
        # All traces need to have the same delta value and also be on the same
        # grid spacing. It is enough to only check the sampling rate because
        # the algorithm that creates the preview assures that the grid spacing
        # is correct.
        sampling_rates = set([tr.stats.sampling_rate for tr in value])
        if len(sampling_rates) != 1:
            msg = 'More than one sampling rate for traces with id %s.' % \
                  value[0].id
            raise Exception(msg)
        delta = value[0].stats.delta
        # Check dtype.
        dtypes = set([str(tr.data.dtype) for tr in value])
        if len(dtypes) > 1:
            msg = 'Different dtypes for traces with id %s' % value[0].id
            raise Exception(msg)
        dtype = dtypes.pop()
        # Get the minimum start and maximum endtime for all traces.
        min_starttime = min([tr.stats.starttime for tr in value])
        max_endtime = max([tr.stats.endtime for tr in value])
        samples = (max_endtime - min_starttime) / delta + 1
        data = np.empty(samples, dtype=dtype)
        # Fill with negative one values which corresponds to a gap.
        data[:] = -1
        # Create trace and give starttime.
        new_trace = Trace(data=data, header=value[0].stats)
        # Loop over all traces in value and add to data.
        for trace in value:
            start_index = int((trace.stats.starttime - min_starttime) / delta)
            end_index = start_index + len(trace.data)
            # Element-by-element comparison.
            data[start_index:end_index] = \
                np.maximum(data[start_index:end_index], trace.data)
        # set npts again, because data is changed in place
        new_trace.stats.npts = len(data)
        new_stream.append(new_trace)
    stream.traces = copied_traces
    return new_stream
Example #35
0
def dataclean(alltrigs, opt, flag=1):

    """
    Examine triggers and weed out spikes and calibration pulses using kurtosis and
    outlier ratios
    
    alltrigs: triggers output from triggering
    opt: opt from config
    flag: 1 if defining window to check, 0 if want to check whole waveform for spikes
        (note that different threshold values should be used for different window lengths)
    
    Returns good trigs (trigs) and junk (junk)
    """
    
    trigs=Stream()
    junk=Stream()
    for i in range(len(alltrigs)):
            
        njunk = 0
        ntele = 0
        
        for n in range(opt.nsta):
            
            dat = alltrigs[i].data[n*opt.wshape:(n+1)*opt.wshape]
            if flag == 1:
                datcut=dat[range(int((opt.ptrig-opt.kurtwin/2)*opt.samprate),
                    int((opt.ptrig+opt.kurtwin/2)*opt.samprate))]
            else:
                datcut=dat
            
            # Calculate kurtosis in window
            k = stats.kurtosis(datcut)
            # Compute kurtosis of frequency amplitude spectrum next
            datf = np.absolute(fft(dat))
            kf = stats.kurtosis(datf)
            # Calculate outlier ratio using z ((data-median)/mad); outliers have z > 4.45
            mad = np.median(np.absolute(dat - np.median(dat)))
            z = (dat-np.median(dat))/mad
            orm = len(z[z>4.45])/np.array(len(z)).astype(float)
            
            if k >= opt.kurtmax or orm >= opt.oratiomax or kf >= opt.kurtfmax:
                njunk+=1
                
            winstart = opt.ptrig*opt.samprate - opt.winlen/10
            winend = opt.ptrig*opt.samprate - opt.winlen/10 + opt.winlen
            fftwin = np.reshape(fft(dat[winstart:winend]),(opt.winlen,))
            if np.median(np.abs(dat[winstart:winend]))!=0:
                fi = np.log10(np.mean(np.abs(np.real(
                    fftwin[int(opt.fiupmin*opt.winlen/opt.samprate):int(
                    opt.fiupmax*opt.winlen/opt.samprate)])))/np.mean(np.abs(np.real(
                    fftwin[int(opt.filomin*opt.winlen/opt.samprate):int(
                    opt.filomax*opt.winlen/opt.samprate)]))))
                if fi<opt.telefi:
                    ntele+=1
        
        # Allow if there are enough good stations to correlate
        if njunk <= (opt.nsta-opt.ncor) and ntele <= opt.teleok:
            trigs.append(alltrigs[i])
        else:
            junk.append(alltrigs[i])
            
                
    return trigs, junk
Example #36
0
def trigger(st, stC, rtable, opt):

    """
    Run triggering algorithm on a stream of data.

    st: OBSPy stream of data
    rtable: Repeater table contains reference time of previous trigger in samples
    opt: Options object describing station/run parameters

    Returns triggered traces as OBSPy trace object updates ptime for next run 
    """
    
    tr = st[0]
    t = tr.stats.starttime

    cft = coincidence_trigger("classicstalta", opt.trigon, opt.trigoff, stC, opt.nstaC,
        sta=opt.swin, lta=opt.lwin, details=True)
    if len(cft) > 0:
        
        ind = 0
        
        # Slice out the data from st and save the maximum STA/LTA ratio value for
        # use in orphan expiration
        
        # Convert ptime from time of last trigger to seconds before start time
        if rtable.attrs.ptime:
            ptime = (UTCDateTime(rtable.attrs.ptime) - t)
        else:
            ptime = -opt.mintrig
        
        for n in range(len(cft)):
                    
            ttime = cft[n]['time'] # This is a UTCDateTime, not samples
            
            if (ttime >= t + opt.atrig) and (ttime >= t + ptime +
                opt.mintrig) and (ttime < t + len(tr.data)/opt.samprate -
                2*opt.atrig):
                
                ptime = ttime - t
                
                # Slice and save as first trace              
                ttmp = st.slice(ttime - opt.ptrig, ttime + opt.atrig)
                ttmp[0].data = ttmp[0].data[0:opt.wshape] - np.mean(
                    ttmp[0].data[0:opt.wshape])
                for s in range(1,len(ttmp)):
                    ttmp[0].data = np.append(ttmp[0].data, ttmp[s].data[
                        0:opt.wshape] - np.mean(ttmp[s].data[0:opt.wshape]))
                ttmp[0].stats.maxratio = np.max(cft[n]['cft_peaks'])
                if ind is 0:
                    trigs = Stream(ttmp[0])
                    ind = ind+1
                else:
                    trigs = trigs.append(ttmp[0])
                                                         
        if ind is 0:
            return []
        else:
            rtable.attrs.ptime = (t + ptime).isoformat()
            return trigs
    else:
        return []
Example #37
0
def stream_stack_distance_intervals(st, interval, norm_type='no'):
    """ Stack average traces in a stream if their distance difference is
    smaller than interval.

    The stream containing a number of traces with given distance (e.g. from source)
    is used to create a number of equally spaced traces by averaging traces that fall
    into the same distance bin. If interval is a scalar the bins are equally spaced with
    a width of interval. If interval is a sequence its elements define the lower distance
    limit of the bins.

    :type st: :class:`~obspy.core.stream.Stream`
    :param st: Stream fo be used for stacking.
    :type interval: scalar os array like
    :param interval: width of bins in case of scalar or smaller edge of
        bins if interval is a sequence.
    :type norm_type: str
    :param norm_type: normalization to be applied within bins before stacking
        Possibilities are `no` for no normalization, `max` for normalization 
        to maximum, `rms` for normaliation to root mean square or `abs_mean`
        for normalization to the mean of the absolute value.
    :rtype sst: :class:`~obspy.core.stream.Stream`
    :return: **sst**: stacked stream
    """
    dist = []
    npts = []
    for tr in st:
        dist.append(tr.stats.sac['dist'])
        npts.append(tr.stats['npts'])
    
    if not hasattr(interval, "__len__"):
        bins = np.arange(min(dist), max(dist),interval)
    else:
        bins = np.array(interval)
    
    sst = Stream()
    for ii in bins:
        sst.append(Trace(data=np.zeros(max(npts),dtype=np.float64),header={
            'network':'stack','station':str(ii),'location':'',
            'channel':st[0].stats['channel'],'starttime':st[0].stats['starttime'],'sampling_rate':st[0].stats['sampling_rate'],
            'sac':{'dist':ii,'az':0,'evla':0.,'evlo':0.,'stla':ii/(np.pi*6371000)*180.,'stlo':0.}}))
    count = np.zeros_like(bins)
    weight = np.zeros_like(bins)
    for tr in st:
        ind = sum((tr.stats.sac['dist'] - bins)>=0)-1
        if norm_type == 'no':
            norm = 1.
        elif norm_type == 'max':
            norm = np.max(np.abs(tr.data))
        elif norm_type == 'rms':
            norm = np.sqrt(np.mean(tr.data**2))
        elif norm_type == 'abs_mean':
            norm = np.mean(np.abs(tr.data))
        else:
            raise ValueError('norm_type %s not implemented' % norm_type)
        sst[ind].data[0:tr.stats['npts']] += (tr.data/norm)
        weight[ind] += norm
        count[ind] += 1
    for ind, tr in enumerate(sst):
        tr.data *= weight[ind]/(count[ind]**2)
    
    return sst
def removeGaps(self, min_gap, max_gap, verbose="False"): 

    """
    Returns the Stream object without trace gaps/overlaps.
    :param min_gap: All gaps smaller than this value will be omitted. The
          value is assumed to be in seconds. Defaults to None.
    :param max_gap: All gaps larger than this value will be omitted. The
          value is assumed to be in seconds. Defaults to None.
    :param verbose: stdout traces removed. Default verbose=False
    """

    new=Stream()
    self.sort()
    gap_list = []

    # since one would be left
    if(len(self) != 0):
      self.append(self[0])

    for _i in xrange(1,len(self.traces) - 0):
       # skip traces with different network, station, location or channel
       if self.traces[_i - 1].id != self.traces[_i + 0].id:
          new.append(self.traces[_i])
          continue
       # different sampling rates should always result in a gap or overlap
       if self.traces[_i - 1].stats.delta == self.traces[_i + 0].stats.delta:
          flag = True
       else:
          flag = False
       stats = self.traces[_i - 1].stats
       stime = stats['endtime']
       etime = self.traces[_i + 0].stats['starttime']
       delta = etime.timestamp - stime.timestamp

       # Check that any overlap is not larger than the trace coverage
       if delta < 0:
             temp = self.traces[_i + 0].stats['endtime'].timestamp - \
                    etime.timestamp
             if (delta * -1) > temp:
                 delta = -1 * temp
       # Check gap/overlap criteria
       if min_gap and delta < min_gap:
             new.append(self.traces[_i - 1])
             continue
       if max_gap and delta > max_gap:
             new.append(self.traces[_i - 1])
             continue
       # Number of missing samples
       nsamples = int(round(fabs(delta) * stats['sampling_rate']))
       # skip if is equal to delta (1 / sampling rate)
       if flag and nsamples == 1:
             new.append(self.traces[_i - 1])
             continue
       elif delta > 0:
             nsamples -= 1
       else:
             nsamples += 1

       gap_list.append([_i,stats['network'], stats['station'],
                             stats['location'], stats['channel'],
                             stime, etime, delta, nsamples])
       if verbose == "True" or verbose == "TRUE" or verbose == "true":
          print  "Removed because of gap: ",stats['network'],stats['station'],stats['channel'],stime,etime,delta, nsamples

    return new
Example #39
0
def group_channels(streams):
    """Consolidate streams for the same event.

    Checks to see if there are channels for one event in different streams, and
    groups them into one stream. Then streams are checked for duplicate
    channels (traces).

    Args:
        streams (list): List of Stream objects.
    Returns:
        list: List of Stream objects.
    """
    # Return the original stream if there is only one
    if len(streams) <= 1:
        return streams

    # Get the all traces
    trace_list = []
    for stream in streams:
        for trace in stream:
            trace_list += [trace]

    # Create a list of duplicate traces and event matches
    duplicate_list = []
    match_list = []
    for idx1, trace1 in enumerate(trace_list):
        matches = []
        network = trace1.stats['network']
        station = trace1.stats['station']
        starttime = trace1.stats['starttime']
        endtime = trace1.stats['endtime']
        channel = trace1.stats['channel']
        location = trace1.stats['location']
        if 'units' in trace1.stats.standard:
            units = trace1.stats.standard['units']
        else:
            units = ''
        if 'process_level' in trace1.stats.standard:
            process_level = trace1.stats.standard['process_level']
        else:
            process_level = ''
        data = np.asarray(trace1.data)
        for idx2, trace2 in enumerate(trace_list):
            if idx1 != idx2 and idx1 not in duplicate_list:
                event_match = False
                duplicate = False
                try:
                    same_data = ((data == np.asarray(trace2.data)).all())
                except AttributeError:
                    same_data = (data == np.asarray(trace2.data))
                if 'units' in trace2.stats.standard:
                    units2 = trace2.stats.standard['units']
                else:
                    units2 = ''
                if 'process_level' in trace2.stats.standard:
                    process_level2 = trace2.stats.standard['process_level']
                else:
                    process_level2 = ''
                if (network == trace2.stats['network']
                        and station == trace2.stats['station']
                        and starttime == trace2.stats['starttime']
                        and endtime == trace2.stats['endtime']
                        and channel == trace2.stats['channel']
                        and location == trace2.stats['location']
                        and units == units2 and process_level == process_level2
                        and same_data):
                    duplicate = True
                elif (network == trace2.stats['network']
                      and station == trace2.stats['station']
                      and starttime == trace2.stats['starttime']
                      and location == trace2.stats['location']
                      and units == units2 and process_level == process_level2):
                    event_match = True
                if duplicate:
                    duplicate_list += [idx2]
                if event_match:
                    matches += [idx2]
        match_list += [matches]

    # Create an updated list of streams
    streams = []
    for idx, matches in enumerate(match_list):
        stream = Stream()
        grouped = False
        for match_idx in matches:
            if match_idx not in duplicate_list:
                if idx not in duplicate_list:
                    stream.append(trace_list[match_idx])
                    duplicate_list += [match_idx]
                    grouped = True
        if grouped:
            stream.append(trace_list[idx])
            duplicate_list += [idx]
            streams += [stream]

    # Check for ungrouped traces
    for idx, trace in enumerate(trace_list):
        if idx not in duplicate_list:
            stream = Stream()
            streams += [stream.append(trace)]
            warnings.warn('One channel stream:\n%s' % (stream), Warning)

    return streams
Example #40
0
File: db.py Project: ftilmann/miic
        return None, None

    # Create the Stream obj and populate it
    st = Stream()
    for (_, rec) in df.iterrows():
        fname = os.path.join(rec['path'], rec['file'])
        for tr in _read(fname, fformat, headonly=False, **kwargs).traces:
            if (networks_ok) and (tr.stats.network not in networks):
                continue
            if (stations_ok) and (tr.stats.station not in stations):
                continue
            if (locations_ok) and (tr.stats.location not in locations):
                continue
            if (channels_ok) and (tr.stats.channel not in channels):
                continue
            st.append(tr)

    if st.count() > 0:
        # If the starttime is given then it trims the resulting traces
        if starttime:
            st.trim(starttime=starttime, endtime=endtime,
                    nearest_sample=nearest_sample)

        st.merge(method=1, fill_value=0, interpolation_samples=1)
    else:
        print "Empty stream"

    n_trace = st.count()
    return st, n_trace