Skip to content

Commit 0288fc4

Browse files
committed
add time tutorial
1 parent 508c0ba commit 0288fc4

File tree

1 file changed

+187
-0
lines changed

1 file changed

+187
-0
lines changed

tutorials/plot_07-TimeModels.py

Lines changed: 187 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,187 @@
1+
"""
2+
06: Fitting Models over Time
3+
============================
4+
5+
Use extensions of the model object to fit power spectra across time.
6+
"""
7+
8+
###################################################################################################
9+
10+
# sphinx_gallery_thumbnail_number = 2
11+
12+
# Import the time & event model objects
13+
from specparam import SpectralTimeModel, SpectralTimeEventModel
14+
15+
# Import Bands object to manage oscillation band definitions
16+
from specparam import Bands
17+
18+
# Import helper utilities for simulating and plotting spectrograms
19+
from specparam.sim import sim_spectrogram
20+
from specparam.plts.spectra import plot_spectrogram
21+
22+
23+
###################################################################################################
24+
# Parameterizing Spectrograms
25+
# ---------------------------
26+
#
27+
# So far we have seen how to use spectral models to fit individual power spectra, as well as
28+
# groups of power spectra. In this tutorial, we extent this to fitting groups of power
29+
# spectra that are organized across time / events.
30+
#
31+
# Specifically, here we cover the :class:`~specparam.SpectralTimeModel` and
32+
# :class:`~specparam.SpectralTimeEventModel` objects.
33+
#
34+
# Fitting Spectrograms
35+
# ~~~~~~~~~~~~~~~~~~~~
36+
#
37+
# For the goal of fitting power spectra that are organized across adjacent time windows,
38+
# we can consider that what we are really trying to do is to parameterize spectrograms.
39+
#
40+
# Let's start by simulating an example spectrogram, that we can then parameterize.
41+
#
42+
43+
###################################################################################################
44+
45+
# Create & plot an example spectrogram
46+
n_pre_post = 50
47+
freq_range = [3, 25]
48+
ap_params = [[1, 1.5]] * n_pre_post + [[1, 1]] * n_pre_post
49+
pe_params = [[10, 1.5, 2.5]] * n_pre_post + [[10, 0.5, 2.]] * n_pre_post
50+
freqs, spectrogram = sim_spectrogram(n_pre_post * 2, freq_range, ap_params, pe_params, nlvs=0.1)
51+
52+
###################################################################################################
53+
54+
# Plot our simulated spectrogram
55+
plot_spectrogram(freqs, spectrogram)
56+
57+
###################################################################################################
58+
# SpectralTimeModel
59+
# -----------------
60+
#
61+
# The :class:`~specparam.SpectralTimeModel` object is an extension of the SpectralModel objects
62+
# to support parameterizing neural power spectra that are organized across time (spectrograms).
63+
#
64+
# In practice, this object is very similar to the previously introduced spectral model objects,
65+
# especially the Group model object. The time object is a mildly updated Group object.
66+
#
67+
# The main differences with the SpectralTimeModel from previous model objects are that the
68+
# data it accepts and parameterizes should be organized as as array of power spectra over
69+
# time windows - basically as a spectrogram.
70+
#
71+
72+
###################################################################################################
73+
74+
# Initialize a SpectralTimeModel model, which accepts all the same settings as SpectralModel
75+
ft = SpectralTimeModel()
76+
77+
###################################################################################################
78+
# Defining Oscillation Bands
79+
# ~~~~~~~~~~~~~~~~~~~~~~~~~~
80+
#
81+
# Before we start parameterizing power spectra we need to set up some guidance on how to
82+
# organize the results - most notably the peaks. Within the object, the Time model does fit
83+
# and store all the peaks it detects. However, without some definition of how to store and
84+
# visualize the peaks, the object cannot visualize the results across time.
85+
#
86+
# We can therefore use the :class:`~.Bands` object to define oscillation bands of interest.
87+
# By doing so, the Time model object will organize peaks based on these band definitions,
88+
# so we can plot, for example, alpha peaks across time windows.
89+
#
90+
91+
###################################################################################################
92+
93+
# Define a bands object to organize peak parameters
94+
bands = Bands({'alpha' : [7, 14]})
95+
96+
###################################################################################################
97+
#
98+
# Now we are ready to fit our spectrogram! As with all model objects, we can fit the models
99+
# with the `fit` method, or fit, plot, and print with the `report` method.
100+
#
101+
102+
###################################################################################################
103+
104+
# Fit the spectrogram and print out report
105+
ft.report(freqs, spectrogram, peak_org=bands)
106+
107+
###################################################################################################
108+
#
109+
# In the above, we can see that the Time object measures the same aperiodic and periodic
110+
# parameters as before, now organized and plotted across time windows.
111+
#
112+
113+
###################################################################################################
114+
# Parameterizing Repeated Events
115+
# ------------------------------
116+
#
117+
# In the above, we parameterized a single spectrogram reflecting power spectra over time windows.
118+
#
119+
# We can also go one step further - parameterizing multiple spectrograms, with the same
120+
# time definition, which can be thought of as representing events (for example, examining
121+
# +/- 5 seconds around an event of interest, that happens multiple times.)
122+
#
123+
# To start, let's simulate multiple spectrograms, representing our different events.
124+
#
125+
126+
###################################################################################################
127+
128+
# Simulate a collection of spectrograms (across events)
129+
n_events = 3
130+
spectrograms = []
131+
for ind in range(n_events):
132+
freqs, cur_spect = sim_spectrogram(n_pre_post * 2, freq_range, ap_params, pe_params, nlvs=0.1)
133+
spectrograms.append(cur_spect)
134+
135+
###################################################################################################
136+
137+
# Plot the set of simulated spectrograms
138+
for cur_spect in spectrograms:
139+
plot_spectrogram(freqs, cur_spect)
140+
141+
###################################################################################################
142+
# SpectralTimeEventModel
143+
# ----------------------
144+
#
145+
# To parameterize events (multiple spectrograms) we can use the
146+
# :class:`~specparam.SpectralTimeEventModel` object.
147+
#
148+
# The Event is a further extension of the Time object, which can handle multiple spectrograms.
149+
# You can think of it as an object that manages a Time object for each spectrogram, and then
150+
# allows for collecting and examining the results across multiple events. Just like the Time
151+
# object, the Event object can take in a band definition to organize the peak results.
152+
#
153+
# The Event object has all the same attributes and methods as the previous model objects,
154+
# with the notably update that it accepts as data to parameterize a 3d array of spectrograms.
155+
#
156+
157+
###################################################################################################
158+
159+
# Initialize the spectral event model
160+
fe = SpectralTimeEventModel()
161+
162+
###################################################################################################
163+
164+
# Fit the spectrograms and print out report
165+
fe.report(freqs, spectrograms, peak_org=bands)
166+
167+
###################################################################################################
168+
#
169+
# In the above, we can see that the Event object mimics the layout of the Time report, with
170+
# the update that since the data are now averaged across multiple event, each plot now represents
171+
# the average value of each parameter, shaded by it's standard deviation.
172+
#
173+
# When examining peaks across time and trials, there can also be a variable presence of if / when
174+
# peaks of a particular band are detected. To quantify this, the Event report also includes the
175+
# 'presence' plot, which reports on the % of events that have a detected peak for the given
176+
# band definition. Note that only time windows with a detected peak contribute to the
177+
# visualized data in the other periodic parameter plots.
178+
#
179+
180+
###################################################################################################
181+
# Conclusion
182+
# ----------
183+
#
184+
# Now we have explored fitting power spectrum models and running these fits across time
185+
# windows, including across multiple events. Next we dig deeper into how to choose and tune
186+
# the algorithm settings, and how to troubleshoot if any of the fitting seems to go wrong.
187+
#

0 commit comments

Comments
 (0)