def probe_trajectory_coronal( eid, probe_label, one, ax=None): """ Generates plots of coronal sections with the channel locations Args: eid (str): session uuid (eid) for one query probe_label (str): probe label, e.g. probe00 one (ONE instance): ONE instance, pre instantiated ONE instance ax (matplotlib.axes.Axes object, optional): Defaults to None Returns: ax (matplotlib.axes.Axes object): Axes with coronal section plotted """ one.path_from_eid(eid) traj = one.alyx.rest( 'trajectories', 'list', session=eid, provenance='Ephys Aligned Histology Track', probe=probe_label)[0] channels = bbone.load_channel_locations(eid=eid, one=one, probe=probe_label) picks = one.alyx.rest('insertions', 'read', id=traj['probe_insertion'])['json'] picks = np.array(picks['xyz_picks']) / 1e6 ins = atlas.Insertion.from_dict(traj) if ax is None: fig, ax = plt.subplots(1, 1, dpi=100, frameon=False) ax = ba_allen.plot_tilted_slice(xyz=picks, axis=1, volume='image', ax=ax) ax.plot(picks[:, 0] * 1e6, picks[:, 2] * 1e6) ax.plot(channels[probe_label].x * 1e6, channels[probe_label].z * 1e6, 'g*') return ax
# Test with eid that does not have any probe planned/histology values in Alyx # eid = 'da188f2c-553c-4e04-879b-c9ea2d1b9a93' # ----- RECOMMENDED: Option 1 (default) ------ # 1. Get spikes, cluster (with brain regions assigned to clusters) and channels spikes, clusters, channels = bbone.load_spike_sorting_with_channel(eid, one=one) del spikes, clusters, channels # Delete for the purpose of the example # --------------------------------------------- # 2. Get only spikes and clusters (without brain regions assigned to clusters) # data separately from channels # Use merger function to get channels information into clusters # Adding feature x, y from default spikes, clusters = bbone.load_spike_sorting(eid, one=one) channels = bbone.load_channel_locations(eid, one=one) keys = ['x', 'y'] clusters_brain = bbone.merge_clusters_channels(clusters, channels, keys_to_add_extra=keys) del spikes, clusters, clusters_brain, channels # Delete for the purpose of the example # --------------------------------------------- # 3. I don't want to connect to ONE and I already know my session path session_path = one.path_from_eid(eid) # replace by your local path spikes, clusters = bbone.load_spike_sorting(session_path, one=one) # TODO offline loading of channel locations ? Probably by caching the queries. # ---------------- WIP --------------------- # TODO one.load_object(): return dict of bunch
""" # Author: Olivier Winter import numpy as np from one.api import ONE import ibllib.atlas as atlas import brainbox.io.one as bbone # === Parameters section (edit) === eid = 'c7bd79c9-c47e-4ea5-aea3-74dda991b48e' probe_label = 'probe01' # === Code (do not edit) === ba = atlas.AllenAtlas(25) one = ONE(base_url='https://openalyx.internationalbrainlab.org') traj = one.alyx.rest('trajectories', 'list', session=eid, provenance='Ephys aligned histology track', probe=probe_label)[0] channels = bbone.load_channel_locations(eid=eid, one=one, probe=probe_label) picks = one.alyx.rest('insertions', 'read', id=traj['probe_insertion'])['json'] picks = np.array(picks['xyz_picks']) / 1e6 ins = atlas.Insertion.from_dict(traj) cax = ba.plot_tilted_slice(xyz=picks, axis=1, volume='image') cax.plot(picks[:, 0] * 1e6, picks[:, 2] * 1e6) cax.plot(channels[probe_label]['x'] * 1e6, channels[probe_label]['z'] * 1e6, 'g*')
from ibllib.pipes.ephys_alignment import EphysAlignment from oneibl.one import ONE from brainbox.io.one import load_channel_locations import numpy as np import matplotlib.pyplot as plt one = ONE(base_url="https://alyx.internationalbrainlab.org") # Load data from 'ZM_2407' '2019-12-06' eid = '03d3cffc-755a-43db-a839-65d8359a7b93' probe = 'probe_00' channels = load_channel_locations(eid, one=one, probe=probe) # xyz coords of channels xyz_channels = np.c_[channels[probe].x, channels[probe].y, channels[probe].z] # depth along probe of channels depths = channels[probe].axial_um region, region_label, region_colour, region_id = EphysAlignment.get_histology_regions(xyz_channels, depths) fig, ax1 = plt.subplots(figsize=(4,10)) for reg, col in zip(region, region_colour): height = np.abs(reg[1]- reg[0]) bottom = reg[0] color = col/255 ax1.bar(x=0.5, height=height, width=1, color=color, bottom=reg[0], edgecolor='w') ax1.set_yticks(region_label[:, 0].astype(int)) ax1.set_yticklabels(region_label[:, 1]) ax1.hlines([0, 3840], *ax1.get_xlim(), linestyles='dashed', linewidth = 3, colors='k') plt.show()
def download_ch_disp_data(x, y, provenance='Planned', project='ibl_neuropixel_brainwide_01'): """Download channels displacement data for all given probes at the planned insertion coord [x,y] from Alyx Downloads the most up-to-date data from Alyx for all recordings at [x,y], including their channel positionss, and the orthogonal points of each channel from the planned trajectory. Saves this data to a standard location in the file system. Also returns this data as a pandas DataFrame object with following: * subject, eid, probe - the subject, eid and probe IDs * chan_loc - xyz coords of all channels * planned_orth_proj - xyz coord of orthogonal line from chan_loc onto planned proj * dist - the euclidean distance between chan_loc xyz and planned_orth_proj xyz Parameters ---------- x : int x planned insertion coord in µm. Eg. repeated site is -2243 y : int y planned insertion coord in µm. Eg. repeated site is -2000. provenance : str, optional Probe provenance to list trajectories from: Planned, Micro-manipulator, Histology, E-phys aligned. The default is 'Planned'. project : str, optional Project to gather all trajectories from. The default is 'ibl_neuropixel_brainwide_01'. Returns ------- data_frame : pandas DataFrame Dataframe containing: subject, eid, probe; ins_x, ins_y; chan_loc; planned_orth_proj; dist. """ from one.api import ONE from ibllib.atlas import Insertion import brainbox.io.one as bbone #from ibllib.io import params - deprecated! # for catching errors in collecting datasets from ibllib.exceptions import IblError from urllib.error import HTTPError import numpy as np import pandas as pd from pathlib import Path # in format -2000_-2243 prefix = str(str(x) + "_" + str(y)) # connect to ONE one = ONE() # get the planned trajectory for repeated site: x=2243, y=2000 traj = one.alyx.rest('trajectories', 'list', provenance=provenance, x=x, y=y, project=project) # from this collect all eids, probes, subjects that use repeated site: eids = [sess['session']['id'] for sess in traj] probes = [sess['probe_name'] for sess in traj] subj = [sess['session']['subject'] for sess in traj] # new dict to store data from loop: # chan_loc - xyz coord of channels # planned_orth_proj - xyz coord of orthogonal line from chan_loc to planned # proj # dist - the 3D distance between chan_loc xyz and planned_orth_proj xyz data = { 'subject': [], 'lab': [], 'eid': [], 'probe': [], 'ins_x': [], 'ins_y': [], 'chan_loc_x': [], 'chan_loc_y': [], 'chan_loc_z': [], 'planned_orth_proj_x': [], 'planned_orth_proj_y': [], 'planned_orth_proj_z': [], 'dist': [], } # Fetch Repeated Site planned trajectory metadata: planned = one.alyx.rest('trajectories', 'list', session=eids[0], probe=probes[0], provenance='planned') # create insertion object of probe from planned trajectory: ins = Insertion.from_dict(planned[0]) # create a trajectory object of Planned Repeated Site from this insertion: traj = ins.trajectory subindex = 0 # loop through each eid/probe: for eid, probe in zip(eids, probes): print( "==================================================================" ) print(eids.index(eid)) print(eid) print(probe) print(subj[subindex]) subindex = subindex + 1 # get the eid/probe as insertion insertion = one.alyx.rest('insertions', 'list', session=eid, name=probe) if insertion: print(" insertion exists") # check if histology has been traced and loaded tracing = np.array(insertion[0]['json']) if tracing: print(" tracing exists") # For this insertion which has histology tracing, retrieve the # channels in xyz coords: # check the localCoordinates EXIST for this eid/probe # run in a try..except statement to continue over the eid/probe # if localCoordinates dataset does not exist try: channel_coord = one.load_dataset( eid, 'channels.localCoordinates.npy', collection='alf/' + probe) except IblError: print("ALFObjectNotFound") print("") continue except HTTPError: print("HTTPError") print("") continue except: print("ERROR - generic") continue # only proceed if channel_coord is not None if channel_coord is None: continue print(" channel_coords exist") if one.alyx.rest('trajectories', 'list', session=eid, probe=probe, provenance='Histology track') == []: print("ERROR - no Histology Track..") continue chan_loc = bbone.load_channel_locations(eid, one=one, probe=probe) print("chan_loc") # only proceed if channel locations could be retrieved if not chan_loc: continue # Next, create a representation of the planned trajectory as a # line: plannedTraj = one.alyx.rest('trajectories', 'list', session=eid, probe=probe, provenance='planned') print("plannedTraj") # create insertion object from planned trajectory: #ins = Insertion.from_dict(planned[0]) # create a trajectory object from this insertion: #traj = ins.trajectory # NEXT - compute the projected coord for each channel coord onto the # line defined by traj: for ch_ind in range(len(chan_loc[probe]['x'])): cl_x = chan_loc[probe]['x'][ch_ind] cl_y = chan_loc[probe]['y'][ch_ind] cl_z = chan_loc[probe]['z'][ch_ind] # create numpy array from chan_loc coords: ch_loc = np.array([cl_x, cl_y, cl_z]) # project the current chan_loc to the PLANNED trajectory: proj = traj.project(ch_loc) # calculate the distance between proj and chan_loc: dist = np.linalg.norm(ch_loc - proj) data['subject'].append( plannedTraj[0]['session']['subject']) data['lab'].append(plannedTraj[0]['session']['lab']) data['eid'].append(eid) data['probe'].append(probe) data['ins_x'].append(probe) data['ins_y'].append(probe) data['chan_loc_x'].append(cl_x) data['chan_loc_y'].append(cl_y) data['chan_loc_z'].append(cl_z) data['planned_orth_proj_x'].append(proj[0]) data['planned_orth_proj_y'].append(proj[1]) data['planned_orth_proj_z'].append(proj[2]) data['dist'].append(dist) # convert data to a Pandas DataFrame: data_frame = pd.DataFrame.from_dict(data) save_ch_disp_data(data_frame, prefix) return data_frame
from brainbox.io.one import load_spike_sorting, load_channel_locations from oneibl.one import ONE one = ONE(base_url="https://dev.alyx.internationalbrainlab.org") eids = one.search(subject='ZM_2407', task_protocol='ephys') channels = load_channel_locations(eids[0], one=one) spikes, clusters = load_spike_sorting(eids[0], one=one)