From 6a2bbccc1ff2a6c0ffb472ab5517ff6767614a00 Mon Sep 17 00:00:00 2001 From: ehennestad Date: Thu, 21 Nov 2024 21:23:26 +0100 Subject: [PATCH] Use name=value syntax for intro tutorial #570 --- tutorials/html/intro.html | 92 ++++++++++++++++---------------- tutorials/intro.mlx | Bin 221807 -> 221806 bytes tutorials/private/mcode/intro.m | 76 +++++++++++++------------- 3 files changed, 84 insertions(+), 84 deletions(-) diff --git a/tutorials/html/intro.html b/tutorials/html/intro.html index b73348b8..a4b4c878 100644 --- a/tutorials/html/intro.html +++ b/tutorials/html/intro.html @@ -85,7 +85,7 @@ Write Read Reading Data -Next Steps

Installing MatNWB

Use the code below within the brackets to install MatNWB from source. MatNWB works by automatically creating API classes based on the schema.
%{
!git clone https://github.com/NeurodataWithoutBorders/matnwb.git
addpath(genpath(pwd));
%}

Set up the NWB File

An NWB file represents a single session of an experiment. Each file must have a session_description, identifier, and session start time. Create a new NWBFile object with those and additional metadata using the NwbFile command. For all MatNWB classes and functions, we use the Matlab method of entering keyword argument pairs, where arguments are entered as name followed by value. Ellipses are used for clarity.
nwb = NwbFile( ...
'session_description', 'mouse in open exploration',...
'identifier', 'Mouse5_Day3', ...
'session_start_time', datetime(2018, 4, 25, 2, 30, 3, 'TimeZone', 'local'), ...
'general_experimenter', 'Last, First', ... % optional
'general_session_id', 'session_1234', ... % optional
'general_institution', 'University of My Institution', ... % optional
'general_related_publications', {'DOI:10.1016/j.neuron.2016.12.011'}); % optional
nwb
nwb =
NwbFile with properties: +Next Steps

Installing MatNWB

Use the code below within the brackets to install MatNWB from source. MatNWB works by automatically creating API classes based on the schema.
%{
!git clone https://github.com/NeurodataWithoutBorders/matnwb.git
addpath(genpath(pwd));
%}

Set up the NWB File

An NWB file represents a single session of an experiment. Each file must have a session_description, identifier, and session start time. Create a new NWBFile object with those and additional metadata using the NwbFile command. For all MatNWB classes and functions, we use the Matlab method of entering keyword argument pairs, where arguments are entered as name followed by value. Ellipses are used for clarity.
nwb = NwbFile( ...
session_description='mouse in open exploration',...
identifier='Mouse5_Day3', ...
session_start_time=datetime(2018, 4, 25, 2, 30, 3, 'TimeZone', 'local'), ...
general_experimenter='Last, First', ... % optional
general_session_id='session_1234', ... % optional
general_institution='University of My Institution', ... % optional
general_related_publications={'DOI:10.1016/j.neuron.2016.12.011'}); % optional
nwb
nwb =
NwbFile with properties: nwb_version: '2.7.0' file_create_date: [] @@ -138,7 +138,7 @@ units: [] Warning: The following required properties are missing for instance for type "NwbFile": - timestamps_reference_time

Subject Information

You can also provide information about your subject in the NWB file. Create a Subject object to store information such as age, species, genotype, sex, and a freeform description. Then set nwb.general_subject to the Subject object.
Each of these fields is free-form, so any values will be valid, but here are our recommendations:
  • For age, we recommend using the ISO 8601 Duration format
  • For species, we recommend using the formal latin binomal name (e.g. mouse -> Mus musculus, human -> Homo sapiens)
  • For sex, we recommend using F (female), M (male), U (unknown), and O (other)
subject = types.core.Subject( ...
'subject_id', '001', ...
'age', 'P90D', ...
'description', 'mouse 5', ...
'species', 'Mus musculus', ...
'sex', 'M' ...
);
nwb.general_subject = subject;
 
subject
subject =
Subject with properties: + timestamps_reference_time

Subject Information

You can also provide information about your subject in the NWB file. Create a Subject object to store information such as age, species, genotype, sex, and a freeform description. Then set nwb.general_subject to the Subject object.
Each of these fields is free-form, so any values will be valid, but here are our recommendations:
  • For age, we recommend using the ISO 8601 Duration format
  • For species, we recommend using the formal latin binomal name (e.g. mouse -> Mus musculus, human -> Homo sapiens)
  • For sex, we recommend using F (female), M (male), U (unknown), and O (other)
subject = types.core.Subject( ...
subject_id='001', ...
age='P90D', ...
description='mouse 5', ...
species='Mus musculus', ...
sex='M' ...
);
nwb.general_subject = subject;
 
subject
subject =
Subject with properties: age: 'P90D' age_reference: 'birth' @@ -150,10 +150,10 @@ strain: '' subject_id: '001' weight: '' -
Note: the DANDI archive requires all NWB files to have a subject object with subject_id specified, and strongly encourages specifying the other fields.

Time Series Data

TimeSeries is a common base class for measurements sampled over time, and provides fields for data and timestamps (regularly or irregularly sampled). You will also need to supply the name and unit of measurement (SI unit).
For instance, we can store a TimeSeries data where recording started 0.0 seconds after start_time and sampled every second (1 Hz):
time_series_with_rate = types.core.TimeSeries( ...
'description', 'an example time series', ...
'data', linspace(0, 100, 10), ...
'data_unit', 'm', ...
'starting_time', 0.0, ...
'starting_time_rate', 1.0);
For irregularly sampled recordings, we need to provide the timestamps for the data:
time_series_with_timestamps = types.core.TimeSeries( ...
'description', 'an example time series', ...
'data', linspace(0, 100, 10), ...
'data_unit', 'm', ...
'timestamps', linspace(0, 1, 10));
The TimeSeries class serves as the foundation for all other time series types in the NWB format. Several specialized subclasses extend the functionality of TimeSeries, each tailored to handle specific kinds of data. In the next section, we’ll explore one of these specialized types. For a full overview, please check out the type hierarchy in the NWB schema documentation.

Other Types of Time Series

As mentioned previously, there are many subtypes of TimeSeries in MatNWB that are used to store different kinds of data. One example is AnnotationSeries, a subclass of TimeSeries that stores text-based records about the experiment. Similar to our TimeSeries example above, we can create an AnnotationSeries object with text information about a stimulus and add it to the stimulus_presentation group in the NWBFile. Below is an example where we create an AnnotationSeries object with annotations for airpuff stimuli and add it to the NWBFile.
% Create an AnnotationSeries object with annotations for airpuff stimuli
annotations = types.core.AnnotationSeries( ...
'description', 'Airpuff events delivered to the animal', ...
'data', {'Left Airpuff', 'Right Airpuff', 'Right Airpuff'}, ...
'timestamps', [1.0, 3.0, 8.0] ...
);
 
% Add the AnnotationSeries to the NWBFile's stimulus group
nwb.stimulus_presentation.set('Airpuffs', annotations)
ans =
Set with properties: +
Note: the DANDI archive requires all NWB files to have a subject object with subject_id specified, and strongly encourages specifying the other fields.

Time Series Data

TimeSeries is a common base class for measurements sampled over time, and provides fields for data and timestamps (regularly or irregularly sampled). You will also need to supply the name and unit of measurement (SI unit).
For instance, we can store a TimeSeries data where recording started 0.0 seconds after start_time and sampled every second (1 Hz):
time_series_with_rate = types.core.TimeSeries( ...
description='an example time series', ...
data=linspace(0, 100, 10), ...
data_unit='m', ...
starting_time=0.0, ...
starting_time_rate=1.0);
For irregularly sampled recordings, we need to provide the timestamps for the data:
time_series_with_timestamps = types.core.TimeSeries( ...
description='an example time series', ...
data=linspace(0, 100, 10), ...
data_unit='m', ...
timestamps=linspace(0, 1, 10));
The TimeSeries class serves as the foundation for all other time series types in the NWB format. Several specialized subclasses extend the functionality of TimeSeries, each tailored to handle specific kinds of data. In the next section, we’ll explore one of these specialized types. For a full overview, please check out the type hierarchy in the NWB schema documentation.

Other Types of Time Series

