Example #1
0
    def responses(sun_ele=np.pi / 3, uniform=True, noise=.5, bl=.5):
        sun_azi = np.linspace(-np.pi, np.pi, 36, endpoint=False)
        sun_ele = np.full_like(sun_azi, sun_ele)

        phi_maxs = [[]] * 8
        r_means = [[]] * 8
        r_stds = [[]] * 8
        p_values = [[]] * 8
        tb1s = np.empty((0, sun_azi.shape[0], 8), dtype=sun_azi.dtype)

        for n_tb1 in np.arange(8):
            tb1s = np.empty((0, sun_azi.shape[0], 8), dtype=sun_azi.dtype)

            for _ in np.linspace(0, 1, 100):
                d_deg, d_eff, t, phi, r_tb1 = evaluate(
                    uniform_polariser=uniform,
                    sun_azi=sun_azi,
                    sun_ele=sun_ele,
                    tilting=False,
                    noise=noise)
                tb1s = np.vstack([tb1s, np.transpose(r_tb1, axes=(1, 0, 2))])

            r_mean = np.median(tb1s[..., n_tb1], axis=0)
            z = r_mean.max() - r_mean.min()

            r_mean = (r_mean - r_mean.min()) / z - bl
            r_means[n_tb1] = r_mean
            r_stds[n_tb1] = tb1s[..., n_tb1].std(axis=0) / np.sqrt(z)

            p_values[n_tb1] = rayleightest(sun_azi, weights=r_mean + bl)
            phi_max = circmean(sun_azi, weights=np.power(r_mean + bl, 50))
            phi_maxs[n_tb1] = phi_max

        z = tb1s.max() - tb1s.min()
        tb1s = (tb1s - tb1s.min()) / z
        phis = np.transpose(np.array([[sun_azi] * 100] * 8), axes=(1, 2, 0))
        phi_means = circmean(phis, axis=1, weights=np.power(tb1s, 50)).T

        return np.array(phi_maxs)[::-1], phi_means[::-1], np.array(
            r_means)[::-1], np.array(r_stds)[::-1], np.array(p_values)[::-1]
Example #2
0
    with open(fname, 'r') as fp:
        lines = fp.readlines()

    return [line.strip() for line in lines]


if __name__ == '__main__':
    if len(sys.argv) != 2:
        print('$ python3 calc_index.py file.scp')
        exit(1)

    if not os.path.isfile(sys.argv[1]):
        print('[ERR] Failed to find {} file'.format(sys.argv[1]))
        sys.exit(1)

    file_list = read_file_list(sys.argv[1])

    for fname in file_list:
        if not os.path.isfile(fname):
            print('[ERR] Failed to find {} file'.format(fname))
            sys.exit(1)

        radian_list, degree_list = read_angle_csv(fname)
        print("FILE: {}, Data #: {}".format(fname, len(radian_list)))
        print("PI:  {}".format(cal_pi(radian_list)))

        degree_np = np.array(degree_list) * u.deg
        result = rayleightest(degree_np)
        print("RAY: {}".format(result))
        print("")
def get_rayleigh_score_for_cluster(hd_hist: np.ndarray) -> float:
    bins_in_histogram = len(hd_hist)
    values = np.radians(np.arange(0, 360, int(360 / bins_in_histogram)))
    rayleigh_p = rayleightest(values, weights=hd_hist)
    return rayleigh_p
    data = 2 * np.pi * np.random.rand(6, 1000)
    s = np.shape(data)
    print('Imported data with %.0f' % s[0], 'rows (variables) by %.0f' % s[1],
          'columns (observations).')

    data_cent = data * 0
    i = 0
    for d in data:
        d = np.mod(d - circmean(d), np.pi * 2)
        data_cent[i, ] = d
        i = i + 1

    qgroupt, rhogroupt = circ_mean(data_cent)
    plt.plot(rhogroupt, '-k')
    plt.ylabel(r'$ \rho _{group,i}$')
    plt.show()

    polar_histogram(data, s)
    rp0 = rayleightest(np.reshape(data, (s[0] * s[1], 1)))
    print('The Rayleigh test is p=%.4f.' % rp0)

    polar_histogram(data_cent, s)
    rp1 = rayleightest(np.reshape(data_cent, (s[0] * s[1], 1)))
    print('The Rayleigh test is p=%.4f' % rp1)

    for d1, d2 in zip(data, data_cent):
        rp2 = rayleightest(d1)
        rp3 = rayleightest(d2)
        print('The Rayleigh tests are p=%.4f and %.4f.' % (rp2, rp3))
