def test_missing_data_types(self): """Test that calling export_spec on a namespace builder without data types raises a warning.""" with self.assertWarnsWith(UserWarning, 'No data types specified. Exiting.'): export_spec(self.ns_builder, [], '.')
def main(): # the values for ns_builder are auto-generated from your cookiecutter inputs ns_builder = NWBNamespaceBuilder(doc='Implement proposal for hierarchical metadata structure ' 'for intracellular electrophysiology data ', name='ndx-icephys-meta', version='0.2.0', author=['Oliver Ruebel', 'Ryan Ly', 'Benjamin Dichter', 'Thomas Braun', 'Andrew Tritt'], contact=['*****@*****.**', '*****@*****.**', '*****@*****.**', 'None', '*****@*****.**']) # Create a vector-data column that references a range in a time series. I/e., a VectorData column # with a compound data type storing the start_index, count, and TimeSeries reference reference_timeseries_vectordata = NWBDatasetSpec( neurodata_type_inc='VectorData', neurodata_type_def='TimeSeriesReferenceVectorData', doc='Column storing references to a TimeSeries (rows). For each TimeSeries this VectorData ' 'column stores the start_index and count to indicate the range in time to be selected ' 'as well as an object reference to the TimeSeries.', dtype=[ NWBDtypeSpec(name='idx_start', dtype='int32', doc="Start index into the TimeSeries 'data' and 'timestamp' datasets of the " "referenced TimeSeries. The first dimension of those arrays is always time."), NWBDtypeSpec(name='count', dtype='int32', doc="Number of data samples available in this time series, during this epoch"), NWBDtypeSpec(name='timeseries', dtype=NWBRefSpec(target_type='TimeSeries', reftype='object'), doc='The TimeSeries that this index applies to') ] ) # Create a collection of aligned dynamic tables aligned_dynamic_tables_spec = NWBGroupSpec( neurodata_type_inc='DynamicTable', neurodata_type_def='AlignedDynamicTable', doc='DynamicTable container that subports storing a collection of subtables. Each sub-table is a ' 'DynamicTable itself that is aligned with the main table by row index. I.e., all ' 'DynamicTables stored in this group MUST have the same number of rows. This type effectively ' 'defines a 2-level table in which the main data is stored in the main table implemented by this type ' 'and additional columns of the table are grouped into categories, with each category being ' 'represented by a separate DynamicTable stored within the group.', attributes=[NWBAttributeSpec(name='categories', dtype='text', dims=['num_categories'], doc='The names of the categories in this AlignedDynamicTable. Each ' 'category is represented by one DynamicTable stored in the parent group. ' 'This attribute should be used to specify an order of categories.', shape=[None]) ], groups=[NWBGroupSpec(neurodata_type_inc='DynamicTable', doc='A DynamicTable representing a particular category for columns in the ' 'AlignedDynamicTable parent container. The table MUST be aligned ' 'with (i.e., have the same number of rows) as all other DynamicTables ' 'stored in the AlignedDynamicTable parent container. The name of ' 'the category is given by the name of the DynamicTable and its description ' 'by the description attribute of the DynamicTable.', quantity='*') ] ) electrodes_table_spec = NWBGroupSpec( neurodata_type_inc='DynamicTable', neurodata_type_def='IntracellularElectrodesTable', doc='Table for storing intracellular electrode related metadata.', attributes=[NWBAttributeSpec(name='description', dtype='text', doc='Description of what is in this dynamic table.', value='Table for storing intracellular electrode related metadata.')], datasets=[NWBDatasetSpec( name='electrode', neurodata_type_inc='VectorData', doc='Column for storing the reference to the intracellular electrode.', dtype=NWBRefSpec(target_type='IntracellularElectrode', reftype='object') ), ] ) stimuli_table_spec = NWBGroupSpec( neurodata_type_inc='DynamicTable', neurodata_type_def='IntracellularStimuliTable', doc='Table for storing intracellular stimulus related metadata.', attributes=[NWBAttributeSpec(name='description', dtype='text', doc='Description of what is in this dynamic table.', value='Table for storing intracellular stimulus related metadata.')], datasets=[NWBDatasetSpec( name='stimulus', neurodata_type_inc='TimeSeriesReferenceVectorData', doc='Column storing the reference to the recorded stimulus for the recording (rows).'), ] ) responses_table_spec = NWBGroupSpec( neurodata_type_inc='DynamicTable', neurodata_type_def='IntracellularResponsesTable', doc='Table for storing intracellular response related metadata.', attributes=[NWBAttributeSpec(name='description', dtype='text', doc='Description of what is in this dynamic table.', value='Table for storing intracellular response related metadata.')], datasets=[NWBDatasetSpec( name='response', neurodata_type_inc='TimeSeriesReferenceVectorData', doc='Column storing the reference to the recorded response for the recording (rows)'), ] ) # Create our table to group stimulus and response for Intracellular Electrophysiology Recordings icephys_recordings_table_spec = NWBGroupSpec( name='intracellular_recordings', neurodata_type_def='IntracellularRecordingsTable', neurodata_type_inc='AlignedDynamicTable', doc='A table to group together a stimulus and response from a single electrode and a single simultaneous ' 'recording. Each row in the table represents a single recording consisting typically of a stimulus and a ' 'corresponding response. In some cases, however, only a stimulus or a response are recorded as ' 'as part of an experiment. In this case both, the stimulus and response will point to the same ' 'TimeSeries while the idx_start and count of the invalid column will be set to -1, thus, ' 'indicating that no values have been recorded for the stimulus or response, respectively. Note, ' 'a recording MUST contain at least a stimulus or a response. Typically the stimulus and response ' 'are PatchClampSeries. However, the use of AD/DA channels that are not associated to an electrode ' 'is also common in intracellular electrophysiology, in which case other TimeSeries may be used.', attributes=[NWBAttributeSpec( name='description', dtype='text', doc='Description of the contents of this table. Inherited from AlignedDynamicTable ' 'and overwritten here to fix the value of the attribute', value='A table to group together a stimulus and response from a single electrode ' 'and a single simultaneous recording and for storing metadata about the ' 'intracellular recording.'), ], groups=[ NWBGroupSpec( name='electrodes', neurodata_type_inc='IntracellularElectrodesTable', doc='Table for storing intracellular electrode related metadata.', ), NWBGroupSpec( name='stimuli', neurodata_type_inc='IntracellularStimuliTable', doc='Table for storing intracellular stimulus related metadata.' ), NWBGroupSpec( name='responses', neurodata_type_inc='IntracellularResponsesTable', doc='Table for storing intracellular response related metadata.' ), ] ) # Create a SimultaneousRecordingsTable (similar to trials) table to group # intracellular electrophysiology recording that were # recorded at the same time and belong together simultaneous_recordings_table_spec = NWBGroupSpec( name='simultaneous_recordings', neurodata_type_def='SimultaneousRecordingsTable', neurodata_type_inc='DynamicTable', doc='A table for grouping different intracellular recordings from the ' 'IntracellularRecordingsTable table together that were recorded simultaneously ' 'from different electrodes', datasets=[NWBDatasetSpec(name='recordings', neurodata_type_inc='DynamicTableRegion', doc='A reference to one or more rows in the IntracellularRecordingsTable table.', attributes=[ NWBAttributeSpec( name='table', dtype=NWBRefSpec(target_type='IntracellularRecordingsTable', reftype='object'), doc='Reference to the IntracellularRecordingsTable table that ' 'this table region applies to. This specializes the ' 'attribute inherited from DynamicTableRegion to fix ' 'the type of table that can be referenced here.' )]), NWBDatasetSpec(name='recordings_index', neurodata_type_inc='VectorIndex', doc='Index dataset for the recordings column.') ] ) # Create the SequentialRecordingsTable table to group different SimultaneousRecordingsTable together sequentialrecordings_table_spec = NWBGroupSpec( name='sequential_recordings', neurodata_type_def='SequentialRecordingsTable', neurodata_type_inc='DynamicTable', doc='A table for grouping different sequential recordings from the ' 'SimultaneousRecordingsTable table together. This is typically ' 'used to group together sequential recordings where the a sequence ' 'of stimuli of the same type with varying parameters ' 'have been presented in a sequence.', datasets=[NWBDatasetSpec(name='simultaneous_recordings', neurodata_type_inc='DynamicTableRegion', doc='A reference to one or more rows in the SimultaneousRecordingsTable table.', attributes=[ NWBAttributeSpec( name='table', dtype=NWBRefSpec(target_type='SimultaneousRecordingsTable', reftype='object'), doc='Reference to the SimultaneousRecordingsTable table that this table region ' 'applies to. This specializes the attribute inherited ' 'from DynamicTableRegion to fix the type of table that ' 'can be referenced here.' ) ]), NWBDatasetSpec(name='simultaneous_recordings_index', neurodata_type_inc='VectorIndex', doc='Index dataset for the simultaneous_recordings column.'), NWBDatasetSpec(name='stimulus_type', neurodata_type_inc='VectorData', doc='The type of stimulus used for the sequential recording.', dtype='text') ] ) # Create the RepetitionsTable table to group different SequentialRecordingsTable together repetitions_table_spec = NWBGroupSpec( name='repetitions', neurodata_type_def='RepetitionsTable', neurodata_type_inc='DynamicTable', doc='A table for grouping different sequential intracellular recordings together. ' 'With each SequentialRecording typically representing a particular type of stimulus, the ' 'RepetitionsTable table is typically used to group sets of stimuli applied in sequence.', datasets=[NWBDatasetSpec(name='sequential_recordings', neurodata_type_inc='DynamicTableRegion', doc='A reference to one or more rows in the SequentialRecordingsTable table.', attributes=[ NWBAttributeSpec( name='table', dtype=NWBRefSpec(target_type='SequentialRecordingsTable', reftype='object'), doc='Reference to the SequentialRecordingsTable table that this table region ' 'applies to. This specializes the attribute inherited ' 'from DynamicTableRegion to fix the type of table that ' 'can be referenced here.' ) ]), NWBDatasetSpec(name='sequential_recordings_index', neurodata_type_inc='VectorIndex', doc='Index dataset for the sequential_recordings column.') ] ) # Create ExperimentalConditionsTable tbale for grouping different RepetitionsTable together experimental_conditions_table_spec = NWBGroupSpec( name='experimental_conditions', neurodata_type_def='ExperimentalConditionsTable', neurodata_type_inc='DynamicTable', doc='A table for grouping different intracellular recording repetitions together that ' 'belong to the same experimental experimental_conditions.', datasets=[NWBDatasetSpec(name='repetitions', neurodata_type_inc='DynamicTableRegion', doc='A reference to one or more rows in the RepetitionsTable table.', attributes=[ NWBAttributeSpec( name='table', dtype=NWBRefSpec(target_type='RepetitionsTable', reftype='object'), doc='Reference to the RepetitionsTable table that this table region ' 'applies to. This specializes the attribute inherited ' 'from DynamicTableRegion to fix the type of table that ' 'can be referenced here.' ) ]), NWBDatasetSpec(name='repetitions_index', neurodata_type_inc='VectorIndex', doc='Index dataset for the repetitions column.') ] ) # Update NWBFile to modify /general/intracellular_ephys in NWB to support adding the new structure there # NOTE: If this proposal for extension to NWB gets merged with the core schema the new NWBFile type would # need to be removed and the NWBFile schema updated instead icephys_file_spec = NWBGroupSpec( neurodata_type_inc='NWBFile', neurodata_type_def='ICEphysFile', doc='Extension of the NWBFile class to allow placing the new icephys ' 'metadata types in /general/intracellular_ephys in the NWBFile ' 'NOTE: If this proposal for extension to NWB gets merged with ' 'the core schema, then this type would be removed and the ' 'NWBFile specification updated instead.', groups=[NWBGroupSpec( name='general', doc='expand definition of general from NWBFile', groups=[NWBGroupSpec(name='intracellular_ephys', doc='expand definition from NWBFile', groups=[NWBGroupSpec(neurodata_type_inc='IntracellularRecordingsTable', doc=icephys_recordings_table_spec.doc, name='intracellular_recordings', quantity='?'), NWBGroupSpec(neurodata_type_inc='SimultaneousRecordingsTable', doc=simultaneous_recordings_table_spec.doc, name='simultaneous_recordings', quantity='?'), NWBGroupSpec(neurodata_type_inc='SequentialRecordingsTable', doc=sequentialrecordings_table_spec.doc, name='sequential_recordings', quantity='?'), NWBGroupSpec(neurodata_type_inc='RepetitionsTable', doc=repetitions_table_spec.doc, name='repetitions', quantity='?'), NWBGroupSpec(neurodata_type_inc='ExperimentalConditionsTable', doc=experimental_conditions_table_spec.doc, name='experimental_conditions', quantity='?'), # Update doc on SweepTable to declare it as deprecated NWBGroupSpec(neurodata_type_inc='SweepTable', doc='[DEPRACATED] Table used to group different PatchClampSeries.' 'SweepTable is being replaced by IntracellularRecordingsTable ' 'and SimultaneousRecordingsTable tabels (and corresponding ' 'SequentialRecordingsTable, RepetitionsTable and ' 'ExperimentalConditions tables.', name='sweep_table', quantity='?') ], datasets=[NWBDatasetSpec(name='filtering', doc='[DEPRECATED] Use IntracellularElectrode.filtering instead. ' 'Description of filtering used. Includes filtering type ' 'and parameters, frequency fall-off, etc. If this changes ' 'between TimeSeries, filter description should be stored ' 'as a text attribute for each TimeSeries.', dtype='text', quantity='?')] ) ] ) ] ) # Add the type we want to include from core to this list include_core_types = ['Container', 'DynamicTable', 'DynamicTableRegion', 'VectorData', 'VectorIndex', 'PatchClampSeries', 'IntracellularElectrode', 'NWBFile'] # Include the types that are used by the extension and their namespaces (where to find them) for type_name in include_core_types: ns_builder.include_type(type_name, namespace='core') # Add our new data types to this list new_data_types = [aligned_dynamic_tables_spec, reference_timeseries_vectordata, icephys_recordings_table_spec, simultaneous_recordings_table_spec, sequentialrecordings_table_spec, repetitions_table_spec, experimental_conditions_table_spec, icephys_file_spec, electrodes_table_spec, stimuli_table_spec, responses_table_spec] # Export the spec project_dir = os.path.abspath(os.path.join(os.path.dirname(__file__), '..', '..')) output_dir = os.path.join(project_dir, 'spec') export_spec(ns_builder=ns_builder, new_data_types=new_data_types, output_dir=output_dir) print("Exported specification to: %s" % output_dir)
def test_export(self): """Test that export_spec writes the correct files.""" export_spec(self.ns_builder, self.data_types, '.') self._test_namespace_file() self._test_extensions_file()
def main(): # these arguments were auto-generated from your cookie-cutter inputs ns_builder = NamespaceBuilder( doc='An extension for storing point clouds in an NWB file', name='ndx-point-cloud-table', version='0.1.0', author=list(map(str.strip, 'Ben Dichter'.split(','))), contact=list(map(str.strip, '*****@*****.**'.split(',')))) ns_builder.include_type('DynamicTable', namespace='hdmf-common') ns_builder.include_type('VectorData', namespace='hdmf-common') ns_builder.include_type('VectorIndex', namespace='hdmf-common') PointCloudTable = GroupSpec( doc='type for storing time-varying 3D point clouds', data_type_def='PointCloudTable', data_type_inc='DynamicTable', default_name='PointCloudTable') PointCloudTable.add_dataset(name='timestamps', data_type_inc='VectorData', doc='time of each frame in seconds', dims=('num_frames', ), shape=(None, ), dtype='float') PointCloudTable.add_dataset( name='point_cloud', data_type_inc='VectorData', doc='datapoints locations over time', dims=('time', '[x, y, z]'), shape=(None, 3), dtype='float', ) PointCloudTable.add_dataset( name='point_cloud_index', data_type_inc='VectorIndex', doc='datapoints indices', dims=('index', ), shape=(None, ), ) PointCloudTable.add_dataset(name='color', data_type_inc='VectorData', doc='datapoints color', dims=('time', '[r, g, b]'), shape=(None, 3), dtype='float', quantity='?') PointCloudTable.add_dataset(name='color_index', data_type_inc='VectorIndex', doc='datapoints colors indices', dims=('index', ), shape=(None, ), quantity='?') PointCloudTable.add_attribute( name='colnames', dims=('num_columns', ), shape=(None, ), doc= 'The names of the columns in this table. This should be used to specify ' 'an order to the columns.', default_value=('point_cloud', ), dtype='text') new_data_types = [PointCloudTable] # export the spec to yaml files in the spec folder output_dir = os.path.abspath( os.path.join(os.path.dirname(__file__), '..', '..', 'spec')) export_spec(ns_builder, new_data_types, output_dir)