As mentioned previously, there are many subtypes of TimeSeries in MatNWB that are used to store different kinds of data. One example is AnnotationSeries, a subclass of TimeSeries that stores text-based records about the experiment. Similar to our TimeSeries example above, we can create an AnnotationSeries object with text information about a stimulus and add it to the stimulus_presentation group in the NWBFile. Below is an example where we create an AnnotationSeries object with annotations for airpuff stimuli and add it to the NWBFile.
% Create an AnnotationSeries object with annotations for airpuff stimuli
annotations = types.core.AnnotationSeries( ...
description='Airpuff events delivered to the animal', ...
data={'Left Airpuff', 'Right Airpuff', 'Right Airpuff'}, ...
timestamps=[1.0, 3.0, 8.0] ...
);
 
% Add the AnnotationSeries to the NWBFile's stimulus group
nwb.stimulus_presentation.set(Airpuffs=annotations)
ans =
Set with properties: Airpuffs: [types.core.AnnotationSeries] -

Behavior

SpatialSeries and Position

Many types of data have special data types in NWB. To store the spatial position of a subject, we will use the SpatialSeries and Position classes.
Note: These diagrams follow a standard convention called "UML class diagram" to express the object-oriented relationships between NWB classes. For our purposes, all you need to know is that an open triangle means "extends" (i.e., is a specialized subtype of), and an open diamond means "is contained within." Learn more about class diagrams on the wikipedia page.
SpatialSeries is a subclass of TimeSeries, a common base class for measurements sampled over time, and provides fields for data and time (regularly or irregularly sampled). Here, we put a SpatialSeries object called 'SpatialSeries' in a Position object. If the data is sampled at a regular interval, it is recommended to specify the starting_time and the sampling rate (starting_time_rate), although it is still possible to specify timestamps as in the time_series_with_timestamps example above.
% create SpatialSeries object
spatial_series_ts = types.core.SpatialSeries( ...
'data', [linspace(0,10,100); linspace(0,8,100)], ...
'reference_frame', '(0,0) is bottom left corner', ...
'starting_time', 0, ...
'starting_time_rate', 200 ...
);
 
% create Position object and add SpatialSeries
position = types.core.Position('SpatialSeries', spatial_series_ts);
NWB differentiates between raw, acquired data, which should never change, and processed data, which are the results of preprocessing algorithms and could change. Let's assume that the animal's position was computed from a video tracking algorithm, so it would be classified as processed data. Since processed data can be very diverse, NWB allows us to create processing modules, which are like folders, to store related processed data or data that comes from a single algorithm.
Create a processing module called "behavior" for storing behavioral data in the NWBFile and add the Position object to the module.
% create processing module
behavior_module = types.core.ProcessingModule('description', 'contains behavioral data');
 
% add the Position object (that holds the SpatialSeries object) to the module
% and name the Position object "Position"
behavior_module.nwbdatainterface.set('Position', position);
 
% add the processing module to the NWBFile object, and name the processing module "behavior"
nwb.processing.set('behavior', behavior_module);

Trials

Trials are stored in a TimeIntervals object which is a subclass of DynamicTable. DynamicTable objects are used to store tabular metadata throughout NWB, including for trials, electrodes, and sorted units. They offer flexibility for tabular data by allowing required columns, optional columns, and custom columns.
The trials DynamicTable can be thought of as a table with this structure:
Trials are stored in a TimeIntervals object which subclasses DynamicTable. Here, we are adding 'correct', which will be a logical array.
trials = types.core.TimeIntervals( ...
'colnames', {'start_time', 'stop_time', 'correct'}, ...
'description', 'trial data and properties');
 
trials.addRow('start_time', 0.1, 'stop_time', 1.0, 'correct', false)
trials.addRow('start_time', 1.5, 'stop_time', 2.0, 'correct', true)
trials.addRow('start_time', 2.5, 'stop_time', 3.0, 'correct', false)
 
trials.toTable() % visualize the table
ans = 3×4 table
 idstart_timestop_timecorrect
100.100010
211.500021
322.500030
nwb.intervals_trials = trials;
 
% If you have multiple trials tables, you will need to use custom names for
% each one:
nwb.intervals.set('custom_intervals_table_name', trials);

Write

Now, to write the NWB file that we have built so far:
nwbExport(nwb, 'intro_tutorial.nwb')
We can use the HDFView application to inspect the resulting NWB file.

Read

We can then read the file back in using MatNWB and inspect its contents.
read_nwbfile = nwbRead('intro_tutorial.nwb', 'ignorecache')
read_nwbfile =
NwbFile with properties: +

Behavior

SpatialSeries and Position

Many types of data have special data types in NWB. To store the spatial position of a subject, we will use the SpatialSeries and Position classes.
Note: These diagrams follow a standard convention called "UML class diagram" to express the object-oriented relationships between NWB classes. For our purposes, all you need to know is that an open triangle means "extends" (i.e., is a specialized subtype of), and an open diamond means "is contained within." Learn more about class diagrams on the wikipedia page.
SpatialSeries is a subclass of TimeSeries, a common base class for measurements sampled over time, and provides fields for data and time (regularly or irregularly sampled). Here, we put a SpatialSeries object called 'SpatialSeries' in a Position object. If the data is sampled at a regular interval, it is recommended to specify the starting_time and the sampling rate (starting_time_rate), although it is still possible to specify timestamps as in the time_series_with_timestamps example above.
% create SpatialSeries object
spatial_series_ts = types.core.SpatialSeries( ...
data=[linspace(0,10,100); linspace(0,8,100)], ...
reference_frame='(0,0) is bottom left corner', ...
starting_time=0, ...
starting_time_rate=200 ...
);
 
% create Position object and add SpatialSeries
position = types.core.Position('SpatialSeries', spatial_series_ts);
NWB differentiates between raw, acquired data, which should never change, and processed data, which are the results of preprocessing algorithms and could change. Let's assume that the animal's position was computed from a video tracking algorithm, so it would be classified as processed data. Since processed data can be very diverse, NWB allows us to create processing modules, which are like folders, to store related processed data or data that comes from a single algorithm.
Create a processing module called "behavior" for storing behavioral data in the NWBFile and add the Position object to the module.
% create processing module
behavior_module = types.core.ProcessingModule(description='contains behavioral data');
 
% add the Position object (that holds the SpatialSeries object) to the module
% and name the Position object "Position"
behavior_module.nwbdatainterface.set(Position=position);
 
% add the processing module to the NWBFile object, and name the processing module "behavior"
nwb.processing.set(behavior=behavior_module);

Trials

Trials are stored in a TimeIntervals object which is a subclass of DynamicTable. DynamicTable objects are used to store tabular metadata throughout NWB, including for trials, electrodes, and sorted units. They offer flexibility for tabular data by allowing required columns, optional columns, and custom columns.
The trials DynamicTable can be thought of as a table with this structure:
Trials are stored in a TimeIntervals object which subclasses DynamicTable. Here, we are adding 'correct', which will be a logical array.
trials = types.core.TimeIntervals( ...
colnames={'start_time', 'stop_time', 'correct'}, ...
description='trial data and properties');
 
trials.addRow(start_time=0.1, stop_time=1.0, correct=false)
trials.addRow(start_time=1.5, stop_time=2.0, correct=true)
trials.addRow(start_time=2.5, stop_time=3.0, correct=false)
 
trials.toTable() % visualize the table
ans = 3×4 table
 idstart_timestop_timecorrect
100.100010
211.500021
322.500030
nwb.intervals_trials = trials;
 
% If you have multiple trials tables, you will need to use custom names for
% each one:
nwb.intervals.set(custom_intervals_table_name=trials);

Write

Now, to write the NWB file that we have built so far:
nwbExport(nwb, 'intro_tutorial.nwb')
We can use the HDFView application to inspect the resulting NWB file.

Read

