def get_probegroup(self): arr = self.get_property('contact_vector') if arr is None: positions = self.get_property('location') if positions is None: raise ValueError( 'There is not Probe attached to recording. use set_probe(...)' ) else: warn( 'There is no Probe attached to this recording. Creating a dummy one with contact positions' ) ndim = positions.shape[1] probe = Probe(ndim=ndim) probe.set_contacts(positions=positions, shapes='circle', shape_params={'radius': 5}) probe.set_device_channel_indices( np.arange(self.get_num_channels(), dtype='int64')) # probe.create_auto_shape() probegroup = ProbeGroup() probegroup.add_probe(probe) else: probegroup = ProbeGroup.from_numpy(arr) for probe_index, probe in enumerate(probegroup.probes): contour = self.get_annotation( f'probe_{probe_index}_planar_contour') if contour is not None: probe.set_planar_contour(contour) return probegroup
def set_probe(self, probe, group_mode='by_probe', in_place=False): """ Wrapper on top on set_probes when there one unique probe. """ assert isinstance(probe, Probe), 'must give Probe' probegroup = ProbeGroup() probegroup.add_probe(probe) return self.set_probes(probegroup, group_mode=group_mode, in_place=in_place)
def test_probegroup_3d(): probegroup = ProbeGroup() for i in range(3): probe = generate_dummy_probe().to_3d() probe.move([i * 100, i * 80, i * 30]) probegroup.add_probe(probe) assert probegroup.ndim == 3
def test_plot_probe_group(): probegroup = generate_dummy_probe_group() plot_probe_group(probegroup, same_axe=True, with_channel_index=True) plot_probe_group(probegroup, same_axe=False) # 3d probegroup_3d = ProbeGroup() for probe in probegroup.probes: probegroup_3d.add_probe(probe.to_3d()) probegroup_3d.probes[-1].move([0, 150, -50]) plot_probe_group(probegroup_3d, same_axe=True)
def test_probegroup(): probegroup = ProbeGroup() for i in range(3): probe = generate_dummy_probe() probe.move([i * 100, i * 80]) probegroup.add_probe(probe) indices = probegroup.get_global_device_channel_indices() ids = probegroup.get_global_electrode_ids() df = probegroup.to_dataframe()
def set_probes(self, probe_or_probegroup, group_mode='by_probe', in_place=False): """ Attach a Probe to a recording. For this Probe.device_channel_indices is used to link contacts to recording channels. If some contacts of the Probe are not connected (device_channel_indices=-1) then the recording is "sliced" and only connected channel are kept. The probe order is not kept. Channel ids are re-ordered to match the channel_ids of the recording. Parameters ---------- probe_or_probegroup: Probe, list of Probe, or ProbeGroup The probe(s) to be attached to the recording group_mode: str 'by_probe' or 'by_shank'. Adds grouping property to the recording based on the probes ('by_probe') or shanks ('by_shanks') in_place: bool False by default. Useful internally when extractor do self.set_probegroup(probe) Returns ------- sub_recording: BaseRecording A view of the recording (ChannelSliceRecording or clone or itself) """ from spikeinterface import ChannelSliceRecording assert group_mode in ( 'by_probe', 'by_shank'), "'group_mode' can be 'by_probe' or 'by_shank'" # handle several input possibilities if isinstance(probe_or_probegroup, Probe): probegroup = ProbeGroup() probegroup.add_probe(probe_or_probegroup) elif isinstance(probe_or_probegroup, ProbeGroup): probegroup = probe_or_probegroup elif isinstance(probe_or_probegroup, list): assert all([isinstance(e, Probe) for e in probe_or_probegroup]) probegroup = ProbeGroup() for probe in probe_or_probegroup: probegroup.add_probe(probe) else: raise ValueError('must give Probe or ProbeGroup or list of Probe') # handle not connected channels assert all(probe.device_channel_indices is not None for probe in probegroup.probes), \ 'Probe must have device_channel_indices' # this is a vector with complex fileds (dataframe like) that handle all contact attr arr = probegroup.to_numpy(complete=True) # keep only connected contact ( != -1) keep = arr['device_channel_indices'] >= 0 if np.any(~keep): warn( 'The given probes have unconnected contacts: they are removed') arr = arr[keep] inds = arr['device_channel_indices'] order = np.argsort(inds) inds = inds[order] # check if np.max(inds) >= self.get_num_channels(): raise ValueError( 'The given Probe have "device_channel_indices" that do not match channel count' ) new_channel_ids = self.get_channel_ids()[inds] arr = arr[order] # create recording : channel slice or clone or self if in_place: if not np.array_equal(new_channel_ids, self.get_channel_ids()): raise Exception( 'set_proce(inplace=True) must have all channel indices') sub_recording = self else: if np.array_equal(new_channel_ids, self.get_channel_ids()): sub_recording = self.clone() else: sub_recording = ChannelSliceRecording(self, new_channel_ids) # create a vector that handle all conatcts in property sub_recording.set_property('contact_vector', arr, ids=None) # planar_contour is saved in annotations for probe_index, probe in enumerate(probegroup.probes): contour = probe.probe_planar_contour if contour is not None: sub_recording.set_annotation( f'probe_{probe_index}_planar_contour', contour, overwrite=True) # duplicate positions to "locations" property ndim = probegroup.ndim locations = np.zeros((arr.size, ndim), dtype='float64') for i, dim in enumerate(['x', 'y', 'z'][:ndim]): locations[:, i] = arr[dim] sub_recording.set_property('location', locations, ids=None) # handle groups groups = np.zeros(arr.size, dtype='int64') if group_mode == 'by_probe': for group, probe_index in enumerate(np.unique(arr['probe_index'])): mask = arr['probe_index'] == probe_index groups[mask] = group elif group_mode == 'by_shank': assert all(probe.shank_ids is not None for probe in probegroup.probes), \ 'shank_ids is None in probe, you cannot group by shank' for group, a in enumerate( np.unique(arr[['probe_index', 'shank_ids']])): mask = (arr['probe_index'] == a['probe_index']) & ( arr['shank_ids'] == a['shank_ids']) groups[mask] = group sub_recording.set_property('group', groups, ids=None) return sub_recording
from probeinterface.plotting import plot_probe_group from probeinterface import generate_dummy_probe ############################################################################## # Generate 2 dummy `Probe` objects with the utils function: # probe0 = generate_dummy_probe(elec_shapes='square') probe1 = generate_dummy_probe(elec_shapes='circle') probe1.move([250, -90]) ############################################################################## # Let's create a `ProbeGroup` and # add the `Probe` objects into it: probegroup = ProbeGroup() probegroup.add_probe(probe0) probegroup.add_probe(probe1) print('probe0.get_electrode_count()', probe0.get_electrode_count()) print('probe1.get_electrode_count()', probe1.get_electrode_count()) print('probegroup.get_channel_count()', probegroup.get_channel_count()) ############################################################################## # We can now plot all probes in the same axis: plot_probe_group(probegroup, same_axe=True) ############################################################################## # or in separate axes:
############################################################################## # Import import numpy as np import matplotlib.pyplot as plt from probeinterface import Probe, ProbeGroup from probeinterface.plotting import plot_probe, plot_probe_group ############################################################################## # Generate 4 tetrodes: # from probeinterface import generate_tetrode probegroup = ProbeGroup() for i in range(4): tetrode = generate_tetrode() tetrode.move([i * 50, 0]) probegroup.add_probe(tetrode) probegroup.set_global_device_channel_indices(np.arange(16)) df = probegroup.to_dataframe() df plot_probe_group(probegroup, with_channel_index=True, same_axes=True) ############################################################################## # Generate a linear probe: #
plot_probe(probe, with_channel_index=True) ############################################################################## # Very often we have several probes on the device and this can lead to even # more complex channel indices. # `ProbeGroup.get_global_device_channel_indices()` gives an overview of the device wiring. probe0 = generate_multi_columns_probe(num_columns=3, num_elec_per_column=[5, 6, 5], xpitch=75, ypitch=75, y_shift_per_column=[0, -37.5, 0], electrode_shapes='circle', electrode_shape_params={'radius': 12}) probe1 = probe0.copy() probe1.move([350, 200]) probegroup = ProbeGroup() probegroup.add_probe(probe0) probegroup.add_probe(probe1) # wire probe0 0 to 31 and shuffle channel_indices0 = np.arange(16) np.random.shuffle(channel_indices0) probe0.set_device_channel_indices(channel_indices0) # wire probe0 32 to 63 and shuffle channel_indices1 = np.arange(16, 32) np.random.shuffle(channel_indices1) probe1.set_device_channel_indices(channel_indices1) print(probegroup.get_global_device_channel_indices())
from probeinterface import Probe, ProbeGroup from probeinterface.plotting import plot_probe, plot_probe_group from probeinterface import generate_dummy_probe from probeinterface import write_probeinterface, read_probeinterface from probeinterface import write_prb, read_prb ############################################################################## # Let's first generate 2 dummy probes and combine them # into a ProbeGroup probe0 = generate_dummy_probe(elec_shapes='square') probe1 = generate_dummy_probe(elec_shapes='circle') probe1.move([250, -90]) probegroup = ProbeGroup() probegroup.add_probe(probe0) probegroup.add_probe(probe1) ############################################################################## # With the `write_probeinterface` and `read_probeinterface` functions we can # write to and read from the json-based probeinterface format: write_probeinterface('my_two_probe_setup.json', probegroup) probegroup2 = read_probeinterface('my_two_probe_setup.json') plot_probe_group(probegroup2) ############################################################################## # The format looks like this:
def test_probegroup(): probegroup = ProbeGroup() nchan = 0 for i in range(3): probe = generate_dummy_probe() probe.move([i * 100, i * 80]) n = probe.get_contact_count() probe.set_device_channel_indices(np.arange(n)[::-1] + nchan) shank_ids = np.ones(n) shank_ids[:n // 2] *= i * 2 shank_ids[n // 2:] *= i * 2 + 1 probe.set_shank_ids(shank_ids) probegroup.add_probe(probe) nchan += n indices = probegroup.get_global_device_channel_indices() ids = probegroup.get_global_contact_ids() df = probegroup.to_dataframe() #~ print(df['global_contact_ids']) arr = probegroup.to_numpy(complete=False) other = ProbeGroup.from_numpy(arr) arr = probegroup.to_numpy(complete=True) other = ProbeGroup.from_numpy(arr) d = probegroup.to_dict() other = ProbeGroup.from_dict(d) #~ from probeinterface.plotting import plot_probe_group, plot_probe #~ import matplotlib.pyplot as plt #~ plot_probe_group(probegroup) #~ plot_probe_group(other) #~ plt.show() # checking automatic generation of ids with new dummy probes probegroup.probes = [] for i in range(3): probegroup.add_probe(generate_dummy_probe()) probegroup.auto_generate_contact_ids() probegroup.auto_generate_probe_ids() for p in probegroup.probes: assert p.contact_ids is not None assert 'probe_id' in p.annotations
num_channels=16) # make dumpable recording = recording.save() ############################################################################## # Initially all channel are in the same group. print(recording.get_channel_groups()) ############################################################################## # Lets now change the probe mapping and assign a 4 tetrodes to this recording. # for this we will use the `probeinterface` module and create a `ProbeGroup` containing for dummy tetrode. from probeinterface import generate_tetrode, ProbeGroup probegroup = ProbeGroup() for i in range(4): tetrode = generate_tetrode() tetrode.set_device_channel_indices(np.arange(4) + i * 4) probegroup.add_probe(tetrode) ############################################################################## # now our new recording contain 4 groups recording_4_tetrodes = recording.set_probegroup(probegroup, group_mode='by_probe') # get group print(recording_4_tetrodes.get_channel_groups()) # similar to this print(recording_4_tetrodes.get_property('group'))