def lag_calc(detections, detect_data, template_names, templates,<EOL>shift_len=<NUM_LIT>, min_cc=<NUM_LIT>, horizontal_chans=['<STR_LIT:E>', '<STR_LIT:N>', '<STR_LIT:1>', '<STR_LIT:2>'],<EOL>vertical_chans=['<STR_LIT>'], cores=<NUM_LIT:1>, interpolate=False,<EOL>plot=False, parallel=True, debug=<NUM_LIT:0>):
if debug > <NUM_LIT:2> and plot:<EOL><INDENT>prep_plot = True<EOL><DEDENT>else:<EOL><INDENT>prep_plot = False<EOL><DEDENT>for tr in detect_data:<EOL><INDENT>if tr.stats.sampling_rate != detect_data[<NUM_LIT:0>].stats.sampling_rate:<EOL><INDENT>raise LagCalcError('<STR_LIT>')<EOL><DEDENT><DEDENT>for template in templates:<EOL><INDENT>for tr in template:<EOL><INDENT>if tr.stats.sampling_rate != detect_data[<NUM_LIT:0>].stats.sampling_rate:<EOL><INDENT>raise LagCalcError('<STR_LIT>')<EOL><DEDENT><DEDENT><DEDENT>delays = []  <EOL>zipped_templates = list(zip(template_names, templates))<EOL>detect_stachans = [(tr.stats.station, tr.stats.channel)<EOL>for tr in detect_data]<EOL>for template in zipped_templates:<EOL><INDENT>temp_delays = {}<EOL>_template = template[<NUM_LIT:1>].copy()<EOL>for tr in _template:<EOL><INDENT>if (tr.stats.station, tr.stats.channel) not in detect_stachans:<EOL><INDENT>_template.remove(tr)<EOL><DEDENT><DEDENT>for tr in _template:<EOL><INDENT>temp_delays.update(<EOL>{tr.stats.station + '<STR_LIT:.>' + tr.stats.channel:<EOL>tr.stats.starttime -<EOL>_template.sort(['<STR_LIT>'])[<NUM_LIT:0>].stats.starttime})<EOL><DEDENT>delays.append((template[<NUM_LIT:0>], temp_delays))<EOL>del _template<EOL><DEDENT>initial_cat = Catalog()<EOL>for template in zipped_templates:<EOL><INDENT>print('<STR_LIT>' % template[<NUM_LIT:0>])<EOL>template_detections = [detection for detection in detections<EOL>if detection.template_name == template[<NUM_LIT:0>]]<EOL>t_delays = [d for d in delays if d[<NUM_LIT:0>] == template[<NUM_LIT:0>]][<NUM_LIT:0>][<NUM_LIT:1>]<EOL>delaylist = list(t_delays.items())<EOL>delaylist.sort(key=lambda tup: tup[<NUM_LIT:1>])<EOL>for detection in template_detections:<EOL><INDENT>detection_stachans = list()<EOL>for stachan in detection.chans:<EOL><INDENT>detection_stachans.append(stachan[<NUM_LIT:0>] + '<STR_LIT:.>' + stachan[<NUM_LIT:1>])<EOL><DEDENT>earlier = <NUM_LIT:0><EOL>for delay in delaylist:<EOL><INDENT>delay_stachan = delay[<NUM_LIT:0>]<EOL>if delay_stachan in detection_stachans:<EOL><INDENT>earlier = delay[<NUM_LIT:1>]<EOL>break<EOL><DEDENT><DEDENT>detection.detect_time = detection.detect_time - earlier<EOL>if earlier > <NUM_LIT:0>:<EOL><INDENT>print('<STR_LIT>' + detection.id + '<STR_LIT>' + str(earlier))<EOL><DEDENT><DEDENT>debug_print(<EOL>'<STR_LIT>' % len(template_detections), <NUM_LIT:2>, debug)<EOL>detect_streams = _prepare_data(<EOL>detect_data=detect_data, detections=template_detections,<EOL>template=template, delays=t_delays, shift_len=shift_len,<EOL>plot=prep_plot)<EOL>detect_streams = [detect_stream[<NUM_LIT:1>] for detect_stream in detect_streams]<EOL>if len(template_detections) > <NUM_LIT:0>:<EOL><INDENT>template_cat = _day_loop(<EOL>detection_streams=detect_streams, template=template[<NUM_LIT:1>],<EOL>min_cc=min_cc, detections=template_detections,<EOL>horizontal_chans=horizontal_chans,<EOL>vertical_chans=vertical_chans, interpolate=interpolate,<EOL>cores=cores, parallel=parallel, debug=debug)<EOL>initial_cat += template_cat<EOL>if plot:<EOL><INDENT>for i, event in enumerate(template_cat):<EOL><INDENT>if len(event.picks) == <NUM_LIT:0>:<EOL><INDENT>continue<EOL><DEDENT>plot_stream = detect_streams[i].copy()<EOL>template_plot = template[<NUM_LIT:1>].copy()<EOL>pick_stachans = [(pick.waveform_id.station_code,<EOL>pick.waveform_id.channel_code)<EOL>for pick in event.picks]<EOL>for tr in plot_stream:<EOL><INDENT>if (tr.stats.station, tr.stats.channel)not in pick_stachans:<EOL><INDENT>plot_stream.remove(tr)<EOL><DEDENT><DEDENT>for tr in template_plot:<EOL><INDENT>if (tr.stats.station, tr.stats.channel)not in pick_stachans:<EOL><INDENT>template_plot.remove(tr)<EOL><DEDENT><DEDENT>plot_repicked(template=template_plot, picks=event.picks,<EOL>det_stream=plot_stream)<EOL><DEDENT><DEDENT><DEDENT><DEDENT>output_cat = Catalog()<EOL>for det in detections:<EOL><INDENT>event = [e for e in initial_cat if str(e.resource_id) == str(det.id)]<EOL>if len(event) == <NUM_LIT:1>:<EOL><INDENT>output_cat.append(event[<NUM_LIT:0>])<EOL><DEDENT>elif len(event) == <NUM_LIT:0>:<EOL><INDENT>print('<STR_LIT>' % det.__str__())<EOL><DEDENT>else:<EOL><INDENT>raise NotImplementedError('<STR_LIT>'<EOL>'<STR_LIT>')<EOL><DEDENT><DEDENT>return output_cat<EOL>
Main lag-calculation function for detections of specific events.

