def write_catalog(event_list, max_sep=8, min_link=8, debug=0):
    """
    Generate a dt.ct for hypoDD for a series of events.

    Takes input event list from
    :func:`eqcorrscan.utils.catalog_to_dd.write_event` as a list of tuples of
    event id and sfile.  It will read the pick information from the seisan
    formated s-file using the sfile_util utilities.

    :type event_list: list
    :param event_list: List of tuples of event_id (int) and sfile (String)
    :type max_sep: float
    :param max_sep: Maximum separation between event pairs in km
    :type min_link: int
    :param min_link:
        Minimum links for an event to be paired, e.g. minimum number of picks
        from the same station and channel (and phase) that are shared between
        two events for them to be paired.
    :type debug: int
    :param debug: Debug output level.

    :returns: list of stations that have been used in this catalog

    .. note::
        We have not yet implemented a method for taking unassociated event
        objects and wavefiles.  As such if you have events with associated
        wavefiles you are advised to generate Sfiles for each event using
        the :mod:`eqcorrscan.utils.sfile_util` module prior to this step.
    """
    # Cope with possibly being passed a zip in python 3.x
    event_list = list(event_list)
    f = open('dt.ct', 'w')
    f2 = open('dt.ct2', 'w')
    fphase = open('phase.dat', 'w')
    stations = []
    evcount = 0
    for i, master in enumerate(event_list):
        master_sfile = master[1]
        master_event_id = master[0]
        master_event = read_nordic(master_sfile)[0]
        master_ori_time = master_event.origins[0].time
        master_location = (master_event.origins[0].latitude,
                           master_event.origins[0].longitude,
                           master_event.origins[0].depth / 1000)
        if len(master_event.magnitudes) > 0:
            master_magnitude = master_event.magnitudes[0].mag or ' '
        else:
            master_magnitude = ' '
        header = '# ' + \
            master_ori_time.strftime('%Y  %m  %d  %H  %M  %S.%f') +\
            ' ' + str(master_location[0]).ljust(8) + ' ' +\
            str(master_location[1]).ljust(8) + ' ' +\
            str(master_location[2]).ljust(4) + ' ' +\
            str(master_magnitude).ljust(4) + ' 0.0 0.0 0.0' +\
            str(master_event_id).rjust(4)
        fphase.write(header + '\n')
        for pick in master_event.picks:
            if not hasattr(pick, 'phase_hint') or len(pick.phase_hint) == 0:
                warnings.warn('No phase-hint for pick:')
                print(pick)
                continue
            if pick.phase_hint[0].upper() in ['P', 'S']:
                weight = [arrival.time_weight
                          for arrival in master_event.origins[0].arrivals
                          if arrival.pick_id == pick.resource_id][0]
                # Convert seisan weight to hypoDD 0-1 weights
                if weight == 0:
                    weight = 1.0
                elif weight == 9:
                    weight = 0.0
                else:
                    weight = 1 - weight / 4.0
                fphase.write(pick.waveform_id.station_code + '  ' +
                             _cc_round(pick.time -
                                       master_ori_time, 3).rjust(6) +
                             '   ' + str(weight).ljust(5) +
                             pick.phase_hint + '\n')
        for j in range(i + 1, len(event_list)):
            # Use this tactic to only output unique event pairings
            slave_sfile = event_list[j][1]
            slave_event_id = event_list[j][0]
            # Write out the header line
            event_text = '#' + str(master_event_id).rjust(10) +\
                str(slave_event_id).rjust(10) + '\n'
            event_text2 = '#' + str(master_event_id).rjust(10) +\
                str(slave_event_id).rjust(10) + '\n'
            slave_event = read_nordic(slave_sfile)[0]
            slave_ori_time = slave_event.origins[0].time
            slave_location = (slave_event.origins[0].latitude,
                              slave_event.origins[0].longitude,
                              slave_event.origins[0].depth / 1000)
            if dist_calc(master_location, slave_location) > max_sep:
                continue
            links = 0  # Count the number of linkages
            for pick in master_event.picks:
                if not hasattr(pick, 'phase_hint') or\
                                len(pick.phase_hint) == 0:
                    continue
                if pick.phase_hint[0].upper() not in ['P', 'S']:
                    continue
                    # Only use P and S picks, not amplitude or 'other'
                # Added by Carolin
                slave_matches = [p for p in slave_event.picks
                                 if hasattr(p, 'phase_hint') and
                                 p.phase_hint == pick.phase_hint and
                                 p.waveform_id.station_code.upper() ==
                                 pick.waveform_id.station_code.upper()]
                # Loop through the matches
                for slave_pick in slave_matches:
                    links += 1
                    master_weight = [arrival.time_weight
                                     for arrival in master_event.
                                     origins[0].arrivals
                                     if arrival.pick_id == pick.resource_id][0]
                    slave_weight = [arrival.time_weight
                                    for arrival in slave_event.
                                    origins[0].arrivals
                                    if arrival.pick_id ==
                                    slave_pick.resource_id][0]
                    master_weight = str(int(master_weight))
                    slave_weight = str(int(slave_weight))
                    event_text += pick.waveform_id.station_code.ljust(5) +\
                        _cc_round(pick.time - master_ori_time, 3).rjust(11) +\
                        _cc_round(slave_pick.time -
                                  slave_ori_time, 3).rjust(8) +\
                        _av_weight(master_weight, slave_weight).rjust(7) +\
                        ' ' + pick.phase_hint + '\n'
                    # Added by Carolin
                    event_text2 += pick.waveform_id.station_code.ljust(5) +\
                        _cc_round(pick.time - master_ori_time, 3).rjust(11) +\
                        _cc_round(slave_pick.time -
                                  slave_ori_time, 3).rjust(8) +\
                        _av_weight(master_weight, slave_weight).rjust(7) +\
                        ' ' + pick.phase_hint + '\n'
                    stations.append(pick.waveform_id.station_code)
            if links >= min_link:
                f.write(event_text)
                f2.write(event_text2)
                evcount += 1
    print('You have ' + str(evcount) + ' links')
    # f.write('\n')
    f.close()
    f2.close()
    fphase.close()
    return list(set(stations))
Generate a dt.ct for hypoDD for a series of events.

    Takes input event list from
    :func:`eqcorrscan.utils.catalog_to_dd.write_event` as a list of tuples of
    event id and sfile.  It will read the pick information from the seisan
    formated s-file using the sfile_util utilities.

    :type event_list: list
    :param event_list: List of tuples of event_id (int) and sfile (String)
    :type max_sep: float
    :param max_sep: Maximum separation between event pairs in km
    :type min_link: int
    :param min_link:
        Minimum links for an event to be paired, e.g. minimum number of picks
        from the same station and channel (and phase) that are shared between
        two events for them to be paired.
    :type debug: int
    :param debug: Debug output level.

    :returns: list of stations that have been used in this catalog

    .. note::
        We have not yet implemented a method for taking unassociated event
        objects and wavefiles.  As such if you have events with associated
        wavefiles you are advised to generate Sfiles for each event using
        the :mod:`eqcorrscan.utils.sfile_util` module prior to this step.