Example #5
0
def heinze_real(mode=1, n_tb1=0):

    columns = [
        ['fz1028'],  # L8/R1
        ['060126', '060131', '050105a', 'fz1049'],  # L7/R2
        ['050329', '050309a', '050124b', '041215', 'fz1020',
         'fz1038'],  # L6/R3
        ['060124', '060206a', '060206b', 'fz1016'],  # L5/R4
        ['050520', '040604b', 'fz1040'],  # L4/R5
        [],  # L3/R6
        ['050309b', '050222'],  # L2/R7
        ['041209', 'fz1051'],  # L1/R8
    ]

    phi_tb1 = 3 * np.pi / 2 - np.linspace(0, np.pi, 8)
    # phi_tb1 = np.linspace(0, np.pi, 8) + np.pi/2
    phi = np.linspace(np.deg2rad(5), np.deg2rad(355), 36)
    phi_max = []

    for j, filenames in enumerate(
            columns if n_tb1 is None else [columns[n_tb1]]):
        col = j if n_tb1 is None else n_tb1
        phi_max.append([])

        for i, filename in enumerate(filenames):
            if 'fz' in filename:
                continue
            tb1s = loadmat("../data/TB1_neurons/mean_rotation_%s.mat" %
                           filename)['mean_rotation'][:, ::2]
            tb1s = tb1s.reshape((-1, 2)).mean(axis=1).reshape((1, -1))

            z = tb1s.max() - tb1s.min()
            r_std = tb1s.std(axis=0) / np.sqrt(z)
            bl = .5
            r_mean = tb1s.flatten() / tb1s.max() - bl
            p_value = rayleightest(phi, weights=r_mean + bl)
            phi_mean_00 = circmean((phi - np.pi / 2) % np.pi + np.pi / 2,
                                   weights=np.power(r_mean + bl, 8))
            phi_var_00 = circvar((phi - np.pi / 2) % np.pi + np.pi / 2,
                                 weights=np.power(r_mean + bl, 8))
            phi_mean_90 = circmean(phi % np.pi,
                                   weights=np.power(r_mean + bl, 8))
            phi_var_90 = circvar(phi % np.pi, weights=np.power(r_mean + bl, 8))
            phi_mean = phi_mean_00 if phi_var_00 < phi_var_90 else phi_mean_90
            d_00 = np.absolute((phi_mean - phi_tb1[-1 - i] + np.pi) %
                               (2 * np.pi) - np.pi)
            d_pi = np.absolute((phi_mean - phi_tb1[-1 - i]) % (2 * np.pi) -
                               np.pi)
            if d_00 > d_pi:
                phi_mean += np.pi
            phi_max[j].append(phi_mean)
            print "Col %d - %s, mean: % 3.2f, p = %.4f" % (
                col, filename, np.rad2deg(phi_mean), p_value)

            if mode == 1:
                plt.figure("heinze-L%d-R%d-%s" % (8 - col, col + 1, filename),
                           figsize=(3, 3))
                ax = plt.subplot(111, polar=True)
                ax.set_theta_zero_location("N")
                ax.set_theta_direction(-1)

                y_min, y_max = -.3, 1.1
                plt.bar(phi, bl + r_mean, .1, yerr=r_std, facecolor='black')
                plt.plot(np.linspace(-np.pi, np.pi, 361), np.full(361, bl),
                         'k-')
                x_mean = [
                    phi_mean, phi_mean, phi_mean + np.pi, phi_mean + np.pi
                ]
                plt.plot(x_mean, [y_max, y_min, y_min, y_max], 'r-.')
                plt.yticks([])
                plt.xticks(np.linspace(0, 2 * np.pi, 8, endpoint=False), [
                    r'%d$^\circ$' % x for x in (
                        (np.linspace(0, 360, 8, endpoint=False) + 180) % 360 -
                        180)
                ])
                plt.ylim([y_min, y_max])
                # plt.savefig("heinze-%s%d.eps" % ("abs-" if absolute else "uni-" if uniform else "", n_tb1))
                plt.show()

    if mode == 2:
        plt.figure("heinze-real-fig-1F", figsize=(5, 5))
        tb1_names = []
        x, y = [], []
        for i, phi_max_i in enumerate(phi_max):
            col = i if n_tb1 is None else n_tb1
            for j, phi_max_j in enumerate(phi_max_i):
                d_00 = np.absolute((phi_max_j - phi_tb1[-1 - i] + np.pi) %
                                   (2 * np.pi) - np.pi)
                d_pi = np.absolute((phi_max_j - phi_tb1[-1 - i]) %
                                   (2 * np.pi) - np.pi)
                if d_00 > d_pi:
                    phi_max_i[j] += np.pi

            phi_mean_i = circmean(np.array(phi_max_i)) % (2 * np.pi)
            if not np.isnan(phi_mean_i):
                x.append([phi_mean_i, 1])
                y.append(col)
            tb1_names.append('L%d/R%d' % (8 - col, col + 1))
            plt.scatter([col] * len(phi_max_i),
                        np.rad2deg(phi_max_i) % 360,
                        s=20,
                        c='black')
            plt.scatter(col,
                        np.rad2deg(phi_mean_i) % 360,
                        s=50,
                        c='red',
                        marker='*')
        x = np.array(x)
        y = np.array(y)
        a, b = np.linalg.pinv(x).dot(y)
        plt.plot([-1, 8], np.rad2deg([(-1 - b) / a, (8 - b) / a]), 'r-.')
        plt.xticks([0, 1, 2, 3, 4, 5, 6, 7], [
            tb1_names[0], '', tb1_names[2], '', tb1_names[4], '', tb1_names[6],
            ''
        ])
        plt.yticks([0, 45, 90, 135, 180, 225, 270, 315, 360],
                   ['0', '', '90', '', '180', '', '270', '', '360'])
        plt.ylim([-20, 380])
        plt.xlim([-1, 8])
        plt.show()
