예제 #1
0
def plot_frequencies_zoom(psd_data, peak_data, image_folder, nbin, df_zoom):
    """

    Args:
        psd_data:
        peak_data:
        image_folder:
        nbin:
        df_zoom:

    Returns:

    """

    for i in range(len(peak_data)):
        fig = plt.figure()
        mode = peak_data.iloc[i]['mode'][0]
        fo = peak_data.iloc[i]['peak freq']

        f = avrg(psd_data['f'][1:], nbin)
        x = avrg(psd_data[mode][1:], nbin)

        # rough selection
        # fmin, fmax = fo - 3 * df_zoom / 2, 3 * fo + df_zoom / 2
        # xs = x[np.all([f > fmin, f < fmax], axis=0)]
        # fs = f[np.all([f > fmin, f < fmax], axis=0)]
        #
        # fo = fs[np.argmax(xs)]

        fmin, fmax = fo - df_zoom / 2, fo + df_zoom / 2
        x = x[np.all([f > fmin, f < fmax], axis=0)]
        fs = f[np.all([f > fmin, f < fmax], axis=0)]

        plt.plot(fs, x, '-o')
        plt.xlabel('frequency (Hz)')
        print(fo,' {:04.3f}Hz'.format(fo), ' {:04.03f}Hz'.format(fo))
        plt.title('mode ' + str(peak_data.index[i]) + ' {:04.3f}Hz'.format(fo))

        filename = '{:02d}_{:s}_{:04.0f}Hz.png'.format(i, mode, fo)
        fig.savefig(os.path.join(image_folder, filename))
        plt.close(fig)
예제 #2
0
def plot_rot_angle_dist(data, info, frame_max=100, n_avrg_list = [1,2, 4, 8, 16, 32, 64, 128]):
    """
    plots the distribution of angles as a function of binning length
    Args:
        data:
        time_step:
        source_folder_positions:
        verbose:
        frame_max:

    Returns:

    """
    time_step = info['info']['FrameRate']
    rot_angle = data['ellipse angle']

    fig, axes = plt.subplots(2, 2, sharey=False, sharex=False, figsize=(20, 8))
    res = []

    for n_avrg in n_avrg_list:

        rot_angle_avrg = avrg(rot_angle, n=n_avrg)

        x = axes[0,0].hist(rot_angle_avrg, log=True, bins=50, density=True, alpha=0.3)

        res.append(get_rotation_frequency(data, info)[0:2])

        axes[1,0].plot(np.arange(int(frame_max/n_avrg))*time_step*n_avrg, rot_angle_avrg[:int(frame_max/n_avrg)], '.-', label='n_avrg={:d}'.format(n_avrg))

    axes[0,1].semilogx(n_avrg_list, [abs(val[0]) for val in res],'o')
    axes[0,1].set_xlabel('number of averages')
    axes[0,1].set_ylabel('mean freq')

    axes[1,1].loglog(n_avrg_list, [val[1] for val in res], 'o')
    axes[1,1].set_xlabel('number of averages')
    axes[1,1].set_ylabel('std dev freq')


    axes[0,0].set_xlabel('angle (deg')
    axes[0,0].set_ylabel('prob. density')

    axes[1,0].set_xlabel('time (s)')
    axes[1,0].set_ylabel('angle (deg)')

    return fig, axes
