def multi_event_singlechan(streams, catalog, station, channel,
                           clip=10.0, pre_pick=2.0,
                           freqmin=False, freqmax=False, realign=False,
                           cut=(-3.0, 5.0), PWS=False, **kwargs):
    """
    Plot data from a single channel for multiple events.

    Data will be aligned by their pick-time given in the appropriate picks.
    Requires an individual stream for each event you want to plot,
    events are stored in the :class:`obspy.core.event.Catalog` object, and
    there must be picks present for the streams you wish to plot.  Events will
    be aligned if `realign=True`, in this case the traces will be aligned
    using the window defined by `cut`.

    :type streams: list
    :param streams:
        List of the :class:`obspy.core.stream.Stream` objects to use, can
        contain more traces than you plan on plotting (e.g. from more channels)
        - must be in the same order as events in catalog.
    :type catalog: obspy.core.event.Catalog
    :param catalog: Catalog of events, one for each stream.
    :type station: str
    :param station: Station to plot.
    :type channel: str
    :param channel: Channel to plot.
    :type clip: float
    :param clip: Length in seconds to plot, defaults to 10.0
    :type pre_pick: float
    :param pre_pick: Length in seconds to extract and plot before the pick, \
        defaults to 2.0
    :type freqmin: float
    :param freqmin: Low cut for bandpass in Hz
    :type freqmax: float
    :param freqmax: High cut for bandpass in Hz
    :type realign: bool
    :param realign:
        To compute best alignment based on correlation with the stack or not.
    :type cut: tuple
    :param cut: tuple of start and end times for cut in seconds from the \
        pick, used for alignment.  Will only use this window to align the \
        traces.
    :type PWS: bool
    :param PWS: compute Phase Weighted Stack, if False, will compute linear \
        stack for alignment.

    :returns: Aligned and cut :class:`obspy.core.trace.Trace`
    :rtype: list
    :returns:
        New picks in based on alignment (if alignment is performed, if not
        will return the same as input)
    :rtype: :class:`obspy.core.event.Catalog`
    :returns: Figure object for further editing
    :rtype: :class:`matplotlib.figure.Figure`

    .. rubric:: Example

    >>> from obspy import read, Catalog, read_events
    >>> from obspy.io.nordic.core import readwavename
    >>> from eqcorrscan.utils.plotting import multi_event_singlechan
    >>> import glob
    >>> sfiles = glob.glob('eqcorrscan/tests/test_data/REA/TEST_/*.S??????')
    >>> catalog = Catalog()
    >>> streams = []
    >>> for sfile in sfiles:
    ...     catalog += read_events(sfile)
    ...     wavfile = readwavename(sfile)[0]
    ...     stream_path = 'eqcorrscan/tests/test_data/WAV/TEST_/' + wavfile
    ...     stream = read(stream_path)
    ...     # Annoying coping with seisan 2 letter channels
    ...     for tr in stream:
    ...         tr.stats.channel = tr.stats.channel[0] + tr.stats.channel[-1]
    ...     streams.append(stream)
    >>> multi_event_singlechan(streams=streams, catalog=catalog,
    ...                        station='GCSZ', channel='EZ') # doctest: +SKIP

    .. image:: ../../plots/multi_event_singlechan.png
    """
    import matplotlib.pyplot as plt
    # Work out how many picks we should have...
    short_cat = Catalog()
    short_streams = []
    for i, event in enumerate(catalog):
        event_stachans = [(pick.waveform_id.station_code,
                           pick.waveform_id.channel_code)
                          for pick in event.picks]
        if (station, channel) in event_stachans:
            short_cat.append(event)
            short_streams.append(streams[i])
    if len(short_cat) == 0:
        raise IOError('No picks for ' + station + ' ' + channel)
    traces = []
    al_traces = []
    al_picks = []
    if isinstance(short_streams, Stream):
        short_streams = [short_streams]
    st_list = deepcopy(short_streams)
    print(short_cat)
    for i, event in enumerate(short_cat):
        # Extract the appropriate pick
        _pick = [pick for pick in event.picks if
                 pick.waveform_id.station_code == station and
                 pick.waveform_id.channel_code == channel]
        if len(_pick) == 0:
            print('No pick for channel')
            continue
        else:
            _pick = _pick[0]
        if st_list[i].select(station=station, channel=channel):
            tr = st_list[i].select(station=station, channel=channel)[0]
        else:
            print('No data for ' + _pick.waveform_id.station_code)
            continue
        tr.detrend('linear')
        if freqmin:
            tr.filter('bandpass', freqmin=freqmin, freqmax=freqmax)
        if realign:
            tr_cut = tr.copy()
            tr_cut.trim(_pick.time + cut[0],
                        _pick.time + cut[1],
                        nearest_sample=False)
            if len(tr_cut.data) <= (0.5 * (cut[1] - cut[0]) *
                                    tr_cut.stats.sampling_rate):
                msg = ''.join(['Not enough in the trace for ',
                               tr.stats.station,
                               '.', tr.stats.channel, '\n',
                               'Suggest removing pick from event at time ',
                               str(_pick.time)])
                warnings.warn(msg)
            else:
                al_traces.append(tr_cut)
                al_picks.append(_pick)
        else:
            tr.trim(_pick.time - pre_pick,
                    _pick.time + clip - pre_pick,
                    nearest_sample=False)
        if len(tr.data) == 0:
            msg = ''.join(['No data in the trace for ', tr.stats.station,
                           '.', tr.stats.channel, '\n',
                           'Suggest removing pick from event at time ',
                           str(event.picks[0].time)])
            warnings.warn(msg)
            continue
        traces.append(tr)
    if realign:
        shift_len = int(0.25 * (cut[1] - cut[0]) *
                        al_traces[0].stats.sampling_rate)
        shifts = align_traces(al_traces, shift_len)[0]
        for i in range(len(shifts)):
            print('Shifting by ' + str(shifts[i]) + ' seconds')
            _pick.time -= shifts[i]
            traces[i].trim(al_picks[i].time - pre_pick,
                           al_picks[i].time + clip - pre_pick,
                           nearest_sample=True)
    # We now have a list of traces
    if PWS:
        stack = 'PWS'
    else:
        stack = 'linstack'
    for tr in traces:
        print(tr)
    fig = multi_trace_plot(
        traces=traces, corr=True, stack=stack, show=False, return_figure=True)
    plt.subplots_adjust(hspace=0)
    fig = _finalise_figure(fig=fig, **kwargs)  # pragma: no cover
    return traces, short_cat, fig