Example #6
0
def heinze_experiment(n_tb1=0,
                      eta=.0,
                      sun_ele=np.pi / 2,
                      absolute=False,
                      uniform=False):
    sun_azi = np.linspace(-np.pi, np.pi, 36, endpoint=False)
    sun_ele = np.full_like(sun_azi, sun_ele)
    tb1s = np.empty((0, sun_azi.shape[0], 8), dtype=sun_azi.dtype)

    for _ in np.linspace(0, 1, 100):
        d_deg, d_eff, t, phi, r_tb1 = evaluate(uniform_polariser=uniform,
                                               sun_azi=sun_azi,
                                               sun_ele=sun_ele,
                                               tilting=False,
                                               noise=eta)
        tb1s = np.vstack([tb1s, np.transpose(r_tb1, axes=(1, 0, 2))])

    if absolute:
        tb1s = np.absolute(tb1s)
    bl = .5
    r_mean = np.median(tb1s[..., n_tb1], axis=0)
    z = r_mean.max() - r_mean.min()

    r_mean = (r_mean - r_mean.min()) / z - bl
    r_std = tb1s[..., n_tb1].std(axis=0) / np.sqrt(z)

    p_value = rayleightest(sun_azi, weights=r_mean + bl)
    if uniform:
        # phi_mean_00 = circmean((sun_azi - np.pi / 2) % np.pi + np.pi / 2, weights=np.power(r_mean + bl, 8))
        # phi_var_00 = circvar((sun_azi - np.pi / 2) % np.pi + np.pi / 2, weights=np.power(r_mean + bl, 8))
        # phi_mean_90 = circmean(sun_azi % np.pi, weights=np.power(r_mean + bl, 8))
        # phi_var_90 = circvar(sun_azi % np.pi, weights=np.power(r_mean + bl, 8))
        # phi_mean = phi_mean_00 if phi_var_00 < phi_var_90 else phi_mean_90
        phi_mean = circmean(sun_azi, weights=np.power(r_mean + bl, 50))
    else:
        phi_mean = circmean(sun_azi, weights=np.power(r_mean + bl, 50))
    # phi_max[j].append(phi_mean)

    plt.figure(
        "heinze-%s%s" %
        ("abs-" if absolute else "uni-" if uniform else "", tb1_names[n_tb1]),
        figsize=(3, 3))
    ax = plt.subplot(111, polar=True)
    ax.set_theta_zero_location("N")
    ax.set_theta_direction(-1)

    y_min, y_max = -.3, 1.1
    plt.bar((sun_azi + np.pi) % (2 * np.pi) - np.pi,
            bl + r_mean,
            .1,
            yerr=r_std,
            facecolor='black')
    plt.plot(np.linspace(-np.pi, np.pi, 361), np.full(361, bl), 'k-')
    if uniform:
        x_mean = [phi_mean, phi_mean, phi_mean + np.pi, phi_mean + np.pi]
        plt.plot(x_mean, [y_max, y_min, y_min, y_max], 'r-.')
    else:
        plt.plot([phi_mean, phi_mean], [y_max, y_min], 'r-.')
    plt.yticks([])
    plt.xticks(np.linspace(0, 2 * np.pi, 8, endpoint=False), [
        r'%d$^\circ$' % x
        for x in ((np.linspace(0, 360, 8, endpoint=False) + 180) % 360 - 180)
    ])
    plt.ylim([y_min, y_max])
    # plt.savefig("heinze-%s%d.eps" % ("abs-" if absolute else "uni-" if uniform else "", n_tb1))
    plt.show()
