From bed4c7f7d0e769735c65101acbb18920cd6818c7 Mon Sep 17 00:00:00 2001 From: mschart Date: Tue, 12 Oct 2021 12:33:45 +0100 Subject: [PATCH 1/7] update one2, replace load mp4 method --- dlc/DLC_labeled_video.py | 163 ++++++++++++++------------------------- 1 file changed, 58 insertions(+), 105 deletions(-) diff --git a/dlc/DLC_labeled_video.py b/dlc/DLC_labeled_video.py index 3f87da0..4178cc7 100644 --- a/dlc/DLC_labeled_video.py +++ b/dlc/DLC_labeled_video.py @@ -1,14 +1,26 @@ import numpy as np -import alf.io -from oneibl.one import ONE +from one.api import ONE from pathlib import Path import cv2 -import os -from oneibl.webclient import http_download_file_list +import os,fnmatch import matplotlib import pandas as pd # conda install -c conda-forge pyarrow +import os + +def Find(pattern, path): + ''' + find a local video like so: + flatiron='/home/mic/Downloads/FlatIron' + vids = Find('*.mp4', flatiron) + ''' + result = [] + for root, dirs, files in os.walk(path): + for name in files: + if fnmatch.fnmatch(name, pattern): + result.append(os.path.join(root, name)) + return result def find_nearest(array, value): array = np.asarray(array) @@ -16,51 +28,12 @@ def find_nearest(array, value): return idx -def download_raw_video(eid, cameras=None): - """ - Downloads the raw video from FlatIron or cache dir. - This allows you to download just one of the - three videos - :param cameras: the specific camera to load - (i.e. 'left', 'right', or 'body') If None all - three videos are downloaded. - :return: the file path(s) of the raw videos - """ - one = ONE() - if cameras: - cameras = [cameras] if isinstance(cameras, str) else cameras - cam_files = ['_iblrig_{}Camera.raw.mp4'.format(cam) for cam in cameras] - datasets = one._alyxClient.get( - 'sessions/' + eid)['data_dataset_session_related'] - urls = [ds['data_url'] for ds in datasets if ds['name'] in cam_files] - cache_dir = one.path_from_eid(eid).joinpath('raw_video_data') - if not os.path.exists(str(cache_dir)): - os.mkdir(str(cache_dir)) - else: # Check if file already downloaded - # cam_files = [fi[:-4] for fi in cam_files] # Remove ext - filenames = [f for f in os.listdir(str(cache_dir)) - if any([cam in f for cam in cam_files])] - if filenames: - return [cache_dir.joinpath(file) for file in filenames] - - http_download_file_list( - urls, - username=one._par.HTTP_DATA_SERVER_LOGIN, - password=one._par.HTTP_DATA_SERVER_PWD, - cache_dir=str(cache_dir)) - - return - - else: - return one.load(eid, ['_iblrig_Camera.raw'], download_only=True) - - def Viewer(eid, video_type, trial_range, save_video=True, eye_zoom=False): ''' eid: session id, e.g. '3663d82b-f197-4e8b-b299-7b803a155b84' video_type: one of 'left', 'right', 'body' trial_range: first and last trial number of range to be shown, e.g. [5,7] - save_video: video is displayed and saved in local folder + save_video: video is saved this local folder Example usage to view and save labeled video with wheel angle: Viewer('3663d82b-f197-4e8b-b299-7b803a155b84', 'left', [5,7]) @@ -72,47 +45,33 @@ def Viewer(eid, video_type, trial_range, save_video=True, eye_zoom=False): return 'Last character of save_vids_here must be slash' one = ONE() - dataset_types = ['camera.times', - 'wheel.position', - 'wheel.timestamps', - 'trials.intervals', - 'camera.dlc'] - - a = one.list(eid, 'dataset-types') - - assert all([i in a for i in dataset_types] - ), 'For this eid, not all data available' - - D = one.load(eid, dataset_types=dataset_types, dclass_output=True) - alf_path = Path(D.local_path[0]).parent.parent / 'alf' + alf_path = one.eid2path(eid) # Download a single video - video_data = alf_path.parent / 'raw_video_data' - download_raw_video(eid, cameras=[video_type]) - video_path = list( - video_data.rglob( - '_iblrig_%sCamera.raw.*' % - video_type))[0] - print(video_path) - - # that gives cam time stamps and DLC output (change to alf_path eventually) - - cam = alf.io.load_object( - alf_path, - '%sCamera' % - video_type, - namespace='ibl') - - # just to read in times for newer data (which has DLC results in pqt format - # cam = alf.io.load_object(alf_path, '_ibl_%sCamera' % video_type) - - # set where to read and save video and get video info + video_path = (alf_path / + f'raw_video_data/_iblrig_{video_type}Camera.raw.mp4') + + if not os.path.isfile(video_path): + print('mp4 not found locally, downloading it ...') + video_path = one.load_dataset(eid, + f'raw_video_data/_iblrig_{video_type}Camera.raw.mp4', + download_only=True) + + # Get trials info + trials = one.load_object(eid, 'trials', download_only=True) + + + # Download DLC traces and stamps + Times = one.load_dataset(eid,f'alf/_ibl_{video_type}Camera.times.npy') + cam = one.load_dataset(eid,f'alf/_ibl_{video_type}Camera.dlc.pqt') + + # get video info cap = cv2.VideoCapture(video_path.as_uri()) length = int(cap.get(cv2.CAP_PROP_FRAME_COUNT)) fps = cap.get(cv2.CAP_PROP_FPS) size = (int(cap.get(3)), int(cap.get(4))) - assert length < len(cam['times']), '#frames > #stamps' + print(eid, ', ', video_type, @@ -121,26 +80,26 @@ def Viewer(eid, video_type, trial_range, save_video=True, eye_zoom=False): ', #frames:', length, ', #stamps:', - len(cam['times']), + len(Times), ', #frames - #stamps = ', - length - len(cam['times'])) + length - len(Times)) # pick trial range for which to display stuff - trials = alf.io.load_object(alf_path, 'trials', namespace='ibl') + trials = one.load_object(eid, 'trials') num_trials = len(trials['intervals']) if trial_range[-1] > num_trials - 1: print('There are only %s trials' % num_trials) - - frame_start = find_nearest(cam['times'], + print('There are %s trials' % num_trials) + frame_start = find_nearest(Times, [trials['intervals'][trial_range[0]][0]]) - frame_stop = find_nearest(cam['times'], + frame_stop = find_nearest(Times, [trials['intervals'][trial_range[-1]][1]]) ''' - wheel related stuff + load wheel ''' - wheel = alf.io.load_object(alf_path, 'wheel', namespace='ibl') + wheel = one.load_object(eid, 'wheel') import brainbox.behavior.wheel as wh try: pos, t = wh.interpolate_position( @@ -159,7 +118,7 @@ def Viewer(eid, video_type, trial_range, save_video=True, eye_zoom=False): # alignment of cam stamps and interpolated wheel stamps wheel_pos = [] kk = 0 - for wt in cam['times'][frame_start:frame_stop]: + for wt in Times[frame_start:frame_stop]: wheel_pos.append(pos_int[find_nearest(t_int, wt)]) kk += 1 if kk % 3000 == 0: @@ -168,26 +127,14 @@ def Viewer(eid, video_type, trial_range, save_video=True, eye_zoom=False): ''' DLC related stuff ''' - Times = cam['times'][frame_start:frame_stop] - del cam['times'] + Times = Times[frame_start:frame_stop] # some exception for inconsisitent data formats - try: - dlc_name = '_ibl_%sCamera.dlc.pqt' % video_type - dlc_path = alf_path / dlc_name - cam = pd.read_parquet(dlc_path, engine="fastparquet") - print('it is pqt') - except BaseException: - raw_vid_path = alf_path.parent / 'raw_video_data' - cam = alf.io.load_object( - raw_vid_path, - '%sCamera' % - video_type, - namespace='ibl') + + points = np.unique(['_'.join(x.split('_')[:-1]) for x in cam.keys()]) if len(points) == 1: - cam = cam['dlc'] points = np.unique(['_'.join(x.split('_')[:-1]) for x in cam.keys()]) if video_type != 'body': @@ -319,14 +266,17 @@ def Viewer(eid, video_type, trial_range, save_video=True, eye_zoom=False): # col = np.array([0, 0, 255]) # all points red X = X.astype(int) Y = Y.astype(int) +# cv2.imshow('frame', gray) +# print(gray.shape) +# print(X - dot_s,X + dot_s, Y - dot_s,Y + dot_s) gray[X - dot_s:X + dot_s, Y - dot_s:Y + dot_s] = block * col ll += 1 gray = gray[y0:y1, x0:x1] if save_video: out.write(gray) - cv2.imshow('frame', gray) - cv2.waitKey(1) + #cv2.imshow('frame', gray) + #cv2.waitKey(1) k += 1 if k == (frame_stop - frame_start) - 1: break @@ -334,4 +284,7 @@ def Viewer(eid, video_type, trial_range, save_video=True, eye_zoom=False): if save_video: out.release() cap.release() - cv2.destroyAllWindows() + #cv2.destroyAllWindows() + + print(eid, video_type, frame_stop, frame_start) + #return XYs, Times From 156e48fef6eec7ccb5ac8f0aa6b851581b8707b0 Mon Sep 17 00:00:00 2001 From: mschart Date: Tue, 12 Oct 2021 12:37:59 +0100 Subject: [PATCH 2/7] Update DLC_labeled_video.py --- dlc/DLC_labeled_video.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dlc/DLC_labeled_video.py b/dlc/DLC_labeled_video.py index 4178cc7..0de7629 100644 --- a/dlc/DLC_labeled_video.py +++ b/dlc/DLC_labeled_video.py @@ -40,7 +40,7 @@ def Viewer(eid, video_type, trial_range, save_video=True, eye_zoom=False): 3D example: 'cb2ad999-a6cb-42ff-bf71-1774c57e5308', [5,7] ''' - save_vids_here = '/home/mic/' + save_vids_here = str(Path.home()) if save_vids_here[-1] != '/': return 'Last character of save_vids_here must be slash' From ebab92e8d065eac20f90576c01e63e03290462a4 Mon Sep 17 00:00:00 2001 From: mschart Date: Tue, 12 Oct 2021 12:38:56 +0100 Subject: [PATCH 3/7] Update DLC_labeled_video.py --- dlc/DLC_labeled_video.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/dlc/DLC_labeled_video.py b/dlc/DLC_labeled_video.py index 0de7629..b24e5b2 100644 --- a/dlc/DLC_labeled_video.py +++ b/dlc/DLC_labeled_video.py @@ -41,8 +41,6 @@ def Viewer(eid, video_type, trial_range, save_video=True, eye_zoom=False): ''' save_vids_here = str(Path.home()) - if save_vids_here[-1] != '/': - return 'Last character of save_vids_here must be slash' one = ONE() alf_path = one.eid2path(eid) From 1d9382070662ff370ac1c4682b8981ab166d8902 Mon Sep 17 00:00:00 2001 From: mschart Date: Tue, 12 Oct 2021 12:46:05 +0100 Subject: [PATCH 4/7] Update DLC_labeled_video.py --- dlc/DLC_labeled_video.py | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/dlc/DLC_labeled_video.py b/dlc/DLC_labeled_video.py index b24e5b2..babec53 100644 --- a/dlc/DLC_labeled_video.py +++ b/dlc/DLC_labeled_video.py @@ -40,7 +40,7 @@ def Viewer(eid, video_type, trial_range, save_video=True, eye_zoom=False): 3D example: 'cb2ad999-a6cb-42ff-bf71-1774c57e5308', [5,7] ''' - save_vids_here = str(Path.home()) + save_vids_here = Path.home() one = ONE() alf_path = one.eid2path(eid) @@ -177,11 +177,10 @@ def Viewer(eid, video_type, trial_range, save_video=True, eye_zoom=False): dot_s = 5 if save_video: - loc = save_vids_here + '%s_trials_%s_%s_%s.mp4' % (eid, - trial_range[0], - trial_range[-1], - video_type) - out = cv2.VideoWriter(loc, + loc = (save_vids_here / + f'{eid}_trials_{trial_range[0]}_{trial_range[-1]}_{video_type}.mp4') + + out = cv2.VideoWriter(str(loc), cv2.VideoWriter_fourcc(*'mp4v'), fps, size) # put , 0 if grey scale From a89d8d3af61f970899f4bfc563259c5aa1076eb6 Mon Sep 17 00:00:00 2001 From: mschart Date: Tue, 2 Nov 2021 16:49:44 +0000 Subject: [PATCH 5/7] Update overview_plot_dlc.py --- dlc/overview_plot_dlc.py | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/dlc/overview_plot_dlc.py b/dlc/overview_plot_dlc.py index e94ccfb..48c4bc3 100644 --- a/dlc/overview_plot_dlc.py +++ b/dlc/overview_plot_dlc.py @@ -219,17 +219,16 @@ def get_ME(eid, video_type): return Times, ME - Times = cam0['times'] def get_example_images(eid): - eids = get_repeated_sites() -# eid = eids[23] -# video_type = 'body' +# eids = get_repeated_sites() +## eid = eids[23] +## video_type = 'body' - #eids = ['15f742e1-1043-45c9-9504-f1e8a53c1744'] - eids = ['4a45c8ba-db6f-4f11-9403-56e06a33dfa4'] +# #eids = ['15f742e1-1043-45c9-9504-f1e8a53c1744'] +# eids = ['4a45c8ba-db6f-4f11-9403-56e06a33dfa4'] frts = {'body':30, 'left':60,'right':150} one=ONE() @@ -1265,7 +1264,6 @@ def plot_all(eid): plt.tight_layout() - s2 = ' '.join(l) # print QC outcome in title and DLC task version one = ONE() @@ -1338,7 +1336,7 @@ def plot_all(eid): plt.tight_layout(rect=[0, 0.03, 1, 0.95]) #plt.savefig(f'/home/mic/reproducible_dlc/overviewJune/{eid}.png') #plt.savefig(f'/home/mic/reproducible_dlc/all_DLC/{s1}_{eid}.png') - plt.savefig(f'/home/mic/reproducible_dlc/miles_QC_update/{s1}_{eid}.png') + plt.savefig(f'/home/mic/reproducible_dlc/motor_correlate/{s1}_{eid}.png') plt.close() From 0a4da71ee7feb370ea2cb6965d7112d6c2508c24 Mon Sep 17 00:00:00 2001 From: Mayo Faulkner Date: Thu, 10 Feb 2022 09:16:57 +0000 Subject: [PATCH 6/7] add raw data plots to alignment gui --- .../alignment_with_easyqc.py | 5 ++- atlaselectrophysiology/ephys_atlas_gui.py | 7 +++- atlaselectrophysiology/ephys_gui_setup.py | 8 +++++ atlaselectrophysiology/example_code.py | 3 -- atlaselectrophysiology/plot_data.py | 34 +++++++++++++++++++ 5 files changed, 50 insertions(+), 7 deletions(-) diff --git a/atlaselectrophysiology/alignment_with_easyqc.py b/atlaselectrophysiology/alignment_with_easyqc.py index bcc486e..7db8a04 100644 --- a/atlaselectrophysiology/alignment_with_easyqc.py +++ b/atlaselectrophysiology/alignment_with_easyqc.py @@ -1,7 +1,7 @@ from easyqc.gui import viewseis from ibllib.dsp import voltage from ibllib.ephys import neuropixel -from viewspikes.data import stream, get_ks2 +from viewspikes.data import stream from viewspikes.plots import overlay_spikes import scipy from PyQt5 import QtCore, QtGui @@ -140,12 +140,11 @@ def stream_ap(self, t): sos = scipy.signal.butter(3, 300 / self.ap.fs / 2, btype='highpass', output='sos') butt = scipy.signal.sosfiltfilt(sos, raw) destripe = voltage.destripe(raw, fs=self.ap.fs) - ks2 = get_ks2(raw, dsets, self.loaddata.one) + self.eqc['butterworth'] = viewseis(butt.T, si=1 / self.ap.fs, h=h, t0=t0, title='butt', taxis=0) self.eqc['destripe'] = viewseis(destripe.T, si=1 / self.ap.fs, h=h, t0=t0, title='destr', taxis=0) - self.eqc['ks2'] = viewseis(ks2.T, si=1 / self.ap.fs, h=h, t0=t0, title='ks2', taxis=0) overlay_spikes(self.eqc['butterworth'], self.plotdata.spikes, self.plotdata.clusters, self.plotdata.channels) diff --git a/atlaselectrophysiology/ephys_atlas_gui.py b/atlaselectrophysiology/ephys_atlas_gui.py index 9a46fdf..2350347 100644 --- a/atlaselectrophysiology/ephys_atlas_gui.py +++ b/atlaselectrophysiology/ephys_atlas_gui.py @@ -1273,6 +1273,11 @@ def data_button_pressed(self): self.probe_rfmap, self.rfmap_boundaries = self.plotdata.get_rfmap_data() self.img_stim_data = self.plotdata.get_passive_events() + if not self.offline: + self.img_raw_data = self.plotdata.get_raw_data_image(self.loaddata.probe_id, one=self.loaddata.one) + else: + self.img_raw_data = {} + if self.histology_exists: self.slice_data = self.loaddata.get_slice_images(self.ephysalign.xyz_samples) else: @@ -2113,7 +2118,7 @@ def viewer(probe_id, one=None, histology=False, spike_collection=None, title=Non parser = argparse.ArgumentParser(description='Offline vs online mode') parser.add_argument('-o', '--offline', default=False, required=False, help='Offline mode') - parser.add_argument('-r', '--remote', default=False, required=False, action='store_true', help='Remote mode') + parser.add_argument('-r', '--remote', default=False, required=False, action='store_true', help='Remote mode') parser.add_argument('-i', '--insertion', default=None, required=False, help='Insertion mode') args = parser.parse_args() diff --git a/atlaselectrophysiology/ephys_gui_setup.py b/atlaselectrophysiology/ephys_gui_setup.py index 37af73b..86cd6b9 100644 --- a/atlaselectrophysiology/ephys_gui_setup.py +++ b/atlaselectrophysiology/ephys_gui_setup.py @@ -105,6 +105,14 @@ def init_menubar(self): img_options.addAction(scatter_amp) self.img_options_group.addAction(scatter_amp) + raw_type = list(self.img_raw_data.keys()) + for raw in raw_type: + img = QtWidgets.QAction(raw, self, checkable=True, checked=False) + img.triggered.connect(lambda checked, item=raw: self.plot_image( + self.img_raw_data[item])) + img_options.addAction(img) + self.img_options_group.addAction(img) + stim_type = list(self.img_stim_data.keys()) for stim in stim_type: img = QtWidgets.QAction(stim, self, checkable=True, checked=False) diff --git a/atlaselectrophysiology/example_code.py b/atlaselectrophysiology/example_code.py index 7618439..82a6b00 100644 --- a/atlaselectrophysiology/example_code.py +++ b/atlaselectrophysiology/example_code.py @@ -6,6 +6,3 @@ av = viewer(probe_id, one=one) - - -# To add trials to the window \ No newline at end of file diff --git a/atlaselectrophysiology/plot_data.py b/atlaselectrophysiology/plot_data.py index e4f7c34..27d3e6d 100644 --- a/atlaselectrophysiology/plot_data.py +++ b/atlaselectrophysiology/plot_data.py @@ -3,8 +3,10 @@ import numpy as np import one.alf as alf from brainbox.processing import bincount2D +from brainbox.io.spikeglx import stream from brainbox.population.decode import xcorr from brainbox.task import passive +from ibllib.dsp import voltage import scipy from PyQt5 import QtGui @@ -472,6 +474,38 @@ def median_subtract(a): return data_img, data_probe + # only for IBL sorry + def get_raw_data_image(self, pid, t0=(1000, 2000, 3000), one=None): + + def gain2level(gain): + return 10 ** (gain / 20) * 4 * np.array([-1, 1]) + data_img = dict() + for t in t0: + + sr, t = stream(pid, t, one=one) + raw = sr[:, :-sr.nsync].T + channel_labels, channel_features = voltage.detect_bad_channels(raw, sr.fs) + raw = voltage.destripe(raw, fs=sr.fs, channel_labels=channel_labels) + raw_image = raw[:, int((450 / 1e3) * sr.fs):int((500 / 1e3) * sr.fs)].T + x_range = np.array([0, raw_image.shape[0] - 1]) / sr.fs * 1e3 + levels = gain2level(-90) + xscale = (x_range[1] - x_range[0]) / raw_image.shape[0] + yscale = (self.chn_max - self.chn_min) / raw_image.shape[1] + + data_raw = { + 'img': raw_image, + 'scale': np.array([xscale, yscale]), + 'levels': levels, + 'offset': np.array([0, 0]), + 'cmap': 'bone', + 'xrange': x_range, + 'xaxis': 'Time (ms)', + 'title': 'Power (uV)' + } + data_img[f'Raw data t={t}'] = data_raw + + return data_img + def get_lfp_spectrum_data(self): freq_bands = np.vstack(([0, 4], [4, 10], [10, 30], [30, 80], [80, 200])) data_probe = {} From d39cce7dd6d6d2f6768137007fed413fb8a85c90 Mon Sep 17 00:00:00 2001 From: Mayo Faulkner Date: Thu, 10 Feb 2022 09:27:03 +0000 Subject: [PATCH 7/7] change cache to target dir --- atlaselectrophysiology/load_histology.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/atlaselectrophysiology/load_histology.py b/atlaselectrophysiology/load_histology.py index df9e956..8f57c48 100644 --- a/atlaselectrophysiology/load_histology.py +++ b/atlaselectrophysiology/load_histology.py @@ -51,7 +51,7 @@ def download_histology_data(subject, lab): path_to_image = Path(CACHE_DIR, file) if not path_to_image.exists(): url = (baseurl + '/' + file) - http_download_file(url, cache_dir=CACHE_DIR, + http_download_file(url, target_dir=CACHE_DIR, username=par.HTTP_DATA_SERVER_LOGIN, password=par.HTTP_DATA_SERVER_PWD)