예제 #3
0
def spectra_2D_map(position_file_names,source_folder_positions=None, modes='xy', navrg=10,
                   frequency_range=None, tag='_Sample_6_Bead_1_', nmax=None,
                   y_axis = '',
                   method = 'fit_ellipse', verbose=False):
    """

    calculated the psds and plots them as a waterfall plot

    Args:
        position_file_names:
        modes:
        navrg:
        y_axis: determines what to use for the y-axis, ['run', 'time (h)', ''] if '' y is equilly spaced
        xlim:
        tag:
        nmax:
        verbose:

    Returns:

    """
    fig, ax = plt.subplots(len(modes), 1, sharex=True, figsize=(18, 5 * len(modes)))

    if len(modes)==1:
        ax = [ax]

    psd_data = {'y_axis':[]}
    for i, filename in enumerate(position_file_names):
        run = int(filename.split(tag)[1].split('-')[0].strip('_'))
        if verbose:
            print(filename, run)
        data, info = load_time_trace(filename, source_folder_positions=source_folder_positions, verbose=False)
        dt = 1./info['info']['FrameRate']
        if verbose:
            print('FrameRate', info['info']['FrameRate'])
        if y_axis == '':
            psd_data['y_axis'].append(i)
        elif y_axis == 'run':
            psd_data['y_axis'].append(run)
        elif y_axis == 'time (h)':
            time = info['info']['File_Modified_Date_Local']
            time = datetime.strptime(time.split('.')[0], '%Y-%m-%d %H:%M:%S')
            if i==0:
                start = time
            time = time-start
            psd_data['y_axis'].append(time.seconds/(60 * 60) + time.days * 24)

        # calculate the psd

        for mode in modes:
            if method == 'fit_ellipse':
                if mode == 'r':
                    x = data['ellipse angle']
                elif mode == 'z':
                    x = data['ellipse a'] * data['ellipse b']
                else:
                    x = data['ellipse ' + mode]
            elif method.lower() == 'bright px':
                x = data['bright px ' + mode]

            x -= np.mean(x)
            if nmax is not None:
                x = x[0:nmax]

            f, p = power_spectral_density(x, time_step=dt, frequency_range=frequency_range)
            p = avrg(p, navrg)

            if mode in psd_data:

                psd_data[mode] = np.vstack([psd_data[mode],p])
            else:
                psd_data[mode] = p


    psd_data['f'] = avrg(f, navrg)


    for a, mode in enumerate(modes):
        z = np.log10(psd_data[mode])  # get data
        y = psd_data['y_axis']
        x = psd_data['f']

        ax[a].pcolormesh(x, y, z)  # plot

        ax[a].set_title(mode + ' data')
        ax[a].set_xlabel('frequency (Hz)')
        ax[a].set_ylabel(y_axis)

    return fig
예제 #4
0
def waterfall(position_file_names,source_folder_positions=None, modes='xy', navrg=10, off_set_factor=-3,
              frequency_range=None, tag='_Sample_6_Bead_1_', nmax=None,
              method = 'fit_ellipse', verbose=False):
    """

    calculated the psds and plots them as a waterfall plot

    Args:
        position_file_names:
        modes:
        navrg:
        off_set_factor:
        xlim:
        tag:
        nmax:
        verbose:

    Returns:

    """
    fig, ax = plt.subplots(len(modes), 1, sharex=True, figsize=(18, 5 * len(modes)))

    if len(modes)==1:
        ax = [ax]


    for i, filename in enumerate(position_file_names):
        run = int(filename.split(tag)[1].split('-')[0].strip('_'))
        if verbose:
            print(filename, run)
        data, info = load_time_trace(filename, source_folder_positions=source_folder_positions, verbose=False)
        dt = 1./info['info']['FrameRate']
        # calculate the psd
        psd_data = {}
        for mode in modes:
            if method == 'fit_ellipse':
                if mode == 'r':
                    x = data['ellipse angle']
                elif mode == 'z':
                    x = data['ellipse a'] * data['ellipse b']
                else:
                    x = data['ellipse ' + mode]
            elif method.lower() == 'bright px':
                x = data['bright px ' + mode]

            x -= np.mean(x)
            if nmax is not None:
                x = x[0:nmax]
            f, p = power_spectral_density(x, time_step=dt, frequency_range=frequency_range)
            psd_data[mode] = p
        psd_data['f'] = f

        f = psd_data['f'][1:]  # get rid of first point (DC)
        f = avrg(f, navrg)  # refold (assume that signal is aliasied)
        #         f = np.mean(df_modes['FrameRate'])-avrg(f, navrg)  # refold (assume that signal is aliasied)

        for a, mode in enumerate(modes):
            d = psd_data[mode]  # get data
            d = avrg(d[1:] * 10 ** (off_set_factor * i), navrg)  # shift on a log scale to get the waterfall effect
            ax[a].semilogy(f, d, label=str(run), alpha=0.5)  # plot




    # if xlim is not None:
    #     assert len(xlim) == 2
    #     ax[0].set_xlim(xlim)
    for a, mode in enumerate(modes):
        ax[a].set_title(mode + ' data')
    ax[a].set_xlabel('frequency (Hz)')
    plt.legend(loc=(1, 0.0))

    return fig
