|
1 | 1 | """ |
2 | | -Example for usecases.rst |
| 2 | +Analyzing and Plotting Data with Neo Structures |
| 3 | +=============================================== |
3 | 4 | """ |
| 5 | +###################################################### |
| 6 | +# First we import some packages. Since we are making simulated |
| 7 | +# data we will import quite a few neo features as well as use |
| 8 | +# quantities to provide units |
4 | 9 |
|
5 | 10 | from itertools import cycle |
6 | 11 | import numpy as np |
7 | 12 | from quantities import ms, mV, kHz |
8 | 13 | import matplotlib.pyplot as plt |
9 | 14 | from neo import Block, Segment, ChannelView, Group, SpikeTrain, AnalogSignal |
10 | 15 |
|
| 16 | +########################################################################## |
| 17 | +# For Neo we start with a block of data that will contain segments of data |
| 18 | +# so we will create a block of probe data that has a couple tetrodes |
| 19 | +# Then we will load in 3 segments (for examples trials of a stimulus) |
11 | 20 | store_signals = False |
12 | 21 |
|
13 | 22 | block = Block(name="probe data", tetrode_ids=["Tetrode #1", "Tetrode #2"]) |
|
17 | 26 | Segment(name="trial #3", index=2), |
18 | 27 | ] |
19 | 28 |
|
| 29 | +# we will decide how many units each tetrode has found. If only science was this easy |
20 | 30 | n_units = {"Tetrode #1": 2, "Tetrode #2": 5} |
21 | 31 |
|
| 32 | +################################################################################## |
| 33 | +# Neo can also have groups. Groups are structures within a block that can cross segments |
| 34 | +# for example we could group a neuron across trials or across probes. |
| 35 | + |
22 | 36 | # Create a group for each neuron, annotate each group with the tetrode from which it was recorded |
23 | 37 | groups = [] |
24 | 38 | counter = 0 |
|
29 | 43 |
|
30 | 44 | iter_group = cycle(groups) |
31 | 45 |
|
| 46 | +########################################################################################## |
| 47 | +# Segments are also containers of data. Segments can hold raw signal data like an AnalogSignal |
| 48 | +# Segments can also hold spiketrain data (in a SpikeTrain). It can also hold event data (which |
| 49 | +# we are not show in this example) |
| 50 | + |
| 51 | + |
32 | 52 | # Create dummy data, one segment at a time |
33 | 53 | for segment in block.segments: |
34 | 54 |
|
35 | | - # create two 4-channel AnalogSignals with dummy data |
| 55 | + # create two 4-channel AnalogSignals with simulated data (because we have two tetrodes!) |
| 56 | + # note that the AnalogSignal with have numpy array-like data with units and sampling rates |
| 57 | + # Neo keeps track of these units while also giving you the flexibility of treating the raw data |
| 58 | + # like a numpy array |
36 | 59 | signals = { |
37 | 60 | "Tetrode #1": AnalogSignal(np.random.rand(1000, 4) * mV, sampling_rate=10 * kHz, tetrode_id="Tetrode #1"), |
38 | 61 | "Tetrode #2": AnalogSignal(np.random.rand(1000, 4) * mV, sampling_rate=10 * kHz, tetrode_id="Tetrode #2"), |
39 | 62 | } |
40 | 63 | if store_signals: |
41 | 64 | segment.analogsignals.extend(signals.values()) |
42 | 65 |
|
43 | | - # create spike trains with dummy data |
44 | | - # we will pretend the spikes have been extracted from the dummy signal |
| 66 | + # create spike trains with simulated data |
| 67 | + # we will pretend the spikes have been extracted from the simulated signal |
45 | 68 | for tetrode_id in ("Tetrode #1", "Tetrode #2"): |
46 | 69 | for i in range(n_units[tetrode_id]): |
47 | 70 | spiketrain = SpikeTrain(np.random.uniform(0, 100, size=30) * ms, t_stop=100 * ms) |
|
57 | 80 | current_group.add(signals[tetrode_id]) |
58 | 81 |
|
59 | 82 |
|
60 | | -# Now plot the data |
| 83 | +################################################### |
| 84 | +# Now we will plot the data |
| 85 | +# Neo doesn't provide it's own plotting functions, but |
| 86 | +# since its data can be treated like numpy arrays |
| 87 | +# it is easy to use standard packages like matplotlib |
| 88 | +# for all your plotting needs |
| 89 | +# We do a classic in neuroscience and show various ways |
| 90 | +# to plot a PSTH (Peristimulus histogram) |
61 | 91 |
|
| 92 | +################################################### |
62 | 93 | # .. by trial |
63 | 94 | plt.figure() |
64 | 95 | for seg in block.segments: |
|
68 | 99 | count, bins = np.histogram(stlist) |
69 | 100 | plt.bar(bins[:-1], count, width=bins[1] - bins[0]) |
70 | 101 | plt.title(f"PSTH in segment {seg.index}") |
| 102 | +plt.tight_layout() |
71 | 103 | plt.show() |
72 | 104 |
|
| 105 | +#################################################### |
73 | 106 | # ..by neuron |
74 | 107 |
|
75 | 108 | plt.figure() |
|
79 | 112 | count, bins = np.histogram(stlist) |
80 | 113 | plt.bar(bins[:-1], count, width=bins[1] - bins[0]) |
81 | 114 | plt.title(f"PSTH of unit {group.name}") |
| 115 | +plt.tight_layout() |
82 | 116 | plt.show() |
83 | 117 |
|
84 | | -# ..by tetrode |
| 118 | +########################################################### |
| 119 | +# ..by tetrode (or other electrode number) |
85 | 120 |
|
86 | 121 | plt.figure() |
87 | 122 | for i, tetrode_id in enumerate(block.annotations["tetrode_ids"]): |
|
92 | 127 | count, bins = np.histogram(stlist) |
93 | 128 | plt.bar(bins[:-1], count, width=bins[1] - bins[0]) |
94 | 129 | plt.title(f"PSTH blend of tetrode {tetrode_id}") |
| 130 | +plt.tight_layout() |
95 | 131 | plt.show() |
0 commit comments