Skip to content

Commit 207b851

Browse files
committed
more examples touchups
1 parent 51dfa2b commit 207b851

File tree

6 files changed

+166
-44
lines changed

6 files changed

+166
-44
lines changed

examples/plot_igorio.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@
1616
# Downloaded from Human Brain Project Collaboratory
1717
# Digital Reconstruction of Neocortical Microcircuitry (nmc-portal)
1818
# http://microcircuits.epfl.ch/#/animal/8ecde7d1-b2d2-11e4-b949-6003088da632
19+
20+
1921
datafile_url = "https://microcircuits.epfl.ch/data/released_data/B95.zip"
2022
filename_zip = "B95.zip"
2123
filename = "grouped_ephys/B95/B95_Ch0_IDRest_107.ibw"

examples/plot_imageseq.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
# Now we need to generate some data
2020
# We will just make a nice box and then we can attach this
2121
# ImageSequence to a variety of ROIs
22+
# our ImageSequence will be 50 frames of 100x100 pixel images
2223

2324
l = []
2425
for frame in range(50):
@@ -28,6 +29,10 @@
2829
for x in range(100):
2930
l[frame][y].append(random.randint(0, 50))
3031

32+
#####################################################################
33+
# we then make our image sequence and pull out our results from the
34+
# image_seq
35+
3136
image_seq = ImageSequence(l, sampling_rate=500 * pq.Hz, spatial_scale="m", units="V")
3237