We can then read the file back in using MatNWB and inspect its contents.
read_nwbfile = nwbRead('intro_tutorial.nwb', 'ignorecache')
read_nwbfile =
NwbFile with properties: nwb_version: '2.7.0' file_create_date: [1×1 types.untyped.DataStub] @@ -204,7 +204,7 @@ stimulus_presentation: [1×1 types.untyped.Set] stimulus_templates: [0×1 types.untyped.Set] units: [] -
We can print the SpatialSeries data traversing the hierarchy of objects. The processing module called 'behavior' contains our Position object named 'Position'. The Position object contains our SpatialSeries object named 'SpatialSeries'.
read_spatial_series = read_nwbfile.processing.get('behavior'). ...
nwbdatainterface.get('Position').spatialseries.get('SpatialSeries')
read_spatial_series =
SpatialSeries with properties: +
We can print the SpatialSeries data traversing the hierarchy of objects. The processing module called 'behavior' contains our Position object named 'Position'. The Position object contains our SpatialSeries object named 'SpatialSeries'.
read_spatial_series = read_nwbfile.processing.get('behavior'). ...
nwbdatainterface.get('Position').spatialseries.get('SpatialSeries')
read_spatial_series =
SpatialSeries with properties: reference_frame: '(0,0) is bottom left corner' starting_time_unit: 'seconds' @@ -223,16 +223,16 @@ starting_time: 0 starting_time_rate: 200 timestamps: [] -

Reading Data

Counter to normal MATLAB workflow, data arrays are read passively from the file. Calling read_spatial_series.data does not read the data values, but presents a DataStub object that can be indexed to read data.
read_spatial_series.data
ans =
DataStub with properties: +

Reading Data

Counter to normal MATLAB workflow, data arrays are read passively from the file. Calling read_spatial_series.data does not read the data values, but presents a DataStub object that can be indexed to read data.
read_spatial_series.data
ans =
DataStub with properties: filename: 'intro_tutorial.nwb' path: '/processing/behavior/Position/SpatialSeries/data' dims: [2 100] ndims: 2 dataType: 'double' -
This allows you to conveniently work with datasets that are too large to fit in RAM all at once. Access all the data in the matrix using the load method with no arguments.
read_spatial_series.data.load
ans = 2×100
0 0.1010 0.2020 0.3030 0.4040 0.5051 0.6061 0.7071 0.8081 0.9091 1.0101 1.1111 1.2121 1.3131 1.4141 1.5152 1.6162 1.7172 1.8182 1.9192 2.0202 2.1212 2.2222 2.3232 2.4242 2.5253 2.6263 2.7273 2.8283 2.9293 3.0303 3.1313 3.2323 3.3333 3.4343 3.5354 3.6364 3.7374 3.8384 3.9394 4.0404 4.1414 4.2424 4.3434 4.4444 4.5455 4.6465 4.7475 4.8485 4.9495 +
This allows you to conveniently work with datasets that are too large to fit in RAM all at once. Access all the data in the matrix using the load method with no arguments.
read_spatial_series.data.load
ans = 2×100
0 0.1010 0.2020 0.3030 0.4040 0.5051 0.6061 0.7071 0.8081 0.9091 1.0101 1.1111 1.2121 1.3131 1.4141 1.5152 1.6162 1.7172 1.8182 1.9192 2.0202 2.1212 2.2222 2.3232 2.4242 2.5253 2.6263 2.7273 2.8283 2.9293 3.0303 3.1313 3.2323 3.3333 3.4343 3.5354 3.6364 3.7374 3.8384 3.9394 4.0404 4.1414 4.2424 4.3434 4.4444 4.5455 4.6465 4.7475 4.8485 4.9495 0 0.0808 0.1616 0.2424 0.3232 0.4040 0.4848 0.5657 0.6465 0.7273 0.8081 0.8889 0.9697 1.0505 1.1313 1.2121 1.2929 1.3737 1.4545 1.5354 1.6162 1.6970 1.7778 1.8586 1.9394 2.0202 2.1010 2.1818 2.2626 2.3434 2.4242 2.5051 2.5859 2.6667 2.7475 2.8283 2.9091 2.9899 3.0707 3.1515 3.2323 3.3131 3.3939 3.4747 3.5556 3.6364 3.7172 3.7980 3.8788 3.9596 -
If you only need a section of the data, you can read only that section by indexing the DataStub object like a normal array in MATLAB. This will just read the selected region from disk into RAM. This technique is particularly useful if you are dealing with a large dataset that is too big to fit entirely into your available RAM.
read_spatial_series.data(:, 1:10)
ans = 2×10
0 0.1010 0.2020 0.3030 0.4040 0.5051 0.6061 0.7071 0.8081 0.9091 +
If you only need a section of the data, you can read only that section by indexing the DataStub object like a normal array in MATLAB. This will just read the selected region from disk into RAM. This technique is particularly useful if you are dealing with a large dataset that is too big to fit entirely into your available RAM.
read_spatial_series.data(:, 1:10)
ans = 2×10
0 0.1010 0.2020 0.3030 0.4040 0.5051 0.6061 0.7071 0.8081 0.9091 0 0.0808 0.1616 0.2424 0.3232 0.4040 0.4848 0.5657 0.6465 0.7273

Next Steps

This concludes the introductory tutorial. Please proceed to one of the specialized tutorials, which are designed to follow this one.
See the API documentation to learn what data types are available.