axs[0].axis(ymin=-0.45, ymax=0.45)

fig.subplots_adjust(bottom=0.25, top=0.98, right=0.98, left=0.10, wspace=0.28)
# Caption:
#  Time are centers of 3 h bins.
fig.savefig(os.path.join(fig_dir, 'octant-swim_longitudinal_lateral-bw.png'),
            dpi=200)

##

# Stats on octant / lateral
tod_mid_rad = df_start['tod_mid_s'] * 2 * np.pi / 86400
from astropy.stats import rayleightest

# 0.94.
p_rayleigh_arrival = rayleightest(tod_mid_rad)
print("Rayleigh statistic for time of day of arrival: %.4f" %
      p_rayleigh_arrival)

# hmm - so how to translate this to testing whether u_lateral has a diel
# component?
# Can I just use u_lateral as the weighting? No, the result is not independent
# of the mean value.
# 0.1715

## What if I brute force it?

lateral = df_start['mean_swim_lateral'].values


def test_diel(column, df_start=df_start, num=1):
Example #8
0
    def extractFeatures(self, **kwargs):
        tic = time.time()

        #find sampling rate
        fs = self.find_nearest_fs(np.median(1 / np.diff(self.data['t'])))
        self.fs = fs

        #window size for spatial measures in samples
        ws = round_up_to_odd(self.w / 1000.0 * fs + 1)

        #window size in samples for velocity calculation
        ws_vel = round_up_to_odd(self.w_vel / 1000.0 * fs)

        #window size in samples for direction calculation
        ws_dir = round_up_to_odd(self.w_dir / 1000.0 * fs)

        ws_pad = (max((ws, ws_vel, ws_dir)) - 1) / 2
        x_padded = np.pad(self.data['x'], (ws_pad, ws_pad),
                          'constant',
                          constant_values=np.nan)
        y_padded = np.pad(self.data['y'], (ws_pad, ws_pad),
                          'constant',
                          constant_values=np.nan)

        ws_dir_pad = (ws_dir - 1) / 2
        x_padded_dir = np.pad(self.data['x'], (ws_dir_pad, ws_dir_pad),
                              'constant',
                              constant_values=np.nan)
        y_padded_dir = np.pad(self.data['y'], (ws_dir_pad, ws_dir_pad),
                              'constant',
                              constant_values=np.nan)

        x_windowed = rolling_window(x_padded, ws)
        y_windowed = rolling_window(y_padded, ws)
        dx_windowed = rolling_window(np.diff(x_padded), ws - 1)
        dy_windowed = rolling_window(np.diff(y_padded), ws - 1)
        x_windowed_dir = rolling_window(np.diff(x_padded_dir), ws_dir - 1)
        y_windowed_dir = rolling_window(np.diff(y_padded_dir), ws_dir - 1)

        #%%Extract features
        features = dict()

        #sampling rate
        features['fs'] = np.ones(len(self.data)) * fs

        for d, dd in zip(['x', 'y'], [x_windowed, y_windowed]):
            #difference between positions of preceding and succeding windows,
            #aka tobii feature
            means = np.nanmean(dd, axis=1)
            meds = np.nanmedian(dd, axis=1)
            features['mean-diff-%s'%d] = np.roll(means, -(ws-1)/2) - \
                                         np.roll(means,  (ws-1)/2)
            features['med-diff-%s'%d] = np.roll(meds, -(ws-1)/2) - \
                                        np.roll(meds,  (ws-1)/2)

            #standard deviation
            features['std-%s' % d] = np.nanstd(dd, axis=1)
            features['std-next-%s' % d] = np.roll(features['std-%s' % d],
                                                  -(ws - 1) / 2)
            features['std-prev-%s' % d] = np.roll(features['std-%s' % d],
                                                  (ws - 1) / 2)

        features['mean-diff'] = np.hypot(features['mean-diff-x'],
                                         features['mean-diff-y'])
        features['med-diff'] = np.hypot(features['med-diff-x'],
                                        features['med-diff-y'])

        features['std'] = np.hypot(features['std-x'], features['std-y'])
        features['std-diff'] = np.hypot(features['std-next-x'], features['std-next-y']) - \
                               np.hypot(features['std-prev-x'], features['std-prev-y'])

        #BCEA
        P = 0.68  #cumulative probability of area under the multivariate normal
        k = np.log(1 / (1 - P))
        #rho = [np.corrcoef(px, py)[0,1] for px, py in zip(x_windowed, y_windowed)]
        rho = vcorrcoef(x_windowed, y_windowed)
        features['bcea'] = 2 * k * np.pi * \
                           features['std-x'] * features['std-y'] * \
                           np.sqrt(1-np.power(rho,2))
        features['bcea-diff'] = np.roll(features['bcea'], -(ws-1)/2) - \
                                np.roll(features['bcea'], (ws-1)/2)

        #RMS
        features['rms'] = np.hypot(
            np.sqrt(np.mean(np.square(dx_windowed), axis=1)),
            np.sqrt(np.mean(np.square(dy_windowed), axis=1)))
        features['rms-diff'] = np.roll(features['rms'], -(ws-1)/2) - \
                               np.roll(features['rms'], (ws-1)/2)

        #disp, aka idt feature
        x_range = np.nanmax(x_windowed, axis=1) - np.nanmin(x_windowed, axis=1)
        y_range = np.nanmax(y_windowed, axis=1) - np.nanmin(y_windowed, axis=1)
        features['disp'] = x_range + y_range

        #velocity and acceleration
        features['vel'] = np.hypot(
            sg.savgol_filter(self.data['x'], ws_vel, 2, 1),
            sg.savgol_filter(self.data['y'], ws_vel, 2, 1)) * fs

        features['acc'] = np.hypot(
            sg.savgol_filter(self.data['x'], ws_vel, 2, 2),
            sg.savgol_filter(self.data['y'], ws_vel, 2, 2)) * fs**2

        #direction
        self.x_windowed_dir = x_windowed_dir
        self.y_windowed_dir = y_windowed_dir

        angl = np.arctan2(y_windowed_dir, x_windowed_dir)
        features['rayleightest'] = ast.rayleightest(angl, axis=1)

        ###i2mc
        if kwargs.has_key('i2mc_root'):
            features['i2mc'] = self.feat_i2mc
        else:
            features['i2mc'] = np.zeros(len(self.data))

        #remove padding and nans
        mask_nans = np.any(
            [np.isnan(values) for key, values in features.iteritems()], axis=0)
        mask_pad = np.zeros_like(self.data['x'], dtype=np.bool)
        mask_pad[:ws_pad] = True
        mask_pad[-ws_pad:] = True
        mask = mask_nans | mask_pad
        features = {
            key: values[~mask].astype(np.float32)
            for key, values in features.iteritems()
        }

        #return features
        self.features = np.core.records.fromarrays(
            [features[ft_incl] for ft_incl in features_incl],
            np.dtype(zip(features_incl, itertools.repeat(np.float32))))

        self.mask = mask
        #        if not(self.events is None):
        #            self.events=self.events[~mask]
        self.data['status'] = ~self.mask & ~self.maskInterp

        toc = time.time()

        if kwargs.has_key('print_et') and (kwargs['print_et'] == True):
            print 'Feature extraction took %.3f s.' % (toc - tic)
