<SYSTEM_TASK:>
Solve the following problem using Python, implementing the functions described below, one line at a time
<END_TASK>
<USER_TASK:>
Description:
 def cluster(template_list, show=True, corr_thresh=0.3, allow_shift=False, shift_len=0, save_corrmat=False, cores='all', debug=1):
 """ Cluster template waveforms based on average correlations. Function to take a set of templates and cluster them, will return groups as lists of streams. Clustering is done by computing the cross-channel correlation sum of each stream in stream_list with every other stream in the list. :mod:`scipy.cluster.hierarchy` functions are then used to compute the complete distance matrix, where distance is 1 minus the normalised cross-correlation sum such that larger distances are less similar events. Groups are then created by clustering the distance matrix at distances less than 1 - corr_thresh. Will compute the distance matrix in parallel, using all available cores :type template_list: list :param template_list: List of tuples of the template (:class:`obspy.core.stream.Stream`) and the template id to compute clustering for :type show: bool :param show: plot linkage on screen if True, defaults to True :type corr_thresh: float :param corr_thresh: Cross-channel correlation threshold for grouping :type allow_shift: bool :param allow_shift: Whether to allow the templates to shift when correlating :type shift_len: float :param shift_len: How many seconds to allow the templates to shift :type save_corrmat: bool :param save_corrmat: If True will save the distance matrix to dist_mat.npy in the local directory. :type cores: int :param cores: number of cores to use when computing the distance matrix, defaults to 'all' which will work out how many cpus are available and hog them. :type debug: int :param debug: Level of debugging from 1-5, higher is more output, currently only level 1 implemented. :returns: List of groups. Each group is a list of :class:`obspy.core.stream.Stream` making up that group. """

    if cores == 'all':
        num_cores = cpu_count()
    else:
        num_cores = cores
    # Extract only the Streams from stream_list
    stream_list = [x[0] for x in template_list]
    # Compute the distance matrix
    if debug >= 1:
        print('Computing the distance matrix using %i cores' % num_cores)
    dist_mat = distance_matrix(stream_list, allow_shift, shift_len,
                               cores=num_cores)
    if save_corrmat:
        np.save('dist_mat.npy', dist_mat)
        if debug >= 1:
            print('Saved the distance matrix as dist_mat.npy')
    dist_vec = squareform(dist_mat)
    if debug >= 1:
        print('Computing linkage')
    Z = linkage(dist_vec)
    if show:
        if debug >= 1:
            print('Plotting the dendrogram')
        dendrogram(Z, color_threshold=1 - corr_thresh,
                   distance_sort='ascending')
        plt.show()
    # Get the indices of the groups
    if debug >= 1:
        print('Clustering')
    indices = fcluster(Z, t=1 - corr_thresh, criterion='distance')
    # Indices start at 1...
    group_ids = list(set(indices))  # Unique list of group ids
    if debug >= 1:
        msg = ' '.join(['Found', str(len(group_ids)), 'groups'])
        print(msg)
    # Convert to tuple of (group id, stream id)
    indices = [(indices[i], i) for i in range(len(indices))]
    # Sort by group id
    indices.sort(key=lambda tup: tup[0])
    groups = []
    if debug >= 1:
        print('Extracting and grouping')
    for group_id in group_ids:
        group = []
        for ind in indices:
            if ind[0] == group_id:
                group.append(template_list[ind[1]])
            elif ind[0] > group_id:
                # Because we have sorted by group id, when the index is greater
                # than the group_id we can break the inner loop.
                # Patch applied by CJC 05/11/2015
                groups.append(group)
                break
    # Catch the final group
    groups.append(group)
    return groups