3338
result = image_seq.signal_from_region(
@@ -44,5 +49,5 @@
4449
plt.plot(result[i].times, result[i])
4550
plt.xlabel("seconde")
4651
plt.ylabel("valeur")
47-
52+
plt.tight_layout()
4853
plt.show()

examples/plot_multi_tetrode_example.py

Lines changed: 34 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,21 @@
22
Analyzing and Plotting Data with Neo Structures
33
===============================================
44
"""
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
59

610
from itertools import cycle
711
import numpy as np
812
from quantities import ms, mV, kHz
913
import matplotlib.pyplot as plt
1014
from neo import Block, Segment, ChannelView, Group, SpikeTrain, AnalogSignal
1115

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)
1220
store_signals = False
1321

1422
block = Block(name="probe data", tetrode_ids=["Tetrode #1", "Tetrode #2"])
@@ -18,8 +26,13 @@
1826
Segment(name="trial #3", index=2),
1927
]
2028

29+
# we will decide how many units each tetrode has found. If only science was this easy
2130
n_units = {"Tetrode #1": 2, "Tetrode #2": 5}
2231

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+
2336
# Create a group for each neuron, annotate each group with the tetrode from which it was recorded
2437
groups = []
2538
counter = 0
@@ -30,19 +43,28 @@
3043

3144
iter_group = cycle(groups)
3245

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+
3352
# Create dummy data, one segment at a time
3453
for segment in block.segments:
3554

36-
# 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
3759
signals = {
3860
"Tetrode #1": AnalogSignal(np.random.rand(1000, 4) * mV, sampling_rate=10 * kHz, tetrode_id="Tetrode #1"),
3961
"Tetrode #2": AnalogSignal(np.random.rand(1000, 4) * mV, sampling_rate=10 * kHz, tetrode_id="Tetrode #2"),
4062
}
4163
if store_signals:
4264
segment.analogsignals.extend(signals.values())
4365

44-
# create spike trains with dummy data
45-
# 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
4668
for tetrode_id in ("Tetrode #1", "Tetrode #2"):
4769
for i in range(n_units[tetrode_id]):
4870
spiketrain = SpikeTrain(np.random.uniform(0, 100, size=30) * ms, t_stop=100 * ms)
@@ -60,6 +82,12 @@
6082

6183
###################################################
6284
# 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)
6391

6492
###################################################
6593
# .. by trial
@@ -71,6 +99,7 @@
7199
count, bins = np.histogram(stlist)
72100
plt.bar(bins[:-1], count, width=bins[1] - bins[0])
73101
plt.title(f"PSTH in segment {seg.index}")
102+
plt.tight_layout()
74103
plt.show()
75104

76105
####################################################
@@ -83,6 +112,7 @@
83112
count, bins = np.histogram(stlist)
84113
plt.bar(bins[:-1], count, width=bins[1] - bins[0])
85114
plt.title(f"PSTH of unit {group.name}")
115+
plt.tight_layout()
86116
plt.show()
87117

88118
###########################################################
@@ -97,4 +127,5 @@
97127
count, bins = np.histogram(stlist)
98128
plt.bar(bins[:-1], count, width=bins[1] - bins[0])
99129
plt.title(f"PSTH blend of tetrode {tetrode_id}")
130+
plt.tight_layout()
100131
plt.show()

examples/plot_read_files_neo_rawio.py

Lines changed: 58 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -11,21 +11,24 @@
1111
import urllib
1212
from neo.rawio import PlexonRawIO
1313

14-
url_repo = "https://web.gin.g-node.org/NeuralEnsemble/ephy_testing_data/raw/master/"
15-
1614
##############################################################
1715
# 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
1918
# 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.
2122

23+
url_repo = "https://web.gin.g-node.org/NeuralEnsemble/ephy_testing_data/raw/master/"
2224
distantfile = url_repo + "plexon/File_plexon_3.plx"
2325
localfile = "File_plexon_3.plx"
2426
urllib.request.urlretrieve(distantfile, localfile)
2527

2628
###############################################################
2729
# 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)
2932
# Then we need to do the slow step of parsing the header with the
3033
# `parse_header` function. This collects metadata as well as
3134
# make all future steps much faster for us
@@ -42,56 +45,70 @@
4245
# we can use None to mean look at all channels. We also need to
4346
# specify the block of data (block_index) as well as the segment
4447
# (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
4649
# the sample rate (so index = time / sampling_rate)
50+
4751
channel_indexes = None # could be channel_indexes = [0]
4852
raw_sigs = reader.get_analogsignal_chunk(
4953
block_index=0, seg_index=0, i_start=1024, i_stop=2048, channel_indexes=channel_indexes
5054
)
5155

5256
# raw_sigs are not voltages so to convert to voltages we do the follwing
5357
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+
5569
sampling_rate = reader.get_signal_sampling_rate()
70+
# Like above we need to indicate the block and segment
5671
t_start = reader.get_signal_t_start(block_index=0, seg_index=0)
5772
units = reader.header["signal_channels"][0]["units"]
73+
5874
# and we can display all of this information
59-
print(raw_sigs.shape, raw_sigs.dtype)
60-
print(float_sigs.shape, float_sigs.dtype)
6175
print(f"{sampling_rate=}, {t_start=}, {units=}")
6276

6377

6478
####################################################################
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
6781
# for us PlexonRawIO does have spikes data!!
6882

6983
# Count units and spikes per unit
7084
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")
7287
for spike_channel_index in range(nb_unit):
7388
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")
7590

7691
# Read spike times and rescale (just like analogsignal above)
7792
spike_timestamps = reader.get_spike_timestamps(
7893
block_index=0, seg_index=0, spike_channel_index=0, t_start=0.0, t_stop=10.0
7994
)
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")
8197
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")
8399

84100
#######################################################################
85101
# 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)
87104

88105
# Read spike waveforms
89106
raw_waveforms = reader.get_spike_raw_waveforms(
90107
block_index=0, seg_index=0, spike_channel_index=0, t_start=0.0, t_stop=10.0
91108
)
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")
93110
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")
95112

96113
#########################################################################
97114
# RawIOs can also read event timestamps. But looks like our luck ran out
@@ -102,18 +119,36 @@
102119
localfile = "File_plexon_2.plx"
103120
urllib.request.urlretrieve(distantfile, localfile)
104121

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+
106126
reader = PlexonRawIO(filename="File_plexon_2.plx")
107127
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+
108135
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
110138
for chan_index in range(nb_event_channel):
111139
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.
113148

114149
ev_timestamps, ev_durations, ev_labels = reader.get_event_timestamps(
115150
block_index=0, seg_index=0, event_channel_index=0, t_start=None, t_stop=None
116151
)
117-
print(f"{ev_timestamps=}\n{ev_durations=}\n{ev_labels=}")
152+
print(f"{ev_timestamps=}\n{ev_durations=}\n{ev_labels=}\n")
118153
ev_times = reader.rescale_event_timestamp(ev_timestamps, dtype="float64")
119-
print(f"{ev_times=}")
154+
print(f"{ev_times=}\n")

0 commit comments

Comments
 (0)