def extract_contact_responses_to_each_whisker(
    coef_wscale_df,
    big_waveform_info_df=None,
    coef_metric='scaled_coef_single',
    include_task=('discrimination',),
    floor_response_at_zero=False,
    drop_always_suppressed=False,
    drop_C0=True,
    drop_neurons_missing_whisker=True,
    combine_off_target=True,
    ):
    """Extract contact responses of each whisker
    
    big_waveform_info_df : DataFrame or None
        Joins on metadata, or does nothing if None
    
    coef_metric : which coef_metric to use
        Using the "scaled" metrics puts the results in a per-contact basis
        Probably better to use _single rather than _best, because otherwise
        different regularization by neuron contaminates the results
        coef_best_z is used for significance
    
    drop_neurons_missing_whisker : bool
        If True, drop neurons missing a coefficient for any of the whiskers
        C1-C3 (or C0-C3 if drop_C0 is False)
    
    combine_off_target : bool
        If True, replace all strings in 'recording_location' that are not
        in the C-row with the string 'off'
    """
    ## Get data
    # Slice contact_binarized
    data = coef_wscale_df.xs('contact_binarized', level='metric').copy()
    
    # Slice coef_metric
    data = data[coef_metric]

    # Floor negative responses to zero
    if floor_response_at_zero:
        data[data < 0] = 0
    
    # Unstack label
    data = data.unstack('label')

    if drop_C0:
        # Drop C0 which is often missing
        data = data.drop('C0', 1)
    
    # Drop any neuron missing C1-C3
    if drop_neurons_missing_whisker:
        data = data.dropna()
    
    # Include task
    # Using list prevents droplevel
    data = data.loc[list(include_task)]

    # Drop neurons that are suppressed by every whisker
    if drop_always_suppressed:
        data = data[(data > 0).any(1)]


    ## Join on metadata
    if big_waveform_info_df is not None:
        data = data.join(
            big_waveform_info_df[['NS', 'layer', 'stratum', 'Z_corrected', 
                'recording_location', 'crow_recording_location']], 
            on=['session', 'neuron'])

        # Replace all off-target locations with the string 'off'
        if combine_off_target:
            off_mask = (
                data['recording_location'] != data['crow_recording_location']
                )
            data.loc[off_mask, 'recording_location'] = 'off'

    return data