예제 #1
0
def test_fit_rc_c_1nF(c_data_1nF):
    actual_res, actual_cap, _ = \
         fit_impedance(c_data_1nF, model='rc',
                 model_config='parallel', p0=(1, 1))
    desired_res, desired_cap = [1e13, 1e-9 / (2 * np.pi)]

    assert_allclose(actual_cap, desired_cap, atol=1e-22)
예제 #2
0
def test_fit_rc_series_complex(rc_data_complex):
    actual_res, actual_cap, impedance_func = \
         fit_impedance(rc_data_complex, model='rc',
                 model_config='series', p0=(1, 1))
    desired_res, desired_cap = 1000, 1e-9

    assert_allclose(actual_cap, desired_cap, rtol=1e-6)
    assert_allclose(actual_res, desired_res, rtol=1e-6)
예제 #3
0
def test_fit_rc_series(rc_data_series):
    data = rc_data_series['data']
    actual_res, actual_cap, _ = \
         fit_impedance(data, model='rc',
                 model_config='series', p0=(1, 1))
    desired_res, desired_cap = rc_data_series['params']

    assert_allclose(actual_cap, desired_cap, rtol=1e-5)
    assert_allclose(actual_res, desired_res, rtol=1e-5)
예제 #4
0
def test_fit_rc_r_only(r_data):
    actual_res, actual_cap, _ = \
         fit_impedance(r_data, model='rc',
                 model_config='parallel', p0=(10, 1))
    desired_res, desired_cap = [1, 0]
    actual_params = np.array([actual_res, actual_cap])
    desired_params = np.array([desired_res, desired_cap])

    assert_allclose(actual_params, desired_params, atol=1e-10)
예제 #5
0
def test_fit_rc_parallel(rc_data_parallel):
    data = rc_data_parallel['data']
    actual_res, actual_cap, impedance_func = \
         fit_impedance(data, model='rc',
                 model_config='parallel', p0=(1, 1))
    desired_res, desired_cap = rc_data_parallel['params']
    if abs(np.log10(2 * np.pi * desired_res * desired_cap * 100)) > 5:
        rtol = 1e-1
    else:
        rtol = 1e-4

    assert_allclose(actual_cap, desired_cap, rtol=rtol)
    assert_allclose(actual_res, desired_res, rtol=rtol)
예제 #6
0
def plot_impedance(data,
                   fit=True,
                   model='rc',
                   model_config='series',
                   **kwargs):
    """
    Plots the magnitude / phase of a set of impedance data.

    :param fit: Whether to attempt to fit an impedance model to the data
    :param model: Real/reactive model - options are "rc"
    :param model_config: Model configuration, either "series" or "parallel"
    """
    # The challenge here is that we need to plot two things with the same x axis and different y axes: the magnitude and phase data.
    if data.shape[1] == 2:
        data_complex = True
        z_data = column_from_unit(data, ureg.ohm).to(ureg.ohm).m
        phase_data = np.angle(z_data)
        magnitude_data = np.abs(z_data)
        data_to_plot = pd.DataFrame({
            'Frequency (Hz)': data.iloc[:, 0],
            '|Z| (ohm)': magnitude_data,
            'Phase (deg)': phase_data * 180 / np.pi
        })
    else:
        data_complex = False
        phase_data = column_from_unit(data, ureg.rad).to(ureg.deg).m
        phase_name = cname_from_unit(data, ureg.rad)
        data_to_plot = data.rename(columns={phase_name: 'Phase (deg)'})
        data_to_plot['Phase (deg)'] = phase_data

    if fit:
        _, _, impedance_func = fit_impedance(data)
        # This needs to return a functional form for the impedance vs. frequency in addition to the relevant parameters, as it's not clear
        freq_data = column_from_unit(data, ureg.Hz)
        min_log = np.log10(freq_data.min().to(ureg.Hz).m)
        max_log = np.log10(freq_data.max().to(ureg.Hz).m)
        freq_theory_data = np.logspace(min_log, max_log, 100)
        impedance_theory_data = impedance_func(freq_theory_data)
        mag_theory_data = abs(impedance_theory_data)
        phase_theory_data = np.angle(impedance_theory_data) * 180 / np.pi
        theory_data = pd.DataFrame({
            'Frequency (Hz)': freq_theory_data,
            'Z (ohm)': mag_theory_data,
            'Phase (deg)': phase_theory_data
        })

    else:
        theory_data = None

    theory_to_plot = None
    subplot_kw = {'xscale': 'log', 'yscale': 'log'}

    if theory_data is not None:
        theory_to_plot = theory_data.iloc[:, [0, 1]]

    kwargs.update(subplot_kw=subplot_kw,
                  theory_data=theory_to_plot,
                  theory_name='|Z| (Fit)',
                  plot_type='scatter')
    fig, ax = default_plotter(data_to_plot.iloc[:, [0, 1]], **kwargs)

    if theory_data is not None:
        theory_to_plot = theory_data.iloc[:, [0, -1]]
    kwargs.update(subplot_kw=subplot_kw,
                  fig=fig,
                  ax=ax,
                  theory_data=theory_to_plot,
                  theory_name='Phase (Fit)',
                  plot_type='scatter')
    fig, ax = default_plotter(data_to_plot.iloc[:, [0, -1]], **kwargs)

    prettifyPlot(fig=fig, ax=ax)
    return fig, ax