def find_object(img, thresholds, sizerange, dist_thresh, erode=False, check_centers=True): body = nim.threshold(img, thresholds[0], thresholds[1]) if erode is not False: for i in range(erode): body = binary_erosion(body) if check_centers is False: blobs = nim.find_blobs(body, sizerange=sizerange, aslist=False) else: blobs = nim.find_blobs(body, sizerange=sizerange, aslist=True) body = blobs if check_centers: centers = nim.center_of_blob(blobs) dist = [] for center in centers: diff = np.linalg.norm( center - np.array(img.shape)/2. ) dist.append(diff) body = np.zeros_like(img) for j, d in enumerate(dist): if d < dist_thresh: body += blobs[j] if body.max() > 1: body /= body.max() if body is None: body = np.zeros_like(img) body = np.array(body*255, dtype=np.uint8) return body
def calc_saccades(trajec, threshold_lo=300, threshold_hi=100000000, min_angle=10, plot=False): # thresholds in deg/sec # min_angle = minimum angle necessary to count as a saccade, deg fps = 100. possible_saccade_array = (np.abs(trajec.heading_smooth_diff)*180/np.pi > threshold_lo)*(np.abs(trajec.heading_smooth_diff)*180/np.pi < threshold_hi) possible_saccades = nim.find_blobs(possible_saccade_array, [3,100]) if len(possible_saccades) == 1: if np.sum(possible_saccades[0]) == 0: possible_saccades = [] trajec.all_saccades = [] trajec.saccades = [] trajec.sac_ranges = [] if len(possible_saccades) > 0: for sac in possible_saccades: indices = np.where(sac==1)[0].tolist() if len(indices) > 0: # expand saccade range to make sure we get full turn #lo = np.max([indices[0]-5, 0]) #hi = np.min([indices[-1]+5, len(trajec.speed)-2]) #new_indices = np.arange(lo, hi).tolist() #tmp = np.where( np.abs(trajec.heading_diff_window[new_indices])*180/np.pi > 350 )[0].tolist() #indices = np.array(new_indices)[ tmp ].tolist() angle_of_saccade = np.abs(get_angle_of_saccade(trajec, indices)*180./np.pi) mean_speed = np.mean(trajec.speed[indices]) if len(indices) > 3 and angle_of_saccade > 10: # and mean_speed > 0.005: trajec.sac_ranges.append(indices) s_rel = np.argmax( np.abs(trajec.heading_smooth_diff[indices]) ) s = indices[s_rel] trajec.all_saccades.append(s) if plot: fig = plt.figure() ax = fig.add_subplot(111) ax.set_aspect('equal') ax.plot(trajec.positions[:,0], trajec.positions[:,1], '-', color='black', alpha=1, linewidth=1, zorder=1) for sac in trajec.sac_ranges: ax.plot(trajec.positions[sac,0], trajec.positions[sac,1], '-', color='red', alpha=1, linewidth=1, zorder=1+1) for s in trajec.all_saccades: x = trajec.positions[s, 0] y = trajec.positions[s, 1] saccade = patches.Circle( (x, y), radius=0.001, facecolor='blue', edgecolor='none', alpha=1, zorder=3) ax.add_artist(saccade) post = patches.Circle( (0, 0), radius=0.009565, facecolor='black', edgecolor='none', alpha=1) ax.add_artist(post) fig.savefig('saccade_trajectory.pdf', format='pdf')
def get_bouts_of_constant_speed(movieinfo, accel_threshold=.005, duration_threshold=0.2): duration_threshold_frames = duration_threshold * float(movieinfo.framerate) #speed_diff = np.diff( np.hstack( (movieinfo.scaled.speed[0], movieinfo.scaled.speed) ) ) #speed_diff_bool_tmp = np.abs(speed_diff) < accel_threshold nt, alt_speed = interpolate_to_new_framerate( movieinfo, 5000., movieinfo.trajec.epoch_time, movieinfo.trajec.velocities[:, 2]) nt, speed = interpolate_to_new_framerate(movieinfo, 5000., movieinfo.timestamps, movieinfo.scaled.speed) speed_diff = np.diff(np.hstack((speed[0], speed))) speed_diff_bool_tmp = np.abs(speed_diff) < accel_threshold alt_speed_diff = np.diff(np.hstack((alt_speed[0], alt_speed))) alt_speed_diff_bool_tmp = np.abs(alt_speed_diff) < .005 bool_tmp = alt_speed_diff_bool_tmp * speed_diff_bool_tmp continuous_sequences = nim.find_blobs( bool_tmp, sizerange=[duration_threshold_frames, np.inf], dilate=1) calc_pitch_estimate(movieinfo) pitch = [] speed = [] for i, sequence in enumerate(continuous_sequences): indices = np.where(sequence == 1)[0].tolist() if np.sum(sequence) > 0: print movieinfo.id, len(sequence) r1 = np.median(movieinfo.scaled.speed[indices]) r2 = np.median(movieinfo.scaled.pitchangle[indices]) if not np.isnan(r1) and not np.isnan(r2): pitch.append(r2) speed.append(r1) return pitch, speed
def get_flydra_speed_during_fixation_means(trajec, fixation_threshold_degrees=5, fixation_duration_threshold=0.1): fixation_indices = get_flydra_indices_during_fixation( trajec, fixation_threshold_degrees, fixation_duration_threshold) if len(fixation_indices) > 0: diffarr = np.diff(np.hstack((fixation_indices[0], fixation_indices))) continuous_sequences = nim.find_blobs(diffarr) mean = [] std = [] for sequence in continuous_sequences: indices = np.where(sequence == 1)[0].tolist() mean.append(np.mean(trajec.speed[indices])) std.append(np.std(trajec.speed[indices])) return mean, std else: return [], []
def get_continuous_data(fixation): fixation_angle_bool_tmp = np.abs(fixation) < fixation_threshold_radians dist_bool = trajec.dist_to_stim_r > 0.01 altitude_bool_high = trajec.positions[:, 2] < -.01 altitude_bool_low = trajec.positions[:, 2] > -.1 fixation_bool_tmp = fixation_angle_bool_tmp * altitude_bool_high * altitude_bool_low * dist_bool #fixation_diff = np.diff( np.hstack( (fixation[0], fixation) ) ) #fixation_diff_bool_tmp = fixation_diff < 0.0005 #fixation_bool_tmp = fixation_angle_bool_tmp#*diff_bool_tmp #fixation_indices_tmp = np.where( fixation_angle_bool_tmp == True )[0].tolist() #fixation_indices_tmp = np.where( np.abs(fixation) < fixation_threshold_radians )[0].tolist() continuous_sequences = nim.find_blobs( fixation_bool_tmp, sizerange=[fixation_duration_threshold_frames, np.inf], dilate=False) fixation_indices = [] for sequence in continuous_sequences: indices = np.where(sequence == 1)[0].tolist() fixation_indices = np.hstack((fixation_indices, indices)) return fixation_indices.tolist()
def get_continuous_data(fixation_lower): lower_fixation_angle_bool_tmp = np.abs( fixation_lower) < fixation_threshold_radians fixation_lower_diff = np.diff( np.hstack((fixation_lower[0], fixation_lower))) lower_fixation_diff_bool_tmp = np.abs(fixation_lower_diff) < 0.01745 lower_fixation_bool_tmp = lower_fixation_angle_bool_tmp #lower_fixation_diff_bool_tmp # lower_fixation_indices_tmp = np.where( lower_fixation_bool_tmp == True)[0].tolist() #lower_fixation_indices_tmp = np.where( np.abs(fixation_lower) < fixation_threshold_radians )[0].tolist() continuous_sequences = nim.find_blobs( lower_fixation_indices_tmp, sizerange=[fixation_duration_threshold_frames, np.inf], dilate=1) lower_fixation_indices = [] for sequence in continuous_sequences: indices = np.where(sequence == 1)[0].tolist() lower_fixation_indices = np.hstack( (lower_fixation_indices, np.array(lower_fixation_indices_tmp)[indices])) return lower_fixation_indices.tolist()
def background_subtraction(self, raw, save_raw=False): mask_center_0 = int(self.mask_center[0]) mask_center_1 = int(self.mask_center[1]) mask_0_lo = max(0, mask_center_0 - self.mask_radius) mask_0_hi = min(self.width, mask_center_0 + self.mask_radius) mask_1_lo = max(0, mask_center_1 - self.mask_radius) mask_1_hi = min(self.width, mask_center_1 + self.mask_radius) if self.tracking_mask is not None: tracking_mask = copy.copy(self.tracking_mask) tracking_mask[mask_0_lo:mask_0_hi, mask_1_lo:mask_1_hi] = 1 if self.dynamic_tracking_mask is True: # TODO: currently dynamic tracking and such only works for square format cameras #print 'dynamic tracking' masked_img = raw[mask_0_lo:mask_0_hi, mask_1_lo:mask_1_hi] masked_background = self.background[mask_0_lo:mask_0_hi, mask_1_lo:mask_1_hi] else: masked_img = raw masked_background = self.background ''' if masked_img.shape[0] < 100 or masked_img.shape[1] < 100: #print 'no uframe' self.dynamic_tracking_mask = False uframe = uFrame() return uframe, None ''' absdiff = nim.absdiff(masked_img, masked_background) if self.dynamic_tracking_mask is False and self.tracking_mask is not None: absdiff *= tracking_mask #absdiff = nim.auto_adjust_levels(absdiff) #print 'shape: ', np.shape(absdiff) #threshold = max( 10, absdiff.max() - THRESHRANGE ) #print 'dynamic threshold: ', threshold #diffthresh = nim.threshold(absdiff, threshold) #print 'max absdiff: ', absdiff.max() diffthresh = nim.threshold(absdiff, 15, threshold_hi=255) # abort early if there is no info: s = np.sum(diffthresh) if s < 10: uframe = uFrame() #print 'no uframe, early abort, sum: ', s self.dynamic_tracking_mask = False return uframe, None blobs = nim.find_blobs(diffthresh, self.blob_size_range) if blobs is None: self.dynamic_tracking_mask = False masked_img = raw masked_background = self.background absdiff = nim.absdiff(masked_img, masked_background) diffthresh = nim.threshold(absdiff, threshold) if self.dynamic_tracking_mask is False and self.tracking_mask is not None: diffthresh *= tracking_mask blobs = nim.find_blobs(diffthresh, self.blob_size_range) if blobs is None: uframe = uFrame() if save_raw is False: #print 'no uframe' self.dynamic_tracking_mask = False return uframe, None else: frame = Frame(raw, absdiff, diffthresh) return uframe, frame nblobs = blobs.max() #print 'n blobs: ', nblobs if nblobs > 1: blobs = nim.find_biggest_blob(blobs) center = nim.center_of_blob(blobs) #print 'center: ', center if np.isnan(center)[0] or np.isnan(center)[1]: uframe = uFrame() #print 'no uframe, NaN center!' self.dynamic_tracking_mask = False return uframe, None if center[0] < 1 or center[1] < 1: uframe = uFrame() #print 'no uframe, NaN center!' self.dynamic_tracking_mask = False return uframe, None #print 'center found' if 1: limlo_x = max( int(center[0])-ROI_RADIUS, 0 ) limlo_y = max( int(center[1])-ROI_RADIUS, 0 ) limhi_x = min( int(center[0])+ROI_RADIUS, masked_img.shape[0] ) limhi_y = min( int(center[1])+ROI_RADIUS, masked_img.shape[1] ) # TODO: right now object entering or leaving frame doesnt work perfectly uimg = masked_img[limlo_x:limhi_x, limlo_y:limhi_y] uimg = copy.copy(uimg) uimg_absdiff = absdiff[limlo_x:limhi_x, limlo_y:limhi_y] uimg_absdiff = copy.copy(uimg_absdiff) uimg_diffthresh = blobs[limlo_x:limhi_x, limlo_y:limhi_y] uimg_diffthresh = copy.copy(uimg_diffthresh) if self.dynamic_tracking_mask is True: tmp = np.array([masked_img.shape[0]/2., masked_img.shape[1]/2.]) center = np.array(self.mask_center) + np.array(center) - tmp uimg_indices = [mask_0_lo+limlo_x, mask_0_lo+limhi_x, mask_1_lo+limlo_y, mask_1_lo+limhi_y] else: uimg_indices = [limlo_x, limhi_x, limlo_y, limhi_y] self.dynamic_tracking_mask = True self.mask_center = center uframe = uFrame(center, uimg, uimg_absdiff, uimg_diffthresh) uframe.blobsize = blobs.sum() uframe.indices = uimg_indices if save_raw is False: del(raw) del(absdiff) del(diffthresh) del(blobs) return uframe, None frame = Frame(masked_img, absdiff, diffthresh) return uframe, frame
def calc_saccades_z(trajec, threshold_lo=200, threshold_hi=100000000, min_angle=10, plot=False): # thresholds in deg/sec # min_angle = minimum angle necessary to count as a saccade, deg fps = 100. heading_norollover_for_axes = floris_math.remove_angular_rollover(np.arctan2(trajec.speed_xy[:], trajec.velocities[:,2]), 3) ## kalman data = heading_norollover_for_axes.reshape([len(heading_norollover_for_axes),1]) ss = 3 # state size os = 1 # observation size F = np.array([ [1,1,0], # process update [0,1,1], [0,0,1]], dtype=np.float) H = np.array([ [1,0,0]], # observation matrix dtype=np.float) Q = np.eye(ss) # process noise Q[0,0] = .01 Q[1,1] = .01 Q[2,2] = .01 R = 1*np.eye(os) # observation noise initx = np.array([data[0,0], data[1,0]-data[0,0], 0], dtype=np.float) initv = 0*np.eye(ss) xsmooth,Vsmooth = kalman_math.kalman_smoother(data, F, H, Q, R, initx, initv, plot=False) heading_norollover_smooth_for_axes = xsmooth[:,0] heading_smooth_diff_for_axes = xsmooth[:,1]*trajec.fps heading_for_axes = floris_math.fix_angular_rollover(heading_norollover_for_axes) heading_smooth_for_axes = floris_math.fix_angular_rollover(heading_norollover_smooth_for_axes) trajec.heading_altitude_smooth = heading_smooth_for_axes trajec.heading_altitude_smooth_diff = heading_smooth_diff_for_axes ## saccades possible_saccade_array = (np.abs(trajec.heading_altitude_smooth_diff)*180/np.pi > threshold_lo)*(np.abs(trajec.heading_altitude_smooth_diff)*180/np.pi < threshold_hi) possible_saccades = nim.find_blobs(possible_saccade_array, [3,100]) if len(possible_saccades) == 1: if np.sum(possible_saccades[0]) == 0: possible_saccades = [] trajec.saccades_z = [] if len(possible_saccades) > 0: for sac in possible_saccades: indices = np.where(sac==1)[0].tolist() if len(indices) > 0: # expand saccade range to make sure we get full turn #lo = np.max([indices[0]-5, 0]) #hi = np.min([indices[-1]+5, len(trajec.speed)-2]) #new_indices = np.arange(lo, hi).tolist() #tmp = np.where( np.abs(trajec.heading_diff_window[new_indices])*180/np.pi > 350 )[0].tolist() #indices = np.array(new_indices)[ tmp ].tolist() angle_of_saccade = np.abs(get_angle_of_saccade_z(trajec, indices)*180./np.pi) mean_speed = np.mean(trajec.speed[indices]) if len(indices) > 3 and angle_of_saccade > 10: # and mean_speed > 0.005: trajec.saccades_z.append(indices) if plot: fig = plt.figure() ax = fig.add_subplot(111) ax.plot(trajec.positions[:,0], trajec.positions[:,2], color='black') for sac in trajec.saccades_z: ax.plot(trajec.positions[sac,0], trajec.positions[sac,2], color='red')