Plot the effective attenuation _(i.e., gain less than 1)_ of the control
    board measurements of high-voltage AC input according to:

     - AC signal frequency.
     - feedback resistor used _(varies based on amplitude of AC signal)_.

    Each high-voltage feedback resistor (unintentionally) forms a low-pass
    filter, resulting in attenuation of the voltage measured on the control
    board.  The plot generated by this function plots each of the following
    trends for each feedback resistor:

     - Oscilloscope measurements.
     - Previous model of attenuation.
     - Newly fitted model of attenuation, based on oscilloscope readings.

def plot_feedback_params(hw_major_version, max_resistor_readings,
                         feedback_params, axis=None):
    '''
    Plot the effective attenuation _(i.e., gain less than 1)_ of the control
    board measurements of high-voltage AC input according to:

     - AC signal frequency.
     - feedback resistor used _(varies based on amplitude of AC signal)_.

    Each high-voltage feedback resistor (unintentionally) forms a low-pass
    filter, resulting in attenuation of the voltage measured on the control
    board.  The plot generated by this function plots each of the following
    trends for each feedback resistor:

     - Oscilloscope measurements.
     - Previous model of attenuation.
     - Newly fitted model of attenuation, based on oscilloscope readings.
    '''
    R1 = 10e6

    # Since the feedback circuit changed in version 2 of the control board, we
    # use the transfer function that corresponds to the current control board
    # version that the fitted attenuation model is based on.
    if axis is None:
        fig = plt.figure()
        axis = fig.add_subplot(111)

    markers = MarkerStyle.filled_markers

    def plot_resistor_params(args):
        resistor_index, x = args

        try:
            color = axis._get_lines.color_cycle.next()
        except: # make compatible with matplotlib v1.5
            color = axis._get_lines.prop_cycler.next()['color']

        F = feedback_params.loc[resistor_index]
        # Broadcast values in case sympy function simplifies to scalar value.
        values = np.empty_like(x['frequency'])
        values[:] = compute_from_transfer_function(hw_major_version, 'V2',
                                                   V1=1., R1=R1,
                                                   R2=F['original R'],
                                                   C2=F['original C'],
                                                   f=x['frequency'])
        axis.loglog(x['frequency'], values, color=color, linestyle='--',
                    label='R$_{%d}$ (previous fit)' % resistor_index)

        values[:] = compute_from_transfer_function(hw_major_version, 'V2',
                                                   V1=1., R1=R1,
                                                   R2=F['fitted R'],
                                                   C2=F['fitted C'],
                                                   f=x['frequency'])
        axis.loglog(x['frequency'], values, color=color, linestyle='-',
                    alpha=0.6, label='R$_{%d}$ (new fit)' % resistor_index)
        attenuation = x['board measured V'] / x['oscope measured V']
        axis.plot(x['frequency'], attenuation, color='none',
                  marker=markers[resistor_index % len(markers)],
                  label='R$_{%d}$ (scope measured)' % resistor_index,
                  linestyle='none', markeredgecolor=color, markeredgewidth=2,
                  markersize=8)
        return 0

    map(plot_resistor_params, max_resistor_readings.groupby('resistor index'))
    legend = axis.legend(ncol=3)
    legend.draw_frame(False)
    axis.set_xlabel('Frequency (Hz)')
    axis.set_ylabel(r'$\frac{V_{BOARD}}'
                    r'{V_{SCOPE}}$', fontsize=25)