-
Notifications
You must be signed in to change notification settings - Fork 5
Feather
The feather
object stores the output from the fitting routine. It is called feather
because it is a light-weight wrapper around the fit_data
struct. The name was originally temporary, but it has stuck because there are many different components within BrainTrack and the distinctive name makes it easy to remember.
The main role of the feather
object is to group together a series of fits. Each fit returns a fit_data
and plot_data
struct, but when performing state tracking, you get a sequence of structs that are temporally related. The feather
object stores all of these structs and encapsulates the relationship between them. The main functionality provided by the feather
class is
- A wrapper to arrays of
fit_data
andplot_data
structs - An interface for analysis routines
- A standardized way to store and exchange fit data
The feather
object incorporates a lot of helper methods. These are
- Concatenating multiple
feather
objects - Retrieving a subset of the data (which is returned as another
feather
) - Inserting
fit_data
andplot_data
You can initialize an empty feather using
bt.feather
This means that you can preallocate an array of feathers if you want, using
f(10) = bt.feather
for example. The constructor for a feather has 3 arguments
f = bt.feather(fit_data,plot_data,time)
The fit data and plot data should be the structs returned by bt.fit_spectrum
. The time
is useful if you are not starting at t=1
or if your times are not uniformly spaced. Providing the time value is optional - if you don't provide a time, it will be assumed that the time increment is 1 second starting at t=1
.
For subsequent fits, you can insert the data using
f.insert(fit_data,plot_data,time,idx)
This will preallocate arrays inside the feather
, and insert the fit data and plot data at the specified index. In general, you should not need to specify the index unless you are intentionally overwriting an existing fit.
The feather
class dynamically grows the arrays to provide decent performance when using feather.subrange()
or otherwise adding many points. This is a significant feature because there can be over 20000 fits contained in a single feather
. When you call feather.insert
, the internal arrays are dynamically grown in powers of 2. The actual length of the arrays is stored in feather.prealloc_size
. The amount of data contained is stored in feather.latest
. If you run feather.compress()
then the arrays are truncated so that feather.prealloc_size=feather.latest
, which saves memory once you are done adding things to the feather
.
If you want to obtain a new feather with only a subset of the data, you can use
f2 = f.subrange(indexes)
This will create a new feather using the first of the specified indexes, and then insert each of the subsequent specified fits. The result is a new feather that only contains the requested indexes.
The clouds whose data is stored in plot_data
are important to be able to plot. However, they consume quite a lot of data, which is a huge issue for fits that have over 20000 spectra. To deal with this, instead of storing the actual structs in the feather
, you can instead store the file name of a .mat
file that contains the plot_data
variable. This files are then automatically loaded by bt.viewer
. To use this functionality, you can simply insert a string containing the full file name of the .mat
file. Everything else works as usual.
- The file is automatically split into the parent folder and the file name itself. All of the files need to be stored in the same folder
- This folder is stored in
feather.path_prefix
. If you move the fit folder somewhere else, simply changefeather.path_prefix
appropriately. This way you don't need to change the path in all of theplot_data
strings - If
plot_data
contains strings, the methodfeather.fill
iterates over the strings and loads the plot data into memory, converting thefeather
into one which stores the actual plot data. This provides better performance for visualization, but is only recommended if you have a few (e.g. < 500) spectra in the feather
The feather
class provides several analysis routines. These are approximately structured into three tiers
- Methods that return different representations of the fit data that are suitable for plotting
- Low-level plotting methods for scatter and line plots
- High-level plotting methods for finished figures
The fit data in the feather
object is stored as an array of fit_data
structs, which is not always the most convenient way to work with the data. To assist with custom plotting routines, a number of helper functions are provided:
-
fitted_params
- Returns a matrix of fitted parameters. The row corresponds to the time, and column to the parameter -
fitted_params_from_posterior
- Returns a matrix of the peak of the marginal posterior distribution for each parameter. Rows correspond to time, and column to parameter. These will be more stable than the fitted parameters, but in general they may not provide good fits because of the interdependencies between model parameters -
xyz
- Returns a matrix of XYZ values for each time -
state_blocks
- Returns a two column matrix with start and stop indexes for contiguous states. The first column is the start index, and the second is the stop index. The meaning of this matrix is that all indexes between the first and second column (for a given row) have the same state as the start index. For example, if the output was[1 10; 11 20]
then the first 10 fits all have the same state as the first fit, and fits 11-20 all have the same state as fit 11 -
state_colors
- Return an array where each entry corresponds to the row index ofbt_utils.state_cdata
for the state. Alternatively, this can be also be regarded as a scalar numerical representation of the sleep stage -
state_str
- Return a cell array where each entry corresponds to a string describing the state e.g. 'W' or 'W-S1 (22/8)' -
chisq
- Return an array where each entry corresponds to the chisq value for the fits
The intermediate plotting functions generate scatter and line plots, but leverage the data methods provided above. The low-level plotting commands are:
-
scatter_statecolored
- Takes in 2 or 3 arrays, and plots either a 2D or a 3D scatter in which the colour corresponds to the sleep stage (usingstate_colors
). The number of data points should be the same as the number of points in the feather (if you want to plot a subset of values, usesubrange()
to obtain a feather object for the corresponding indices) -
plot_statecolored
- which plots the input arrays using the colors specified by the states contained within the feather. The lines are plotted based onstate_blocks
which minimizes the number of line objects (thus maximizing performance)
The feather
object contains a number of methods that produce useful analysis figures for fits. Examples of the most common plots are provided in the walkthrough.
-
plot_track
- plots a color-coded track in XYZ space (usesplot_statecolored
internally) -
point_cloud
- plots a color-coded scatter plot of all of the fitted parameters in XYZ space (usesscatter_statecolored
internally) -
blobs
- this function generates convex hulls, grouped by sleep stage. This can be used to generate individualized versions of the blobs in Abeysuriya et. al. (2015). -
clouds
- generates a cloud plot using binned translucent cubes. This is most useful for visualizing densities when points are very closely spaced (and therefore turn into a single blob of color when displayed using a scatter plot) -
cones
- generates a velocity plot in XYZ using cones, where the size of the cone indicates the velocity, and the orientation of the cone indicates the direction of the trajectory. -
timecourse
- Plots the time courses of each of the fit parameters (usesplot_statecolored
internally) -
plot
- this method acts as in interface forbt.viewer
, with the additional feature that theplot()
method stores a reference to the generated figure within thefeather
object, so that if you specify a time index e.g.feather.plot(1)
, subsequently runningfeather.plot(2)
will update the existing figure instead of opening a new one. Unlike simply plotting in the current axis, this functionality will work even if you have multiplefeather
objects and multiple viewers open simultaneously. -
head_plot
- This generates an interactive figure for analyzing multielectrode data.