def calo_time_wins(df, thresh = 5):
    """ Generate a list of time windows for relevant off-trigger incidents (CaloEvents).
    
    Parameters:
    ----------
        df : a pandas DataFrame of a single run. Preferable after cleaning noisy channels.
        threshold : integer threshold for minimum number of hits in the calorimeter per clock-cycle.
    
    Return:
    ------
        time_wins: a dictionary of time windows per event. Keys are the event ids.
        
    Note: the time windows are specified by the first clock-cycle of the window,
          which is the biggest dt value.
    
    """
    
    # Create a list of stable events
    stable_events = df.groupby("eventId").count().xpos < 1000
    stable_events = stable_events[stable_events].index.tolist()
    df_stable = df[df.eventId.isin(stable_events)]
    
    # Create hit counts per clock-cycle
    dt_dist = df_stable.groupby(['eventId', 'dt']).count()
    dt_dist.reset_index(inplace=True)

    time_wins = {}
    
    # Add lists of relevant time windows event-by-event
    for i in stable_events:
        dt_list = dt_dist.dt[(dt_dist.eventId == i) & (dt_dist.xpos >= thresh)].tolist()
        for t in dt_list:
            
            # Remove possible gitter of +/- clock-cycle or long signals double counts
            if (t+1 in dt_list) or (t+6 in dt_list):
                dt_list.remove(t)

        time_wins[i] = dt_list.copy()

    return time_wins