@@ -256,13 +256,13 @@ % followed by value. Ellipses are used for clarity. nwb = NwbFile( ... - 'session_description', 'mouse in open exploration',... - 'identifier', 'Mouse5_Day3', ... - 'session_start_time', datetime(2018, 4, 25, 2, 30, 3, 'TimeZone', 'local'), ... - 'general_experimenter', 'Last, First', ... % optional - 'general_session_id', 'session_1234', ... % optional - 'general_institution', 'University of My Institution', ... % optional - 'general_related_publications', {'DOI:10.1016/j.neuron.2016.12.011'}); % optional + session_description='mouse in open exploration',... + identifier='Mouse5_Day3', ... + session_start_time=datetime(2018, 4, 25, 2, 30, 3, 'TimeZone', 'local'), ... + general_experimenter='Last, First', ... % optional + general_session_id='session_1234', ... % optional + general_institution='University of My Institution', ... % optional + general_related_publications={'DOI:10.1016/j.neuron.2016.12.011'}); % optional nwb %% Subject Information % You can also provide information about your subject in the NWB file. Create @@ -283,11 +283,11 @@ % * For |sex|, we recommend using F (female), M (male), U (unknown), and O (other) subject = types.core.Subject( ... - 'subject_id', '001', ... - 'age', 'P90D', ... - 'description', 'mouse 5', ... - 'species', 'Mus musculus', ... - 'sex', 'M' ... + subject_id='001', ... + age='P90D', ... + description='mouse 5', ... + species='Mus musculus', ... + sex='M' ... ); nwb.general_subject = subject; @@ -309,20 +309,20 @@ % and sampled every second (1 Hz): time_series_with_rate = types.core.TimeSeries( ... - 'description', 'an example time series', ... - 'data', linspace(0, 100, 10), ... - 'data_unit', 'm', ... - 'starting_time', 0.0, ... - 'starting_time_rate', 1.0); + description='an example time series', ... + data=linspace(0, 100, 10), ... + data_unit='m', ... + starting_time=0.0, ... + starting_time_rate=1.0); %% % For irregularly sampled recordings, we need to provide the |timestamps| for % the |data|: time_series_with_timestamps = types.core.TimeSeries( ... - 'description', 'an example time series', ... - 'data', linspace(0, 100, 10), ... - 'data_unit', 'm', ... - 'timestamps', linspace(0, 1, 10)); + description='an example time series', ... + data=linspace(0, 100, 10), ... + data_unit='m', ... + timestamps=linspace(0, 1, 10)); %% % The class serves as the foundation for all other time series types @@ -347,13 +347,13 @@ % Create an AnnotationSeries object with annotations for airpuff stimuli annotations = types.core.AnnotationSeries( ... - 'description', 'Airpuff events delivered to the animal', ... - 'data', {'Left Airpuff', 'Right Airpuff', 'Right Airpuff'}, ... - 'timestamps', [1.0, 3.0, 8.0] ... + description='Airpuff events delivered to the animal', ... + data={'Left Airpuff', 'Right Airpuff', 'Right Airpuff'}, ... + timestamps=[1.0, 3.0, 8.0] ... ); % Add the AnnotationSeries to the NWBFile's stimulus group -nwb.stimulus_presentation.set('Airpuffs', annotations) +nwb.stimulus_presentation.set(Airpuffs=annotations) %% Behavior % SpatialSeries and Position % Many types of data have special data types in NWB. To store the spatial position @@ -383,10 +383,10 @@ % create SpatialSeries object spatial_series_ts = types.core.SpatialSeries( ... - 'data', [linspace(0,10,100); linspace(0,8,100)], ... - 'reference_frame', '(0,0) is bottom left corner', ... - 'starting_time', 0, ... - 'starting_time_rate', 200 ... + data=[linspace(0,10,100); linspace(0,8,100)], ... + reference_frame='(0,0) is bottom left corner', ... + starting_time=0, ... + starting_time_rate=200 ... ); % create Position object and add SpatialSeries @@ -406,14 +406,14 @@ % |*Position*|> object to the module. % create processing module -behavior_module = types.core.ProcessingModule('description', 'contains behavioral data'); +behavior_module = types.core.ProcessingModule(description='contains behavioral data'); % add the Position object (that holds the SpatialSeries object) to the module % and name the Position object "Position" -behavior_module.nwbdatainterface.set('Position', position); +behavior_module.nwbdatainterface.set(Position=position); % add the processing module to the NWBFile object, and name the processing module "behavior" -nwb.processing.set('behavior', behavior_module); +nwb.processing.set(behavior=behavior_module); % Trials % Trials are stored in a object which is a subclass of kji!20LoZvx%ySsaEcMI+iJV9^HcfPuJYTkaj zrn)b!_{}0GN{pE95bu`uG3;IyxqpErd8kA=&P;G90jI@FeNL8={9L=d)Io@ z`l@?wp(VoFD5g0pPRH3fCPz_<5y#1aU|!F6deDM=81`f$B`fDaKw><4X#RWaSvQ@Y zZR0MXir33aGkFHnlM-nxM)-&D1M9^K)YKTYvxgzFC@S?FPHd>I^N5>77C*?#gC=2s zCTRz?Vt!|V*^Ubj`nfcFII_($dl6OJrQ-TAg~OG9$;@ZBuw= z^zKES5V#U4pW&rZ3Uv=eS(tB;{sey70hJ4%Bd-)U^r+F>uis(ks?AM0dY|=Q8D&vENf46WRHH4TRdB@}YO)BCY+g^&HF(eJ^K;xEKHtxxL&b^HkzroDh;0~}ZM zb@|d!gyVpeK`IJAZjb9+-WgvE)AXZT%|Pu7!{`(8+fml3d!eMy%^mwv|P!Ck$fLWyh;cQ&>a}5sPi>2$ZBte3X+#$CU-Qc5#>T~5m=u!XG1@8o(XAq z#Ribq^-4B#KtJ;n`wI)ZwFLjUJkBdk+Upo&Or5&{J66Od~{&M;dAQ@#qJDy%YqMK$vN2%`M+m;VX1tr$rVc{JgsPCzIa&=%F|p z@Icu}5dxdFdQ6*~CG$BCl?e06tc9II+^RIC+?_thNgjn%IxcoKFU=_|Q8$FA8_3%& z5Lskx&sd6HeGbwr!(9B>i>xmjJn#Tv<%AMH!}&G?)%@BJvFHkM2%63;2*HX&TaW>- zphaL)qB~NvYeXM36S!^#i$!9NwyS+6QpzI-UD<;u%6K^@Iic_>rY>LD5D}$r?klI; zR}(N-qrUz~3?@T259J0+d3_SV*}eu5FKAnq6-^35Q9Hj(MrA98i#Q!J8U%9rCTBdd zN{B0&lrFXNTP7}K?FPInXWKoCAcg|h$7HckB$0Y8K`jHTtWpRg0bl_ju8;XW1Y)Iy zH)r%)d=rdsjEMP}D!Q~z9vOv(iD=KfH*!Cip*v<#Q){;# zMYb8mMoAPZUSTh`yc!&LNe=4EBi?ZOkC9`0?hSF1=HC!Y{NCHG4Mg13AKJXeg+L>G z^x^2h*b*=(VN3@D>UgWuvuu6?Ha4b%`F)=rk6Wd%78j0IXT(i%c}Ub6=R~SL_GVj#8XF)Zo+OC>=syg z^00@t#_asJ$;pTvZfk6mVHY*JtYPn;R5DQp;3lIIWj*{5fGFVa(xZL^e+WpzwFa?a zx-`Mub2iZlQ_<+*KTAKUF3fTNfWhsRfx@H{p<`08{$<<6;m8^dMzOU(8xxkPD^Lhr zxJ?hwVuaq(*>OT zh1>HZBL+d}L1naop_2rVpHv#s#rK9QM@qwjAB2c&6lF@w0e61t82S}F$+^V1-sthA zi%`qTN3t8~ZxE`f>B&y!Z$3I05@jfnFFHAv#@-GS|sz}r?775s+=!5s7YH>d;tpqUi8boCFU ztQy3eq^@tEq~EkFyKsILW~QJsQZl|QkeGV2X=-Xt(@Gv;kIkA<$=XSHP3p%^tOa-= z8AYn>hUjV_#M=gQ52t)mXZN10L}yO#V@}WQD3p;Qq+JPzhiq$6-A;-}p2RPq~$@zk;HBiKH(NHU5HEnPmntGvGyY4R^=Auvgv1sf;|4F~c{( z*bvI3U$LZ3BTF5R$0|uXEkyZAY0s0Db_yL>-2C>p&BOJZDpw-9vy;5GIH5HD;kT*+ zx8JVWxxU-Zs&l3Q!@KjT<+Q)eT@Ae%Lz#uAX2xA&q5@*V96WDbL(BK#kxDtU=wfal zkzQC(=019#0JPyOmlSu$C%mkj=uDi^$>m3FT$X|x#D*dGx;LjJ7-U&prD<8O1j%jWzs?pwpmQmr<=k@J-)d#*NC7`=%d>*?gQ(V>m zu2?cB*+~>Rp0d{Dn@4%1j`qulfHf*a21>~maf}F4$7)VJh&;dQ*tkLP5|gOK>4 z=p|W)0fSY@(b$7( zpw;t0xZg@jHxG232)7WIw!1fy`p(WNgt*nMk=@3BJ_*02=2lUi#V=$n^tqRkEye8n zydYmGFg3f7R>+yBN_~K5Tx|1AROEtwjBLme4m@RnA4bb`M+ox()I`I)abJw^B;CSn zgJVkf$J2B}Puy1*L~vcoY=dv&s}L9HIYb#>R+4b()D~Kn7s-AeA>(SAk2!?dP(lJ+ z?pQdIh4$=JYFr#%g;RyTkt@Lijdt3HTy+o8gY~IA7|fjHD_)uU5>@tqG7EmX1qJXitn|D(0>7;Mv^6> zEh=cNN9D&`bjf6{Ft#Z6ysmv=$G1w+lHZ`MtMRoDU>IplBi`Yd6E{3q*Ke_xNYP|E zlATsUfJ_Pl)$P5qUv78m-1;?Us88wuCpQHiDwN+}=((ST<$dCifJ-dwZ=B1U&VXB_ zPlioT12(PLa7_8ozHx)>yk9^tDwWcXrIX*1{_K3bQ|RN6nGvAgee-^6gNBLBc#Al-{c z2@{n>i`P*7Pz|(?@}OOvW)6RsJvowaqQ_D|Yh&hiyG?9m2oROPBK(OX{0GN*S_M2F zaNa5B+#F81C~To4kbU97l{V^i^kG>RVGllm9-_VI)e{QUVQGq1B$M2>DP=dED1e0{ zR7AF_V==Ft?PMcniwS<)J={gYgMu|8ls(Z8Ou9Z*` zeqNLa`A@1RhU#&%R`HPB0Trvsi`TH8#WlEIRbFni;HqkgQ%e5Aon=xc+IP6ITPTH;dg>s^S9G*bQ3dzlelZvt;n>^_CF~K)abg%WveaKC&%w{-8 zk^ylm@zX>~#s;6tBp2a)P-u_;1s6Z+Ra0fy?wF(oJ+oP@7@=>8gPx=!Iv+kF?B(jB z(o7{LA5N8^p*5Tk_A;I$Em$ld4Tn%@W|lm5p3o2NsHRXDNLu1A0j<5Dv9p*9<@G2# zoV;MrTmbr&&#Tk4@~OP80tnWoc>~T%D~Z+B*)?o7oCGbp-8lvQmeq&~7W1}Fy35qlcwLx=rYthjg=B)62K1gAg4sQ+#=k!Uh zDqkRifrIQ!fraH-_+SWh1d*jR@B!Mri@1Xg11K>Bj0DK zi%ch^a`aWy!&yl>1067~NRi$y&PfQBy~&V5ndFC&5Ru9N^I-l1pl&O$O0F#L753+o z1c=dJn_NG=_Ls}6(aMJeZQ{E%{kveR0`JCT zU_|kl%b|}G5|qKl8EisTeL#j$fFZhLKgj>HvL!3OUZRy)1)JAxMCZY`Om<Od-rQ@M_1pY|(E^7>Vt|s4R6nfm%bGB zKoUXAfN^YHAE}C_B}10I9^K6lKyTI+m0L{s-UG>McV9Uiku}zcxBWbzb?ZSK)=V#q+Pz2+ z9Y<=mJ~Ps~rHzNB z2xG6RPD?kdJ>OJjmiAaP`}!}x&=3n!cWt5)Vm-Ux>nWLTNU241LJV~1z?6U*j;SkUW8kH~Cd zda7F099=L9nCW7*Fyo`e$$Iz*o`zqLCBuMC0yj5fxO2v{(tN0_NzyYw z)HTQCJ@L@R+%-eU_Q=+4(R9>cSd z4Y}aDHO-k)mfr@ytaZ0_$qUvms78+C=%^74;XE7b?I`s)u9PLuK55Q3x;@}6EK;wf zRbqfra6wEAY@wX>HnC(`m*Flt?rCHU{2|w}$>p{^sy?Kjz~qv>Z0dfw8qYL!o$GzB z@9p)*;p58m&9xUO)+qKCJ`^m=jMD?SOek^D5<3h*OFe&Qm(5Dg{@S}bf>53_n;KJ7 zn-M=XT!F=x*HkmFj_N+$wbux4_z)d&*$@bNU4hQ-rB-bu%aG%e^H*AX&I7iq6PT(I z<&1}&zWLborP^$0NM*!x{OrToX~KvEEJZtKn@fVbc%91m38}gKeNMavWQ2t(!FKT> zmWfS3PPkCTlURqf@6^nwnKS!hbiMbqL0SjOFER0?lHWM{Fv^-utg}Ds9zf1{cz>zX zzk>K))}KdfxU#N4Ew2P#N73VghgTqcZTaY7tw%b%}44g5vm>FgS$ZmK#RwMPv&(h`tiT4OzeGI3iv12+H9NNW9 zkRn-UQjiSGB}ydnN~*E1C=)-FPJd)0HiC*xykh88WjG!(7Zqfbo?sc|%C9LnW!(6{ zazs9e8wD&cYqotN2ZWjIamsnyyS~QHxVbW%d~zO3Da20yCJG64etNryKYP0j1R5HW zlRJUWqXKqq16Ab9{aB$0mTF&Tk)pU?z}|#|=wpG%7mYos5FTkZ%9zfnasKQ~dQkCa zn-k+ln5}72!eT$(`+8P~s^bad%0|Q6zbkVRif)i?w`9u8@V=tOIlC!lEfGX1+=y-;%*H*ZJ<2((=ogw< zHi-YOGB%r;(fkzM&fw%a%IYmPbN74sSF6*bGbXhtzzI8YKT9o9v>W|SAcx@sa?DAA zqs^(~RL+E^=bW`Y$xxC{Z_krWJc5Dr!NpVK*%HX7A0dKtyw8#bs@kzR_jKuM&+LWZ z@NpssXGo~1}0t>$I5U~GhAMY3x|d?z9yxbF0J8^Tg??t&PgZ}m=(hqX5n>{f4iV#2Yw zpEO3{#fq4EIgB8K9tb@g`>KlIU+UBvj0H@L7MPpiFucU}Z;(}9{4B7DMd+rrCqx;R zSLv-RF{1t6p{~JQA4S>;SrW&NCX;RUU|^36+1CzL~D zf|tS->I~jMR`Z=*IcyE2g=e9;2@d0HSvQ@7V#`J5z3GUpzuU`?3sv`ZGJkX00IHve zeLMzNzl?B&_&|3n9lKpT!V7V9T)uU{qjr*!=&3G18XraVsvCG`5|3{7g8K~hqEd+L z6n*>y)T?SzYib7q@z_(x(eD~H6YWI8AJ<28!gJ_Ai99lm-h%3TvSr49_xB0h%;K1c zw4_AuRxHNHMU=l{26j_5M}p@^*9AIPH1VeQ5l3{pH70yI1p4I+s0-ygiPoFO$4M=_ zQSnAe`1vxUjZqfHW(-L}j8=PXMok(WOr}8*`m=0`Ykboj2HR7`j#IV!UFUU&I93`F zlP|cS_DMN{5dD@mMOI`|Sem3W@2C=Cq5Sp45uj?nxf%QHF_+YL_DYym)W3UY z!OSeJuovcV@cSu6jU?4M)ys%n461f$g(_C;1bcI!0TDc$fZ$;W9c{@PS{Jb(?7D!R zW;N%hfgGYr{VEuRBlr>ps)LU`I0S3d3T$@}tDJY8J|}%i6(fTPhc;49?Ys@&_f7C{ zyLJ7EH|ZN`sdEQxtp!fw=|cRgS9}*piucJ#JNwzL%>PMfx-r{QiJ{~V2wF1VxHwER zNoR~5^6f{|vn;u!u=+ONx^oa00{X(kk~bOEpc_TU=#Rg81OmSL3bxli)1AN~f5-7!W93aAfemg-&8)M;HC z5=ZxY`w|y3{eFP8uH%rT5B%)kAT(zYYq>sugj0)gvtq0lPC~P;T0%xG%Ke3u>NG|c zkCp54HP6b=)I)4^w78Hc>!a(f7YR^z>G{KH>g zza8o8G#vp!yRIBir=H|f!}BWH?5XYD?w6D7PV$bgz9Pm1qW}Mb2!g^_WJ{wmF`i^f zdl)L%l-?HaIlcrf{;~vZofp0p3nCQPGS>%ev2FQg@y!r)8+Gh3_HJ*@`?~v_A(%BW zb1WAqm?C=+zpW97X~l}nFOz;>ku_Sn*g$sARGxe%@t1mc9g5(Z5tz}H8%Wy>2?gXZ zq2hdFB;@#I9*Ir^`hizcd=^}yYpDz1sa{yCx~!^rAlvvf(%2M)v0wVaxf$7GSUp1OBq1G*R8m4g z$>=M8MML@F3?JbZ*&mRxJ=sbQrvU?XTi+hnca&oivEq@Iea-EEYjp)kj;=A@;JiV8 z8{=lA$|lQEs?jmwiH)T_k;}yb5fHRWJ{4NJCyKngA5g17-Bf8(+4iC06#RKlRw5OpA=ARBg8CSTnp1NjZ(i1^d(vNgcI7 z=hILz(VjRv7^&H9p{1KLs@L(^jJ^oSuZn`Geqo-3ymP|ng`^Z^ePm24HzH>3@maTI zE1E`tGIJg+HP`@IK`g(&WDHu_P>h64o(vk*n`7SH!dFEta2kanjH9>V5`t;Mw~tr0 zECL$ojc2(Hd#+b(1?+~>0ytlpqjaZ0etrNtader4@S6}+FO_T@3aQzUO2(oZ^GdE7v!hZM(ZYlU994@q@K%F2 zfL4GvfcXP&;N%BZa@0R&6yXiH7vo7O{7Yl&5W)HWPdtthnD@<6Q89)fDoC@il<$x_ zK!EV>z6`dfM4m3gUX=M%uZoV@;$%shK*mNCDA~6xogQppBt>8g_!1aSSTo8mVJq4L z#rhq7hZAcqobrJ23nutp79%WiEe9T!i(;OJu1M)i5tvmeAvMwbJ0jD=TFB(;y*u)1 z@mKAicj$ol_B<%>TD)q|hf($FkIxr+#eZ~|Q@*PF*_Z@VG=Rx%kQiiV`NZ@1oj_SI zzv4|s48Gi716dmopE_TOGDHN2@4iZZMWy04{wLd6C zh6qNpqS`n37dh5?W?3@l@o!%AT7+3_trqR;WYHc>M>M**BpbOvk}Os&_=%k?<-~!i z0c_RXX$$tXs?V){Ez5-2d?eB@c925;5m&yEtCQ#^g4`3wOYba;A&-|lMnz9Gtirj{XJ?Bm4J2@T?wDLZ|aPg0OPBDPaklEu~w)$th}B0c)Azl%Nx zh9=uGV!m##6{-_4-k`7UKg^N`ElZ4rb|eDXP%ljn&_3r0Xv{;7!**KfnhZ&`XOC1A zeh1j8$EF~EF^`=icjZ#f6Vs>^Y{hw1Gnzad#&5hAgl|TdX)9W4CiZx-@Qjria%886 z>rELm6<2Xhs?%TMPtdKZ3@|I)u%y2AH|dOqFnl0w28T|RsTv-xdbxeF0y~m=4QTt;*7T)n zHIqHMzrA;d?(dfMyll?^3ZR|xWCJNpU4>JVN&261(_}$8Dy5B|EsYv`WUvtYr6LWr zvgyI_YtlbuRQc8ol8kzLst`2|;zf7}ssXh#vfg)o?vhe7ZHA?6W0*t#U_~^UwVxoy zQ&WXa`ym9ILb>9Ar%OtE+z5QsRYJxI!Z+Kvcwq!PhWK41vi@v$eDdU^O?XkQpdGt6 z;IH|2NYCbuD7qQl`juNTKo18T6K=wY!7UY@EFF01qmo<7-}->9Cvprq@ESPcJ+}0r zT77Vm1WkRoXMLVi`e68uHG*izJA)~Et5&O4BrjQ!{C?Vy6$stxYy>j_gZzJMLg|ub zF#II{+Y}iA09gOpr2ibK|7RD{Q_Nt*pj6W5&0s{KhSM?4|6w9s?LUx7hx`Yw>Er)_ zbULC149$Q4p2GqL9||vB&H_dO$|*g;0!9fMXq=vC0Yj2rWekIsZfyaBnT}%#Lkw+U S^517AOBf1xb5odqMgIrOqvR+6 delta 9427 zcmYM4Wl$VIlZF>|(Litl1Si4W-F@)@!QC~uXK{CTcXxMpcXtWy!7tz4)!o#*{nSi# zO;`2Q{OGQ^=tsWnN3K2xLaHo1v4^k$090Q900RI3SnE4l=^HQ@*%~@o8{0V2yINbF z^I1BqamH@F(NwRd)@hX~#Ol^$I5isaY&KKNDb>`~x%~J+9qj)toJtt%t6Kl#hZAJ) zee*5$)CPb_b!rZ_x8eN}CknbYW5s)e{kzoVbsBJ{(;uQdV_tFrS&)_y?L;)1=c4oK z=eqLMa`YZ>1P{fC34tt-sZ}dy!kHv;Si7G}HjXUqPvaaY=WyLPx(iM(NDG&?p zP3?(PD!WZbZKGo0a~U6f9=h|2QV;6K`J8T+;q#F=ibxME#Un2-oq36fV(D&}uIEpj z(8j@9i^bxCdF`knhzm#R5MHTRJB1v0Nr2rpt-)`ju5K?(93j;Bm&Ry01)79bm;=@c+NAqCsbnA8>^qI_ z{j=6sB2ob%`mXf+quWm@-D-wi-I8!IdyVH>%`zf8VKa0y$V*hur}7ok?%|?EhL)nP zTSm<5Y5m*8Ccswd1Z{aphE%6D+Y-fVHJd5J#(B~0qc0imgs#ACk~a8ukpH9!Wt)ap zdclYBQ{=NJd~084un6vk5EkK+Hda=mk!TrCX1gsR;RR7wXS1g^b+k+_R05+Am`-yq z+Bk!rvA5?G5*8Nr=FTV38!=6L&a#1p)M}cp zq=XQ;|NF1{)y>}()xk{O(Yy#5LrE_Z5q=%eZ*Mr@H`Y>{Gd6mCTfzg6H|TUz*=8;? z{0ssjt+NP}AkXcQ{tgeFu4O(~?c_0uYuUQ5bk8W9x|ODVaAjf-S`FwqsUgU*#7W%^ z8tYw|}4h8xzS*-DLsGRhZ53%oi0o@usz zz3Z#eg#3|2_A8ZSRQ5uj_R7vrYvfhY?xSIBdDlrQKk_|9zG%-?CXuK5++i$_&)dS1UK_4R z=qu|pdt=wqiD{8A9dOISN8xebEpsW6J)nm4&@O&@K7u=l6E>(f`Ia#}GuAx~9-9s` zm6E0gbE%kVzlDhhWIun=9mqwD8xp&Mw6=bUY_^m;@(%(BP~xWl%~p9-&X47PBnU8l zEzHB-{dvo%i)p>DriO$rMDCt84|J-Q)48c^M_eJ=1XoG zqE{KWryZ{$?U&+-7=DnZwju_64Wtnsh;Bj!Yhw|cBVr~5m+&x&?!{g=8-8} zVZ{`T3Z^-D70L9RdG(uP)HMUTO>+R8->p(HgKr2V{rP*)=Z*oW-G~5RXJ#!vUH=2U zqVe78ao(vlVKF0*-on+&>hnxte{UHqKlqAzjt#1 zb~}My&1?c6fiW`))#cv-=Y-vmEX1|49-?EUg_93x*hqpPLCDU7T&4W>80n$DLq9VT zJdtZIP50kj(XXh>D1fe<7XvU{0#bE`N9pCo`ILDusp6mcoD<7$BT+d)lGIBg&MK|~ zWkqWK-T~Pw@|roUJhVRKT{gO&t=uI`?d}!7)!qj3I_Vq55SLCZD`-rooui0PegrzD~pNAwda&9Gr~gMKt)%JgsdfUk(oDZYFr3y9f-2&;17?K~vva+vV(KNP+sB4IFp z#7PmyG368UBT$%UvfRdbm@Zu=XmjgLEqbHMh&AbXGS1GS*m9Q zsa!$LUI?Czq)!{CCNUh7KZZ~nTW82noXhK;h~UixJJ=p6`IJ@2V^+S;ky>;E^DOY7 z?RS+sF|nI&sG0ND@(U#_1&%AIjJu1j59Z-nve-mbVht$ zZ*I>*wYDp9>Fo=KAPeTl*w~UO+|bb%vH<~_5t?_R1Z;}> z90oihhDt#Yb5g{rWHpPLsVanj~@>yUyd^$hxymi z=R4z4BmxnV*xK2-uVkxIgA%{Fcx%mOwGvuI(oU!F9}oM8zoZARD>X*fOx3024_SGAsLz5Qh1;CzDm1R5#?gw->KTm z;h{H*o9$xqnsE%+xG^t%CPeQ)D}nMn^@Tx;HWM7dOyPpbwWsAaA2wXR@z%wSBBXP7 z;SFTxFX=Vfmw^5iNp7`zDZ;i5dzy-Vv3Lp7Vg9Wsr7JG1XL4APhNeoAiM>XAufk#z z34_jE7P4UT8|Dg;`(^^m18@^>-F*ADR^Qfk-@<-wbAGjAy}A*xR$uI;WX5y@a}s(S z&azn`+d9|DLn5q*iy0WXB;$%6?y%c?6)qHa0va5uMZPx_>HoMk8c);qXaa5r^d+W z&Ag2}9DJoxsiM{)4ml5Bupou|PL{8yNi6J>s`Uz^>b0tw3REufXvp9=t);sO-_H3< zsMv)t!F6)3b&ui6ZaK}T;G#JqImcFstgvsEx<#fPnf>)L;8`skK%^f|CsxoD^$YDG z2x8VTq<0I2AQS43?zC{g=|MMJ)j>UhE>Ny&fIH+FPWI1JB45SdGRWF`LEQIj zNjag&rl-Egz5Y0R%U3HIqPU-myDRo;AT)lP@O3xQt5ny<#P5$?A8?EP{f97pjzzQz z(L=2(_v9GR(Gg?tU|Q&zeSp~Nj4`mTJ>pYV!^6b^kK4x zw!U^4Z(Fqo6Oz%1m`op^mLEXSL9KHy^*XD1>#swd5$PM7R9xJCLmI{r!?;U($N*AR z3}Zi$o_w~Y@H#kwe5cwsxG^T5P&{3a#}e)>OkvGu(TXtU!k$lheZ+Uq$EpcROphn( zd|SSnD}y!xWzi*K*+MjinMYrR^XsJ@Q{oWI;fFzSfSLa>bpN-ruAk%|3zSVEvdlu8 z2~(c!F?L3~L}%TG>hM?YG$c74^nx(Y7*5jiDo5Th zW?@&A%6_!Sde%>U&g0g?mCi4LT|P8PSw*mMLq;~(tQy_UJd3BB3H`_IVb=AgCH%#_ z&3cB0f_QV{e#ChL>D<7!OGjY2jTguKi@KCf8_xHB(-I5$v$T*AD`!vdtJ4e6jAp!XsIoJ=&dI&UcCLIp>(BAaa$i?u`|1?^ za_c?N5;REY=AFO0YeSJ&A)y%x-GI@Qo&>M$95>kGK)H^~VNFry_SCQu{*X!_IHor& zeRFp(nNPjIlz58d0F zuie}6!Q-J^ej{Y9--lF*naC=WmND4!;ecMZoO+$17ZGc|J0zmh)Y7_D0%}Wz)<1>y zKR;l@gZB1W5vOTj(hwH$E9%g=(HGI(iT$|-6VY(EXQ$aui5coe2g@rV8zDj|Jl040Tp)}h>z0ciXtTEO=O^-tC@nVDHv#}Nw}AU^#BNiSjuk*MR0~WONC#XjM|UGB^Xam z{>tKIjXMaI%IXn$n7yn8JvifdXGZL-Cz@=1?k!R4Zc#b^6VXolvB0MM!J#Vw^k zw1T~WY+()N?EUUugJo43qvm(SgT|dSvnRiBCG(jdlBR0)r2sLB&}ZMCdW&f(M3SrY zD%rbf_)f?+7WuMbN)dA9wC9Z>D-^1V+bMW7dU@&<8Kcqb4HkQ+oUDEosx`0d56_Zr zUs*YaiyNaIN_4VKl;r4F*Z=#l}qIV(0d9K zQU>W~QT;kKYy%q4MNya9ssE~t-Yj@Vy5+6{Z9GXblGit=ejWWSfftnJPc<^BH|I?M ztX)}7(n881x46NKzeI^OwKx6;w!?X@Ij;1Jh??lh96`0bghXdkztYm zw%K#rR`9IzTy)eM%B#7O7Eulwi6AKt*ezo`-wDvaxG7LXDEYv|wKEPQWOb(9vEwzL zs44BsYpE&iSeha#TiyCg!p@7OM|m-Du4XBKCy`dj$zyLV+hnp91~>AEUDPQDF|0Xb zO1iv#&*@l-YwR@{dDXi$dJl4s{V8uxp{BE3ITg?rjdLYDQ_M1O{%W+vom^vwq?Uz_ zXirG#vb0eD30Zidrvm{nwcpq&M!5DavP_ zF4-=>z(9fl)}H=zvLfHknS6FZh+B2A?tHcue(B-D&|qHph}ATrrHEz?OI=*63*+L* zg&GAh{^4ECOLkPphJXdsz^&Mq{81U5IE$A&2SmX z-tfOTMDNt-f^{^vEOcx%BVQ{W!``8(Z91=E$1nQ&`j#YyhFZpI>tcEDh!(tG7l7$v zI~MYL8L;dU%G1)u#WP2nhu0&}brUF!h!0Tpw-=g3w8_k`(7Q>0XOau$W=JMP9P_OO zhQDnB5?vS`qEH^A=q1!9A<~Gf29fr>>__&DIIbJnvg(Wbq@U)A5wTEWsWJBu1}*q^ zj^73j1hTD|vYfjvZ8jP>HXcXL(_lQNFUD*f z^#b-5zhs&Q$6;&!TVb=*?p*lfAFy4hng>!cNa~st&=W| zK6!57;K8^3Y@AKwc9Be?v-X5!wut6QJ>59;Idhlkm(pq6Cu`0S2DuE4(eA@B9m$a#w(qTwjKd#V z+x6D@&l2@)Ex9PY3Ues#D?JAY>X<5lh9lY+H_8vs~JW0w3 za$C&XnU2GlKdUG$J|}lNG4$q01=zQy4Naa?^qE+#87B`x{I&Ndnm@5BRF9DsNZ@@J zvZYVqSQvYi#JpNp3A6V1O9 z{ACb-hzjza6Xw>ep1Ig)zh8@kdo@Y_Ij+paN$$e{>LTR#;)!y=TJp2dR z5E&#M?x$kN#u6~s3*rRexd*TkPxT4#(OiiSz2M_YDK|{(Rgif4pD>qA9qMq+1H}cy z=_P3(I#DKRm^Z084l5xtJRY<02CLIUwfQxfC|u=}79)qcV!#4w&zZ~5MQSuBICZX% z$Sm_>I7*x0vh6*GN&%%Tr_fDX1e^QJu6^=dA3hwtX&U&JS;fD?p5Ew;E^e?4VwV}^np5VM6fcAi+F~JSNGCyQb88?Q}WOb zuf8d7P)l;MZ;1w2*1XwZ?#_gt35HF`Z)KkGx8&cb9J_?NgSsB-eJM^N-5R4edWdF{ z<=(`^t8sd@kK)xDh+Ef$3gX_kJ4VBwX)49~cPI9v*k2(Am$a`r|*yR(|AT0-ZVe2W|PQ*U+XQ`q!2 zm0hOB1y{`=J1&NYWdALSE5-gBMTYx4i2LWM0jylN{j!2g$tAbL&h8^Ky@B~P%+oCj zb$TOCBGo$)@)XWxD^4~Wa@-mzyug2k6f4X_4CWy;o1-df< z!}3vz+6f@bz%4wx`pEr!(BWsq)kjvJuK<(Ipj!`{dn2MNA-!5`yj1ek^7Eg@G;N8y zahyr}&#qeakCW26>Dau71*!46vub)sU2L@l*UyWt4R7nS)12p4$1#NsA#groiQ)!i z1gv+-)BqthzF<(=f&h8P7-VdPbc`vN@c1dYFuek|i|5Qx7V*I&IsmFir2$!5O3Vele8)Px7vesf7R)>}nVf}aix8HR9M-v42 ze_uZ=B*&6`pJ#y(6qb+IIl}iWeO0oQr1UC}sPiCD+2M`Uvs(DnU{w@`VHN+K*}Xn3 zN4BhdoMdrK!LHrTFfL`dfidH?yaB2?;7!wcoh@zg;Pq!P%tmay_11p;w$%L z+hcKMhwD@O=auyI&fB9z@4wcJh@CwhrakXdUUuoT%`W(gDN;Q-o;kZk^> zmiyOOG(+V@QLR0=`?IPZBfk`P+sx>SMFgtDtm7i%DC?m;3E>;X_z$LL)un2Ww~eaM(IE7L z0u?l>LXCr^o^VzxC?~j(X3rLseYwmHt2qfO3xtzptJd_B6`V&xHV4f4 zdUfBlP0}w~p@nfiw$g^HsMG!epR>{uw}rWc60$WhPooRF^e=qN`RlUXz4*mpn~{#c z&&@Ks=vuq*aqY;ilRgOy>RDZM&Ghvf@#CWmR=a-pP=lBrfy-~PK9MELp9_5aVzmr& zhaDtE2-{r|WEa6Y%2p~bL|v{t>Q^rPszoIb_Aw@!)ogVmJDJoWpetwHDTwKj7Mdvv zzHYsiJ<0IKQg;s#2_|Dor`xL>eps#uFl)4-K%h_kncRNB-%7)oX6`h>F7GkZ82bXm zB>RRHEDTXshPyZqTSgenBOoVeb<(#K>8aEU#N1@8(AM|Ry>(_-Qq^p=LDQ*|biEiD z@J7l+s&*xlRPe-YhuD));zSu~?qbx&)KWLn6>Q0mR}8)j!hxDvPZr9WuY>y)KE6Nn zpVAtPv>_YGG4Oxxf5#7pi=OcKjPqn$gRs>-C;~A7rMpBE7QU+B)u8xY54?o>kiszY z^Q~Bf)S|n*Wu~4Na>Z~r)NosXYr(|_ab8Xqj}3~jV_Up2H?`t&P7?7CCrP1$t|V+= z+e5W1NYEqSosD`xoWtPQQs2N?D*#C?{byY<6#JLrS~$1iw^qjAtVWP= z;JZ_L85Ki(uc1Gi95a$?=xabqFH9}Io4^1J{cN}^ylgBw9`zI#n8xXAvFLGkZBnf_ zFD!!OattKdg9|rN7G+91{o+~aa=6W28@blAc{W0(R_xUotCP+ep*;a`i5+|e9(kDP z7OAR8A@T0ivKm7bD)jRmo~W=UV0ecWpoJG-xr0@Sc@BYP+k^fz})HrU-XBrjiV7YW)F z4ks7Vv@!6 zFBw&sMrdtG1!WL-sC|j0)M#F2uIC>b>TI7}amR0zmhd8~n3SsVFj4tdW2*6nT%q=K zONsHOZlO1Hx{5wnlom!2AY&ALW=xp>aYT;F$6r&7w`_w%=JT%oh_`(SMLZK!B=h)2 zX$n7APMM4())S2d6N+`vO-8k3r!D0cSwy*YjfKVeFW}_xhWO`(WY8j*PGG!VYKuqEWH>!|Gf-9>YVy-Rj?R(zi~1!a&TM#moG=(P{xdW=26)NR6P zG1ZnGK?968qBz-sX!Xx{44s0s z0BS|O@bQQSiIznLYHyY*e2gNEzlRu&|71Q|tU?)SBX%@Lvs* z^~--k)gVD4(I5$@$0G@${70#O>z^7V{zet328pWhd;g9S$y0?F(xve)F2?FrYlDzE zO1y%+{g~vVq_-{Im3>1N^J0GwXyl>?>hL)VDKCnA0a@`mo+LGVchrZ?9^wezarXoo zE$)5oo;ANh#z5nP7mmz@6Oz=uBZg0zFc(CJ~7&4f}UZ$owS%A1fyQQUY1u-n!L2 z6mbDAmW|U3BtGQe-m%b@FKf&3H9@=avbQ!$}R~bob_Fw9*T$CqADCYHGv(0H+REV zal>^&_uMMBL2LHG(;OzBMVueEx&P1sKbuAIt7qrq4#IS~ zJRIM`NT=oqUU`^C@f&CN^XNq_iFn+p1HZ%l5uR;etoMlFQ1IFnlw!&J^m{9D+QLpo zD2;`r=Q4wjPLBH6hfdt1d4SgIS+L@8UG9p`M8)J)Dr2zpzsf-}nCgQ5gcjRXHZ}I?LZ3+<1uKqwu>pZ_bVZh|v5&y{p zlKBGhlc5Nbp@8})=q4Eo;1V;adGB**5`_kk9g>!ke@@TZHrwBi7vbWcY27c3kiD^~ zquRvn6q2<6F`3l&6m~FKe+=}T&Y)u&vk&hst(p^9XkS>qZQJ`#4Tj5pvlN=6jDv4<+3@PocUWML)q3I7=QGH#fEB3 z2Fc5ZBeBavBT9(COSsr*^2=7l)L_&z%%(NGOJn1{Aka$Z3@~*B+4hRLN{ZWmxs$y2 z%DSKP0l%<3+e02XJrm44niHV4WKpRjopX4H;gO|3UpK5#xn*vyFVbjTr?bQ|z-!K@ zhplK;pDy{nr+)0PmgF|P%X5>3qfJ^kqtYEZ^sJ=ZeUns~70_0VlW(%r1dag_|Noy* zlAtb-?ARLpd`>r6POgE1;k6z)dylGb?O80fKFQfy+x4(Z2+VO U8fgEogOmY~2v%PQ_%HB(0jItSC;$Ke diff --git a/tutorials/private/mcode/intro.m b/tutorials/private/mcode/intro.m index 417c24f8..307ae203 100644 --- a/tutorials/private/mcode/intro.m +++ b/tutorials/private/mcode/intro.m @@ -16,13 +16,13 @@ % followed by value. Ellipses are used for clarity. nwb = NwbFile( ... - 'session_description', 'mouse in open exploration',... - 'identifier', 'Mouse5_Day3', ... - 'session_start_time', datetime(2018, 4, 25, 2, 30, 3, 'TimeZone', 'local'), ... - 'general_experimenter', 'Last, First', ... % optional - 'general_session_id', 'session_1234', ... % optional - 'general_institution', 'University of My Institution', ... % optional - 'general_related_publications', {'DOI:10.1016/j.neuron.2016.12.011'}); % optional + session_description='mouse in open exploration',... + identifier='Mouse5_Day3', ... + session_start_time=datetime(2018, 4, 25, 2, 30, 3, 'TimeZone', 'local'), ... + general_experimenter='Last, First', ... % optional + general_session_id='session_1234', ... % optional + general_institution='University of My Institution', ... % optional + general_related_publications={'DOI:10.1016/j.neuron.2016.12.011'}); % optional nwb %% Subject Information % You can also provide information about your subject in the NWB file. Create @@ -43,11 +43,11 @@ % * For |sex|, we recommend using F (female), M (male), U (unknown), and O (other) subject = types.core.Subject( ... - 'subject_id', '001', ... - 'age', 'P90D', ... - 'description', 'mouse 5', ... - 'species', 'Mus musculus', ... - 'sex', 'M' ... + subject_id='001', ... + age='P90D', ... + description='mouse 5', ... + species='Mus musculus', ... + sex='M' ... ); nwb.general_subject = subject; @@ -69,20 +69,20 @@ % and sampled every second (1 Hz): time_series_with_rate = types.core.TimeSeries( ... - 'description', 'an example time series', ... - 'data', linspace(0, 100, 10), ... - 'data_unit', 'm', ... - 'starting_time', 0.0, ... - 'starting_time_rate', 1.0); + description='an example time series', ... + data=linspace(0, 100, 10), ... + data_unit='m', ... + starting_time=0.0, ... + starting_time_rate=1.0); %% % For irregularly sampled recordings, we need to provide the |timestamps| for % the |data|: time_series_with_timestamps = types.core.TimeSeries( ... - 'description', 'an example time series', ... - 'data', linspace(0, 100, 10), ... - 'data_unit', 'm', ... - 'timestamps', linspace(0, 1, 10)); + description='an example time series', ... + data=linspace(0, 100, 10), ... + data_unit='m', ... + timestamps=linspace(0, 1, 10)); %% % The class serves as the foundation for all other time series types @@ -107,13 +107,13 @@ % Create an AnnotationSeries object with annotations for airpuff stimuli annotations = types.core.AnnotationSeries( ... - 'description', 'Airpuff events delivered to the animal', ... - 'data', {'Left Airpuff', 'Right Airpuff', 'Right Airpuff'}, ... - 'timestamps', [1.0, 3.0, 8.0] ... + description='Airpuff events delivered to the animal', ... + data={'Left Airpuff', 'Right Airpuff', 'Right Airpuff'}, ... + timestamps=[1.0, 3.0, 8.0] ... ); % Add the AnnotationSeries to the NWBFile's stimulus group -nwb.stimulus_presentation.set('Airpuffs', annotations) +nwb.stimulus_presentation.set(Airpuffs=annotations) %% Behavior % SpatialSeries and Position % Many types of data have special data types in NWB. To store the spatial position @@ -143,10 +143,10 @@ % create SpatialSeries object spatial_series_ts = types.core.SpatialSeries( ... - 'data', [linspace(0,10,100); linspace(0,8,100)], ... - 'reference_frame', '(0,0) is bottom left corner', ... - 'starting_time', 0, ... - 'starting_time_rate', 200 ... + data=[linspace(0,10,100); linspace(0,8,100)], ... + reference_frame='(0,0) is bottom left corner', ... + starting_time=0, ... + starting_time_rate=200 ... ); % create Position object and add SpatialSeries @@ -166,14 +166,14 @@ % |*Position*|> object to the module. % create processing module -behavior_module = types.core.ProcessingModule('description', 'contains behavioral data'); +behavior_module = types.core.ProcessingModule(description='contains behavioral data'); % add the Position object (that holds the SpatialSeries object) to the module % and name the Position object "Position" -behavior_module.nwbdatainterface.set('Position', position); +behavior_module.nwbdatainterface.set(Position=position); % add the processing module to the NWBFile object, and name the processing module "behavior" -nwb.processing.set('behavior', behavior_module); +nwb.processing.set(behavior=behavior_module); % Trials % Trials are stored in a object which is a subclass of