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_dummy_probe_from_locations(self, locations, shape="circle", shape_params={"radius": 1}): probe = Probe() probe.set_contacts(locations, shapes=shape, shape_params=shape_params) probe.set_device_channel_indices(np.arange(self.get_num_channels())) self.set_probe(probe, in_place=True)
y = i % 8 positions[i] = x, y positions *= 20 positions[8:16, 1] -= 10 ############################################################################## # Now we can create a `Probe` object # and set the position and shape of each contact # # The `ndim` argument indicates that the contact is 2d, so the positions have a (n_elec, 2) shape. # We can also define 3d probe with `ndim=3` and positions will have a (n_elec, 3) shape. # # Note: `shapes` and `shape_params` could be arrays as well, indicating the shape for each contact separately. probe = Probe(ndim=2, si_units='um') probe.set_contacts(positions=positions, shapes='circle', shape_params={'radius': 5}) ############################################################################## # `Probe` objects have fancy prints! print(probe) ############################################################################## # In addition to contacts, we can crate the planar contour (polygon) of the probe polygon = [(-20, -30), (20, -110), (60, -30), (60, 190), (-20, 190)] probe.set_planar_contour(polygon) ############################################################################## # If `pandas` is installed, the `Probe` object can be exported as a dataframe for a simpler view:
def test_BaseRecording(): num_seg = 2 num_chan = 3 num_samples = 30 sampling_frequency = 10000 dtype = 'int16' files_path = [f'test_base_recording_{i}.raw' for i in range(num_seg)] for i in range(num_seg): a = np.memmap(files_path[i], dtype=dtype, mode='w+', shape=(num_samples, num_chan)) a[:] = np.random.randn(*a.shape).astype(dtype) rec = BinaryRecordingExtractor(files_path, sampling_frequency, num_chan, dtype) print(rec) assert rec.get_num_segments() == 2 assert rec.get_num_channels() == 3 assert np.all(rec.ids_to_indices([0, 1, 2]) == [0, 1, 2]) assert np.all( rec.ids_to_indices([0, 1, 2], prefer_slice=True) == slice(0, 3, None)) # annotations / properties rec.annotate(yep='yop') assert rec.get_annotation('yep') == 'yop' rec.set_property('quality', [1., 3.3, np.nan]) values = rec.get_property('quality') assert np.all(values[:2] == [ 1., 3.3, ]) # dump/load dict d = rec.to_dict() rec2 = BaseExtractor.from_dict(d) rec3 = load_extractor(d) # dump/load json rec.dump_to_json('test_BaseRecording.json') rec2 = BaseExtractor.load('test_BaseRecording.json') rec3 = load_extractor('test_BaseRecording.json') # dump/load pickle rec.dump_to_pickle('test_BaseRecording.pkl') rec2 = BaseExtractor.load('test_BaseRecording.pkl') rec3 = load_extractor('test_BaseRecording.pkl') # cache to binary cache_folder = Path('./my_cache_folder') folder = cache_folder / 'simple_recording' rec.save(format='binary', folder=folder) rec2 = BaseExtractor.load_from_folder(folder) assert 'quality' in rec2.get_property_keys() # but also possible rec3 = BaseExtractor.load('./my_cache_folder/simple_recording') # cache to memory rec4 = rec3.save(format='memory') traces4 = rec4.get_traces(segment_index=0) traces = rec.get_traces(segment_index=0) assert np.array_equal(traces4, traces) # cache joblib several jobs rec.save(name='simple_recording_2', chunk_size=10, n_jobs=4) # set/get Probe only 2 channels probe = Probe(ndim=2) positions = [[0., 0.], [0., 15.], [0, 30.]] probe.set_contacts(positions=positions, shapes='circle', shape_params={'radius': 5}) probe.set_device_channel_indices([2, -1, 0]) probe.create_auto_shape() rec2 = rec.set_probe(probe, group_mode='by_shank') rec2 = rec.set_probe(probe, group_mode='by_probe') positions2 = rec2.get_channel_locations() assert np.array_equal(positions2, [[0, 30.], [0., 0.]]) probe2 = rec2.get_probe() positions3 = probe2.contact_positions assert np.array_equal(positions2, positions3) # from probeinterface.plotting import plot_probe_group, plot_probe # import matplotlib.pyplot as plt # plot_probe(probe) # plot_probe(probe2) # plt.show() # test return_scale sampling_frequency = 30000 traces = np.zeros((1000, 5), dtype='int16') rec_int16 = NumpyRecording([traces], sampling_frequency) assert rec_int16.get_dtype() == 'int16' print(rec_int16) traces_int16 = rec_int16.get_traces() assert traces_int16.dtype == 'int16' # return_scaled raise error when no gain_to_uV/offset_to_uV properties with pytest.raises(ValueError): traces_float32 = rec_int16.get_traces(return_scaled=True) rec_int16.set_property('gain_to_uV', [.195] * 5) rec_int16.set_property('offset_to_uV', [0.] * 5) traces_float32 = rec_int16.get_traces(return_scaled=True) assert traces_float32.dtype == 'float32'
def toy_example(duration=10, num_channels=4, num_units=10, sampling_frequency=30000.0, num_segments=2, average_peak_amplitude=-100, upsample_factor=13, dumpable=False, dump_folder=None, seed=None): ''' Creates toy recording and sorting extractors. Parameters ---------- duration: float (or list if multi segment) Duration in s (default 10) num_channels: int Number of channels (default 4) num_units: int Number of units (default 10) sampling_frequency: float Sampling frequency (default 30000) num_segments: int default 2 Number of segments. dumpable: bool If True, objects are dumped to file and become 'dumpable' dump_folder: str or Path Path to dump folder (if None, 'test' is used seed: int Seed for random initialization Returns ------- recording: RecordingExtractor The output recording extractor. If dumpable is False it's a NumpyRecordingExtractor, otherwise it's an MdaRecordingExtractor sorting: SortingExtractor The output sorting extractor. If dumpable is False it's a NumpyRecordingExtractor, otherwise it's an NpzSortingExtractor ''' if isinstance(duration, int): duration = float(duration) if isinstance(duration, float): durations = [duration] * num_segments else: durations = duration assert isinstance(duration, list) assert len(durations) == num_segments assert all(isinstance(d, float) for d in durations) assert num_channels > 0 assert num_units > 0 waveforms, geometry = synthesize_random_waveforms( num_units=num_units, num_channels=num_channels, average_peak_amplitude=average_peak_amplitude, upsample_factor=upsample_factor, seed=seed) unit_ids = np.arange(num_units, dtype='int64') traces_list = [] times_list = [] labels_list = [] for segment_index in range(num_segments): times, labels = synthesize_random_firings( num_units=num_units, duration=durations[segment_index], sampling_frequency=sampling_frequency, seed=seed) times_list.append(times) labels_list.append(labels) traces = synthesize_timeseries( times, labels, unit_ids, waveforms, sampling_frequency, durations[segment_index], noise_level=10, waveform_upsample_factor=upsample_factor, seed=seed) traces_list.append(traces) sorting = NumpySorting.from_times_labels(times_list, labels_list, sampling_frequency) recording = NumpyRecording(traces_list, sampling_frequency) recording.annotate(is_filtered=True) probe = Probe(ndim=2) probe.set_contacts(positions=geometry, shapes='circle', shape_params={'radius': 5}) probe.create_auto_shape(probe_type='rect', margin=20) probe.set_device_channel_indices(np.arange(num_channels, dtype='int64')) recording = recording.set_probe(probe) return recording, sorting
############################################################################## # The `plane_axes` argument handles the axis for each contact. # It can be used for contact-wise rotations. # `plane_axes` has a shape of (num_elec, 2, ndim) plane_axes = [[[1 / np.sqrt(2), 1 / np.sqrt(2)], [-1 / np.sqrt(2), 1 / np.sqrt(2)]]] * n plane_axes = np.array(plane_axes) ############################################################################## # Create the probe probe = Probe(ndim=2, si_units='um') probe.set_contacts(positions=positions, plane_axes=plane_axes, shapes=shapes, shape_params=shape_params) probe.create_auto_shape() ############################################################################## plot_probe(probe) ############################################################################## # We can also use the `rotate_contacts` to make contact-wise rotations: from probeinterface import generate_multi_columns_probe probe = generate_multi_columns_probe(num_columns=3, num_contact_per_column=8, xpitch=20,
def test_BaseRecording(): num_seg = 2 num_chan = 3 num_samples = 30 sampling_frequency = 10000 dtype = 'int16' file_paths = [f'test_base_recording_{i}.raw' for i in range(num_seg)] for i in range(num_seg): a = np.memmap(file_paths[i], dtype=dtype, mode='w+', shape=(num_samples, num_chan)) a[:] = np.random.randn(*a.shape).astype(dtype) rec = BinaryRecordingExtractor(file_paths, sampling_frequency, num_chan, dtype) assert rec.get_num_segments() == 2 assert rec.get_num_channels() == 3 assert np.all(rec.ids_to_indices([0, 1, 2]) == [0, 1, 2]) assert np.all( rec.ids_to_indices([0, 1, 2], prefer_slice=True) == slice(0, 3, None)) # annotations / properties rec.annotate(yep='yop') assert rec.get_annotation('yep') == 'yop' rec.set_channel_groups([0, 0, 1]) rec.set_property('quality', [1., 3.3, np.nan]) values = rec.get_property('quality') assert np.all(values[:2] == [ 1., 3.3, ]) # missing property rec.set_property('string_property', ["ciao", "bello"], ids=[0, 1]) values = rec.get_property('string_property') assert values[2] == "" # setting an different type raises an error assert_raises(Exception, rec.set_property, key='string_property_nan', values=["ciao", "bello"], ids=[0, 1], missing_value=np.nan) # int properties without missing values raise an error assert_raises(Exception, rec.set_property, key='int_property', values=[5, 6], ids=[1, 2]) rec.set_property('int_property', [5, 6], ids=[1, 2], missing_value=200) values = rec.get_property('int_property') assert values.dtype.kind == "i" times0 = rec.get_times(segment_index=0) # dump/load dict d = rec.to_dict() rec2 = BaseExtractor.from_dict(d) rec3 = load_extractor(d) # dump/load json rec.dump_to_json('test_BaseRecording.json') rec2 = BaseExtractor.load('test_BaseRecording.json') rec3 = load_extractor('test_BaseRecording.json') # dump/load pickle rec.dump_to_pickle('test_BaseRecording.pkl') rec2 = BaseExtractor.load('test_BaseRecording.pkl') rec3 = load_extractor('test_BaseRecording.pkl') # dump/load dict - relative d = rec.to_dict(relative_to=".") rec2 = BaseExtractor.from_dict(d, base_folder=".") rec3 = load_extractor(d, base_folder=".") # dump/load json rec.dump_to_json('test_BaseRecording_rel.json', relative_to=".") rec2 = BaseExtractor.load('test_BaseRecording_rel.json', base_folder=".") rec3 = load_extractor('test_BaseRecording_rel.json', base_folder=".") # cache to binary cache_folder = Path('./my_cache_folder') folder = cache_folder / 'simple_recording' rec.save(format='binary', folder=folder) rec2 = BaseExtractor.load_from_folder(folder) assert 'quality' in rec2.get_property_keys() values = rec2.get_property('quality') assert values[0] == 1. assert values[1] == 3.3 assert np.isnan(values[2]) groups = rec2.get_channel_groups() assert np.array_equal(groups, [0, 0, 1]) # but also possible rec3 = BaseExtractor.load('./my_cache_folder/simple_recording') # cache to memory rec4 = rec3.save(format='memory') traces4 = rec4.get_traces(segment_index=0) traces = rec.get_traces(segment_index=0) assert np.array_equal(traces4, traces) # cache joblib several jobs folder = cache_folder / 'simple_recording2' rec2 = rec.save(folder=folder, chunk_size=10, n_jobs=4) traces2 = rec2.get_traces(segment_index=0) # set/get Probe only 2 channels probe = Probe(ndim=2) positions = [[0., 0.], [0., 15.], [0, 30.]] probe.set_contacts(positions=positions, shapes='circle', shape_params={'radius': 5}) probe.set_device_channel_indices([2, -1, 0]) probe.create_auto_shape() rec_p = rec.set_probe(probe, group_mode='by_shank') rec_p = rec.set_probe(probe, group_mode='by_probe') positions2 = rec_p.get_channel_locations() assert np.array_equal(positions2, [[0, 30.], [0., 0.]]) probe2 = rec_p.get_probe() positions3 = probe2.contact_positions assert np.array_equal(positions2, positions3) assert np.array_equal(probe2.device_channel_indices, [0, 1]) # test save with probe folder = cache_folder / 'simple_recording3' rec2 = rec_p.save(folder=folder, chunk_size=10, n_jobs=2) rec2 = load_extractor(folder) probe2 = rec2.get_probe() assert np.array_equal(probe2.contact_positions, [[0, 30.], [0., 0.]]) positions2 = rec_p.get_channel_locations() assert np.array_equal(positions2, [[0, 30.], [0., 0.]]) traces2 = rec2.get_traces(segment_index=0) assert np.array_equal(traces2, rec_p.get_traces(segment_index=0)) # from probeinterface.plotting import plot_probe_group, plot_probe # import matplotlib.pyplot as plt # plot_probe(probe) # plot_probe(probe2) # plt.show() # test return_scale sampling_frequency = 30000 traces = np.zeros((1000, 5), dtype='int16') rec_int16 = NumpyRecording([traces], sampling_frequency) assert rec_int16.get_dtype() == 'int16' traces_int16 = rec_int16.get_traces() assert traces_int16.dtype == 'int16' # return_scaled raise error when no gain_to_uV/offset_to_uV properties with pytest.raises(ValueError): traces_float32 = rec_int16.get_traces(return_scaled=True) rec_int16.set_property('gain_to_uV', [.195] * 5) rec_int16.set_property('offset_to_uV', [0.] * 5) traces_float32 = rec_int16.get_traces(return_scaled=True) assert traces_float32.dtype == 'float32' # test with t_start rec = BinaryRecordingExtractor(file_paths, sampling_frequency, num_chan, dtype, t_starts=np.arange(num_seg) * 10.) times1 = rec.get_times(1) folder = cache_folder / 'recording_with_t_start' rec2 = rec.save(folder=folder) assert np.allclose(times1, rec2.get_times(1)) # test with time_vector rec = BinaryRecordingExtractor(file_paths, sampling_frequency, num_chan, dtype) rec.set_times(np.arange(num_samples) / sampling_frequency + 30., segment_index=0) rec.set_times(np.arange(num_samples) / sampling_frequency + 40., segment_index=1) times1 = rec.get_times(1) folder = cache_folder / 'recording_with_times' rec2 = rec.save(folder=folder) assert np.allclose(times1, rec2.get_times(1)) rec3 = load_extractor(folder) assert np.allclose(times1, rec3.get_times(1))
# and make some alien probes probe3 = Probe() positions = [[0, 0], [0, 50], [25, 77], [45, 27]] shapes = ['circle', 'square', 'rect', 'circle'] params = [{ 'radius': 10 }, { 'width': 30 }, { 'width': 20, 'height': 12 }, { 'radius': 13 }] probe3.set_contacts(positions=positions, shapes=shapes, shape_params=params) probe3.create_auto_shape(probe_type='rect') probe3.rotate(theta=25) probe3.move([600, 0]) plot_probe(probe3, ax=ax, contacts_colors=['b', 'c', 'g', 'y']) ax.set_xlim(-100, 700) ax.set_ylim(-200, 350) ax.set_aspect('equal') ############################################################################## # Some example in 3d for romantic who like flowers... fig = plt.figure() ax = fig.add_subplot(1, 1, 1, projection='3d')