Example #1
0
 def setUp(self):
     # directory where the test files are located
     self.path = os.path.join(os.path.dirname(__file__), 'data')
     self.filename_css = os.path.join(self.path, 'test_css.wfdisc')
     self.filename_nnsa = os.path.join(self.path, 'test_nnsa.wfdisc')
     # set up stream for validation
     header = {}
     header['station'] = 'TEST'
     header['starttime'] = UTCDateTime(1296474900.0)
     header['sampling_rate'] = 80.0
     header['calib'] = 1.0
     header['calper'] = 1.0
     header['_format'] = 'CSS'
     filename = os.path.join(self.path, '201101311155.10.ascii.gz')
     with gzip.open(filename, 'rb') as fp:
         data = np.loadtxt(fp, dtype=np.int_)
     # traces in the test files are sorted ZEN
     st = Stream()
     for x, cha in zip(data.reshape((3, 4800)), ('HHZ', 'HHE', 'HHN')):
         # big-endian copy
         tr = Trace(x, header.copy())
         tr.stats.station += 'be'
         tr.stats.channel = cha
         st += tr
         # little-endian copy
         tr = Trace(x, header.copy())
         tr.stats.station += 'le'
         tr.stats.channel = cha
         st += tr
     self.st_result_css = st.copy()
     for tr in st:
         tr.stats['_format'] = "NNSA_KB_CORE"
     self.st_result_nnsa = st
Example #2
0
 def setUp(self):
     # directory where the test files are located
     self.path = os.path.join(os.path.dirname(__file__), 'data')
     self.filename_css = os.path.join(self.path, 'test_css.wfdisc')
     self.filename_nnsa = os.path.join(self.path, 'test_nnsa.wfdisc')
     self.filename_css_2 = os.path.join(self.path, 'test_css_2.wfdisc')
     self.filename_css_3 = os.path.join(self.path, 'test_css_3.wfdisc')
     # set up stream for validation
     header = {}
     header['station'] = 'TEST'
     header['starttime'] = UTCDateTime(1296474900.0)
     header['sampling_rate'] = 80.0
     header['calib'] = 1.0
     header['calper'] = 1.0
     header['_format'] = 'CSS'
     filename = os.path.join(self.path, '201101311155.10.ascii.gz')
     with gzip.open(filename, 'rb') as fp:
         data = np.loadtxt(fp, dtype=np.int_)
     # traces in the test files are sorted ZEN
     st = Stream()
     for x, cha in zip(data.reshape((3, 4800)), ('HHZ', 'HHE', 'HHN')):
         # big-endian copy
         tr = Trace(x, header.copy())
         tr.stats.station += 'be'
         tr.stats.channel = cha
         st += tr
         # little-endian copy
         tr = Trace(x, header.copy())
         tr.stats.station += 'le'
         tr.stats.channel = cha
         st += tr
     self.st_result_css = st.copy()
     for tr in st:
         tr.stats['_format'] = "NNSA_KB_CORE"
     self.st_result_nnsa = st
Example #3
0
def update_waveform():

    # Load new data
    global st
    st = Stream()

    st = utils.get_stream(settings['datasource'], settings['scnl'],
                          UTCDateTime(start_input.value),
                          UTCDateTime(start_input.value) + 30 * 60)
    st = st.filter('bandpass', freqmin=FREQMIN, freqmax=FREQMAX)

    # Initialize data source for filtered waveform plotting
    st_plot = st.copy()
    st_plot.filter('lowpass', freq=20.0)
    offset = len(
        st
    ) * 2 - 2  # offset is defined and incremented such that (e.g.) four channels will be plotted top to bottom at center values 6,4,2,0
    times = []
    traces = []
    for s in st_plot:
        times.append(num2date(s.times('matplotlib')))
        traces.append(s.data / max(s.data) + offset)
        offset -= 2
    waveclr = ['black'] * len(st)
    source_waveforms.data = {
        'times': times,
        'traces': traces,
        'color': waveclr
    }

    # Update the CFT
    update_cft(ticker_alg.value)
Example #4
0
def QC_streams(start, end, st):

    # Check start times
    if not np.all([tr.stats.starttime == start for tr in st]):
        print("* Start times are not all close to true start: ")
        [
            print("*   " + tr.stats.channel + " " + str(tr.stats.starttime) +
                  " " + str(tr.stats.endtime)) for tr in st
        ]
        print("*   True start: " + str(start))
        print("* -> Shifting traces to true start")
        delay = [tr.stats.starttime - start for tr in st]
        st_shifted = Stream(
            traces=[traceshift(tr, dt) for tr, dt in zip(st, delay)])
        st = st_shifted.copy()

    # # Check sampling rate
    # sr = st[0].stats.sampling_rate
    # sr_round = float(floor_decimal(sr, 0))
    # if not sr == sr_round:
    #     print("* Sampling rate is not an integer value: ", sr)
    #     print("* -> Resampling")
    #     st.resample(sr_round, no_filter=False)

    # Try trimming
    dt = st[0].stats.delta
    try:
        st.trim(start, end - dt, fill_value=0., pad=True)
    except:
        print("* Unable to trim")
        print("* -> Skipping")
        print("**************************************************")
        return False, None

    # Check final lengths - they should all be equal if start times
    # and sampling rates are all equal and traces have been trimmed
    sr = st[0].stats.sampling_rate
    if not np.allclose([tr.stats.npts for tr in st[1:]], st[0].stats.npts):
        print("* Lengths are incompatible: ")
        [print("*     " + str(tr.stats.npts)) for tr in st]
        print("* -> Skipping")
        print("**************************************************")

        return False, None

    elif not np.allclose([st[0].stats.npts], int((end - start) * sr), atol=1):
        print("* Length is too short: ")
        print("*    " + str(st[0].stats.npts) + " ~= " +
              str(int((end - start) * sr)))
        print("* -> Skipping")
        print("**************************************************")

        return False, None

    else:
        return True, st
Example #5
0
File: hk.py Project: shineusn/RfPy
    def _residuals(self):
        """ 
        Internal method to obtain residuals between observed and predicted
        receiver functions given the Moho depth and Vp/Vs obtained from
        the Hk stack.
        """
        from telewavesim import utils

        # Simple 1-layer model over half-space
        model = utils.Model([self.h0, 0.], [2800., 3300.], [self.vp, 8.0],
                            [self.vp / self.k0, 4.5], ['iso', 'iso'])

        # Parameters for run
        slow = [tr.stats.slow for tr in self.rfV1]
        npts = self.rfV1[0].stats.npts
        dt = self.rfV1[0].stats.delta

        trR = Stream()

        for sl in slow:
            trxyz = utils.run_plane(model, sl, npts, dt)
            tfs = utils.tf_from_xyz(trxyz,
                                    pvh=True,
                                    vp=self.vp,
                                    vs=self.vp / self.k0)
            tfs[0].data = np.fft.fftshift(tfs[0].data)
            trR.append(tfs[0])

        trR.filter('bandpass',
                   freqmin=0.05,
                   freqmax=0.5,
                   corners=2,
                   zerophase=True)

        # Get stream of residuals
        res = trR.copy()
        for i in range(len(res)):
            res[i].data = self.rfV1[i].data - trR[i].data
        return res
Example #6
0
    summary += exceptions
summary.append("#" * 79)

trig = []
mutt = []
if st:
    # preprocessing, backup original data for plotting at end
    st.merge(0)
    st.detrend("linear")
    for tr in st:
        tr.data = tr.data * cosTaper(len(tr), 0.01)
    #st.simulate(paz_remove="self", paz_simulate=cornFreq2Paz(1.0), remove_sensitivity=False)
    st.sort()
    st.filter("bandpass", freqmin=PAR.LOW, freqmax=PAR.HIGH, corners=1, zerophase=True)
    st.trim(T1, T2)
    st_trigger = st.copy()
    st.normalize(global_max=False)
    # do the triggering
    trig = coincidenceTrigger("recstalta", PAR.ON, PAR.OFF, st_trigger,
            thr_coincidence_sum=PAR.MIN_STATIONS,
            max_trigger_length=PAR.MAXLEN, trigger_off_extension=PAR.ALLOWANCE,
            details=True, sta=PAR.STA, lta=PAR.LTA)

    for t in trig:
        info = "%s %ss %s %s" % (t['time'].strftime("%Y-%m-%dT%H:%M:%S"), ("%.1f" % t['duration']).rjust(4), ("%i" % t['cft_peak_wmean']).rjust(3), "-".join(t['stations']))
        summary.append(info)
        tmp = st.slice(t['time'] - 1, t['time'] + t['duration'])
        outfilename = "%s/%s_%.1f_%i_%s-%s_%s.png" % (PLOTDIR, t['time'].strftime("%Y-%m-%dT%H:%M:%S"), t['duration'], t['cft_peak_wmean'], len(t['stations']), num_stations, "-".join(t['stations']))
        tmp.plot(outfile=outfilename)
        mutt += ("-a", outfilename)
Example #7
0
def correlate(io,
              day,
              outkey,
              edge=60,
              length=3600,
              overlap=1800,
              demean_window=True,
              discard=None,
              only_auto_correlation=False,
              station_combinations=None,
              component_combinations=('ZZ', ),
              max_lag=100,
              keep_correlations=False,
              stack='1d',
              njobs=0,
              **preprocessing_kwargs):
    """
    Correlate data of one day

    :param io: io config dictionary
    :param day: |UTC| object with day
    :param outkey: the output key for the HDF5 index
    :param edge: additional time span requested from day before and after
        in seconds
    :param length: length of correlation in seconds (string possible)
    :param overlap: length of overlap in seconds (string possible)
    :param demean_window: demean each window individually before correlating
    :param discard: discard correlations with less data coverage
        (float from interval [0, 1])
    :param only_auto_correlations: Only correlate stations with itself
        (different components possible)
    :param station_combinations: specify station combinations
        (e.g. ``'CX.PATCX-CX.PB01``, network code can be
        omitted, e.g. ``'PATCX-PB01'``, default: all)
    :param component_combinations: component combinations to calculate,
        tuple of strings with length two, e.g. ``('ZZ', 'ZN', 'RR')``,
        if ``'R'`` or ``'T'`` is specified, components will be rotated after
        preprocessing, default: only ZZ components
    :param max_lag: max time lag in correlations in seconds
    :param keep_correlatons: write correlations into HDF5 file (dafault: False)
    :param stack: stack correlations and write stacks into HDF5 file
        (default: ``'1d'``, must be smaller than one day or one day)

        .. note::

            If you want to stack larger time spans
            use the separate stack command on correlations or stacked
            correlations.

    :param njobs: number of jobs used. Some tasks will run parallel
        (preprocessing and correlation).
    :param \*\*preprocessing_kwargs: all other kwargs are passed to
        `preprocess`

    """
    inventory = io['inventory']
    length = _time2sec(length)
    overlap = _time2sec(overlap)
    if not keep_correlations and stack is None:
        msg = ('keep_correlation is False and stack is None -> correlations '
               ' would not be saved')
        raise ValueError(msg)
    components = set(''.join(component_combinations))
    if 'R' in components or 'T' in components:
        load_components = components - {'R', 'T'} | {'N', 'E'}
    else:
        load_components = components
    if station_combinations is not None:
        load_stations = set(sta for comb in station_combinations
                            for sta in comb.split('-'))
    else:
        load_stations = None
    # load data
    stream = obspy.Stream()
    for smeta in _iter_station_meta(inventory, load_components):
        if (load_stations is not None and smeta['station'] not in load_stations
                and '.'.join((smeta['network'], smeta['station']))
                not in load_stations):
            continue
        stream2 = get_data(smeta,
                           io['data'],
                           io['data_format'],
                           day,
                           overlap=overlap,
                           edge=edge)
        if stream2:
            stream += stream2
    if len(stream) == 0:
        log.warning('empty stream for day %s', str(day)[:10])
        return
    preprocess(stream,
               day,
               inventory,
               overlap=overlap,
               njobs=njobs,
               **preprocessing_kwargs)
    # collect trace pairs for correlation
    next_day = day + 24 * 3600
    stations = sorted({tr.id[:-1] for tr in stream})
    tasks = []
    for station1, station2 in itertools.combinations_with_replacement(
            stations, 2):
        if only_auto_correlation and station1 != station2:
            continue
        if station_combinations and not any(
                set(station_comb.split('-')) ==
            ({station1.rsplit('.', 2)[0],
              station2.rsplit('.', 2)[0]} if '.' in (station_comb) else
             {station1.
              split('.')[1], station2.split('.')[1]})
                for station_comb in station_combinations):
            continue
        stream1 = Stream([tr for tr in stream if tr.id[:-1] == station1])
        stream2 = Stream([tr for tr in stream if tr.id[:-1] == station2])
        datetime1 = _midtime(stream1[0].stats)
        datetime2 = _midtime(stream2[0].stats)
        msg = 'Cannot get coordinates for channel %s datetime %s'
        try:
            c1 = inventory.get_coordinates(stream1[0].id, datetime=datetime1)
        except Exception as ex:
            raise RuntimeError(msg % (stream1[0].id, datetime1)) from ex
        try:
            c2 = inventory.get_coordinates(stream2[0].id, datetime=datetime2)
        except Exception as ex:
            raise RuntimeError(msg % (stream2[0].id, datetime2)) from ex
        args = (c1['latitude'], c1['longitude'], c2['latitude'],
                c2['longitude'])
        dist, azi, baz = gps2dist_azimuth(*args)
        if ('R' in components or 'T' in components) and station1 != station2:
            stream1 = stream1.copy()
            stream1b = stream1.copy().rotate('NE->RT', azi)
            stream1.extend(stream1b.select(component='R'))
            stream1.extend(stream1b.select(component='T'))
            stream2 = stream2.copy()
            stream2b = stream2.copy().rotate('NE->RT', azi)
            stream2.extend(stream2b.select(component='R'))
            stream2.extend(stream2b.select(component='T'))
        it_ = (itertools.product(stream1, stream2) if station1 != station2 else
               itertools.combinations_with_replacement(stream1, 2))
        for tr1, tr2 in it_:
            comps = tr1.stats.channel[-1] + tr2.stats.channel[-1]
            if component_combinations and (comps not in component_combinations
                                           and comps[::-1]
                                           not in component_combinations):
                continue
            tasks.append((tr1, tr2, dist, azi, baz))
    # start correlation
    do_work = partial(_slide_and_correlate_traces, day, next_day, length,
                      overlap, discard, max_lag, outkey, demean_window)
    streams = start_parallel_jobs_inner_loop(tasks, do_work, njobs)
    xstream = Stream()
    xstream.traces = [tr for s_ in streams for tr in s_]
    if len(xstream) > 0:
        res = {}
        if keep_correlations:
            res['corr'] = xstream
        if stack:
            res['stack'] = yam.stack.stack(xstream, stack)
        return res
class Seedlink_plotter(SLClient):
    """
    This module plots realtime seismic data from a Seedlink server
    """

    def __init__(self, figure, canvas, interval, backtrace, args):

        # Set the log level to display minimal info
        super(Seedlink_plotter, self).__init__(loglevel='CRITICAL')
#         super(Seedlink_plotter, self).__init__()
        self.figure = figure
        self.stream = Stream()
        self.interval = interval
        self.backtrace = backtrace
        self.canvas = canvas
        self.flip = 0
        self.scale = args.scale
        self.args = args
        self.initial_update_rate = 800
        self.update_rate = 2
        # Plot after geting the penultimate line of data
        self.print_percentage = (
            self.backtrace-60.0*self.interval)/self.backtrace
        self.print_max = (self.backtrace-60.0*self.interval)
        widgets = [FormatLabel('Receiving Data: - '), BouncingBar(
            marker=RotatingMarker())]
        self.pbar = ProgressBar(maxval=self.print_max, widgets=widgets).start()
#         print "max "+ str(self.print_max)

        # converter for the colors gradient
    def rgb_to_hex(self, r, g, b):
        return '#%02X%02X%02X' % (r, g, b)

        # Rainbow color generator
    def rainbow_color_generator(self, max_color):
        color_list = []
        frequency = 0.3
        for compteur_lignes in xrange(max_color):
            red = sin(frequency*compteur_lignes*2 + 0)*127+128
            green = sin(frequency*compteur_lignes*2 + 2)*127+128
            blue = sin(frequency*compteur_lignes*2 + 4)*127+128

            color_list.append(self.rgb_to_hex(red, green, blue))

        return tuple(color_list)

    def plot_graph(self):

        #######################################################################
        # filter section
        #######################################################################
        self.local_stream = self.stream.copy()
        # Filter example
#         self.local_stream.filter('bandpass', freqmin=0.001, freqmax=0.5,corners=2, zerophase=True)
        #######################################################################

        # With this upscale factor the graph  look nice !
        upscale_factor = 30

        if args.rainbow:
            # Rainbow colors !
            self.color = self.rainbow_color_generator(
                int(args.nb_rainbow_colors))
        else:
            # Regular colors
            self.color = ('#000000', '#ff0000', '#0000ff', '#56a83c')

        self.local_stream.plot(
            fig=self.figure, type='dayplot', interval=self.interval,
            number_of_ticks=13, tick_format='%d/%m %Hh',
            size=(args.x_size * upscale_factor, args.y_size * upscale_factor),
            x_labels_size=8,
            y_labels_size=8, title=self.title, title_size=14, linewidth=0.5, right_vertical_labels=False,
            vertical_scaling_range=self.scale,
            subplots_adjust_left=0.03, subplots_adjust_right=0.99,
            subplots_adjust_top=0.95, subplots_adjust_bottom=0.1,
            one_tick_per_line=True,
            # noir  Rouge bleu vert
            color = self.color,
            show_y_UTC_label=False)

    def packetHandler(self, count, slpack):
        """
        Processes each packet received from the SeedLinkConnection.
        :type count: int
        :param count:  Packet counter.
        :type slpack: :class:`~obspy.seedlink.SLPacket`
        :param slpack: packet to process.
        :return: Boolean true if connection to SeedLink server should be
            closed and session terminated, false otherwise.
        """

        # check if not a complete packet
        if slpack is None or (slpack == SLPacket.SLNOPACKET) or \
                (slpack == SLPacket.SLERROR):
            return False

        # get basic packet info
        type = slpack.getType()

        # process INFO packets here
        if (type == SLPacket.TYPE_SLINF):
            return False
        if (type == SLPacket.TYPE_SLINFT):
#             print "Complete INFO:\n" + self.slconn.getInfoString()
            if self.infolevel is not None:
                return True
            else:
                return False

        # process packet data
        trace = slpack.getTrace()
        if trace is None:
            print self.__class__.__name__ + ": blockette contains no trace"
            return False

        # new samples add to the main stream
        self.stream += trace
        self.stream.merge()

        now = UTCDateTime()

        # Stop time will be the next round date
        stop_time = UTCDateTime(
            now.year, now.month, now.day, now.hour, 0, 0)+3600
        start_time = stop_time-self.backtrace

        # Limit the stream size
        self.stream = self.stream.slice(start_time, stop_time)
        self.stream.trim(start_time, stop_time)

        self.title = self.stream.traces[0].stats.station+" "+self.stream.traces[0].stats.network+" "+self.stream.traces[
            0].stats.location+" "+self.stream.traces[0].stats.channel+' scale: '+str(self.scale) + " - non filtre"

        stream_time_length = self.stream.traces[
            0].stats.endtime - self.stream.traces[0].stats.starttime

        ### Before we reach  print_percentage of the time data to plot, we plot each initial_update_rate we received
#         if (stream_time_length < (self.backtrace*self.print_percentage)):
#        if ((stream_time_length))<(self.backtrace-60.0*self.interval):
#         print str(stream_time_length)+"/"+str(self.print_max)
        if stream_time_length <= self.print_max:

            self.flip += 1

#             if ((stream_time_length))<(self.backtrace-60.0*self.interval):
            self.pbar.update(stream_time_length+1)
