mbauman / Signals.jl

An abandoned work-in-progress for a high level Signal type with a common timebase (in seconds) and groups of channels. Deprecated in favor of AxisArrays.jl.
github.com/JuliaArrays/AxisArrays.jl
Other
6 stars 0 forks source link

Repetitions of irregularly sampled signals are tough to work with #6

Open mbauman opened 10 years ago

mbauman commented 10 years ago

Diagramming these complicated nested structures makes thinking about this much more concrete. Let's start with a regularly sampled Signal with three channels:

(t)  chan1  chan2  chan3
 |     |      |      |
 |     |      |      |
 |     |      |      |
 |     |      |      |
 |     |      |      |
 V     V      V      V

When we take windowed repetitions of it, the result is a Signal (often irregularly sampled), with each channel being its own regularly sampled signal that contains a two-dimensional 4x3 SignalMatrix. The only disconnect here is that each channel calls its nested repetitions "channels," and the nested time vectors are unnecessarily repeated—they're all the same. But, really, this works fairly well in practice. This is a signal containing a vector of three regularly-sampled signals, all with the same time vector: When the outer signal slices across the inner signal to access each channel ([:,i]), the inner signal returns a SignalVector.

(t)  chan1  chan2  chan3
 o   ---->  ---->  ---->
 o   ---->  ---->  ---->
 o   ---->  ---->  ---->
 o   ---->  ---->  ---->
     (t)->  (t)->  (t)->

Typical analyses on this kind of signal will subsequently work across each channel independently, e.g., to find the mean response, so re-arranging the data to fit this paradigm makes sense.

Windowing repetitions of an irregularly sampled signal, however, must behave very differently. Each repetition has its own time vector, and so we can no longer share time across all dimensions or store the array in a densely packed format. In the example below, there are 12 independent signals! This could be represented by a signal containing a matrix of 1-element signals. Slicing across a channel ([:,i]) would yield a vector of 1-element Signals.

(t)      chan1       chan2       chan3

 o       * * *       * * *       * * *
      (t)o o o    (t)o o o    (t)o o o

 o       *  **       *  **       *  **
      (t)o  oo    (t)o  oo    (t)o  oo

 o       ** **       ** **       ** **
      (t)oo oo    (t)oo oo    (t)oo oo

 o       * **        * **        * ** 
      (t)o oo     (t)o oo     (t)o oo 

Again, typical analyses will work channel-by-channel, so there's not much to be gained by sharing the common time-points.

It's type-stable, but there is an asymmetry here. Grabbing a channel of the windowed regular signal will yield a Signal, whereas the windowed irregular signal gives us a Vector{Signal}. This feels wrong, but it completely represents the difference in complexity. I'll be wanting to create methods for those Vector{Signal}s (e.g., PSTH, raster, etc), which further makes me think that I want a new type here.

This is compounded by the fact that the kinds of analyses done on repetitions is very different from those done on independent channels.

Here's a brainstorm of one possible solution:

Other ideas:

I really like the idea of restricting Signals to only contain one matrix as data storage. Is there a way we could have the repetitions be a matrix? This would be tough, and probably problematic, as I'd want reps[:,i] to return a specialized repetition vector type. It could be made to be consistent, but it'd require totally re-inventing slice, sub and getindex.