Overseer function to take a list of detection objects, cut the data for
them to lengths of the same length of the template + shift_len on
either side. This will output a :class:`obspy.core.event.Catalog` of
picked events. Pick times are based on the lag-times found at the maximum
correlation, providing that correlation is above the min_cc.

:type detections: list
:param detections:
    List of :class:`eqcorrscan.core.match_filter.Detection` objects.
:type detect_data: obspy.core.stream.Stream
:param detect_data:
    All the data needed to cut from - can be a gappy Stream.
:type template_names: list
:param template_names:
    List of the template names, used to help identify families of events.
    Must be in the same order as templates.
:type templates: list
:param templates:
    List of the templates, templates must be a list of
     :class:`obspy.core.stream.Stream` objects.
:type shift_len: float
:param shift_len:
    Shift length allowed for the pick in seconds, will be plus/minus this
    amount - default=0.2
:type min_cc: float
:param min_cc:
    Minimum cross-correlation value to be considered a pick, default=0.4.
:type horizontal_chans: list
:param horizontal_chans:
    List of channel endings for horizontal-channels, on which S-picks will
    be made.
:type vertical_chans: list
:param vertical_chans:
    List of channel endings for vertical-channels, on which P-picks will
    be made.
:type cores: int
:param cores:
    Number of cores to use in parallel processing, defaults to one.
:type interpolate: bool
:param interpolate:
    Interpolate the correlation function to achieve sub-sample precision.
:type plot: bool
:param plot:
    To generate a plot for every detection or not, defaults to False
:type parallel: bool
:param parallel: Turn parallel processing on or off.
:type debug: int
:param debug: Debug output level, 0-5 with 5 being the most output.


:returns:
    Catalog of events with picks.  No origin information is included.
    These events can then be written out via
    :func:`obspy.core.event.Catalog.write`, or to Nordic Sfiles using
    :func:`eqcorrscan.utils.sfile_util.eventtosfile` and located
    externally.
:rtype: obspy.core.event.Catalog

.. note::
    Picks output in catalog are generated relative to the template
    start-time.  For example, if you generated your template with a
    pre_pick time of 0.2 seconds, you should expect picks generated by
    lag_calc to occur 0.2 seconds before the true phase-pick.  This
    is because we do not currently store template meta-data alongside the
    templates.

.. warning::
    Because of the above note, origin times will be consistently
    shifted by the static pre_pick applied to the templates.

.. warning::
    This routine requires only one template per channel (e.g. you should
    not use templates with a P and S template on a single channel).  If
    this does occur an error will be raised.

.. note::
    S-picks will be made on horizontal channels, and P picks made on
    vertical channels - the default is that horizontal channels end in
    one of: 'E', 'N', '1' or '2', and that vertical channels end in 'Z'.
    The options vertical_chans and horizontal_chans can be changed to suit
    your dataset.

.. note::
    Individual channel cross-correlations are stored as a
    :class:`obspy.core.event.Comment` for each pick, and the summed
    cross-correlation value resulting from these is stored as a
    :class:`obspy.core.event.Comment` in the main
    :class:`obspy.core.event.Event` object.

.. note::
    The order of events is preserved (e.g. detections[n] == output[n]),
    providing picks have been made for that event.  If no picks have
    been made for an event, it will not be included in the output.
    However, as each detection has an ID associated with it, these can
    be mapped to the output resource_id for each Event in the output
    Catalog. e.g.

        detections[n].id == output[m].resource_id

    if the output[m] is for the same event as detections[n].