@@ -105,7 +105,9 @@ def constant_reaction_time(eid, rt, st,stype='stim'):
105105 wheelMoves = one .load_object (eid , 'wheelMoves' )
106106 trials = one .load_object (eid , 'trials' )
107107 d = {} # dictionary, trial number and still interval
108-
108+ evts = ['goCue_times' , 'feedback_times' , 'probabilityLeft' ,
109+ 'choice' , 'feedbackType' ]
110+
109111 for tr in range (len (trials ['intervals' ])):
110112 if stype == 'motion' :
111113 a = wheelMoves ['intervals' ][:,0 ]
@@ -115,9 +117,10 @@ def constant_reaction_time(eid, rt, st,stype='stim'):
115117 pl = trials ['probabilityLeft' ][tr ]
116118 ft = trials ['feedbackType' ][tr ]
117119
118- if np .isnan (c ):
119- #print(f'feedback time is nan for trial {tr} and eid {eid}')
120- continue
120+
121+ if any (np .isnan ([trials [k ][tr ] for k in evts ])):
122+ continue
123+
121124
122125 if c - b > 10 : # discard too long trials
123126 continue
@@ -270,10 +273,10 @@ def get_mean_positions(XYs):
270273 return mloc
271274
272275
273- def plot_paw_on_image (eid , video_type , XYs = None ):
276+ def plot_paw_on_image (eid , video_type = 'left' , XYs = None ):
274277
275278 #fig = plt.figure(figsize=(8,4))
276- k = 1
279+
277280
278281 Cs_l = {'paw_l' :'r' ,'paw_r' :'cyan' }
279282 Cs_r = {'paw_l' :'cyan' ,'paw_r' :'r' }
@@ -286,54 +289,64 @@ def plot_paw_on_image(eid, video_type, XYs = None):
286289 r = np .load (f'/home/mic/reproducible_dlc/example_images/'
287290 f'{ eid } _{ video_type } .npy' )[0 ]
288291
289-
290- if XYs == None :
291- _ , XYs = get_dlc_XYs (eid , video_type )
292- #ax = plt.subplot(1,2,k)
293-
294-
295- ds = {'body' :3 ,'left' :6 ,'right' :15 }
296-
297- if video_type == 'left' :
298- Cs = Cs_l
299- else :
300- Cs = Cs_r
301292
302- for point in XYs :# ['paw_l','paw_r']:
303- if point in ['tube_bottom' , 'tube_top' ]:
304- continue
305-
306- # downsample; normalise number of points to be the same
307- # across all sessions
308- xs = XYs [point ][0 ][0 ::ds [video_type ]]
309- ys = XYs [point ][1 ][0 ::ds [video_type ]]
310-
311- plt .scatter (xs ,ys , alpha = 0.05 , s = 2 ,
312- label = point )#, color = Cs[point])
313-
314- # plot whisker pad rectangle
315- mloc = get_mean_positions (XYs )
316- p_nose = np .array (mloc ['nose_tip' ])
317- p_pupil = np .array (mloc ['pupil_top_r' ])
318-
319- # heuristic to find whisker area in side videos:
320- # square with side length half the distance
321- # between nose and pupil and anchored on midpoint
322-
323- p_anchor = np .mean ([p_nose ,p_pupil ],axis = 0 )
324- squared_dist = np .sum ((p_nose - p_pupil )** 2 , axis = 0 )
325- dist = np .sqrt (squared_dist )
326- whxy = [int (dist / 2 ), int (dist / 3 ),
327- int (p_anchor [0 ] - dist / 4 ), int (p_anchor [1 ])]
328-
329- rect = patches .Rectangle ((whxy [2 ], whxy [3 ]), whxy [0 ], whxy [1 ], linewidth = 1 ,
330- edgecolor = 'lime' , facecolor = 'none' )
331- ax = plt .gca ()
332- ax .add_patch (rect )
333- plt .imshow (r ,cmap = 'gray' )
334- plt .axis ('off' )
335- k += 1
336- plt .tight_layout ()
293+ try :
294+ if XYs == None :
295+ _ , XYs = get_dlc_XYs (eid , video_type )
296+
297+
298+
299+ ds = {'body' :3 ,'left' :6 ,'right' :15 }
300+
301+ if video_type == 'left' :
302+ Cs = Cs_l
303+ else :
304+ Cs = Cs_r
305+
306+ for point in XYs :# ['paw_l','paw_r']:
307+ if point in ['tube_bottom' , 'tube_top' ]:
308+ continue
309+
310+ # downsample; normalise number of points to be the same
311+ # across all sessions
312+ xs = XYs [point ][0 ][0 ::ds [video_type ]]
313+ ys = XYs [point ][1 ][0 ::ds [video_type ]]
314+
315+ plt .scatter (xs ,ys , alpha = 0.05 , s = 2 ,
316+ label = point )#, color = Cs[point])
317+
318+ # plot whisker pad rectangle
319+ mloc = get_mean_positions (XYs )
320+ p_nose = np .array (mloc ['nose_tip' ])
321+ p_pupil = np .array (mloc ['pupil_top_r' ])
322+
323+ # heuristic to find whisker area in side videos:
324+ # square with side length half the distance
325+ # between nose and pupil and anchored on midpoint
326+
327+ p_anchor = np .mean ([p_nose ,p_pupil ],axis = 0 )
328+ squared_dist = np .sum ((p_nose - p_pupil )** 2 , axis = 0 )
329+ dist = np .sqrt (squared_dist )
330+ whxy = [int (dist / 2 ), int (dist / 3 ),
331+ int (p_anchor [0 ] - dist / 4 ), int (p_anchor [1 ])]
332+
333+ rect = patches .Rectangle ((whxy [2 ], whxy [3 ]), whxy [0 ], whxy [1 ], linewidth = 1 ,
334+ edgecolor = 'lime' , facecolor = 'none' )
335+ ax = plt .gca ()
336+ ax .add_patch (rect )
337+
338+ plt .axis ('off' )
339+ plt .tight_layout ()
340+ plt .imshow (r ,cmap = 'gray' )
341+ plt .tight_layout ()
342+ except :
343+
344+ plt .imshow (r ,cmap = 'gray' )
345+ ax = plt .gca ()
346+ plt .text (.5 , .5 ,'DLC is nan' ,color = 'r' ,fontweight = 'bold' ,
347+ bbox = dict (facecolor = 'white' , alpha = 0.5 ),
348+ fontsize = 10 ,transform = ax .transAxes )
349+ plt .tight_layout ()
337350 #plt.show()
338351 #plt.legend(loc='lower right')
339352
@@ -560,13 +573,39 @@ def plot_licks(eid, combine=False):
560573 plt .xlabel ('time [sec]' )
561574 plt .ylabel ('lick events \n [a.u.]' )
562575 plt .legend (loc = 'lower right' )
563- return licks_pos
576+
564577
565578
566- def lick_raster (licks_pos ):
579+ def lick_raster (eid ):
567580
568581 #plt.figure(figsize=(4,4))
569582
583+ T_BIN = 0.02
584+ rt = 2
585+ st = - 0.5
586+ times , XYs = get_dlc_XYs (eid , 'left' )
587+ lick_times = times [get_licks (XYs )]
588+
589+ R , t , _ = bincount2D (lick_times , np .ones (len (lick_times )), T_BIN )
590+ D = R [0 ]
591+
592+ # that's centered at feedback time
593+ d = constant_reaction_time (eid , rt , st ,stype = 'feedback' )
594+
595+ licks_pos = []
596+ licks_neg = []
597+
598+ for i in d :
599+
600+ start_idx = find_nearest (t ,d [i ][0 ])
601+ end_idx = start_idx + int (d [i ][1 ]/ T_BIN )
602+
603+ # split by feedback type)
604+ if d [i ][5 ] == 1 :
605+ licks_pos .append (D [start_idx :end_idx ])
606+
607+ licks_pos_ = np .array (licks_pos ).mean (axis = 0 )
608+
570609 y_dims , x_dims = len (licks_pos ), len (licks_pos [0 ])
571610 plt .imshow (licks_pos ,aspect = 'auto' , extent = [- 0.5 ,1.5 ,y_dims ,0 ],
572611 cmap = 'gray_r' )
@@ -615,23 +654,21 @@ def plot_wheel_position(eid):
615654 end_idx = start_idx + int (d [i ][1 ]/ T_BIN )
616655
617656 wheel_pos = pos [start_idx :end_idx ]
657+ if len (wheel_pos ) == 1 :
658+ print (i , [start_idx ,end_idx ])
659+
618660 wheel_pos = wheel_pos - wheel_pos [0 ]
619661
620662 if d [i ][4 ] == - 1 :
621663 whe_left .append (wheel_pos )
622664 if d [i ][4 ] == 1 :
623665 whe_right .append (wheel_pos )
624666
625-
626- # times = np.arange(len(whe_left[0]))*T_BIN
627- #
628- # return times
629667 xs = np .arange (len (whe_left [0 ]))* T_BIN
630668 times = np .concatenate ([
631669 - 1 * np .array (list (reversed (xs [:int (len (xs )* abs (st / rt ))]))),
632670 np .array (xs [:int (len (xs )* (1 - abs (st / rt )))])])
633-
634-
671+
635672
636673 for i in range (len (whe_left )):
637674 plt .plot (times , whe_left [i ],c = '#1f77b4' , alpha = 0.5 , linewidth = 0.05 )
@@ -960,8 +997,6 @@ def pupil_diameter_PSTH(eid, s=None, times=None):
960997 plt .legend (loc = 'lower right' )
961998
962999
963-
964-
9651000def motion_energy_PSTH (eid ):
9661001
9671002 '''
@@ -1051,7 +1086,6 @@ def motion_energy_PSTH(eid):
10511086 except :
10521087 plt .title ('No motion energy available!' )
10531088
1054-
10551089
10561090def interp_nans (y ):
10571091
@@ -1078,48 +1112,60 @@ def plot_all(eid):
10781112 matplotlib .rcParams .update ({'font.size' : 10 })
10791113 # report eid = '4a45c8ba-db6f-4f11-9403-56e06a33dfa4'
10801114
1115+ panels = {'plot_paw_on_image' :plot_paw_on_image ,
1116+ 'plot_wheel_position' :plot_wheel_position ,
1117+ 'paw_speed_PSTH' :paw_speed_PSTH ,
1118+ 'plot_licks' :plot_licks ,
1119+ 'lick_raster' :lick_raster ,
1120+ 'nose_speed_PSTH' :nose_speed_PSTH ,
1121+ 'pupil_diameter_PSTH' :pupil_diameter_PSTH ,
1122+ 'motion_energy_PSTH' :motion_energy_PSTH }
1123+
10811124 nrows = 2
10821125 ncols = 4
10831126
10841127 plt .ioff ()
1085- one = ONE ()
1086- plt .figure (figsize = (15 ,10 ))
1087- plt .subplot (nrows ,ncols ,1 )
1088- add_panel_letter (1 )
1089- plot_paw_on_image (eid , 'left' )
1090- # p = one.path_from_eid(eid)
1091- # plt.title(' '.join([str(p).split('/')[i] for i in [5,7,8,9]]),
1092- # backgroundcolor= 'white')
1093-
1094- plt .subplot (nrows ,ncols ,2 )
1095- add_panel_letter (2 )
1096- #plot_paw_on_image(eid, 'right')
1097- plot_wheel_position (eid )
1098- plt .subplot (nrows ,ncols ,3 )
1099- add_panel_letter (3 )
1100- paw_speed_PSTH (eid )
1101- plt .subplot (nrows ,ncols ,4 )
1102- add_panel_letter (4 )
1103- licks_pos = plot_licks (eid )
1104- plt .subplot (nrows ,ncols ,5 )
1105- add_panel_letter (5 )
1106- lick_raster (licks_pos )
1107- plt .subplot (nrows ,ncols ,6 )
1108- add_panel_letter (6 )
1109- nose_speed_PSTH (eid )
1110- plt .subplot (nrows ,ncols ,7 )
1111- add_panel_letter (7 )
1112- pupil_diameter_PSTH (eid )
1113- plt .subplot (nrows ,ncols ,8 )
1114- add_panel_letter (8 )
1115- motion_energy_PSTH (eid )
1116-
1117- #plt.subplot(3,3,9)
1118- #plot_sniffPSTH(eid)
1128+
1129+ plt .figure (figsize = (15 ,10 ))
1130+
1131+ k = 1
1132+ for panel in panels :
1133+ plt .subplot (nrows ,ncols ,k )
1134+ add_panel_letter (k )
1135+ try :
1136+ panels [panel ](eid )
1137+ except :
1138+ ax = plt .gca ()
1139+ plt .text (.5 , .5 ,f'error in \n { panel } ' ,color = 'r' ,fontweight = 'bold' ,
1140+ bbox = dict (facecolor = 'white' , alpha = 0.5 ),
1141+ fontsize = 10 , transform = ax .transAxes )
1142+ k += 1
1143+
11191144
11201145 plt .tight_layout ()
1146+
1147+
1148+ # print QC outcome in title and DLC task version
1149+ one = ONE ()
1150+ task = one .alyx .rest ('tasks' , 'list' , session = eid , name = 'EphysDLC' )[0 ]
1151+ det = one .get_details (eid , True )['extended_qc' ]
11211152 p = one .path_from_eid (eid )
1122- plt .suptitle (' ' .join ([str (p ).split ('/' )[i ] for i in [4 ,6 ,7 ,8 ]]),
1153+ s1 = ' ' .join ([str (p ).split ('/' )[i ] for i in [4 ,6 ,7 ,8 ]])
1154+
1155+ qcs = ['task' ,'videoLeft' ,'videoRight' ,'videoBody' ,
1156+ 'dlcLeft' ,'dlcRight' ,'dlcBody' ,'behavior' ]
1157+
1158+ l = []
1159+ for q in qcs :
1160+ try :
1161+ l .append (q + ':' + str (det [q ]))
1162+ except :
1163+ continue
1164+
1165+ s2 = ' ' .join (l )
1166+
1167+
1168+ plt .suptitle (s1 + ' QC ' + s2 + ' ' + 'DLC version: ' + str (task ['version' ]),
11231169 backgroundcolor = 'white' )
11241170 plt .tight_layout ()
11251171 plt .tight_layout ()
@@ -1141,8 +1187,3 @@ def plot_all(eid):
11411187# 'ebe090af-5922-4fcd-8fc6-17b8ba7bad6d',
11421188# '7f6b86f9-879a-4ea2-8531-294a221af5d0']
11431189
1144-
1145-
1146-
1147-
1148-
0 commit comments