def detect_firstbeat(tailbout, direction=10, thresh=10): #detect the frame where the fish carry the first tail beat frame_list = [] for bout in tailbout: frame = 0 boutangle = tail2angles( bout, direction=direction) # extract the tailfits of the bout frames peaks = peakdetector.peakdetold(boutangle, 4) ### parameters!!! for p in peaks[0]: if abs(p[1]) >= thresh: frame = p[0] break for p in peaks[1]: if abs(p[1]) >= thresh: if frame > p[0]: frame = p[0] break frame_list.append(frame) return frame_list
def diffpeaks(tailfit): """Mean # of frames between peaks""" peaks = peakdetector.peakdetold(tail2angles(tailfit), 4) peaks = [p[0] for p in peaks[0] + peaks[1]] val = np.diff(peaks).mean() if not np.isnan(val) and not np.isinf(val): #nan or inf return val else: return 0
def tailfreq_mean_function(tailbout, direction='down', sampling_rate=500): tailfreq_mean = [] for bout in tailbout: nFrames = len(bout) Fs = 1 / float(sampling_rate) boutangle = tail2angles( bout, direction=direction) # extract the tailfits of the bout frames peak = peakdetector.peakdetold(boutangle, 4) ### parameters!!! tailfreq_mean.append((len(peak[0]) + len(peak[1])) / float( (2 * Fs * nFrames))) return tailfreq_mean
tailfreq_mean = [] tailamplitude_mean = [] tailamplitude_max = [] boutduration = [] tailasymmetry = [] tailvigour = [] # parameters calculation! for i, j in zip(indexer, indexer[1:]): ps = tail_points[i:j] nFrames = len(ps) boutangle = tail2angles( ps, direction='left') # extract the tailfits of the bout frames velocity = np.diff(boutangle) peak = peakdetector.peakdetold(boutangle, 4) ### parameters!!! Fs = 1 / float(500) ### parameters!!! 500 for duncan, 300 for dt p = 0 n = 0 for angle in boutangle: if angle >= 0: p += 1 else: n += 1 if abs(max(boutangle)) <= abs(min(boutangle)): tailamplitude_max.append(abs(min(boutangle))) else: tailamplitude_max.append(abs(max(boutangle))) tailamplitude_mean.append(sum(boutangle) / float(len(boutangle)))
def extract_tail_eye_bout(eyes,vel, tailfits, Fs, bout_thresh, peakthres): # --------------------- READ TAILFITS ----------------------------------- shv = shelve.open(tailfits) print shv if shv: tailfit = shv[shv.keys()[0]].tailfit shv.close() tailfit = normalizetailfit(tailfit) tailangle = -(tail2angles(tailfit)) boutedges, var = extractbouts(tailangle, bout_thresh) # --------------------- READ EYE ANGLES ----------------------------------- LeftEye = eyes[0]['LeftEye'] RightEye = eyes[0]['RightEye'] LeftVel = vel[0]['LeftVel'] RightVel = vel[0]['RightVel'] filename = eyes[0]['filename'] # --------------------- EXTRACT TAIL BOUTS ----------------------------------- bouts = [] for bout in boutedges: # if boutacceptable(tailfit[bout[0]:bout[1]]): # tag bouts += [{'tail': tailfit[bout[0]:bout[1]], 'frames': [bout[0], bout[1]]}] ''' bout_angles = [] left_eyeangles = [] right_eyeangles = [] tailfreq = [] peaks=[] ''' sum_eyes = map(add, LeftEye, RightEye) taileye = [] ''' if not bouts: taileye += [{'tail': tailangle, 'left': LeftEye, 'right': RightEye, 'sum_eyes': sum_eyes, 'LeftVel': LeftVel, 'RightVel': RightVel, 'filename': filename, 'no_bouts': [1]}] ''' # else: for i in range(len(bouts)): nFrames = len(bouts[i]['tail']) # frames = bouts[i]['tail'] # print bouts[i]['frames'][0] left_eyeangle = LeftEye[bouts[i]['frames'][0]:bouts[i]['frames'][1]] right_eyeangle = RightEye[bouts[i]['frames'][0]:bouts[i]['frames'][1]] left_vel = LeftVel[bouts[i]['frames'][0]:bouts[i]['frames'][1]] right_vel = RightVel[bouts[i]['frames'][0]:bouts[i]['frames'][1]] left_eyeangle_delay = LeftEye[(bouts[i]['frames'][0] - 50):bouts[i]['frames'][1]] right_eyeangle_delay = RightEye[(bouts[i]['frames'][0] - 50):bouts[i]['frames'][1]] left_vel_delay = LeftVel[(bouts[i]['frames'][0] - 50):bouts[i]['frames'][1]] right_vel_delay = RightVel[(bouts[i]['frames'][0] - 50):bouts[i]['frames'][1]] sum_eyeangles = map(add, left_eyeangle, right_eyeangle) boutangle = tail2angles(bouts[i]['tail']) # extract the tailfits of the bout frames boutangle = [-1*a for a in boutangle] peak = peakdetector.peakdetold( boutangle, peakthres) # get the number of peaks which tells us about how many tail beats for the bout peak_new = [] # print 'Length of peak: ', len(peak[0]) # print 'Length of frames: ', nFrames # print 'Length of tail: ', len(bouts[i]['tail']) # print 'Length of tail: ', len(bouts[i]['tail']) for item in peak[0]: peak_new.append([boutedges[i][0] + item[0], item[1]]) ''' left_eyeangles.append(left_eyeangle) right_eyeangles.append(right_eyeangle) tailfreq.append(len(peak[0]) / float((Fs * nFrames))) bout_angles.append(boutangle) peaks.append(peak_new) ''' # left_eyeangles = eye angles during bouts # left_eyeangles_delay = eye angles during bouts with delay # sum_eyeangles = sum of eye angles during bouts # sum_eyes = summation of eye angles during the whole trial # left_v = eye velocity during the bout # left_vel_delay = eye velocity during the bout with delay # LeftVel - eye velocity during the whole trial # frames = the initial and last frame of the bout # filename = the filename of the eye files taileye += [{'tail': tailangle, 'bout_angles': boutangle, 'tailfreq': len(peak[0])/(0.0033*nFrames), 'left_eyeangles': left_eyeangle, 'right_eyeangles': right_eyeangle, 'left_eyeangles_delay': left_eyeangle_delay, 'right_eyeangles_delay': right_eyeangle_delay, 'sum_eyeangles': sum_eyeangles, 'left': LeftEye, 'right': RightEye, 'sum_eyes': sum_eyes, 'left_v': left_vel, 'right_v': right_vel, 'LeftVel': LeftVel, 'RightVel': RightVel, 'frames': bouts[i]['frames'], 'filename': filename, 'left_vel_delay': left_vel_delay, 'right_vel_delay': right_vel_delay, 'no_bouts': [0]}] else: print "Tailfit empty" taileye = [] return taileye # bout_angles,tailfreq, left_eyeangles, right_eyeangles
def extract_tail_eye_bout2(eyes,vel, tailangle, Fs, bout_thresh, peakthres, delay): if tailangle: boutedges, var = extractbouts(tailangle, bout_thresh) # --------------------- READ EYE ANGLES ----------------------------------- LeftEye = eyes[0]['LeftEye'] RightEye = eyes[0]['RightEye'] LeftVel = vel[0]['LeftVel'] RightVel = vel[0]['RightVel'] filename = eyes[0]['filename'] # --------------------- EXTRACT TAIL BOUTS ----------------------------------- bouts = [] for bout in boutedges: # if boutacceptable(tailfit[bout[0]:bout[1]]): # tag bouts += [{'tail': tailangle[bout[0]:bout[1]], 'frames': [bout[0], bout[1]]}] sum_eyes = map(add, LeftEye, RightEye) taileye = [] for i in range(len(bouts)): nFrames = len(bouts[i]['tail']) left_eyeangle = LeftEye[bouts[i]['frames'][0]:bouts[i]['frames'][1]] right_eyeangle = RightEye[bouts[i]['frames'][0]:bouts[i]['frames'][1]] left_vel = LeftVel[bouts[i]['frames'][0]:bouts[i]['frames'][1]] right_vel = RightVel[bouts[i]['frames'][0]:bouts[i]['frames'][1]] if delay > bouts[i]['frames'][0]: left_eyeangle_delay = LeftEye[0:bouts[i]['frames'][1]] right_eyeangle_delay = RightEye[0:bouts[i]['frames'][1]] left_vel_delay = LeftVel[0:bouts[i]['frames'][1]] right_vel_delay = RightVel[0:bouts[i]['frames'][1]] else: left_eyeangle_delay = LeftEye[(bouts[i]['frames'][0] - delay):bouts[i]['frames'][1]] right_eyeangle_delay = RightEye[(bouts[i]['frames'][0] - delay):bouts[i]['frames'][1]] left_vel_delay = LeftVel[(bouts[i]['frames'][0] - delay):bouts[i]['frames'][1]] right_vel_delay = RightVel[(bouts[i]['frames'][0] - delay):bouts[i]['frames'][1]] sum_eyeangles = map(add, left_eyeangle, right_eyeangle) boutangle = tailangle[bouts[i]['frames'][0]:bouts[i]['frames'][1]] # extract the tail bouts boutangle = [-1 * a for a in boutangle] peak = peakdetector.peakdetold( boutangle, peakthres) # get the number of peaks which tells us about how many tail beats for the bout peak_new = [] for item in peak[0]: peak_new.append([boutedges[i][0] + item[0], item[1]]) taileye += [{'tail': tailangle, 'bout_angles': boutangle, 'tailfreq': len(peak[0])/(0.0033*nFrames), 'left_eyeangles': left_eyeangle, 'right_eyeangles': right_eyeangle, 'left_eyeangles_delay': left_eyeangle_delay, 'right_eyeangles_delay': right_eyeangle_delay, 'sum_eyeangles': sum_eyeangles, 'left': LeftEye, 'right': RightEye, 'sum_eyes': sum_eyes, 'left_v': left_vel, 'right_v': right_vel, 'LeftVel': LeftVel, 'RightVel': RightVel, 'frames': bouts[i]['frames'], 'filename': filename, 'left_vel_delay': left_vel_delay, 'right_vel_delay': right_vel_delay, 'no_bouts': [0]}] else: print("Tailfit empty") taileye = [] return taileye # bout_angles,tailfreq, left_eyeangles, right_eyeangles
def striking_detection(data, binocular, peak_thresh=0.03, temporal_thresh=15, amplitude_thresh=0.2): # input data has to be an iterate, either list or tuple # peak_thresh is the threshold for detecting peaks in function peakdetector.peakdetold(data,0.15) # temporal_thresh specifies the positive peak has to be within 'temporal_thresh' frames right after negative peaks # amplitude_thresh specifies the value for positive peak has to be 'amplitude_thresh' bigger than the negative peaks peakind = peakdetector.peakdetold(data,peak_thresh) # get the number of peaks which tells us about how many tail beats for the bout # the second number is the threshold, it compares the peaks with neighbor value p_p = peakind[0] #positive peaks n_p = peakind[1] #negative peaks striking_frame = [] for i, p in enumerate(n_p): for sub_i, sub_p in enumerate(p_p): if 0 < p_p[sub_i][0] - n_p[i][0] < temporal_thresh: # temporal threshold! #the positive peak has to be within 'temporal_thresh' frames right after negative peaks if p_p[sub_i][1] - n_p[i][1] > amplitude_thresh: # peak amplitude threshold! #the value for positive peak has to be 'amplitude_thresh' bigger than the negative peaks mid = (p_p[sub_i][0] + n_p[i][0]) / 2 if binocular[mid]>30: #to make sure the binocular eyes convergence is bigger than 30 striking_frame.append((mid, data[mid])) break # just break the inner for loop and go back to the outer for loop # plotting # plt.plot(data) # plt.scatter(np.array(peakind[0])[:, 0],np.array(peakind[0])[:, 1]) # peakind[0] give you the peaks for the positive peaks # plt.scatter(np.array(peakind[1])[:, 0], np.array(peakind[1])[:, 1], c='r',edgecolors='face') # peakind[1] give you the peaks for the positive peaks # plt.show() #detect the the same strike predicted as the 2 frame orginal_striking_frame = striking_frame #save the frame for future reference if len(striking_frame) > 1: for i in range(0, len(striking_frame) - 1): if i >= len(striking_frame)-1: break if striking_frame[i + 1][0] - striking_frame[i][0] < 15: # two strikes can not occur within an interval less than 30 frame during 300Hz sampling mid_x = (striking_frame[i + 1][0] + striking_frame[i][0]) / 2 mid_y = data[mid_x] striking_frame[i] = (mid_x, mid_y) striking_frame.remove(striking_frame[i + 1]) #just do twice to reduce extra close one... if len(striking_frame) > 1: for i in range(0, len(striking_frame) - 1): if i >= len(striking_frame) - 1: break if striking_frame[i + 1][0] - striking_frame[i][0] < 15: # two strikes can not occur within an interval less than 30 frame during 300Hz sampling mid_x = (striking_frame[i + 1][0] + striking_frame[i][0]) / 2 mid_y = data[mid_x] striking_frame[i] = (mid_x, mid_y) striking_frame.remove(striking_frame[i + 1]) # using the following code to give a line plotted on the corresponding striking frame if striking_frame != []: for frame in np.array(striking_frame)[:, 0]: y = np.arange(min(data), max(data), 0.001) x = [] for i in y: x.append(frame) # plt.plot(x, y, 'r') # plt.tight_layout(pad=0.5, w_pad=0.5, h_pad=0.5) # adjust the layout # print np.array(peakind[1][:,0]) return striking_frame, orginal_striking_frame
def tailbeatfreq(input_path, threshval, Fs, peakthres, shv_file = None): # DT added shv_file is the file name of the shv that need to be analyzed, so that the function can go through one shv for each time #the following modification enables this function to read single shv if shv_file != None: shvs = [str(input_path+'\\'+shv_file)] bouts = [] video_list = [] else: ### Load shv files shvs = os.listdir(input_path) shvs = [os.path.join(input_path, shv) for shv in shvs if os.path.splitext(shv)[1] == '.shv'] bouts = [] video_list = [] '''LOAD TAIL-FIT''' for shvname in shvs: # Note. Accroding to the code, shvs should be the dictionary that each value(shvlist) is a tuple of shelve shv = shelve.open(shvname) print 'Currently analyzing ' + str(shvname) # Note. shvs are opened here! for i in [1]: # Note. useless for loop, added to complete the code for video in shv.keys(): video_list.append(video) # Note. shelf should contains several tailfit results for different videos # Note. shv[str(os.path.basename(videopath))]=result, according to the tailfit, video/key of shv should be the videopath # Note. the value of the shv should be tailfitresult, because IT has 'tailfit' as attribute. result = tailfitresult(fittedtail, str(os.path.basename(videopath)),videopath, startpoint, FPS, len(fittedtail), direction, shahash, __version__) if type(shv[video]) is list: # Question. how could the key be a list? print 'enter the 1st if, because type(shv[video]) is list' tailfit = shv[video][0] else: tailfit = shv[video].tailfit # Note. in such scheme, then the shv[video] should definitely be a tailfitresult class, because it has tailfit attribute! # Note. tailfit correspond to fitted_tail, which is the following: # NOTE. CONFIRMED. fitted_tail is the final result of the whole program. # NOTE. CONFIRMED. it is a list, storing arrays with the total number of total frame analyzed/read # NOTE. CONFIRMED. each array corresponds to one frame, storing x number of points (x=tail_lengh/count) # NOTE. CONFIRMED. points is the fitted result_point(mid point of tail edge), it is the coordinate in each frame # NOTE. CONFIRMED. count would be the final number of total circles. '''NORMALIZE & PROCESS TAILFIT ''' lens = np.array([len(i) for i in tailfit]) ### Task. I made a big modification... maybe I should do with display as well to see if the threshold is proper if lens.var() < 4 and lens.mean() > 3: # ensure tailfit quality is good # Note. only do the normalization when the tailfit is good .... # Note. lens.var(), Compute the variance along the specified axis. # STAR-Question. count/tail_length has to be bigger than 30? resolution limit? # Question. in theory, tail_length should be the same for each frame, right? if all(lens > 2): tailfit = normalizetailfit(tailfit) # plt.plot(tailfit[0][:,0],tailfit[0][:,1],'b') # plt.plot(tailfit[700][:,0],tailfit[700][:,1],'r') # plt.show() # Question. What if not normalization. For many estimators, including the SVMs, having datasets with unit standard deviation for each feature is important to get good prediction. angles = tail2angles(tailfit) # Note. Calculate the tail_angle! # Note. this function takes tailfit result, for each frame calculate the vector from the startpoint of fitting to the mean point of fraction of tail end # Note. extract the angles of vectors and store the angle of each frame in the returned list. '''PLOT AND DIVIDE THE BOUTS''' boutedges, var = extractbouts(angles, threshval) # tag print 'the frame range for all the bouts are: ' + str(boutedges) # Note. boutedges are the list storing tuples corresponds to edges of each bout for bout in boutedges: # if boutacceptable(tailfit[bout[0]:bout[1]]): # tag # task. not really sure how this boutacceptable work, delete if first... bouts += [{'tail': tailfit[bout[0]:bout[1]], 'shvname': shvname, 'vidname': video, 'frames': [bout[0], bout[1]]}] # Note. so the bouts I got here should be ... the list contains all the bouts from all shv files... # Note. the bouts edge info is the value of 'frames' tailfreq = [] boutangles = [] peaks = [] Fs = 1 / float(Fs) for i in range(len(bouts)): nFrames = len(bouts[i]['tail']) boutangle = tail2angles(bouts[i]['tail']) # extract the tailfits of the bout frames peak = peakdetector.peakdetold(boutangle, peakthres) # get the number of peaks which tells us about how many tail beats for the bout peak_new = [] for item in peak[0]: peak_new.append([boutedges[i][0]+item[0],item[1]]) tailfreq.append(len(peak[0]) / float((Fs * nFrames))) boutangles.append(boutangle) peaks.append(peak_new) return tailfreq, boutangles, peaks, boutedges, video_list
def numpeaks(tailfit): """Number of peaks in tail angle""" peaks = peakdetector.peakdetold(tail2angles(tailfit), 4) peaks = [p[0] for p in peaks[0] + peaks[1]] return len(peaks)