예제 #5
0
def plot_rotations_vs_time(data, time_step, t_max=0.1, n_avrg=20,n_avrg_unwrapped=20, axes=None, verbose=False, wrap_angle=None):
    """
    plots a zoom in of the unwrapped angle, the full time trace and the distribution histogram of frequencies
    which are calculated from the derivative of the phase
    Args:
        data:
        time_step:
        zoom_frames:
        n_avrg:
        axes:
        verbose:
        wrap_angle: if None find wrap_angle automatically otherwise wrap angles at this value

    Returns:

    """


    if wrap_angle is None:
        wrap_angle = get_wrap_angle(data['ellipse angle'], navrg=n_avrg)

    if verbose:
        print('wrap_angle', wrap_angle)


    min_frame, max_frame = 0, int(t_max/time_step/n_avrg)


    if axes is None:
        fig, axes = plt.subplots(2, 2, sharey=False, sharex=False, figsize=(18, 8))
    else:
        fig = None

    ax1, ax2 = axes[0]
    ax3, ax4 = axes[1]




    rot_angle = data['ellipse angle']



    rot_angle = avrg(rot_angle, n=n_avrg)
    x = ax4.hist(rot_angle, log=True, bins=50, alpha=0.3)

    rot_angle = np.unwrap(rot_angle, discont=wrap_angle)

    frames = np.arange(min_frame, max_frame)
    t = time_step * frames* n_avrg
    ax1.plot(t, rot_angle[frames] / 360)

    t2 = time_step *n_avrg* np.arange(len(rot_angle))
    if max(rot_angle)>1e3:
        ax2.plot(t2, 1e-3 * rot_angle / 360)
        label2 = 'rotations (x 1000)'
    else:
        ax2.plot(t2, rot_angle / 360)
        label2 = 'rotations'


    rot_angle = avrg(rot_angle, n=n_avrg_unwrapped)
    freqs = np.diff(rot_angle) / (360 * time_step * n_avrg_unwrapped)

    freq_estimate = np.mean(freqs)

    if verbose:
        print('{:d} datapoints'.format(len(rot_angle)))
        print('freq_estimate {:0.3f}'.format(freq_estimate))
        print('wrap angle {:0.2f} deg'.format(wrap_angle))



    x = ax3.hist(freqs, log=True, bins=50, alpha=0.3)


    # if fig is None:
    ax1.set_title('zoom')
    ax2.set_title('full')

    ax1.set_ylabel('rotations')
    ax2.set_ylabel(label2)
    ax3.set_ylabel('probability density')
    ax1.set_xlabel('time (s)')
    ax2.set_xlabel('time (s)')
    ax3.set_xlabel('rotation freq. (Hz)')

    ax4.set_xlabel('angles')
    ax4.set_ylabel('prob density')

    return fig, axes
예제 #6
0
def plot_ellipse_spectra(data, info, annotation_dict={}, freq_range=None, n_avrg=None, plot_type = 'lin', verbose=False, normalize=True, return_data=False, axes = None):
    """

    Args:
        data:
        info:
        annotation_dict:
        freq_range:
        n_avrg: average n_avrg successive datapoint to smoothen the data
        plot_type:

    Returns:

    """

    coordinates = [['x', 'y', 'area'], ['a', 'b', 'angle']]
    feature = 'ellipse'

    time_step = 1. / info['info']['FrameRate']
    axes_shape = np.shape(coordinates)

    if axes is None:
        fig, axes = plt.subplots(axes_shape[0], axes_shape[1], sharey=False, sharex=False,
                                 figsize=(8 * axes_shape[1], 3 * axes_shape[0]))
    else:
        fig = None




    if return_data:
        #containers for the data
        p_list = []
    modes = {}
    for i, row in enumerate(zip(coordinates, axes)):

        #     print('row', row)
        c_row, a_row = row
        for c, ax in zip(c_row, a_row):

            if verbose:
                print('plotting ' + c)

            if c == 'area':
                d = data[feature + ' a'] * data[feature + ' b'] * np.pi
            else:
                d = data[feature + ' ' + c]

            d = d - np.mean(d) # get rid of DC off set

            f, p = power_spectral_density(d, time_step, frequency_range=freq_range)

            if n_avrg is not None:
                f, p = avrg(f, n=n_avrg), avrg(p, n=n_avrg)

            if normalize:
                p = p / max(p)

            if plot_type == 'log':
                ax.loglog(f, p, linewidth=3)
            elif plot_type == 'lin':
                ax.plot(f, p, linewidth=3)
            elif plot_type == 'semilogy':
                ax.semilogy(f, p, linewidth=3)
            elif plot_type == 'semilogx':
                ax.semilogx(f, p, linewidth=3)

            # if we plot on a preexisting plot, don't add labels
            if fig is not None:
                if len(annotation_dict) > 0:
                    annotate_frequencies(ax, annotation_dict, higher_harm=1)
                #         annotate_frequencies(ax, annotation_dict, higher_harm=1)

            modes[c] = f[np.argmax(p)]

            ax.set_ylabel(c + ' (norm)')
            ax.set_xlim((min(f), max(f)))

            if i == len(coordinates) - 1:
                ax.set_xlabel('frequency (Hz)')

            if return_data:

                # containers for the data
                p_list.append(p)

    if return_data:
        return fig, axes, {'frequencies': f, 'spectra':p_list, 'coordinates':coordinates}
    else:
        return fig, axes
