In this notebook we will simulate rhythmic activity as a first step in our understanding of brain rhythms.
Making sinusoids
It’s relatively easy to make sinusoids in Python, using built-in commands. There are many ways to do so, and we’ll start here by constructing a time axis. Consider the following:
Q: The variable t defines a time axis. When does time start? When does time end? What is the sampling interval (i.e., the time between samples)?
Now, let’s define a new variable that represents a sinusoid,
Q: Is x a sinusoid? What is the frequency of the oscillation?
Q: How would you update x to create a sine function that oscillates at 10 Hz?
Q: How would you create a cosine function that oscillates at 14 Hz?
Orthogonality of sinusoids
An important feature of sinusoids is orthogonality.
Briefly, if we multiply together two cosine functions, and sum the resulting product, we get zero unless the frequencies match.
Let’s illustrate this idea in Python. To do so, first define two sinusoids,
Q: What is the frequency of each sinusoid? Plot these sinusoids to see how they behave.
To check orthogonality, we want to multiply together these two cosine functions, point-by-point at each time, then sum their product over all time.
Q: How do we perform this operation in Python? Do so, and report what you find.
Q: How does this result change for different choices of f1 and f2?
Q: How does this result change if you use sine?
Decomposing a sinusoid into one component
We’ll now consider a more complicated signal. Please download the data Rhythms_1.csv and load the data,
Q: What are the dimensions of each variable? What is the sampling interval? What is the total duration of the data?
Q: By visual inspection of the data, what frequencies dominate the signal?
Now, we’d like to compare sinusoids with known frequency to the data.
In doing so, our goal is to identify those sinusoids that “best match” the data; this will reveal the rhythms that appear in the signal, which we will ultimately display graphically in a power spectrum.
To begin this process, we’ll specify a handful of frequencies to consider.
Let’s start with a sine function oscillating at 1 Hz.
Q: Define a 1 Hz sine function that lasts for the duration of the data, and has the same sampling interval (i.e., the same time axis as the data).
With the sine function now defined, let’s “compare” it to the data
To do so, we multiply point-by-point the data and sine function and sum the result.
Because we’re approximating an integral, we’ll need to include the differential (dt) in the sum.
Q: How do we compute this integral?
Q: Consider your result for this integral. Does the 1 Hz sine function make a significant contribution to the data? Is the result of this integral consistent with your visual inspection of the data?
Decomposing a sinusoid into many components
Now, we’ve compared a single sinusoid - the 1 Hz sine function - to the data.
In this case, we’ve found that the corresponding integral is small.
However, we’re not interested in only this sinusoid; we’d really like to consider a range of sinusoids (both sine and cosine functions) oscillating at different frequencies.
Our goal in this part of notebook is to do so, and compare the data to sinusoids at different frequencies.
Q: Compare the data to sinusoids at integer frequencies {1,2,3, …, 10} Hz. Save your results for each frequency of the cosine function in a variable called “A”, and the results for each frequency of the sine function in a variable called “B”.
HINT: There are many ways to compute these comparisons. You might perform each computation “by hand” (e.g., compute A at 1 Hz, B at 1 Hz, A at 2 Hz, B at 2 Hz, . . . ). In doing so, you’ll notice a lot of repetition. Is there a more efficient way to perform so many similar computations?