|
11 | 11 | import urllib |
12 | 12 | from neo.rawio import PlexonRawIO |
13 | 13 |
|
14 | | -url_repo = "https://web.gin.g-node.org/NeuralEnsemble/ephy_testing_data/raw/master/" |
15 | | - |
16 | 14 | ############################################################## |
17 | 15 | # Get Plexon files |
18 | | -# We will be pulling these files down, but if you have local file |
| 16 | + |
| 17 | +# We will be pulling these files down, but if you have a local file |
19 | 18 | # then all you need to do is specify the file location on your |
20 | | -# computer |
| 19 | +# computer. NeuralEnsemble keeps a wide variety of freely accesible, small |
| 20 | +# test files that can be used. So for this example we will take advantage of that |
| 21 | +# fact. |
21 | 22 |
|
| 23 | +url_repo = "https://web.gin.g-node.org/NeuralEnsemble/ephy_testing_data/raw/master/" |
22 | 24 | distantfile = url_repo + "plexon/File_plexon_3.plx" |
23 | 25 | localfile = "File_plexon_3.plx" |
24 | 26 | urllib.request.urlretrieve(distantfile, localfile) |
25 | 27 |
|
26 | 28 | ############################################################### |
27 | 29 | # Create a reader |
28 | | -# All it takes to create a reader is giving the filename |
| 30 | + |
| 31 | +# All it takes to create a reader is giving the filename (or dirname) |
29 | 32 | # Then we need to do the slow step of parsing the header with the |
30 | 33 | # `parse_header` function. This collects metadata as well as |
31 | 34 | # make all future steps much faster for us |
|
42 | 45 | # we can use None to mean look at all channels. We also need to |
43 | 46 | # specify the block of data (block_index) as well as the segment |
44 | 47 | # (seg_index). Then we give the index start and stop. Since we |
45 | | -# often thing in time to go from time to index would just require |
| 48 | +# often think in time: to go from time to index would just require |
46 | 49 | # the sample rate (so index = time / sampling_rate) |
| 50 | + |
47 | 51 | channel_indexes = None # could be channel_indexes = [0] |
48 | 52 | raw_sigs = reader.get_analogsignal_chunk( |
49 | 53 | block_index=0, seg_index=0, i_start=1024, i_stop=2048, channel_indexes=channel_indexes |
50 | 54 | ) |
51 | 55 |
|
52 | 56 | # raw_sigs are not voltages so to convert to voltages we do the follwing |
53 | 57 | float_sigs = reader.rescale_signal_raw_to_float(raw_sigs, dtype="float64") |
54 | | -# each rawio gives you access to lots of information about your data |
| 58 | + |
| 59 | +# We can see that the shapes are the same, but that the datatypes |
| 60 | +# are different once we've rescaled our data |
| 61 | +print("Raw Data: ", raw_sigs.shape, raw_sigs.dtype) |
| 62 | +print("Scaled Data: ", float_sigs.shape, float_sigs.dtype) |
| 63 | + |
| 64 | +############################################################### |
| 65 | +# Each rawio gives you access to lots of information about your data |
| 66 | +# some of this information comes from functions |
| 67 | +# other information is stored as metadata in the reader.header |
| 68 | + |
55 | 69 | sampling_rate = reader.get_signal_sampling_rate() |
| 70 | +# Like above we need to indicate the block and segment |
56 | 71 | t_start = reader.get_signal_t_start(block_index=0, seg_index=0) |
57 | 72 | units = reader.header["signal_channels"][0]["units"] |
| 73 | + |
58 | 74 | # and we can display all of this information |
59 | | -print(raw_sigs.shape, raw_sigs.dtype) |
60 | | -print(float_sigs.shape, float_sigs.dtype) |
61 | 75 | print(f"{sampling_rate=}, {t_start=}, {units=}") |
62 | 76 |
|
63 | 77 |
|
64 | 78 | #################################################################### |
65 | | -# Some rawio's and file formats all provide information about spikes |
66 | | -# If an rawio can't read this data it will raise an error, but lucky |
| 79 | +# Some rawio's and file formats also provide information about spikes |
| 80 | +# If a rawio can't read this data it will raise an error, but lucky |
67 | 81 | # for us PlexonRawIO does have spikes data!! |
68 | 82 |
|
69 | 83 | # Count units and spikes per unit |
70 | 84 | nb_unit = reader.spike_channels_count() |
71 | | -print("nb_unit", nb_unit) |
| 85 | +print(f"nb_unit: {nb_unit}\n") # nb_unit stands for number of units |
| 86 | +print("spike_channel_index nb_spike") |
72 | 87 | for spike_channel_index in range(nb_unit): |
73 | 88 | nb_spike = reader.spike_count(block_index=0, seg_index=0, spike_channel_index=spike_channel_index) |
74 | | - print(f"{spike_channel_index=}\n{nb_spike}\n") |
| 89 | + print(f"{spike_channel_index}: {nb_spike}\n") |
75 | 90 |
|
76 | 91 | # Read spike times and rescale (just like analogsignal above) |
77 | 92 | spike_timestamps = reader.get_spike_timestamps( |
78 | 93 | block_index=0, seg_index=0, spike_channel_index=0, t_start=0.0, t_stop=10.0 |
79 | 94 | ) |
80 | | -print(f"{spike_timestamps.shape=}\n{spike_timestamps.dtype=}\n{spike_timestamps[:5]=}") |
| 95 | + |
| 96 | +print(f"{spike_timestamps.shape=}\n{spike_timestamps.dtype=}\n{spike_timestamps[:5]=}\n") |
81 | 97 | spike_times = reader.rescale_spike_timestamp(spike_timestamps, dtype="float64") |
82 | | -print(f"{spike_times.shape=}\n{spike_times.dtype=}\n{spike_times[:5]}") |
| 98 | +print(f"{spike_times.shape=}\n{spike_times.dtype=}\n{spike_times[:5]}\n") |
83 | 99 |
|
84 | 100 | ####################################################################### |
85 | 101 | # Some file formats can also give waveform information. We are lucky |
86 | | -# again. Our file has waveform data!! |
| 102 | +# again our file has waveform data!! We forms are a 3d dataset of |
| 103 | +# (nb_spike, nb_channel, nb_sample) |
87 | 104 |
|
88 | 105 | # Read spike waveforms |
89 | 106 | raw_waveforms = reader.get_spike_raw_waveforms( |
90 | 107 | block_index=0, seg_index=0, spike_channel_index=0, t_start=0.0, t_stop=10.0 |
91 | 108 | ) |
92 | | -print(f"{raw_waveforms.shape=}\n{raw_waveforms.dtype=}\n{raw_waveforms[0, 0, :4]=}") |
| 109 | +print(f"{raw_waveforms.shape=}\n{raw_waveforms.dtype=}\n{raw_waveforms[0, 0, :4]=}\n") |
93 | 110 | float_waveforms = reader.rescale_waveforms_to_float(raw_waveforms, dtype="float32", spike_channel_index=0) |
94 | | -print(f"{float_waveforms.shape=}\n{float_waveforms.dtype=}{float_waveforms[0, 0, :4]=}") |
| 111 | +print(f"{float_waveforms.shape=}\n{float_waveforms.dtype=}{float_waveforms[0, 0, :4]=}\n") |
95 | 112 |
|
96 | 113 | ######################################################################### |
97 | 114 | # RawIOs can also read event timestamps. But looks like our luck ran out |
|
102 | 119 | localfile = "File_plexon_2.plx" |
103 | 120 | urllib.request.urlretrieve(distantfile, localfile) |
104 | 121 |
|
105 | | -# Count events per channel |
| 122 | +######################################################################### |
| 123 | +# Since this is a new file we need to read initialize our reader as well |
| 124 | +# as parse the header |
| 125 | + |
106 | 126 | reader = PlexonRawIO(filename="File_plexon_2.plx") |
107 | 127 | reader.parse_header() |
| 128 | +# if we look at this header we see it is different than the header above |
| 129 | +print(reader.header) |
| 130 | + |
| 131 | +########################################################################### |
| 132 | +# Now let's look at some event data. This could be things like stimuli applied |
| 133 | +# during the course of an ephys recording |
| 134 | + |
108 | 135 | nb_event_channel = reader.event_channels_count() |
109 | | -print("nb_event_channel:", nb_event_channel) |
| 136 | +print(f"nb_event_channel: {nb_event_channel}") |
| 137 | +# now iterate through the channels |
110 | 138 | for chan_index in range(nb_event_channel): |
111 | 139 | nb_event = reader.event_count(block_index=0, seg_index=0, event_channel_index=chan_index) |
112 | | - print("chan_index", chan_index, "nb_event", nb_event) |
| 140 | + print(f"chan_index: {chan_index} nb_event: {nb_event}\n") |
| 141 | + |
| 142 | + |
| 143 | +############################################################################### |
| 144 | +# Finally we can get our actual event timestamps. Some file formats provide the |
| 145 | +# real timestamps (timestamps in s/ms) others have raw timestamps (in samples) |
| 146 | +# so we can do the same style of functions as above. Get the raw timestamps |
| 147 | +# and convert to real times with a rescale function. |
113 | 148 |
|
114 | 149 | ev_timestamps, ev_durations, ev_labels = reader.get_event_timestamps( |
115 | 150 | block_index=0, seg_index=0, event_channel_index=0, t_start=None, t_stop=None |
116 | 151 | ) |
117 | | -print(f"{ev_timestamps=}\n{ev_durations=}\n{ev_labels=}") |
| 152 | +print(f"{ev_timestamps=}\n{ev_durations=}\n{ev_labels=}\n") |
118 | 153 | ev_times = reader.rescale_event_timestamp(ev_timestamps, dtype="float64") |
119 | | -print(f"{ev_times=}") |
| 154 | +print(f"{ev_times=}\n") |
0 commit comments