#             print str(stream_time_length)+"/"+str(self.print_max)
            if (self.flip > self.initial_update_rate):
                self.flip = 0
                self.figure.clear()
                self.plot_graph()

 #             self.pbar.finish()

        # Real time plotting
        # We plot each update_rate packet we received
        # if (stream_time_length >= (self.backtrace*self.print_percentage)):
        if ((stream_time_length)) > (self.print_max):
#             print str(stream_time_length)+"/"+str(self.print_max)

            self.flip += 1
            if (self.flip > self.update_rate):
                self.figure.clear()
                self.plot_graph()
                self.flip = 0

        return False
Example #9
0
fs = st2[0].stats.sampling_rate
if debug:
    print("Sample rate is ", fs)
total_count = Window * fs

# Start of Sliding window loop to calculate orientation angle
for stW in st.slide(Window, (1. - Overlap) * Window):
    print('On day: ' + str(stW[0].stats.starttime))

    # Get start and end times and trim accordingly
    starttime = stW[0].stats.starttime

    endtime = starttime + Window

    st2W = st2.copy()
    st2W.trim(starttime, endtime)

    stPW = stP.copy()
    stPW.trim(starttime, endtime)

    # Fill data gaps and detrend
    stW.merge(fill_value=0.)
    st2W.merge(fill_value=0.)
    stPW.merge(fill_value=0.)

    data_count = np.count_nonzero(st2W[0].data)
    if data_count / total_count >= Comp_Thres:

        try:
Example #10
0
    if st.count() > 0: # need waveforms to continue
        std = Stream()
        for tr in st:
            num = tr.stats.npts
            samp = tr.stats.sampling_rate             
            if num >= (samp*86400)*.8:
                std.append(tr)
        
        print('number of good waveforms ', std.count())
        if std.count() < 3: # want 3 or more waveforms for templates
            print('skipping event not enough good waveforms')
            
        else:         
            std.sort(['starttime'])
            std.merge(fill_value="interpolate")
            st1=std.copy()
            
            start = UTCDateTime(year = yr, julday = days)
            end = start + 86400
            st_filter=st1.trim(starttime=start, endtime=end)
        
#            print('GENERATING TEMPLATE FOR ' + str(start) +   ' SAVING AS MINISEED FILES & PLOTS ARE SAVED TO FOLDER.')
            # template matching
            template = template_gen.from_meta_file(meta_file = new_catalog, st = st_filter,
                                                   lowcut = 3, highcut = 10, filt_order = 4, samp_rate = 25,
                                                   prepick = 0.15, length = 4.6, swin = 'P',
                                                   parallel = True)
            
            if len(template[0]) < 3:
                print('Skipping template -- %i picks & %i WF in template' % (n_picks[i], len(template[0])))
                
