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
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'
# 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, ypitch=20, contact_shapes='square',
# First, let's create one 2d probe with 32 contacts: n = 24 positions = np.zeros((n, 2)) for i in range(n): x = i // 8 y = i % 8 positions[i] = x, y positions *= 20 positions[8:16, 1] -= 10 probe_2d = Probe(ndim=2, si_units='um') probe_2d.set_contacts(positions=positions, shapes='circle', shape_params={'radius': 5}) probe_2d.create_auto_shape(probe_type='tip') ############################################################################## # Let's transform it into a 3d probe. # # Here the axes are 'xz' so y will be 0 for all contacts. # The shape of probe_3d.contact_positions is now (n_elec, 3) probe_3d = probe_2d.to_3d(axes='xz') print(probe_2d.contact_positions.shape) print(probe_3d.contact_positions.shape) ############################################################################## # Note that all **"y"** coordinates are 0 df = probe_3d.to_dataframe()
# 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_electrodes(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, electrode_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')
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))
def test_probe(): positions = _dummy_posistion() probe = Probe(ndim=2, si_units='um') probe.set_electrodes(positions=positions, shapes='circle', shape_params={'radius': 5}) probe.set_electrodes(positions=positions, shapes='square', shape_params={'width': 5}) probe.set_electrodes(positions=positions, shapes='rect', shape_params={ 'width': 8, 'height': 5 }) assert probe.get_electrode_count() == 24 # shape of the probe vertices = [(-20, -30), (20, -110), (60, -30), (60, 190), (-20, 190)] probe.set_planar_contour(vertices) # auto shape probe.create_auto_shape() # device channel chans = np.arange(0, 24, dtype='int') np.random.shuffle(chans) probe.set_device_channel_indices(chans) # electrode_ids int or str elec_ids = np.arange(24) probe.set_electrode_ids(elec_ids) elec_ids = [f'elec #{e}' for e in range(24)] probe.set_electrode_ids(elec_ids) # copy probe2 = probe.copy() # move rotate probe.move([20, 50]) probe.rotate(theta=40, center=[0, 0], axis=None) # make annimage values = np.random.randn(24) image, xlims, ylims = probe.to_image(values, method='cubic') image2, xlims, ylims = probe.to_image(values, method='cubic', num_pixel=16) #~ from probeinterface.plotting import plot_probe_group, plot_probe #~ import matplotlib.pyplot as plt #~ fig, ax = plt.subplots() #~ plot_probe(probe, ax=ax) #~ ax.imshow(image, extent=xlims+ylims, origin='lower') #~ ax.imshow(image2, extent=xlims+ylims, origin='lower') #~ plt.show() # 3d probe_3d = probe.to_3d() probe_3d.rotate(theta=60, center=[0, 0, 0], axis=[0, 1, 0]) #~ from probeinterface.plotting import plot_probe_group, plot_probe #~ import matplotlib.pyplot as plt #~ plot_probe(probe_3d) #~ plt.show() # get shanks for shank in probe.get_shanks(): print(shank) print(shank.electrode_positions) # get dict and df d = probe.to_dict() #~ print(d) df = probe.to_dataframe() print(df)