head_direction.py 1.9 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859
  1. import numpy as np
  2. from scipy import signal
  3. def head_direction(tl, hd_update_speed=0.04):
  4. width = 200 # 100 points ~= 1 sec with at 100Hz
  5. kernel = signal.gaussian(width, std=(width) / 7.2)
  6. x_smooth = np.convolve(tl[:, 1], kernel, 'same') / kernel.sum()
  7. y_smooth = np.convolve(tl[:, 2], kernel, 'same') / kernel.sum()
  8. diff_x = np.diff(x_smooth, axis=0)
  9. diff_y = np.diff(y_smooth, axis=0)
  10. hd = -np.arctan2(diff_y, diff_x)
  11. hd = np.concatenate([np.array([hd[0]]), hd]) # make the same length as timeline
  12. # reset idle periods
  13. idle_periods = []
  14. idle_idxs = np.where(tl[:, 3] < hd_update_speed)[0]
  15. crit = np.where(np.diff(idle_idxs) > 1)[0]
  16. idle_periods.append( (idle_idxs[0], idle_idxs[crit[0]]) ) # first idle period
  17. for i, point in enumerate(crit[:-1]):
  18. idx_start = idle_idxs[crit[i] + 1]
  19. idx_end = idle_idxs[crit[i+1]]
  20. idle_periods.append( (idx_start, idx_end) )
  21. idle_periods = np.array(idle_periods)
  22. for (i1, i2) in idle_periods:
  23. hd[i1:i2] = hd[i1-1]
  24. return hd
  25. def head_direction_slow(tl): # not used, slow computation
  26. offset = 10
  27. hd_update_speed = 0.04
  28. hd = np.zeros(len(tl))
  29. for i, pos in enumerate(tl[offset:]):
  30. recent_traj = tl[(tl[:, 0] > pos[0] - 0.25) & (tl[:, 0] <= pos[0])]
  31. avg_speed = recent_traj[:, 3].mean()
  32. if avg_speed > hd_update_speed: # if animal runs basically
  33. x, y = recent_traj[0][1], recent_traj[0][2]
  34. vectors = [np.array([a[1], a[2]]) - np.array([x, y]) for a in recent_traj[1:]]
  35. avg_direction = np.array(vectors).sum(axis=0) / len(vectors)
  36. avg_angle = -np.arctan2(avg_direction[1], avg_direction[0])
  37. hd[i + offset] = avg_angle # in radians
  38. else:
  39. hd[i + offset] = hd[i + offset - 1]
  40. first_non_zero_idx = np.nonzero(hd)[0][0]
  41. hd[:first_non_zero_idx] = hd[first_non_zero_idx]
  42. return hd