예제 #7
0
def plot_ellipse_spectra_zoom(data, info, annotation_dict={}, freq_window=1, n_avrg=None, plot_type='lin', normalize=True, axes=None, verbose=False):
    for mode in ['x', 'y', 'z', '2r', 'r', 'm']:
        assert mode in annotation_dict

    if normalize is True:
        normalize = 'max_peak'
    elif normalize is False:
        normalize = 'false'

    assert normalize in ['max_peak', 'false', 'std_dev']

    coordinates = [['x', 'y', 'z'], ['r', '2r', 'm']]
    feature = 'ellipse'

    time_step = 1. / info['info']['FrameRate']
    axes_shape = np.shape(coordinates)


    if axes is None:
        fig, axes = plt.subplots(axes_shape[0], axes_shape[1], sharey=False, sharex=False,
                                 figsize=(8 * axes_shape[1], 3 * axes_shape[0]))
    else:
        fig = None

    if verbose:
        print('axes shape', axes_shape, np.shape(axes), np.shape(coordinates))

    modes = {}
    for i, row in enumerate(zip(coordinates, axes)):

        c_row, a_row = row
        if verbose:
            print('row', i, c_row)
        if verbose:
            print('columns', np.shape(c_row), np.shape(a_row))
        for mode, ax in zip(c_row, a_row):
            if verbose:
                print('====', mode)
            axis_peak = mode
            # if mode in ['x', 'y', 'z']:
            #     data_labels = ['x', 'y', 'area']
            # elif mode in ['r', '2r', 'm']:
            #     data_labels = ['area', 'angle']

            if mode in ['x', 'y']:
                data_labels = [mode]
            elif mode in ['r', '2r', 'm', 'z']:
                data_labels = ['area']

            for data_label in data_labels:

                # as a proxy for the z mode we use the area
                if data_label == 'area':
                    d = data[feature + ' a'] * data[feature + ' b'] * np.pi
                else:
                    d = data[feature + ' ' + data_label]

                d = d - np.mean(d)  # get rid of DC off set


                if normalize == 'std_dev':
                    d /= np.std(d)

                # set the frequency range to be +- freq_window/2 around the peak
                frequency_range = (max(0, annotation_dict[axis_peak][0] - 0.5 * freq_window),
                                   min(annotation_dict[axis_peak][0] + 0.5 * freq_window, 0.5 * info['info']['FrameRate']))

                f, p = power_spectral_density(d, time_step, frequency_range=frequency_range)

                if n_avrg is not None:
                    f, p = avrg(f, n=n_avrg), avrg(p, n=n_avrg)

                if normalize == 'max_peak':
                    p = p / max(p)

                if plot_type == 'log':
                    ax.loglog(f, p, linewidth=3)
                elif plot_type == 'lin':
                    ax.plot(f, p, linewidth=3)
                elif plot_type == 'semilogy':
                    ax.semilogy(f, p, linewidth=3)
                elif plot_type == 'semilogx':
                    ax.semilogx(f, p, linewidth=3)

            # line_length = 0.2
            # # trying to get better lengths for log plots but doesn't work...
            # # if plot_type in ['lin', 'semilogx']:
            # #     line_length = 0.2
            # #
            # # elif plot_type in ['log', 'semilogy']:
            # #     line_length = 1-0.8*min(p / max(p))
            #
            # if len(annotation_dict) > 0:
            #     annotate_frequencies(ax, annotation_dict, x_off=0.1*freq_window, line_length=line_length, higher_harm=1)
            # #         annotate_frequencies(ax, annotation_dict, higher_harm=1)

            modes[mode] = f[np.argmax(p)]
            if normalize == 'max_peak':
                ax.set_ylabel(mode + ' (norm max peak)')
            elif normalize == 'std_dev':
                ax.set_ylabel(mode + ' (norm std)')
            else:
                ax.set_ylabel(mode)
            ax.set_xlim((min(f), max(f)))

            if i == len(coordinates) - 1:
                ax.set_xlabel('frequency (Hz)')

    return fig, axes