Example #9
0
def extractFeatures(etdata, **kwargs):
    '''Extracts features for IRF
    '''

    #get parameters
    data = etdata.data
    w, w_vel, w_dir = kwargs['w'], kwargs['w_vel'], kwargs['w_dir']

    tic = time.time()

    #find sampling rate
    fs = etdata.fs

    #window size for spatial measures in samples
    ws = round_up_to_odd(w/1000.0*fs+1)

    #window size in samples for velocity calculation
    ws_vel = round_up_to_odd(w_vel/1000.0*fs)

    #window size in samples for direction calculation
    ws_dir = round_up_to_odd(w_dir/1000.0*fs)

    maskInterp = np.zeros(len(data), dtype=np.bool)
    '''Legacy code. Interpolates through missing points.
    if kwargs.has_key('interp') and kwargs['interp']:
        r = np.arange(len(data))
        _mask = np.isnan(data['x']) | np.isnan(data['y'])
        fx = interp.PchipInterpolator(r[~_mask], data[~_mask]['x'],
                                    extrapolate=True)
        fy = interp.PchipInterpolator(r[~_mask], data[~_mask]['y'],
                                    extrapolate=True)
        data['x'][_mask]=fx(r[_mask])
        data['y'][_mask]=fy(r[_mask])
        maskInterp = _mask
    '''

    #prepare data for vectorized processing
    ws_pad=(max((ws, ws_vel, ws_dir))-1)/2
    x_padded = np.pad(data['x'], (ws_pad, ws_pad),
                      'constant', constant_values=np.nan)
    y_padded = np.pad(data['y'], (ws_pad, ws_pad),
                      'constant', constant_values=np.nan)

    ws_dir_pad=(ws_dir-1)/2
    x_padded_dir=np.pad(data['x'], (ws_dir_pad, ws_dir_pad),
                        'constant', constant_values=np.nan)
    y_padded_dir=np.pad(data['y'], (ws_dir_pad, ws_dir_pad),
                        'constant', constant_values=np.nan)

    x_windowed = rolling_window(x_padded, ws)
    y_windowed = rolling_window(y_padded, ws)
    dx_windowed = rolling_window(np.diff(x_padded), ws-1)
    dy_windowed = rolling_window(np.diff(y_padded), ws-1)
    x_windowed_dir = rolling_window(np.diff(x_padded_dir), ws_dir-1)
    y_windowed_dir = rolling_window(np.diff(y_padded_dir), ws_dir-1)

    #%%Extract features
    features=dict()

    #sampling rate
    features['fs'] = np.ones(len(data))*fs

    for d, dd in zip(['x', 'y'], [x_windowed, y_windowed]):
        #difference between positions of preceding and succeding windows,
        #aka tobii feature, together with data quality features and its variants
        means=np.nanmean(dd, axis = 1)
        meds=np.nanmedian(dd, axis = 1)
        features['mean-diff-%s'%d] = np.roll(means, -(ws-1)/2) - \
                                     np.roll(means,  (ws-1)/2)
        features['med-diff-%s'%d] = np.roll(meds, -(ws-1)/2) - \
                                    np.roll(meds,  (ws-1)/2)

        #standard deviation
        features['std-%s'%d] = np.nanstd(dd, axis=1)
        features['std-next-%s'%d] = np.roll(features['std-%s'%d], -(ws-1)/2)
        features['std-prev-%s'%d] = np.roll(features['std-%s'%d],  (ws-1)/2)

    features['mean-diff']= np.hypot(features['mean-diff-x'],
                                    features['mean-diff-y'])
    features['med-diff']= np.hypot(features['med-diff-x'],
                                   features['med-diff-y'])

    features['std'] = np.hypot(features['std-x'], features['std-y'])
    features['std-diff'] = np.hypot(features['std-next-x'], features['std-next-y']) - \
                           np.hypot(features['std-prev-x'], features['std-prev-y'])

    #BCEA
    P = 0.68 #cumulative probability of area under the multivariate normal
    k = np.log(1/(1-P))
    #rho = [np.corrcoef(px, py)[0,1] for px, py in zip(x_windowed, y_windowed)]
    rho = vcorrcoef(x_windowed, y_windowed)
    features['bcea'] = 2 * k * np.pi * \
                       features['std-x'] * features['std-y'] * \
                       np.sqrt(1-np.power(rho,2))
    features['bcea-diff'] = np.roll(features['bcea'], -(ws-1)/2) - \
                            np.roll(features['bcea'], (ws-1)/2)

    #RMS
    features['rms'] = np.hypot(np.sqrt(np.mean(np.square(dx_windowed), axis=1)),
                               np.sqrt(np.mean(np.square(dy_windowed), axis=1)))
    features['rms-diff'] = np.roll(features['rms'], -(ws-1)/2) - \
                           np.roll(features['rms'], (ws-1)/2)

    #disp, aka idt feature
    x_range = np.nanmax(x_windowed, axis=1) - np.nanmin(x_windowed, axis=1)
    y_range = np.nanmax(y_windowed, axis=1) - np.nanmin(y_windowed, axis=1)
    features['disp'] = x_range + y_range

    #velocity and acceleration
    features['vel']=np.hypot(sg.savgol_filter(data['x'], ws_vel, 2, 1),
                             sg.savgol_filter(data['y'], ws_vel, 2, 1))*fs

    features['acc']=np.hypot(sg.savgol_filter(data['x'], ws_vel, 2, 2),
                             sg.savgol_filter(data['y'], ws_vel, 2, 2))*fs**2

    #rayleightest
    angl = np.arctan2(y_windowed_dir, x_windowed_dir)
    features['rayleightest'] = ast.rayleightest(angl, axis=1)

    #i2mc
    if kwargs.has_key('i2mc') and kwargs['i2mc'] is not None:
        features['i2mc'] = kwargs['i2mc']['finalweights'].flatten()
    else:
        features['i2mc'] = np.zeros(len(data))

    #remove padding and nans
    mask_nans = np.any([np.isnan(values) for key, values\
                                         in features.iteritems()], axis=0)
    mask_pad = np.zeros_like(data['x'], dtype=np.bool)
    mask_pad[:ws_pad] = True
    mask_pad[-ws_pad:] = True
    mask = mask_nans | mask_pad | maskInterp
    features={key: values[~mask].astype(np.float32) for key, values \
                                                    in features.iteritems()}

    dtype = np.dtype(zip(features.keys(), itertools.repeat(np.float32)))
    features = np.core.records.fromarrays(features.values(), dtype=dtype)

    #return features
    toc = time.time()
    if kwargs.has_key('print_et') and kwargs['print_et']:
        print 'Feature extraction took %.3f s.'%(toc-tic)
    return features, ~mask