<SYSTEM_TASK:>
Given the following text description, write Python code to implement the functionality described below step by step
<END_TASK>
<USER_TASK:>
Description:
 Series
A Series object is a collection of 1D arrays, all of which share a common index. Under the hood, it wraps an n-dimensional array, and supports either distributed operations via Spark or local operations via numpy, with an identical API. The final dimension of the array indexes the series, and the initial dimensions are arbitrary.
The most common series data is time series data, in which case the index is time and each record is a different signal, like a channel or pixel.
Here, we show examples of loading and manipulating series data.
Setup plotting
Step1:  Loading series
series data can be loaded using the td.series.from* methods, which support loading from a few different formats. Here we'll load example data.
Step2:  Inspection
Let's plot a random subset of the data using the sample method, after filtering by standard deviation
Step3:  Note the variation in raw intensity levels.
Processing
A Series object has various methods for processing and transforming data. For example, center subtracts the mean, squelch sets to 0 any records not exceeding a threshold, and zscore subtracts the mean and divides by the standard deviation. Note the changes in the y-axis.
Step4:  Related methods include standardize, detrend, and normalize.
Selections
A Series has a 1D index, which can be used to subselect values.
Step5:  For example, to select a range
Step6:  Note that the index changes to reflect the subselected range
Step7:  In this case we could have also just use bracket notation
Step8:  But explicitly referencing the index can be useful when the index encodes information (see below).
We can also select based on an arbitrary criterion function
Step9:  The default index generated for Series objects will be the range of integers starting at zero and ending one before the length of the series data, as shown in these examples. However, other data types can also be used as the index for a series object, such as a sequence of strings, providing text labels for each element in the series array, or a tuple with indices at different levels.
Statistics
A series can be summarized with statistics both within and across records. To summarize across records
Step10:  To compute statistics within records, we can make use of the map method, which executes an artbirary function on each record
Step11:  We can also correlate each record with a signal of interest. As expected, for a random signal, the correlation should be near 0.
Step12:  We can use the fourier method to compute the statistics of a Fourier transform
Step13:  And plot phase as a function of coherence
Step14:  We can also detrend over time, which will remove the periodic structure
Step15:  And we can compute a covariance matrix.
<ASSISTANT_TASK:>
Python Code:
%matplotlib inline
import matplotlib.pyplot as plt
import seaborn as sns
sns.set_style('darkgrid')
sns.set_context('notebook')
from showit import image
import thunder as td
Explanation: Series
A Series object is a collection of 1D arrays, all of which share a common index. Under the hood, it wraps an n-dimensional array, and supports either distributed operations via Spark or local operations via numpy, with an identical API. The final dimension of the array indexes the series, and the initial dimensions are arbitrary.
The most common series data is time series data, in which case the index is time and each record is a different signal, like a channel or pixel.
Here, we show examples of loading and manipulating series data.
Setup plotting
End of explanation
series = td.series.fromexample('fish')
Explanation: Loading series
series data can be loaded using the td.series.from* methods, which support loading from a few different formats. Here we'll load example data.
End of explanation
examples = series.filter(lambda x: x.std() > 4).sample(n=50).toarray()
plt.plot(examples.T);
Explanation: Inspection
Let's plot a random subset of the data using the sample method, after filtering by standard deviation
End of explanation
examples = series.filter(lambda x: x.std() > 4).center().sample(n=50).toarray()
plt.plot(examples.T);
examples = series.squelch(150).zscore().filter(lambda x: x.std() > 0.1).toarray()
plt.plot(examples.T);
Explanation: Note the variation in raw intensity levels.
Processing
A Series object has various methods for processing and transforming data. For example, center subtracts the mean, squelch sets to 0 any records not exceeding a threshold, and zscore subtracts the mean and divides by the standard deviation. Note the changes in the y-axis.
End of explanation
series.index
Explanation: Related methods include standardize, detrend, and normalize.
Selections
A Series has a 1D index, which can be used to subselect values.
End of explanation
series.between(0,8).shape
Explanation: For example, to select a range:
End of explanation
series.between(0,8).index
Explanation: Note that the index changes to reflect the subselected range:
End of explanation
series[:, :, :, 0:8].shape
Explanation: In this case we could have also just use bracket notation
End of explanation
series.select(lambda x: x < 5).index
Explanation: But explicitly referencing the index can be useful when the index encodes information (see below).
We can also select based on an arbitrary criterion function:
End of explanation
plt.plot(series.normalize().max());
plt.plot(series.normalize().mean());
plt.plot(series.normalize().min());
Explanation: The default index generated for Series objects will be the range of integers starting at zero and ending one before the length of the series data, as shown in these examples. However, other data types can also be used as the index for a series object, such as a sequence of strings, providing text labels for each element in the series array, or a tuple with indices at different levels.
Statistics
A series can be summarized with statistics both within and across records. To summarize across records:
End of explanation
means = series.map(lambda x: x.mean()).flatten().toarray()
stds = series.map(lambda x: x.std()).flatten().toarray()
plt.plot(means, stds, '.');
Explanation: To compute statistics within records, we can make use of the map method, which executes an artbirary function on each record
End of explanation
from numpy import random
signal = random.randn(20)
correlations = series.filter(lambda x: x.std() > 0).correlate(signal).flatten().toarray()
plt.hist(correlations);
Explanation: We can also correlate each record with a signal of interest. As expected, for a random signal, the correlation should be near 0.
End of explanation
fourier = series.filter(lambda x: x.std() > 1).flatten().fourier(freq=1)
fourier.index
Explanation: We can use the fourier method to compute the statistics of a Fourier transform
End of explanation
plt.plot(fourier.select('coherence').toarray(), fourier.select('phase').toarray(), '.')
Explanation: And plot phase as a function of coherence
End of explanation
plt.plot(series.mean())
plt.plot(series.detrend('nonlinear', order=5).mean());
Explanation: We can also detrend over time, which will remove the periodic structure
End of explanation
image(series.flatten().cov());
Explanation: And we can compute a covariance matrix.
End of explanation
<END_TASK>