def multi_event_singlechan ( streams , catalog , station , channel , clip = 10.0 , pre_pick = 2.0 , freqmin = False , freqmax = False , realign = False , cut = ( - 3.0 , 5.0 ) , PWS = False , ** kwargs ) : import matplotlib . pyplot as plt short_cat = Catalog ( ) short_streams = [ ] for i , event in enumerate ( catalog ) : event_stachans = [ ( pick . waveform_id . station_code , pick . waveform_id . channel_code ) for pick in event . picks ] if ( station , channel ) in event_stachans : short_cat . append ( event ) short_streams . append ( streams [ i ] ) if len ( short_cat ) == 0 : raise IOError ( 'No picks for ' + station + ' ' + channel ) traces = [ ] al_traces = [ ] al_picks = [ ] if isinstance ( short_streams , Stream ) : short_streams = [ short_streams ] st_list = deepcopy ( short_streams ) print ( short_cat ) for i , event in enumerate ( short_cat ) : _pick = [ pick for pick in event . picks if pick . waveform_id . station_code == station and pick . waveform_id . channel_code == channel ] if len ( _pick ) == 0 : print ( 'No pick for channel' ) continue else : _pick = _pick [ 0 ] if st_list [ i ] . select ( station = station , channel = channel ) : tr = st_list [ i ] . select ( station = station , channel = channel ) [ 0 ] else : print ( 'No data for ' + _pick . waveform_id . station_code ) continue tr . detrend ( 'linear' ) if freqmin : tr . filter ( 'bandpass' , freqmin = freqmin , freqmax = freqmax ) if realign : tr_cut = tr . copy ( ) tr_cut . trim ( _pick . time + cut [ 0 ] , _pick . time + cut [ 1 ] , nearest_sample = False ) if len ( tr_cut . data ) <= ( 0.5 * ( cut [ 1 ] - cut [ 0 ] ) * tr_cut . stats . sampling_rate ) : msg = '' . join ( [ 'Not enough in the trace for ' , tr . stats . station , '.' , tr . stats . channel , '\n' , 'Suggest removing pick from event at time ' , str ( _pick . time ) ] ) warnings . warn ( msg ) else : al_traces . append ( tr_cut ) al_picks . append ( _pick ) else : tr . trim ( _pick . time - pre_pick , _pick . time + clip - pre_pick , nearest_sample = False ) if len ( tr . data ) == 0 : msg = '' . join ( [ 'No data in the trace for ' , tr . stats . station , '.' , tr . stats . channel , '\n' , 'Suggest removing pick from event at time ' , str ( event . picks [ 0 ] . time ) ] ) warnings . warn ( msg ) continue traces . append ( tr ) if realign : shift_len = int ( 0.25 * ( cut [ 1 ] - cut [ 0 ] ) * al_traces [ 0 ] . stats . sampling_rate ) shifts = align_traces ( al_traces , shift_len ) [ 0 ] for i in range ( len ( shifts ) ) : print ( 'Shifting by ' + str ( shifts [ i ] ) + ' seconds' ) _pick . time -= shifts [ i ] traces [ i ] . trim ( al_picks [ i ] . time - pre_pick , al_picks [ i ] . time + clip - pre_pick , nearest_sample = True ) if PWS : stack = 'PWS' else : stack = 'linstack' for tr in traces : print ( tr ) fig = multi_trace_plot ( traces = traces , corr = True , stack = stack , show = False , return_figure = True ) plt . subplots_adjust ( hspace = 0 ) fig = _finalise_figure ( fig = fig , ** kwargs ) return traces , short_cat , fig
Plot data from a single channel for multiple events.

    Data will be aligned by their pick-time given in the appropriate picks.
    Requires an individual stream for each event you want to plot,
    events are stored in the :class:`obspy.core.event.Catalog` object, and
    there must be picks present for the streams you wish to plot.  Events will
    be aligned if `realign=True`, in this case the traces will be aligned
    using the window defined by `cut`.

    :type streams: list
    :param streams:
        List of the :class:`obspy.core.stream.Stream` objects to use, can
        contain more traces than you plan on plotting (e.g. from more channels)
        - must be in the same order as events in catalog.
    :type catalog: obspy.core.event.Catalog
    :param catalog: Catalog of events, one for each stream.
    :type station: str
    :param station: Station to plot.
    :type channel: str
    :param channel: Channel to plot.
    :type clip: float
    :param clip: Length in seconds to plot, defaults to 10.0
    :type pre_pick: float
    :param pre_pick: Length in seconds to extract and plot before the pick, \
        defaults to 2.0
    :type freqmin: float
    :param freqmin: Low cut for bandpass in Hz
    :type freqmax: float
    :param freqmax: High cut for bandpass in Hz
    :type realign: bool
    :param realign:
        To compute best alignment based on correlation with the stack or not.
    :type cut: tuple
    :param cut: tuple of start and end times for cut in seconds from the \
        pick, used for alignment.  Will only use this window to align the \
        traces.
    :type PWS: bool
    :param PWS: compute Phase Weighted Stack, if False, will compute linear \
        stack for alignment.

    :returns: Aligned and cut :class:`obspy.core.trace.Trace`
    :rtype: list
    :returns:
        New picks in based on alignment (if alignment is performed, if not
        will return the same as input)
    :rtype: :class:`obspy.core.event.Catalog`
    :returns: Figure object for further editing
    :rtype: :class:`matplotlib.figure.Figure`

    .. rubric:: Example

    >>> from obspy import read, Catalog, read_events
    >>> from obspy.io.nordic.core import readwavename
    >>> from eqcorrscan.utils.plotting import multi_event_singlechan
    >>> import glob
    >>> sfiles = glob.glob('eqcorrscan/tests/test_data/REA/TEST_/*.S??????')
    >>> catalog = Catalog()
    >>> streams = []
    >>> for sfile in sfiles:
    ...     catalog += read_events(sfile)
    ...     wavfile = readwavename(sfile)[0]
    ...     stream_path = 'eqcorrscan/tests/test_data/WAV/TEST_/' + wavfile
    ...     stream = read(stream_path)
    ...     # Annoying coping with seisan 2 letter channels
    ...     for tr in stream:
    ...         tr.stats.channel = tr.stats.channel[0] + tr.stats.channel[-1]
    ...     streams.append(stream)
    >>> multi_event_singlechan(streams=streams, catalog=catalog,
    ...                        station='GCSZ', channel='EZ') # doctest: +SKIP

    .. image:: ../../plots/multi_event_singlechan.png