Example #11
0
class WaveformPlotting(object):
    """
    Class that provides several solutions for plotting large and small waveform
    data sets.

    .. warning::
        This class should NOT be used directly, instead use the
        :meth:`~obspy.core.stream.Stream.plot` method of the
        ObsPy :class:`~obspy.core.stream.Stream` or
        :class:`~obspy.core.trace.Trace` objects.

    It uses matplotlib to plot the waveforms.
    """

    def __init__(self, **kwargs):
        """
        Checks some variables and maps the kwargs to class variables.
        """
        self.stream = kwargs.get('stream')
        # Check if it is a Stream or a Trace object.
        if isinstance(self.stream, Trace):
            self.stream = Stream([self.stream])
        elif not isinstance(self.stream, Stream):
            msg = 'Plotting is only supported for Stream or Trace objects.'
            raise TypeError(msg)
        # Stream object should contain at least one Trace
        if len(self.stream) < 1:
            msg = "Empty object"
            raise IndexError(msg)
        # Type of the plot.
        self.type = kwargs.get('type', 'normal')
        # Start- and endtimes of the plots.
        self.starttime = kwargs.get('starttime', None)
        self.endtime = kwargs.get('endtime', None)
        self.fig_obj = kwargs.get('fig', None)
        # If no times are given take the min/max values from the stream object.
        if not self.starttime:
            self.starttime = min([trace.stats.starttime for \
                             trace in self.stream])
        if not self.endtime:
            self.endtime = max([trace.stats.endtime for \
                           trace in self.stream])
        # Map stream object and slice just in case.
        self.stream = self.stream.slice(self.starttime, self.endtime)
        # normalize times
        if self.type == 'relative':
            dt = self.starttime
            # fix plotting boundaries
            self.endtime = UTCDateTime(self.endtime - self.starttime)
            self.starttime = UTCDateTime(0)
            # fix stream times
            for tr in self.stream:
                tr.stats.starttime = UTCDateTime(tr.stats.starttime - dt)
        # Whether to use straight plotting or the fast minmax method.
        self.plotting_method = kwargs.get('method', 'fast')
        # Below that value the data points will be plotted normally. Above it
        # the data will be plotted using a different approach (details see
        # below). Can be overwritten by the above self.plotting_method kwarg.
        self.max_npts = 400000
        # If automerge is enabled. Merge traces with the same id for the plot.
        self.automerge = kwargs.get('automerge', True)
        # Set default values.
        # The default value for the size is determined dynamically because
        # there might be more than one channel to plot.
        self.size = kwargs.get('size', None)
        # Values that will be used to calculate the size of the plot.
        self.default_width = 800
        self.default_height_per_channel = 250
        if not self.size:
            self.width = 800
            # Check the kind of plot.
            if self.type == 'dayplot':
                self.height = 600
            else:
                # One plot for each trace.
                if self.automerge:
                    count = []
                    for tr in self.stream:
                        if hasattr(tr.stats, 'preview') and tr.stats.preview:
                            tr_id = tr.id + 'preview'
                        else:
                            tr_id = tr.id
                        if not tr_id in count:
                            count.append(tr_id)
                    count = len(count)
                else:
                    count = len(self.stream)
                self.height = count * 250
        else:
            self.width, self.height = self.size
        # Interval length in minutes for dayplot.
        self.interval = 60 * kwargs.get('interval', 15)
        # Scaling.
        self.vertical_scaling_range = kwargs.get('vertical_scaling_range',
                                                 None)
        # Dots per inch of the plot. Might be useful for printing plots.
        self.dpi = kwargs.get('dpi', 100)
        # Color of the graph.
        if self.type == 'dayplot':
            self.color = kwargs.get('color', ('#000000','#B2000F', '#004C12',
                                              '#0E01FF'))
            if isinstance(self.color, basestring):
                self.color = (self.color,)
            self.number_of_ticks = kwargs.get('number_of_ticks', None)
        else:
            self.color = kwargs.get('color', 'k')
            self.number_of_ticks = kwargs.get('number_of_ticks', 5)
        # Background and face color.
        self.background_color = kwargs.get('bgcolor', 'w')
        self.face_color = kwargs.get('face_color', 'w')
        # Transparency. Overwrites background and facecolor settings.
        self.transparent = kwargs.get('transparent', False)
        if self.transparent:
            self.background_color = None
        # Ticks.
        self.tick_format = kwargs.get('tick_format', '%H:%M:%S')
        self.tick_rotation = kwargs.get('tick_rotation', 0)
        # Whether or not to save a file.
        self.outfile = kwargs.get('outfile')
        self.handle = kwargs.get('handle')
        # File format of the resulting file. Usually defaults to PNG but might
        # be dependent on your matplotlib backend.
        self.format = kwargs.get('format')

    def plotWaveform(self, *args, **kwargs):
        """
        Creates a graph of any given ObsPy Stream object. It either saves the
        image directly to the file system or returns an binary image string.

        For all color values you can use legit HTML names, HTML hex strings
        (e.g. '#eeefff') or you can pass an R , G , B tuple, where each of
        R , G , B are in the range [0, 1]. You can also use single letters for
        basic built-in colors ('b' = blue, 'g' = green, 'r' = red, 'c' = cyan,
        'm' = magenta, 'y' = yellow, 'k' = black, 'w' = white) and gray shades
        can be given as a string encoding a float in the 0-1 range.
        """
        # Setup the figure if not passed explicitly.
        if not self.fig_obj:
            self.__setupFigure()
        else:
            self.fig = self.fig_obj
        # Determine kind of plot and do the actual plotting.
        if self.type == 'dayplot':
            self.plotDay(*args, **kwargs)
        else:
            self.plot(*args, **kwargs)
        # Adjust the subplot so there is always a margin of 80 px on every
        # side except for plots with just a single trace.
        if self.type != 'dayplot':
            if self.height >= 400:
                fract_y = 80.0 / self.height
            else:
                fract_y = 25.0 / self.height
            fract_x = 80.0 / self.width
            self.fig.subplots_adjust(top=1.0 - fract_y, bottom=fract_y,
                                     left=fract_x, right=1 - fract_x)
        self.fig.canvas.draw()
        # The following just serves as a unified way of saving and displaying
        # the plots.
        if not self.transparent:
            extra_args = {'dpi': self.dpi,
                          'facecolor': self.face_color,
                          'edgecolor': self.face_color}
        else:
            extra_args = {'dpi': self.dpi,
                          'transparent': self.transparent}
        if self.outfile:
            # If format is set use it.
            if self.format:
                self.fig.savefig(self.outfile, format=self.format,
                                 **extra_args)
            # Otherwise use format from self.outfile or default to PNG.
            else:
                self.fig.savefig(self.outfile, **extra_args)
        else:
            # Return an binary imagestring if not self.outfile but self.format.
            if self.format:
                imgdata = StringIO.StringIO()
                self.fig.savefig(imgdata, format=self.format,
                                 **extra_args)
                imgdata.seek(0)
                return imgdata.read()
            elif self.handle:
                return self.fig
            else:
                if not self.fig_obj:
                    plt.show()

    def plot(self, *args, **kwargs):
        """
        Plot the Traces showing one graph per Trace.

        Plots the whole time series for self.max_npts points and less. For more
        points it plots minmax values.
        """
        stream_new = []
        # Just remove empty traces.
        if not self.automerge:
            for tr in self.stream:
                stream_new.append([])
                if len(tr.data):
                    stream_new[-1].append(tr)
        else:
            # Generate sorted list of traces (no copy)
            # Sort order, id, starttime, endtime
            ids = []
            for tr in self.stream:
                if hasattr(tr.stats, 'preview') and tr.stats.preview:
                    id = tr.id + 'preview'
                else:
                    id = tr.id
                if not id in ids:
                    ids.append(id)
            for id in ids:
                stream_new.append([])
                for tr in self.stream:
                    if hasattr(tr.stats, 'preview') and tr.stats.preview:
                        tr_id = tr.id + 'preview'
                    else:
                        tr_id = tr.id
                    if tr_id == id:
                        # does not copy the elements of the data array
                        tr_ref = copy(tr)
                        # Trim does nothing if times are outside
                        if self.starttime >= tr_ref.stats.endtime or \
                                self.endtime <= tr_ref.stats.starttime:
                            continue
                        if tr_ref.data.size:
                            stream_new[-1].append(tr_ref)
                # delete if empty list
                if not len(stream_new[-1]):
                    stream_new.pop()
                    continue
                stream_new[-1].sort(key=lambda x: x.stats.endtime)
                stream_new[-1].sort(key=lambda x: x.stats.starttime)
        # If everything is lost in the process raise an Exception.
        if not len(stream_new):
            raise Exception("Nothing to plot")
        # Create helper variable to track ids and min/max/mean values.
        self.stats = []
        # Loop over each Trace and call the appropriate plotting method.
        self.axis = []
        for _i, tr in enumerate(stream_new):
            # Each trace needs to have the same sampling rate.
            sampling_rates = set([_tr.stats.sampling_rate for _tr in tr])
            if len(sampling_rates) > 1:
                msg = "All traces with the same id need to have the same " + \
                      "sampling rate."
                raise Exception(msg)
            sampling_rate = sampling_rates.pop()
            if self.background_color:
                ax = self.fig.add_subplot(len(stream_new), 1, _i + 1,
                                          axisbg=self.background_color)
            else:
                ax = self.fig.add_subplot(len(stream_new), 1, _i + 1)
            self.axis.append(ax)
            # XXX: Also enable the minmax plotting for previews.
            if self.plotting_method != 'full' and \
                ((self.endtime - self.starttime) * sampling_rate > \
                 self.max_npts):
                self.__plotMinMax(stream_new[_i], ax, *args, **kwargs)
            else:
                self.__plotStraight(stream_new[_i], ax, *args, **kwargs)
        # Set ticks.
        self.__plotSetXTicks()
        self.__plotSetYTicks()

    def plotDay(self, *args, **kwargs):
        """
        Extend the seismogram.
        """
        # Create a copy of the stream because it might be operated on.
        self.stream = self.stream.copy()
        # Merge and trim to pad.
        self.stream.merge()
        if len(self.stream) != 1:
            msg = "All traces need to be of the same id for a dayplot"
            raise ValueError(msg)
        self.stream.trim(self.starttime, self.endtime, pad=True)
        # Get minmax array.
        self.__dayplotGetMinMaxValues(self, *args, **kwargs)
        # Normalize array
        self.__dayplotNormalizeValues(self, *args, **kwargs)
        # Get timezone information. If none is  given, use local time.
        self.time_offset = kwargs.get('time_offset',
                           round((UTCDateTime(datetime.now()) - \
                           UTCDateTime()) / 3600.0, 2))
        self.timezone = kwargs.get('timezone', 'local time')
        # Try to guess how many steps are needed to advance one full time unit.
        self.repeat = None
        intervals = self.extreme_values.shape[0]
        if self.interval < 60 and 60 % self.interval == 0:
            self.repeat = 60 / self.interval
        elif self.interval < 1800 and 3600 % self.interval == 0:
            self.repeat = 3600 / self.interval
        # Otherwise use a maximum value of 10.
        else:
            if intervals >= 10:
                self.repeat = 10
            else:
                self.repeat = intervals
        # Create axis to plot on.
        if self.background_color:
            ax = self.fig.add_subplot(1, 1, 1, axisbg=self.background_color)
        else:
            ax = self.fig.add_subplot(1, 1, 1)
        # Adjust the subplots to be symmetrical. Also make some more room
        # at the top.
        self.fig.subplots_adjust(left=0.12, right=0.88, top=0.88)
        # Create x_value_array.
        aranged_array = np.arange(self.width)
        x_values = np.empty(2 * self.width)
        x_values[0::2] = aranged_array
        x_values[1::2] = aranged_array
        intervals = self.extreme_values.shape[0]
        # Loop over each step.
        for _i in xrange(intervals):
            # Create offset array.
            y_values = np.ma.empty(self.width * 2)
            y_values.fill(intervals - (_i + 1))
            # Add min and max values.
            y_values[0::2] += self.extreme_values[_i, :, 0]
            y_values[1::2] += self.extreme_values[_i, :, 1]
            # Plot the values.
            ax.plot(x_values, y_values,
                    color=self.color[_i % len(self.color)])
        # Set ranges.
        ax.set_xlim(0, self.width - 1)
        ax.set_ylim(-0.3, intervals + 0.3)
        self.axis = [ax]
        # Set ticks.
        self.__dayplotSetYTicks()
        self.__dayplotSetXTicks()
        # Choose to show grid but only on the x axis.
        self.fig.axes[0].grid()
        self.fig.axes[0].yaxis.grid(False)
        # Set the title of the plot.
        #suptitle = '%s %s'%(self.stream[0].id,self.starttime.strftime('%Y-%m-%d'))
        #self.fig.suptitle(suptitle, fontsize='small')

    def __plotStraight(self, trace, ax, *args, **kwargs):  # @UnusedVariable
        """
        Just plots the data samples in the self.stream. Useful for smaller
        datasets up to around 1000000 samples (depending on the machine its
        being run on).

        Slow and high memory consumption for large datasets.
        """
        # Copy to avoid any changes to original data.
        trace = deepcopy(trace)
        if len(trace) > 1:
            stream = Stream(traces=trace)
            # Merge with 'interpolation'. In case of overlaps this method will
            # always use the longest available trace.
            if hasattr(trace[0].stats, 'preview') and trace[0].stats.preview:
                stream = Stream(traces=stream)
                stream = mergePreviews(stream)
            else:
                stream.merge(method=1)
            trace = stream[0]
        else:
            trace = trace[0]
        # Check if it is a preview file and adjust accordingly.
        # XXX: Will look weird if the preview file is too small.
        if hasattr(trace.stats, 'preview') and trace.stats.preview:
            # Mask the gaps.
            trace.data = np.ma.masked_array(trace.data)
            trace.data[trace.data == -1] = np.ma.masked
            # Recreate the min_max scene.
            dtype = trace.data.dtype
            old_time_range = trace.stats.endtime - trace.stats.starttime
            data = np.empty(2 * trace.stats.npts, dtype=dtype)
            data[0::2] = trace.data / 2.0
            data[1::2] = -trace.data / 2.0
            trace.data = data
            # The times are not supposed to change.
            trace.stats.delta = old_time_range / float(trace.stats.npts - 1)
        # Write to self.stats.
        calib = trace.stats.calib
        max = trace.data.max()
        min = trace.data.min()
        if hasattr(trace.stats, 'preview') and trace.stats.preview:
            tr_id = trace.id + ' [preview]'
        else:
            tr_id = trace.id
        self.stats.append([tr_id, calib * trace.data.mean(),
                           calib * min, calib * max])
        # Pad the beginning and the end with masked values if necessary. Might
        # seem like overkill but it works really fast and is a clean solution
        # to gaps at the beginning/end.
        concat = [trace]
        if self.starttime != trace.stats.starttime:
            samples = (trace.stats.starttime - self.starttime) * \
                trace.stats.sampling_rate
            temp = [np.ma.masked_all(int(samples))]
            concat = temp.extend(concat)
            concat = temp
        if self.endtime != trace.stats.endtime:
            samples = (self.endtime - trace.stats.endtime) * \
                      trace.stats.sampling_rate
            concat.append(np.ma.masked_all(int(samples)))
        if len(concat) > 1:
            # Use the masked array concatenate, otherwise it will result in a
            # not masked array.
            trace.data = np.ma.concatenate(concat)
            # set starttime and calculate endtime
            trace.stats.starttime = self.starttime
        trace.data *= calib
        ax.plot(trace.data, color=self.color)
        # Set the x limit for the graph to also show the masked values at the
        # beginning/end.
        ax.set_xlim(0, len(trace.data) - 1)

    def __plotMinMax(self, trace, ax, *args, **kwargs):  # @UnusedVariable
        """
        Plots the data using a min/max approach that calculated the minimum and
        maximum values of each "pixel" and than plots only these values. Works
        much faster with large data sets.
        """
        # Some variables to help calculate the values.
        starttime = self.starttime.timestamp
        endtime = self.endtime.timestamp
        # The same trace will always have the same sampling_rate.
        sampling_rate = trace[0].stats.sampling_rate
        # The samples per resulting pixel.
        pixel_length = int((endtime - starttime) / self.width *
                           sampling_rate)
        # Loop over all the traces. Do not merge them as there are many samples
        # and therefore merging would be slow.
        for _i, _t in enumerate(trace):
            # Get the start of the next pixel in case the starttime of the
            # trace does not match the starttime of the plot.
            ts = _t.stats.starttime
            if ts > self.starttime:
                start = int(ceil(((ts - self.starttime) * \
                        sampling_rate) / pixel_length))
                # Samples before start.
                prestart = int(((self.starttime + start * pixel_length /
                           sampling_rate) - ts) * sampling_rate)
            else:
                start = 0
                prestart = 0
            # Figure out the number of pixels in the current trace.
            length = len(_t.data) - prestart
            pixel_count = int(length // pixel_length)
            rest = int(length % pixel_length)
            # Reference to new data array which does not copy data but is
            # reshapeable.
            data = _t.data[prestart: prestart + pixel_count * pixel_length]
            data = data.reshape(pixel_count, pixel_length)
            # Calculate extreme_values and put them into new array.
            extreme_values = np.ma.masked_all((self.width, 2), dtype=np.float)
            min = data.min(axis=1) * _t.stats.calib
            max = data.max(axis=1) * _t.stats.calib
            extreme_values[start: start + pixel_count, 0] = min
            extreme_values[start: start + pixel_count, 1] = max
            # First and last and last pixel need separate treatment.
            if start and prestart:
                extreme_values[start - 1, 0] = \
                    _t.data[:prestart].min() * _t.stats.calib
                extreme_values[start - 1, 1] = \
                    _t.data[:prestart].max() * _t.stats.calib
            if rest:
                if start + pixel_count == self.width:
                    index = self.width - 1
                else:
                    index = start + pixel_count
                extreme_values[index, 0] = \
                    _t.data[-rest:].min() * _t.stats.calib
                extreme_values[index, 1] = \
                    _t.data[-rest:].max() * _t.stats.calib
            # Use the first array as a reference and merge all following
            # extreme_values into it.
            if _i == 0:
                minmax = extreme_values
            else:
                # Merge minmax and extreme_values.
                min = np.ma.empty((self.width, 2))
                max = np.ma.empty((self.width, 2))
                # Fill both with the values.
                min[:, 0] = minmax[:, 0]
                min[:, 1] = extreme_values[:, 0]
                max[:, 0] = minmax[:, 1]
                max[:, 1] = extreme_values[:, 1]
                # Find the minimum and maximum values.
                min = min.min(axis=1)
                max = max.max(axis=1)
                # Write again to minmax.
                minmax[:, 0] = min
                minmax[:, 1] = max
        # Write to self.stats.
        self.stats.append([trace[0].id, minmax.mean(),
                           minmax[:, 0].min(),
                           minmax[:, 1].max()])
        # Finally plot the data.
        x_values = np.empty(2 * self.width)
        aranged = np.arange(self.width)
        x_values[0::2] = aranged
        x_values[1::2] = aranged
        # Initialize completely masked array. This version is a little bit
        # slower than first creating an empty array and then setting the mask
        # to True. But on NumPy 1.1 this results in a 0-D array which can not
        # be indexed.
        y_values = np.ma.masked_all(2 * self.width)
        y_values[0::2] = minmax[:, 0]
        y_values[1::2] = minmax[:, 1]
        ax.plot(x_values, y_values, color=self.color)
        # Set the x-limit to avoid clipping of masked values.
        ax.set_xlim(0, self.width - 1)

    def __plotSetXTicks(self, *args, **kwargs):  # @UnusedVariable
        """
        Goes through all axes in pyplot and sets time ticks on the x axis.
        """
        # Loop over all axes.
        for ax in self.axis:
            # Get the xlimits.
            start, end = ax.get_xlim()
            # Set the location of the ticks.
            ax.set_xticks(np.linspace(start, end, self.number_of_ticks))
            # Figure out times.
            interval = float(self.endtime - self.starttime) / \
                       (self.number_of_ticks - 1)
            # Set the actual labels.
            if self.type == 'relative':
                s = ['%.2f' % (self.starttime + _i * interval).timestamp \
                          for _i in range(self.number_of_ticks)]
            else:
                labels = [(self.starttime + _i * \
                          interval).strftime(self.tick_format) for _i in \
                          range(self.number_of_ticks)]

            ax.set_xticklabels(labels, fontsize='small',
                               rotation=self.tick_rotation)

    def __plotSetYTicks(self, *args, **kwargs):  # @UnusedVariable
        """
        Goes through all axes in pyplot, reads self.stats and sets all ticks on
        the y axis.

        This method also adjusts the y limits so that the mean value is always
        in the middle of the graph and all graphs are equally scaled.
        """
        # Figure out the maximum distance from the mean value to either end.
        # Add 10 percent for better looking graphs.
        max_distance = max([max(trace[1] - trace[2], trace[3] - trace[1])
                            for trace in self.stats]) * 1.1
        # Loop over all axes.
        for _i, ax in enumerate(self.axis):
            mean = self.stats[_i][1]
            # Set the ylimit.
            min_range = mean - max_distance
            max_range = mean + max_distance
            # Set the location of the ticks.
            ticks = [mean - 0.75 * max_distance,
                     mean - 0.5 * max_distance,
                     mean - 0.25 * max_distance,
                     mean,
                     mean + 0.25 * max_distance,
                     mean + 0.5 * max_distance,
                     mean + 0.75 * max_distance]
            ax.set_yticks(ticks)
            # Setup format of the major ticks
            if max(ticks) - min(ticks) > 10:
                fmt = '%d'
            else:
                fmt = '%.2g'
            ax.set_yticklabels([fmt % t for t in ax.get_yticks()],
                               fontsize='small')
            # Set the title of each plot.
            ax.set_title(self.stats[_i][0], horizontalalignment='left',
                      fontsize='small', verticalalignment='center')
            ax.set_ylim(min_range, max_range)

    def __dayplotGetMinMaxValues(self, *args, **kwargs):  # @UnusedVariable
        """
        Takes a Stream object and calculates the min and max values for each
        pixel in the dayplot.

        Writes a three dimensional array. The first axis is the step, i.e
        number of trace, the second is the pixel in that step and the third
        contains the minimum and maximum value of the pixel.
        """
        # Helper variables for easier access.
        trace = self.stream[0]
        trace_length = len(trace.data)

        # Samples per interval.
        spi = int(self.interval * trace.stats.sampling_rate)
        # Check the approximate number of samples per pixel and raise
        # error as fit.
        spp = float(spi) / self.width
        if spp < 1.0:
            msg = """
            Too few samples to use dayplot with the given arguments.
            Adjust your arguments or use a different plotting method.
            """
            msg = " ".join(msg.strip().split())
            raise ValueError(msg)
        # Number of intervals plotted.
        noi = float(trace_length) / spi
        inoi = int(round(noi))
        # Plot an extra interval if at least 2 percent of the last interval
        # will actually contain data. Do it this way to lessen floating point
        # inaccuracies.
        if abs(noi - inoi) > 2E-2:
            noi = inoi + 1
        else:
            noi = inoi

        # Adjust data. Fill with masked values in case it is necessary.
        number_of_samples = noi * spi
        delta = number_of_samples - trace_length
        if delta < 0:
            trace.data = trace.data[:number_of_samples]
        elif delta > 0:
            trace.data = np.ma.concatenate([trace.data,
                            createEmptyDataChunk(delta, trace.data.dtype)])

        # Create array for min/max values. Use masked arrays to handle gaps.
        extreme_values = np.ma.empty((noi, self.width, 2))
        trace.data.shape = (noi, spi)

        ispp = int(spp)
        fspp = spp % 1.0
        if fspp == 0.0:
            delta = None
        else:
            delta = spi - ispp * self.width

        # Loop over each interval to avoid larger errors towards the end.
        for _i in range(noi):
            if delta:
                cur_interval = trace.data[_i][:-delta]
                rest = trace.data[_i][-delta:]
            else:
                cur_interval = trace.data[_i]
            cur_interval.shape = (self.width, ispp)
            extreme_values[_i, :, 0] = cur_interval.min(axis=1)
            extreme_values[_i, :, 1] = cur_interval.max(axis=1)
            # Add the rest.
            if delta:
                extreme_values[_i, -1, 0] = min(extreme_values[_i, -1, 0],
                                                rest.min())
                extreme_values[_i, -1, 1] = max(extreme_values[_i, -1, 0],
                                                rest.max())
        # Set class variable.
        self.extreme_values = extreme_values

    def __dayplotNormalizeValues(self, *args, **kwargs):  # @UnusedVariable
        """
        Normalizes all values in the 3 dimensional array, so that the minimum
        value will be 0 and the maximum value will be 1.

        It will also convert all values to floats.
        """
        # Convert to native floats.
        self.extreme_values = self.extreme_values.astype(np.float) * \
                              self.stream[0].stats.calib
        # Make sure that the mean value is at 0
        self.extreme_values -= self.extreme_values.mean()

        # Scale so that 99.5 % of the data will fit the given range.
        if self.vertical_scaling_range is None:
            percentile_delta = 0.005
            max_values = self.extreme_values[:, :, 1].compressed()
            min_values = self.extreme_values[:, :, 0].compressed()
            # Remove masked values.
            max_values.sort()
            min_values.sort()
            length = len(max_values)
            index = int((1.0 - percentile_delta) * length)
            max_val = max_values[index]
            index = int(percentile_delta * length)
            min_val = min_values[index]
        # Exact fit.
        elif float(self.vertical_scaling_range) == 0.0:
            max_val = self.extreme_values[:, :, 1].max()
            min_val = self.extreme_values[:, :, 0].min()
        # Fit with custom range.
        else:
            max_val = min_val = abs(self.vertical_scaling_range) / 2.0

        # Scale from 0 to 1.
        self.extreme_values = self.extreme_values / (max(abs(max_val),
                                                         abs(min_val)) * 2)
        self.extreme_values += 0.5

    def __dayplotSetXTicks(self, *args, **kwargs):  # @UnusedVariable
        """
        Sets the xticks for the dayplot.
        """
        max_value = self.width - 1
        # Check whether it are sec/mins/hours and convert to a universal unit.
        if self.interval < 240:
            time_type = 'seconds'
            time_value = self.interval
        elif self.interval < 24000:
            time_type = '[min]'
            time_value = self.interval / 60
        else:
            time_type = 'hours'
            time_value = self.interval / 3600
        count = None
        # Hardcode some common values. The plus one is itentional. It had
        # hardly any performance impact and enhances readability.
        if self.interval == 15 * 60:
            count = 15 + 1
        elif self.interval == 20 * 60:
            count = 4 + 1
        elif self.interval == 30 * 60:
            count = 6 + 1
        elif self.interval == 60 * 60:
            count = 4 + 1
        elif self.interval == 90 * 60:
            count = 6 + 1
        elif self.interval == 120 * 60:
            count = 4 + 1
        elif self.interval == 180 * 60:
            count = 6 + 1
        elif self.interval == 240 * 60:
            count = 6 + 1
        elif self.interval == 300 * 60:
            count = 6 + 1
        elif self.interval == 360 * 60:
            count = 12 + 1
        elif self.interval == 720 * 60:
            count = 12 + 1
        # Otherwise run some kind of autodetection routine.
        if not count:
            # Up to 15 time units and if its a full number, show every unit.
            if time_value <= 15 and time_value % 1 == 0:
                count = time_value
            # Otherwise determine whether they are dividable for numbers up to
            # 15. If a number is not dividable just show 10 units.
            else:
                count = 10
                for _i in xrange(15, 1, -1):
                    if time_value % _i == 0:
                        count = _i
                        break
            # Show at least 5 ticks.
            if count < 5:
                count = 5
        # Everything can be overwritten by user specified number of ticks.
        if self.number_of_ticks:
            count = self.number_of_ticks
        # Calculate and set ticks.
        ticks = np.linspace(0.0, max_value, count)
        ticklabels = ['%i' % _i for _i in np.linspace(0.0,
                                    time_value, count)]
        self.axis[0].set_xticks(ticks)
        self.axis[0].set_xticklabels(ticklabels, rotation=self.tick_rotation)
        self.axis[0].set_xlabel('Zeit %s' % time_type)

    def __dayplotSetYTicks(self, *args, **kwargs):  # @UnusedVariable
        """
        Sets the yticks for the dayplot.
        """
        intervals = self.extreme_values.shape[0]
        # Do not display all ticks except if it are five or less steps.
        if intervals <= 5:
            tick_steps = range(0, intervals)
            ticks = np.arange(intervals, 0, -1, dtype=np.float)
            ticks -= 0.5
        else:
            tick_steps = range(0, intervals, self.repeat)
            ticks = np.arange(intervals, 0, -1 * self.repeat, dtype=np.float)
            ticks -= 0.5
        ticklabels = [(self.starttime + (_i + 1) * self.interval + \
                      self.time_offset * 3600).strftime('%H:%M') \
                      for _i in tick_steps]

        self.axis[0].set_yticks(ticks)
        self.axis[0].set_yticklabels(ticklabels)
        # self.axis[0].set_ylabel('UTC')
        # Save range.
        yrange = self.axis[0].get_ylim()
        # Create twin axis.
        #XXX
        self.twin = self.axis[0].twinx()
        self.twin.set_ylim(yrange)
        self.twin.set_yticks(ticks)
        ticklabels = [(self.starttime + _i * self.interval).strftime('%H:%M') \
                      for _i in tick_steps]
        self.twin.set_yticklabels(ticklabels)
        # Complicated way to calculate the label of the y-Axis showing the
        # second time zone.
        sign = '%+i' % self.time_offset
        sign = sign[0]
      #  time_label = self.timezone.strip() + ' (UTC%s%02i:%02i)' % \
        time_label = 'Berlin' + ' (UTC%s%02i:%02i)' % \
                     (sign, abs(self.time_offset), (self.time_offset % 1 * 60))
        self.axis[0].set_ylabel(time_label)
        self.twin.set_ylabel('UTC')

    def __setupFigure(self):
        """
        The design and look of the whole plot to be produced.
        """
        # Setup figure and axes
        self.fig = plt.figure(num=None, dpi=self.dpi,
                              figsize=(float(self.width) / self.dpi,
                                       float(self.height) / self.dpi))
        # XXX: Figure out why this is needed sometimes.
        # Set size and dpi.
        self.fig.set_dpi(self.dpi)
        self.fig.set_figwidth(float(self.width) / self.dpi)
        self.fig.set_figheight(float(self.height) / self.dpi)
        # hide time information if set as option
        if self.type == 'relative':
            return
        if self.type == 'dayplot':
            suptitle = '%s %s'%(self.stream[0].id,self.starttime.strftime('%Y-%m-%d'))
            self.fig.suptitle(suptitle, y=0.94, fontsize='small')
        else:
           pattern = '%Y-%m-%dT%H:%M:%SZ'
           suptitle = '%s  -  %s' % (self.starttime.strftime(pattern),
                 self.endtime.strftime(pattern))
           self.fig.suptitle(suptitle, x=0.02, y=0.96, fontsize='small',
                 horizontalalignment='left')
Example #12
0
def download_data(client=None,
                  sta=None,
                  start=None,
                  end=None,
                  stdata=[],
                  ndval=nan,
                  new_sr=0.,
                  verbose=False):
    """
    Function to build a stream object for a seismogram in a given time window either
    by downloading data from the client object or alternatively first checking if the
    given data is already available locally.

    Note 
    ----
    Currently only supports NEZ Components!

    Parameters
    ----------
    client : :class:`~obspy.client.fdsn.Client`
        Client object
    sta : Dict
        Station metadata from :mod:`~StDb` data base
    start : :class:`~obspy.core.utcdatetime.UTCDateTime`
        Start time for request
    end : :class:`~obspy.core.utcdatetime.UTCDateTime`
        End time for request
    stdata : List
        Station list
    ndval : float or nan
        Default value for missing data

    Returns
    -------
    err : bool
        Boolean for error handling (`False` is associated with success)
    trN : :class:`~obspy.core.Trace`
        Trace of North component of motion
    trE : :class:`~obspy.core.Trace`
        Trace of East component of motion
    trZ : :class:`~obspy.core.Trace` 
        Trace of Vertical component of motion

    """

    from fnmatch import filter
    from obspy import read, Stream
    from os.path import dirname, join, exists
    from numpy import any
    from math import floor

    # Output
    print(("*     {0:s}.{1:2s} - ZNE:".format(sta.station,
                                              sta.channel.upper())))

    # Set Error Default to True
    erd = True

    # Check if there is local data
    if len(stdata) > 0:
        # Only a single day: Search for local data
        # Get Z localdata
        errZ, stZ = parse_localdata_for_comp(comp='Z',
                                             stdata=stdata,
                                             sta=sta,
                                             start=start,
                                             end=end,
                                             ndval=ndval)
        # Get N localdata
        errN, stN = parse_localdata_for_comp(comp='N',
                                             stdata=stdata,
                                             sta=sta,
                                             start=start,
                                             end=end,
                                             ndval=ndval)
        # Get E localdata
        errE, stE = parse_localdata_for_comp(comp='E',
                                             stdata=stdata,
                                             sta=sta,
                                             start=start,
                                             end=end,
                                             ndval=ndval)
        # Retreived Succesfully?
        erd = errZ or errN or errE
        if not erd:
            # Combine Data
            st = stZ + stN + stE

    # No local data? Request using client
    if erd:
        erd = False

        for loc in sta.location:
            tloc = loc
            # Construct location name
            if len(tloc) == 0:
                tloc = "--"
            # Construct Channel List
            channelsZNE = sta.channel.upper() + 'Z,' + sta.channel.upper() + \
                'N,' + sta.channel.upper() + 'E'
            print(("*          {1:2s}[ZNE].{2:2s} - Checking Network".format(
                sta.station, sta.channel.upper(), tloc)))

            # Get waveforms, with extra 1 second to avoid
            # traces cropped too short - traces are trimmed later
            try:
                st = client.get_waveforms(network=sta.network,
                                          station=sta.station,
                                          location=loc,
                                          channel=channelsZNE,
                                          starttime=start,
                                          endtime=end + 1.,
                                          attach_response=False)
                if len(st) == 3:
                    print("*              - ZNE Data Downloaded")

                # It's possible if len(st)==1 that data is Z12
                else:
                    # Construct Channel List
                    channelsZ12 = sta.channel.upper() + 'Z,' + \
                        sta.channel.upper() + '1,' + \
                        sta.channel.upper() + '2'
                    msg = "*          {1:2s}[Z12].{2:2s} - Checking Network".format(
                        sta.station, sta.channel.upper(), tloc)
                    print(msg)
                    try:
                        st = client.get_waveforms(network=sta.network,
                                                  station=sta.station,
                                                  location=loc,
                                                  channel=channelsZ12,
                                                  starttime=start,
                                                  endtime=end + 1.,
                                                  attach_response=False)
                        if len(st) == 3:
                            print("*              - Z12 Data Downloaded")
                        else:
                            st = None
                    except:
                        st = None
            except:
                st = None

            # Break if we successfully obtained 3 components in st
            if not erd:

                break

    # Check the correct 3 components exist
    if st is None:
        print("* Error retrieving waveforms")
        print("**************************************************")
        return True, None

    # Three components successfully retrieved
    else:

        # Detrend and apply taper
        st.detrend('linear').taper(max_percentage=0.05, max_length=5.)

        # Check start times
        if not np.all([tr.stats.starttime == start for tr in st]):
            print("* Start times are not all close to true start: ")
            [
                print("*   " + tr.stats.channel + " " +
                      str(tr.stats.starttime) + " " + str(tr.stats.endtime))
                for tr in st
            ]
            print("*   True start: " + str(start))
            print("* -> Shifting traces to true start")
            delay = [tr.stats.starttime - start for tr in st]
            st_shifted = Stream(
                traces=[traceshift(tr, dt) for tr, dt in zip(st, delay)])
            st = st_shifted.copy()

        # Check sampling rate
        sr = st[0].stats.sampling_rate
        sr_round = float(floor_decimal(sr, 0))
        if not sr == sr_round:
            print("* Sampling rate is not an integer value: ", sr)
            print("* -> Resampling")
            st.resample(sr_round, no_filter=False)

        # Try trimming
        try:
            st.trim(start, end)
        except:
            print("* Unable to trim")
            print("* -> Aborting")
            print("**************************************************")
            return True, None

        # Check final lengths - they should all be equal if start times
        # and sampling rates are all equal and traces have been trimmed
        if not np.allclose([tr.stats.npts for tr in st[1:]], st[0].stats.npts):
            print("* Lengths are incompatible: ")
            [print("*     " + str(tr.stats.npts)) for tr in st]
            print("* -> Aborting")
            print("**************************************************")

            return True, None

        else:
            print("* Waveforms Retrieved...")
            return False, st
Example #13
0
    arrays = [Hx, Hy, Ex, Ey]
    k = 0

    # Loop over channels to create an obspy stream of the data
    for ar in arrays:
        stats.npts = len(ar)
        stats.channel = channels[k]
        ar = np.asarray(ar)
        trace = Trace(ar, stats)
        stream += trace
        trace = None
        k += 1

    # Create a copy of the stream and resample the copied stream to
    # 10 Hz using the default options of the obspy function resample
    finStream = stream.copy()
    finStream.resample(10.0)

    # Create numpy arrays of the resampled data
    Hx_fin = finStream.select(channel='Hx')[0].data
    Hy_fin = finStream.select(channel='Hy')[0].data
    Ex_fin = finStream.select(channel='Ex')[0].data
    Ey_fin = finStream.select(channel='Ey')[0].data

    # Take start time from resampled stream and set a new delta
    sttime = finStream[0].stats.starttime
    delta = .1
    time = []
    # Create a timestamp array for the resampled data using python's datetime library
    for i in range(0, len(finStream[0].data)):
        time = np.append(time, datetime.utcfromtimestamp(sttime + i * delta))
Example #14
0
class WaveformPlotting(object):
    """
    Class that provides several solutions for plotting large and small waveform
    data sets.

    .. warning::

        This class should NOT be used directly, instead use the
        :meth:`~obspy.core.stream.Stream.plot` method of the
        ObsPy :class:`~obspy.core.stream.Stream` or
        :class:`~obspy.core.trace.Trace` objects.

    It uses matplotlib to plot the waveforms.
    """
    def __init__(self, **kwargs):
        """
        Checks some variables and maps the kwargs to class variables.
        """
        self.stream = kwargs.get('stream')
        # Check if it is a Stream or a Trace object.
        if isinstance(self.stream, Trace):
            self.stream = Stream([self.stream])
        elif not isinstance(self.stream, Stream):
            msg = 'Plotting is only supported for Stream or Trace objects.'
            raise TypeError(msg)
        # Stream object should contain at least one Trace
        if len(self.stream) < 1:
            msg = "Empty stream object"
            raise IndexError(msg)
        # Type of the plot.
        self.type = kwargs.get('type', 'normal')
        # Start- and endtimes of the plots.
        self.starttime = kwargs.get('starttime', None)
        self.endtime = kwargs.get('endtime', None)
        self.fig_obj = kwargs.get('fig', None)
        # If no times are given take the min/max values from the stream object.
        if not self.starttime:
            self.starttime = min([trace.stats.starttime for \
                             trace in self.stream])
        if not self.endtime:
            self.endtime = max([trace.stats.endtime for \
                           trace in self.stream])
        # Map stream object and slice just in case.
        self.stream.trim(self.starttime, self.endtime)
        # normalize times
        if self.type == 'relative':
            dt = self.starttime
            # fix plotting boundaries
            self.endtime = UTCDateTime(self.endtime - self.starttime)
            self.starttime = UTCDateTime(0)
            # fix stream times
            for tr in self.stream:
                tr.stats.starttime = UTCDateTime(tr.stats.starttime - dt)
        # Whether to use straight plotting or the fast minmax method.
        self.plotting_method = kwargs.get('method', 'fast')
        # Below that value the data points will be plotted normally. Above it
        # the data will be plotted using a different approach (details see
        # below). Can be overwritten by the above self.plotting_method kwarg.
        self.max_npts = 400000
        # If automerge is enabled. Merge traces with the same id for the plot.
        self.automerge = kwargs.get('automerge', True)
        # If equal_scale is enabled all plots are equally scaled.
        self.equal_scale = kwargs.get('equal_scale', True)
        # Set default values.
        # The default value for the size is determined dynamically because
        # there might be more than one channel to plot.
        self.size = kwargs.get('size', None)
        # Values that will be used to calculate the size of the plot.
        self.default_width = 800
        self.default_height_per_channel = 250
        if not self.size:
            self.width = 800
            # Check the kind of plot.
            if self.type == 'dayplot':
                self.height = 600
            else:
                # One plot for each trace.
                if self.automerge:
                    count = self.__getMergablesIds()
                    count = len(count)
                else:
                    count = len(self.stream)
                self.height = count * 250
        else:
            self.width, self.height = self.size
        # Interval length in minutes for dayplot.
        self.interval = 60 * kwargs.get('interval', 15)
        # Scaling.
        self.vertical_scaling_range = kwargs.get('vertical_scaling_range',
                                                 None)
        # Dots per inch of the plot. Might be useful for printing plots.
        self.dpi = kwargs.get('dpi', 100)
        # Color of the graph.
        if self.type == 'dayplot':
            self.color = kwargs.get(
                'color', ('#B2000F', '#004C12', '#847200', '#0E01FF'))
            if isinstance(self.color, basestring):
                self.color = (self.color, )
            self.number_of_ticks = kwargs.get('number_of_ticks', None)
        else:
            self.color = kwargs.get('color', 'k')
            self.number_of_ticks = kwargs.get('number_of_ticks', 4)
        # Background and face color.
        self.background_color = kwargs.get('bgcolor', 'w')
        self.face_color = kwargs.get('face_color', 'w')
        # Transparency. Overwrites background and facecolor settings.
        self.transparent = kwargs.get('transparent', False)
        if self.transparent:
            self.background_color = None
        # Ticks.
        self.tick_format = kwargs.get('tick_format', '%H:%M:%S')
        self.tick_rotation = kwargs.get('tick_rotation', 0)
        # Whether or not to save a file.
        self.outfile = kwargs.get('outfile')
        self.handle = kwargs.get('handle')
        # File format of the resulting file. Usually defaults to PNG but might
        # be dependent on your matplotlib backend.
        self.format = kwargs.get('format')

    def __getMergeId(self, tr):
        tr_id = tr.id
        # don't merge normal traces with previews
        try:
            if tr.stats.preview:
                tr_id += 'preview'
        except KeyError:
            pass
        # don't merge traces with different processing steps
        try:
            if tr.stats.processing:
                tr_id += str(tr.stats.processing)
        except KeyError:
            pass
        return tr_id

    def __getMergablesIds(self):
        ids = []
        for tr in self.stream:
            tr_id = self.__getMergeId(tr)
            if not tr_id in ids:
                ids.append(tr_id)
        return ids

    def plotWaveform(self, *args, **kwargs):
        """
        Creates a graph of any given ObsPy Stream object. It either saves the
        image directly to the file system or returns an binary image string.

        For all color values you can use legit HTML names, HTML hex strings
        (e.g. '#eeefff') or you can pass an R , G , B tuple, where each of
        R , G , B are in the range [0, 1]. You can also use single letters for
        basic built-in colors ('b' = blue, 'g' = green, 'r' = red, 'c' = cyan,
        'm' = magenta, 'y' = yellow, 'k' = black, 'w' = white) and gray shades
        can be given as a string encoding a float in the 0-1 range.
        """
        # Setup the figure if not passed explicitly.
        if not self.fig_obj:
            self.__setupFigure()
        else:
            self.fig = self.fig_obj
        # Determine kind of plot and do the actual plotting.
        if self.type == 'dayplot':
            self.plotDay(*args, **kwargs)
        else:
            self.plot(*args, **kwargs)
        # Adjust the subplot so there is always a fixed margin on every side
        if self.type != 'dayplot':
            fract_y = 60.0 / self.height
            fract_y2 = 40.0 / self.height
            fract_x = 80.0 / self.width
            self.fig.subplots_adjust(top=1.0 - fract_y,
                                     bottom=fract_y2,
                                     left=fract_x,
                                     right=1.0 - fract_x / 2)
        self.fig.canvas.draw()
        # The following just serves as a unified way of saving and displaying
        # the plots.
        if not self.transparent:
            extra_args = {
                'dpi': self.dpi,
                'facecolor': self.face_color,
                'edgecolor': self.face_color
            }
        else:
            extra_args = {'dpi': self.dpi, 'transparent': self.transparent}
        if self.outfile:
            # If format is set use it.
            if self.format:
                self.fig.savefig(self.outfile,
                                 format=self.format,
                                 **extra_args)
            # Otherwise use format from self.outfile or default to PNG.
            else:
                self.fig.savefig(self.outfile, **extra_args)
        else:
            # Return an binary imagestring if not self.outfile but self.format.
            if self.format:
                imgdata = StringIO.StringIO()
                self.fig.savefig(imgdata, format=self.format, **extra_args)
                imgdata.seek(0)
                return imgdata.read()
            elif self.handle:
                return self.fig
            else:
                if not self.fig_obj:
                    plt.show()

    def plot(self, *args, **kwargs):
        """
        Plot the Traces showing one graph per Trace.

        Plots the whole time series for self.max_npts points and less. For more
        points it plots minmax values.
        """
        stream_new = []
        # Just remove empty traces.
        if not self.automerge:
            for tr in self.stream:
                stream_new.append([])
                if len(tr.data):
                    stream_new[-1].append(tr)
        else:
            # Generate sorted list of traces (no copy)
            # Sort order, id, starttime, endtime
            ids = self.__getMergablesIds()
            for id in ids:
                stream_new.append([])
                for tr in self.stream:
                    tr_id = self.__getMergeId(tr)
                    if tr_id == id:
                        # does not copy the elements of the data array
                        tr_ref = copy(tr)
                        # Trim does nothing if times are outside
                        if self.starttime >= tr_ref.stats.endtime or \
                                self.endtime <= tr_ref.stats.starttime:
                            continue
                        if tr_ref.data.size:
                            stream_new[-1].append(tr_ref)
                # delete if empty list
                if not len(stream_new[-1]):
                    stream_new.pop()
                    continue
                stream_new[-1].sort(key=lambda x: x.stats.endtime)
                stream_new[-1].sort(key=lambda x: x.stats.starttime)
        # If everything is lost in the process raise an Exception.
        if not len(stream_new):
            raise Exception("Nothing to plot")
        # Create helper variable to track ids and min/max/mean values.
        self.stats = []
        # Loop over each Trace and call the appropriate plotting method.
        self.axis = []
        for _i, tr in enumerate(stream_new):
            # Each trace needs to have the same sampling rate.
            sampling_rates = set([_tr.stats.sampling_rate for _tr in tr])
            if len(sampling_rates) > 1:
                msg = "All traces with the same id need to have the same " + \
                      "sampling rate."
                raise Exception(msg)
            sampling_rate = sampling_rates.pop()
            if self.background_color:
                ax = self.fig.add_subplot(len(stream_new),
                                          1,
                                          _i + 1,
                                          axisbg=self.background_color)
            else:
                ax = self.fig.add_subplot(len(stream_new), 1, _i + 1)
            self.axis.append(ax)
            # XXX: Also enable the minmax plotting for previews.
            if self.plotting_method != 'full' and \
                ((self.endtime - self.starttime) * sampling_rate > \
                 self.max_npts):
                self.__plotMinMax(stream_new[_i], ax, *args, **kwargs)
            else:
                self.__plotStraight(stream_new[_i], ax, *args, **kwargs)
        # Set ticks.
        self.__plotSetXTicks()
        self.__plotSetYTicks()

    def plotDay(self, *args, **kwargs):
        """
        Extend the seismogram.
        """
        # Create a copy of the stream because it might be operated on.
        self.stream = self.stream.copy()
        # Merge and trim to pad.
        self.stream.merge()
        if len(self.stream) != 1:
            msg = "All traces need to be of the same id for a dayplot"
            raise ValueError(msg)
        self.stream.trim(self.starttime, self.endtime, pad=True)
        # Get minmax array.
        self.__dayplotGetMinMaxValues(self, *args, **kwargs)
        # Normalize array
        self.__dayplotNormalizeValues(self, *args, **kwargs)
        # Get timezone information. If none is  given, use local time.
        self.time_offset = kwargs.get(
            'time_offset',
            round((UTCDateTime(datetime.now()) - UTCDateTime()) / 3600.0, 2))
        self.timezone = kwargs.get('timezone', 'local time')
        # Try to guess how many steps are needed to advance one full time unit.
        self.repeat = None
        intervals = self.extreme_values.shape[0]
        if self.interval < 60 and 60 % self.interval == 0:
            self.repeat = 60 / self.interval
        elif self.interval < 1800 and 3600 % self.interval == 0:
            self.repeat = 3600 / self.interval
        # Otherwise use a maximum value of 10.
        else:
            if intervals >= 10:
                self.repeat = 10
            else:
                self.repeat = intervals
        # Create axis to plot on.
        if self.background_color:
            ax = self.fig.add_subplot(1, 1, 1, axisbg=self.background_color)
        else:
            ax = self.fig.add_subplot(1, 1, 1)
        # Adjust the subplots to be symmetrical. Also make some more room
        # at the top.
        self.fig.subplots_adjust(left=0.12, right=0.88, top=0.95)
        # Create x_value_array.
        aranged_array = np.arange(self.width)
        x_values = np.empty(2 * self.width)
        x_values[0::2] = aranged_array
        x_values[1::2] = aranged_array
        intervals = self.extreme_values.shape[0]
        # Loop over each step.
        for _i in xrange(intervals):
            # Create offset array.
            y_values = np.ma.empty(self.width * 2)
            y_values.fill(intervals - (_i + 1))
            # Add min and max values.
            y_values[0::2] += self.extreme_values[_i, :, 0]
            y_values[1::2] += self.extreme_values[_i, :, 1]
            # Plot the values.
            ax.plot(x_values, y_values, color=self.color[_i % len(self.color)])
        # Set ranges.
        ax.set_xlim(0, self.width - 1)
        ax.set_ylim(-0.3, intervals + 0.3)
        self.axis = [ax]
        # Set ticks.
        self.__dayplotSetYTicks(*args, **kwargs)
        self.__dayplotSetXTicks(*args, **kwargs)
        # Choose to show grid but only on the x axis.
        self.fig.axes[0].grid()
        self.fig.axes[0].yaxis.grid(False)

    def __plotStraight(self, trace, ax, *args, **kwargs):  # @UnusedVariable
        """
        Just plots the data samples in the self.stream. Useful for smaller
        datasets up to around 1000000 samples (depending on the machine its
        being run on).

        Slow and high memory consumption for large datasets.
        """
        # Copy to avoid any changes to original data.
        trace = [tr.copy() for tr in trace]
        if len(trace) > 1:
            stream = Stream(traces=trace)
            # Merge with 'interpolation'. In case of overlaps this method will
            # always use the longest available trace.
            if hasattr(trace[0].stats, 'preview') and trace[0].stats.preview:
                stream = Stream(traces=stream)
                stream = mergePreviews(stream)
            else:
                stream.merge(method=1)
            trace = stream[0]
        else:
            trace = trace[0]
        # Check if it is a preview file and adjust accordingly.
        # XXX: Will look weird if the preview file is too small.
        if hasattr(trace.stats, 'preview') and trace.stats.preview:
            # Mask the gaps.
            trace.data = np.ma.masked_array(trace.data)
            trace.data[trace.data == -1] = np.ma.masked
            # Recreate the min_max scene.
            dtype = trace.data.dtype
            old_time_range = trace.stats.endtime - trace.stats.starttime
            data = np.empty(2 * trace.stats.npts, dtype=dtype)
            data[0::2] = trace.data / 2.0
            data[1::2] = -trace.data / 2.0
            trace.data = data
            # The times are not supposed to change.
            trace.stats.delta = old_time_range / float(trace.stats.npts - 1)
        # Write to self.stats.
        calib = trace.stats.calib
        max = trace.data.max()
        min = trace.data.min()
        # set label
        if hasattr(trace.stats, 'preview') and trace.stats.preview:
            tr_id = trace.id + ' [preview]'
        elif hasattr(trace, 'label'):
            tr_id = trace.label
        else:
            tr_id = trace.id
        self.stats.append(
            [tr_id, calib * trace.data.mean(), calib * min, calib * max])
        # Pad the beginning and the end with masked values if necessary. Might
        # seem like overkill but it works really fast and is a clean solution
        # to gaps at the beginning/end.
        concat = [trace]
        if self.starttime != trace.stats.starttime:
            samples = (trace.stats.starttime - self.starttime) * \
                trace.stats.sampling_rate
            temp = [np.ma.masked_all(int(samples))]
            concat = temp.extend(concat)
            concat = temp
        if self.endtime != trace.stats.endtime:
            samples = (self.endtime - trace.stats.endtime) * \
                      trace.stats.sampling_rate
            concat.append(np.ma.masked_all(int(samples)))
        if len(concat) > 1:
            # Use the masked array concatenate, otherwise it will result in a
            # not masked array.
            trace.data = np.ma.concatenate(concat)
            # set starttime and calculate endtime
            trace.stats.starttime = self.starttime
        trace.data *= calib
        ax.plot(trace.data, color=self.color)
        # Set the x limit for the graph to also show the masked values at the
        # beginning/end.
        ax.set_xlim(0, len(trace.data) - 1)

    def __plotMinMax(self, trace, ax, *args, **kwargs):  # @UnusedVariable
        """
        Plots the data using a min/max approach that calculated the minimum and
        maximum values of each "pixel" and than plots only these values. Works
        much faster with large data sets.
        """
        # Some variables to help calculate the values.
        starttime = self.starttime.timestamp
        endtime = self.endtime.timestamp
        # The same trace will always have the same sampling_rate.
        sampling_rate = trace[0].stats.sampling_rate
        # The samples per resulting pixel.
        pixel_length = int((endtime - starttime) / self.width * sampling_rate)
        # Loop over all the traces. Do not merge them as there are many samples
        # and therefore merging would be slow.
        for _i, tr in enumerate(trace):
            # Get the start of the next pixel in case the starttime of the
            # trace does not match the starttime of the plot.
            ts = tr.stats.starttime
            if ts > self.starttime:
                start = int(ceil(((ts - self.starttime) * \
                        sampling_rate) / pixel_length))
                # Samples before start.
                prestart = int(
                    ((self.starttime + start * pixel_length / sampling_rate) -
                     ts) * sampling_rate)
            else:
                start = 0
                prestart = 0
            # Figure out the number of pixels in the current trace.
            length = len(tr.data) - prestart
            pixel_count = int(length // pixel_length)
            rest = int(length % pixel_length)
            # Reference to new data array which does not copy data but is
            # reshapeable.
            data = tr.data[prestart:prestart + pixel_count * pixel_length]
            data = data.reshape(pixel_count, pixel_length)
            # Calculate extreme_values and put them into new array.
            extreme_values = np.ma.masked_all((self.width, 2), dtype=np.float)
            min = data.min(axis=1) * tr.stats.calib
            max = data.max(axis=1) * tr.stats.calib
            extreme_values[start:start + pixel_count, 0] = min
            extreme_values[start:start + pixel_count, 1] = max
            # First and last and last pixel need separate treatment.
            if start and prestart:
                extreme_values[start - 1, 0] = \
                    tr.data[:prestart].min() * tr.stats.calib
                extreme_values[start - 1, 1] = \
                    tr.data[:prestart].max() * tr.stats.calib
            if rest:
                if start + pixel_count == self.width:
                    index = self.width - 1
                else:
                    index = start + pixel_count
                extreme_values[index, 0] = \
                    tr.data[-rest:].min() * tr.stats.calib
                extreme_values[index, 1] = \
                    tr.data[-rest:].max() * tr.stats.calib
            # Use the first array as a reference and merge all following
            # extreme_values into it.
            if _i == 0:
                minmax = extreme_values
            else:
                # Merge minmax and extreme_values.
                min = np.ma.empty((self.width, 2))
                max = np.ma.empty((self.width, 2))
                # Fill both with the values.
                min[:, 0] = minmax[:, 0]
                min[:, 1] = extreme_values[:, 0]
                max[:, 0] = minmax[:, 1]
                max[:, 1] = extreme_values[:, 1]
                # Find the minimum and maximum values.
                min = min.min(axis=1)
                max = max.max(axis=1)
                # Write again to minmax.
                minmax[:, 0] = min
                minmax[:, 1] = max
        # set label
        if hasattr(trace[0], 'label'):
            tr_id = trace[0].label
        else:
            tr_id = trace[0].id
        # Write to self.stats.
        self.stats.append(
            [tr_id,
             minmax.mean(), minmax[:, 0].min(), minmax[:, 1].max()])
        # Finally plot the data.
        x_values = np.empty(2 * self.width)
        aranged = np.arange(self.width)
        x_values[0::2] = aranged
        x_values[1::2] = aranged
        # Initialize completely masked array. This version is a little bit
        # slower than first creating an empty array and then setting the mask
        # to True. But on NumPy 1.1 this results in a 0-D array which can not
        # be indexed.
        y_values = np.ma.masked_all(2 * self.width)
        y_values[0::2] = minmax[:, 0]
        y_values[1::2] = minmax[:, 1]
        ax.plot(x_values, y_values, color=self.color)
        # Set the x-limit to avoid clipping of masked values.
        ax.set_xlim(0, self.width - 1)

    def __plotSetXTicks(self, *args, **kwargs):  # @UnusedVariable
        """
        Goes through all axes in pyplot and sets time ticks on the x axis.
        """
        # Loop over all axes.
        for ax in self.axis:
            # Get the xlimits.
            start, end = ax.get_xlim()
            # Set the location of the ticks.
            ax.set_xticks(np.linspace(start, end, self.number_of_ticks))
            # Figure out times.
            interval = float(self.endtime - self.starttime) / \
                       (self.number_of_ticks - 1)
            # Set the actual labels.
            if self.type == 'relative':
                labels = ['%.2f' % (self.starttime + _i * interval).timestamp \
                          for _i in range(self.number_of_ticks)]
            else:
                labels = [(self.starttime + _i * \
                          interval).strftime(self.tick_format) for _i in \
                          range(self.number_of_ticks)]

            ax.set_xticklabels(labels,
                               fontsize='small',
                               rotation=self.tick_rotation)

    def __plotSetYTicks(self, *args, **kwargs):  # @UnusedVariable
        """
        Goes through all axes in pyplot, reads self.stats and sets all ticks on
        the y axis.

        This method also adjusts the y limits so that the mean value is always
        in the middle of the graph and all graphs are equally scaled.
        """
        # Figure out the maximum distance from the mean value to either end.
        # Add 10 percent for better looking graphs.
        max_distance = max([
            max(trace[1] - trace[2], trace[3] - trace[1])
            for trace in self.stats
        ]) * 1.1
        # Loop over all axes.
        for _i, ax in enumerate(self.axis):
            mean = self.stats[_i][1]
            if not self.equal_scale:
                trace = self.stats[_i]
                max_distance = max(trace[1] - trace[2],
                                   trace[3] - trace[1]) * 1.1
            # Set the ylimit.
            min_range = mean - max_distance
            max_range = mean + max_distance
            # Set the location of the ticks.
            ticks = [
                mean - 0.75 * max_distance, mean - 0.5 * max_distance,
                mean - 0.25 * max_distance, mean, mean + 0.25 * max_distance,
                mean + 0.5 * max_distance, mean + 0.75 * max_distance
            ]
            ax.set_yticks(ticks)
            # Setup format of the major ticks
            if abs(max(ticks) - min(ticks)) > 10:
                # integer numbers
                fmt = '%d'
                if abs(min(ticks)) > 10e6:
                    # but switch back to exponential for huge numbers
                    fmt = '%.2g'
            else:
                fmt = '%.2g'
            ax.set_yticklabels([fmt % t for t in ax.get_yticks()],
                               fontsize='small')
            # Set the title of each plot.
            ax.set_title(self.stats[_i][0],
                         horizontalalignment='center',
                         fontsize='small',
                         verticalalignment='center')
            ax.set_ylim(min_range, max_range)

    def __dayplotGetMinMaxValues(self, *args, **kwargs):  # @UnusedVariable
        """
        Takes a Stream object and calculates the min and max values for each
        pixel in the dayplot.

        Writes a three dimensional array. The first axis is the step, i.e
        number of trace, the second is the pixel in that step and the third
        contains the minimum and maximum value of the pixel.
        """
        # Helper variables for easier access.
        trace = self.stream[0]
        trace_length = len(trace.data)

        # Samples per interval.
        spi = int(self.interval * trace.stats.sampling_rate)
        # Check the approximate number of samples per pixel and raise
        # error as fit.
        spp = float(spi) / self.width
        if spp < 1.0:
            msg = """
            Too few samples to use dayplot with the given arguments.
            Adjust your arguments or use a different plotting method.
            """
            msg = " ".join(msg.strip().split())
            raise ValueError(msg)
        # Number of intervals plotted.
        noi = float(trace_length) / spi
        inoi = int(round(noi))
        # Plot an extra interval if at least 2 percent of the last interval
        # will actually contain data. Do it this way to lessen floating point
        # inaccuracies.
        if abs(noi - inoi) > 2E-2:
            noi = inoi + 1
        else:
            noi = inoi

        # Adjust data. Fill with masked values in case it is necessary.
        number_of_samples = noi * spi
        delta = number_of_samples - trace_length
        if delta < 0:
            trace.data = trace.data[:number_of_samples]
        elif delta > 0:
            trace.data = np.ma.concatenate(
                [trace.data,
                 createEmptyDataChunk(delta, trace.data.dtype)])

        # Create array for min/max values. Use masked arrays to handle gaps.
        extreme_values = np.ma.empty((noi, self.width, 2))
        trace.data.shape = (noi, spi)

        ispp = int(spp)
        fspp = spp % 1.0
        if fspp == 0.0:
            delta = None
        else:
            delta = spi - ispp * self.width

        # Loop over each interval to avoid larger errors towards the end.
        for _i in range(noi):
            if delta:
                cur_interval = trace.data[_i][:-delta]
                rest = trace.data[_i][-delta:]
            else:
                cur_interval = trace.data[_i]
            cur_interval.shape = (self.width, ispp)
            extreme_values[_i, :, 0] = cur_interval.min(axis=1)
            extreme_values[_i, :, 1] = cur_interval.max(axis=1)
            # Add the rest.
            if delta:
                extreme_values[_i, -1, 0] = min(extreme_values[_i, -1, 0],
                                                rest.min())
                extreme_values[_i, -1, 1] = max(extreme_values[_i, -1, 0],
                                                rest.max())
        # Set class variable.
        self.extreme_values = extreme_values

    def __dayplotNormalizeValues(self, *args, **kwargs):  # @UnusedVariable
        """
        Normalizes all values in the 3 dimensional array, so that the minimum
        value will be 0 and the maximum value will be 1.

        It will also convert all values to floats.
        """
        # Convert to native floats.
        self.extreme_values = self.extreme_values.astype(np.float) * \
                              self.stream[0].stats.calib
        # Make sure that the mean value is at 0
        self.extreme_values -= self.extreme_values.mean()

        # Scale so that 99.5 % of the data will fit the given range.
        if self.vertical_scaling_range is None:
            percentile_delta = 0.005
            max_values = self.extreme_values[:, :, 1].compressed()
            min_values = self.extreme_values[:, :, 0].compressed()
            # Remove masked values.
            max_values.sort()
            min_values.sort()
            length = len(max_values)
            index = int((1.0 - percentile_delta) * length)
            max_val = max_values[index]
            index = int(percentile_delta * length)
            min_val = min_values[index]
        # Exact fit.
        elif float(self.vertical_scaling_range) == 0.0:
            max_val = self.extreme_values[:, :, 1].max()
            min_val = self.extreme_values[:, :, 0].min()
        # Fit with custom range.
        else:
            max_val = min_val = abs(self.vertical_scaling_range) / 2.0

        # Scale from 0 to 1.
        self.extreme_values = self.extreme_values / (
            max(abs(max_val), abs(min_val)) * 2)
        self.extreme_values += 0.5

    def __dayplotSetXTicks(self, *args, **kwargs):  # @UnusedVariable
        """
        Sets the xticks for the dayplot.
        """
        localization_dict = kwargs.get('localization_dict', {})
        localization_dict.setdefault('seconds', 'seconds')
        localization_dict.setdefault('minutes', 'minutes')
        localization_dict.setdefault('hours', 'hours')
        localization_dict.setdefault('time in', 'time in')
        max_value = self.width - 1
        # Check whether it are sec/mins/hours and convert to a universal unit.
        if self.interval < 240:
            time_type = localization_dict['seconds']
            time_value = self.interval
        elif self.interval < 24000:
            time_type = localization_dict['minutes']
            time_value = self.interval / 60
        else:
            time_type = localization_dict['hours']
            time_value = self.interval / 3600
        count = None
        # Hardcode some common values. The plus one is intentional. It had
        # hardly any performance impact and enhances readability.
        if self.interval == 15 * 60:
            count = 15 + 1
        elif self.interval == 20 * 60:
            count = 4 + 1
        elif self.interval == 30 * 60:
            count = 6 + 1
        elif self.interval == 60 * 60:
            count = 4 + 1
        elif self.interval == 90 * 60:
            count = 6 + 1
        elif self.interval == 120 * 60:
            count = 4 + 1
        elif self.interval == 180 * 60:
            count = 6 + 1
        elif self.interval == 240 * 60:
            count = 6 + 1
        elif self.interval == 300 * 60:
            count = 6 + 1
        elif self.interval == 360 * 60:
            count = 12 + 1
        elif self.interval == 720 * 60:
            count = 12 + 1
        # Otherwise run some kind of autodetection routine.
        if not count:
            # Up to 15 time units and if its a full number, show every unit.
            if time_value <= 15 and time_value % 1 == 0:
                count = time_value
            # Otherwise determine whether they are dividable for numbers up to
            # 15. If a number is not dividable just show 10 units.
            else:
                count = 10
                for _i in xrange(15, 1, -1):
                    if time_value % _i == 0:
                        count = _i
                        break
            # Show at least 5 ticks.
            if count < 5:
                count = 5
        # Everything can be overwritten by user specified number of ticks.
        if self.number_of_ticks:
            count = self.number_of_ticks
        # Calculate and set ticks.
        ticks = np.linspace(0.0, max_value, count)
        ticklabels = ['%i' % _i for _i in np.linspace(0.0, time_value, count)]
        self.axis[0].set_xticks(ticks)
        self.axis[0].set_xticklabels(ticklabels, rotation=self.tick_rotation)
        self.axis[0].set_xlabel('%s %s' %
                                (localization_dict['time in'], time_type))

    def __dayplotSetYTicks(self, *args, **kwargs):  # @UnusedVariable
        """
        Sets the yticks for the dayplot.
        """
        intervals = self.extreme_values.shape[0]
        # Do not display all ticks except if it are five or less steps.
        if intervals <= 5:
            tick_steps = range(0, intervals)
            ticks = np.arange(intervals, 0, -1, dtype=np.float)
            ticks -= 0.5
        else:
            tick_steps = range(0, intervals, self.repeat)
            ticks = np.arange(intervals, 0, -1 * self.repeat, dtype=np.float)
            ticks -= 0.5

        left_time_offset = 0
        right_time_offset = self.time_offset
        left_ylabel = 'UTC'

        # Complicated way to calculate the label of the y-Axis showing the
        # second time zone.
        sign = '%+i' % self.time_offset
        sign = sign[0]
        time_label = self.timezone.strip() + ' (UTC%s%02i:%02i)' % \
                     (sign, abs(self.time_offset), (self.time_offset % 1 * 60))
        right_ylabel = time_label

        if kwargs.get('swap_time_axis', False):
            left_time_offset, right_time_offset = \
                    right_time_offset, left_time_offset
            left_ylabel, right_ylabel = right_ylabel, left_ylabel

        left_ticklabels = [(self.starttime + _i * self.interval + \
                            left_time_offset * 3600).strftime('%H:%M') \
                      for _i in tick_steps]
        right_ticklabels = [(self.starttime + (_i + 1) * self.interval + \
                            right_time_offset * 3600).strftime('%H:%M') \
                      for _i in tick_steps]

        self.axis[0].set_yticks(ticks)
        self.axis[0].set_yticklabels(left_ticklabels)
        self.axis[0].set_ylabel(left_ylabel)
        # Save range.
        yrange = self.axis[0].get_ylim()
        # Create twin axis.
        #XXX
        self.twin = self.axis[0].twinx()
        self.twin.set_ylim(yrange)
        self.twin.set_yticks(ticks)
        self.twin.set_yticklabels(right_ticklabels)
        self.twin.set_ylabel(right_ylabel)

    def __setupFigure(self):
        """
        The design and look of the whole plot to be produced.
        """
        # Setup figure and axes
        self.fig = plt.figure(num=None,
                              dpi=self.dpi,
                              figsize=(float(self.width) / self.dpi,
                                       float(self.height) / self.dpi))
        # XXX: Figure out why this is needed sometimes.
        # Set size and dpi.
        self.fig.set_dpi(self.dpi)
        self.fig.set_figwidth(float(self.width) / self.dpi)
        self.fig.set_figheight(float(self.height) / self.dpi)
        x = self.__getX(10)
        y = self.__getY(15)
        if hasattr(self.stream, 'label'):
            suptitle = self.stream.label
        elif self.type == 'relative':
            # hide time information for relative plots
            return
        elif self.type == 'dayplot':
            suptitle = '%s %s' % (self.stream[0].id,
                                  self.starttime.strftime('%Y-%m-%d'))
            x = self.fig.subplotpars.left
        else:
            pattern = '%Y-%m-%dT%H:%M:%SZ'
            suptitle = '%s  -  %s' % (self.starttime.strftime(pattern),
                                      self.endtime.strftime(pattern))
        # add suptitle
        self.fig.suptitle(suptitle,
                          x=x,
                          y=y,
                          fontsize='small',
                          horizontalalignment='left')

    def __getY(self, dy):
        return (self.height - dy) * 1.0 / self.height

    def __getX(self, dx):
        return dx * 1.0 / self.width
# Number of points of windows and overlap for PSD calculation
# Easiest to split up in powers of two
nfft = 2**10
windlap = 0.5

total_seconds = ((60. * 60. * 24. * Daynum) - (3601. * 3.))

st.detrend('constant')
st.merge(fill_value=0.)

# Start the loop of PSD calculations

for i in range(0, Nwin):

    st2 = st.copy()

    # get a random start time in seconds

    # Note this will always be an integer second

    ss = random.randint(0, total_seconds)

    if "H_day" not in vars():
        H_day = ss / (60. * 60. * 24)

    else:
        H_day = np.vstack((H_day, ss / (60. * 60. * 24)))

    stime = sday + ss
Example #16
0
 def test_coincidenceTrigger(self):
     """
     Test network coincidence trigger.
     """
     st = Stream()
     files = [
         "BW.UH1._.SHZ.D.2010.147.cut.slist.gz",
         "BW.UH2._.SHZ.D.2010.147.cut.slist.gz",
         "BW.UH3._.SHZ.D.2010.147.cut.slist.gz",
         "BW.UH4._.EHZ.D.2010.147.cut.slist.gz"
     ]
     for filename in files:
         filename = os.path.join(self.path, filename)
         st += read(filename)
     # some prefiltering used for UH network
     st.filter('bandpass', freqmin=10, freqmax=20)
     # 1. no weighting, no stations specified, good settings
     # => 3 events, no false triggers
     # for the first test we make some additional tests regarding types
     res = coincidenceTrigger("recstalta",
                              3.5,
                              1,
                              st.copy(),
                              3,
                              sta=0.5,
                              lta=10)
     self.assertTrue(isinstance(res, list))
     self.assertTrue(len(res) == 3)
     expected_keys = [
         'time', 'coincidence_sum', 'duration', 'stations', 'trace_ids'
     ]
     expected_types = [UTCDateTime, float, float, list, list]
     for item in res:
         self.assertTrue(isinstance(item, dict))
         for key, _type in zip(expected_keys, expected_types):
             self.assertTrue(key in item)
             self.assertTrue(isinstance(item[key], _type))
     self.assertTrue(res[0]['time'] > UTCDateTime("2010-05-27T16:24:31"))
     self.assertTrue(res[0]['time'] < UTCDateTime("2010-05-27T16:24:35"))
     self.assertTrue(4.2 < res[0]['duration'] < 4.8)
     self.assertTrue(res[0]['stations'] == ['UH3', 'UH2', 'UH1', 'UH4'])
     self.assertTrue(res[0]['coincidence_sum'] == 4)
     self.assertTrue(res[1]['time'] > UTCDateTime("2010-05-27T16:26:59"))
     self.assertTrue(res[1]['time'] < UTCDateTime("2010-05-27T16:27:03"))
     self.assertTrue(3.2 < res[1]['duration'] < 3.7)
     self.assertTrue(res[1]['stations'] == ['UH2', 'UH3', 'UH1'])
     self.assertTrue(res[1]['coincidence_sum'] == 3)
     self.assertTrue(res[2]['time'] > UTCDateTime("2010-05-27T16:27:27"))
     self.assertTrue(res[2]['time'] < UTCDateTime("2010-05-27T16:27:33"))
     self.assertTrue(4.2 < res[2]['duration'] < 4.4)
     self.assertTrue(res[2]['stations'] == ['UH3', 'UH2', 'UH1', 'UH4'])
     self.assertTrue(res[2]['coincidence_sum'] == 4)
     # 2. no weighting, station selection
     # => 2 events, no false triggers
     trace_ids = ['BW.UH1..SHZ', 'BW.UH3..SHZ', 'BW.UH4..EHZ']
     # ignore UserWarnings
     with warnings.catch_warnings(record=True):
         warnings.simplefilter('ignore', UserWarning)
         re = coincidenceTrigger("recstalta",
                                 3.5,
                                 1,
                                 st.copy(),
                                 3,
                                 trace_ids=trace_ids,
                                 sta=0.5,
                                 lta=10)
         self.assertTrue(len(re) == 2)
         self.assertTrue(re[0]['time'] > UTCDateTime("2010-05-27T16:24:31"))
         self.assertTrue(re[0]['time'] < UTCDateTime("2010-05-27T16:24:35"))
         self.assertTrue(4.2 < re[0]['duration'] < 4.8)
         self.assertTrue(re[0]['stations'] == ['UH3', 'UH1', 'UH4'])
         self.assertTrue(re[0]['coincidence_sum'] == 3)
         self.assertTrue(re[1]['time'] > UTCDateTime("2010-05-27T16:27:27"))
         self.assertTrue(re[1]['time'] < UTCDateTime("2010-05-27T16:27:33"))
         self.assertTrue(4.2 < re[1]['duration'] < 4.4)
         self.assertTrue(re[1]['stations'] == ['UH3', 'UH1', 'UH4'])
         self.assertTrue(re[1]['coincidence_sum'] == 3)
     # 3. weighting, station selection
     # => 3 events, no false triggers
     trace_ids = {
         'BW.UH1..SHZ': 0.4,
         'BW.UH2..SHZ': 0.35,
         'BW.UH3..SHZ': 0.4,
         'BW.UH4..EHZ': 0.25
     }
     res = coincidenceTrigger("recstalta",
                              3.5,
                              1,
                              st.copy(),
                              1.0,
                              trace_ids=trace_ids,
                              sta=0.5,
                              lta=10)
     self.assertTrue(len(res) == 3)
     self.assertTrue(res[0]['time'] > UTCDateTime("2010-05-27T16:24:31"))
     self.assertTrue(res[0]['time'] < UTCDateTime("2010-05-27T16:24:35"))
     self.assertTrue(4.2 < res[0]['duration'] < 4.8)
     self.assertTrue(res[0]['stations'] == ['UH3', 'UH2', 'UH1', 'UH4'])
     self.assertTrue(res[0]['coincidence_sum'] == 1.4)
     self.assertTrue(res[1]['time'] > UTCDateTime("2010-05-27T16:26:59"))
     self.assertTrue(res[1]['time'] < UTCDateTime("2010-05-27T16:27:03"))
     self.assertTrue(3.2 < res[1]['duration'] < 3.7)
     self.assertTrue(res[1]['stations'] == ['UH2', 'UH3', 'UH1'])
     self.assertTrue(res[1]['coincidence_sum'] == 1.15)
     self.assertTrue(res[2]['time'] > UTCDateTime("2010-05-27T16:27:27"))
     self.assertTrue(res[2]['time'] < UTCDateTime("2010-05-27T16:27:33"))
     self.assertTrue(4.2 < res[2]['duration'] < 4.4)
     self.assertTrue(res[2]['stations'] == ['UH3', 'UH2', 'UH1', 'UH4'])
     self.assertTrue(res[2]['coincidence_sum'] == 1.4)
     # 4. weighting, station selection, max_len
     # => 2 events, no false triggers, small event does not overlap anymore
     trace_ids = {'BW.UH1..SHZ': 0.6, 'BW.UH2..SHZ': 0.6}
     # ignore UserWarnings
     with warnings.catch_warnings(record=True):
         warnings.simplefilter('ignore', UserWarning)
         re = coincidenceTrigger("recstalta",
                                 3.5,
                                 1,
                                 st.copy(),
                                 1.2,
                                 trace_ids=trace_ids,
                                 max_trigger_length=0.13,
                                 sta=0.5,
                                 lta=10)
         self.assertTrue(len(re) == 2)
         self.assertTrue(re[0]['time'] > UTCDateTime("2010-05-27T16:24:31"))
         self.assertTrue(re[0]['time'] < UTCDateTime("2010-05-27T16:24:35"))
         self.assertTrue(0.2 < re[0]['duration'] < 0.3)
         self.assertTrue(re[0]['stations'] == ['UH2', 'UH1'])
         self.assertTrue(re[0]['coincidence_sum'] == 1.2)
         self.assertTrue(re[1]['time'] > UTCDateTime("2010-05-27T16:27:27"))
         self.assertTrue(re[1]['time'] < UTCDateTime("2010-05-27T16:27:33"))
         self.assertTrue(0.18 < re[1]['duration'] < 0.2)
         self.assertTrue(re[1]['stations'] == ['UH2', 'UH1'])
         self.assertTrue(re[1]['coincidence_sum'] == 1.2)
     # 5. station selection, extremely sensitive settings
     # => 4 events, 1 false triggers
     res = coincidenceTrigger("recstalta",
                              2.5,
                              1,
                              st.copy(),
                              2,
                              trace_ids=['BW.UH1..SHZ', 'BW.UH3..SHZ'],
                              sta=0.3,
                              lta=5)
     self.assertTrue(len(res) == 5)
     self.assertTrue(res[3]['time'] > UTCDateTime("2010-05-27T16:27:01"))
     self.assertTrue(res[3]['time'] < UTCDateTime("2010-05-27T16:27:02"))
     self.assertTrue(1.5 < res[3]['duration'] < 1.7)
     self.assertTrue(res[3]['stations'] == ['UH3', 'UH1'])
     self.assertTrue(res[3]['coincidence_sum'] == 2.0)
     # 6. same as 5, gappy stream
     # => same as 5 (almost, duration of 1 event changes by 0.02s)
     st2 = st.copy()
     tr1 = st2.pop(0)
     t1 = tr1.stats.starttime
     t2 = tr1.stats.endtime
     td = t2 - t1
     tr1a = tr1.slice(starttime=t1, endtime=t1 + 0.45 * td)
     tr1b = tr1.slice(starttime=t1 + 0.6 * td, endtime=t1 + 0.94 * td)
     st2.insert(1, tr1a)
     st2.insert(3, tr1b)
     res = coincidenceTrigger("recstalta",
                              2.5,
                              1,
                              st2,
                              2,
                              trace_ids=['BW.UH1..SHZ', 'BW.UH3..SHZ'],
                              sta=0.3,
                              lta=5)
     self.assertTrue(len(res) == 5)
     self.assertTrue(res[3]['time'] > UTCDateTime("2010-05-27T16:27:01"))
     self.assertTrue(res[3]['time'] < UTCDateTime("2010-05-27T16:27:02"))
     self.assertTrue(1.5 < res[3]['duration'] < 1.7)
     self.assertTrue(res[3]['stations'] == ['UH3', 'UH1'])
     self.assertTrue(res[3]['coincidence_sum'] == 2.0)
     # 7. same as 3 but modify input trace ids and check output of trace_ids
     # and other additional information with ``details=True``
     st2 = st.copy()
     st2[0].stats.network = "XX"
     st2[1].stats.location = "99"
     st2[1].stats.network = ""
     st2[1].stats.location = "99"
     st2[1].stats.channel = ""
     st2[2].stats.channel = "EHN"
     st2[3].stats.network = ""
     st2[3].stats.channel = ""
     st2[3].stats.station = ""
     trace_ids = {
         'XX.UH1..SHZ': 0.4,
         '.UH2.99.': 0.35,
         'BW.UH3..EHN': 0.4,
         '...': 0.25
     }
     res = coincidenceTrigger("recstalta",
                              3.5,
                              1,
                              st2,
                              1.0,
                              trace_ids=trace_ids,
                              details=True,
                              sta=0.5,
                              lta=10)
     self.assertTrue(len(res) == 3)
     self.assertTrue(res[0]['time'] > UTCDateTime("2010-05-27T16:24:31"))
     self.assertTrue(res[0]['time'] < UTCDateTime("2010-05-27T16:24:35"))
     self.assertTrue(4.2 < res[0]['duration'] < 4.8)
     self.assertTrue(res[0]['stations'] == ['UH3', 'UH2', 'UH1', ''])
     self.assertTrue(res[0]['trace_ids'][0] == st2[2].id)
     self.assertTrue(res[0]['trace_ids'][1] == st2[1].id)
     self.assertTrue(res[0]['trace_ids'][2] == st2[0].id)
     self.assertTrue(res[0]['trace_ids'][3] == st2[3].id)
     self.assertTrue(res[0]['coincidence_sum'] == 1.4)
     self.assertTrue(res[1]['time'] > UTCDateTime("2010-05-27T16:26:59"))
     self.assertTrue(res[1]['time'] < UTCDateTime("2010-05-27T16:27:03"))
     self.assertTrue(3.2 < res[1]['duration'] < 3.7)
     self.assertTrue(res[1]['stations'] == ['UH2', 'UH3', 'UH1'])
     self.assertTrue(res[1]['trace_ids'][0] == st2[1].id)
     self.assertTrue(res[1]['trace_ids'][1] == st2[2].id)
     self.assertTrue(res[1]['trace_ids'][2] == st2[0].id)
     self.assertTrue(res[1]['coincidence_sum'] == 1.15)
     self.assertTrue(res[2]['time'] > UTCDateTime("2010-05-27T16:27:27"))
     self.assertTrue(res[2]['time'] < UTCDateTime("2010-05-27T16:27:33"))
     self.assertTrue(4.2 < res[2]['duration'] < 4.4)
     self.assertTrue(res[2]['stations'] == ['UH3', 'UH2', 'UH1', ''])
     self.assertTrue(res[2]['trace_ids'][0] == st2[2].id)
     self.assertTrue(res[2]['trace_ids'][1] == st2[1].id)
     self.assertTrue(res[2]['trace_ids'][2] == st2[0].id)
     self.assertTrue(res[2]['trace_ids'][3] == st2[3].id)
     self.assertTrue(res[2]['coincidence_sum'] == 1.4)
     expected_keys = [
         'cft_peak_wmean', 'cft_std_wmean', 'cft_peaks', 'cft_stds'
     ]
     expected_types = [float, float, list, list]
     for item in res:
         for key, _type in zip(expected_keys, expected_types):
             self.assertTrue(key in item)
             self.assertTrue(isinstance(item[key], _type))
     # check some of the detailed info
     ev = res[-1]
     self.assertAlmostEquals(ev['cft_peak_wmean'], 18.097582068353855)
     self.assertAlmostEquals(ev['cft_std_wmean'], 4.7972436395074087)
     self.assertAlmostEquals(ev['cft_peaks'][0], 18.973097608513633)
     self.assertAlmostEquals(ev['cft_peaks'][1], 16.852175794415011)
     self.assertAlmostEquals(ev['cft_peaks'][2], 18.64005853900883)
     self.assertAlmostEquals(ev['cft_peaks'][3], 17.572363634564621)
     self.assertAlmostEquals(ev['cft_stds'][0], 4.8811165222946951)
     self.assertAlmostEquals(ev['cft_stds'][1], 4.4446373508521804)
     self.assertAlmostEquals(ev['cft_stds'][2], 5.3499401252675964)
     self.assertAlmostEquals(ev['cft_stds'][3], 4.2723814539487703)
            if not st:
                logging.error(f"No data retrieved for {STA}")
                continue

            st.merge(fill_value='latest')
            st.trim(STARTTIME - 2 * config.taper_val,
                    ENDTIME + 2 * config.taper_val,
                    pad='true',
                    fill_value=0)
            st.sort()
            logging.info(st)

            # print('Removing sensitivity...')
            # st.remove_sensitivity()

            stf = st.copy()
            stf.detrend('demean')
            stf.taper(max_percentage=None, max_length=config.taper_val)
            stf.filter("bandpass",
                       freqmin=FMIN,
                       freqmax=FMAX,
                       corners=2,
                       zerophase=True)
            st.trim(STARTTIME, ENDTIME, pad='true', fill_value=0)

            # %% Get inventory and lat/lon info
            client = Client("IRIS")
            try:
                inv = client.get_stations(network=NET,
                                          station=STA,
                                          channel=CHAN,
Example #18
0
def main():

    print()
    print("#########################################")
    print("#        __                 _     _     #")
    print("#  _ __ / _|_ __  _   _    | |__ | | __ #")
    print("# | '__| |_| '_ \| | | |   | '_ \| |/ / #")
    print("# | |  |  _| |_) | |_| |   | | | |   <  #")
    print("# |_|  |_| | .__/ \__, |___|_| |_|_|\_\ #")
    print("#          |_|    |___/_____|           #")
    print("#                                       #")
    print("#########################################")
    print()

    # Run Input Parser
    args = arguments.get_hk_arguments()

    # Load Database
    db = stdb.io.load_db(fname=args.indb)

    # Construct station key loop
    allkeys = db.keys()
    sorted(allkeys)

    # Extract key subset
    if len(args.stkeys) > 0:
        stkeys = []
        for skey in args.stkeys:
            stkeys.extend([s for s in allkeys if skey in s])
    else:
        stkeys = db.keys()
        sorted(stkeys)

    # Loop over station keys
    for stkey in list(stkeys):

        # Extract station information from dictionary
        sta = db[stkey]

        # Define path to see if it exists
        if args.phase in ['P', 'PP', 'allP']:
            datapath = Path('P_DATA') / stkey
        elif args.phase in ['S', 'SKS', 'allS']:
            datapath = Path('S_DATA') / stkey
        if not datapath.is_dir():
            print('Path to ' + str(datapath) + ' doesn`t exist - continuing')
            continue

        # Define save path
        if args.save:
            savepath = Path('HK_DATA') / stkey
            if not savepath.is_dir():
                print('Path to ' + str(savepath) +
                      ' doesn`t exist - creating it')
                savepath.mkdir(parents=True)

        # Get search start time
        if args.startT is None:
            tstart = sta.startdate
        else:
            tstart = args.startT

        # Get search end time
        if args.endT is None:
            tend = sta.enddate
        else:
            tend = args.endT

        if tstart > sta.enddate or tend < sta.startdate:
            continue

        # Temporary print locations
        tlocs = sta.location
        if len(tlocs) == 0:
            tlocs = ['']
        for il in range(0, len(tlocs)):
            if len(tlocs[il]) == 0:
                tlocs[il] = "--"
        sta.location = tlocs

        # Update Display
        print(" ")
        print(" ")
        print("|===============================================|")
        print("|===============================================|")
        print("|                   {0:>8s}                    |".format(
            sta.station))
        print("|===============================================|")
        print("|===============================================|")
        print("|  Station: {0:>2s}.{1:5s}                            |".format(
            sta.network, sta.station))
        print("|      Channel: {0:2s}; Locations: {1:15s}  |".format(
            sta.channel, ",".join(tlocs)))
        print("|      Lon: {0:7.2f}; Lat: {1:6.2f}                |".format(
            sta.longitude, sta.latitude))
        print("|      Start time: {0:19s}          |".format(
            sta.startdate.strftime("%Y-%m-%d %H:%M:%S")))
        print("|      End time:   {0:19s}          |".format(
            sta.enddate.strftime("%Y-%m-%d %H:%M:%S")))
        print("|-----------------------------------------------|")

        rfRstream = Stream()

        datafiles = [x for x in datapath.iterdir() if x.is_dir()]
        for folder in datafiles:

            # Skip hidden folders
            if folder.name.startswith('.'):
                continue

            date = folder.name.split('_')[0]
            year = date[0:4]
            month = date[4:6]
            day = date[6:8]
            dateUTC = UTCDateTime(year + '-' + month + '-' + day)

            if dateUTC > tstart and dateUTC < tend:

                # Load meta data
                metafile = folder / "Meta_Data.pkl"
                if not metafile.is_file():
                    continue
                meta = pickle.load(open(metafile, 'rb'))

                # Skip data not in list of phases
                if meta.phase not in args.listphase:
                    continue

                # QC Thresholding
                if meta.snrh < args.snrh:
                    continue
                if meta.snr < args.snr:
                    continue
                if meta.cc < args.cc:
                    continue

                # # Check bounds on data
                # if meta.slow < args.slowbound[0] and meta.slow > args.slowbound[1]:
                #     continue
                # if meta.baz < args.bazbound[0] and meta.baz > args.bazbound[1]:
                #     continue

                # If everything passed, load the RF data
                filename = folder / "RF_Data.pkl"
                if filename.is_file():
                    file = open(filename, "rb")
                    rfdata = pickle.load(file)
                    rfRstream.append(rfdata[1])
                    file.close()
                if rfdata[0].stats.npts != 1451:
                    print(folder)

        if len(rfRstream) == 0:
            continue

        if args.no_outl:
            t1 = 0.
            t2 = 30.

            varR = []
            for i in range(len(rfRstream)):
                taxis = rfRstream[i].stats.taxis
                tselect = (taxis > t1) & (taxis < t2)
                varR.append(np.var(rfRstream[i].data[tselect]))
            varR = np.array(varR)

            # Remove outliers wrt variance within time range
            medvarR = np.median(varR)
            madvarR = 1.4826 * np.median(np.abs(varR - medvarR))
            robustR = np.abs((varR - medvarR) / madvarR)
            outliersR = np.arange(len(rfRstream))[robustR > 2.5]
            for i in outliersR[::-1]:
                rfRstream.remove(rfRstream[i])

        print('')
        print("Number of radial RF data: " + str(len(rfRstream)))
        print('')

        # Try binning if specified
        if args.calc_dip:
            rf_tmp = binning.bin_baz_slow(rfRstream,
                                          nbaz=args.nbaz + 1,
                                          nslow=args.nslow + 1,
                                          pws=args.pws)
            rfRstream = rf_tmp[0]
        else:
            rf_tmp = binning.bin(rfRstream,
                                 typ='slow',
                                 nbin=args.nslow + 1,
                                 pws=args.pws)
            rfRstream = rf_tmp[0]

        # Get a copy of the radial component and filter
        if args.copy:
            rfRstream_copy = rfRstream.copy()
            rfRstream_copy.filter('bandpass',
                                  freqmin=args.bp_copy[0],
                                  freqmax=args.bp_copy[1],
                                  corners=2,
                                  zerophase=True)

        # Check bin counts:
        for tr in rfRstream:
            if (tr.stats.nbin < args.binlim):
                rfRstream.remove(tr)

        # Continue if stream is too short
        if len(rfRstream) < 5:
            continue

        if args.save_plot and not Path('HK_PLOTS').is_dir():
            Path('HK_PLOTS').mkdir(parents=True)

        print('')
        print("Number of radial RF bins: " + str(len(rfRstream)))
        print('')

        # Filter original stream
        rfRstream.filter('bandpass',
                         freqmin=args.bp[0],
                         freqmax=args.bp[1],
                         corners=2,
                         zerophase=True)

        # Initialize the HkStack object
        try:
            hkstack = HkStack(rfRstream,
                              rfV2=rfRstream_copy,
                              strike=args.strike,
                              dip=args.dip,
                              vp=args.vp)
        except:
            hkstack = HkStack(rfRstream,
                              strike=args.strike,
                              dip=args.dip,
                              vp=args.vp)

        # Update attributes
        hkstack.hbound = args.hbound
        hkstack.kbound = args.kbound
        hkstack.dh = args.dh
        hkstack.dk = args.dk
        hkstack.weights = args.weights

        # Stack with or without dip
        if args.calc_dip:
            hkstack.stack_dip()
        else:
            hkstack.stack()

        # Average stacks
        hkstack.average(typ=args.typ)

        if args.plot:
            hkstack.plot(args.save_plot, args.title, args.form)

        if args.save:
            filename = savepath / (hkstack.rfV1[0].stats.station + \
                ".hkstack."+args.typ+".pkl")

            hkstack.save(file=filename)
Example #19
0
def parallel_waveformDL(mpi_flatfile_directory,eventdir_unfiltered,eventdir_filtered,client_name,resp_prefilt_bottom,respfilt_bottom,start_delta,end_delta,fig_x,fig_y,output_directory,rank,size):
    '''
    Run the waveform data download in parallel.
    Attempts to download waveforms for record information in each line of 
    latfile_csvpath. Removes instrument response and saves as unfiltered, also
    removes inst. resp and filters and saves in a separate directory for the 
    event, directory structure supplied as input. Data and plots only saved if
    SNR >=5.  Makes a figure of the waveform with theoretical P and S wave
    arrival times, and outputs new flatfile.
    Input:
        mpi_flatfile_directory: String with the directory containing the MPI flatfiles, saved in format "flatfile_{rank}.csv"
        eventdir_unfiltered:    String with the path to the unfiltered event save directory
        eventdir_filtered:      String with the path to the filtered event save directory
        client_name:            String with the client name (i.e., 'NCEDC')
        resp_prefilt_bottom:    List with the bottom two values in Hz to use in prefilt to use response (i.e., [0.005, 0.006])
        respfilt_bottom:        List with the bottom two values in Hz to use in prefilt w/ filtering as well
        start_delta:            Float with time difference in seconds to subtract from p-wave arrival for downloading waveforms
        end_delta:              Float with time difference in seconds to add to S wave arrival for downloading waveforms
        fig_x:                  Figure size x in inches to use for plotting the waveforms 
        fig_y:                  Figure size y in inches to use for plotting the waveforms 
        output_directory:       Float with path of directory to use for output flatfile csv's, WITHOUT slash at end
        rank:                   Float with the rank
        size:                   Float with the size
    Output:
        
    '''
    
    from obspy.clients.fdsn import Client
    from obspy.core import Stream, read, UTCDateTime
    from datetime import datetime, timedelta
    import matplotlib.pyplot as plt
    from glob import glob
    import numpy as np
    import csv
    import pandas as pd
    from os import path,makedirs
    import kappa_utils as kutils
   
    # InitializeLog file for data with unequal HHN and HHE lengths
    log = '/home/tnye/kappa/data/record_length.log'
    f = open(log,'w+')

    data_dir1 = eventdir_unfiltered
    data_dir2 = eventdir_filtered
    flatfile_path = mpi_flatfile_directory + '/flatfile_' + np.str(rank) + '.csv'
    client = Client(client_name)
    start_td = start_delta  ## Time difference to subtract from p-wave arrival for downloading waveforms
    end_td = end_delta ## Time difference to add to S wave arrival for downloading waveforms
    ## Filter bottoms to use in prefilt for -
    ##  INstrument response ONLY:
    resp_only_filtbottom = resp_prefilt_bottom
    ##  Instrument response and filtering
    resp_filt_filtbottom = respfilt_bottom
    ## Figure size:
    figure_size = (fig_x,fig_y)
    
    print('\n')
    
    ## Read in metadata:
    allmetadata = pd.read_csv(flatfile_path)
    
    ## Go through the metadata lines, extract record metadata, download waveforms,
    ##  correct instrument response / filter, make plots + save, save as a SAC in 
    ##  the appropriate directory.
    
    ## Start a counter for hte number of lines
    count = 0 
    ## Counter for the number of station/event permutations missed (no data to DL)
    nummissed = 0
    ## Empty list for... ?
    ffl = []
    
    ## Empty arrays for output flatfiles if the data was downloaded
    out_network = np.array([])
    out_station = np.array([])
    out_stlat = np.array([])
    out_stlon = np.array([])
    out_stelv = np.array([])
    out_quakenum = np.array([])
    out_m = np.array([])
    out_qlat = np.array([])
    out_qlon = np.array([])
    out_qdep = np.array([])
    out_orgt = np.array([])
    out_rhyp = np.array([])
    out_parr = np.array([])
    out_sarr = np.array([])

    ## Loop over the lines in the given file 
    for i_line in range(len(allmetadata)):
        
        #if nummissed == 10000:
        #    break
        ## Grab the appropriate metadata for this line
        i_eventnum = allmetadata.loc[i_line]['Quake#']
        i_qlon = allmetadata.loc[i_line]['Qlon']
        i_qlat = allmetadata.loc[i_line]['Qlat']
        i_qdep = allmetadata.loc[i_line]['Qdep']
        i_m = allmetadata.loc[i_line]['Mag']
        
        ##Origin time
        i_origintime = allmetadata.loc[i_line]['OrgT']
        i_date,i_time = allmetadata.loc[i_line]['OrgT'].split(' ')
        i_year,i_month,i_day = i_date.split('-')
        i_hr,i_min,i_sec = i_time.split(':')
       # try:
           # print(f'Origin = {i_origintime}... Try:')
           # i_sec,_ = i_sec.split('.')
       # except:
            #print(f'Origin = {i_origintime}... Except:')
           # continue
        
        i_parr = allmetadata.loc[i_line]['Parr']
        i_sarr =  allmetadata.loc[i_line]['Sarr']
        i_network = allmetadata.loc[i_line]['Network']
        i_Parr = datetime.strptime(i_parr,"%Y-%m-%d %H:%M:%S")
        i_Sarr =datetime.strptime(i_sarr,"%Y-%m-%d %H:%M:%S")
        i_station = allmetadata.loc[i_line]['Name']
        i_stlon = allmetadata.loc[i_line]['Slon']
        i_stlat = allmetadata.loc[i_line]['Slat']
        i_stelv = allmetadata.loc[i_line]['Selv']
        
        i_rhyp = allmetadata.loc[i_line]['rhyp']
        
        sp = i_Sarr - i_Parr   ## Get the s arrival - p arrival time difference
        i_start = i_Sarr - timedelta(seconds=start_td)
        i_end = i_start + timedelta(seconds=end_td)
        i_network = str(i_network)
        i_station = str(i_station)

        event = 'Event'+'_'+i_year+'_'+i_month+'_'+i_day+'_'+i_hr+'_'+i_min+'_'+i_sec
        
    ########################################################################################################################################3
        ## Initiate empty stream obmects for the N and E channels
        raw_stn = Stream()
        raw_ste = Stream()
        
        ## Try to download data for the N channel - if it works, add it to the N 
        ##  stream object
#        print(f'searching for {i_network} {i_station} HNN event {i_eventnum} on rank {rank}')
        try:
            raw_stn += client.get_waveforms(i_network, i_station, "*", 'HHN', UTCDateTime(i_start), UTCDateTime(i_end), attach_response=True)
        ## If it's missed, add 0.5 to the missed number (half a channel missing),
        ##  and continue...
        except:
            nummissed += .5
            #print('missed DL record for network ' + i_network + ', station ' + i_station + ' on channel HHN, event ' + np.str(i_eventnum))
            ## continue to next line of loop (i_line)
            continue
        
        ## Make copies of the raw station objects to use for removing instrument 
        ##   response ONLY, and for removing ins. resp and filtering:
        ir_stn = raw_stn.copy()
        ir_filt_stn = raw_stn.copy()
        
        ## Get sampling rate and make the filters to use in removing instrument response
        samprate = ir_stn[0].stats['sampling_rate']
        ## Make the prefilt for the instrment response - 1/2 sampling rate is nyquist
        prefilt1 = (resp_only_filtbottom[0], resp_only_filtbottom[1], ((samprate/2)-5), (samprate/2))  ## this is 20 to 25 at the end
        try:
            ir_stn[0].remove_response(output='ACC',pre_filt=prefilt1) ## The units of data are now acceleration, m/s/s
        except:
            nummissed += .5
            #print('missed remove IR record for network ' + i_network + ', station ' + i_station + ' on channel HHN, event ' + np.str(i_eventnum))
            ## continue to next line of loop (i_line)
            continue
        prefilt2 = (resp_filt_filtbottom[0],resp_filt_filtbottom[1], ((samprate/2)-5), (samprate/2)) ## 0.063 just above 16 sec microsiesem, .28 just above 4 sec
        try:
            ir_filt_stn[0].remove_response(output='ACC',pre_filt=prefilt2) ## The units of data are now acceleration, m/s/s
        except:
            nummissed += .5
            #print('missed remove IR record for network ' + i_network + ', station ' + i_station + ' on channel HHN, event ' + np.str(i_eventnum))
            ## continue to next line of loop (i_line)
            continue
        
        
    ######################################################################################################################################################################################
        ## Try to download for the E channel - if it works, do same as above
#        print(f'searching for {i_network} {i_station} HNE event {i_eventnum} on rank {rank}')
        try:
            raw_ste += client.get_waveforms(i_network, i_station, "*", 'HHE', UTCDateTime(i_start), UTCDateTime(i_end), attach_response=True)
        except:
            nummissed += .5
            #print('missed DL record for network ' + i_network + ', station ' + i_station + ' on channel HHE, event ' + np.str(i_eventnum))
            continue
        ir_ste = raw_ste.copy()
        ir_filt_ste = raw_ste.copy()
        
        
        samprate = ir_ste[0].stats['sampling_rate']
        ## Make the prefilt for the instrment response - AT.SIT is @ 50Hz so 25 is nyquist
        prefilt1 = (resp_only_filtbottom[0], resp_only_filtbottom[1], ((samprate/2)-5), (samprate/2))  ## this is 20 to 25 at the end
        try:
            ir_ste[0].remove_response(output='ACC',pre_filt=prefilt1) ## The units of data are now acceleration, m/s/s
        except:
            nummissed += .5
            #print('missed remove IR record for network ' + i_network + ', station ' + i_station + ' on channel HHE, event ' + np.str(i_eventnum))
            ## continue to next line of loop (i_line)
            continue
        prefilt2 = (resp_filt_filtbottom[0],resp_filt_filtbottom[1], ((samprate/2)-5), (samprate/2)) ## 0.063 just above 16 sec microsiesem, .28 just above 4 sec
        try:
            ir_filt_ste[0].remove_response(output='ACC',pre_filt=prefilt2) ## The units of data are now acceleration, m/s/s
        except:
            nummissed += .5
            #print('missed remove IR record for network ' + i_network + ', station ' + i_station + ' on channel HHE, event ' + np.str(i_eventnum))
            ## continue to next line of loop (i_line)
            continue
        
        if len(raw_stn[0].data) != len(raw_ste[0].data):
            print('Length HHN != Length HHE')
            print(f'\t{i_network} {i_station}')
            print(f'\t{event}')
            f.write(f'{i_network} {i_station} {event}\n')

    ######################################################################################################################################################################################
        ## Calculate SNR and only save waveforms and plots if it's >= 5. 
        SNR_N = kutils.comp_SNR(ir_filt_stn, 10, 30, 15)
        SNR_E = kutils.comp_SNR(ir_filt_ste, 10, 30, 15)
        SNR_avg = (SNR_N + SNR_E)/2
        
#        print(f'SNR for {i_network} {i_station} {i_eventnum} is {SNR_avg} on rank {rank}') 

        if SNR_avg >=5:
            
            ## Make sure paths exist
            if not path.exists(data_dir1+event):
                makedirs(data_dir1+event)
            if not path.exists(data_dir2+event):
                makedirs(data_dir2+event)
            
            ### North component 
            ## make and save plot of unfiltered data
            # plt.figure(figsize=figure_size)
            # plt.plot(ir_stn[0].times(),ir_stn[0].data,'g')
            # ## Plot a vertical line for the p-wave arrival
            # plt.axvline(x=start_td)
            # ## Plot a vertical line for the s-wave arrival
            # plt.axvline(x=start_td-sp.seconds)
            # plt.xlabel('Time from ')
            # plt.ylabel('Acceleration (m/s/s)')
            # plt.title('Instrument Response Removed, Unfiltered, \n' + i_network + i_station )
            # plt.savefig(data_dir1+event+'/'+i_network+'_'+i_station+'_'+'HHN'+'_'+i_year+'_'+i_month+'_'+i_day+'_'+i_hr+'_'+i_min+ '_' + i_sec +'.png')
            # plt.close('all')
            ir_stn[0].write(data_dir1+event+'/'+i_network+'_'+i_station+'_'+'HHN'+'_'+i_year+'_'+i_month+'_'+i_day+'_'+i_hr+'_'+i_min+ '_'+ i_sec + '.sac',format='SAC')
            
            ## make and save plot of filtered data
            # plt.figure(figsize=figure_size)
            # plt.plot(ir_filt_stn[0].times(),ir_filt_stn[0].data,'g')
            # ## Plot a vertical line for the p-wave arrival
            # plt.axvline(x=start_td)
            # ## Plot a vertical line for the s-wave arrival
            # plt.axvline(x=start_td-sp.seconds)
            # plt.xlabel('Time from ')
            # plt.ylabel('Acceleration (m/s/s)')
            # plt.title('Instrument Response Removed, filtered, \n' + i_network +i_station )
            # plt.savefig(data_dir2+event+'/'+i_network+'_'+i_station+'_'+'HHN'+'_'+i_year+'_'+i_month+'_'+i_day+'_'+i_hr+'_'+i_min+ '_' + i_sec +'.png')
            # plt.close('all')
            ir_filt_stn[0].write(data_dir2+event+'/'+i_network+'_'+i_station+'_'+'HHN'+'_'+i_year+'_'+i_month+'_'+i_day+'_'+i_hr+'_'+i_min+ '_' + i_sec + '.sac',format='SAC')
            
            ### East component 
            ## make and save plot of unfiltered data
            # plt.figure(figsize=figure_size)
            # plt.plot(ir_ste[0].times(),ir_ste[0].data,'g')
            # ## Plot a vertical line for the p-wave arrival
            # plt.axvline(x=start_td)
            # ## Plot a vertical line for the s-wave arrival
            # plt.axvline(x=start_td-sp.seconds)
            # plt.xlabel('Time from ')
            # plt.ylabel('Acceleration (m/s/s)')
            # plt.title('Instrument Response Removed, Unfiltered, \n' + i_network + i_station )
            # plt.savefig(data_dir1+event+'/'+i_network+'_'+i_station+'_'+'HHE'+'_'+i_year+'_'+i_month+'_'+i_day+'_'+i_hr+'_'+i_min+ '_' + i_sec +'.png')
            # plt.close('all')
            ir_ste[0].write(data_dir1+event+'/'+i_network+'_'+i_station+'_'+'HHE'+'_'+i_year+'_'+i_month+'_'+i_day+'_'+i_hr+'_'+i_min+ '_' + i_sec +'.sac',format='SAC')
            
            ## make and save plot of filtered data
            # plt.figure(figsize=figure_size)
            # plt.plot(ir_filt_ste[0].times(),ir_filt_ste[0].data,'g')
            # ## Plot a vertical line for the p-wave arrival
            # plt.axvline(x=start_td)
            # ## Plot a vertical line for the s-wave arrival
            # plt.axvline(x=start_td-sp.seconds)
            # plt.xlabel('Time from ')
            # plt.ylabel('Acceleration (m/s/s)')
            # plt.title('Instrument Response Removed, filtered, \n' + i_network + i_station )
            # plt.savefig(data_dir2+event+'/'+i_network+'_'+i_station+'_'+'HHE'+'_'+i_year+'_'+i_month+'_'+i_day+'_'+i_hr+'_'+i_min+ '_' + i_sec +'.png')
            # plt.close('all')
            ir_filt_ste[0].write(data_dir2+event+'/'+i_network+'_'+i_station+'_'+'HHE'+'_'+i_year+'_'+i_month+'_'+i_day+'_'+i_hr+'_'+i_min+ '_' + i_sec +'.sac',format='SAC')
            
            ## Add to arrays for new output file:
            out_network = np.append(out_network,i_network)
            out_station = np.append(out_station,i_station)
            out_stlat = np.append(out_stlat,i_stlat)
            out_stlon = np.append(out_stlon,i_stlon)
            out_stelv = np.append(out_stelv,i_stelv)
            out_quakenum = np.append(out_quakenum,i_eventnum)
            out_m = np.append(out_m,i_m)
            out_qlat = np.append(out_qlat,i_qlat)
            out_qlon = np.append(out_qlon,i_qlon)
            out_qdep = np.append(out_qdep,i_qdep)
            out_orgt = np.append(out_orgt,i_origintime)
            out_rhyp = np.append(out_rhyp,i_rhyp)
            out_parr = np.append(out_parr,i_parr)
            out_sarr = np.append(out_sarr,i_sarr)
    
    ## Make new dataframe and flatfile with output arrays:
    ## Dict:
    collected_dict = {'Network':out_network,'Name':out_station,'Slat':out_stlat,'Slon':out_stlon,
                      'Selv':out_stelv,'Quake#':out_quakenum,'Mag':out_m,'Qlat':out_qlat,
                      'Qlon':out_qlon,'Qdep':out_qdep,'OrgT':out_orgt,'rhyp':out_rhyp,
                      'Parr':out_parr,'Sarr':out_sarr}
    collected_df = pd.DataFrame(collected_dict)
    ## Write to file:
    collected_df.to_csv(output_directory+'collected_flatfile+'+np.str(rank)+'.csv')
    
    f.close()
Example #20
0
plt.figure(figsize=(12, 6))
plt.plot(st2[0].times(), st2[0].data)
plt.xlabel('Time from ')
plt.ylabel('Velocity (m/s)')
plt.title('Instrument Response Removed, Unfiltered, \n AT station SIT')
#plt.savefig(data_dir + 'at.sit_unfilt.png')

print('Write unfiltered response removed')
## Write the data (instr resp removed) to a SAC file, m/s
#st2.write(data_dir+'at.sit_unfilt.sac',format='SAC')
#%%
print('Filter')
## Filter the data with a highpass filter around the 13s microseism:
filtfreq = 1 / 13.
## Make a copy of the stream object:
st2filt = st2.copy()
## Highpass filter using 2 corners, zerophase true so it filters forwards and back
##   (so 4 corners in the end):
st2filt[0].filter('highpass', freq=filtfreq, corners=2, zerophase=True)

print('Plot filtered')
## Plot:
plt.figure(figsize=(12, 6))
plt.plot(st2filt[0].times(), st2filt[0].data)
plt.xlabel('Time from Aug17_2015 UTC midnight (s)')
plt.ylabel('Velocity (m/s)')
plt.title(
    'Instrument Response Removed, Highpass filtered 13sec, \n AT station SIT')
plt.savefig(data_dir + 'at.sit_hpfilt_13s.png')

print('Write to file')
Example #21
0
def main():

    # Run Input Parser
    (opts, indb) = options.get_hk_options()

    # Load Database
    db = stdb.io.load_db(fname=indb)

    # Construct station key loop
    allkeys = db.keys()
    sorted(allkeys)

    # Extract key subset
    if len(opts.stkeys) > 0:
        stkeys = []
        for skey in opts.stkeys:
            stkeys.extend([s for s in allkeys if skey in s])
    else:
        stkeys = db.keys()
        sorted(stkeys)

    # Loop over station keys
    for stkey in list(stkeys):

        # Extract station information from dictionary
        sta = db[stkey]

        # Define path to see if it exists
        datapath = 'DATA/' + stkey
        if not os.path.isdir(datapath):
            raise (Exception('Path to ' + datapath +
                             ' doesn`t exist - aborting'))

        # Get search start time
        if opts.startT is None:
            tstart = sta.startdate
        else:
            tstart = opts.startT

        # Get search end time
        if opts.endT is None:
            tend = sta.enddate
        else:
            tend = opts.endT

        if tstart > sta.enddate or tend < sta.startdate:
            continue

        # Temporary print locations
        tlocs = sta.location
        if len(tlocs) == 0:
            tlocs = ['']
        for il in range(0, len(tlocs)):
            if len(tlocs[il]) == 0:
                tlocs[il] = "--"
        sta.location = tlocs

        # Update Display
        print(" ")
        print(" ")
        print("|===============================================|")
        print("|===============================================|")
        print("|                   {0:>8s}                    |".format(
            sta.station))
        print("|===============================================|")
        print("|===============================================|")
        print("|  Station: {0:>2s}.{1:5s}                            |".format(
            sta.network, sta.station))
        print("|      Channel: {0:2s}; Locations: {1:15s}  |".format(
            sta.channel, ",".join(tlocs)))
        print("|      Lon: {0:7.2f}; Lat: {1:6.2f}                |".format(
            sta.longitude, sta.latitude))
        print("|      Start time: {0:19s}          |".format(
            sta.startdate.strftime("%Y-%m-%d %H:%M:%S")))
        print("|      End time:   {0:19s}          |".format(
            sta.enddate.strftime("%Y-%m-%d %H:%M:%S")))
        print("|-----------------------------------------------|")

        rfRstream = Stream()

        for folder in os.listdir(datapath):

            date = folder.split('_')[0]
            year = date[0:4]
            month = date[4:6]
            day = date[6:8]
            dateUTC = UTCDateTime(year + '-' + month + '-' + day)

            if dateUTC > tstart and dateUTC < tend:

                file = open(datapath + "/" + folder + "/RF_Data.pkl", "rb")
                rfdata = pickle.load(file)
                rfRstream.append(rfdata)
                file.close()

            else:
                continue

        # plotting.wiggle(rfRstream, sort='baz')

        # Try binning if specified
        if opts.nbin is not None:
            rf_tmp = binning.bin(rfRstream, typ='slow', nbin=opts.nbin + 1)
            rfRstream = rf_tmp[0]

        # Get a copy of the radial component and filter
        if opts.copy:
            rfRstream_copy = rfRstream.copy()
            rfRstream_copy.filter('bandpass',
                                  freqmin=opts.freqs_copy[0],
                                  freqmax=opts.freqs_copy[1],
                                  corners=2,
                                  zerophase=True)

        # Filter original stream
        rfRstream.filter('bandpass',
                         freqmin=opts.freqs[0],
                         freqmax=opts.freqs[1],
                         corners=2,
                         zerophase=True)

        # Initialize the HkStack object
        try:
            hkstack = HkStack(rfRstream,
                              rfV2=rfRstream_copy,
                              strike=opts.strike,
                              dip=opts.dip,
                              vp=opts.vp)
        except:
            hkstack = HkStack(rfRstream,
                              strike=opts.strike,
                              dip=opts.dip,
                              vp=opts.vp)

        # Update attributes
        hkstack.hbound = opts.hbound
        hkstack.kbound = opts.kbound
        hkstack.dh = opts.dh
        hkstack.dk = opts.dk
        hkstack.weights = opts.weights

        # Stack with or without dip
        if opts.calc_dip:
            hkstack.stack_dip()
        else:
            hkstack.stack()

        # Average stacks
        hkstack.average(typ=opts.typ)

        if opts.plot:
            hkstack.plot(opts.save_plot, opts.title, opts.form)

        if opts.save:
            filename = datapath + "/" + hkstack.hstream[0].stats.station + \
                ".hkstack.pkl"
            hkstack.save(file=filename)
Example #22
0
if debug:
    print(files)

# Make a stream object to hold data
st = Stream()
for curfile in files:
    if debug:
        print('Here is our current file: ' + curfile)
    st += read(curfile, starttime=stime, endtime=etime)
st.merge()
if debug:
    print(st)
    st.plot()
    
# Here we can do a 10 volt test
st2 = st.copy()
nstime = UTCDateTime('2017-011T16:59:55.0')
netime = nstime + 20.
st2.trim(starttime=nstime, endtime=netime)
# st2 Now has data for our first 10 V test
# Now we convert st2 into Volts

# Make two empty lists to save our results
mminus =[]
sminus =[]

# This is the first voltage 
for tr in st2:
    tr.data.astype(np.float64)
    # Here we are converting from counts to Volts
    tr.data = tr.data*(40. /(2.**26))
Example #23
0
        st = Stream()
        std = Stream()
        st = read('/auto/proj/Cascadia/PermStatWF/*/*[HE]HZ.%s.%s' %
                  (yr, jday))

        for tr in st:
            num = tr.stats.npts
            samp = tr.stats.sampling_rate

            if num >= (samp * 86400) * .80:
                std.append(tr)

        if len(std) > 0:  # need wf in stream to cont.
            std.sort(['starttime'])
            std.merge()
            std1 = std.copy()

            # want full day of waveform - trim to start - end time
            starttime1 = dt
            if jday == 365:  #handles end of year
                endtime1 = UTCDateTime(year=yr + 1, julday=1, hour=0, minute=0)
            else:
                endtime1 = dt + 86400  #1 day
            std1.trim(starttime=starttime1, endtime=endtime1)

            #pre-process day waveform data -- needs to be same as processing for templates
            std_filter = pre_processing.dayproc(std1,
                                                lowcut=3,
                                                highcut=10,
                                                filt_order=4,
                                                samp_rate=25,
Example #24
0
    i_start = i_Parr - timedelta(seconds=td)
    i_end = i_Sarr + timedelta(seconds=90)
    i_network = str(i_network)
    i_station = str(i_station)
########################################################################################################################################3
# chlear stream objects 
    raw_stn = Stream()
    raw_ste = Stream()
#data download and plot for Nort
    try:
        raw_stn += client.get_waveforms(i_network, i_station, "*", 'HHN', UTCDateTime(i_start), UTCDateTime(i_end), attach_response=True)
    except:
        nummissed += .5
        print('oops')
        continue
    i_stn = raw_stn.copy()
    j_stn = raw_stn.copy()
    
    
    samprate = i_stn[0].stats['sampling_rate']
    ## Make the prefilt for the instrment response - AT.SIT is @ 50Hz so 25 is nyquist
    prefilt1 = (0.005, 0.006, ((samprate/2)-5), (samprate/2))  ## this is 20 to 25 at the end
    i_stn[0].remove_response(output='VEL',pre_filt=prefilt1) ## The units of data are now Velocity, m/s
    prefilt2 = (0.063, 0.28,((samprate/2)-5), (samprate/2)) ## 0.063 just above 16 sec microsiesem, .28 just above 4 sec
    j_stn[0].remove_response(output='VEL',pre_filt=prefilt2) ## The units of data are now Velocity, m/s
    
    ## make and save plot
    plt.figure(figsize=(12,6))
    plt.plot(i_stn[0].times(),i_stn[0].data,'g')
    plt.axvline(x=td)
    plt.axvline(x=td+sp.seconds)
Example #25
0
 def test_coincidenceTrigger(self):
     """
     Test network coincidence trigger.
     """
     st = Stream()
     files = ["BW.UH1._.SHZ.D.2010.147.cut.slist.gz",
              "BW.UH2._.SHZ.D.2010.147.cut.slist.gz",
              "BW.UH3._.SHZ.D.2010.147.cut.slist.gz",
              "BW.UH4._.EHZ.D.2010.147.cut.slist.gz"]
     for filename in files:
         filename = os.path.join(self.path, filename)
         st += read(filename)
     # some prefiltering used for UH network
     st.filter('bandpass', freqmin=10, freqmax=20)
     # 1. no weighting, no stations specified, good settings
     # => 3 events, no false triggers
     # for the first test we make some additional tests regarding types
     res = coincidenceTrigger("recstalta", 3.5, 1, st.copy(), 3, sta=0.5,
                              lta=10)
     self.assertTrue(isinstance(res, list))
     self.assertTrue(len(res) == 3)
     expected_keys = ['time', 'coincidence_sum', 'duration', 'stations',
                      'trace_ids']
     expected_types = [UTCDateTime, float, float, list, list]
     for item in res:
         self.assertTrue(isinstance(item, dict))
         for key, _type in zip(expected_keys, expected_types):
             self.assertTrue(key in item)
             self.assertTrue(isinstance(item[key], _type))
     self.assertTrue(res[0]['time'] > UTCDateTime("2010-05-27T16:24:31"))
     self.assertTrue(res[0]['time'] < UTCDateTime("2010-05-27T16:24:35"))
     self.assertTrue(4.2 < res[0]['duration'] < 4.8)
     self.assertTrue(res[0]['stations'] == ['UH3', 'UH2', 'UH1', 'UH4'])
     self.assertTrue(res[0]['coincidence_sum'] == 4)
     self.assertTrue(res[1]['time'] > UTCDateTime("2010-05-27T16:26:59"))
     self.assertTrue(res[1]['time'] < UTCDateTime("2010-05-27T16:27:03"))
     self.assertTrue(3.2 < res[1]['duration'] < 3.7)
     self.assertTrue(res[1]['stations'] == ['UH2', 'UH3', 'UH1'])
     self.assertTrue(res[1]['coincidence_sum'] == 3)
     self.assertTrue(res[2]['time'] > UTCDateTime("2010-05-27T16:27:27"))
     self.assertTrue(res[2]['time'] < UTCDateTime("2010-05-27T16:27:33"))
     self.assertTrue(4.2 < res[2]['duration'] < 4.4)
     self.assertTrue(res[2]['stations'] == ['UH3', 'UH2', 'UH1', 'UH4'])
     self.assertTrue(res[2]['coincidence_sum'] == 4)
     # 2. no weighting, station selection
     # => 2 events, no false triggers
     trace_ids = ['BW.UH1..SHZ', 'BW.UH3..SHZ', 'BW.UH4..EHZ']
     # ignore UserWarnings
     with warnings.catch_warnings(record=True):
         warnings.simplefilter('ignore', UserWarning)
         re = coincidenceTrigger("recstalta", 3.5, 1, st.copy(), 3,
                                  trace_ids=trace_ids, sta=0.5, lta=10)
         self.assertTrue(len(re) == 2)
         self.assertTrue(re[0]['time'] > UTCDateTime("2010-05-27T16:24:31"))
         self.assertTrue(re[0]['time'] < UTCDateTime("2010-05-27T16:24:35"))
         self.assertTrue(4.2 < re[0]['duration'] < 4.8)
         self.assertTrue(re[0]['stations'] == ['UH3', 'UH1', 'UH4'])
         self.assertTrue(re[0]['coincidence_sum'] == 3)
         self.assertTrue(re[1]['time'] > UTCDateTime("2010-05-27T16:27:27"))
         self.assertTrue(re[1]['time'] < UTCDateTime("2010-05-27T16:27:33"))
         self.assertTrue(4.2 < re[1]['duration'] < 4.4)
         self.assertTrue(re[1]['stations'] == ['UH3', 'UH1', 'UH4'])
         self.assertTrue(re[1]['coincidence_sum'] == 3)
     # 3. weighting, station selection
     # => 3 events, no false triggers
     trace_ids = {'BW.UH1..SHZ': 0.4, 'BW.UH2..SHZ': 0.35,
                  'BW.UH3..SHZ': 0.4, 'BW.UH4..EHZ': 0.25}
     res = coincidenceTrigger("recstalta", 3.5, 1, st.copy(), 1.0,
                              trace_ids=trace_ids, sta=0.5, lta=10)
     self.assertTrue(len(res) == 3)
     self.assertTrue(res[0]['time'] > UTCDateTime("2010-05-27T16:24:31"))
     self.assertTrue(res[0]['time'] < UTCDateTime("2010-05-27T16:24:35"))
     self.assertTrue(4.2 < res[0]['duration'] < 4.8)
     self.assertTrue(res[0]['stations'] == ['UH3', 'UH2', 'UH1', 'UH4'])
     self.assertTrue(res[0]['coincidence_sum'] == 1.4)
     self.assertTrue(res[1]['time'] > UTCDateTime("2010-05-27T16:26:59"))
     self.assertTrue(res[1]['time'] < UTCDateTime("2010-05-27T16:27:03"))
     self.assertTrue(3.2 < res[1]['duration'] < 3.7)
     self.assertTrue(res[1]['stations'] == ['UH2', 'UH3', 'UH1'])
     self.assertTrue(res[1]['coincidence_sum'] == 1.15)
     self.assertTrue(res[2]['time'] > UTCDateTime("2010-05-27T16:27:27"))
     self.assertTrue(res[2]['time'] < UTCDateTime("2010-05-27T16:27:33"))
     self.assertTrue(4.2 < res[2]['duration'] < 4.4)
     self.assertTrue(res[2]['stations'] == ['UH3', 'UH2', 'UH1', 'UH4'])
     self.assertTrue(res[2]['coincidence_sum'] == 1.4)
     # 4. weighting, station selection, max_len
     # => 2 events, no false triggers, small event does not overlap anymore
     trace_ids = {'BW.UH1..SHZ': 0.6, 'BW.UH2..SHZ': 0.6}
     # ignore UserWarnings
     with warnings.catch_warnings(record=True):
         warnings.simplefilter('ignore', UserWarning)
         re = coincidenceTrigger("recstalta", 3.5, 1, st.copy(), 1.2,
                                  trace_ids=trace_ids,
                                  max_trigger_length=0.13, sta=0.5, lta=10)
         self.assertTrue(len(re) == 2)
         self.assertTrue(re[0]['time'] > UTCDateTime("2010-05-27T16:24:31"))
         self.assertTrue(re[0]['time'] < UTCDateTime("2010-05-27T16:24:35"))
         self.assertTrue(0.2 < re[0]['duration'] < 0.3)
         self.assertTrue(re[0]['stations'] == ['UH2', 'UH1'])
         self.assertTrue(re[0]['coincidence_sum'] == 1.2)
         self.assertTrue(re[1]['time'] > UTCDateTime("2010-05-27T16:27:27"))
         self.assertTrue(re[1]['time'] < UTCDateTime("2010-05-27T16:27:33"))
         self.assertTrue(0.18 < re[1]['duration'] < 0.2)
         self.assertTrue(re[1]['stations'] == ['UH2', 'UH1'])
         self.assertTrue(re[1]['coincidence_sum'] == 1.2)
     # 5. station selection, extremely sensitive settings
     # => 4 events, 1 false triggers
     res = coincidenceTrigger("recstalta", 2.5, 1, st.copy(), 2,
                              trace_ids=['BW.UH1..SHZ', 'BW.UH3..SHZ'],
                              sta=0.3, lta=5)
     self.assertTrue(len(res) == 5)
     self.assertTrue(res[3]['time'] > UTCDateTime("2010-05-27T16:27:01"))
     self.assertTrue(res[3]['time'] < UTCDateTime("2010-05-27T16:27:02"))
     self.assertTrue(1.5 < res[3]['duration'] < 1.7)
     self.assertTrue(res[3]['stations'] == ['UH3', 'UH1'])
     self.assertTrue(res[3]['coincidence_sum'] == 2.0)
     # 6. same as 5, gappy stream
     # => same as 5 (almost, duration of 1 event changes by 0.02s)
     st2 = st.copy()
     tr1 = st2.pop(0)
     t1 = tr1.stats.starttime
     t2 = tr1.stats.endtime
     td = t2 - t1
     tr1a = tr1.slice(starttime=t1, endtime=t1 + 0.45 * td)
     tr1b = tr1.slice(starttime=t1 + 0.6 * td, endtime=t1 + 0.94 * td)
     st2.insert(1, tr1a)
     st2.insert(3, tr1b)
     res = coincidenceTrigger("recstalta", 2.5, 1, st2, 2,
                              trace_ids=['BW.UH1..SHZ', 'BW.UH3..SHZ'],
                              sta=0.3, lta=5)
     self.assertTrue(len(res) == 5)
     self.assertTrue(res[3]['time'] > UTCDateTime("2010-05-27T16:27:01"))
     self.assertTrue(res[3]['time'] < UTCDateTime("2010-05-27T16:27:02"))
     self.assertTrue(1.5 < res[3]['duration'] < 1.7)
     self.assertTrue(res[3]['stations'] == ['UH3', 'UH1'])
     self.assertTrue(res[3]['coincidence_sum'] == 2.0)
     # 7. same as 3 but modify input trace ids and check output of trace_ids
     # and other additional information with ``details=True``
     st2 = st.copy()
     st2[0].stats.network = "XX"
     st2[1].stats.location = "99"
     st2[1].stats.network = ""
     st2[1].stats.location = "99"
     st2[1].stats.channel = ""
     st2[2].stats.channel = "EHN"
     st2[3].stats.network = ""
     st2[3].stats.channel = ""
     st2[3].stats.station = ""
     trace_ids = {'XX.UH1..SHZ': 0.4, '.UH2.99.': 0.35,
                  'BW.UH3..EHN': 0.4, '...': 0.25}
     res = coincidenceTrigger("recstalta", 3.5, 1, st2, 1.0,
                              trace_ids=trace_ids, details=True,
                              sta=0.5, lta=10)
     self.assertTrue(len(res) == 3)
     self.assertTrue(res[0]['time'] > UTCDateTime("2010-05-27T16:24:31"))
     self.assertTrue(res[0]['time'] < UTCDateTime("2010-05-27T16:24:35"))
     self.assertTrue(4.2 < res[0]['duration'] < 4.8)
     self.assertTrue(res[0]['stations'] == ['UH3', 'UH2', 'UH1', ''])
     self.assertTrue(res[0]['trace_ids'][0] == st2[2].id)
     self.assertTrue(res[0]['trace_ids'][1] == st2[1].id)
     self.assertTrue(res[0]['trace_ids'][2] == st2[0].id)
     self.assertTrue(res[0]['trace_ids'][3] == st2[3].id)
     self.assertTrue(res[0]['coincidence_sum'] == 1.4)
     self.assertTrue(res[1]['time'] > UTCDateTime("2010-05-27T16:26:59"))
     self.assertTrue(res[1]['time'] < UTCDateTime("2010-05-27T16:27:03"))
     self.assertTrue(3.2 < res[1]['duration'] < 3.7)
     self.assertTrue(res[1]['stations'] == ['UH2', 'UH3', 'UH1'])
     self.assertTrue(res[1]['trace_ids'][0] == st2[1].id)
     self.assertTrue(res[1]['trace_ids'][1] == st2[2].id)
     self.assertTrue(res[1]['trace_ids'][2] == st2[0].id)
     self.assertTrue(res[1]['coincidence_sum'] == 1.15)
     self.assertTrue(res[2]['time'] > UTCDateTime("2010-05-27T16:27:27"))
     self.assertTrue(res[2]['time'] < UTCDateTime("2010-05-27T16:27:33"))
     self.assertTrue(4.2 < res[2]['duration'] < 4.4)
     self.assertTrue(res[2]['stations'] == ['UH3', 'UH2', 'UH1', ''])
     self.assertTrue(res[2]['trace_ids'][0] == st2[2].id)
     self.assertTrue(res[2]['trace_ids'][1] == st2[1].id)
     self.assertTrue(res[2]['trace_ids'][2] == st2[0].id)
     self.assertTrue(res[2]['trace_ids'][3] == st2[3].id)
     self.assertTrue(res[2]['coincidence_sum'] == 1.4)
     expected_keys = ['cft_peak_wmean', 'cft_std_wmean', 'cft_peaks',
                      'cft_stds']
     expected_types = [float, float, list, list]
     for item in res:
         for key, _type in zip(expected_keys, expected_types):
             self.assertTrue(key in item)
             self.assertTrue(isinstance(item[key], _type))
     # check some of the detailed info
     ev = res[-1]
     self.assertAlmostEquals(ev['cft_peak_wmean'], 18.097582068353855)
     self.assertAlmostEquals(ev['cft_std_wmean'], 4.7972436395074087)
     self.assertAlmostEquals(ev['cft_peaks'][0], 18.973097608513633)
     self.assertAlmostEquals(ev['cft_peaks'][1], 16.852175794415011)
     self.assertAlmostEquals(ev['cft_peaks'][2], 18.64005853900883)
     self.assertAlmostEquals(ev['cft_peaks'][3], 17.572363634564621)
     self.assertAlmostEquals(ev['cft_stds'][0], 4.8811165222946951)
     self.assertAlmostEquals(ev['cft_stds'][1], 4.4446373508521804)
     self.assertAlmostEquals(ev['cft_stds'][2], 5.3499401252675964)
     self.assertAlmostEquals(ev['cft_stds'][3], 4.2723814539487703)
Example #26
0
    summary += exceptions
summary.append("#" * 79)

trig = []
mutt = []
if st:
    # preprocessing, backup original data for plotting at end
    st.merge(0)
    st.detrend("linear")
    for tr in st:
        tr.data = tr.data * cosTaper(len(tr), 0.01)
    #st.simulate(paz_remove="self", paz_simulate=cornFreq2Paz(1.0), remove_sensitivity=False)
    st.sort()
    st.filter("bandpass", freqmin=PAR.LOW, freqmax=PAR.HIGH, corners=1, zerophase=True)
    st.trim(T1, T2)
    st_trigger = st.copy()
    st.normalize(global_max=False)
    # do the triggering
    trig = coincidenceTrigger("recstalta", PAR.ON, PAR.OFF, st_trigger,
            thr_coincidence_sum=PAR.MIN_STATIONS,
            max_trigger_length=PAR.MAXLEN, trigger_off_extension=PAR.ALLOWANCE,
            details=True, sta=PAR.STA, lta=PAR.LTA)

    for t in trig:
        info = "%s %ss %s %s" % (t['time'].strftime("%Y-%m-%dT%H:%M:%S"), ("%.1f" % t['duration']).rjust(4), ("%i" % t['cft_peak_wmean']).rjust(3), "-".join(t['stations']))
        summary.append(info)
        tmp = st.slice(t['time'] - 1, t['time'] + t['duration'])
        outfilename = "%s/%s_%.1f_%i_%s-%s_%s.png" % (PLOTDIR, t['time'].strftime("%Y-%m-%dT%H:%M:%S"), t['duration'], t['cft_peak_wmean'], len(t['stations']), num_stations, "-".join(t['stations']))
        tmp.plot(outfile=outfilename)
        mutt += ("-a", outfilename)
Example #27
0
if debug:
    print(files)

# Make a stream object to hold data
st = Stream()
for curfile in files:
    if debug:
        print('Here is our current file: ' + curfile)
    st += read(curfile, starttime=stime, endtime=etime)
st.merge()
if debug:
    print(st)
    st.plot()

# Here we can do a 10 volt test
st2 = st.copy()
nstime = UTCDateTime('2017-017T22:19:36.0')
netime = nstime + 10.
st2.trim(starttime=nstime, endtime=netime)
# st2 Now has data for our first 10 V test
# Now we convert st2 into Volts

# Make two empty lists to save our results
mminus = []
sminus = []

# This is the first voltage
for tr in st2:
    tr.data.astype(np.float64)
    # Here we are converting from counts to Volts
    tr.data = tr.data * (40. / (2.**26))