-
Notifications
You must be signed in to change notification settings - Fork 0
Mapping
This document describes how the Neo data model is mapped into NIX when writing using the Neo-NixIO.
Each Neo object maps to at least one instance of a NIX object. Each object's attributes are mapped into the corresponding attributes in NIX. If there is no NIX attribute that holds the same meaning as the Neo attribute, the object's metadata section is used.
Each NIX object refers to one metadata Section.
This section shares the NIX object's name.
The type is the same as the type
attribute with the suffix .metadata
.
Metadata Sections are created when the object is created, even if there are no properties to be stored.
The NIX metadata tree reflects the Neo object tree.
Since Version 1.4.3, NIXPY allows any string to be used as a unit. Previously, NIX restricted dimensions to SI units. With this change, the Neo-NixIO can store any unit specified in Neo into the file without much trouble. In some situations, however, there is a small change that needs to be made for the data in the NIX file to be consistent.
Certain attribute values are scaled to fit a particular unit when writing.
The clearest example of this is t_start
for AnalogSignal
.
When written to NIX, this attribute is stored in the time dimension, a dimension object of type SampledDimension
.
The unit of this attribute must match the signal's time dimension unit (the offset
, which is the t_start
counterpart, does not have its own unit; instead it is stored in the time dimension and shares the same unit as the sampling frequency).
In the cases where it does not match, the attribute is rescaled to match, the original unit is stored as metadata, and it is restored to its original value when reading.
Example behaviour:
-
AnalogSignal
with:sampling_period = 0.1 * ms
t_start = 1 * s
- When writing to NIX this will be converted to a
DataArray
with aSampledDimension
to represent the time axis with:sampling_interval = 0.1
offset = 1000
unit = "ms"
- In order to losslessly recover the state of the original
AnalogSignal
, the following property is stored in theDataArray
's metadata:da.metadata["t_start"] = 1
da.metadata["t_start"].unit = "s"
Objects in Neo do not require names to be unique or non-empty. This is an issue for NIX since NIX requires non-empty, unique names. To work around this, the following naming scheme is implemented during writing:
- When a Neo object is written to NIX, a unique
nix_name
is generated. - The NIX name is added to the Neo object as an annotation (
nix_name
). - The Neo object's original name is stored in the NIX object's metadata (
neo_name
). - When reading the file, the Neo object's original name is restored and the autogenerated NIX name is stored as an annotation.
During step 1., if the Neo object already has a nix_name
annotation, that name is used instead of generating a new one.
See the Naming Example for an example of this behaviour.
When a Block is written to a file, the NixIO checks whether the neo.Block
has a nix_name
annotation.
If it does and it matches the name of a nix.Block
already in the file, the entire Block is deleted and rewritten.
If no conflict exists, the Block is written alongside existing ones.
See the Naming Example for an example of this behaviour.
Maps to nix.Block
.
-
Attributes
Neo NIX Block.name(string) Block.name(string) Block.description(string) Block.definition(string) Block.rec_datetime(datetime) Block.created_at(int) Block.file_datetime(datetime) Block.metadata(Section) [1] Block.file_origin(string) Block.metadata(Section) [1] -
Objects
- neo.Block.segments(Segment[]):
- Maps to nix.Block.groups(Group[]).
- See the neo.Segment section for details.
- neo.Block.channel_indexes(ChannelIndex[]):
- Maps to nix.Block.sources(Source[]) with
type = "neo.channelindex"
. - See the neo.ChannelIndex section for details.
- Maps to nix.Block.sources(Source[]) with
- neo.Block.segments(Segment[]):
Maps to nix.Group
.
-
Attributes
Neo NIX Segment.name(string) Group.name(string) Segment.description(string) Group.definition(string) Segment.rec_datetime(datetime) Group.created_at(int) Segment.file_datetime(datetime) Group.metadata(Section) [1] Segment.file_origin(string) Group.metadata(Section) [1] -
Objects
- Segment.analogsignals(AnalogSignal[]) & Segment.irregularlysampledsignals(IrregularlySampledSignal[]):
For each item in both lists, a
nix.DataArray
is created which holds the signal data and attributes. Thetype
attribute of theDataArray
is set toneo.analogsignal
orneo.irregularlysampledsignal
accordingly. These are stored in theGroup.data_arrays
list. See the neo.AnalogSignal and neo.IrregularlySampledSignal sections for details.- Signal objects in Neo can be grouped, e.g.,
Segment.analogsignals
is a list ofAnalogSignal
objects, each of which can hold multiple signals. In order to be able to reconstruct the original signal groupings, allDataArray
objects that belong to the sameAnalogSignal
(orIrregularlySampledSignal
) have theirmetadata
attribute point to the sameSection
.
- Signal objects in Neo can be grouped, e.g.,
- Segment.epochs(Epoch[]):
For each item in
Segment.epochs
, anix.MultiTag
is created withtype = neo.epoch
. This is stored in theGroup.multi_tags
list. See the neo.Epoch section for details. - Segment.events(Event[]):
For each item in
Segment.events
, anix.MultiTag
is created withtype = neo.event
. This is stored in theGroup.multi_tags
list. See the neo.Event section for details. - Segment.spiketrains(SpikeTrain[]):
For each item in
Segment.spiketrains
, anix.MultiTag
is created withtype = neo.spiketrain
. This is stored in theGroup.multi_tags
list. See the neo.SpikeTrain section for details.
- Segment.analogsignals(AnalogSignal[]) & Segment.irregularlysampledsignals(IrregularlySampledSignal[]):
For each item in both lists, a
Maps to nix.Source with type = neo.channelindex
.
-
Attributes
Neo NIX ChannelIndex.name(string) Source.name(string) ChannelIndex.description(string) Source.definition(string) -
Objects
- For each channel in
ChannelIndex
, determined by theindex
array, anix.Source
is created withtype = neo.channelindex
.- The name of each channel is the NIX name of the
ChannelIndex
object withChannelIndex<N>
to it (where<N>
is an incremental index). - Each channel has a metadata section which stores:
- A property that specifies its channel index, from
channel_indexes
. - A property that stores the corresponding name, from
channel_names
(if available). - A property that stores the corresponding id, from
channel_ids
(if available). - A property that stores the corresponding
(x, y, z)
coordinate, with unit, fromcoordinates
(if available).
- A property that specifies its channel index, from
- The name of each channel is the NIX name of the
-
ChannelIndex.units
Maps tonix.Source
withtype = neo.unit
. See the neo.Unit section for details.
- For each channel in
-
AnalogSignal and IrregularlySampledSignal references
- The
nix.DataArray
objects which represent theneo.AnalogSignal
andneo.IrregularlySampedSignal
objects referenced by theneo.ChannelIndex
, reference the respectivenix.Source
object (the reference direction is reversed).
- The
Maps to a nix.DataArray
with type = neo.analogsignal
.
-
Attributes
Neo NIX AnalogSignal.name(string) DataArray.name(string) AnalogSignal.description(string) DataArray.definition(string) -
Objects
- AnalogSignal.signal(Quantity 2D):
- Maps to a set of
DataArray.data(DataType[])
, one for each signal in the signal group. -
DataArray.unit(string)
is set based on the units of the Quantity array (AnalogSignal.signal
). -
DataArray.dimensions(Dimension[])
contains two objects:- A
SampledDimension
to denote that the signals are regularly sampled. The attributes of this dimension are:-
sampling_interval
assigned from the value ofAnalogSignal.sampling_rate(Quantity scalar)
. -
offset
assigned from the value ofAnalogSignal.t_start(Quantity scalar)
. -
unit
inheriting the value of theDataArray.unit
.
-
- A
SetDimension
to denote that the second dimension represents a set (collection) of signals.
- A
- Maps to a set of
- AnalogSignal.signal(Quantity 2D):
-
ChannelIndex references
- If a
neo.AnalogSignal
is referenced by aneo.ChannelIndex
, thenix.DataArray
s each reference the correspondingnix.Source
.
- If a
Maps to a nix.DataArray
with type = neo.irregularlysampledsignal
.
-
Attributes
Neo NIX IrregularlySampledSignal.name(string) DataArray.name(string) IrregularlySampledSignal.description(string) DataArray.definition(string) -
Objects
- IrregularlySampledSignal.signal(Quantity 2D):
- Maps to a set of
DataArray.data(DataType[])
, one for each signal in the signal group. -
DataArray.unit(string)
is set based on the units of the Quantity array (IrregularlySampledSignal.signal
). -
DataArray.dimensions(Dimension[])
contains two objects:- A
RangeDimension
to denote that the signals are irregularly sampled. The attributes of this dimension are:-
ticks
assigned from the value ofIrregularlySampledSignal.times(Quantity 1D)
. -
unit
inheriting the value of theDataArray.unit
.
-
- A
SetDimension
to denote that the second dimension represents a set (collection) of signals.
- A
- Maps to a set of
- IrregularlySampledSignal.signal(Quantity 2D):
-
ChannelIndex references
- If a
neo.IrregularlySampedSignal
is referenced by aneo.ChannelIndex
, thenix.DataArray
s each reference the correspondingnix.Source
.
- If a
Maps to a nix.MultiTag
with type = neo.epoch
.
-
Attributes
Neo NIX Epoch.name(string) MultiTag.name(string) Epoch.description(string) MultiTag.definition(string) -
Objects
- Epoch.times(Quantity 1D) maps to
MultiTag.positions(DataArray)
with typeneo.epoch.times
. - Epoch.durations(Quantity 1D) maps to
MultiTag.extents(DataArray)
with typeneo.epoch.durations
. - Epoch.labels(string[]) maps to the
labels
attribute of aSetDimension
of the positionsDataArray
. TheSetDimension
is also referenced by the extentsDataArray
. - The
references
attribute of thenix.MultiTag
points to all theAnalogSignal
andIrregularlySampledSignal
objects that exist in the sameneo.Segment
as the epoch.
- Epoch.times(Quantity 1D) maps to
Maps to a nix.MultiTag
with type = neo.event
.
-
Attributes
Neo NIX Event.name(string) MultiTag.name(string) Event.description(string) MultiTag.definition(string) -
Objects
- Event.times(Quantity 1D) maps to
MultiTag.positions(DataArray)
with typeneo.event.times
. - Event.labels(string[]) maps to the
labels
attribute of aSetDimension
of the positionsDataArray
. - The
references
attribute of thenix.MultiTag
points to all theAnalogSignal
andIrregularlySampledSignal
objects that exist in the sameneo.Segment
as the event.
- Event.times(Quantity 1D) maps to
Maps to a nix.MultiTag
with type = neo.spiketrain
.
-
Attributes
Neo NIX SpikeTrain.name(string) MultiTag.name(string) SpikeTrain.description(string) MultiTag.definition(string) SpikeTrain.t_start(Quantity scalar) MultiTag.metadata(Section) [1] SpikeTrain.t_stop(Quantity scalar) MultiTag.metadata(Section) [1] SpikeTrain.left_sweep(Quantity scalar) MultiTag.metadata(Section) [1] -
Objects
- SpikeTrain.times(Quantity 1D):
- Maps to
MultiTag.positions(DataArray)
. - The positions
DataArray
is of typeneo.spiketrain
and has a singleSetDimension
.
- Maps to
- SpikeTrain.waveforms(Quantity 3D):
- Waveform data and metadata associated with spikes are stored in a
DataArray
of typeneo.waveforms
. - The
DataArray
is associated with the spiketrainMultiTag
via anix.Feature
. Specifically,MultiTag.features
holds a reference to a singleFeature
withlink_type = indexed
. -
Feature.data
refers to theDataArray
where the waveforms are stored. - The
DataArray
also refers to ametadata
Section that stores theleft_sweep
value. - The
DataArray
has 3 dimensions:-
SetDimension
. -
SetDimension
. -
SampledDimension
: TheSpikeTrain.sampling_rate
is stored in this dimension'ssampling_interval
and theunit
is set accordingly.
-
- Waveform data and metadata associated with spikes are stored in a
- SpikeTrain.times(Quantity 1D):
-
Unit references
- If a
neo.SpikeTrain
is referenced by aneo.Unit
, thenix.MultiTag
references the correspondingnix.Source
as well as the Unit's parentneo.ChannelIndex
.
- If a
Maps to a nix.Source
with type = neo.unit
.
-
Attributes
Neo NIX Unit.name(string) Source.name(string) Unit.description(string) Source.definition(string) -
nix.Source
objects that representneo.Unit
s are created on the correspondingnix.Source
which represents the originalneo.RecordingChannelGroup
. -
SpikeTrain references
- The
nix.MultiTag
objects which represent theneo.SpikeTrain
objects referenced by theneo.Unit
, reference the respectivenix.Source
object (the reference direction is reversed).
- The