This repository has been archived by the owner on Jan 1, 2020. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 14
/
nwb_core.py
2733 lines (2698 loc) · 137 KB
/
nwb_core.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
# Definitions of NWB file format
# This is JSON, but allows Python comments (proceeded by #)
# and multiline strings in parentheses e.g. ("part-1" "part 2") or in triple quotes
# "fs" stands for 'format specification'
# "core" is the schema id (also called 'namespace')
{"fs": {"core": {
# info section has metadata about the schema
"info": {
"name": "NWB file format specification",
"version": "1.0.6",
"date": "April 8, 2017",
"author": "The many scientists who helped make the NWB:Neurophysiology format a reality.",
"contact": "[email protected], [email protected]",
"description": "Specification for the core NWB (Neurodata Withoug Borders) format."
},
# schema section specifies all datasets and groups:
# "identifier" - dataset
# "identifier/" - group (has trailing slash)
# "<identifier>" - dataset with variable name
# "<identifier>/" - group with variable name
"schema": {
"/": {
"description": "Top level of NWB file.",
# Example of how a root attribute would be specified:
# "attributes": {
# "nwb_version": {
# "data_type": "text",
# "value": fs["core"]["info"]["version"]}},
"nwb_version": {
"data_type": "text",
"description": ("File version string. COMMENT: Eg, NWB-1.0.0. This will be the "
"name of the format with trailing major, minor and patch numbers.")},
"identifier": {
"data_type": "text",
"description": "A unique text identifier for the file. COMMENT: Eg, concatenated "
"lab name, file creation date/time and experimentalist, or a hash of these "
"and/or other values. The goal is that the string should be unique to all "
"other files."},
"file_create_date": {
"data_type": "text",
"description": ("Time file was created, UTC, and subsequent modifications to file. "
"COMMENT: Date + time, Use ISO format (eg, ISO 8601) or a format that is "
"easy to read and unambiguous. File can be created after "
"the experiment was run, so this may differ from experiment start "
"time. Each modifictation to file adds new entry to array. "),
"dimensions": ["*unlimited*"]},
"session_start_time": {
"data_type": "text",
"description": ("Time of experiment/session start, UTC. COMMENT: Date "
"+ time, Use ISO format (eg, ISO 8601) or an easy-to-read and unambiguous "
"format. All times stored in the "
"file use this time as reference (ie, time zero)")},
"session_description": {
"data_type": "text",
"description": "One or two sentences describing the experiment and data in the file."},
},
"/acquisition/": {
"description": ("Data streams recorded from the system, including ephys, ophys, tracking, etc. "
"COMMENT: This group is read-only after the experiment is completed and timestamps are corrected to "
"a common timebase. The data stored here may be links to raw data stored in external HDF5 "
"files. This will allow keeping bulky raw data out of the file while preserving the option "
"of keeping some/all in the file. "
"MORE_INFO: Acquired data includes tracking and experimental data streams (ie, "
"everything measured from the system). "
"If bulky data is stored in the /acquisition group, the data can exist in a "
"separate HDF5 file that is linked to by the file being used for processing "
"and analysis."),
"_properties": {"create": True},
"images/": {
"description": "Acquired images",
"_properties": {"create": True},
"<image_X>*": {
"data_type": "binary",
"dimensions": [["1d_size"],["num_rows","num_cols"]],
"description": ("Photograph of experiment or experimental setup (video also OK). "
"COMMENT: Name is arbitrary. Data is stored as a single binary object "
"(HDF5 opaque type)."),
"attributes": {
"format": {
"data_type": "text",
"description": "Format of the image. COMMENT: eg, jpg, png, mpeg" },
"description^": {
"data_type": "text",
"description": ("Human description of image. "
"COMMENT: If image is of slice data, include slice thickness and "
"orientation, and reference to appropriate entry in /general/slices")}}}},
# "include": {"<image_X>*": {}},
"timeseries/": {
"description": ("Acquired TimeSeries."
"COMMENT: When importing acquisition data to an NWB file, "
"all acquisition/tracking/stimulus data must already be aligned to a common time "
"frame. It is assumed that this task has already been performed."),
"_properties": {"create": True},
"include": {
"<TimeSeries>/*":{"_options": {"subclasses": True}},
}}
},
"/analysis/": {
"description": ("Lab-specific and custom scientific analysis of data. There is no "
"defined format for the content of this group - the format is up to the individual "
"user/lab. COMMENT: To facilitate sharing analysis data between labs, the contents "
"here should be stored in standard types (eg, INCF types) and appropriately "
"documented. "
"MORE_INFO: The file can store lab-specific and custom data analysis without "
"restriction on its form or schema, reducing data formatting restrictions on "
"end users. Such data should be placed in the analysis group. The analysis data "
"should be documented so that it is sharable with other labs"),
"_properties": {"create": True},
},
"/epochs/": {
"description": ("Experimental intervals, whether that be logically distinct sub-experiments "
"having a particular scientific goal, trials during an experiment, or epochs deriving "
"from analysis of data. COMMENT: Epochs provide pointers to time series that are "
"relevant to the epoch, and windows into the data in those time series (i.e., the start "
"and end indices of TimeSeries::data[] that overlap with the epoch). This allows easy "
"access to a range of data in specific experimental intervals. "
"MORE_INFO: An experiment can be separated "
"into one or many logical intervals, with the order and duration of these intervals "
"often definable before the experiment starts. In this document, and in the context "
"of NWB, these intervals are called 'epochs'. Epochs have acquisition and stimulus "
"data associated with them, and different epochs can overlap. Examples of epochs are "
"the time when a rat runs around an enclosure or maze as well as intervening sleep "
"sessions; the presentation of a set of visual stimuli to a mouse running on a "
"wheel; or the uninterrupted presentation of current to a patch-clamped cell. Epochs "
"can be limited to the interval of a particular stimulus, or they can span multiple "
"stimuli. Different windows into the same time series can be achieved by including "
"multiple instances of that time series, each with different start/stop times."),
"_properties": {"create": True},
"attributes": {
"tags": {
"description": ("A sorted list of the different tags used by epochs. "
"COMMENT:This is a sorted list of all tags that are in any of the "
"<epoch_X>/tags datasets`."),
"data_type": "text",
"dimensions": ["num_tags",],
"autogen": {
"type": "values",
"target":"<epoch_X>/tags",
"trim": True,
"qty": "*",
"include_empty": True}}},
"<epoch_X>/*": {
"_description": ("One of possibly many different experimental epoch"
"COMMENT: Name is arbitrary but must be unique within the experiment."),
"attributes": {
"neurodata_type": {
"description": "The string \"Epoch\"",
"data_type": "text", "value": "Epoch", "const": True },
"links": {
"description": ("A sorted list "
"mapping TimeSeries entries in "
"the epoch to the path of the TimeSeries within the file. "
"Each entry in the list has the following format: "
"\"'<i><TimeSeries_X></i>' <b>is</b> '<i>path_to_TimeSeries</i>'\", "
"where <i><TimeSeries_X></i> is the name assigned to group "
" <TimeSeries_X> (below). Note that the name and path are both "
"enclosed in single quotes and the word \"is\" (with a single space before "
"and after) separate them. "
"<b>Example list element:</b> "
"\"'auditory_cue' is '/stimulus/presentation/auditory_cue'\"."
),
"data_type": "text",
"dimensions": ["num_links"],
"autogen": {
"type": "link_path",
"target":"<timeseries_X>/timeseries",
"trim": True,
"qty": "*",
"format": "'$s' is '$t'",
"include_empty": True}},
},
"description?": {
"data_type": "text",
"description": "Description of this epoch (<epoch_X>)."},
"start_time": {
"description": "Start time of epoch, in seconds",
"data_type": "float64!"},
"stop_time": {
"description": "Stop time of epoch, in seconds",
"data_type": "float64!"},
"tags?": {
"description": ("User-defined tags used throughout "
"the epochs. Tags are "
"to help identify or categorize epochs. "
"COMMENT: E.g., can describe stimulus (if template) or behavioral "
"characteristic (e.g., \"lick left\")"),
"data_type": "text",
"dimensions": ["num_tags"]},
"<timeseries_X>/*" : {
"description": ("One of possibly many input or output streams recorded during epoch. "
"COMMENT: Name is arbitrary and does not have to match the TimeSeries that "
"it refers to."),
"idx_start": {
"description": ("Epoch's start index in TimeSeries data[] field. "
"COMMENT: This can be used to calculate location in TimeSeries timestamp[] "
"field"),
"data_type": "int32", },
"count": {
"description": ("Number of data samples available in this time series, "
"during this epoch."),
"data_type": "int32", },
"timeseries/": {
"description": ("Link to TimeSeries. An HDF5 soft-link should be "
"used."),
"link": {"target_type": "<TimeSeries>/", "allow_subclasses": True } } } }
},
"/general/": {
"description": ("Experimental metadata, including protocol, notes and description "
"of hardware device(s). COMMENT: The metadata stored in this section should "
"be used to describe the experiment. Metadata necessary for interpreting the "
"data is stored with the data. "
"MORE_INFO: General experimental metadata, including animal strain, experimental "
"protocols, experimenter, devices, etc, are stored under 'general'. "
"Core metadata (e.g., that required to interpret data fields) is "
"stored with the data itself, and implicitly defined by the file "
"specification (eg, time is in seconds). The strategy used here for "
"storing non-core metadata is to use free-form text fields, such as "
"would appear in sentences or paragraphs from a Methods section. "
"Metadata fields are text to enable them to be more general, for "
"example to represent ranges instead of numerical values. "
"Machine-readable metadata is stored as attributes to these free-form "
"datasets. <br /><br />"
"All entries in the below table are to be included when data is present. "
"Unused groups (e.g., intracellular_ephys in an optophysiology experiment) "
"should not be created unless there is data to store within them."),
"_properties": {"create": True},
"__custom?": {
"description": ("Indicates that this group (general/) is the default location for custom"
" nodes. This dataset in the format specification is just a flag. "
" There is no actual data stored in the HDF5 file for this dataset."),
"data_type": "int"},
"session_id^": {
"data_type": "text",
"description":("Lab-specific ID for the session."
"COMMENT: Only 1 session_id per file, with all time aligned to "
"experiment start time.")},
"experimenter^": {
"data_type": "text",
"description": ("Name of person who performed the experiment."
"COMMENT: More than one person OK. Can specify roles of different people involved.")},
"institution^": {
"data_type": "text",
"description": "Institution(s) where experiment was performed"},
"lab^": {
"data_type": "text",
"description": "Lab where experiment was performed"},
"related_publications?": {
"data_type": "text",
"description": ("Publication information."
"COMMENT: PMID, DOI, URL, etc. If multiple, concatenate together and describe "
"which is which. such as PMID, DOI, URL, etc")},
"notes?": {
"data_type": "text",
"description": ("Notes about the experiment. COMMENT: Things particular to"
" this experiment")},
"experiment_description^": {
"data_type": "text",
"description": ("General description of the experiment."
"COMMENT: Can be from Methods")},
"data_collection?": {
"data_type": "text",
"description": ("Notes about data collection and analysis."
"COMMENT: Can be from Methods")},
"stimulus?": {
"data_type": "text",
"description": ("Notes about stimuli, such as how and where presented."
"COMMENT: Can be from Methods")},
"pharmacology?": {
"data_type": "text",
"description": ("Description of drugs used, including how and when they were"
" administered. "
"COMMENT: Anesthesia(s), painkiller(s), etc., plus dosage, concentration, "
"etc.")},
"surgery?": {
"data_type": "text",
"description": ("Narrative description about surgery/surgeries, including date(s)"
" and who performed surgery. "
"COMMENT: Much can be copied from Methods")},
"protocol?": {
"data_type": "text",
"description": ("Experimetnal protocol, if applicable."
"COMMENT: E.g., include IACUC protocol")},
"subject/?": {
"_description": ("Information about the animal or person from which the "
"data was measured."),
"subject_id?": {
"data_type": "text",
"description": ("ID of animal/person used/participating in experiment"
" (lab convention)")},
"description?": {
"data_type": "text",
"description": ("Description of subject and where subject came from (e.g.,"
" breeder, if animal)")},
"species?": {
"data_type": "text",
"description": "Species of subject"},
"genotype?": {
"data_type": "text",
"description": ("Genetic strain "
"COMMENT: If absent, assume Wild Type (WT)")},
"sex?": {
"data_type": "text",
"description": "Gender of subject"},
"age?": {
"data_type": "text",
"description": "Age of subject"},
"weight?": {
"data_type": "text",
"description": ("Weight at time of experiment, at time of surgery and at other"
" important times")}
},
"virus?": {
"data_type": "text",
"description": ("Information about virus(es) used in experiments, including"
" virus ID, source, date made, injection location, volume, etc")
},
"slices?": {
"data_type": "text",
"description": ("Description of slices, including information about preparation"
" thickness, orientation, temperature and bath solution")
},
"devices/?": {
"description": ("Description of hardware devices used during experiment. "
"COMMENT: Eg, monitors, ADC boards, microscopes, etc"),
"<device_X>*": {
"description": ("One of possibly many. Information about device and device "
"description. "
"COMMENT: Name should be informative. Contents can be from Methods."),
"data_type": "text"},
},
"source_script?": {
"description": "Script file used to create this NWB file.",
"attributes": {
"file_name?": {
"description": "Name of script file",
"data_type": "text" }
},
"data_type": "text"
},
"specifications/?": {
"description": "Group for storing format specification files.",
"<specification_file>*": {
"description": "Dataset for storing contents of a specification file for either "
"the core format or an extension. Name should match name of file.`",
"attributes": {
"help?": {
"data_type": "text",
"value": "Contents of format specification file." },
"namespaces": {
"description": "Namespaces defined in the file",
"data_type": "text",
"dimensions": ["num_namespaces"]
}
# "version": { "data_type": "text"},
# "date": { "data_type": "text"},
# "author": {"data_type": "text"},
# "contact": {"data_type": "text"},
# "description": {"data_type": "text"},
},
"data_type": "text"
}
}
},
"/general/intracellular_ephys/?": {
"description": "Metadata related to intracellular electrophysiology",
"filtering?": {
"data_type": "text",
"description": ("Description of filtering used. "
"COMMENT: 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.") },
"<electrode_X>/": {
"_description": ("One of possibly many. "
"COMMENT: Name should be informative."),
"description": {
"data_type": "text",
"description": ("Recording description, description of electrode (e.g., "
" whole-cell, sharp, etc)"
"COMMENT: Free-form text (can be from Methods)")},
"location?": {
"data_type": "text",
"description": ("Area, layer, comments on estimation, stereotaxis coordinates"
" (if in vivo, etc)") },
"device?": {
"data_type": "text",
"description": "Name(s) of devices in general/devices" },
"slice?": {
"data_type": "text",
"description": "Information about slice used for recording" },
"initial_access_resistance?": {
"data_type": "text",
"description": "Initial access resistance" },
"seal?": {
"data_type": "text",
"description": "Information about seal used for recording" },
"resistance?": {
"data_type": "text",
"description": "Electrode resistance COMMENT: unit: Ohm" },
"filtering?": {
"data_type": "text",
"description": "Electrode specific filtering."}
},
},
"/general/extracellular_ephys/?": {
"description": "Metadata related to extracellular electrophysiology.",
"electrode_map": {
"description": ("Physical location of electrode, (x,y,z in meters) "
"COMMENT: Location of electrodes relative to one another. This "
"records the points in space. If an electrode is moved, it needs "
"a new entry in the electrode map for its new location. Otherwise "
"format doesn't support using the same electrode in a new location, "
"or processing spikes pre/post drift."),
"dimensions": ["num_electrodes","xyz"], # specifies 2-D array
"data_type": "number",
"xyz" : { # definition of dimension xyz
"type": "structure",
"components": [
{ "alias": "x", "unit": "meter" },
{ "alias": "y", "unit": "meter" },
{ "alias": "z", "unit": "meter" } ] }
},
"electrode_group": {
"description": ("Identification string for probe, shank or tetrode "
"each electrode resides on. Name should correspond to one of "
"electrode_group_X groups below. "
"COMMENT: There's one entry here for each element in electrode_map. "
"All elements in an electrode group should have a functional association, "
"for example all being on the same planar electrode array, or on the "
"same shank."),
"dimensions": ["num_electrodes"], # specifies 1-D array
"references": "<electrode_group_X>/",
"data_type": "text",
},
"impedance": {
"description": ("Impedence of electrodes listed in electrode_map. "
"COMMENT: Text, in the event that impedance is stored as range "
"and not a fixed value"),
"dimensions": ["num_electrodes"], # specifies 1-D array
"data_type": "text"
},
"filtering": {
"description": ("Description of filtering used. "
"COMMENT: 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. If this changes between "
"TimeSeries, filter description should be stored as a text attribute "
"for each TimeSeries."),
"data_type": "text"
},
"<electrode_group_X>/": {
"_description": ("One of possibly many groups, one for each electrode group. "
"If the groups have a hierarchy, such as multiple probes each having multiple "
"shanks, that hierarchy can be mirrored here, using groups for "
"electrode_probe_X and subgroups for electrode_group_X."
"COMMENT: Name is arbitrary but should be meaningful."),
"description": { # this description is a dataset since it is a dict with a data_type
"data_type": "text",
"description": "Description of probe or shank", },
"location": {
"data_type": "text",
"description": ("Description of probe location"
"COMMENT: E.g., stereotaxic coordinates and other data, e.g., drive "
"placement, angle and orientation and tetrode location in drive and "
"tetrode depth") },
"device": {
"data_type": "text",
"description": "Name of device(s) in /general/devices",
"references": "/general/devices/devices/<device_X>/", }
}
},
"/general/optophysiology/?": {
"description": "Metadata related to optophysiology.",
"<imaging_plane_X>/*": {
"_description": ("One of possibly many groups describing an imaging plane. "
"COMMENT: Name is arbitrary but should be meaningful. It is referenced by "
"TwoPhotonSeries and also ImageSegmentation and DfOverF interfaces"),
"description?": {
"description": "Description of <image_plane_X>",
"data_type": "text"
},
"manifold^": {
"description": ("Physical position of each pixel. "
"COMMENT: \"xyz\" represents the position of the pixel relative to the "
"defined coordinate space"),
"data_type": "float32",
"dimensions": ["height", "weight", "xyz"],
"attributes": {
"unit": {
"description": ("Base unit that coordinates are stored in "
"(e.g., Meters)"),
"data_type": "text", "value": "Meter"},
"conversion": {
"description": ("Multiplier to get from stored values to specified "
"unit (e.g., 1000 for millimeters)"),
"data_type": "float", "value": 1.0}},
"xyz" : { # definition of dimension xyz
"type": "structure",
"components": [
{ "alias": "x", "unit": "Meter" },
{ "alias": "y", "unit": "Meter" },
{ "alias": "z", "unit": "Meter" } ] }},
"reference_frame^": {
"description": ("Describes position and reference frame of manifold based "
"on position of first element in manifold. For example, text description "
"of anotomical location or vectors needed to rotate to common anotomical "
"axis (eg, AP/DV/ML). "
"COMMENT: This field is necessary to interpret manifold. If manifold is "
"not present then this field is not required"),
"data_type": "text" },
"<channel_X>/": {
"_description": ("One of possibly many groups storing channel-specific data "
"COMMENT: Name is arbitrary but should be meaningful"),
"emission_lambda": {
"description": "Emission lambda for channel",
"data_type": "text"},
"description": {
"description": "Any notes or comments about the channel",
"data_type": "text"}},
"indicator": {
"description": "Calcium indicator",
"data_type": "text" },
"excitation_lambda": {
"description": "Excitation wavelength",
"data_type": "text" },
"imaging_rate": {
"description": "Rate images are acquired, in Hz.",
"data_type": "text" },
"location": {
"description": "Location of image plane",
"data_type": "text" },
"device": {
"description": "Name of device in /general/devices",
"data_type": "text",
"references": "/general/devices/<device_X>/"}}
},
"/general/optogenetics/?": {
"description": "Metadata describing optogenetic stimuluation",
"<site_X>/*": {
"_description": ("One of possibly many groups describing an optogenetic "
"stimuluation site. "
"COMMENT: Name is arbitrary but should be meaningful. Name is referenced "
"by OptogeneticSeries"),
"description": {
"description": "Description of site",
"data_type": "text"},
"device": {
"description": "Name of device in /general/devices",
"data_type": "text",
"references": "/general/devices/<device_X>/"},
"excitation_lambda": {
"description": "Excitation wavelength",
"data_type": "text" },
"location": {
"description": "Location of stimulation site",
"data_type": "text" }}
},
"/processing/": {
"description": ("The home for processing Modules. These modules perform intermediate "
"analysis of data that is necessary to perform before scientific analysis. "
"Examples include spike clustering, extracting position from tracking data, stitching "
"together image slices. "
"COMMENT: Modules are defined below. They can be large and express many data sets "
"from relatively complex analysis (e.g., spike detection and clustering) or small, "
"representing extraction of position information from tracking video, or even binary"
" ""lick/no-lick"" decisions. Common software tools (e.g., klustakwik, MClust) are "
"expected to read/write data here. "
"MORE_INFO: 'Processing' refers to intermediate analysis of the acquired data to make "
"it more amenable to scientific analysis. These are performed using Modules, as "
"defined above. All modules reside in the processing group."),
"_properties": {"create": True},
"include": { "<Module>/*": {"_options": {"subclasses": True} }}
},
"/stimulus/": {
"description": ("Data pushed into the system (eg, video stimulus, sound, voltage, etc) and "
"secondary representations of that data (eg, measurements of something used as a "
"stimulus) COMMENT: This group is read-only after experiment complete and timestamps "
"are corrected to common timebase. Stores both presented stimuli and stimulus templates, "
"the latter in case the same stimulus is presented multiple times, or is pulled from an "
"external stimulus library."
"MORE_INFO: Stimuli are here defined as any signal that is pushed into the system "
"as part of the experiment (eg, sound, video, voltage, etc). Many different "
"experiments can use the same stimuli, and stimuli can be re-used during an "
"experiment. The stimulus group is organized so that one version of template "
"stimuli can be stored and these be used multiple times. These templates can "
"exist in the present file or can be HDF5-linked to a remote library file."
),
"_properties": {"create": True},
"presentation/": {
"description": "Stimuli presented during the experiment.",
"_properties": {"create": True},
"include": {
"<TimeSeries>/*":{"_options": {"subclasses": True}},
}
},
"templates/": {
"description": ("Template stimuli. "
"COMMENT: Time stamps in templates are based on stimulus design and are "
"relative to the beginning of the stimulus. When templates are used, the "
"stimulus instances must convert presentation times to the experiment's "
"time reference frame."),
"_properties": {"create": True},
"include": {
"<TimeSeries>/*":{"_options": {"subclasses": True}},
}
},
},
# start of id's without absolute path
"<Module>/": {
"description": ("Module. Name should be descriptive. "
"Stores a collection of related data organized by "
"contained interfaces. Each interface is a contract specifying content "
"related to a particular type of data."),
"attributes": {
"description?": {
"data_type": "text",
"description": "Description of Module"},
"interfaces": {
"description": ("Names of the data interfaces offered by this module. "
"COMMENT: E.g., [0]=\"EventDetection\", [1]=\"Clustering\", "
"[2]=\"FeatureExtraction\""),
"data_type": "text",
"dimensions": ["num_interfaces",],
"autogen": {
"type": "names",
"target":"<*>/",
# should modify autogen to use target <Interface> subclass, rather than tsig
# "target":"<Interface>/",
"tsig": {"type": "group",
"attrs": { "neurodata_type": "Interface"}},
"trim": True,
"qty": "*"}},
"neurodata_type": {
"description": "The string \"Module\"",
"data_type": "text", "value": "Module", "const":True}},
"include": { "<Interface>/*": {"_options": {"subclasses": True}}}
},
# base timeSeries structure
"<TimeSeries>/": {
"description": "General purpose time series.",
"attributes": {
"description^": {
"data_type": "text",
# "value": "", # default empty string
"description": "Description of TimeSeries"},
"comments^": {
"data_type": "text",
# "value":"", # default empty string
"description": ("Human-readable comments about the TimeSeries. This second "
"descriptive field can be used to store additional information, or "
"descriptive information if the primary description field is populated "
"with a computer-readable string.")},
"source": {
"description": ("Name of TimeSeries or Modules that serve as the source for "
"the data contained here. It can also be the name of a device, for "
"stimulus or acquisition data"),
# "value": "", # default to empty string if nothing specified
"data_type": "text"},
"ancestry": {
"data_type": "text", "value": ["TimeSeries"], "const": True,
"description": ("The class-hierarchy of this TimeSeries, with one entry "
"in the array for each ancestor. An alternative and equivalent "
"description is that this TimeSeries object contains the datasets "
"defined for all of the TimeSeries classes listed. The class hierarchy "
"is described more fully below. "
"COMMENT: For example: [0]=""TimeSeries"", [1]=""ElectricalSeries"" "
"[2]=""PatchClampSeries"". The hierarchical order should be preserved "
"in the array -- i.e., the parent object of subclassed element N in the "
"array should be element N-1")},
"neurodata_type": {
"data_type": "text", "value": "TimeSeries", "const": True},
# "description": "The string \"TimeSeries\"",
"data_link": {
"description": ("A sorted list of the paths of all TimeSeries that share a link "
"to the same data field. "
"Example element of list: \"/stimulus/presentation/Sweep_0\"` "
"COMMENT: Attribute is only present if links are present. "
"List should include the path to this TimeSeries also."),
"data_type": "text",
"dimensions": ["num_dlinks"],
"autogen": {
"type": "links",
"target":"data",
"trim": True,
"qty": "*"}},
"timestamp_link": {
"description": ("A sorted list of the paths of all TimeSeries that share a link "
"to the same timestamps field. "
"Example element of list: \"/acquisition/timeseries/lick_trace\" "
"COMMENT: Attribute is only present if links "
"are present. List should include the path to this TimeSeries also."),
"data_type": "text",
"dimensions": ["num_tslinks"],
"autogen": {
"type": "links",
"target":"timestamps",
"trim": True,
"qty": "*"}},
"missing_fields^": {
"description": ("List of fields that are not optional (i.e. either "
"required or recommended parts of the"
" TimeSeries) that are missing. "
"The list can also include additional identifiers, as long as "
"they are not present in the group, whether or not they optional."
"COMMENT: Only present if one or more required or recommended fields are missing. Note that "
"a missing required field (such as data or timestamps) should generate an error "
"by the API"),
"data_type": "text",
"dimensions": ["num_missing_fields"],
"autogen": {
"type": "missing",
"allow_others": True,
# "target":
# "trim": True,
"qty": "*"}},
"extern_fields^": {
"description": ("List of fields that are HDF5 external links."
"COMMENT: Only present if one or more datasets is set to an HDF5 external link."),
"data_type": "text",
"dimensions": ["num_extern_fields"],
"autogen": {
"type": "extern",
# "target":
# "trim": True,
"qty": "*"}},
"help?": {
"description": ("Short description indicating what this type of TimeSeries stores."),
"data_type": "text",
"value": "General time series object",
"const": True
}
},
"timestamps": {
"description": ("Timestamps for samples stored in data."
"COMMENT: Timestamps here have all been corrected to the common experiment "
"master-clock. Time is stored as seconds and all timestamps are relative to "
"experiment start time."),
"data_type": "float64!",
"dimensions": ["num_times"],
"attributes": {
"interval": {
"description": ("The number of samples between each timestamp. "
"COMMENT: Presently this value is restricted to 1 (ie, a timestamp "
"for each sample)"),
"data_type": "int32", "value": 1, "const": True},
"unit": {
"description": ("The string \"Seconds\" "
"COMMENT: All timestamps in the file are stored in seconds. "
"Specifically, this is the number of seconds since the start of the "
"experiment (i.e., since session_start_time)"),
"data_type": "text", "value": "Seconds"} },
},
"_required": { # Specifies required member combinations",
"start_time" :
["starting_time XOR timestamps",
"Either starting_time or timestamps must be present, but not both."],
"control":
["(control AND control_description) OR (NOT control AND NOT control_description)",
("If either control or control_description are present, then "
"both must be present.")]},
"_exclude_in": {
# specifies path where members must (!) or should (^) not be present, or are optional (?)
"/stimulus/templates": [ "starting_time!", "timestamps!", "num_samples?"] },
"starting_time?": {
"description": ("The timestamp of the first sample. "
"COMMENT: When timestamps are uniformly spaced, the timestamp of the first "
"sample can be specified and all subsequent ones calculated from the "
"sampling rate."),
"data_type": "float64!",
"attributes": {
"rate": {
"description": ("Sampling rate, in Hz "
"COMMENT: Rate information is stored in Hz"),
"data_type": "float32!"},
"unit": {
"description": ("The string \"Seconds\""
"COMMENT: All timestamps in the file are stored in seconds. "
"Specifically, this is the number of seconds since the start of the "
"experiment (i.e., since session_start_time)"),
"data_type": "text",
"value": "Seconds"}},
},
"num_samples": {
"description": ("Number of samples in data, or number of image frames. "
"COMMENT: This is important if the length of timestamp and data are "
"different, such as for externally stored stimulus image stacks"),
"data_type": "int32",
"autogen": {
"type": "length",
"target":"timestamps"},
},
"control?": {
"description": ("Numerical labels that apply to each element in data[]. "
"COMMENT: Optional field. If present, the control array should have the "
"same number of elements as data[]."),
"data_type": "uint8",
"dimensions": ["num_times"],
"references": "control_description.num_control_values"
},
"control_description?": {
"data_type": "text",
"dimensions": ["num_control_values"],
"description": ("Description of each control value. COMMENT: Array length should "
"be as long as the highest number in control minus one, generating an "
"zero-based indexed array for control values.")
},
"sync/?": {
"description": ("Lab specific time and sync information as provided directly "
"from hardware devices and that is necessary for aligning all acquired "
"time information to a common timebase. The timestamp array stores time "
"in the common timebase. "
"COMMENT: This group will usually only be populated in TimeSeries that "
"are stored external to the NWB file, in files storing raw data. Once "
"timestamp data is calculated, the contents of 'sync' are mostly for "
"archival purposes.") },
"data": {
"description": ("Data values. Can also store binary data (eg, image frames) "
"COMMENT: This field may be a link to data stored in an external file, "
"especially in the case of raw data."),
"attributes": {
"conversion": {
"description": ("Scalar to multiply each element in data to convert it to "
"the specified unit"),
"value": 1.0, # default value
"data_type": "float32!" },
"unit": {
"description": ("The base unit of measure used to store data. This should "
"be in the SI unit. "
"COMMENT: This is the SI unit (when appropriate) of the stored data, "
"such as Volts. If the actual data is stored in millivolts, the field "
"'conversion' below describes how to convert the data to the specified "
"SI unit."),
"data_type": "text"},
"resolution": {
"description": ("Smallest meaningful difference between values in data, stored "
"in the specified by unit. "
"COMMENT: E.g., the change in value of the least significant bit, or a larger "
"number if signal noise is known to be present. If unknown, use NaN"),
"value": 0.0, # default value
"data_type": "float32!"},
},
"dimensions": [["num_times"], # 1-d array (normal case)
["num_times", "num_d2"], # 2-d array
["num_times", "num_d2", "num_d3"]], # 3-d array
"data_type": "any"
},
},
"<AbstractFeatureSeries>/": {
"description": (
"Abstract features, such as quantitative descriptions of sensory "
"stimuli. The TimeSeries::data field is a 2D array, storing those features (e.g., "
"for visual grating stimulus this might be orientation, spatial frequency and "
"contrast). Null stimuli (eg, uniform gray) can be marked as being an independent "
"feature (eg, 1.0 for gray, 0.0 for actual stimulus) or by storing NaNs for "
"feature values, or through use of the TimeSeries::control fields. A set of "
"features is considered to persist until the next set of features is defined. "
"The final set of features stored should be the null set."),
"merge": ["<TimeSeries>/"],
"attributes": {
"ancestry": {"data_type": "text",
"dimensions": ["2"],
"value":["TimeSeries","AbstractFeatureSeries"],
"const": True},
"help?": {
"data_type": "text",
"value": ("Features of an applied stimulus. This is useful when storing the raw "
"stimulus is impractical"),
"const": True}},
"features": {
"description": "Description of the features represented in TimeSeries::data.",
"dimensions": ["num_features"],
"data_type": "text"},
"feature_units^": {
"description": "Units of each feature.",
"dimensions": ["num_features"],
"data_type": "text"},
"data": {
"description": "Values of each feature at each time.",
"dimensions": ["num_times", "num_features"],
"data_type": "float32",
"attributes": { "unit": {
"value": "see 'feature_units'"}}},
},
"<AnnotationSeries>/": {
"description": ("Stores, eg, user annotations made during an experiment. The "
"TimeSeries::data[] field stores a text array, and timestamps are stored for "
"each annotation (ie, interval=1). This is largely an alias to a standard TimeSeries "
"storing a text array but that is identifiable as storing annotations in a "
"machine-readable way."),
"merge": ["<TimeSeries>/"],
"attributes": {
"ancestry": {
"data_type": "text",
"dimensions": ["2"],
"value":["TimeSeries","AnnotationSeries"],
"const": True },
"help?": {
"data_type": "text",
"value": "Time-stamped annotations about an experiment",
"const": True}},
"data": {
"description": "Annotations made during an experiment.",
"dimensions": ["num_times"],
"data_type": "text",
"attributes": {
"conversion": {
"description": "Value is float('NaN') since this does not apply.",
"value": "float('NaN')"},
"resolution": {
"description": "Value is float('NaN') since this does not apply.",
"value": "float('NaN')"},
"unit": {
"description": "Value is \"n/a\" to indicate that this does not apply.",
"value": "n/a"}}},
},
"<IndexSeries>/": {
"description": ("Stores indices to (typically image) frames stored in another TimeSeries. "
"Its purpose is to allow a static image stack to be stored somewhere, "
"and the images in the stack to be referenced out-of-order. This can be for the "
"display of individual images, or of movie segments (as a movie is simply a "
"series of images). The data field stores the index of the frame in the "
"referenced TimeSeries, and the timestamps array indicates when that frame "
"was displayed. Can also be used for non-image data."),
"merge": ["<TimeSeries>/"],
"attributes": {
"ancestry": {
"data_type": "text",
"dimensions": ["2"],
"value":["TimeSeries","IndexSeries"],
"const": True},
"help?": {
"data_type": "text",
"value": ("A sequence that is generated from an existing image stack. "
"Frames can be presented in an arbitrary order. The data[] field "
"stores frame number in reference stack"),
"const": True}},
"data": {
"dimensions": ["num_times"],
"data_type": "int",
"description": "Index of the frame in the referenced ImageSeries.",
"references": "indexed_timeseries/data.num_times"},
"indexed_timeseries/": {
"description": "HDF5 link to TimeSeries containing images that are indexed.",
"link": {"target_type": "<TimeSeries>/", "allow_subclasses": True } },
"indexed_timeseries_path": {
"description": "Path to linked TimeSeries",
"data_type": "text",
"autogen": {
"type": "link_path",
"target":"indexed_timeseries/",
"trim": False,
"qty": "!",
"format": "$t"}},
},
"<IntervalSeries>/": {
"description": ("Stores intervals of data. The timestamps field stores the beginning "
"and end of intervals. The data field stores whether the interval just started "
"(<0 value) or ended (>0 value). Different interval types can be represented in "
"the same series by using multiple key values (eg, 1 for feature A, 2 for feature "
"B, 3 for feature C, etc). The field data stores an 8-bit integer. This is largely "
"an alias of a standard TimeSeries but that is identifiable as representing time "
"intervals in a machine-readable way."),
"merge": ["<TimeSeries>/"],
"attributes": {
"ancestry": {
"data_type": "text",
"dimensions": ["2"],
"value": ["TimeSeries","IntervalSeries"],
"const": True},
"help?": {
"data_type": "text",
"value": "Stores the start and stop times for events",
"const": True}},
"data": {
"description": (">0 if interval started, <0 if interval ended."),
"dimensions": ["num_times"],
"attributes": {
"conversion": {
# "description": "Value is float('nan') since this does not apply.",
"value": "float('NaN')"},
"resolution": {
# "description": "Value is float('nan') since this does not apply",
"value": "float('NaN')"},
"unit": {
# "description": "Value is \"n/a\" to indicate that this does not apply",
"value": "n/a"}},
"data_type": "int8"},
},
"<OptogeneticSeries>/": {