11import numpy as np
22import alf .io
3- from oneibl .one import ONE
3+ #from oneibl.one import ONE
4+ from one .api import ONE
45from pathlib import Path
56import pandas as pd
67import matplotlib .pyplot as plt
78import matplotlib .image as mpimg
89#os.environ['CUDA_VISIBLE_DEVICES'] = str(gputouse)
910from ibllib .io .video import get_video_meta , get_video_frames_preload
11+ import ibllib .io .video as vidio
1012import brainbox .behavior .wheel as wh
1113import math
1214from brainbox .processing import bincount2D
1618import string
1719from scipy .interpolate import interp1d
1820from scipy .stats import zscore
21+
1922#Generate scatterplots, variances, 2-state AR-HMMs to summarize differences in behavior in different sessions. Develop a 1-page figure per session that provides a behavioral overview. Would be great to generate these figs for the RS sessions noted in repro-ephys slides above
2023#lickogram
2124import matplotlib
2225# https://github.com/lindermanlab/ssm
23-
24-
25-
26+ import os
27+
28+
2629def get_all_sess_with_ME ():
2730 one = ONE ()
2831 # get all bwm sessions with dlc
@@ -157,16 +160,15 @@ def get_dlc_XYs(eid, video_type):
157160
158161 #video_type = 'left'
159162 one = ONE ()
160- dataset_types = ['camera.dlc' , 'camera.times' ]
161- a = one .list (eid ,'dataset-types' )
162- # for newer iblib version do [x['dataset_type'] for x in a]
163- # if not all([(u in [x['dataset_type'] for x in a]) for u in dataset_types]):
164- # print('not all data available')
165- # return
166-
167-
168- one .load (eid , dataset_types = dataset_types ) #clobber=True # force download
169- local_path = one .path_from_eid (eid )
163+ dataset_types = ['alf/_ibl_leftCamera.dlc.pqt' ,
164+ 'alf/_ibl_leftCamera.times.npy' ]
165+
166+ a = one .list_datasets (eid )
167+ if not all ([u in a for u in dataset_types ]):
168+ print ('not all data available' )
169+ return
170+
171+ local_path = one .eid2path (eid )
170172 alf_path = local_path / 'alf'
171173
172174 cam0 = alf .io .load_object (
@@ -175,7 +177,6 @@ def get_dlc_XYs(eid, video_type):
175177 video_type ,
176178 namespace = 'ibl' )
177179
178-
179180 Times = cam0 ['times' ]
180181
181182 cam = cam0 ['dlc' ]
@@ -200,16 +201,15 @@ def get_ME(eid, video_type):
200201
201202 #video_type = 'left'
202203 one = ONE ()
203- dataset_types = ['camera.ROIMotionEnergy' , 'camera.times' ]
204- a = one .list (eid ,'dataset-types' )
205- # for newer iblib version do [x['dataset_type'] for x in a]
206- # if not all([(u in [x['dataset_type'] for x in a]) for u in dataset_types]):
207- # print('not all data available')
208- # return
209-
210-
211- one .load (eid , dataset_types = dataset_types )
212- local_path = one .path_from_eid (eid )
204+ dataset_types = [f'alf/{ video_type } Camera.ROIMotionEnergy.npy' ,
205+ f'alf/_ibl_{ video_type } Camera.times.npy' ]
206+
207+ a = one .list_datasets (eid )
208+ if not all ([u in a for u in dataset_types ]):
209+ print ('not all data available' )
210+ return
211+
212+ local_path = one .eid2path (eid )
213213 alf_path = local_path / 'alf'
214214
215215 cam0 = alf .io .load_object (
@@ -241,17 +241,14 @@ def get_example_images(eid):
241241
242242
243243 #for eid in eids:
244+ urls = vidio .url_from_eid (eid , one = one )
244245 for video_type in frts :
245246
246- frame_idx = [20 * 60 * frts [video_type ]]
247+ frame_idx = [5 * 60 * frts [video_type ]]
247248 try :
248249
249- r = one .list (eid , 'dataset_types' )
250- recs = [x for x in r if f'{ video_type } Camera.raw.mp4'
251- in x ['name' ]][0 ]['file_records' ]
252- video_path = [x ['data_url' ] for x in recs
253- if x ['data_url' ] is not None ][0 ]
254250
251+ video_path = urls [video_type ]
255252 frames = get_video_frames_preload (video_path ,
256253 frame_idx ,
257254 mask = np .s_ [:, :, 0 ])
@@ -276,31 +273,26 @@ def plot_paw_on_image(eid, video_type='left', XYs = None):
276273
277274 #fig = plt.figure(figsize=(8,4))
278275
279-
280- Cs_l = { 'paw_l' : 'r' , 'paw_r' : 'cyan' }
281- Cs_r = { 'paw_l' : 'cyan ' ,'paw_r' : 'r' }
282- #for video_type in ['left','right']:#,'body']:
276+ Cs = [ '#636EFA' , '#EF553B' , '#00CC96' , '#AB63FA' ,
277+ '#FFA15A' , '#19D3F3' , '#FF6692' , '#B6E880' ,
278+ '#FF97FF' , '#FECB52 ' ,'cyan' ]
279+
283280 try :
284281 r = np .load (f'/home/mic/reproducible_dlc/example_images/'
285282 f'{ eid } _{ video_type } .npy' )[0 ]
286283 except :
287284 get_example_images (eid )
288285 r = np .load (f'/home/mic/reproducible_dlc/example_images/'
289286 f'{ eid } _{ video_type } .npy' )[0 ]
290-
291287
292288 try :
293289 if XYs == None :
294290 _ , XYs = get_dlc_XYs (eid , video_type )
295291
296-
292+ Cs = dict ( zip ( XYs . keys (), Cs ))
297293
298294 ds = {'body' :3 ,'left' :6 ,'right' :15 }
299295
300- if video_type == 'left' :
301- Cs = Cs_l
302- else :
303- Cs = Cs_r
304296
305297 for point in XYs :# ['paw_l','paw_r']:
306298 if point in ['tube_bottom' , 'tube_top' ]:
@@ -312,8 +304,9 @@ def plot_paw_on_image(eid, video_type='left', XYs = None):
312304 ys = XYs [point ][1 ][0 ::ds [video_type ]]
313305
314306 plt .scatter (xs ,ys , alpha = 0.05 , s = 2 ,
315- label = point )#, color = Cs[point])
316-
307+ label = point , color = Cs [point ])
308+
309+
317310 # plot whisker pad rectangle
318311 mloc = get_mean_positions (XYs )
319312 p_nose = np .array (mloc ['nose_tip' ])
@@ -329,15 +322,81 @@ def plot_paw_on_image(eid, video_type='left', XYs = None):
329322 whxy = [int (dist / 2 ), int (dist / 3 ),
330323 int (p_anchor [0 ] - dist / 4 ), int (p_anchor [1 ])]
331324
332- rect = patches .Rectangle ((whxy [2 ], whxy [3 ]), whxy [0 ], whxy [1 ], linewidth = 1 ,
333- edgecolor = 'lime' , facecolor = 'none' )
325+ rect = patches .Rectangle ((whxy [2 ], whxy [3 ]), whxy [0 ], whxy [1 ],
326+ linewidth = 1 ,
327+ edgecolor = 'lime' ,
328+ facecolor = 'none' )
334329 ax = plt .gca ()
335330 ax .add_patch (rect )
336331
337332 plt .axis ('off' )
338333 plt .tight_layout ()
339334 plt .imshow (r ,cmap = 'gray' )
340335 plt .tight_layout ()
336+
337+ # plot eye region zoom as inset in upper right corner
338+ pivot = np .nanmean (XYs ['pupil_top_r' ], axis = 1 )
339+ x0 = int (pivot [0 ]) - 33
340+ x1 = int (pivot [0 ]) + 33
341+ y0 = int (pivot [1 ]) - 28
342+ y1 = int (pivot [1 ]) + 38
343+
344+ axins = ax .inset_axes ([0.65 , 0.6 , 0.5 , 0.5 ])
345+ axins .spines ['bottom' ].set_color ('white' )
346+ axins .spines ['top' ].set_color ('white' )
347+ axins .spines ['right' ].set_color ('white' )
348+ axins .spines ['left' ].set_color ('white' )
349+ axins .imshow (r , cmap = 'gray' , origin = "lower" )
350+
351+ for point in XYs :# ['paw_l','paw_r']:
352+ if point in ['tube_bottom' , 'tube_top' ]:
353+ continue
354+
355+ # downsample; normalise number of points to be the same
356+ # across all sessions
357+ xs = XYs [point ][0 ][0 ::ds [video_type ]]
358+ ys = XYs [point ][1 ][0 ::ds [video_type ]]
359+
360+ axins .scatter (xs ,ys , alpha = 0.05 , s = 0.1 ,
361+ label = point , color = Cs [point ])
362+ axins .set_xlim (x0 , x1 )
363+ axins .set_ylim (y1 , y0 )
364+ axins .set_xticklabels ('' )
365+ axins .set_yticklabels ('' )
366+ #ax.indicate_inset_zoom(axins, edgecolor="white")
367+
368+ # plot tongue region zoom as inset in llower right corner
369+ p1 = np .nanmean (XYs ['tube_top' ], axis = 1 )
370+ p2 = np .nanmean (XYs ['tube_bottom' ], axis = 1 )
371+ pivot = np .nanmean ([p1 ,p2 ], axis = 0 )
372+ x0 = int (pivot [0 ]) - 60
373+ x1 = int (pivot [0 ]) + 100
374+ y0 = int (pivot [1 ]) - 100
375+ y1 = int (pivot [1 ]) + 60
376+
377+ axins = ax .inset_axes ([0.65 , 0.1 , 0.5 , 0.5 ])
378+ axins .spines ['bottom' ].set_color ('white' )
379+ axins .spines ['top' ].set_color ('white' )
380+ axins .spines ['right' ].set_color ('white' )
381+ axins .spines ['left' ].set_color ('white' )
382+ axins .imshow (r , cmap = 'gray' , origin = "upper" )
383+
384+ for point in XYs :# ['paw_l','paw_r']:
385+ if point in ['tube_bottom' , 'tube_top' ]:
386+ continue
387+ # downsample; normalise number of points to be the same
388+ # across all sessions
389+ xs = XYs [point ][0 ][0 ::ds [video_type ]]
390+ ys = XYs [point ][1 ][0 ::ds [video_type ]]
391+
392+ axins .scatter (xs ,ys , alpha = 0.05 , s = 0.01 ,
393+ label = point , color = Cs [point ])
394+ axins .set_xlim (x0 , x1 )
395+ axins .set_ylim (y1 , y0 )
396+ axins .set_xticklabels ('' )
397+ axins .set_yticklabels ('' )
398+ #ax.indicate_inset_zoom(axins, edgecolor="white")
399+
341400 except :
342401
343402 plt .imshow (r ,cmap = 'gray' )
@@ -526,13 +585,18 @@ def plot_licks(eid, combine=True):
526585 lick_times = []
527586 for video_type in ['right' ,'left' ]:
528587 times , XYs = get_dlc_XYs (eid , video_type )
529- lick_times .append (times [get_licks (XYs )])
588+ # for the case that there are less times than DLC points
589+ r = get_licks (XYs )
590+ idx = np .where (np .array (r )< len (times ))[0 ][- 1 ]
591+ lick_times .append (times [r [:idx ]])
530592
531593 lick_times = sorted (np .concatenate (lick_times ))
532594
533595 else :
534596 times , XYs = get_dlc_XYs (eid , 'left' )
535- lick_times = times [get_licks (XYs )]
597+ r = get_licks (XYs )
598+ idx = np .where (np .array (r )< len (times ))[0 ][- 1 ]
599+ lick_times = times [r [:idx ]]
536600
537601
538602 R , t , _ = bincount2D (lick_times , np .ones (len (lick_times )), T_BIN )
@@ -591,13 +655,17 @@ def lick_raster(eid, combine=True):
591655 lick_times = []
592656 for video_type in ['right' ,'left' ]:
593657 times , XYs = get_dlc_XYs (eid , video_type )
594- lick_times .append (times [get_licks (XYs )])
658+ r = get_licks (XYs )
659+ idx = np .where (np .array (r )< len (times ))[0 ][- 1 ]
660+ lick_times .append (times [r [:idx ]])
595661
596662 lick_times = sorted (np .concatenate (lick_times ))
597663
598664 else :
599665 times , XYs = get_dlc_XYs (eid , 'left' )
600- lick_times = times [get_licks (XYs )]
666+ r = get_licks (XYs )
667+ idx = np .where (np .array (r )< len (times ))[0 ][- 1 ]
668+ lick_times = times [r [:idx ]]
601669
602670 R , t , _ = bincount2D (lick_times , np .ones (len (lick_times )), T_BIN )
603671 D = R [0 ]
@@ -960,7 +1028,7 @@ def non_uniform_savgol(x, y, window, polynom):
9601028
9611029
9621030
963- def pupil_diameter_PSTH (eid , s = None , times = None ):
1031+ def pupil_diameter_PSTH (eid , s = None , times = None , per_trial_norm = True ):
9641032
9651033 '''
9661034 nose speed PSTH
@@ -993,9 +1061,18 @@ def pupil_diameter_PSTH(eid, s=None, times=None):
9931061 for i in d :
9941062
9951063 start_idx = find_nearest (times ,d [i ][0 ])
996- end_idx = start_idx + rt * 60
997-
998- D [stype ].append (s [start_idx :end_idx ])
1064+ end_idx = start_idx + rt * 60
1065+
1066+ if per_trial_norm :
1067+ # per trial baseline - at start = 0
1068+ dia = s [start_idx :end_idx ]
1069+ dia = zscore (dia ,nan_policy = 'omit' )
1070+ dia = dia - dia [0 ]
1071+ else :
1072+ dia = s [start_idx :end_idx ]
1073+
1074+
1075+ D [stype ].append (dia )
9991076
10001077
10011078 MEAN = np .mean (D [stype ],axis = 0 )
@@ -1140,7 +1217,7 @@ def plot_all(eid):
11401217 nrows = 2
11411218 ncols = 4
11421219
1143- # plt.ioff()
1220+ plt .ioff ()
11441221
11451222 plt .figure (figsize = (15 ,10 ))
11461223
@@ -1202,10 +1279,44 @@ def plot_all(eid):
12021279
12031280 plt .suptitle (s1 + ', DLC version: ' + str (task ['version' ])+ ' \n ' + s2 ,
12041281 backgroundcolor = 'white' , fontsize = 6 )
1205- plt .tight_layout (rect = [0 , 0.03 , 1 , 0.95 ])
1206- #plt.tight_layout()
1207- plt .savefig (f'/home/mic/reproducible_dlc/overviewJune /{ eid } .png' )
1282+ plt .tight_layout (rect = [0 , 0.03 , 1 , 0.95 ])
1283+ #plt.savefig(f'/home/mic/reproducible_dlc/overviewJune/{eid}.png')
1284+ plt .savefig (f'/home/mic/reproducible_dlc/all_DLC /{ eid } .png' )
12081285 plt .close ()
12091286
12101287
1288+ def inspection ():
1289+ '''
1290+ go through computed png images
1291+ to report QC issues
1292+ '''
1293+ one = ONE ()
1294+ a = os .listdir ('/home/mic/reproducible_dlc/overviewJune/' )
1295+
1296+ for i in a :
1297+ plt .figure (figsize = (15 ,10 ))
1298+ eid = i .split ('.' )[0 ]
1299+ p = one .path_from_eid (eid )
1300+ s1 = '/' .join ([str (p ).split ('/' )[i ] for i in [4 ,5 ,6 ,7 ,8 ]])
1301+ print (s1 )
1302+ print (eid )
1303+ img = mpimg .imread ('/home/mic/reproducible_dlc/overviewJune/' + i )
1304+ plt .imshow (img )
1305+ plt .tight_layout ()
1306+ plt .show ()
1307+ input ("Press Enter to continue..." )
1308+ plt .close ()
1309+
1310+
1311+ def get_all_sess_with_ME ():
1312+ one = ONE ()
1313+ # get all bwm sessions with dlc
1314+ all_sess = one .alyx .rest ('sessions' , 'list' ,
1315+ project = 'ibl_neuropixel_brainwide_01' ,
1316+ task_protocol = "ephys" ,
1317+ dataset_types = 'camera.ROIMotionEnergy' )
1318+
1319+ eids = [s ['url' ].split ('/' )[- 1 ] for s in all_sess ]
12111320
1321+ return eids
1322+
0 commit comments