pynwb-1.2.1/0000755000655200065520000000000013612200376014240 5ustar circlecicircleci00000000000000pynwb-1.2.1/test.py0000755000655200065520000001675613612200244015605 0ustar circlecicircleci00000000000000#!/usr/bin/env python import warnings import re import argparse import glob import inspect import logging import os.path import os import sys import traceback import unittest from tests.coloredtestrunner import ColoredTestRunner, ColoredTestResult flags = {'pynwb': 2, 'integration': 3, 'example': 4, 'backwards': 5} TOTAL = 0 FAILURES = 0 ERRORS = 0 def run_test_suite(directory, description="", verbose=True): global TOTAL, FAILURES, ERRORS logging.info("running %s" % description) directory = os.path.join(os.path.dirname(__file__), directory) if verbose > 1: runner = ColoredTestRunner(verbosity=verbose) else: runner = unittest.TextTestRunner(verbosity=verbose, resultclass=ColoredTestResult) test_result = runner.run(unittest.TestLoader().discover(directory)) TOTAL += test_result.testsRun FAILURES += len(test_result.failures) ERRORS += len(test_result.errors) return test_result def _import_from_file(script): import imp return imp.load_source(os.path.basename(script), script) warning_re = re.compile("Parent module '[a-zA-Z0-9]+' not found while handling absolute import") def run_example_tests(): global TOTAL, FAILURES, ERRORS logging.info('running example tests') examples_scripts = list() for root, dirs, files in os.walk(os.path.join(os.path.dirname(__file__), "docs", "gallery")): for f in files: if f.endswith(".py"): examples_scripts.append(os.path.join(root, f)) TOTAL += len(examples_scripts) for script in examples_scripts: try: logging.info("Executing %s" % script) ws = list() with warnings.catch_warnings(record=True) as tmp: _import_from_file(script) for w in tmp: # ignore RunTimeWarnings about importing if isinstance(w.message, RuntimeWarning) and not warning_re.match(str(w.message)): ws.append(w) for w in ws: warnings.showwarning(w.message, w.category, w.filename, w.lineno, w.line) except Exception: print(traceback.format_exc()) FAILURES += 1 ERRORS += 1 def validate_nwbs(): global TOTAL, FAILURES, ERRORS logging.info('running validation tests on NWB files') examples_nwbs = glob.glob('*.nwb') import pynwb TOTAL += len(examples_nwbs) for nwb in examples_nwbs: try: logging.info("Validating file %s" % nwb) ws = list() with warnings.catch_warnings(record=True) as tmp: with pynwb.NWBHDF5IO(nwb, mode='r') as io: errors = pynwb.validate(io) if errors: FAILURES += 1 ERRORS += 1 for err in errors: print("Error: %s" % err) for w in tmp: # ignore RunTimeWarnings about importing if isinstance(w.message, RuntimeWarning) and not warning_re.match(str(w.message)): ws.append(w) for w in ws: warnings.showwarning(w.message, w.category, w.filename, w.lineno, w.line) except Exception: print(traceback.format_exc()) FAILURES += 1 ERRORS += 1 def run_integration_tests(verbose=True): pynwb_test_result = run_test_suite("tests/integration", "integration tests", verbose=verbose) test_cases = pynwb_test_result.get_all_cases_run() import pynwb type_map = pynwb.get_type_map() tested_containers = {} for test_case in test_cases: if not hasattr(test_case, 'container'): continue container_class = test_case.container.__class__ if container_class not in tested_containers: tested_containers[container_class] = [test_case._testMethodName] else: tested_containers[container_class].append(test_case._testMethodName) count_missing = 0 for container_class in type_map.get_container_classes('core'): if container_class not in tested_containers: count_missing += 1 if verbose > 1: logging.info('%s missing test case; should define in %s' % (container_class, inspect.getfile(container_class))) if count_missing > 0: logging.info('%d classes missing integration tests in ui_write' % count_missing) else: logging.info('all classes have integration tests') def main(): # setup and parse arguments parser = argparse.ArgumentParser('python test.py [options]') parser.set_defaults(verbosity=1, suites=[]) parser.add_argument('-v', '--verbose', const=2, dest='verbosity', action='store_const', help='run in verbose mode') parser.add_argument('-q', '--quiet', const=0, dest='verbosity', action='store_const', help='run disabling output') parser.add_argument('-p', '--pynwb', action='append_const', const=flags['pynwb'], dest='suites', help='run unit tests for pynwb package') parser.add_argument('-i', '--integration', action='append_const', const=flags['integration'], dest='suites', help='run integration tests') parser.add_argument('-e', '--example', action='append_const', const=flags['example'], dest='suites', help='run example tests') parser.add_argument('-b', '--backwards', action='append_const', const=flags['backwards'], dest='suites', help='run backwards compatibility tests') args = parser.parse_args() if not args.suites: args.suites = list(flags.values()) args.suites.pop(args.suites.index(flags['example'])) # remove example as a suite run by default # set up logger root = logging.getLogger() root.setLevel(logging.DEBUG) ch = logging.StreamHandler(sys.stdout) ch.setLevel(logging.DEBUG) formatter = logging.Formatter('======================================================================\n' '%(asctime)s - %(levelname)s - %(message)s') ch.setFormatter(formatter) root.addHandler(ch) warnings.simplefilter('always') warnings.filterwarnings("ignore", category=ImportWarning, module='importlib._bootstrap', message=("can't resolve package from __spec__ or __package__, falling back on __name__ " "and __path__")) # Run unit tests for pynwb package if flags['pynwb'] in args.suites: run_test_suite("tests/unit", "pynwb unit tests", verbose=args.verbosity) # Run example tests if flags['example'] in args.suites: run_example_tests() validate_nwbs() # Run integration tests if flags['integration'] in args.suites: run_integration_tests(verbose=args.verbosity) if flags['backwards'] in args.suites: run_test_suite("tests/back_compat", "pynwb backwards compatibility tests", verbose=args.verbosity) final_message = 'Ran %s tests' % TOTAL exitcode = 0 if ERRORS > 0 or FAILURES > 0: exitcode = 1 _list = list() if ERRORS > 0: _list.append('errors=%d' % ERRORS) if FAILURES > 0: _list.append('failures=%d' % FAILURES) final_message = '%s - FAILED (%s)' % (final_message, ','.join(_list)) else: final_message = '%s - OK' % final_message logging.info(final_message) return exitcode if __name__ == "__main__": sys.exit(main()) pynwb-1.2.1/Legal.txt0000644000655200065520000000150713612200244016022 0ustar circlecicircleci00000000000000“pynwb” Copyright (c) 2017-2020, The Regents of the University of California, through Lawrence Berkeley National Laboratory (subject to receipt of any required approvals from the U.S. Dept. of Energy). All rights reserved. If you have questions about your rights to use or distribute this software, please contact Berkeley Lab's Innovation & Partnerships Office at IPO@lbl.gov. NOTICE. This Software was developed under funding from the U.S. Department of Energy and the U.S. Government consequently retains certain rights. As such, the U.S. Government has been granted for itself and others acting on its behalf a paid-up, nonexclusive, irrevocable, worldwide license in the Software to reproduce, distribute copies to the public, prepare derivative works, and perform publicly and display publicly, and to permit other to do so. pynwb-1.2.1/tox.ini0000644000655200065520000000521313612200244015546 0ustar circlecicircleci00000000000000# Tox (https://tox.readthedocs.io/) is a tool for running tests # in multiple virtualenvs. This configuration file will run the # test suite on all supported python versions. To use it, "pip install tox" # and then run "tox" from this directory. [tox] envlist = py35, py36, py37 [testenv] usedevelop = True setenv = PYTHONDONTWRITEBYTECODE = 1 install_command = pip install -U {opts} {packages} deps = -rrequirements-dev.txt -rrequirements.txt commands = pip check # check for conflicting packages python test.py -v # Env to create coverage report locally [testenv:localcoverage] basepython = python3.6 commands = coverage run test.py --pynwb coverage html -d tests/coverage/htmlcov # Test with python 3.5, pinned dev reqs, and minimum run requirements [testenv:py35-min-req] basepython = python3.5 deps = -rrequirements-dev.txt -rrequirements-min.txt commands = {[testenv]commands} # Envs that builds wheels and source distribution [testenv:build] commands = python setup.py sdist python setup.py bdist_wheel [testenv:build-py35] basepython = python3.5 commands = {[testenv:build]commands} [testenv:build-py36] basepython = python3.6 commands = {[testenv:build]commands} [testenv:build-py37] basepython = python3.7 commands = {[testenv:build]commands} [testenv:build-py35-min-req] basepython = python3.5 deps = -rrequirements-dev.txt -rrequirements-min.txt commands = {[testenv:build]commands} # Envs that will only be executed on CI that does coverage reporting [testenv:coverage] passenv = CODECOV_TOKEN basepython = python3.7 commands = coverage run test.py --pynwb coverage report -m codecov -X fix # Envs that will test installation from a wheel [testenv:wheelinstall-py35] deps = null commands = python -c "import pynwb" [testenv:wheelinstall-py36] deps = null commands = python -c "import pynwb" [testenv:wheelinstall-py37] deps = null commands = python -c "import pynwb" [testenv:wheelinstall-py35-min-req] deps = null commands = python -c "import pynwb" # Envs that will execute gallery tests [testenv:gallery] install_command = pip install -U {opts} {packages} deps = -rrequirements-dev.txt -rrequirements.txt -rrequirements-doc.txt commands = python test.py --example [testenv:gallery-py36] basepython = python3.6 deps = {[testenv:gallery]deps} commands = {[testenv:gallery]commands} [testenv:gallery-py37] basepython = python3.7 deps = {[testenv:gallery]deps} commands = {[testenv:gallery]commands} [testenv:gallery-py36-min-req] basepython = python3.6 deps = -rrequirements-dev.txt -rrequirements-min.txt -rrequirements-doc.txt commands = {[testenv:gallery]commands} pynwb-1.2.1/versioneer.py0000644000655200065520000021317413612200244016775 0ustar circlecicircleci00000000000000# Version: 0.18 """The Versioneer - like a rocketeer, but for versions. The Versioneer ============== * like a rocketeer, but for versions! * https://github.com/warner/python-versioneer * Brian Warner * License: Public Domain * Compatible With: python2.6, 2.7, 3.2, 3.3, 3.4, 3.5, 3.6, and pypy * [![Latest Version] (https://pypip.in/version/versioneer/badge.svg?style=flat) ](https://pypi.python.org/pypi/versioneer/) * [![Build Status] (https://travis-ci.org/warner/python-versioneer.png?branch=master) ](https://travis-ci.org/warner/python-versioneer) This is a tool for managing a recorded version number in distutils-based python projects. The goal is to remove the tedious and error-prone "update the embedded version string" step from your release process. Making a new release should be as easy as recording a new tag in your version-control system, and maybe making new tarballs. ## Quick Install * `pip install versioneer` to somewhere to your $PATH * add a `[versioneer]` section to your setup.cfg (see below) * run `versioneer install` in your source tree, commit the results ## Version Identifiers Source trees come from a variety of places: * a version-control system checkout (mostly used by developers) * a nightly tarball, produced by build automation * a snapshot tarball, produced by a web-based VCS browser, like github's "tarball from tag" feature * a release tarball, produced by "setup.py sdist", distributed through PyPI Within each source tree, the version identifier (either a string or a number, this tool is format-agnostic) can come from a variety of places: * ask the VCS tool itself, e.g. "git describe" (for checkouts), which knows about recent "tags" and an absolute revision-id * the name of the directory into which the tarball was unpacked * an expanded VCS keyword ($Id$, etc) * a `_version.py` created by some earlier build step For released software, the version identifier is closely related to a VCS tag. Some projects use tag names that include more than just the version string (e.g. "myproject-1.2" instead of just "1.2"), in which case the tool needs to strip the tag prefix to extract the version identifier. For unreleased software (between tags), the version identifier should provide enough information to help developers recreate the same tree, while also giving them an idea of roughly how old the tree is (after version 1.2, before version 1.3). Many VCS systems can report a description that captures this, for example `git describe --tags --dirty --always` reports things like "0.7-1-g574ab98-dirty" to indicate that the checkout is one revision past the 0.7 tag, has a unique revision id of "574ab98", and is "dirty" (it has uncommitted changes. The version identifier is used for multiple purposes: * to allow the module to self-identify its version: `myproject.__version__` * to choose a name and prefix for a 'setup.py sdist' tarball ## Theory of Operation Versioneer works by adding a special `_version.py` file into your source tree, where your `__init__.py` can import it. This `_version.py` knows how to dynamically ask the VCS tool for version information at import time. `_version.py` also contains `$Revision$` markers, and the installation process marks `_version.py` to have this marker rewritten with a tag name during the `git archive` command. As a result, generated tarballs will contain enough information to get the proper version. To allow `setup.py` to compute a version too, a `versioneer.py` is added to the top level of your source tree, next to `setup.py` and the `setup.cfg` that configures it. This overrides several distutils/setuptools commands to compute the version when invoked, and changes `setup.py build` and `setup.py sdist` to replace `_version.py` with a small static file that contains just the generated version data. ## Installation See [INSTALL.md](./INSTALL.md) for detailed installation instructions. ## Version-String Flavors Code which uses Versioneer can learn about its version string at runtime by importing `_version` from your main `__init__.py` file and running the `get_versions()` function. From the "outside" (e.g. in `setup.py`), you can import the top-level `versioneer.py` and run `get_versions()`. Both functions return a dictionary with different flavors of version information: * `['version']`: A condensed version string, rendered using the selected style. This is the most commonly used value for the project's version string. The default "pep440" style yields strings like `0.11`, `0.11+2.g1076c97`, or `0.11+2.g1076c97.dirty`. See the "Styles" section below for alternative styles. * `['full-revisionid']`: detailed revision identifier. For Git, this is the full SHA1 commit id, e.g. "1076c978a8d3cfc70f408fe5974aa6c092c949ac". * `['date']`: Date and time of the latest `HEAD` commit. For Git, it is the commit date in ISO 8601 format. This will be None if the date is not available. * `['dirty']`: a boolean, True if the tree has uncommitted changes. Note that this is only accurate if run in a VCS checkout, otherwise it is likely to be False or None * `['error']`: if the version string could not be computed, this will be set to a string describing the problem, otherwise it will be None. It may be useful to throw an exception in setup.py if this is set, to avoid e.g. creating tarballs with a version string of "unknown". Some variants are more useful than others. Including `full-revisionid` in a bug report should allow developers to reconstruct the exact code being tested (or indicate the presence of local changes that should be shared with the developers). `version` is suitable for display in an "about" box or a CLI `--version` output: it can be easily compared against release notes and lists of bugs fixed in various releases. The installer adds the following text to your `__init__.py` to place a basic version in `YOURPROJECT.__version__`: from ._version import get_versions __version__ = get_versions()['version'] del get_versions ## Styles The setup.cfg `style=` configuration controls how the VCS information is rendered into a version string. The default style, "pep440", produces a PEP440-compliant string, equal to the un-prefixed tag name for actual releases, and containing an additional "local version" section with more detail for in-between builds. For Git, this is TAG[+DISTANCE.gHEX[.dirty]] , using information from `git describe --tags --dirty --always`. For example "0.11+2.g1076c97.dirty" indicates that the tree is like the "1076c97" commit but has uncommitted changes (".dirty"), and that this commit is two revisions ("+2") beyond the "0.11" tag. For released software (exactly equal to a known tag), the identifier will only contain the stripped tag, e.g. "0.11". Other styles are available. See [details.md](details.md) in the Versioneer source tree for descriptions. ## Debugging Versioneer tries to avoid fatal errors: if something goes wrong, it will tend to return a version of "0+unknown". To investigate the problem, run `setup.py version`, which will run the version-lookup code in a verbose mode, and will display the full contents of `get_versions()` (including the `error` string, which may help identify what went wrong). ## Known Limitations Some situations are known to cause problems for Versioneer. This details the most significant ones. More can be found on Github [issues page](https://github.com/warner/python-versioneer/issues). ### Subprojects Versioneer has limited support for source trees in which `setup.py` is not in the root directory (e.g. `setup.py` and `.git/` are *not* siblings). The are two common reasons why `setup.py` might not be in the root: * Source trees which contain multiple subprojects, such as [Buildbot](https://github.com/buildbot/buildbot), which contains both "master" and "slave" subprojects, each with their own `setup.py`, `setup.cfg`, and `tox.ini`. Projects like these produce multiple PyPI distributions (and upload multiple independently-installable tarballs). * Source trees whose main purpose is to contain a C library, but which also provide bindings to Python (and perhaps other languages) in subdirectories. Versioneer will look for `.git` in parent directories, and most operations should get the right version string. However `pip` and `setuptools` have bugs and implementation details which frequently cause `pip install .` from a subproject directory to fail to find a correct version string (so it usually defaults to `0+unknown`). `pip install --editable .` should work correctly. `setup.py install` might work too. Pip-8.1.1 is known to have this problem, but hopefully it will get fixed in some later version. [Bug #38](https://github.com/warner/python-versioneer/issues/38) is tracking this issue. The discussion in [PR #61](https://github.com/warner/python-versioneer/pull/61) describes the issue from the Versioneer side in more detail. [pip PR#3176](https://github.com/pypa/pip/pull/3176) and [pip PR#3615](https://github.com/pypa/pip/pull/3615) contain work to improve pip to let Versioneer work correctly. Versioneer-0.16 and earlier only looked for a `.git` directory next to the `setup.cfg`, so subprojects were completely unsupported with those releases. ### Editable installs with setuptools <= 18.5 `setup.py develop` and `pip install --editable .` allow you to install a project into a virtualenv once, then continue editing the source code (and test) without re-installing after every change. "Entry-point scripts" (`setup(entry_points={"console_scripts": ..})`) are a convenient way to specify executable scripts that should be installed along with the python package. These both work as expected when using modern setuptools. When using setuptools-18.5 or earlier, however, certain operations will cause `pkg_resources.DistributionNotFound` errors when running the entrypoint script, which must be resolved by re-installing the package. This happens when the install happens with one version, then the egg_info data is regenerated while a different version is checked out. Many setup.py commands cause egg_info to be rebuilt (including `sdist`, `wheel`, and installing into a different virtualenv), so this can be surprising. [Bug #83](https://github.com/warner/python-versioneer/issues/83) describes this one, but upgrading to a newer version of setuptools should probably resolve it. ### Unicode version strings While Versioneer works (and is continually tested) with both Python 2 and Python 3, it is not entirely consistent with bytes-vs-unicode distinctions. Newer releases probably generate unicode version strings on py2. It's not clear that this is wrong, but it may be surprising for applications when then write these strings to a network connection or include them in bytes-oriented APIs like cryptographic checksums. [Bug #71](https://github.com/warner/python-versioneer/issues/71) investigates this question. ## Updating Versioneer To upgrade your project to a new release of Versioneer, do the following: * install the new Versioneer (`pip install -U versioneer` or equivalent) * edit `setup.cfg`, if necessary, to include any new configuration settings indicated by the release notes. See [UPGRADING](./UPGRADING.md) for details. * re-run `versioneer install` in your source tree, to replace `SRC/_version.py` * commit any changed files ## Future Directions This tool is designed to make it easily extended to other version-control systems: all VCS-specific components are in separate directories like src/git/ . The top-level `versioneer.py` script is assembled from these components by running make-versioneer.py . In the future, make-versioneer.py will take a VCS name as an argument, and will construct a version of `versioneer.py` that is specific to the given VCS. It might also take the configuration arguments that are currently provided manually during installation by editing setup.py . Alternatively, it might go the other direction and include code from all supported VCS systems, reducing the number of intermediate scripts. ## License To make Versioneer easier to embed, all its code is dedicated to the public domain. The `_version.py` that it creates is also in the public domain. Specifically, both are released under the Creative Commons "Public Domain Dedication" license (CC0-1.0), as described in https://creativecommons.org/publicdomain/zero/1.0/ . """ from __future__ import print_function try: import configparser except ImportError: import ConfigParser as configparser import errno import fnmatch # PYNWB import json import os import re import subprocess import sys class VersioneerConfig: """Container for Versioneer configuration parameters.""" def get_root(): """Get the project root directory. We require that all commands are run from the project root, i.e. the directory that contains setup.py, setup.cfg, and versioneer.py . """ root = os.path.realpath(os.path.abspath(os.getcwd())) setup_py = os.path.join(root, "setup.py") versioneer_py = os.path.join(root, "versioneer.py") if not (os.path.exists(setup_py) or os.path.exists(versioneer_py)): # allow 'python path/to/setup.py COMMAND' root = os.path.dirname(os.path.realpath(os.path.abspath(sys.argv[0]))) setup_py = os.path.join(root, "setup.py") versioneer_py = os.path.join(root, "versioneer.py") if not (os.path.exists(setup_py) or os.path.exists(versioneer_py)): err = ("Versioneer was unable to run the project root directory. " "Versioneer requires setup.py to be executed from " "its immediate directory (like 'python setup.py COMMAND'), " "or in a way that lets it use sys.argv[0] to find the root " "(like 'python path/to/setup.py COMMAND').") raise VersioneerBadRootError(err) try: # Certain runtime workflows (setup.py install/develop in a setuptools # tree) execute all dependencies in a single python process, so # "versioneer" may be imported multiple times, and python's shared # module-import table will cache the first one. So we can't use # os.path.dirname(__file__), as that will find whichever # versioneer.py was first imported, even in later projects. me = os.path.realpath(os.path.abspath(__file__)) me_dir = os.path.normcase(os.path.splitext(me)[0]) vsr_dir = os.path.normcase(os.path.splitext(versioneer_py)[0]) if me_dir != vsr_dir: print("Warning: build in %s is using versioneer.py from %s" % (os.path.dirname(me), versioneer_py)) except NameError: pass return root def get_config_from_root(root): """Read the project setup.cfg file to determine Versioneer config.""" # This might raise EnvironmentError (if setup.cfg is missing), or # configparser.NoSectionError (if it lacks a [versioneer] section), or # configparser.NoOptionError (if it lacks "VCS="). See the docstring at # the top of versioneer.py for instructions on writing your setup.cfg . setup_cfg = os.path.join(root, "setup.cfg") parser = configparser.SafeConfigParser() with open(setup_cfg, "r") as f: parser.readfp(f) VCS = parser.get("versioneer", "VCS") # mandatory def get(parser, name): if parser.has_option("versioneer", name): return parser.get("versioneer", name) return None cfg = VersioneerConfig() cfg.VCS = VCS cfg.style = get(parser, "style") or "" cfg.versionfile_source = get(parser, "versionfile_source") cfg.versionfile_build = get(parser, "versionfile_build") cfg.tag_prefix = get(parser, "tag_prefix") if cfg.tag_prefix in ("''", '""'): cfg.tag_prefix = "" cfg.parentdir_prefix = get(parser, "parentdir_prefix") cfg.verbose = get(parser, "verbose") return cfg class NotThisMethod(Exception): """Exception raised if a method is not valid for the current scenario.""" # these dictionaries contain VCS-specific tools LONG_VERSION_PY = {} HANDLERS = {} def register_vcs_handler(vcs, method): # decorator """Decorator to mark a method as the handler for a particular VCS.""" def decorate(f): """Store f in HANDLERS[vcs][method].""" if vcs not in HANDLERS: HANDLERS[vcs] = {} HANDLERS[vcs][method] = f return f return decorate def run_command(commands, args, cwd=None, verbose=False, hide_stderr=False, env=None): """Call the given command(s).""" assert isinstance(commands, list) p = None for c in commands: try: dispcmd = str([c] + args) # remember shell=False, so use git.cmd on windows, not just git p = subprocess.Popen([c] + args, cwd=cwd, env=env, stdout=subprocess.PIPE, stderr=(subprocess.PIPE if hide_stderr else None)) break except EnvironmentError: e = sys.exc_info()[1] if e.errno == errno.ENOENT: continue if verbose: print("unable to run %s" % dispcmd) print(e) return None, None else: if verbose: print("unable to find command, tried %s" % (commands,)) return None, None stdout = p.communicate()[0].strip() if sys.version_info[0] >= 3: stdout = stdout.decode() if p.returncode != 0: if verbose: print("unable to run %s (error)" % dispcmd) print("stdout was %s" % stdout) return None, p.returncode return stdout, p.returncode LONG_VERSION_PY['git'] = ''' # This file helps to compute a version number in source trees obtained from # git-archive tarball (such as those provided by githubs download-from-tag # feature). Distribution tarballs (built by setup.py sdist) and build # directories (produced by setup.py build) will contain a much shorter file # that just contains the computed version number. # This file is released into the public domain. Generated by # versioneer-0.18 (https://github.com/warner/python-versioneer) """Git implementation of _version.py.""" import errno import fnmatch # PYNWB import os import re import subprocess import sys def get_keywords(): """Get the keywords needed to look up the version information.""" # these strings will be replaced by git during git-archive. # setup.py/versioneer.py will grep for the variable names, so they must # each be defined on a line of their own. _version.py will just call # get_keywords(). git_refnames = "%(DOLLAR)sFormat:%%d%(DOLLAR)s" git_full = "%(DOLLAR)sFormat:%%H%(DOLLAR)s" git_date = "%(DOLLAR)sFormat:%%ci%(DOLLAR)s" keywords = {"refnames": git_refnames, "full": git_full, "date": git_date} return keywords class VersioneerConfig: """Container for Versioneer configuration parameters.""" def get_config(): """Create, populate and return the VersioneerConfig() object.""" # these strings are filled in when 'setup.py versioneer' creates # _version.py cfg = VersioneerConfig() cfg.VCS = "git" cfg.style = "%(STYLE)s" cfg.tag_prefix = "%(TAG_PREFIX)s" cfg.parentdir_prefix = "%(PARENTDIR_PREFIX)s" cfg.versionfile_source = "%(VERSIONFILE_SOURCE)s" cfg.verbose = False return cfg class NotThisMethod(Exception): """Exception raised if a method is not valid for the current scenario.""" LONG_VERSION_PY = {} HANDLERS = {} def register_vcs_handler(vcs, method): # decorator """Decorator to mark a method as the handler for a particular VCS.""" def decorate(f): """Store f in HANDLERS[vcs][method].""" if vcs not in HANDLERS: HANDLERS[vcs] = {} HANDLERS[vcs][method] = f return f return decorate def run_command(commands, args, cwd=None, verbose=False, hide_stderr=False, env=None): """Call the given command(s).""" assert isinstance(commands, list) p = None for c in commands: try: dispcmd = str([c] + args) # remember shell=False, so use git.cmd on windows, not just git p = subprocess.Popen([c] + args, cwd=cwd, env=env, stdout=subprocess.PIPE, stderr=(subprocess.PIPE if hide_stderr else None)) break except EnvironmentError: e = sys.exc_info()[1] if e.errno == errno.ENOENT: continue if verbose: print("unable to run %%s" %% dispcmd) print(e) return None, None else: if verbose: print("unable to find command, tried %%s" %% (commands,)) return None, None stdout = p.communicate()[0].strip() if sys.version_info[0] >= 3: stdout = stdout.decode() if p.returncode != 0: if verbose: print("unable to run %%s (error)" %% dispcmd) print("stdout was %%s" %% stdout) return None, p.returncode return stdout, p.returncode def versions_from_parentdir(parentdir_prefix, root, verbose): """Try to determine the version from the parent directory name. Source tarballs conventionally unpack into a directory that includes both the project name and a version string. We will also support searching up two directory levels for an appropriately named parent directory """ rootdirs = [] for i in range(3): dirname = os.path.basename(root) if dirname.startswith(parentdir_prefix): return {"version": dirname[len(parentdir_prefix):], "full-revisionid": None, "dirty": False, "error": None, "date": None} else: rootdirs.append(root) root = os.path.dirname(root) # up a level if verbose: print("Tried directories %%s but none started with prefix %%s" %% (str(rootdirs), parentdir_prefix)) raise NotThisMethod("rootdir doesn't start with parentdir_prefix") @register_vcs_handler("git", "get_keywords") def git_get_keywords(versionfile_abs): """Extract version information from the given file.""" # the code embedded in _version.py can just fetch the value of these # keywords. When used from setup.py, we don't want to import _version.py, # so we do it with a regexp instead. This function is not used from # _version.py. keywords = {} try: f = open(versionfile_abs, "r") for line in f.readlines(): if line.strip().startswith("git_refnames ="): mo = re.search(r'=\s*"(.*)"', line) if mo: keywords["refnames"] = mo.group(1) if line.strip().startswith("git_full ="): mo = re.search(r'=\s*"(.*)"', line) if mo: keywords["full"] = mo.group(1) if line.strip().startswith("git_date ="): mo = re.search(r'=\s*"(.*)"', line) if mo: keywords["date"] = mo.group(1) f.close() except EnvironmentError: pass return keywords @register_vcs_handler("git", "keywords") def git_versions_from_keywords(keywords, tag_prefix, verbose): """Get version information from git keywords.""" if not keywords: raise NotThisMethod("no keywords at all, weird") date = keywords.get("date") if date is not None: # git-2.2.0 added "%%cI", which expands to an ISO-8601 -compliant # datestamp. However we prefer "%%ci" (which expands to an "ISO-8601 # -like" string, which we must then edit to make compliant), because # it's been around since git-1.5.3, and it's too difficult to # discover which version we're using, or to work around using an # older one. date = date.strip().replace(" ", "T", 1).replace(" ", "", 1) refnames = keywords["refnames"].strip() if refnames.startswith("$Format"): if verbose: print("keywords are unexpanded, not using") raise NotThisMethod("unexpanded keywords, not a git-archive tarball") refs = set([r.strip() for r in refnames.strip("()").split(",")]) # starting in git-1.8.3, tags are listed as "tag: foo-1.0" instead of # just "foo-1.0". If we see a "tag: " prefix, prefer those. TAG = "tag: " tags = set([r[len(TAG):] for r in refs if r.startswith(TAG)]) if not tags: # Either we're using git < 1.8.3, or there really are no tags. We use # a heuristic: assume all version tags have a digit. The old git %%d # expansion behaves like git log --decorate=short and strips out the # refs/heads/ and refs/tags/ prefixes that would let us distinguish # between branches and tags. By ignoring refnames without digits, we # filter out many common branch names like "release" and # "stabilization", as well as "HEAD" and "master". tags = set([r for r in refs if re.search(r'\d', r)]) if verbose: print("discarding '%%s', no digits" %% ",".join(refs - tags)) if verbose: print("likely tags: %%s" %% ",".join(sorted(tags))) for ref in sorted(tags): # sorting will prefer e.g. "2.0" over "2.0rc1" # PYNWB: Support tag_prefix specified as a glob pattern tag_is_glob_pattern = "*" in tag_prefix if tag_is_glob_pattern: if fnmatch.fnmatch(ref, tag_prefix): r = ref if verbose: print("picking %s" % r) return {"version": r, "full-revisionid": keywords["full"].strip(), "dirty": False, "error": None, "date": date} else: if ref.startswith(tag_prefix): r = ref[len(tag_prefix):] if verbose: print("picking %s" % r) return {"version": r, "full-revisionid": keywords["full"].strip(), "dirty": False, "error": None, "date": date} # no suitable tags, so version is "0+unknown", but full hex is still there if verbose: print("no suitable tags, using unknown + full revision id") return {"version": "0+unknown", "full-revisionid": keywords["full"].strip(), "dirty": False, "error": "no suitable tags", "date": None} @register_vcs_handler("git", "pieces_from_vcs") def git_pieces_from_vcs(tag_prefix, root, verbose, run_command=run_command): """Get version from 'git describe' in the root of the source tree. This only gets called if the git-archive 'subst' keywords were *not* expanded, and _version.py hasn't already been rewritten with a short version string, meaning we're inside a checked out source tree. """ GITS = ["git"] if sys.platform == "win32": GITS = ["git.cmd", "git.exe"] out, rc = run_command(GITS, ["rev-parse", "--git-dir"], cwd=root, hide_stderr=True) if rc != 0: if verbose: print("Directory %%s not under git control" %% root) raise NotThisMethod("'git rev-parse --git-dir' returned error") # PYNWB: Support tag_prefix specified as a glob pattern tag_is_glob_pattern = "*" in tag_prefix match_argument = tag_prefix if not tag_is_glob_pattern: match_argument = tag_prefix + "*" # if there is a tag matching tag_prefix, this yields TAG-NUM-gHEX[-dirty] # if there isn't one, this yields HEX[-dirty] (no NUM) describe_out, rc = run_command(GITS, ["describe", "--tags", "--dirty", "--always", "--long", "--match", "%s" % match_argument], cwd=root) # --long was added in git-1.5.5 if describe_out is None: raise NotThisMethod("'git describe' failed") describe_out = describe_out.strip() full_out, rc = run_command(GITS, ["rev-parse", "HEAD"], cwd=root) if full_out is None: raise NotThisMethod("'git rev-parse' failed") full_out = full_out.strip() pieces = {} pieces["long"] = full_out pieces["short"] = full_out[:7] # maybe improved later pieces["error"] = None # parse describe_out. It will be like TAG-NUM-gHEX[-dirty] or HEX[-dirty] # TAG might have hyphens. git_describe = describe_out # look for -dirty suffix dirty = git_describe.endswith("-dirty") pieces["dirty"] = dirty if dirty: git_describe = git_describe[:git_describe.rindex("-dirty")] # now we have TAG-NUM-gHEX or HEX if "-" in git_describe: # TAG-NUM-gHEX mo = re.search(r'^(.+)-(\d+)-g([0-9a-f]+)$', git_describe) if not mo: # unparseable. Maybe git-describe is misbehaving? pieces["error"] = ("unable to parse git-describe output: '%%s'" %% describe_out) return pieces # tag full_tag = mo.group(1) # PYNWB: Support tag_prefix specified as a glob pattern if tag_is_glob_pattern: if not fnmatch.fnmatch(full_tag, tag_prefix): if verbose: fmt = "tag '%%s' doesn't match glob pattern '%%s'" print(fmt %% (full_tag, tag_prefix)) pieces["error"] = ("tag '%%s' doesn't match glob pattern '%%s'" %% (full_tag, tag_prefix)) return pieces pieces["closest-tag"] = full_tag else: if not full_tag.startswith(tag_prefix): if verbose: fmt = "tag '%%s' doesn't start with prefix '%%s'" print(fmt %% (full_tag, tag_prefix)) pieces["error"] = ("tag '%%s' doesn't start with prefix '%%s'" %% (full_tag, tag_prefix)) return pieces pieces["closest-tag"] = full_tag[len(tag_prefix):] # distance: number of commits since tag pieces["distance"] = int(mo.group(2)) # commit: short hex revision ID pieces["short"] = mo.group(3) else: # HEX: no tags pieces["closest-tag"] = None count_out, rc = run_command(GITS, ["rev-list", "HEAD", "--count"], cwd=root) pieces["distance"] = int(count_out) # total number of commits # commit date: see ISO-8601 comment in git_versions_from_keywords() date = run_command(GITS, ["show", "-s", "--format=%%ci", "HEAD"], cwd=root)[0].strip() pieces["date"] = date.strip().replace(" ", "T", 1).replace(" ", "", 1) return pieces def plus_or_dot(pieces): """Return a + if we don't already have one, else return a .""" if "+" in pieces.get("closest-tag", ""): return "." return "+" def render_pep440(pieces): """Build up version string, with post-release "local version identifier". Our goal: TAG[+DISTANCE.gHEX[.dirty]] . Note that if you get a tagged build and then dirty it, you'll get TAG+0.gHEX.dirty Exceptions: 1: no tags. git_describe was just HEX. 0+untagged.DISTANCE.gHEX[.dirty] """ if pieces["closest-tag"]: rendered = pieces["closest-tag"] if pieces["distance"] or pieces["dirty"]: rendered += plus_or_dot(pieces) rendered += "%%d.g%%s" %% (pieces["distance"], pieces["short"]) if pieces["dirty"]: rendered += ".dirty" else: # exception #1 rendered = "0+untagged.%%d.g%%s" %% (pieces["distance"], pieces["short"]) if pieces["dirty"]: rendered += ".dirty" return rendered def render_pep440_pre(pieces): """TAG[.post.devDISTANCE] -- No -dirty. Exceptions: 1: no tags. 0.post.devDISTANCE """ if pieces["closest-tag"]: rendered = pieces["closest-tag"] if pieces["distance"]: rendered += ".post.dev%%d" %% pieces["distance"] else: # exception #1 rendered = "0.post.dev%%d" %% pieces["distance"] return rendered def render_pep440_post(pieces): """TAG[.postDISTANCE[.dev0]+gHEX] . The ".dev0" means dirty. Note that .dev0 sorts backwards (a dirty tree will appear "older" than the corresponding clean one), but you shouldn't be releasing software with -dirty anyways. Exceptions: 1: no tags. 0.postDISTANCE[.dev0] """ if pieces["closest-tag"]: rendered = pieces["closest-tag"] if pieces["distance"] or pieces["dirty"]: rendered += ".post%%d" %% pieces["distance"] if pieces["dirty"]: rendered += ".dev0" rendered += plus_or_dot(pieces) rendered += "g%%s" %% pieces["short"] else: # exception #1 rendered = "0.post%%d" %% pieces["distance"] if pieces["dirty"]: rendered += ".dev0" rendered += "+g%%s" %% pieces["short"] return rendered def render_pep440_old(pieces): """TAG[.postDISTANCE[.dev0]] . The ".dev0" means dirty. Eexceptions: 1: no tags. 0.postDISTANCE[.dev0] """ if pieces["closest-tag"]: rendered = pieces["closest-tag"] if pieces["distance"] or pieces["dirty"]: rendered += ".post%%d" %% pieces["distance"] if pieces["dirty"]: rendered += ".dev0" else: # exception #1 rendered = "0.post%%d" %% pieces["distance"] if pieces["dirty"]: rendered += ".dev0" return rendered def render_git_describe(pieces): """TAG[-DISTANCE-gHEX][-dirty]. Like 'git describe --tags --dirty --always'. Exceptions: 1: no tags. HEX[-dirty] (note: no 'g' prefix) """ if pieces["closest-tag"]: rendered = pieces["closest-tag"] if pieces["distance"]: rendered += "-%%d-g%%s" %% (pieces["distance"], pieces["short"]) else: # exception #1 rendered = pieces["short"] if pieces["dirty"]: rendered += "-dirty" return rendered def render_git_describe_long(pieces): """TAG-DISTANCE-gHEX[-dirty]. Like 'git describe --tags --dirty --always -long'. The distance/hash is unconditional. Exceptions: 1: no tags. HEX[-dirty] (note: no 'g' prefix) """ if pieces["closest-tag"]: rendered = pieces["closest-tag"] rendered += "-%%d-g%%s" %% (pieces["distance"], pieces["short"]) else: # exception #1 rendered = pieces["short"] if pieces["dirty"]: rendered += "-dirty" return rendered def render(pieces, style): """Render the given version pieces into the requested style.""" if pieces["error"]: return {"version": "unknown", "full-revisionid": pieces.get("long"), "dirty": None, "error": pieces["error"], "date": None} if not style or style == "default": style = "pep440" # the default if style == "pep440": rendered = render_pep440(pieces) elif style == "pep440-pre": rendered = render_pep440_pre(pieces) elif style == "pep440-post": rendered = render_pep440_post(pieces) elif style == "pep440-old": rendered = render_pep440_old(pieces) elif style == "git-describe": rendered = render_git_describe(pieces) elif style == "git-describe-long": rendered = render_git_describe_long(pieces) else: raise ValueError("unknown style '%%s'" %% style) return {"version": rendered, "full-revisionid": pieces["long"], "dirty": pieces["dirty"], "error": None, "date": pieces.get("date")} def get_versions(): """Get version information or return default if unable to do so.""" # I am in _version.py, which lives at ROOT/VERSIONFILE_SOURCE. If we have # __file__, we can work backwards from there to the root. Some # py2exe/bbfreeze/non-CPython implementations don't do __file__, in which # case we can only use expanded keywords. cfg = get_config() verbose = cfg.verbose try: return git_versions_from_keywords(get_keywords(), cfg.tag_prefix, verbose) except NotThisMethod: pass try: root = os.path.realpath(__file__) # versionfile_source is the relative path from the top of the source # tree (where the .git directory might live) to this file. Invert # this to find the root from __file__. for i in cfg.versionfile_source.split('/'): root = os.path.dirname(root) except NameError: return {"version": "0+unknown", "full-revisionid": None, "dirty": None, "error": "unable to find root of source tree", "date": None} try: pieces = git_pieces_from_vcs(cfg.tag_prefix, root, verbose) return render(pieces, cfg.style) except NotThisMethod: pass try: if cfg.parentdir_prefix: return versions_from_parentdir(cfg.parentdir_prefix, root, verbose) except NotThisMethod: pass return {"version": "0+unknown", "full-revisionid": None, "dirty": None, "error": "unable to compute version", "date": None} ''' @register_vcs_handler("git", "get_keywords") def git_get_keywords(versionfile_abs): """Extract version information from the given file.""" # the code embedded in _version.py can just fetch the value of these # keywords. When used from setup.py, we don't want to import _version.py, # so we do it with a regexp instead. This function is not used from # _version.py. keywords = {} try: f = open(versionfile_abs, "r") for line in f.readlines(): if line.strip().startswith("git_refnames ="): mo = re.search(r'=\s*"(.*)"', line) if mo: keywords["refnames"] = mo.group(1) if line.strip().startswith("git_full ="): mo = re.search(r'=\s*"(.*)"', line) if mo: keywords["full"] = mo.group(1) if line.strip().startswith("git_date ="): mo = re.search(r'=\s*"(.*)"', line) if mo: keywords["date"] = mo.group(1) f.close() except EnvironmentError: pass return keywords @register_vcs_handler("git", "keywords") def git_versions_from_keywords(keywords, tag_prefix, verbose): """Get version information from git keywords.""" if not keywords: raise NotThisMethod("no keywords at all, weird") date = keywords.get("date") if date is not None: # git-2.2.0 added "%cI", which expands to an ISO-8601 -compliant # datestamp. However we prefer "%ci" (which expands to an "ISO-8601 # -like" string, which we must then edit to make compliant), because # it's been around since git-1.5.3, and it's too difficult to # discover which version we're using, or to work around using an # older one. date = date.strip().replace(" ", "T", 1).replace(" ", "", 1) refnames = keywords["refnames"].strip() if refnames.startswith("$Format"): if verbose: print("keywords are unexpanded, not using") raise NotThisMethod("unexpanded keywords, not a git-archive tarball") refs = set([r.strip() for r in refnames.strip("()").split(",")]) # starting in git-1.8.3, tags are listed as "tag: foo-1.0" instead of # just "foo-1.0". If we see a "tag: " prefix, prefer those. TAG = "tag: " tags = set([r[len(TAG):] for r in refs if r.startswith(TAG)]) if not tags: # Either we're using git < 1.8.3, or there really are no tags. We use # a heuristic: assume all version tags have a digit. The old git %d # expansion behaves like git log --decorate=short and strips out the # refs/heads/ and refs/tags/ prefixes that would let us distinguish # between branches and tags. By ignoring refnames without digits, we # filter out many common branch names like "release" and # "stabilization", as well as "HEAD" and "master". tags = set([r for r in refs if re.search(r'\d', r)]) if verbose: print("discarding '%s', no digits" % ",".join(refs - tags)) if verbose: print("likely tags: %s" % ",".join(sorted(tags))) for ref in sorted(tags): # sorting will prefer e.g. "2.0" over "2.0rc1" # PYNWB: Support tag_prefix specified as a glob pattern tag_is_glob_pattern = "*" in tag_prefix if tag_is_glob_pattern: if fnmatch.fnmatch(ref, tag_prefix): r = ref if verbose: print("picking %s" % r) return {"version": r, "full-revisionid": keywords["full"].strip(), "dirty": False, "error": None, "date": date} else: if ref.startswith(tag_prefix): r = ref[len(tag_prefix):] if verbose: print("picking %s" % r) return {"version": r, "full-revisionid": keywords["full"].strip(), "dirty": False, "error": None, "date": date} # no suitable tags, so version is "0+unknown", but full hex is still there if verbose: print("no suitable tags, using unknown + full revision id") return {"version": "0+unknown", "full-revisionid": keywords["full"].strip(), "dirty": False, "error": "no suitable tags", "date": None} @register_vcs_handler("git", "pieces_from_vcs") def git_pieces_from_vcs(tag_prefix, root, verbose, run_command=run_command): """Get version from 'git describe' in the root of the source tree. This only gets called if the git-archive 'subst' keywords were *not* expanded, and _version.py hasn't already been rewritten with a short version string, meaning we're inside a checked out source tree. """ GITS = ["git"] if sys.platform == "win32": GITS = ["git.cmd", "git.exe"] out, rc = run_command(GITS, ["rev-parse", "--git-dir"], cwd=root, hide_stderr=True) if rc != 0: if verbose: print("Directory %s not under git control" % root) raise NotThisMethod("'git rev-parse --git-dir' returned error") # PYNWB: Support tag_prefix specified as a glob pattern tag_is_glob_pattern = "*" in tag_prefix match_argument = tag_prefix if not tag_is_glob_pattern: match_argument = tag_prefix + "*" # if there is a tag matching tag_prefix, this yields TAG-NUM-gHEX[-dirty] # if there isn't one, this yields HEX[-dirty] (no NUM) describe_out, rc = run_command(GITS, ["describe", "--tags", "--dirty", "--always", "--long", "--match", "%s" % match_argument], cwd=root) # --long was added in git-1.5.5 if describe_out is None: raise NotThisMethod("'git describe' failed") describe_out = describe_out.strip() full_out, rc = run_command(GITS, ["rev-parse", "HEAD"], cwd=root) if full_out is None: raise NotThisMethod("'git rev-parse' failed") full_out = full_out.strip() pieces = {} pieces["long"] = full_out pieces["short"] = full_out[:7] # maybe improved later pieces["error"] = None # parse describe_out. It will be like TAG-NUM-gHEX[-dirty] or HEX[-dirty] # TAG might have hyphens. git_describe = describe_out # look for -dirty suffix dirty = git_describe.endswith("-dirty") pieces["dirty"] = dirty if dirty: git_describe = git_describe[:git_describe.rindex("-dirty")] # now we have TAG-NUM-gHEX or HEX if "-" in git_describe: # TAG-NUM-gHEX mo = re.search(r'^(.+)-(\d+)-g([0-9a-f]+)$', git_describe) if not mo: # unparseable. Maybe git-describe is misbehaving? pieces["error"] = ("unable to parse git-describe output: '%s'" % describe_out) return pieces # tag full_tag = mo.group(1) # PYNWB: Support tag_prefix specified as a glob pattern if tag_is_glob_pattern: if not fnmatch.fnmatch(full_tag, tag_prefix): if verbose: fmt = "tag '%s' doesn't match glob pattern '%s'" print(fmt % (full_tag, tag_prefix)) pieces["error"] = ("tag '%s' doesn't match glob pattern '%s'" % (full_tag, tag_prefix)) return pieces pieces["closest-tag"] = full_tag else: if not full_tag.startswith(tag_prefix): if verbose: fmt = "tag '%s' doesn't start with prefix '%s'" print(fmt % (full_tag, tag_prefix)) pieces["error"] = ("tag '%s' doesn't start with prefix '%s'" % (full_tag, tag_prefix)) return pieces pieces["closest-tag"] = full_tag[len(tag_prefix):] # distance: number of commits since tag pieces["distance"] = int(mo.group(2)) # commit: short hex revision ID pieces["short"] = mo.group(3) else: # HEX: no tags pieces["closest-tag"] = None count_out, rc = run_command(GITS, ["rev-list", "HEAD", "--count"], cwd=root) pieces["distance"] = int(count_out) # total number of commits # commit date: see ISO-8601 comment in git_versions_from_keywords() date = run_command(GITS, ["show", "-s", "--format=%ci", "HEAD"], cwd=root)[0].strip() pieces["date"] = date.strip().replace(" ", "T", 1).replace(" ", "", 1) return pieces def do_vcs_install(manifest_in, versionfile_source, ipy): """Git-specific installation logic for Versioneer. For Git, this means creating/changing .gitattributes to mark _version.py for export-subst keyword substitution. """ GITS = ["git"] if sys.platform == "win32": GITS = ["git.cmd", "git.exe"] files = [manifest_in, versionfile_source] if ipy: files.append(ipy) try: me = __file__ if me.endswith(".pyc") or me.endswith(".pyo"): me = os.path.splitext(me)[0] + ".py" versioneer_file = os.path.relpath(me) except NameError: versioneer_file = "versioneer.py" files.append(versioneer_file) present = False try: f = open(".gitattributes", "r") for line in f.readlines(): if line.strip().startswith(versionfile_source): if "export-subst" in line.strip().split()[1:]: present = True f.close() except EnvironmentError: pass if not present: f = open(".gitattributes", "a+") f.write("%s export-subst\n" % versionfile_source) f.close() files.append(".gitattributes") run_command(GITS, ["add", "--"] + files) def versions_from_parentdir(parentdir_prefix, root, verbose): """Try to determine the version from the parent directory name. Source tarballs conventionally unpack into a directory that includes both the project name and a version string. We will also support searching up two directory levels for an appropriately named parent directory """ rootdirs = [] for i in range(3): dirname = os.path.basename(root) if dirname.startswith(parentdir_prefix): return {"version": dirname[len(parentdir_prefix):], "full-revisionid": None, "dirty": False, "error": None, "date": None} else: rootdirs.append(root) root = os.path.dirname(root) # up a level if verbose: print("Tried directories %s but none started with prefix %s" % (str(rootdirs), parentdir_prefix)) raise NotThisMethod("rootdir doesn't start with parentdir_prefix") SHORT_VERSION_PY = """ # This file was generated by 'versioneer.py' (0.18) from # revision-control system data, or from the parent directory name of an # unpacked source archive. Distribution tarballs contain a pre-generated copy # of this file. import json version_json = ''' %s ''' # END VERSION_JSON def get_versions(): return json.loads(version_json) """ def versions_from_file(filename): """Try to determine the version from _version.py if present.""" try: with open(filename) as f: contents = f.read() except EnvironmentError: raise NotThisMethod("unable to read _version.py") mo = re.search(r"version_json = '''\n(.*)''' # END VERSION_JSON", contents, re.M | re.S) if not mo: mo = re.search(r"version_json = '''\r\n(.*)''' # END VERSION_JSON", contents, re.M | re.S) if not mo: raise NotThisMethod("no version_json in _version.py") return json.loads(mo.group(1)) def write_to_version_file(filename, versions): """Write the given version number to the given _version.py file.""" os.unlink(filename) contents = json.dumps(versions, sort_keys=True, indent=1, separators=(",", ": ")) with open(filename, "w") as f: f.write(SHORT_VERSION_PY % contents) print("set %s to '%s'" % (filename, versions["version"])) def plus_or_dot(pieces): """Return a + if we don't already have one, else return a .""" if "+" in pieces.get("closest-tag", ""): return "." return "+" def render_pep440(pieces): """Build up version string, with post-release "local version identifier". Our goal: TAG[+DISTANCE.gHEX[.dirty]] . Note that if you get a tagged build and then dirty it, you'll get TAG+0.gHEX.dirty Exceptions: 1: no tags. git_describe was just HEX. 0+untagged.DISTANCE.gHEX[.dirty] """ if pieces["closest-tag"]: rendered = pieces["closest-tag"] if pieces["distance"] or pieces["dirty"]: rendered += plus_or_dot(pieces) rendered += "%d.g%s" % (pieces["distance"], pieces["short"]) if pieces["dirty"]: rendered += ".dirty" else: # exception #1 rendered = "0+untagged.%d.g%s" % (pieces["distance"], pieces["short"]) if pieces["dirty"]: rendered += ".dirty" return rendered def render_pep440_pre(pieces): """TAG[.post.devDISTANCE] -- No -dirty. Exceptions: 1: no tags. 0.post.devDISTANCE """ if pieces["closest-tag"]: rendered = pieces["closest-tag"] if pieces["distance"]: rendered += ".post.dev%d" % pieces["distance"] else: # exception #1 rendered = "0.post.dev%d" % pieces["distance"] return rendered def render_pep440_post(pieces): """TAG[.postDISTANCE[.dev0]+gHEX] . The ".dev0" means dirty. Note that .dev0 sorts backwards (a dirty tree will appear "older" than the corresponding clean one), but you shouldn't be releasing software with -dirty anyways. Exceptions: 1: no tags. 0.postDISTANCE[.dev0] """ if pieces["closest-tag"]: rendered = pieces["closest-tag"] if pieces["distance"] or pieces["dirty"]: rendered += ".post%d" % pieces["distance"] if pieces["dirty"]: rendered += ".dev0" rendered += plus_or_dot(pieces) rendered += "g%s" % pieces["short"] else: # exception #1 rendered = "0.post%d" % pieces["distance"] if pieces["dirty"]: rendered += ".dev0" rendered += "+g%s" % pieces["short"] return rendered def render_pep440_old(pieces): """TAG[.postDISTANCE[.dev0]] . The ".dev0" means dirty. Eexceptions: 1: no tags. 0.postDISTANCE[.dev0] """ if pieces["closest-tag"]: rendered = pieces["closest-tag"] if pieces["distance"] or pieces["dirty"]: rendered += ".post%d" % pieces["distance"] if pieces["dirty"]: rendered += ".dev0" else: # exception #1 rendered = "0.post%d" % pieces["distance"] if pieces["dirty"]: rendered += ".dev0" return rendered def render_git_describe(pieces): """TAG[-DISTANCE-gHEX][-dirty]. Like 'git describe --tags --dirty --always'. Exceptions: 1: no tags. HEX[-dirty] (note: no 'g' prefix) """ if pieces["closest-tag"]: rendered = pieces["closest-tag"] if pieces["distance"]: rendered += "-%d-g%s" % (pieces["distance"], pieces["short"]) else: # exception #1 rendered = pieces["short"] if pieces["dirty"]: rendered += "-dirty" return rendered def render_git_describe_long(pieces): """TAG-DISTANCE-gHEX[-dirty]. Like 'git describe --tags --dirty --always -long'. The distance/hash is unconditional. Exceptions: 1: no tags. HEX[-dirty] (note: no 'g' prefix) """ if pieces["closest-tag"]: rendered = pieces["closest-tag"] rendered += "-%d-g%s" % (pieces["distance"], pieces["short"]) else: # exception #1 rendered = pieces["short"] if pieces["dirty"]: rendered += "-dirty" return rendered def render(pieces, style): """Render the given version pieces into the requested style.""" if pieces["error"]: return {"version": "unknown", "full-revisionid": pieces.get("long"), "dirty": None, "error": pieces["error"], "date": None} if not style or style == "default": style = "pep440" # the default if style == "pep440": rendered = render_pep440(pieces) elif style == "pep440-pre": rendered = render_pep440_pre(pieces) elif style == "pep440-post": rendered = render_pep440_post(pieces) elif style == "pep440-old": rendered = render_pep440_old(pieces) elif style == "git-describe": rendered = render_git_describe(pieces) elif style == "git-describe-long": rendered = render_git_describe_long(pieces) else: raise ValueError("unknown style '%s'" % style) return {"version": rendered, "full-revisionid": pieces["long"], "dirty": pieces["dirty"], "error": None, "date": pieces.get("date")} class VersioneerBadRootError(Exception): """The project root directory is unknown or missing key files.""" def get_versions(verbose=False): """Get the project version from whatever source is available. Returns dict with two keys: 'version' and 'full'. """ if "versioneer" in sys.modules: # see the discussion in cmdclass.py:get_cmdclass() del sys.modules["versioneer"] root = get_root() cfg = get_config_from_root(root) assert cfg.VCS is not None, "please set [versioneer]VCS= in setup.cfg" handlers = HANDLERS.get(cfg.VCS) assert handlers, "unrecognized VCS '%s'" % cfg.VCS verbose = verbose or cfg.verbose assert cfg.versionfile_source is not None, \ "please set versioneer.versionfile_source" assert cfg.tag_prefix is not None, "please set versioneer.tag_prefix" versionfile_abs = os.path.join(root, cfg.versionfile_source) # extract version from first of: _version.py, VCS command (e.g. 'git # describe'), parentdir. This is meant to work for developers using a # source checkout, for users of a tarball created by 'setup.py sdist', # and for users of a tarball/zipball created by 'git archive' or github's # download-from-tag feature or the equivalent in other VCSes. get_keywords_f = handlers.get("get_keywords") from_keywords_f = handlers.get("keywords") if get_keywords_f and from_keywords_f: try: keywords = get_keywords_f(versionfile_abs) ver = from_keywords_f(keywords, cfg.tag_prefix, verbose) if verbose: print("got version from expanded keyword %s" % ver) return ver except NotThisMethod: pass try: ver = versions_from_file(versionfile_abs) if verbose: print("got version from file %s %s" % (versionfile_abs, ver)) return ver except NotThisMethod: pass from_vcs_f = handlers.get("pieces_from_vcs") if from_vcs_f: try: pieces = from_vcs_f(cfg.tag_prefix, root, verbose) ver = render(pieces, cfg.style) if verbose: print("got version from VCS %s" % ver) return ver except NotThisMethod: pass try: if cfg.parentdir_prefix: ver = versions_from_parentdir(cfg.parentdir_prefix, root, verbose) if verbose: print("got version from parentdir %s" % ver) return ver except NotThisMethod: pass if verbose: print("unable to compute version") return {"version": "0+unknown", "full-revisionid": None, "dirty": None, "error": "unable to compute version", "date": None} def get_version(): """Get the short version string for this project.""" return get_versions()["version"] def get_cmdclass(): """Get the custom setuptools/distutils subclasses used by Versioneer.""" if "versioneer" in sys.modules: del sys.modules["versioneer"] # this fixes the "python setup.py develop" case (also 'install' and # 'easy_install .'), in which subdependencies of the main project are # built (using setup.py bdist_egg) in the same python process. Assume # a main project A and a dependency B, which use different versions # of Versioneer. A's setup.py imports A's Versioneer, leaving it in # sys.modules by the time B's setup.py is executed, causing B to run # with the wrong versioneer. Setuptools wraps the sub-dep builds in a # sandbox that restores sys.modules to it's pre-build state, so the # parent is protected against the child's "import versioneer". By # removing ourselves from sys.modules here, before the child build # happens, we protect the child from the parent's versioneer too. # Also see https://github.com/warner/python-versioneer/issues/52 cmds = {} # we add "version" to both distutils and setuptools from distutils.core import Command class cmd_version(Command): description = "report generated version string" user_options = [] boolean_options = [] def initialize_options(self): pass def finalize_options(self): pass def run(self): vers = get_versions(verbose=True) print("Version: %s" % vers["version"]) print(" full-revisionid: %s" % vers.get("full-revisionid")) print(" dirty: %s" % vers.get("dirty")) print(" date: %s" % vers.get("date")) if vers["error"]: print(" error: %s" % vers["error"]) cmds["version"] = cmd_version # we override "build_py" in both distutils and setuptools # # most invocation pathways end up running build_py: # distutils/build -> build_py # distutils/install -> distutils/build ->.. # setuptools/bdist_wheel -> distutils/install ->.. # setuptools/bdist_egg -> distutils/install_lib -> build_py # setuptools/install -> bdist_egg ->.. # setuptools/develop -> ? # pip install: # copies source tree to a tempdir before running egg_info/etc # if .git isn't copied too, 'git describe' will fail # then does setup.py bdist_wheel, or sometimes setup.py install # setup.py egg_info -> ? # we override different "build_py" commands for both environments if "setuptools" in sys.modules: from setuptools.command.build_py import build_py as _build_py else: from distutils.command.build_py import build_py as _build_py class cmd_build_py(_build_py): def run(self): root = get_root() cfg = get_config_from_root(root) versions = get_versions() _build_py.run(self) # now locate _version.py in the new build/ directory and replace # it with an updated value if cfg.versionfile_build: target_versionfile = os.path.join(self.build_lib, cfg.versionfile_build) print("UPDATING %s" % target_versionfile) write_to_version_file(target_versionfile, versions) cmds["build_py"] = cmd_build_py if "cx_Freeze" in sys.modules: # cx_freeze enabled? from cx_Freeze.dist import build_exe as _build_exe # nczeczulin reports that py2exe won't like the pep440-style string # as FILEVERSION, but it can be used for PRODUCTVERSION, e.g. # setup(console=[{ # "version": versioneer.get_version().split("+", 1)[0], # FILEVERSION # "product_version": versioneer.get_version(), # ... class cmd_build_exe(_build_exe): def run(self): root = get_root() cfg = get_config_from_root(root) versions = get_versions() target_versionfile = cfg.versionfile_source print("UPDATING %s" % target_versionfile) write_to_version_file(target_versionfile, versions) _build_exe.run(self) os.unlink(target_versionfile) with open(cfg.versionfile_source, "w") as f: LONG = LONG_VERSION_PY[cfg.VCS] f.write(LONG % {"DOLLAR": "$", "STYLE": cfg.style, "TAG_PREFIX": cfg.tag_prefix, "PARENTDIR_PREFIX": cfg.parentdir_prefix, "VERSIONFILE_SOURCE": cfg.versionfile_source, }) cmds["build_exe"] = cmd_build_exe del cmds["build_py"] if 'py2exe' in sys.modules: # py2exe enabled? try: from py2exe.distutils_buildexe import py2exe as _py2exe # py3 except ImportError: from py2exe.build_exe import py2exe as _py2exe # py2 class cmd_py2exe(_py2exe): def run(self): root = get_root() cfg = get_config_from_root(root) versions = get_versions() target_versionfile = cfg.versionfile_source print("UPDATING %s" % target_versionfile) write_to_version_file(target_versionfile, versions) _py2exe.run(self) os.unlink(target_versionfile) with open(cfg.versionfile_source, "w") as f: LONG = LONG_VERSION_PY[cfg.VCS] f.write(LONG % {"DOLLAR": "$", "STYLE": cfg.style, "TAG_PREFIX": cfg.tag_prefix, "PARENTDIR_PREFIX": cfg.parentdir_prefix, "VERSIONFILE_SOURCE": cfg.versionfile_source, }) cmds["py2exe"] = cmd_py2exe # we override different "sdist" commands for both environments if "setuptools" in sys.modules: from setuptools.command.sdist import sdist as _sdist else: from distutils.command.sdist import sdist as _sdist class cmd_sdist(_sdist): def run(self): versions = get_versions() self._versioneer_generated_versions = versions # unless we update this, the command will keep using the old # version self.distribution.metadata.version = versions["version"] return _sdist.run(self) def make_release_tree(self, base_dir, files): root = get_root() cfg = get_config_from_root(root) _sdist.make_release_tree(self, base_dir, files) # now locate _version.py in the new base_dir directory # (remembering that it may be a hardlink) and replace it with an # updated value target_versionfile = os.path.join(base_dir, cfg.versionfile_source) print("UPDATING %s" % target_versionfile) write_to_version_file(target_versionfile, self._versioneer_generated_versions) cmds["sdist"] = cmd_sdist return cmds CONFIG_ERROR = """ setup.cfg is missing the necessary Versioneer configuration. You need a section like: [versioneer] VCS = git style = pep440 versionfile_source = src/myproject/_version.py versionfile_build = myproject/_version.py tag_prefix = parentdir_prefix = myproject- You will also need to edit your setup.py to use the results: import versioneer setup(version=versioneer.get_version(), cmdclass=versioneer.get_cmdclass(), ...) Please read the docstring in ./versioneer.py for configuration instructions, edit setup.cfg, and re-run the installer or 'python versioneer.py setup'. """ SAMPLE_CONFIG = """ # See the docstring in versioneer.py for instructions. Note that you must # re-run 'versioneer.py setup' after changing this section, and commit the # resulting files. [versioneer] #VCS = git #style = pep440 #versionfile_source = #versionfile_build = #tag_prefix = #parentdir_prefix = """ INIT_PY_SNIPPET = """ from ._version import get_versions __version__ = get_versions()['version'] del get_versions """ def do_setup(): """Main VCS-independent setup function for installing Versioneer.""" root = get_root() try: cfg = get_config_from_root(root) except (EnvironmentError, configparser.NoSectionError, configparser.NoOptionError) as e: if isinstance(e, (EnvironmentError, configparser.NoSectionError)): print("Adding sample versioneer config to setup.cfg", file=sys.stderr) with open(os.path.join(root, "setup.cfg"), "a") as f: f.write(SAMPLE_CONFIG) print(CONFIG_ERROR, file=sys.stderr) return 1 print(" creating %s" % cfg.versionfile_source) with open(cfg.versionfile_source, "w") as f: LONG = LONG_VERSION_PY[cfg.VCS] f.write(LONG % {"DOLLAR": "$", "STYLE": cfg.style, "TAG_PREFIX": cfg.tag_prefix, "PARENTDIR_PREFIX": cfg.parentdir_prefix, "VERSIONFILE_SOURCE": cfg.versionfile_source, }) ipy = os.path.join(os.path.dirname(cfg.versionfile_source), "__init__.py") if os.path.exists(ipy): try: with open(ipy, "r") as f: old = f.read() except EnvironmentError: old = "" if INIT_PY_SNIPPET not in old: print(" appending to %s" % ipy) with open(ipy, "a") as f: f.write(INIT_PY_SNIPPET) else: print(" %s unmodified" % ipy) else: print(" %s doesn't exist, ok" % ipy) ipy = None # Make sure both the top-level "versioneer.py" and versionfile_source # (PKG/_version.py, used by runtime code) are in MANIFEST.in, so # they'll be copied into source distributions. Pip won't be able to # install the package without this. manifest_in = os.path.join(root, "MANIFEST.in") simple_includes = set() try: with open(manifest_in, "r") as f: for line in f: if line.startswith("include "): for include in line.split()[1:]: simple_includes.add(include) except EnvironmentError: pass # That doesn't cover everything MANIFEST.in can do # (http://docs.python.org/2/distutils/sourcedist.html#commands), so # it might give some false negatives. Appending redundant 'include' # lines is safe, though. if "versioneer.py" not in simple_includes: print(" appending 'versioneer.py' to MANIFEST.in") with open(manifest_in, "a") as f: f.write("include versioneer.py\n") else: print(" 'versioneer.py' already in MANIFEST.in") if cfg.versionfile_source not in simple_includes: print(" appending versionfile_source ('%s') to MANIFEST.in" % cfg.versionfile_source) with open(manifest_in, "a") as f: f.write("include %s\n" % cfg.versionfile_source) else: print(" versionfile_source already in MANIFEST.in") # Make VCS-specific changes. For git, this means creating/changing # .gitattributes to mark _version.py for export-subst keyword # substitution. do_vcs_install(manifest_in, cfg.versionfile_source, ipy) return 0 def scan_setup_py(): """Validate the contents of setup.py against Versioneer's expectations.""" found = set() setters = False errors = 0 with open("setup.py", "r") as f: for line in f.readlines(): if "import versioneer" in line: found.add("import") if "versioneer.get_cmdclass()" in line: found.add("cmdclass") if "versioneer.get_version()" in line: found.add("get_version") if "versioneer.VCS" in line: setters = True if "versioneer.versionfile_source" in line: setters = True if len(found) != 3: print("") print("Your setup.py appears to be missing some important items") print("(but I might be wrong). Please make sure it has something") print("roughly like the following:") print("") print(" import versioneer") print(" setup( version=versioneer.get_version(),") print(" cmdclass=versioneer.get_cmdclass(), ...)") print("") errors += 1 if setters: print("You should remove lines like 'versioneer.VCS = ' and") print("'versioneer.versionfile_source = ' . This configuration") print("now lives in setup.cfg, and should be removed from setup.py") print("") errors += 1 return errors if __name__ == "__main__": cmd = sys.argv[1] if cmd == "setup": errors = do_setup() errors += scan_setup_py() if errors: sys.exit(1) pynwb-1.2.1/setup.cfg0000644000655200065520000000117613612200376016066 0ustar circlecicircleci00000000000000[bdist_wheel] universal = 1 [versioneer] vcs = git versionfile_source = src/pynwb/_version.py versionfile_build = pynwb/_version.py style = pep440-pre tag_prefix = *.*.* [flake8] max-line-length = 120 max-complexity = 17 exclude = .git, .tox, __pycache__, docs/_build/, dist/, src/pynwb/nwb-schema/ docs/source/conf.py versioneer.py per-file-ignores = docs/gallery/*:E402, docs/source/tutorials/*:E402 src/pynwb/io/__init__.py:F401 src/pynwb/legacy/io/__init__.py:F401 tests/integration/__init__.py:F401 src/pynwb/testing/__init__.py:F401 [metadata] description-file = README.rst [egg_info] tag_build = tag_date = 0 pynwb-1.2.1/setup.py0000755000655200065520000000427113612200244015753 0ustar circlecicircleci00000000000000# -*- coding: utf-8 -*- from setuptools import setup, find_packages import versioneer with open('README.rst', 'r') as fp: readme = fp.read() pkgs = find_packages('src', exclude=['data']) print('found these packages:', pkgs) schema_dir = 'nwb-schema/core' with open('requirements-min.txt', 'r') as fp: # replace == with >= and remove trailing comments and spaces reqs = [x.replace('==', '>=').split('#')[0].strip() for x in fp] reqs = [x for x in reqs if x] # remove empty strings print(reqs) setup_args = { 'name': 'pynwb', 'version': versioneer.get_version(), 'cmdclass': versioneer.get_cmdclass(), 'description': 'Package for working with Neurodata stored in the NWB format', 'long_description': readme, 'long_description_content_type': 'text/x-rst; charset=UTF-8', 'author': 'Andrew Tritt', 'author_email': 'ajtritt@lbl.gov', 'url': 'https://github.com/NeurodataWithoutBorders/pynwb', 'license': "BSD", 'install_requires': reqs, 'packages': pkgs, 'package_dir': {'': 'src'}, 'package_data': {'pynwb': ["%s/*.yaml" % schema_dir, "%s/*.json" % schema_dir]}, 'classifiers': [ "Programming Language :: Python", "Programming Language :: Python :: 3.5", "Programming Language :: Python :: 3.6", "Programming Language :: Python :: 3.7", "License :: OSI Approved :: BSD License", "Development Status :: 2 - Pre-Alpha", "Intended Audience :: Developers", "Intended Audience :: Science/Research", "Operating System :: Microsoft :: Windows", "Operating System :: MacOS", "Operating System :: Unix", "Topic :: Scientific/Engineering :: Medical Science Apps." ], 'keywords': 'Neuroscience ' 'python ' 'HDF ' 'HDF5 ' 'cross-platform ' 'open-data ' 'data-format ' 'open-source ' 'open-science ' 'reproducible-research ' 'PyNWB ' 'NWB ' 'NWB:N ' 'NeurodataWithoutBorders', 'zip_safe': False } if __name__ == '__main__': setup(**setup_args) pynwb-1.2.1/README.rst0000644000655200065520000001513413612200244015725 0ustar circlecicircleci00000000000000===== PyNWB ===== Documentation of PyNWB can be found at https://pynwb.readthedocs.io Latest Release ============== .. image:: https://badge.fury.io/py/pynwb.svg :target: https://badge.fury.io/py/pynwb .. image:: https://anaconda.org/conda-forge/pynwb/badges/version.svg :target: https://anaconda.org/conda-forge/pynwb Build Status ============ .. table:: +-----------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------+ | Linux | Windows and MacOS | +=========================================================================================+=================================================================================================================================+ | .. image:: https://circleci.com/gh/NeurodataWithoutBorders/pynwb.svg?style=shield | .. image:: https://dev.azure.com/NeurodataWithoutBorders/pynwb/_apis/build/status/NeurodataWithoutBorders.pynwb?branchName=dev | | :target: https://circleci.com/gh/NeurodataWithoutBorders/pynwb | :target: https://dev.azure.com/NeurodataWithoutBorders/pynwb/_build/latest?definitionId=3&branchName=dev | +-----------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------+ **Conda** .. image:: https://circleci.com/gh/conda-forge/pynwb-feedstock.svg?style=shield :target: https://circleci.com/gh/conda-forge/pynwb-feedstocks Overall Health ============== .. image:: https://codecov.io/gh/NeurodataWithoutBorders/pynwb/branch/dev/graph/badge.svg :target: https://codecov.io/gh/NeurodataWithoutBorders/pynwb .. image:: https://requires.io/github/NeurodataWithoutBorders/pynwb/requirements.svg?branch=dev :target: https://requires.io/github/NeurodataWithoutBorders/pynwb/requirements/?branch=dev :alt: Requirements Status NWB Format API ============== PyNWB is a Python package for working with NWB files. It provides a high-level API for efficiently working with Neurodata stored in the `NWB format `_. `Neurodata Without Borders: Neurophysiology (NWB:N) `_ is a project to develop a unified data format for cellular-based neurophysiology data, focused on the dynamics of groups of neurons measured under a large range of experimental conditions. The NWB:N team consists of neuroscientists and software developers who recognize that adoption of a unified data format is an important step toward breaking down the barriers to data sharing in neuroscience. Installation ============ See the PyNWB documentation for details http://pynwb.readthedocs.io/en/latest/getting_started.html#installation Code of Conduct =============== This project and everyone participating in it is governed by our `code of conduct guidelines <.github/CODE_OF_CONDUCT.rst>`_. By participating, you are expected to uphold this code. Contributing ============ For details on how to contribute to PyNWB see our `contribution guidelines `_. LICENSE ======= "pynwb" Copyright (c) 2017-2019, The Regents of the University of California, through Lawrence Berkeley National Laboratory (subject to receipt of any required approvals from the U.S. Dept. of Energy). All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: (1) Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. (2) Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. (3) Neither the name of the University of California, Lawrence Berkeley National Laboratory, U.S. Dept. of Energy nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. You are under no obligation whatsoever to provide any bug fixes, patches, or upgrades to the features, functionality or performance of the source code ("Enhancements") to anyone; however, if you choose to make your Enhancements available either publicly, or directly to Lawrence Berkeley National Laboratory, without imposing a separate written license agreement for such Enhancements, then you hereby grant the following license: a non-exclusive, royalty-free perpetual license to install, use, modify, prepare derivative works, incorporate into other computer software, distribute, and sublicense such enhancements or derivative works thereof, in binary and source code form. COPYRIGHT ========= "pynwb" Copyright (c) 2017-2019, The Regents of the University of California, through Lawrence Berkeley National Laboratory (subject to receipt of any required approvals from the U.S. Dept. of Energy). All rights reserved. If you have questions about your rights to use or distribute this software, please contact Berkeley Lab's Innovation & Partnerships Office at IPO@lbl.gov. NOTICE. This Software was developed under funding from the U.S. Department of Energy and the U.S. Government consequently retains certain rights. As such, the U.S. Government has been granted for itself and others acting on its behalf a paid-up, nonexclusive, irrevocable, worldwide license in the Software to reproduce, distribute copies to the public, prepare derivative works, and perform publicly and display publicly, and to permit other to do so. pynwb-1.2.1/requirements-dev.txt0000644000655200065520000000007213612200244020271 0ustar circlecicircleci00000000000000codecov==2.0.15 coverage==5.0.3 flake8==3.7.9 tox==3.14.3 pynwb-1.2.1/MANIFEST.in0000644000655200065520000000027713612200244015776 0ustar circlecicircleci00000000000000include license.txt Legal.txt versioneer.py src/pynwb/_version.py include requirements.txt requirements-dev.txt requirements-doc.txt requirements-min.txt include test.py tox.ini graft tests pynwb-1.2.1/src/0000755000655200065520000000000013612200376015027 5ustar circlecicircleci00000000000000pynwb-1.2.1/src/pynwb/0000755000655200065520000000000013612200376016166 5ustar circlecicircleci00000000000000pynwb-1.2.1/src/pynwb/image.py0000644000655200065520000002245613612200244017625 0ustar circlecicircleci00000000000000import warnings from collections.abc import Iterable from hdmf.utils import docval, popargs, call_docval_func, get_docval from . import register_class, CORE_NAMESPACE from .base import TimeSeries, Image @register_class('ImageSeries', CORE_NAMESPACE) class ImageSeries(TimeSeries): ''' General image data that is common between acquisition and stimulus time series. The image data can be stored in the HDF5 file or it will be stored as an external image file. ''' __nwbfields__ = ('dimension', 'external_file', 'starting_frame', 'format') @docval(*get_docval(TimeSeries.__init__, 'name'), # required {'name': 'data', 'type': ('array_data', 'data', TimeSeries), 'shape': ([None] * 3, [None] * 4), 'doc': 'The data this TimeSeries dataset stores. Can also store binary data e.g. image frames', 'default': None}, *get_docval(TimeSeries.__init__, 'unit'), {'name': 'format', 'type': str, 'doc': 'Format of image. Three types: 1) Image format; tiff, png, jpg, etc. 2) external 3) raw.', 'default': None}, {'name': 'external_file', 'type': ('array_data', 'data'), 'doc': 'Path or URL to one or more external file(s). Field only present if format=external. ' 'Either external_file or data must be specified, but not both.', 'default': None}, {'name': 'starting_frame', 'type': Iterable, 'doc': 'Each entry is the frame number in the corresponding external_file variable. ' 'This serves as an index to what frames each file contains.', 'default': None}, {'name': 'bits_per_pixel', 'type': int, 'doc': 'DEPRECATED: Number of bits per image pixel', 'default': None}, {'name': 'dimension', 'type': Iterable, 'doc': 'Number of pixels on x, y, (and z) axes.', 'default': None}, *get_docval(TimeSeries.__init__, 'resolution', 'conversion', 'timestamps', 'starting_time', 'rate', 'comments', 'description', 'control', 'control_description')) def __init__(self, **kwargs): bits_per_pixel, dimension, external_file, starting_frame, format = popargs( 'bits_per_pixel', 'dimension', 'external_file', 'starting_frame', 'format', kwargs) call_docval_func(super(ImageSeries, self).__init__, kwargs) if external_file is None and self.data is None: raise ValueError('must supply either external_file or data to ' + self.name) self.bits_per_pixel = bits_per_pixel self.dimension = dimension self.external_file = external_file self.starting_frame = starting_frame self.format = format @property def bits_per_pixel(self): return self.fields.get('bits_per_pixel') @bits_per_pixel.setter def bits_per_pixel(self, val): if val is not None: warnings.warn("bits_per_pixel is no longer used", DeprecationWarning) self.fields['bits_per_pixel'] = val @register_class('IndexSeries', CORE_NAMESPACE) class IndexSeries(TimeSeries): ''' Stores indices to image frames stored in an ImageSeries. The purpose of the ImageIndexSeries 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 ImageSeries, and the timestamps array indicates when that image was displayed. ''' __nwbfields__ = ('indexed_timeseries',) @docval(*get_docval(TimeSeries.__init__, 'name'), # required {'name': 'data', 'type': ('array_data', 'data', TimeSeries), 'shape': (None, ), # required 'doc': 'The data this TimeSeries dataset stores. Can also store binary data e.g. image frames'}, *get_docval(TimeSeries.__init__, 'unit'), {'name': 'indexed_timeseries', 'type': TimeSeries, # required 'doc': 'HDF5 link to TimeSeries containing images that are indexed.'}, *get_docval(TimeSeries.__init__, 'resolution', 'conversion', 'timestamps', 'starting_time', 'rate', 'comments', 'description', 'control', 'control_description')) def __init__(self, **kwargs): name, data = popargs('name', 'data', kwargs) indexed_timeseries = popargs('indexed_timeseries', kwargs) super(IndexSeries, self).__init__(name, data, **kwargs) self.indexed_timeseries = indexed_timeseries @register_class('ImageMaskSeries', CORE_NAMESPACE) class ImageMaskSeries(ImageSeries): ''' An alpha mask that is applied to a presented visual stimulus. The data[] array contains an array of mask values that are applied to the displayed image. Mask values are stored as RGBA. Mask can vary with time. The timestamps array indicates the starting time of a mask, and that mask pattern continues until it's explicitly changed. ''' __nwbfields__ = ('masked_imageseries',) @docval(*get_docval(ImageSeries.__init__, 'name'), # required {'name': 'data', 'type': ('array_data', 'data', TimeSeries), # required 'doc': 'The data this TimeSeries dataset stores. Can also store binary data e.g. image frames'}, *get_docval(ImageSeries.__init__, 'unit'), {'name': 'masked_imageseries', 'type': ImageSeries, # required 'doc': 'Link to ImageSeries that mask is applied to.'}, *get_docval(ImageSeries.__init__, 'format', 'external_file', 'starting_frame', 'bits_per_pixel', 'dimension', 'resolution', 'conversion', 'timestamps', 'starting_time', 'rate', 'comments', 'description', 'control', 'control_description')) def __init__(self, **kwargs): name, data = popargs('name', 'data', kwargs) masked_imageseries = popargs('masked_imageseries', kwargs) super(ImageMaskSeries, self).__init__(name, data, **kwargs) self.masked_imageseries = masked_imageseries @register_class('OpticalSeries', CORE_NAMESPACE) class OpticalSeries(ImageSeries): ''' Image data that is presented or recorded. A stimulus template movie will be stored only as an image. When the image is presented as stimulus, additional data is required, such as field of view (eg, how much of the visual field the image covers, or how what is the area of the target being imaged). If the OpticalSeries represents acquired imaging data, orientation is also important. ''' __nwbfields__ = ('distance', 'field_of_view', 'orientation') @docval(*get_docval(ImageSeries.__init__, 'name', 'data'), # required *get_docval(ImageSeries.__init__, 'unit', 'format'), {'name': 'distance', 'type': 'float', 'doc': 'Distance from camera/monitor to target/eye.'}, # required {'name': 'field_of_view', 'type': ('array_data', 'data', 'TimeSeries'), 'shape': ((2, ), (3, )), # required 'doc': 'Width, height and depth of image, or imaged area (meters).'}, {'name': 'orientation', 'type': str, # required 'doc': 'Description of image relative to some reference frame (e.g., which way is up). ' 'Must also specify frame of reference.'}, *get_docval(ImageSeries.__init__, 'external_file', 'starting_frame', 'bits_per_pixel', 'dimension', 'resolution', 'conversion', 'timestamps', 'starting_time', 'rate', 'comments', 'description', 'control', 'control_description')) def __init__(self, **kwargs): name, data, = popargs('name', 'data', kwargs) distance, field_of_view, orientation = popargs('distance', 'field_of_view', 'orientation', kwargs) super(OpticalSeries, self).__init__(name, data, **kwargs) self.distance = distance self.field_of_view = field_of_view self.orientation = orientation @register_class('GrayscaleImage', CORE_NAMESPACE) class GrayscaleImage(Image): @docval(*get_docval(Image.__init__, 'name'), # required {'name': 'data', 'type': ('array_data', 'data'), 'doc': 'data of image', # required 'shape': (None, None)}, *get_docval(Image.__init__, 'resolution', 'description')) def __init__(self, **kwargs): call_docval_func(super(GrayscaleImage, self).__init__, kwargs) @register_class('RGBImage', CORE_NAMESPACE) class RGBImage(Image): @docval(*get_docval(Image.__init__, 'name'), {'name': 'data', 'type': ('array_data', 'data'), 'doc': 'data of image', # required 'shape': (None, None, 3)}, *get_docval(Image.__init__, 'resolution', 'description')) def __init__(self, **kwargs): call_docval_func(super(RGBImage, self).__init__, kwargs) @register_class('RGBAImage', CORE_NAMESPACE) class RGBAImage(Image): @docval(*get_docval(Image.__init__, 'name'), {'name': 'data', 'type': ('array_data', 'data'), 'doc': 'data of image', # required 'shape': (None, None, 4)}, *get_docval(Image.__init__, 'resolution', 'description')) def __init__(self, **kwargs): call_docval_func(super(RGBAImage, self).__init__, kwargs) pynwb-1.2.1/src/pynwb/device.py0000644000655200065520000000146413612200244017776 0ustar circlecicircleci00000000000000from hdmf.utils import docval, call_docval_func from . import register_class, CORE_NAMESPACE from .core import NWBContainer @register_class('Device', CORE_NAMESPACE) class Device(NWBContainer): """ """ __nwbfields__ = ('name', 'description', 'manufacturer') @docval({'name': 'name', 'type': str, 'doc': 'the name of this device'}, {'name': 'description', 'type': str, 'doc': 'Description of the device (e.g., model, firmware version, processing software version, etc.)', 'default': None}, {'name': 'manufacturer', 'type': str, 'doc': 'the name of the manufacturer of this device', 'default': None}) def __init__(self, **kwargs): call_docval_func(super(Device, self).__init__, kwargs) pynwb-1.2.1/src/pynwb/file.py0000644000655200065520000007724613612200244017471 0ustar circlecicircleci00000000000000from datetime import datetime from dateutil.tz import tzlocal from collections.abc import Iterable from warnings import warn import copy as _copy import numpy as np import pandas as pd from hdmf.utils import docval, getargs, call_docval_func, get_docval from . import register_class, CORE_NAMESPACE from .base import TimeSeries, ProcessingModule from .device import Device from .epoch import TimeIntervals from .ecephys import ElectrodeGroup from .icephys import IntracellularElectrode, SweepTable, PatchClampSeries from .ophys import ImagingPlane from .ogen import OptogeneticStimulusSite from .misc import Units from .core import NWBContainer, NWBDataInterface, MultiContainerInterface, \ ScratchData, LabelledDict from hdmf.common import DynamicTableRegion, DynamicTable def _not_parent(arg): return arg['name'] != 'parent' @register_class('LabMetaData', CORE_NAMESPACE) class LabMetaData(NWBContainer): @docval({'name': 'name', 'type': str, 'doc': 'name of metadata'}) def __init__(self, **kwargs): super(LabMetaData, self).__init__(kwargs['name']) @register_class('Subject', CORE_NAMESPACE) class Subject(NWBContainer): __nwbfields__ = ( 'age', 'description', 'genotype', 'sex', 'species', 'subject_id', 'weight', 'date_of_birth' ) @docval({'name': 'age', 'type': str, 'doc': 'the age of the subject', 'default': None}, {'name': 'description', 'type': str, 'doc': 'a description of the subject', 'default': None}, {'name': 'genotype', 'type': str, 'doc': 'the genotype of the subject', 'default': None}, {'name': 'sex', 'type': str, 'doc': 'the sex of the subject', 'default': None}, {'name': 'species', 'type': str, 'doc': 'the species of the subject', 'default': None}, {'name': 'subject_id', 'type': str, 'doc': 'a unique identifier for the subject', 'default': None}, {'name': 'weight', 'type': str, 'doc': 'the weight of the subject', 'default': None}, {'name': 'date_of_birth', 'type': datetime, 'default': None, 'doc': 'datetime of date of birth. May be supplied instead of age.'}) def __init__(self, **kwargs): kwargs['name'] = 'subject' call_docval_func(super(Subject, self).__init__, kwargs) self.age = getargs('age', kwargs) self.description = getargs('description', kwargs) self.genotype = getargs('genotype', kwargs) self.sex = getargs('sex', kwargs) self.species = getargs('species', kwargs) self.subject_id = getargs('subject_id', kwargs) self.weight = getargs('weight', kwargs) date_of_birth = getargs('date_of_birth', kwargs) if date_of_birth and date_of_birth.tzinfo is None: self.date_of_birth = _add_missing_timezone(date_of_birth) else: self.date_of_birth = date_of_birth @register_class('NWBFile', CORE_NAMESPACE) class NWBFile(MultiContainerInterface): """ A representation of an NWB file. """ __clsconf__ = [ { 'attr': 'acquisition', 'add': '_add_acquisition_internal', 'type': (NWBDataInterface, DynamicTable), 'get': 'get_acquisition' }, { 'attr': 'analysis', 'add': 'add_analysis', 'type': (NWBContainer, DynamicTable), 'get': 'get_analysis' }, { 'attr': 'scratch', 'add': '_add_scratch', 'type': (DynamicTable, NWBContainer, ScratchData), 'get': '_get_scratch' }, { 'attr': 'stimulus', 'add': '_add_stimulus_internal', 'type': TimeSeries, 'get': 'get_stimulus' }, { 'attr': 'stimulus_template', 'add': '_add_stimulus_template_internal', 'type': TimeSeries, 'get': 'get_stimulus_template' }, { 'attr': 'processing', 'add': 'add_processing_module', 'type': ProcessingModule, 'create': 'create_processing_module', 'get': 'get_processing_module' }, { 'attr': 'devices', 'add': 'add_device', 'type': Device, 'create': 'create_device', 'get': 'get_device' }, { 'attr': 'electrode_groups', 'add': 'add_electrode_group', 'type': ElectrodeGroup, 'create': 'create_electrode_group', 'get': 'get_electrode_group' }, { 'attr': 'imaging_planes', 'add': 'add_imaging_plane', 'type': ImagingPlane, 'create': 'create_imaging_plane', 'get': 'get_imaging_plane' }, { 'attr': 'ic_electrodes', 'add': 'add_ic_electrode', 'type': IntracellularElectrode, 'create': 'create_ic_electrode', 'get': 'get_ic_electrode' }, { 'attr': 'ogen_sites', 'add': 'add_ogen_site', 'type': OptogeneticStimulusSite, 'create': 'create_ogen_site', 'get': 'get_ogen_site' }, { 'attr': 'intervals', 'add': 'add_time_intervals', 'type': TimeIntervals, 'create': 'create_time_intervals', 'get': 'get_time_intervals' }, { 'attr': 'lab_meta_data', 'add': 'add_lab_meta_data', 'type': LabMetaData, 'create': 'create_lab_meta_data', 'get': 'get_lab_meta_data' } ] __nwbfields__ = ({'name': 'session_description', 'settable': False}, {'name': 'identifier', 'settable': False}, {'name': 'session_start_time', 'settable': False}, {'name': 'timestamps_reference_time', 'settable': False}, {'name': 'file_create_date', 'settable': False}, 'experimenter', 'experiment_description', 'session_id', 'institution', 'keywords', 'notes', 'pharmacology', 'protocol', 'related_publications', 'slices', 'source_script', 'source_script_file_name', 'data_collection', 'surgery', 'virus', 'stimulus_notes', 'lab', {'name': 'electrodes', 'child': True, 'required_name': 'electrodes'}, {'name': 'epochs', 'child': True, 'required_name': 'epochs'}, {'name': 'trials', 'child': True, 'required_name': 'trials'}, {'name': 'units', 'child': True, 'required_name': 'units'}, {'name': 'subject', 'child': True, 'required_name': 'subject'}, {'name': 'sweep_table', 'child': True, 'required_name': 'sweep_table'}, {'name': 'invalid_times', 'child': True, 'required_name': 'invalid_times'}, 'epoch_tags',) @docval({'name': 'session_description', 'type': str, 'doc': 'a description of the session where this data was generated'}, {'name': 'identifier', 'type': str, 'doc': 'a unique text identifier for the file'}, {'name': 'session_start_time', 'type': datetime, 'doc': 'the start date and time of the recording session'}, {'name': 'file_create_date', 'type': ('array_data', datetime), 'doc': 'the date and time the file was created and subsequent modifications made', 'default': None}, {'name': 'timestamps_reference_time', 'type': datetime, 'doc': 'date and time corresponding to time zero of all timestamps; defaults to value ' 'of session_start_time', 'default': None}, {'name': 'experimenter', 'type': (tuple, list, str), 'doc': 'name of person who performed experiment', 'default': None}, {'name': 'experiment_description', 'type': str, 'doc': 'general description of the experiment', 'default': None}, {'name': 'session_id', 'type': str, 'doc': 'lab-specific ID for the session', 'default': None}, {'name': 'institution', 'type': str, 'doc': 'institution(s) where experiment is performed', 'default': None}, {'name': 'keywords', 'type': 'array_data', 'doc': 'Terms to search over', 'default': None}, {'name': 'notes', 'type': str, 'doc': 'Notes about the experiment.', 'default': None}, {'name': 'pharmacology', 'type': str, 'doc': 'Description of drugs used, including how and when they were administered. ' 'Anesthesia(s), painkiller(s), etc., plus dosage, concentration, etc.', 'default': None}, {'name': 'protocol', 'type': str, 'doc': 'Experimental protocol, if applicable. E.g., include IACUC protocol', 'default': None}, {'name': 'related_publications', 'type': (tuple, list, str), 'doc': 'Publication information.' 'PMID, DOI, URL, etc. If multiple, concatenate together and describe which is which. ' 'such as PMID, DOI, URL, etc', 'default': None}, {'name': 'slices', 'type': str, 'doc': 'Description of slices, including information about preparation ' 'thickness, orientation, temperature and bath solution', 'default': None}, {'name': 'source_script', 'type': str, 'doc': 'Script file used to create this NWB file.', 'default': None}, {'name': 'source_script_file_name', 'type': str, 'doc': 'Name of the source_script file', 'default': None}, {'name': 'data_collection', 'type': str, 'doc': 'Notes about data collection and analysis.', 'default': None}, {'name': 'surgery', 'type': str, 'doc': 'Narrative description about surgery/surgeries, including date(s) ' 'and who performed surgery.', 'default': None}, {'name': 'virus', 'type': str, 'doc': 'Information about virus(es) used in experiments, including virus ID, ' 'source, date made, injection location, volume, etc.', 'default': None}, {'name': 'stimulus_notes', 'type': str, 'doc': 'Notes about stimuli, such as how and where presented.', 'default': None}, {'name': 'lab', 'type': str, 'doc': 'lab where experiment was performed', 'default': None}, {'name': 'acquisition', 'type': (list, tuple), 'doc': 'Raw TimeSeries objects belonging to this NWBFile', 'default': None}, {'name': 'analysis', 'type': (list, tuple), 'doc': 'result of analysis', 'default': None}, {'name': 'stimulus', 'type': (list, tuple), 'doc': 'Stimulus TimeSeries objects belonging to this NWBFile', 'default': None}, {'name': 'stimulus_template', 'type': (list, tuple), 'doc': 'Stimulus template TimeSeries objects belonging to this NWBFile', 'default': None}, {'name': 'epochs', 'type': TimeIntervals, 'doc': 'Epoch objects belonging to this NWBFile', 'default': None}, {'name': 'epoch_tags', 'type': (tuple, list, set), 'doc': 'A sorted list of tags used across all epochs', 'default': set()}, {'name': 'trials', 'type': TimeIntervals, 'doc': 'A table containing trial data', 'default': None}, {'name': 'invalid_times', 'type': TimeIntervals, 'doc': 'A table containing times to be omitted from analysis', 'default': None}, {'name': 'intervals', 'type': (list, tuple), 'doc': 'any TimeIntervals tables storing time intervals', 'default': None}, {'name': 'units', 'type': Units, 'doc': 'A table containing unit metadata', 'default': None}, {'name': 'processing', 'type': (list, tuple), 'doc': 'ProcessingModule objects belonging to this NWBFile', 'default': None}, {'name': 'lab_meta_data', 'type': (list, tuple), 'default': None, 'doc': 'an extension that contains lab-specific meta-data'}, {'name': 'electrodes', 'type': DynamicTable, 'doc': 'the ElectrodeTable that belongs to this NWBFile', 'default': None}, {'name': 'electrode_groups', 'type': Iterable, 'doc': 'the ElectrodeGroups that belong to this NWBFile', 'default': None}, {'name': 'ic_electrodes', 'type': (list, tuple), 'doc': 'IntracellularElectrodes that belong to this NWBFile', 'default': None}, {'name': 'sweep_table', 'type': SweepTable, 'doc': 'the SweepTable that belong to this NWBFile', 'default': None}, {'name': 'imaging_planes', 'type': (list, tuple), 'doc': 'ImagingPlanes that belong to this NWBFile', 'default': None}, {'name': 'ogen_sites', 'type': (list, tuple), 'doc': 'OptogeneticStimulusSites that belong to this NWBFile', 'default': None}, {'name': 'devices', 'type': (list, tuple), 'doc': 'Device objects belonging to this NWBFile', 'default': None}, {'name': 'subject', 'type': Subject, 'doc': 'subject metadata', 'default': None}, {'name': 'scratch', 'type': (list, tuple), 'doc': 'scratch data', 'default': None}) def __init__(self, **kwargs): kwargs['name'] = 'root' call_docval_func(super(NWBFile, self).__init__, kwargs) self.fields['session_description'] = getargs('session_description', kwargs) self.fields['identifier'] = getargs('identifier', kwargs) self.fields['session_start_time'] = getargs('session_start_time', kwargs) if self.fields['session_start_time'].tzinfo is None: self.fields['session_start_time'] = _add_missing_timezone(self.fields['session_start_time']) self.fields['timestamps_reference_time'] = getargs('timestamps_reference_time', kwargs) if self.fields['timestamps_reference_time'] is None: self.fields['timestamps_reference_time'] = self.fields['session_start_time'] elif self.fields['timestamps_reference_time'].tzinfo is None: raise ValueError("'timestamps_reference_time' must be a timezone-aware datetime object.") self.fields['file_create_date'] = getargs('file_create_date', kwargs) if self.fields['file_create_date'] is None: self.fields['file_create_date'] = datetime.now(tzlocal()) if isinstance(self.fields['file_create_date'], datetime): self.fields['file_create_date'] = [self.fields['file_create_date']] self.fields['file_create_date'] = list(map(_add_missing_timezone, self.fields['file_create_date'])) fieldnames = [ 'acquisition', 'analysis', 'stimulus', 'stimulus_template', 'keywords', 'processing', 'epoch_tags', 'electrodes', 'electrode_groups', 'devices', 'ic_electrodes', 'imaging_planes', 'ogen_sites', 'intervals', 'subject', 'sweep_table', 'lab_meta_data', 'epochs', 'trials', 'invalid_times', 'units', 'scratch', 'experiment_description', 'session_id', 'lab', 'institution', 'data_collection', 'notes', 'pharmacology', 'protocol', 'slices', 'source_script', 'source_script_file_name', 'surgery', 'virus', 'stimulus_notes', ] for attr in fieldnames: setattr(self, attr, kwargs.get(attr, None)) experimenter = kwargs.get('experimenter', None) if isinstance(experimenter, str): experimenter = (experimenter,) setattr(self, 'experimenter', experimenter) related_pubs = kwargs.get('related_publications', None) if isinstance(related_pubs, str): related_pubs = (related_pubs,) setattr(self, 'related_publications', related_pubs) if getargs('source_script', kwargs) is None and getargs('source_script_file_name', kwargs) is not None: raise ValueError("'source_script' cannot be None when 'source_script_file_name' is set") self.__obj = None def all_children(self): stack = [self] ret = list() self.__obj = LabelledDict(label='all_objects', def_key_name='object_id') while len(stack): n = stack.pop() ret.append(n) if n.object_id is not None: self.__obj[n.object_id] = n else: warn('%s "%s" does not have an object_id' % (n.neurodata_type, n.name)) if hasattr(n, 'children'): for c in n.children: stack.append(c) return ret @property def objects(self): if self.__obj is None: self.all_children() return self.__obj @property def modules(self): warn("replaced by NWBFile.processing", DeprecationWarning) return self.processing @property def ec_electrode_groups(self): warn("replaced by NWBFile.electrode_groups", DeprecationWarning) return self.electrode_groups @property def ec_electrodes(self): warn("replaced by NWBFile.electrodes", DeprecationWarning) return self.electrodes def __check_epochs(self): if self.epochs is None: self.epochs = TimeIntervals('epochs', 'experimental epochs') @docval(*get_docval(TimeIntervals.add_column)) def add_epoch_column(self, **kwargs): """ Add a column to the electrode table. See :py:meth:`~pynwb.core.TimeIntervals.add_column` for more details """ self.__check_epochs() self.epoch_tags.update(kwargs.pop('tags', list())) call_docval_func(self.epochs.add_column, kwargs) def add_epoch_metadata_column(self, *args, **kwargs): """ This method is deprecated and will be removed in future versions. Please use :py:meth:`~pynwb.file.NWBFile.add_epoch_column` instead """ raise DeprecationWarning("Please use NWBFile.add_epoch_column") @docval(*get_docval(TimeIntervals.add_interval), allow_extra=True) def add_epoch(self, **kwargs): """ Creates a new Epoch object. Epochs are used to track intervals in an experiment, such as exposure to a certain type of stimuli (an interval where orientation gratings are shown, or of sparse noise) or a different paradigm (a rat exploring an enclosure versus sleeping between explorations) """ self.__check_epochs() if kwargs['tags'] is not None: self.epoch_tags.update(kwargs['tags']) call_docval_func(self.epochs.add_interval, kwargs) def __check_electrodes(self): if self.electrodes is None: self.electrodes = ElectrodeTable() @docval(*get_docval(DynamicTable.add_column)) def add_electrode_column(self, **kwargs): """ Add a column to the electrode table. See :py:meth:`~hdmf.common.DynamicTable.add_column` for more details """ self.__check_electrodes() call_docval_func(self.electrodes.add_column, kwargs) @docval({'name': 'x', 'type': 'float', 'doc': 'the x coordinate of the position'}, {'name': 'y', 'type': 'float', 'doc': 'the y coordinate of the position'}, {'name': 'z', 'type': 'float', 'doc': 'the z coordinate of the position'}, {'name': 'imp', 'type': 'float', 'doc': 'the impedance of the electrode'}, {'name': 'location', 'type': str, 'doc': 'the location of electrode within the subject e.g. brain region'}, {'name': 'filtering', 'type': str, 'doc': 'description of hardware filtering'}, {'name': 'group', 'type': ElectrodeGroup, 'doc': 'the ElectrodeGroup object to add to this NWBFile'}, {'name': 'id', 'type': int, 'doc': 'a unique identifier for the electrode', 'default': None}, allow_extra=True) def add_electrode(self, **kwargs): """ Add a unit to the unit table. See :py:meth:`~hdmf.common.DynamicTable.add_row` for more details. Required fields are *x*, *y*, *z*, *imp*, *location*, *filtering*, *group* and any columns that have been added (through calls to `add_electrode_columns`). """ self.__check_electrodes() d = _copy.copy(kwargs['data']) if kwargs.get('data') is not None else kwargs if d.get('group_name', None) is None: d['group_name'] = d['group'].name call_docval_func(self.electrodes.add_row, d) @docval({'name': 'region', 'type': (slice, list, tuple), 'doc': 'the indices of the table'}, {'name': 'description', 'type': str, 'doc': 'a brief description of what this electrode is'}, {'name': 'name', 'type': str, 'doc': 'the name of this container', 'default': 'electrodes'}) def create_electrode_table_region(self, **kwargs): if self.electrodes is None: msg = "no electrodes available. add electrodes before creating a region" raise RuntimeError(msg) region = getargs('region', kwargs) for idx in region: if idx < 0 or idx >= len(self.electrodes): raise IndexError('The index ' + str(idx) + ' is out of range for the ElectrodeTable of length ' + str(len(self.electrodes))) desc = getargs('description', kwargs) name = getargs('name', kwargs) return DynamicTableRegion(name, region, desc, self.electrodes) def __check_units(self): if self.units is None: self.units = Units(name='units', description='Autogenerated by NWBFile') @docval(*get_docval(Units.add_column)) def add_unit_column(self, **kwargs): """ Add a column to the unit table. See :py:meth:`~hdmf.common.DynamicTable.add_column` for more details """ self.__check_units() call_docval_func(self.units.add_column, kwargs) @docval(*get_docval(Units.add_unit), allow_extra=True) def add_unit(self, **kwargs): """ Add a unit to the unit table. See :py:meth:`~hdmf.common.DynamicTable.add_row` for more details. """ self.__check_units() call_docval_func(self.units.add_unit, kwargs) def __check_trials(self): if self.trials is None: self.trials = TimeIntervals('trials', 'experimental trials') @docval(*get_docval(DynamicTable.add_column)) def add_trial_column(self, **kwargs): """ Add a column to the trial table. See :py:meth:`~hdmf.common.DynamicTable.add_column` for more details """ self.__check_trials() call_docval_func(self.trials.add_column, kwargs) @docval(*get_docval(TimeIntervals.add_interval), allow_extra=True) def add_trial(self, **kwargs): """ Add a trial to the trial table. See :py:meth:`~hdmf.common.DynamicTable.add_interval` for more details. Required fields are *start_time*, *stop_time*, and any columns that have been added (through calls to `add_trial_columns`). """ self.__check_trials() call_docval_func(self.trials.add_interval, kwargs) def __check_invalid_times(self): if self.invalid_times is None: self.invalid_times = TimeIntervals('invalid_times', 'time intervals to be removed from analysis') @docval(*get_docval(DynamicTable.add_column)) def add_invalid_times_column(self, **kwargs): """ Add a column to the trial table. See :py:meth:`~hdmf.common.DynamicTable.add_column` for more details """ self.__check_invalid_times() call_docval_func(self.invalid_times.add_column, kwargs) def add_invalid_time_interval(self, **kwargs): """ Add a trial to the trial table. See :py:meth:`~hdmf.common.DynamicTable.add_row` for more details. Required fields are *start_time*, *stop_time*, and any columns that have been added (through calls to `add_invalid_times_columns`). """ self.__check_invalid_times() call_docval_func(self.invalid_times.add_interval, kwargs) @docval({'name': 'electrode_table', 'type': DynamicTable, 'doc': 'the ElectrodeTable for this file'}) def set_electrode_table(self, **kwargs): """ Set the electrode table of this NWBFile to an existing ElectrodeTable """ if self.electrodes is not None: msg = 'ElectrodeTable already exists, cannot overwrite' raise ValueError(msg) electrode_table = getargs('electrode_table', kwargs) self.electrodes = electrode_table def _check_sweep_table(self): """ Create a SweepTable if not yet done. """ if self.sweep_table is None: self.sweep_table = SweepTable(name='sweep_table') def _update_sweep_table(self, nwbdata): """ Add all PatchClampSeries with a valid sweep number to the sweep_table """ if isinstance(nwbdata, PatchClampSeries): if nwbdata.sweep_number is not None: self._check_sweep_table() self.sweep_table.add_entry(nwbdata) @docval({'name': 'nwbdata', 'type': (NWBDataInterface, DynamicTable)}) def add_acquisition(self, nwbdata): self._add_acquisition_internal(nwbdata) self._update_sweep_table(nwbdata) @docval({'name': 'timeseries', 'type': TimeSeries}) def add_stimulus(self, timeseries): self._add_stimulus_internal(timeseries) self._update_sweep_table(timeseries) @docval({'name': 'timeseries', 'type': TimeSeries}) def add_stimulus_template(self, timeseries): self._add_stimulus_template_internal(timeseries) self._update_sweep_table(timeseries) @docval({'name': 'data', 'type': (np.ndarray, list, tuple, pd.DataFrame, DynamicTable, NWBContainer, ScratchData), 'help': 'the data to add to the scratch space'}, {'name': 'name', 'type': str, 'help': 'the name of the data. Only used when passing in numpy.ndarray, list, or tuple', 'default': None}, {'name': 'notes', 'type': str, 'help': 'notes to add to the data. Only used when passing in numpy.ndarray, list, or tuple', 'default': None}, {'name': 'table_description', 'type': str, 'help': 'description for the internal DynamicTable used to store a pandas.DataFrame', 'default': ''}) def add_scratch(self, **kwargs): '''Add data to the scratch space''' data, name, notes = getargs('data', 'name', 'notes', kwargs) if isinstance(data, (np.ndarray, pd.DataFrame, list, tuple)): if name is None: raise ValueError('please provide a name for scratch data') if isinstance(data, pd.DataFrame): table_description = getargs('table_description', kwargs) data = DynamicTable.from_dataframe(df=data, name=name, table_description=table_description) if notes is not None: warn('Notes argument is ignored when adding a pandas DataFrame to scratch') else: data = ScratchData(name=name, data=data, notes=notes) else: if notes is not None: warn('Notes argument is ignored when adding an NWBContainer to scratch') if name is not None: warn('Name argument is ignored when adding an NWBContainer to scratch') self._add_scratch(data) @docval({'name': 'name', 'type': str, 'help': 'the name of the object to get'}, {'name': 'convert', 'type': bool, 'help': 'return the original data, not the NWB object', 'default': True}) def get_scratch(self, **kwargs): '''Get data from the scratch space''' name, convert = getargs('name', 'convert', kwargs) ret = self._get_scratch(name) if convert: if isinstance(ret, DynamicTable): ret = ret.to_dataframe() elif isinstance(ret, ScratchData): ret = np.asarray(ret.data) return ret def copy(self): """ Shallow copy of an NWB file. Useful for linking across files. """ kwargs = self.fields.copy() for key in self.fields: if isinstance(self.fields[key], LabelledDict): kwargs[key] = list(self.fields[key].values()) # HDF5 object references cannot point to objects external to the file. Both DynamicTables such as TimeIntervals # contain such object references and types such as ElectricalSeries contain references to DynamicTables. # Below, copy the table and link to the columns so that object references work. fields_to_copy = ['electrodes', 'epochs', 'trials', 'units', 'subject', 'sweep_table', 'invalid_times'] for field in fields_to_copy: if field in kwargs: if isinstance(self.fields[field], DynamicTable): kwargs[field] = self.fields[field].copy() else: warn('Cannot copy child of NWBFile that is not a DynamicTable.') # handle dictionaries of DynamicTables dt_to_copy = ['scratch', 'intervals'] for dt in dt_to_copy: if dt in kwargs: kwargs[dt] = [v.copy() if isinstance(v, DynamicTable) else v for v in kwargs[dt]] return NWBFile(**kwargs) def _add_missing_timezone(date): """ Add local timezone information on a datetime object if it is missing. """ if not isinstance(date, datetime): raise ValueError("require datetime object") if date.tzinfo is None: warn("Date is missing timezone information. Updating to local timezone.") return date.replace(tzinfo=tzlocal()) return date def _tablefunc(table_name, description, columns): t = DynamicTable(table_name, description) for c in columns: if isinstance(c, tuple): t.add_column(c[0], c[1]) elif isinstance(c, str): t.add_column(c) else: raise ValueError("Elements of 'columns' must be str or tuple") return t def ElectrodeTable(name='electrodes', description='metadata about extracellular electrodes'): return _tablefunc(name, description, [('x', 'the x coordinate of the channel location'), ('y', 'the y coordinate of the channel location'), ('z', 'the z coordinate of the channel location'), ('imp', 'the impedance of the channel'), ('location', 'the location of channel within the subject e.g. brain region'), ('filtering', 'description of hardware filtering'), ('group', 'a reference to the ElectrodeGroup this electrode is a part of'), ('group_name', 'the name of the ElectrodeGroup this electrode is a part of')] ) def TrialTable(name='trials', description='metadata about experimental trials'): return _tablefunc(name, description, ['start_time', 'stop_time']) def InvalidTimesTable(name='invalid_times', description='time intervals to be removed from analysis'): return _tablefunc(name, description, ['start_time', 'stop_time']) pynwb-1.2.1/src/pynwb/epoch.py0000644000655200065520000000716413612200244017640 0ustar circlecicircleci00000000000000from bisect import bisect_left from hdmf.utils import docval, getargs, popargs, call_docval_func, get_docval from hdmf.data_utils import DataIO from . import register_class, CORE_NAMESPACE from .base import TimeSeries from hdmf.common import DynamicTable @register_class('TimeIntervals', CORE_NAMESPACE) class TimeIntervals(DynamicTable): """ Table for storing Epoch data """ __defaultname__ = 'epochs' __columns__ = ( {'name': 'start_time', 'description': 'Start time of epoch, in seconds', 'required': True}, {'name': 'stop_time', 'description': 'Stop time of epoch, in seconds', 'required': True}, {'name': 'tags', 'description': 'user-defined tags', 'index': True}, {'name': 'timeseries', 'description': 'index into a TimeSeries object', 'index': True} ) @docval({'name': 'name', 'type': str, 'doc': 'name of this TimeIntervals'}, # required {'name': 'description', 'type': str, 'doc': 'Description of this TimeIntervals', 'default': "experimental intervals"}, *get_docval(DynamicTable.__init__, 'id', 'columns', 'colnames')) def __init__(self, **kwargs): call_docval_func(super(TimeIntervals, self).__init__, kwargs) @docval({'name': 'start_time', 'type': 'float', 'doc': 'Start time of epoch, in seconds'}, {'name': 'stop_time', 'type': 'float', 'doc': 'Stop time of epoch, in seconds'}, {'name': 'tags', 'type': (str, list, tuple), 'doc': 'user-defined tags used throughout time intervals', 'default': None}, {'name': 'timeseries', 'type': (list, tuple, TimeSeries), 'doc': 'the TimeSeries this epoch applies to', 'default': None}, allow_extra=True) def add_interval(self, **kwargs): tags, timeseries = popargs('tags', 'timeseries', kwargs) start_time, stop_time = getargs('start_time', 'stop_time', kwargs) rkwargs = dict(kwargs) if tags is not None: if isinstance(tags, str): tags = [s.strip() for s in tags.split(",") if not s.isspace()] rkwargs['tags'] = tags if not (timeseries is None or (isinstance(timeseries, (tuple, list)) and len(timeseries) == 0)): if isinstance(timeseries, TimeSeries): timeseries = [timeseries] tmp = list() for ts in timeseries: idx_start, count = self.__calculate_idx_count(start_time, stop_time, ts) tmp.append((idx_start, count, ts)) timeseries = tmp rkwargs['timeseries'] = timeseries return super(TimeIntervals, self).add_row(**rkwargs) def __calculate_idx_count(self, start_time, stop_time, ts_data): if isinstance(ts_data.timestamps, DataIO): ts_timestamps = ts_data.timestamps.data ts_starting_time = ts_data.starting_time ts_rate = ts_data.rate else: ts = ts_data ts_timestamps = ts.timestamps ts_starting_time = ts.starting_time ts_rate = ts.rate if ts_starting_time is not None and ts_rate: start_idx = int((start_time - ts_starting_time)*ts_rate) stop_idx = int((stop_time - ts_starting_time)*ts_rate) elif len(ts_timestamps) > 0: timestamps = ts_timestamps start_idx = bisect_left(timestamps, start_time) stop_idx = bisect_left(timestamps, stop_time) else: raise ValueError("TimeSeries object must have timestamps or starting_time and rate") count = stop_idx - start_idx idx_start = start_idx return int(idx_start), int(count) pynwb-1.2.1/src/pynwb/nwb-schema/0000755000655200065520000000000013612200376020212 5ustar circlecicircleci00000000000000pynwb-1.2.1/src/pynwb/nwb-schema/core/0000755000655200065520000000000013612200376021142 5ustar circlecicircleci00000000000000pynwb-1.2.1/src/pynwb/nwb-schema/core/nwb.ecephys.yaml0000644000655200065520000002567413612200246024265 0ustar circlecicircleci00000000000000groups: - neurodata_type_def: ElectricalSeries neurodata_type_inc: TimeSeries doc: A time series of acquired voltage data from extracellular recordings. The data field is an int or float array storing data in volts. The first dimension should always represent time. The second dimension, if present, should represent channels. datasets: - name: data dtype: numeric dims: - - num_times - - num_times - num_channels - - num_times - num_channels - num_samples shape: - - null - - null - null - - null - null - null doc: Recorded voltage data. attributes: - name: unit dtype: text value: volts doc: Base unit of measurement for working with the data. This value is fixed to 'volts'. Actual stored values are not necessarily stored in these units. To access the data in these units, multiply 'data' by 'conversion' and 'channel_conversion' (if present). - name: electrodes neurodata_type_inc: DynamicTableRegion doc: DynamicTableRegion pointer to the electrodes that this time series was generated from. - name: channel_conversion dtype: float dims: - num_channels shape: - null doc: Channel-specific conversion factor. Multiply the data in the 'data' dataset by these values along the channel axis (as indicated by axis attribute) AND by the global conversion factor in the 'conversion' attribute of 'data' to get the data values in Volts, i.e, data in Volts = data * data.conversion * channel_conversion. This approach allows for both global and per-channel data conversion factors needed to support the storage of electrical recordings as native values generated by data acquisition systems. If this dataset is not present, then there is no channel-specific conversion factor, i.e. it is 1 for all channels. quantity: '?' attributes: - name: axis dtype: int value: 1 doc: The zero-indexed axis of the 'data' dataset that the channel-specific conversion factor corresponds to. This value is fixed to 1. - neurodata_type_def: SpikeEventSeries neurodata_type_inc: ElectricalSeries doc: "Stores snapshots/snippets of recorded spike events (i.e., threshold crossings). This may also be raw data, as reported by ephys hardware. If so, the TimeSeries::description field should describe how events were detected. All SpikeEventSeries should reside in a module (under EventWaveform interface) even if the spikes were reported and stored by hardware. All events span the same recording channels and store snapshots of equal duration. TimeSeries::data array structure: [num events] [num channels] [num samples] (or [num events] [num samples] for single electrode)." datasets: - name: data dtype: numeric dims: - - num_events - num_samples - - num_events - num_channels - num_samples shape: - - null - null - - null - null - null doc: Spike waveforms. attributes: - name: unit dtype: text value: volts doc: Unit of measurement for waveforms, which is fixed to 'volts'. - name: timestamps dtype: float64 dims: - num_times shape: - null doc: Timestamps for samples stored in data, in seconds, relative to the common experiment master-clock stored in NWBFile.timestamps_reference_time. Timestamps are required for the events. Unlike for TimeSeries, timestamps are required for SpikeEventSeries and are thus re-specified here. attributes: - name: interval dtype: int32 value: 1 doc: Value is '1' - name: unit dtype: text value: seconds doc: Unit of measurement for timestamps, which is fixed to 'seconds'. - neurodata_type_def: FeatureExtraction neurodata_type_inc: NWBDataInterface default_name: FeatureExtraction doc: Features, such as PC1 and PC2, that are extracted from signals stored in a SpikeEventSeries or other source. datasets: - name: description dtype: text dims: - num_features shape: - null doc: Description of features (eg, ''PC1'') for each of the extracted features. - name: features dtype: float32 dims: - num_events - num_channels - num_features shape: - null - null - null doc: Multi-dimensional array of features extracted from each event. - name: times dtype: float64 dims: - num_events shape: - null doc: Times of events that features correspond to (can be a link). - name: electrodes neurodata_type_inc: DynamicTableRegion doc: DynamicTableRegion pointer to the electrodes that this time series was generated from. - neurodata_type_def: EventDetection neurodata_type_inc: NWBDataInterface default_name: EventDetection doc: Detected spike events from voltage trace(s). datasets: - name: detection_method dtype: text doc: Description of how events were detected, such as voltage threshold, or dV/dT threshold, as well as relevant values. - name: source_idx dtype: int32 dims: - num_events shape: - null doc: Indices (zero-based) into source ElectricalSeries::data array corresponding to time of event. ''description'' should define what is meant by time of event (e.g., .25 ms before action potential peak, zero-crossing time, etc). The index points to each event from the raw data. - name: times dtype: float64 dims: - num_events shape: - null doc: Timestamps of events, in seconds. attributes: - name: unit dtype: text value: seconds doc: Unit of measurement for event times, which is fixed to 'seconds'. links: - name: source_electricalseries target_type: ElectricalSeries doc: Link to the ElectricalSeries that this data was calculated from. Metadata about electrodes and their position can be read from that ElectricalSeries so it's not necessary to include that information here. - neurodata_type_def: EventWaveform neurodata_type_inc: NWBDataInterface default_name: EventWaveform doc: Represents either the waveforms of detected events, as extracted from a raw data trace in /acquisition, or the event waveforms that were stored during experiment acquisition. groups: - neurodata_type_inc: SpikeEventSeries doc: SpikeEventSeries object(s) containing detected spike event waveforms. quantity: '*' - neurodata_type_def: FilteredEphys neurodata_type_inc: NWBDataInterface default_name: FilteredEphys doc: Electrophysiology data from one or more channels that has been subjected to filtering. Examples of filtered data include Theta and Gamma (LFP has its own interface). FilteredEphys modules publish an ElectricalSeries for each filtered channel or set of channels. The name of each ElectricalSeries is arbitrary but should be informative. The source of the filtered data, whether this is from analysis of another time series or as acquired by hardware, should be noted in each's TimeSeries::description field. There is no assumed 1::1 correspondence between filtered ephys signals and electrodes, as a single signal can apply to many nearby electrodes, and one electrode may have different filtered (e.g., theta and/or gamma) signals represented. Filter properties should be noted in the ElectricalSeries. groups: - neurodata_type_inc: ElectricalSeries doc: ElectricalSeries object(s) containing filtered electrophysiology data. quantity: '+' - neurodata_type_def: LFP neurodata_type_inc: NWBDataInterface default_name: LFP doc: LFP data from one or more channels. The electrode map in each published ElectricalSeries will identify which channels are providing LFP data. Filter properties should be noted in the ElectricalSeries description or comments field. groups: - neurodata_type_inc: ElectricalSeries doc: ElectricalSeries object(s) containing LFP data for one or more channels. quantity: '+' - neurodata_type_def: ElectrodeGroup neurodata_type_inc: NWBContainer doc: A physical grouping of electrodes, e.g. a shank of an array. attributes: - name: description dtype: text doc: Description of this electrode group. - name: location dtype: text doc: Location of electrode group. Specify the area, layer, comments on estimation of area/layer, stereotaxic coordinates if in vivo, etc. Use standard atlas names for anatomical regions when possible. links: - name: device target_type: Device doc: Link to the device that was used to record from this electrode group. # The types below have been deprecated - neurodata_type_def: ClusterWaveforms neurodata_type_inc: NWBDataInterface default_name: ClusterWaveforms doc: DEPRECATED The mean waveform shape, including standard deviation, of the different clusters. Ideally, the waveform analysis should be performed on data that is only high-pass filtered. This is a separate module because it is expected to require updating. For example, IMEC probes may require different storage requirements to store/display mean waveforms, requiring a new interface or an extension of this one. datasets: - name: waveform_filtering dtype: text doc: Filtering applied to data before generating mean/sd - name: waveform_mean dtype: float32 dims: - num_clusters - num_samples shape: - null - null doc: The mean waveform for each cluster, using the same indices for each wave as cluster numbers in the associated Clustering module (i.e, cluster 3 is in array slot [3]). Waveforms corresponding to gaps in cluster sequence should be empty (e.g., zero- filled) - name: waveform_sd dtype: float32 dims: - num_clusters - num_samples shape: - null - null doc: Stdev of waveforms for each cluster, using the same indices as in mean links: - name: clustering_interface target_type: Clustering doc: Link to Clustering interface that was the source of the clustered data - neurodata_type_def: Clustering neurodata_type_inc: NWBDataInterface default_name: Clustering doc: DEPRECATED Clustered spike data, whether from automatic clustering tools (e.g., klustakwik) or as a result of manual sorting. datasets: - name: description dtype: text doc: Description of clusters or clustering, (e.g. cluster 0 is noise, clusters curated using Klusters, etc) - name: num dtype: int32 dims: - num_events shape: - null doc: Cluster number of each event - name: peak_over_rms dtype: float32 dims: - num_clusters shape: - null doc: Maximum ratio of waveform peak to RMS on any channel in the cluster (provides a basic clustering metric). - name: times dtype: float64 dims: - num_events shape: - null doc: Times of clustered events, in seconds. This may be a link to times field in associated FeatureExtraction module. pynwb-1.2.1/src/pynwb/nwb-schema/core/nwb.epoch.yaml0000644000655200065520000000254113612200246023707 0ustar circlecicircleci00000000000000groups: - neurodata_type_def: TimeIntervals neurodata_type_inc: DynamicTable doc: A container for aggregating epoch data and the TimeSeries that each epoch applies to. datasets: - name: start_time neurodata_type_inc: VectorData dtype: float doc: Start time of epoch, in seconds. - name: stop_time neurodata_type_inc: VectorData dtype: float doc: Stop time of epoch, in seconds. - name: tags neurodata_type_inc: VectorData dtype: text doc: User-defined tags that identify or categorize events. quantity: '?' - name: tags_index neurodata_type_inc: VectorIndex doc: Index for tags. quantity: '?' - name: timeseries neurodata_type_inc: VectorData dtype: - 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. - name: count dtype: int32 doc: Number of data samples available in this time series, during this epoch. - name: timeseries dtype: target_type: TimeSeries reftype: object doc: the TimeSeries that this index applies to. doc: An index into a TimeSeries object. quantity: '?' - name: timeseries_index neurodata_type_inc: VectorIndex doc: Index for timeseries. quantity: '?' pynwb-1.2.1/src/pynwb/nwb-schema/core/nwb.file.yaml0000644000655200065520000004137413612200246023537 0ustar circlecicircleci00000000000000groups: - neurodata_type_def: NWBFile neurodata_type_inc: NWBContainer name: root doc: An NWB:N file storing cellular-based neurophysiology data from a single experimental session. attributes: - name: nwb_version dtype: text value: 2.1.0 doc: File version string. Use semantic versioning, e.g. 1.2.1. This will be the name of the format with trailing major, minor and patch numbers. datasets: - name: file_create_date dtype: isodatetime dims: - num_modifications shape: - null doc: 'A record of the date the file was created and of subsequent modifications. The date is stored in UTC with local timezone offset as ISO 8601 extended formatted strings: 2018-09-28T14:43:54.123+02:00. Dates stored in UTC end in "Z" with no timezone offset. Date accuracy is up to milliseconds. The file can be created after the experiment was run, so this may differ from the experiment start time. Each modification to the nwb file adds a new entry to the array.' - name: identifier dtype: text doc: A unique text identifier for the file. For example, 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. - name: session_description dtype: text doc: A description of the experimental session and data in the file. - name: session_start_time dtype: isodatetime doc: 'Date and time of the experiment/session start. The date is stored in UTC with local timezone offset as ISO 8601 extended formatted string: 2018-09-28T14:43:54.123+02:00. Dates stored in UTC end in "Z" with no timezone offset. Date accuracy is up to milliseconds.' - name: timestamps_reference_time dtype: isodatetime doc: 'Date and time corresponding to time zero of all timestamps. The date is stored in UTC with local timezone offset as ISO 8601 extended formatted string: 2018-09-28T14:43:54.123+02:00. Dates stored in UTC end in "Z" with no timezone offset. Date accuracy is up to milliseconds. All times stored in the file use this time as reference (i.e., time zero).' groups: - name: acquisition doc: Data streams recorded from the system, including ephys, ophys, tracking, etc. This group should be 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 NWB files. This will allow keeping bulky raw data out of the file while preserving the option of keeping some/all in the file. Acquired data includes tracking and experimental data streams (i.e., everything measured from the system). If bulky data is stored in the /acquisition group, the data can exist in a separate NWB file that is linked to by the file being used for processing and analysis. groups: - neurodata_type_inc: NWBDataInterface doc: Acquired, raw data. quantity: '*' - neurodata_type_inc: DynamicTable doc: Tabular data that is relevent to acquisition quantity: '*' - name: analysis doc: 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. To facilitate sharing analysis data between labs, the contents here should be stored in standard types (e.g., neurodata_types) and appropriately documented. 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 could be shared with other labs. groups: - neurodata_type_inc: NWBContainer doc: Custom analysis results. quantity: '*' - neurodata_type_inc: DynamicTable doc: Tabular data that is relevent to data stored in analysis quantity: '*' - name: scratch doc: 'A place to store one-off analysis results. Data placed here is not intended for sharing. By placing data here, users acknowledge that there is no guarantee that their data meets any standard.' quantity: '?' groups: - neurodata_type_inc: NWBContainer doc: Any one-off containers quantity: '*' - neurodata_type_inc: DynamicTable doc: Any one-off tables quantity: '*' datasets: - neurodata_type_def: ScratchData neurodata_type_inc: NWBData doc: Any one-off datasets quantity: '*' attributes: - name: notes doc: 'Any notes the user has about the dataset being stored' dtype: text - name: processing doc: "The home for ProcessingModules. 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. ProcessingModules 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. \ \ 'Processing' refers to intermediate analysis of the acquired data to make\ \ it more amenable to scientific analysis." groups: - neurodata_type_inc: ProcessingModule doc: Intermediate analysis of acquired data. quantity: '*' - name: stimulus doc: '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). This group should be made 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. 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 linked to a remote library file.' groups: - name: presentation doc: Stimuli presented during the experiment. groups: - neurodata_type_inc: TimeSeries doc: TimeSeries objects containing data of presented stimuli. quantity: '*' - name: templates doc: 'Template stimuli. Timestamps 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.' groups: - neurodata_type_inc: TimeSeries doc: TimeSeries objects containing template data of presented stimuli. quantity: '*' - name: general doc: "Experimental metadata, including protocol, notes and description of hardware\ \ device(s). The metadata stored in this section should be used to\ \ describe the experiment. Metadata necessary for interpreting the data is stored\ \ with the data. 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\ \ (e.g., 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. 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." datasets: - name: data_collection dtype: text doc: Notes about data collection and analysis. quantity: '?' - name: experiment_description dtype: text doc: General description of the experiment. quantity: '?' - name: experimenter dtype: text doc: Name of person(s) who performed the experiment. Can also specify roles of different people involved. quantity: '?' dims: - num_experimenters shape: - null - name: institution dtype: text doc: Institution(s) where experiment was performed. quantity: '?' - name: keywords dtype: text dims: - num_keywords shape: - null doc: Terms to search over. quantity: '?' - name: lab dtype: text doc: Laboratory where experiment was performed. quantity: '?' - name: notes dtype: text doc: Notes about the experiment. quantity: '?' - name: pharmacology dtype: text doc: Description of drugs used, including how and when they were administered. Anesthesia(s), painkiller(s), etc., plus dosage, concentration, etc. quantity: '?' - name: protocol dtype: text doc: Experimental protocol, if applicable. e.g., include IACUC protocol number. quantity: '?' - name: related_publications dtype: text doc: Publication information. PMID, DOI, URL, etc. dims: - num_publications shape: - null quantity: '?' - name: session_id dtype: text doc: Lab-specific ID for the session. quantity: '?' - name: slices dtype: text doc: Description of slices, including information about preparation thickness, orientation, temperature, and bath solution. quantity: '?' - name: source_script dtype: text doc: Script file or link to public source code used to create this NWB file. quantity: '?' attributes: - name: file_name dtype: text doc: Name of script file. - name: stimulus dtype: text doc: Notes about stimuli, such as how and where they were presented. quantity: '?' - name: surgery dtype: text doc: Narrative description about surgery/surgeries, including date(s) and who performed surgery. quantity: '?' - name: virus dtype: text doc: Information about virus(es) used in experiments, including virus ID, source, date made, injection location, volume, etc. quantity: '?' groups: - neurodata_type_def: LabMetaData neurodata_type_inc: NWBContainer doc: Place-holder than can be extended so that lab-specific meta-data can be placed in /general. quantity: '*' - name: devices doc: Description of hardware devices used during experiment, e.g., monitors, ADC boards, microscopes, etc. quantity: '?' groups: - neurodata_type_def: Device neurodata_type_inc: NWBContainer doc: A data acquisition device, e.g. recording system. quantity: '+' - neurodata_type_def: Subject neurodata_type_inc: NWBContainer name: subject doc: Information about the animal or person from which the data was measured. quantity: '?' datasets: - name: age dtype: text doc: Age of subject. Can be supplied instead of 'date_of_birth'. quantity: '?' - name: date_of_birth dtype: isodatetime doc: Date of birth of subject. Can be supplied instead of 'age'. quantity: '?' - name: description dtype: text doc: Description of subject and where subject came from (e.g., breeder, if animal). quantity: '?' - name: genotype dtype: text doc: Genetic strain. If absent, assume Wild Type (WT). quantity: '?' - name: sex dtype: text doc: Gender of subject. quantity: '?' - name: species dtype: text doc: Species of subject. quantity: '?' - name: subject_id dtype: text doc: ID of animal/person used/participating in experiment (lab convention). quantity: '?' - name: weight dtype: text doc: Weight at time of experiment, at time of surgery and at other important times. quantity: '?' - name: extracellular_ephys doc: Metadata related to extracellular electrophysiology. quantity: '?' groups: - neurodata_type_inc: ElectrodeGroup doc: Physical group of electrodes. quantity: '*' - name: electrodes neurodata_type_inc: DynamicTable doc: A table of all electrodes (i.e. channels) used for recording. quantity: '?' datasets: - name: x neurodata_type_inc: VectorData dtype: float doc: x coordinate of the channel location. - name: y neurodata_type_inc: VectorData dtype: float doc: y coordinate of the channel location. - name: z neurodata_type_inc: VectorData dtype: float doc: z coordinate of the channel location. - name: imp neurodata_type_inc: VectorData dtype: float doc: Impedance of the channel. - name: location neurodata_type_inc: VectorData dtype: ascii doc: Location of the electrode (channel). Specify the area, layer, comments on estimation of area/layer, stereotaxic coordinates if in vivo, etc. Use standard atlas names for anatomical regions when possible. - name: filtering neurodata_type_inc: VectorData dtype: float doc: Description of hardware filtering. - name: group neurodata_type_inc: VectorData dtype: target_type: ElectrodeGroup reftype: object doc: Reference to the ElectrodeGroup this electrode is a part of. - name: group_name neurodata_type_inc: VectorData dtype: ascii doc: Name of the ElectrodeGroup this electrode is a part of. - name: intracellular_ephys doc: Metadata related to intracellular electrophysiology. quantity: '?' datasets: - name: filtering dtype: text doc: 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. quantity: '?' groups: - neurodata_type_inc: IntracellularElectrode doc: An intracellular electrode. quantity: '*' - name: sweep_table neurodata_type_inc: SweepTable doc: The table which groups different PatchClampSeries together. quantity: '?' - name: optogenetics doc: Metadata describing optogenetic stimuluation. quantity: '?' groups: - neurodata_type_inc: OptogeneticStimulusSite doc: An optogenetic stimulation site. quantity: '*' - name: optophysiology doc: Metadata related to optophysiology. quantity: '?' groups: - neurodata_type_inc: ImagingPlane doc: An imaging plane. quantity: '*' - name: intervals doc: Experimental intervals, whether that be logically distinct sub-experiments having a particular scientific goal, trials (see trials subgroup) during an experiment, or epochs (see epochs subgroup) deriving from analysis of data. quantity: '?' groups: - name: epochs neurodata_type_inc: TimeIntervals doc: Divisions in time marking experimental stages or sub-divisions of a single recording session. quantity: '?' - name: trials neurodata_type_inc: TimeIntervals doc: Repeated experimental events that have a logical grouping. quantity: '?' - name: invalid_times neurodata_type_inc: TimeIntervals doc: Time intervals that should be removed from analysis. quantity: '?' - neurodata_type_inc: TimeIntervals doc: Optional additional table(s) for describing other experimental time intervals. quantity: '*' - name: units neurodata_type_inc: Units doc: Data about sorted spike units. quantity: '?' pynwb-1.2.1/src/pynwb/nwb-schema/core/nwb.behavior.yaml0000644000655200065520000001157413612200246024416 0ustar circlecicircleci00000000000000groups: - neurodata_type_def: SpatialSeries neurodata_type_inc: TimeSeries doc: "Direction, e.g., of gaze or travel, or position. The TimeSeries::data field\ \ is a 2D array storing position or direction relative to some reference frame.\ \ Array structure: [num measurements] [num dimensions]. Each SpatialSeries has\ \ a text dataset reference_frame that indicates the zero-position, or the zero-axes\ \ for direction. For example, if representing gaze direction, 'straight-ahead'\ \ might be a specific pixel on the monitor, or some other point in space. For\ \ position data, the 0,0 point might be the top-left corner of an enclosure, as\ \ viewed from the tracking camera. The unit of data will indicate how to interpret\ \ SpatialSeries values." datasets: - name: data dtype: numeric dims: - - num_times - - num_times - num_features shape: - - null - - null - null doc: 1-D or 2-D array storing position or direction relative to some reference frame. attributes: - name: unit dtype: text default_value: meters doc: Base unit of measurement for working with the data. The default value is 'meters'. Actual stored values are not necessarily stored in these units. To access the data in these units, multiply 'data' by 'conversion'. required: false - name: reference_frame dtype: text doc: Description defining what exactly 'straight-ahead' means. quantity: '?' - neurodata_type_def: BehavioralEpochs neurodata_type_inc: NWBDataInterface default_name: BehavioralEpochs doc: TimeSeries for storing behavioral epochs. The objective of this and the other two Behavioral interfaces (e.g. BehavioralEvents and BehavioralTimeSeries) is to provide generic hooks for software tools/scripts. This allows a tool/script to take the output one specific interface (e.g., UnitTimes) and plot that data relative to another data modality (e.g., behavioral events) without having to define all possible modalities in advance. Declaring one of these interfaces means that one or more TimeSeries of the specified type is published. These TimeSeries should reside in a group having the same name as the interface. For example, if a BehavioralTimeSeries interface is declared, the module will have one or more TimeSeries defined in the module sub-group 'BehavioralTimeSeries'. BehavioralEpochs should use IntervalSeries. BehavioralEvents is used for irregular events. BehavioralTimeSeries is for continuous data. groups: - neurodata_type_inc: IntervalSeries doc: IntervalSeries object containing start and stop times of epochs. quantity: '*' - neurodata_type_def: BehavioralEvents neurodata_type_inc: NWBDataInterface default_name: BehavioralEvents doc: TimeSeries for storing behavioral events. See description of BehavioralEpochs for more details. groups: - neurodata_type_inc: TimeSeries doc: TimeSeries object containing behavioral events. quantity: '*' - neurodata_type_def: BehavioralTimeSeries neurodata_type_inc: NWBDataInterface default_name: BehavioralTimeSeries doc: TimeSeries for storing Behavoioral time series data. See description of BehavioralEpochs for more details. groups: - neurodata_type_inc: TimeSeries doc: TimeSeries object containing continuous behavioral data. quantity: '*' - neurodata_type_def: PupilTracking neurodata_type_inc: NWBDataInterface default_name: PupilTracking doc: Eye-tracking data, representing pupil size. groups: - neurodata_type_inc: TimeSeries doc: TimeSeries object containing time series data on pupil size. quantity: '+' - neurodata_type_def: EyeTracking neurodata_type_inc: NWBDataInterface default_name: EyeTracking doc: Eye-tracking data, representing direction of gaze. groups: - neurodata_type_inc: SpatialSeries doc: SpatialSeries object containing data measuring direction of gaze. quantity: '*' - neurodata_type_def: CompassDirection neurodata_type_inc: NWBDataInterface default_name: CompassDirection doc: With a CompassDirection interface, a module publishes a SpatialSeries object representing a floating point value for theta. The SpatialSeries::reference_frame field should indicate what direction corresponds to 0 and which is the direction of rotation (this should be clockwise). The si_unit for the SpatialSeries should be radians or degrees. groups: - neurodata_type_inc: SpatialSeries doc: SpatialSeries object containing direction of gaze travel. quantity: '*' - neurodata_type_def: Position neurodata_type_inc: NWBDataInterface default_name: Position doc: Position data, whether along the x, x/y or x/y/z axis. groups: - neurodata_type_inc: SpatialSeries doc: SpatialSeries object containing position data. quantity: '+' pynwb-1.2.1/src/pynwb/nwb-schema/core/nwb.misc.yaml0000644000655200065520000001677713612200246023564 0ustar circlecicircleci00000000000000groups: - neurodata_type_def: AbstractFeatureSeries neurodata_type_inc: TimeSeries doc: 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. This is useful when storing the raw stimulus is impractical. datasets: - name: data dtype: numeric dims: - - num_times - - num_times - num_features shape: - - null - - null - null doc: Values of each feature at each time. attributes: - name: unit dtype: text default_value: see 'feature_units' doc: Since there can be different units for different features, store the units in 'feature_units'. The default value for this attribute is "see 'feature_units'". required: false - name: feature_units dtype: text dims: - num_features shape: - null doc: Units of each feature. quantity: '?' - name: features dtype: text dims: - num_features shape: - null doc: Description of the features represented in TimeSeries::data. - neurodata_type_def: AnnotationSeries neurodata_type_inc: TimeSeries doc: Stores user annotations made during an experiment. The 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. datasets: - name: data dtype: text dims: - num_times shape: - null doc: Annotations made during an experiment. attributes: - name: resolution dtype: float value: -1.0 doc: Smallest meaningful difference between values in data. Annotations have no units, so the value is fixed to -1.0. - name: unit dtype: text value: n/a doc: Base unit of measurement for working with the data. Annotations have no units, so the value is fixed to 'n/a'. - neurodata_type_def: IntervalSeries neurodata_type_inc: TimeSeries doc: 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. datasets: - name: data dtype: int8 dims: - num_times shape: - null doc: Use values >0 if interval started, <0 if interval ended. attributes: - name: resolution dtype: float value: -1.0 doc: Smallest meaningful difference between values in data. Annotations have no units, so the value is fixed to -1.0. - name: unit dtype: text value: n/a doc: Base unit of measurement for working with the data. Annotations have no units, so the value is fixed to 'n/a'. - neurodata_type_def: DecompositionSeries neurodata_type_inc: TimeSeries doc: Spectral analysis of a time series, e.g. of an LFP or a speech signal. datasets: - name: data dtype: numeric dims: - num_times - num_channels - num_bands shape: - null - null - null doc: Data decomposed into frequency bands. attributes: - name: unit dtype: text default_value: no unit doc: Base unit of measurement for working with the data. Actual stored values are not necessarily stored in these units. To access the data in these units, multiply 'data' by 'conversion'. - name: metric dtype: text doc: The metric used, e.g. phase, amplitude, power. groups: - name: bands neurodata_type_inc: DynamicTable doc: Table for describing the bands that this series was generated from. There should be one row in this table for each band. datasets: - name: band_name neurodata_type_inc: VectorData dtype: text doc: Name of the band, e.g. theta. - name: band_limits neurodata_type_inc: VectorData dtype: float dims: - num_bands - low, high shape: - null - 2 doc: Low and high limit of each band in Hz. If it is a Gaussian filter, use 2 SD on either side of the center. - name: band_mean neurodata_type_inc: VectorData dtype: float dims: - num_bands shape: - null doc: The mean Gaussian filters, in Hz. - name: band_stdev neurodata_type_inc: VectorData dtype: float dims: - num_bands shape: - null doc: The standard deviation of Gaussian filters, in Hz. links: - name: source_timeseries target_type: TimeSeries doc: Link to TimeSeries object that this data was calculated from. Metadata about electrodes and their position can be read from that ElectricalSeries so it is not necessary to store that information here. quantity: '?' - neurodata_type_def: Units neurodata_type_inc: DynamicTable default_name: Units doc: Data about spiking units. Event times of observed units (e.g. cell, synapse, etc.) should be concatenated and stored in spike_times. datasets: - name: spike_times_index neurodata_type_inc: VectorIndex doc: Index into the spike_times dataset. quantity: '?' - name: spike_times neurodata_type_inc: VectorData dtype: double doc: Spike times for each unit. quantity: '?' - name: obs_intervals_index neurodata_type_inc: VectorIndex doc: Index into the obs_intervals dataset. quantity: '?' - name: obs_intervals neurodata_type_inc: VectorData dtype: double dims: - num_intervals - start|end shape: - null - 2 doc: Observation intervals for each unit. quantity: '?' - name: electrodes_index neurodata_type_inc: VectorIndex doc: Index into electrodes. quantity: '?' - name: electrodes neurodata_type_inc: DynamicTableRegion doc: Electrode that each spike unit came from, specified using a DynamicTableRegion. quantity: '?' - name: electrode_group neurodata_type_inc: VectorData dtype: target_type: ElectrodeGroup reftype: object doc: Electrode group that each spike unit came from. quantity: '?' - name: waveform_mean neurodata_type_inc: VectorData dtype: float dims: - - num_units - num_samples - - num_units - num_samples - num_electrodes shape: - - null - null - - null - null - null doc: Spike waveform mean for each spike unit. quantity: '?' - name: waveform_sd neurodata_type_inc: VectorData dtype: float dims: - - num_units - num_samples - - num_units - num_samples - num_electrodes shape: - - null - null - - null - null - null doc: Spike waveform standard deviation for each spike unit. quantity: '?' pynwb-1.2.1/src/pynwb/nwb-schema/core/nwb.ophys.yaml0000644000655200065520000002230213612200246023750 0ustar circlecicircleci00000000000000groups: - neurodata_type_def: TwoPhotonSeries neurodata_type_inc: ImageSeries doc: Image stack recorded over time from 2-photon microscope. attributes: - name: pmt_gain dtype: float32 doc: Photomultiplier gain. required: false - name: scan_line_rate dtype: float32 doc: Lines imaged per second. This is also stored in /general/optophysiology but is kept here as it is useful information for analysis, and so good to be stored w/ the actual data. required: false datasets: - name: field_of_view dtype: float32 dims: - width|height - width|height|depth shape: - - 2 - - 3 doc: Width, height and depth of image, or imaged area, in meters. required: false quantity: '?' links: - name: imaging_plane target_type: ImagingPlane doc: Link to ImagingPlane object from which this TimeSeries data was generated. - neurodata_type_def: RoiResponseSeries neurodata_type_inc: TimeSeries doc: ROI responses over an imaging plane. Each row in data should correspond to the signal from one ROI. Each element on the second dimension of data should correspond to the signal from one ROI. datasets: - name: data dtype: numeric dims: - - num_times - - num_times - num_ROIs shape: - - null - - null - null doc: Signals from ROIs. - name: rois neurodata_type_inc: DynamicTableRegion doc: DynamicTableRegion referencing into an ROITable containing information on the ROIs stored in this timeseries. - neurodata_type_def: DfOverF neurodata_type_inc: NWBDataInterface default_name: DfOverF doc: dF/F information about a region of interest (ROI). Storage hierarchy of dF/F should be the same as for segmentation (i.e., same names for ROIs and for image planes). groups: - neurodata_type_inc: RoiResponseSeries doc: RoiResponseSeries object(s) containing dF/F for a ROI. quantity: '+' - neurodata_type_def: Fluorescence neurodata_type_inc: NWBDataInterface default_name: Fluorescence doc: Fluorescence information about a region of interest (ROI). Storage hierarchy of fluorescence should be the same as for segmentation (ie, same names for ROIs and for image planes). groups: - neurodata_type_inc: RoiResponseSeries doc: RoiResponseSeries object(s) containing fluorescence data for a ROI. quantity: '+' - neurodata_type_def: ImageSegmentation neurodata_type_inc: NWBDataInterface default_name: ImageSegmentation doc: Stores pixels in an image that represent different regions of interest (ROIs) or masks. All segmentation for a given imaging plane is stored together, with storage for multiple imaging planes (masks) supported. Each ROI is stored in its own subgroup, with the ROI group containing both a 2D mask and a list of pixels that make up this mask. Segments can also be used for masking neuropil. If segmentation is allowed to change with time, a new imaging plane (or module) is required and ROI names should remain consistent between them. groups: - neurodata_type_def: PlaneSegmentation neurodata_type_inc: DynamicTable doc: Results from image segmentation of a specific imaging plane. quantity: '+' datasets: - name: image_mask neurodata_type_inc: VectorData dims: - - num_roi - num_x - num_y - - num_roi - num_x - num_y - num_z shape: - - null - null - null - - null - null - null - null doc: ROI masks for each ROI. Each image mask is the size of the original imaging plane (or volume) and members of the ROI are finite non-zero. quantity: '?' - name: pixel_mask_index neurodata_type_inc: VectorIndex doc: Index into pixel_mask. quantity: '?' - name: pixel_mask neurodata_type_inc: VectorData dtype: - name: x dtype: uint doc: Pixel x-coordinate. - name: y dtype: uint doc: Pixel y-coordinate. - name: weight dtype: float doc: Weight of the pixel. doc: 'Pixel masks for each ROI: a list of indices and weights for the ROI. Pixel masks are concatenated and parsing of this dataset is maintained by the PlaneSegmentation' quantity: '?' - name: voxel_mask_index neurodata_type_inc: VectorIndex doc: Index into voxel_mask. quantity: '?' - name: voxel_mask neurodata_type_inc: VectorData dtype: - name: x dtype: uint doc: Voxel x-coordinate. - name: y dtype: uint doc: Voxel y-coordinate. - name: z dtype: uint doc: Voxel z-coordinate. - name: weight dtype: float doc: Weight of the voxel. doc: 'Voxel masks for each ROI: a list of indices and weights for the ROI. Voxel masks are concatenated and parsing of this dataset is maintained by the PlaneSegmentation' quantity: '?' groups: - name: reference_images doc: Image stacks that the segmentation masks apply to. groups: - neurodata_type_inc: ImageSeries doc: One or more image stacks that the masks apply to (can be one-element stack). quantity: '*' links: - name: imaging_plane target_type: ImagingPlane doc: Link to ImagingPlane object from which this data was generated. - neurodata_type_def: ImagingPlane neurodata_type_inc: NWBContainer doc: An imaging plane and its metadata. quantity: '*' datasets: - name: description dtype: text doc: Description of the imaging plane. quantity: '?' - name: excitation_lambda dtype: float doc: Excitation wavelength, in nm. - name: imaging_rate dtype: float doc: Rate that images are acquired, in Hz. - name: indicator dtype: text doc: Calcium indicator. - name: location dtype: text doc: Location of the imaging plane. Specify the area, layer, comments on estimation of area/layer, stereotaxic coordinates if in vivo, etc. Use standard atlas names for anatomical regions when possible. - name: manifold dtype: float32 dims: - - height - width - x|y|z - - height - width - depth - x|y|z shape: - - null - null - 3 - - null - null - null - 3 doc: "Physical position of each pixel. 'xyz' represents the position\ \ of the pixel relative to the defined coordinate space." quantity: '?' attributes: - name: conversion dtype: float default_value: 1.0 doc: Scalar to multiply each element in data to convert it to the specified 'unit'. If the data are stored in acquisition system units or other units that require a conversion to be interpretable, multiply the data by 'conversion' to convert the data to the specified 'unit'. e.g. if the data acquisition system stores values in this object as pixels from x = -500 to 499, y = -500 to 499 that correspond to a 2 m x 2 m range, then the 'conversion' multiplier to get from raw data acquisition pixel units to meters is 2/1000. required: false - name: unit dtype: text default_value: meters doc: Base unit of measurement for working with the data. The default value is 'meters'. required: false - name: reference_frame dtype: text doc: Describes position and reference frame of manifold based on position of first element in manifold. For example, text description of anatomical location or vectors needed to rotate to common anatomical axis (eg, AP/DV/ML). This field is necessary to interpret manifold. If manifold is not present then this field is not required. quantity: '?' groups: - neurodata_type_def: OpticalChannel neurodata_type_inc: NWBContainer doc: An optical channel used to record from an imaging plane. datasets: - name: description dtype: text doc: Description or other notes about the channel. - name: emission_lambda dtype: float doc: Emission wavelength for channel, in nm. links: - name: device target_type: Device doc: Link to the Device object that was used to record from this electrode. - neurodata_type_def: MotionCorrection neurodata_type_inc: NWBDataInterface default_name: MotionCorrection doc: 'An image stack where all frames are shifted (registered) to a common coordinate system, to account for movement and drift between frames. Note: each frame at each point in time is assumed to be 2-D (has only x & y dimensions).' groups: - neurodata_type_def: CorrectedImageStack neurodata_type_inc: NWBDataInterface doc: Reuslts from motion correction of an image stack. quantity: '+' groups: - name: corrected neurodata_type_inc: ImageSeries doc: Image stack with frames shifted to the common coordinates. - name: xy_translation neurodata_type_inc: TimeSeries doc: Stores the x,y delta necessary to align each frame to the common coordinates, for example, to align each frame to a reference image. links: - name: original target_type: ImageSeries doc: Link to ImageSeries object that is being registered. pynwb-1.2.1/src/pynwb/nwb-schema/core/nwb.image.yaml0000644000655200065520000001320313612200246023670 0ustar circlecicircleci00000000000000datasets: - neurodata_type_def: GrayscaleImage neurodata_type_inc: Image dims: - y - x shape: - null - null doc: A grayscale image. - neurodata_type_def: RGBImage neurodata_type_inc: Image dims: - y - x - R, G, B shape: - null - null - 3 doc: A color image. - neurodata_type_def: RGBAImage neurodata_type_inc: Image dims: - y - x - R, G, B, A shape: - null - null - 4 doc: A color image with transparency. groups: - neurodata_type_def: ImageSeries neurodata_type_inc: TimeSeries doc: General image data that is common between acquisition and stimulus time series. Sometimes the image data is stored in the file in a raw format while other times it will be stored as a series of external image files in the host file system. The data field will either be binary data, if the data is stored in the NWB file, or empty, if the data is stored in an external image stack. [frame][y][x] or [frame][z][y][x]. datasets: - name: data dtype: numeric dims: - - frame - y - x - - frame - z - y - x shape: - - null - null - null - - null - null - null - null doc: Binary data representing images across frames. quantity: '?' - name: dimension dtype: int32 dims: - rank shape: - null doc: Number of pixels on x, y, (and z) axes. quantity: '?' - name: external_file dtype: text dims: - num_files shape: - null doc: Paths to one or more external file(s). The field is only present if format='external'. This is only relevant if the image series is stored in the file system as one or more image file(s). This field should NOT be used if the image is stored in another NWB file and that file is linked to this file. quantity: '?' attributes: - name: starting_frame dtype: int dims: - num_files shape: - null doc: Each external image may contain one or more consecutive frames of the full ImageSeries. This attribute serves as an index to indicate which frames each file contains, to faciliate random access. The 'starting_frame' attribute, hence, contains a list of frame numbers within the full ImageSeries of the first frame of each file listed in the parent 'external_file' dataset. Zero-based indexing is used (hence, the first element will always be zero). For example, if the 'external_file' dataset has three paths to files and the first file has 5 frames, the second file has 10 frames, and the third file has 20 frames, then this attribute will have values [0, 5, 15]. If there is a single external file that holds all of the frames of the ImageSeries (and so there is a single element in the 'external_file' dataset), then this attribute should have value [0]. - name: format dtype: text default_value: raw doc: Format of image. If this is 'external', then the attribute 'external_file' contains the path information to the image files. If this is 'raw', then the raw (single-channel) binary data is stored in the 'data' dataset. If this attribute is not present, then the default format='raw' case is assumed. quantity: '?' - neurodata_type_def: ImageMaskSeries neurodata_type_inc: ImageSeries doc: An alpha mask that is applied to a presented visual stimulus. The 'data' array contains an array of mask values that are applied to the displayed image. Mask values are stored as RGBA. Mask can vary with time. The timestamps array indicates the starting time of a mask, and that mask pattern continues until it's explicitly changed. links: - name: masked_imageseries target_type: ImageSeries doc: Link to ImageSeries object that this image mask is applied to. - neurodata_type_def: OpticalSeries neurodata_type_inc: ImageSeries doc: Image data that is presented or recorded. A stimulus template movie will be stored only as an image. When the image is presented as stimulus, additional data is required, such as field of view (e.g., how much of the visual field the image covers, or how what is the area of the target being imaged). If the OpticalSeries represents acquired imaging data, orientation is also important. datasets: - name: distance dtype: float32 doc: Distance from camera/monitor to target/eye. quantity: '?' - name: field_of_view dtype: float32 dims: - - width, height - - width, height, depth shape: - - 2 - - 3 doc: Width, height and depth of image, or imaged area, in meters. quantity: '?' - name: orientation dtype: text doc: Description of image relative to some reference frame (e.g., which way is up). Must also specify frame of reference. quantity: '?' - neurodata_type_def: IndexSeries neurodata_type_inc: TimeSeries doc: Stores indices to image frames stored in an ImageSeries. The purpose of the ImageIndexSeries 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 ImageSeries, and the timestamps array indicates when that image was displayed. datasets: - name: data dtype: int dims: - num_times shape: - null doc: Index of the frame in the referenced ImageSeries. links: - name: indexed_timeseries target_type: ImageSeries doc: Link to ImageSeries object containing images that are indexed. pynwb-1.2.1/src/pynwb/nwb-schema/core/nwb.icephys.yaml0000644000655200065520000002000613612200246024251 0ustar circlecicircleci00000000000000groups: - neurodata_type_def: PatchClampSeries neurodata_type_inc: TimeSeries doc: An abstract base class for patch-clamp data - stimulus or response, current or voltage. attributes: - name: stimulus_description dtype: text doc: Protocol/stimulus name for this patch-clamp dataset. - name: sweep_number dtype: uint64 doc: Sweep number, allows to group different PatchClampSeries together. required: false datasets: - name: data dtype: numeric dims: - num_times shape: - null doc: Recorded voltage or current. attributes: - name: unit dtype: text doc: Base unit of measurement for working with the data. Actual stored values are not necessarily stored in these units. To access the data in these units, multiply 'data' by 'conversion'. - name: gain dtype: float doc: Gain of the recording, in units Volt/Amp (v-clamp) or Volt/Volt (c-clamp). quantity: '?' links: - name: electrode target_type: IntracellularElectrode doc: Link to IntracellularElectrode object that describes the electrode that was used to apply or record this data. - neurodata_type_def: CurrentClampSeries neurodata_type_inc: PatchClampSeries doc: Voltage data from an intracellular current-clamp recording. A corresponding CurrentClampStimulusSeries (stored separately as a stimulus) is used to store the current injected. datasets: - name: data doc: Recorded voltage. attributes: - name: unit dtype: text value: volts doc: Base unit of measurement for working with the data. which is fixed to 'volts'. Actual stored values are not necessarily stored in these units. To access the data in these units, multiply 'data' by 'conversion'. - name: bias_current dtype: float32 doc: Bias current, in amps. quantity: '?' - name: bridge_balance dtype: float32 doc: Bridge balance, in ohms. quantity: '?' - name: capacitance_compensation dtype: float32 doc: Capacitance compensation, in farads. quantity: '?' - neurodata_type_def: IZeroClampSeries neurodata_type_inc: CurrentClampSeries doc: Voltage data from an intracellular recording when all current and amplifier settings are off (i.e., CurrentClampSeries fields will be zero). There is no CurrentClampStimulusSeries associated with an IZero series because the amplifier is disconnected and no stimulus can reach the cell. datasets: - name: bias_current dtype: float32 value: 0.0 doc: Bias current, in amps, fixed to 0.0. - name: bridge_balance dtype: float32 value: 0.0 doc: Bridge balance, in ohms, fixed to 0.0. - name: capacitance_compensation dtype: float32 value: 0.0 doc: Capacitance compensation, in farads, fixed to 0.0. - neurodata_type_def: CurrentClampStimulusSeries neurodata_type_inc: PatchClampSeries doc: Stimulus current applied during current clamp recording. datasets: - name: data doc: Stimulus current applied. attributes: - name: unit dtype: text value: amperes doc: Base unit of measurement for working with the data. which is fixed to 'amperes'. Actual stored values are not necessarily stored in these units. To access the data in these units, multiply 'data' by 'conversion'. - neurodata_type_def: VoltageClampSeries neurodata_type_inc: PatchClampSeries doc: Current data from an intracellular voltage-clamp recording. A corresponding VoltageClampStimulusSeries (stored separately as a stimulus) is used to store the voltage injected. datasets: - name: data doc: Recorded current. attributes: - name: unit dtype: text value: amperes doc: Base unit of measurement for working with the data. which is fixed to 'amperes'. Actual stored values are not necessarily stored in these units. To access the data in these units, multiply 'data' by 'conversion'. - name: capacitance_fast dtype: float32 doc: Fast capacitance, in farads. quantity: '?' attributes: - name: unit dtype: text value: farads doc: Unit of measurement for capacitance_fast, which is fixed to 'farads'. - name: capacitance_slow dtype: float32 doc: Slow capacitance, in farads. quantity: '?' attributes: - name: unit dtype: text value: farads doc: Unit of measurement for capacitance_fast, which is fixed to 'farads'. - name: resistance_comp_bandwidth dtype: float32 doc: Resistance compensation bandwidth, in hertz. quantity: '?' attributes: - name: unit dtype: text value: hertz doc: Unit of measurement for resistance_comp_bandwidth, which is fixed to 'hertz'. - name: resistance_comp_correction dtype: float32 doc: Resistance compensation correction, in percent. quantity: '?' attributes: - name: unit dtype: text value: percent doc: Unit of measurement for resistance_comp_correction, which is fixed to 'percent'. - name: resistance_comp_prediction dtype: float32 doc: Resistance compensation prediction, in percent. quantity: '?' attributes: - name: unit dtype: text value: percent doc: Unit of measurement for resistance_comp_prediction, which is fixed to 'percent'. - name: whole_cell_capacitance_comp dtype: float32 doc: Whole cell capacitance compensation, in farads. quantity: '?' attributes: - name: unit dtype: text value: farads doc: Unit of measurement for whole_cell_capacitance_comp, which is fixed to 'farads'. - name: whole_cell_series_resistance_comp dtype: float32 doc: Whole cell series resistance compensation, in ohms. quantity: '?' attributes: - name: unit dtype: text value: ohms doc: Unit of measurement for whole_cell_series_resistance_comp, which is fixed to 'ohms'. - neurodata_type_def: VoltageClampStimulusSeries neurodata_type_inc: PatchClampSeries doc: Stimulus voltage applied during a voltage clamp recording. datasets: - name: data doc: Stimulus voltage applied. attributes: - name: unit dtype: text value: volts doc: Base unit of measurement for working with the data. which is fixed to 'volts'. Actual stored values are not necessarily stored in these units. To access the data in these units, multiply 'data' by 'conversion'. - neurodata_type_def: IntracellularElectrode neurodata_type_inc: NWBContainer doc: An intracellular electrode and its metadata. datasets: - name: description dtype: text doc: Description of electrode (e.g., whole-cell, sharp, etc.). - name: filtering dtype: text doc: Electrode specific filtering. quantity: '?' - name: initial_access_resistance dtype: text doc: Initial access resistance. quantity: '?' - name: location dtype: text doc: Location of the electrode. Specify the area, layer, comments on estimation of area/layer, stereotaxic coordinates if in vivo, etc. Use standard atlas names for anatomical regions when possible. quantity: '?' - name: resistance dtype: text doc: Electrode resistance, in ohms. quantity: '?' - name: seal dtype: text doc: Information about seal used for recording. quantity: '?' - name: slice dtype: text doc: Information about slice used for recording. quantity: '?' links: - name: device target_type: Device doc: Device that was used to record from this electrode. - neurodata_type_def: SweepTable neurodata_type_inc: DynamicTable doc: The table which groups different PatchClampSeries together. datasets: - name: sweep_number neurodata_type_inc: VectorData dtype: uint64 doc: Sweep number of the PatchClampSeries in that row. - name: series neurodata_type_inc: VectorData dtype: target_type: PatchClampSeries reftype: object doc: The PatchClampSeries with the sweep number in that row. - name: series_index neurodata_type_inc: VectorIndex doc: Index for series. pynwb-1.2.1/src/pynwb/nwb-schema/core/nwb.retinotopy.yaml0000644000655200065520000001402313612200246025023 0ustar circlecicircleci00000000000000groups: - neurodata_type_def: ImagingRetinotopy neurodata_type_inc: NWBDataInterface default_name: ImagingRetinotopy doc: 'Intrinsic signal optical imaging or widefield imaging for measuring retinotopy. Stores orthogonal maps (e.g., altitude/azimuth; radius/theta) of responses to specific stimuli and a combined polarity map from which to identify visual areas. Note: for data consistency, all images and arrays are stored in the format [row][column] and [row, col], which equates to [y][x]. Field of view and dimension arrays may appear backward (i.e., y before x).' datasets: - name: axis_1_phase_map dtype: float32 dims: - num_rows - num_cols shape: - null - null doc: Phase response to stimulus on the first measured axis. attributes: - name: dimension dtype: int32 dims: - row_col shape: - null doc: 'Number of rows and columns in the image. NOTE: row, column representation is equivalent to height,width.' - name: field_of_view dtype: float dims: - row|column shape: - null doc: Size of viewing area, in meters. - name: unit dtype: text doc: Unit that axis data is stored in (e.g., degrees). - name: axis_1_power_map dtype: float32 dims: - num_rows - num_cols shape: - null - null doc: Power response on the first measured axis. Response is scaled so 0.0 is no power in the response and 1.0 is maximum relative power. quantity: '?' attributes: - name: dimension dtype: int32 dims: - row_col shape: - null doc: 'Number of rows and columns in the image. NOTE: row, column representation is equivalent to height,width.' - name: field_of_view dtype: float dims: - row_col shape: - null doc: Size of viewing area, in meters. - name: unit dtype: text doc: Unit that axis data is stored in (e.g., degrees). - name: axis_2_phase_map dtype: float32 dims: - num_rows - num_cols shape: - null - null doc: Phase response to stimulus on the second measured axis. attributes: - name: dimension dtype: int32 dims: - row_col shape: - null doc: 'Number of rows and columns in the image. NOTE: row, column representation is equivalent to height,width.' - name: field_of_view dtype: float dims: - row_col shape: - null doc: Size of viewing area, in meters. - name: unit dtype: text doc: Unit that axis data is stored in (e.g., degrees). - name: axis_2_power_map dtype: float32 dims: - num_rows - num_cols shape: - null - null doc: Power response on the second measured axis. Response is scaled so 0.0 is no power in the response and 1.0 is maximum relative power. quantity: '?' attributes: - name: dimension dtype: int32 dims: - row_col shape: - null doc: 'Number of rows and columns in the image. NOTE: row, column representation is equivalent to height,width.' - name: field_of_view dtype: float dims: - row_col shape: - null doc: Size of viewing area, in meters. - name: unit dtype: text doc: Unit that axis data is stored in (e.g., degrees). - name: axis_descriptions dtype: text dims: - names shape: - 2 doc: Two-element array describing the contents of the two response axis fields. Description should be something like ['altitude', 'azimuth'] or '['radius', 'theta']. - name: focal_depth_image dtype: uint16 dims: - num_rows - num_cols shape: - null - null doc: 'Gray-scale image taken with same settings/parameters (e.g., focal depth, wavelength) as data collection. Array format: [rows][columns].' attributes: - name: bits_per_pixel dtype: int32 doc: Number of bits used to represent each value. This is necessary to determine maximum (white) pixel value. - name: dimension dtype: int32 dims: - row_col shape: - null doc: 'Number of rows and columns in the image. NOTE: row, column representation is equivalent to height,width.' - name: field_of_view dtype: float dims: - row_col shape: - null doc: Size of viewing area, in meters. - name: focal_depth dtype: float doc: Focal depth offset, in meters. - name: format dtype: text doc: Format of image. Right now only 'raw' is supported. - name: sign_map dtype: float32 dims: - num_rows - num_cols shape: - null - null doc: Sine of the angle between the direction of the gradient in axis_1 and axis_2. attributes: - name: dimension dtype: int32 dims: - row_col shape: - null doc: 'Number of rows and columns in the image. NOTE: row, column representation is equivalent to height,width.' - name: field_of_view dtype: float dims: - row_col shape: - null doc: Size of viewing area, in meters. - name: vasculature_image dtype: uint16 dims: - num_rows - num_cols shape: - null - null doc: 'Gray-scale anatomical image of cortical surface. Array structure: [rows][columns]' attributes: - name: bits_per_pixel dtype: int32 doc: Number of bits used to represent each value. This is necessary to determine maximum (white) pixel value - name: dimension dtype: int32 dims: - row_col shape: - null doc: 'Number of rows and columns in the image. NOTE: row, column representation is equivalent to height,width.' - name: field_of_view dtype: float dims: - row_col shape: - null doc: Size of viewing area, in meters. - name: format dtype: text doc: Format of image. Right now only 'raw' is supported. pynwb-1.2.1/src/pynwb/nwb-schema/core/nwb.namespace.yaml0000644000655200065520000000341413612200246024545 0ustar circlecicircleci00000000000000namespaces: - name: core doc: NWB namespace author: - Andrew Tritt - Oliver Ruebel - Ryan Ly - Ben Dichter - Keith Godfrey - Jeff Teeters contact: - ajtritt@lbl.gov - oruebel@lbl.gov - rly@lbl.gov - bdichter@lbl.gov - keithg@alleninstitute.org - jteeters@berkeley.edu full_name: NWB core schema: - namespace: hdmf-common - doc: This source module contains base data types used throughout the NWB:N data format. source: nwb.base.yaml title: Base data types - doc: This source module contains neurodata_types for epoch data. source: nwb.epoch.yaml title: Epochs - doc: This source module contains neurodata_types for image data. source: nwb.image.yaml title: Image data - doc: Main NWB:N file specification. source: nwb.file.yaml title: NWB:N file - doc: Miscellaneous types. source: nwb.misc.yaml title: Miscellaneous neurodata_types. - doc: This source module contains neurodata_types for behavior data. source: nwb.behavior.yaml title: Behavior - doc: This source module contains neurodata_types for extracellular electrophysiology data. source: nwb.ecephys.yaml title: Extracellular electrophysiology - doc: This source module contains neurodata_types for intracellular electrophysiology data. source: nwb.icephys.yaml title: Intracellular electrophysiology - doc: This source module contains neurodata_types for opto-genetics data. source: nwb.ogen.yaml title: Optogenetics - doc: This source module contains neurodata_types for optical physiology data. source: nwb.ophys.yaml title: Optical physiology - doc: This source module contains neurodata_type for retinotopy data. source: nwb.retinotopy.yaml title: Retinotopy version: 2.1.0 pynwb-1.2.1/src/pynwb/nwb-schema/core/nwb.ogen.yaml0000644000655200065520000000234313612200246023541 0ustar circlecicircleci00000000000000groups: - neurodata_type_def: OptogeneticSeries neurodata_type_inc: TimeSeries doc: An optogenetic stimulus. datasets: - name: data dtype: numeric dims: - num_times shape: - null doc: Applied power for optogenetic stimulus, in watts. attributes: - name: unit dtype: text value: watts doc: Unit of measurement for data, which is fixed to 'watts'. links: - name: site target_type: OptogeneticStimulusSite doc: Link to OptogeneticStimulusSite object that describes the site to which this stimulus was applied. - neurodata_type_def: OptogeneticStimulusSite neurodata_type_inc: NWBContainer doc: A site of optogenetic stimulation. quantity: '*' datasets: - name: description dtype: text doc: Description of stimulation site. - name: excitation_lambda dtype: float doc: Excitation wavelength, in nm. - name: location dtype: text doc: Location of the stimulation site. Specify the area, layer, comments on estimation of area/layer, stereotaxic coordinates if in vivo, etc. Use standard atlas names for anatomical regions when possible. links: - name: device target_type: Device doc: Device that generated the stimulus. pynwb-1.2.1/src/pynwb/nwb-schema/core/nwb.base.yaml0000644000655200065520000001502113612200246023520 0ustar circlecicircleci00000000000000datasets: - neurodata_type_def: NWBData neurodata_type_inc: Data doc: An abstract data type for a dataset. - neurodata_type_def: Image neurodata_type_inc: NWBData dims: - - num_x - num_y - - num_x - num_y - (r, g, b) - - num_x - num_y - (r, g, b, a) shape: - - null - null - - null - null - 3 - - null - null - 4 doc: An abstract data type for an image. Shape can be 2-D (x, y), or 3-D where the third dimension can have three or four elements, e.g. (x, y, (r, g, b)) or (x, y, (r, g, b, a)). attributes: - name: resolution dtype: float doc: Pixel resolution of the image, in pixels per centimeter. required: false - name: description dtype: text doc: Description of the image. required: false groups: - neurodata_type_def: NWBContainer neurodata_type_inc: Container doc: An abstract data type for a generic container storing collections of data and metadata. Base type for all data and metadata containers. - neurodata_type_def: NWBDataInterface neurodata_type_inc: NWBContainer doc: An abstract data type for a generic container storing collections of data, as opposed to metadata. - neurodata_type_def: TimeSeries neurodata_type_inc: NWBDataInterface doc: General purpose time series. attributes: - name: description dtype: text default_value: no description doc: Description of the time series. required: false - name: comments dtype: text default_value: no comments doc: 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. required: false datasets: - name: data dims: - - num_times - - num_times - num_DIM2 - - num_times - num_DIM2 - num_DIM3 - - num_times - num_DIM2 - num_DIM3 - num_DIM4 shape: - - null - - null - null - - null - null - null - - null - null - null - null doc: Data values. Data can be in 1-D, 2-D, 3-D, or 4-D. The first dimension should always represent time. This can also be used to store binary data (e.g., image frames). This can also be a link to data stored in an external file. attributes: - name: conversion dtype: float32 default_value: 1.0 doc: Scalar to multiply each element in data to convert it to the specified 'unit'. If the data are stored in acquisition system units or other units that require a conversion to be interpretable, multiply the data by 'conversion' to convert the data to the specified 'unit'. e.g. if the data acquisition system stores values in this object as signed 16-bit integers (int16 range -32,768 to 32,767) that correspond to a 5V range (-2.5V to 2.5V), and the data acquisition system gain is 8000X, then the 'conversion' multiplier to get from raw data acquisition values to recorded volts is 2.5/32768/8000 = 9.5367e-9. required: false - name: resolution dtype: float32 default_value: -1.0 doc: Smallest meaningful difference between values in data, stored in the specified by unit, 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 -1.0. required: false - name: unit dtype: text doc: Base unit of measurement for working with the data. Actual stored values are not necessarily stored in these units. To access the data in these units, multiply 'data' by 'conversion'. - name: starting_time dtype: float64 doc: Timestamp of the first sample in seconds. When timestamps are uniformly spaced, the timestamp of the first sample can be specified and all subsequent ones calculated from the sampling rate attribute. quantity: '?' attributes: - name: rate dtype: float32 doc: Sampling rate, in Hz. - name: unit dtype: text value: seconds doc: Unit of measurement for time, which is fixed to 'seconds'. - name: timestamps dtype: float64 dims: - num_times shape: - null doc: Timestamps for samples stored in data, in seconds, relative to the common experiment master-clock stored in NWBFile.timestamps_reference_time. quantity: '?' attributes: - name: interval dtype: int32 value: 1 doc: Value is '1' - name: unit dtype: text value: seconds doc: Unit of measurement for timestamps, which is fixed to 'seconds'. - name: control dtype: uint8 dims: - num_times shape: - null doc: Numerical labels that apply to each time point in data for the purpose of querying and slicing data by these values. If present, the length of this array should be the same size as the first dimension of data. quantity: '?' - name: control_description dtype: text dims: - num_control_values shape: - null doc: Description of each control value. Must be present if control is present. If present, control_description[0] should describe time points where control == 0. quantity: '?' groups: - name: sync doc: 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. 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. quantity: '?' - neurodata_type_def: ProcessingModule neurodata_type_inc: NWBContainer doc: A collection of processed data. attributes: - name: description dtype: text doc: Description of this collection of processed data. groups: - neurodata_type_inc: NWBDataInterface doc: Data objects stored in this collection. quantity: '*' - neurodata_type_inc: DynamicTable doc: Tables stored in this collection. quantity: '*' - neurodata_type_def: Images neurodata_type_inc: NWBDataInterface default_name: Images doc: A collection of images. attributes: - name: description dtype: text doc: Description of this collection of images. datasets: - neurodata_type_inc: Image doc: Images stored in this collection. quantity: '+' pynwb-1.2.1/src/pynwb/testing/0000755000655200065520000000000013612200376017643 5ustar circlecicircleci00000000000000pynwb-1.2.1/src/pynwb/testing/make_test_files.py0000644000655200065520000000303413612200244023345 0ustar circlecicircleci00000000000000from pynwb import NWBFile, NWBHDF5IO, validate, __version__ from datetime import datetime # pynwb 1.0.2 should be installed with hdmf 1.0.3 # pynwb 1.0.3 should be installed with hdmf 1.0.5 # pynwb 1.1.0 should be installed with hdmf 1.2.0 # pynwb 1.1.1+ should be installed with an appopriate version of hdmf def _write(test_name, nwbfile): filename = 'tests/back_compat/%s_%s.nwb' % (__version__, test_name) with NWBHDF5IO(filename, 'w') as io: io.write(nwbfile) with NWBHDF5IO(filename, 'r') as io: validate(io) nwbfile = io.read() def make_nwbfile(): nwbfile = NWBFile(session_description='ADDME', identifier='ADDME', session_start_time=datetime.now().astimezone()) test_name = 'nwbfile' _write(test_name, nwbfile) def make_nwbfile_str_experimenter(): nwbfile = NWBFile(session_description='ADDME', identifier='ADDME', session_start_time=datetime.now().astimezone(), experimenter='one experimenter') test_name = 'str_experimenter' _write(test_name, nwbfile) def make_nwbfile_str_pub(): nwbfile = NWBFile(session_description='ADDME', identifier='ADDME', session_start_time=datetime.now().astimezone(), related_publications='one publication') test_name = 'str_pub' _write(test_name, nwbfile) if __name__ == '__main__': make_nwbfile() make_nwbfile_str_experimenter() make_nwbfile_str_pub() pynwb-1.2.1/src/pynwb/testing/testh5io.py0000644000655200065520000001323613612200244021760 0ustar circlecicircleci00000000000000from datetime import datetime from dateutil.tz import tzlocal, tzutc import os from abc import ABCMeta, abstractmethod import warnings from pynwb import NWBFile, NWBHDF5IO, validate as pynwb_validate from .utils import remove_test_file from hdmf.backends.warnings import BrokenLinkWarning from hdmf.build.warnings import MissingRequiredWarning, OrphanContainerWarning class NWBH5IOMixin(metaclass=ABCMeta): """ Mixin class for methods to run a roundtrip test writing an NWB file with an Container and reading the Container from the NWB file. The setUp, test_roundtrip, and tearDown methods will be run by unittest. The abstract methods setUpContainer, addContainer, and getContainer needs to be implemented by classes that include this mixin. Example: class TestMyContainerIO(NWBH5IOMixin, TestCase): def setUpContainer(self): # return a test Container to read/write def addContainer(self, nwbfile): # add the test Container to an NWB file def getContainer(self, nwbfile): # return the test Container from an NWB file This code is adapted from hdmf.testing.H5RoundTripMixin. """ def setUp(self): self.container = self.setUpContainer() self.start_time = datetime(1971, 1, 1, 12, tzinfo=tzutc()) self.create_date = datetime(2018, 4, 15, 12, tzinfo=tzlocal()) self.container_type = self.container.__class__.__name__ self.filename = 'test_%s.nwb' % self.container_type self.writer = None self.reader = None def tearDown(self): if self.writer is not None: self.writer.close() if self.reader is not None: self.reader.close() remove_test_file(self.filename) @abstractmethod def setUpContainer(self): """ Should return the test Container to read/write """ raise NotImplementedError('Cannot run test unless setUpContainer is implemented') def test_roundtrip(self): """ Test whether the test Container read from file has the same contents as the original test Container and validate the file """ self.read_container = self.roundtripContainer() self.assertIsNotNone(str(self.container)) # added as a test to make sure printing works self.assertIsNotNone(str(self.read_container)) # make sure we get a completely new object self.assertNotEqual(id(self.container), id(self.read_container)) self.assertIs(self.read_nwbfile.objects[self.container.object_id], self.read_container) self.assertContainerEqual(self.read_container, self.container) def roundtripContainer(self, cache_spec=False): """ Add the test Container to an NWBFile, write it to file, read the file, and return the test Container from the file """ description = 'a file to test writing and reading a %s' % self.container_type identifier = 'TEST_%s' % self.container_type nwbfile = NWBFile(description, identifier, self.start_time, file_create_date=self.create_date) self.addContainer(nwbfile) with warnings.catch_warnings(record=True) as ws: self.writer = NWBHDF5IO(self.filename, mode='w') self.writer.write(nwbfile, cache_spec=cache_spec) self.writer.close() self.validate() self.reader = NWBHDF5IO(self.filename, mode='r') self.read_nwbfile = self.reader.read() if ws: for w in ws: if issubclass(w.category, (MissingRequiredWarning, OrphanContainerWarning, BrokenLinkWarning)): raise Exception('%s: %s' % (w.category.__name__, w.message)) else: warnings.warn(w.message, w.category) try: return self.getContainer(self.read_nwbfile) except Exception as e: self.reader.close() self.reader = None raise e @abstractmethod def addContainer(self, nwbfile): """ Should add the test Container to the given NWBFile """ raise NotImplementedError('Cannot run test unless addContainer is implemented') @abstractmethod def getContainer(self, nwbfile): """ Should return the test Container from the given NWBFile """ raise NotImplementedError('Cannot run test unless getContainer is implemented') def validate(self): """ Validate the created file """ if os.path.exists(self.filename): with NWBHDF5IO(self.filename, mode='r') as io: errors = pynwb_validate(io) if errors: for err in errors: raise Exception(err) class AcquisitionH5IOMixin(NWBH5IOMixin): """ Mixin class for methods to run a roundtrip test writing an NWB file with an Container as an acquisition and reading the Container as an acquisition from the NWB file. The setUp, test_roundtrip, and tearDown methods will be run by unittest. The abstract method setUpContainer needs to be implemented by classes that include this mixin. Example: class TestMyContainerIO(NWBH5IOMixin, TestCase): def setUpContainer(self): # return a test Container to read/write This code is adapted from hdmf.testing.H5RoundTripMixin. """ def addContainer(self, nwbfile): ''' Add an NWBDataInterface object to the file as an acquisition ''' nwbfile.add_acquisition(self.container) def getContainer(self, nwbfile): ''' Get the NWBDataInterface object from the file ''' return nwbfile.get_acquisition(self.container.name) pynwb-1.2.1/src/pynwb/testing/__init__.py0000644000655200065520000000025213612200244021745 0ustar circlecicircleci00000000000000from hdmf.testing import TestCase, H5RoundTripMixin from .testh5io import NWBH5IOMixin, AcquisitionH5IOMixin from .utils import remove_test_file CORE_NAMESPACE = 'core' pynwb-1.2.1/src/pynwb/testing/utils.py0000644000655200065520000000070013612200244021344 0ustar circlecicircleci00000000000000import os def remove_test_file(path): """A helper function for removing intermediate test files This checks if the environment variable CLEAN_NWB has been set to False before removing the file. If CLEAN_NWB is set to False, it does not remove the file. """ clean_flag_set = os.getenv('CLEAN_NWB', True) not in ('False', 'false', 'FALSE', '0', 0, False) if os.path.exists(path) and clean_flag_set: os.remove(path) pynwb-1.2.1/src/pynwb/__init__.py0000644000655200065520000002551013612200244020274 0ustar circlecicircleci00000000000000'''This package will contain functions, classes, and objects for reading and writing data in NWB format ''' import os.path from copy import deepcopy from warnings import warn import h5py from hdmf.spec import NamespaceCatalog from hdmf.utils import docval, getargs, popargs, call_docval_func, get_docval from hdmf.backends.io import HDMFIO from hdmf.backends.hdf5 import HDF5IO as _HDF5IO from hdmf.validate import ValidatorMap from hdmf.build import BuildManager, TypeMap import hdmf.common CORE_NAMESPACE = 'core' __core_ns_file_name = 'nwb.namespace.yaml' from .spec import NWBDatasetSpec, NWBGroupSpec, NWBNamespace # noqa E402 def __get_resources(): from pkg_resources import resource_filename ret = dict() ret['namespace_path'] = os.path.join(resource_filename(__name__, 'nwb-schema/core'), __core_ns_file_name) return ret def _get_resources(): # LEGACY: Needed to support legacy implementation. return __get_resources() # a global namespace catalog global __NS_CATALOG global __TYPE_MAP __NS_CATALOG = NamespaceCatalog(NWBGroupSpec, NWBDatasetSpec, NWBNamespace) hdmf_typemap = hdmf.common.get_type_map() __NS_CATALOG.merge(hdmf_typemap.namespace_catalog) __TYPE_MAP = TypeMap(__NS_CATALOG) __TYPE_MAP.merge(hdmf_typemap) @docval({'name': 'extensions', 'type': (str, TypeMap, list), 'doc': 'a path to a namespace, a TypeMap, or a list consisting of paths to namespaces and TypeMaps', 'default': None}, returns="the namespaces loaded from the given file", rtype=tuple, is_method=False) def get_type_map(**kwargs): ''' Get a BuildManager to use for I/O using the given extensions. If no extensions are provided, return a BuildManager that uses the core namespace ''' extensions = getargs('extensions', kwargs) type_map = None if extensions is None: type_map = deepcopy(__TYPE_MAP) else: if isinstance(extensions, TypeMap): type_map = extensions else: type_map = deepcopy(__TYPE_MAP) if isinstance(extensions, list): for ext in extensions: if isinstance(ext, str): type_map.load_namespaces(ext) elif isinstance(ext, TypeMap): type_map.merge(ext) else: raise ValueError('extensions must be a list of paths to namespace specs or a TypeMaps') elif isinstance(extensions, str): type_map.load_namespaces(extensions) elif isinstance(extensions, TypeMap): type_map.merge(extensions) return type_map @docval(*get_docval(get_type_map), returns="the namespaces loaded from the given file", rtype=tuple, is_method=False) def get_manager(**kwargs): ''' Get a BuildManager to use for I/O using the given extensions. If no extensions are provided, return a BuildManager that uses the core namespace ''' type_map = call_docval_func(get_type_map, kwargs) return BuildManager(type_map) @docval({'name': 'namespace_path', 'type': str, 'doc': 'the path to the YAML with the namespace definition'}, returns="the namespaces loaded from the given file", rtype=tuple, is_method=False) def load_namespaces(**kwargs): ''' Load namespaces from file ''' namespace_path = getargs('namespace_path', kwargs) return __TYPE_MAP.load_namespaces(namespace_path) # load the core namespace i.e. base NWB specification __resources = __get_resources() if os.path.exists(__resources['namespace_path']): load_namespaces(__resources['namespace_path']) def available_namespaces(): """Returns all namespaces registered in the namespace catalog""" return __NS_CATALOG.namespaces # a function to register a container classes with the global map @docval({'name': 'neurodata_type', 'type': str, 'doc': 'the neurodata_type to get the spec for'}, {'name': 'namespace', 'type': str, 'doc': 'the name of the namespace'}, {"name": "container_cls", "type": type, "doc": "the class to map to the specified neurodata_type", 'default': None}, is_method=False) def register_class(**kwargs): """Register an NWBContainer class to use for reading and writing a neurodata_type from a specification If container_cls is not specified, returns a decorator for registering an NWBContainer subclass as the class for neurodata_type in namespace. """ neurodata_type, namespace, container_cls = getargs('neurodata_type', 'namespace', 'container_cls', kwargs) def _dec(cls): __TYPE_MAP.register_container_type(namespace, neurodata_type, cls) return cls if container_cls is None: return _dec else: _dec(container_cls) # a function to register an object mapper for a container class @docval({"name": "container_cls", "type": type, "doc": "the Container class for which the given ObjectMapper class gets used"}, {"name": "mapper_cls", "type": type, "doc": "the ObjectMapper class to use to map", 'default': None}, is_method=False) def register_map(**kwargs): """Register an ObjectMapper to use for a Container class type If mapper_cls is not specified, returns a decorator for registering an ObjectMapper class as the mapper for container_cls. If mapper_cls is specified, register the class as the mapper for container_cls """ container_cls, mapper_cls = getargs('container_cls', 'mapper_cls', kwargs) def _dec(cls): __TYPE_MAP.register_map(container_cls, cls) return cls if mapper_cls is None: return _dec else: _dec(mapper_cls) @docval({'name': 'neurodata_type', 'type': str, 'doc': 'the neurodata_type to get the NWBContainer class for'}, {'name': 'namespace', 'type': str, 'doc': 'the namespace the neurodata_type is defined in'}, is_method=False) def get_class(**kwargs): """ Parse the YAML file for a given neurodata_type that is a subclass of NWBContainer and automatically generate its python API. This will work for most containers, but is known to not work for descendants of MultiContainerInterface and DynamicTable, so these must be defined manually (for now). `get_class` infers the API mapping directly from the specification. If you want to define a custom mapping, you should not use this function and you should define the class manually. Examples -------- Generating and registering an extension is as simple as:: MyClass = get_class('MyClass', 'ndx-my-extension') `get_class` defines only the `__init__` for the class. In cases where you want to provide additional methods for querying, plotting, etc. you can still use `get_class` and attach methods to the class after-the-fact, e.g.:: def get_sum(self, a, b): return self.feat1 + self.feat2 MyClass.get_sum = get_sum """ neurodata_type, namespace = getargs('neurodata_type', 'namespace', kwargs) return __TYPE_MAP.get_container_cls(namespace, neurodata_type) @docval({'name': 'io', 'type': HDMFIO, 'doc': 'the HDMFIO object to read from'}, {'name': 'namespace', 'type': str, 'doc': 'the namespace to validate against', 'default': CORE_NAMESPACE}, returns="errors in the file", rtype=list, is_method=False) def validate(**kwargs): """Validate an NWB file against a namespace""" io, namespace = getargs('io', 'namespace', kwargs) builder = io.read_builder() validator = ValidatorMap(io.manager.namespace_catalog.get_namespace(name=namespace)) return validator.validate(builder) class NWBHDF5IO(_HDF5IO): @docval({'name': 'path', 'type': str, 'doc': 'the path to the HDF5 file'}, {'name': 'mode', 'type': str, 'doc': 'the mode to open the HDF5 file with, one of ("w", "r", "r+", "a", "w-", "x")'}, {'name': 'load_namespaces', 'type': bool, 'doc': 'whether or not to load cached namespaces from given path - not applicable in write mode', 'default': False}, {'name': 'manager', 'type': BuildManager, 'doc': 'the BuildManager to use for I/O', 'default': None}, {'name': 'extensions', 'type': (str, TypeMap, list), 'doc': 'a path to a namespace, a TypeMap, or a list consisting paths to namespaces and TypeMaps', 'default': None}, {'name': 'file', 'type': h5py.File, 'doc': 'a pre-existing h5py.File object', 'default': None}, {'name': 'comm', 'type': "Intracomm", 'doc': 'the MPI communicator to use for parallel I/O', 'default': None}) def __init__(self, **kwargs): path, mode, manager, extensions, load_namespaces, file_obj, comm =\ popargs('path', 'mode', 'manager', 'extensions', 'load_namespaces', 'file', 'comm', kwargs) if load_namespaces: if manager is not None: warn("loading namespaces from file - ignoring 'manager'") if extensions is not None: warn("loading namespaces from file - ignoring 'extensions' argument") # namespaces are not loaded when creating an NWBHDF5IO object in write mode if 'w' in mode or mode == 'x': raise ValueError("cannot load namespaces from file when writing to it") tm = get_type_map() super(NWBHDF5IO, self).load_namespaces(tm, path) manager = BuildManager(tm) # XXX: Leaving this here in case we want to revert to this strategy for # loading cached namespaces # ns_catalog = NamespaceCatalog(NWBGroupSpec, NWBDatasetSpec, NWBNamespace) # super(NWBHDF5IO, self).load_namespaces(ns_catalog, path) # tm = TypeMap(ns_catalog) # tm.copy_mappers(get_type_map()) else: if manager is not None and extensions is not None: raise ValueError("'manager' and 'extensions' cannot be specified together") elif extensions is not None: manager = get_manager(extensions=extensions) elif manager is None: manager = get_manager() super(NWBHDF5IO, self).__init__(path, manager=manager, mode=mode, file=file_obj, comm=comm) from . import io as __io # noqa: F401,E402 from .core import NWBContainer, NWBData # noqa: F401,E402 from .base import TimeSeries, ProcessingModule # noqa: F401,E402 from .file import NWBFile # noqa: F401,E402 from . import behavior # noqa: F401,E402 from . import device # noqa: F401,E402 from . import ecephys # noqa: F401,E402 from . import epoch # noqa: F401,E402 from . import icephys # noqa: F401,E402 from . import image # noqa: F401,E402 from . import misc # noqa: F401,E402 from . import ogen # noqa: F401,E402 from . import ophys # noqa: F401,E402 from . import retinotopy # noqa: F401,E402 from . import legacy # noqa: F401,E402 from ._version import get_versions # noqa: E402 __version__ = get_versions()['version'] del get_versions pynwb-1.2.1/src/pynwb/behavior.py0000644000655200065520000001337213612200244020337 0ustar circlecicircleci00000000000000from hdmf.utils import docval, popargs, get_docval from . import register_class, CORE_NAMESPACE from .core import MultiContainerInterface from .misc import IntervalSeries from .base import TimeSeries @register_class('SpatialSeries', CORE_NAMESPACE) class SpatialSeries(TimeSeries): """ Direction, e.g., of gaze or travel, or position. The TimeSeries::data field is a 2D array storing position or direction relative to some reference frame. Array structure: [num measurements] [num dimensions]. Each SpatialSeries has a text dataset reference_frame that indicates the zero-position, or the zero-axes for direction. For example, if representing gaze direction, "straight-ahead" might be a specific pixel on the monitor, or some other point in space. For position data, the 0,0 point might be the top-left corner of an enclosure, as viewed from the tracking camera. The unit of data will indicate how to interpret SpatialSeries values. """ __nwbfields__ = ('reference_frame',) @docval(*get_docval(TimeSeries.__init__, 'name'), # required {'name': 'data', 'type': ('array_data', 'data', TimeSeries), 'shape': ((None, ), (None, None)), # required 'doc': 'The data this TimeSeries dataset stores. Can also store binary data e.g. image frames'}, {'name': 'reference_frame', 'type': str, # required 'doc': 'description defining what the zero-position is'}, *get_docval(TimeSeries.__init__, 'conversion', 'resolution', 'timestamps', 'starting_time', 'rate', 'comments', 'description', 'control', 'control_description')) def __init__(self, **kwargs): """ Create a SpatialSeries TimeSeries dataset """ name, data, reference_frame = popargs('name', 'data', 'reference_frame', kwargs) super(SpatialSeries, self).__init__(name, data, 'meters', **kwargs) self.reference_frame = reference_frame @register_class('BehavioralEpochs', CORE_NAMESPACE) class BehavioralEpochs(MultiContainerInterface): """ TimeSeries for storing behavoioral epochs. The objective of this and the other two Behavioral interfaces (e.g. BehavioralEvents and BehavioralTimeSeries) is to provide generic hooks for software tools/scripts. This allows a tool/script to take the output one specific interface (e.g., UnitTimes) and plot that data relative to another data modality (e.g., behavioral events) without having to define all possible modalities in advance. Declaring one of these interfaces means that one or more TimeSeries of the specified type is published. These TimeSeries should reside in a group having the same name as the interface. For example, if a BehavioralTimeSeries interface is declared, the module will have one or more TimeSeries defined in the module sub-group "BehavioralTimeSeries". BehavioralEpochs should use IntervalSeries. BehavioralEvents is used for irregular events. BehavioralTimeSeries is for continuous data. """ __clsconf__ = { 'add': 'add_interval_series', 'get': 'get_interval_series', 'create': 'create_interval_series', 'type': IntervalSeries, 'attr': 'interval_series' } @register_class('BehavioralEvents', CORE_NAMESPACE) class BehavioralEvents(MultiContainerInterface): """ TimeSeries for storing behavioral events. See description of BehavioralEpochs for more details. """ __clsconf__ = { 'add': 'add_timeseries', 'get': 'get_timeseries', 'create': 'create_timeseries', 'type': TimeSeries, 'attr': 'time_series' } @register_class('BehavioralTimeSeries', CORE_NAMESPACE) class BehavioralTimeSeries(MultiContainerInterface): """ TimeSeries for storing Behavoioral time series data. See description of BehavioralEpochs for more details. """ __clsconf__ = { 'add': 'add_timeseries', 'get': 'get_timeseries', 'create': 'create_timeseries', 'type': TimeSeries, 'attr': 'time_series' } @register_class('PupilTracking', CORE_NAMESPACE) class PupilTracking(MultiContainerInterface): """ Eye-tracking data, representing pupil size. """ __clsconf__ = { 'add': 'add_timeseries', 'get': 'get_timeseries', 'create': 'create_timeseries', 'type': TimeSeries, 'attr': 'time_series' } @register_class('EyeTracking', CORE_NAMESPACE) class EyeTracking(MultiContainerInterface): """ Eye-tracking data, representing direction of gaze. """ __clsconf__ = { 'add': 'add_spatial_series', 'get': 'get_spatial_series', 'create': 'create_spatial_series', 'type': SpatialSeries, 'attr': 'spatial_series' } @register_class('CompassDirection', CORE_NAMESPACE) class CompassDirection(MultiContainerInterface): """ With a CompassDirection interface, a module publishes a SpatialSeries object representing a floating point value for theta. The SpatialSeries::reference_frame field should indicate what direction corresponds to 0 and which is the direction of rotation (this should be clockwise). The si_unit for the SpatialSeries should be radians or degrees. """ __clsconf__ = { 'add': 'add_spatial_series', 'get': 'get_spatial_series', 'create': 'create_spatial_series', 'type': SpatialSeries, 'attr': 'spatial_series' } @register_class('Position', CORE_NAMESPACE) class Position(MultiContainerInterface): """ Position data, whether along the x, x/y or x/y/z axis. """ __clsconf__ = { 'add': 'add_spatial_series', 'get': 'get_spatial_series', 'create': 'create_spatial_series', 'type': SpatialSeries, 'attr': 'spatial_series' } pynwb-1.2.1/src/pynwb/retinotopy.py0000644000655200065520000001370413612200244020753 0ustar circlecicircleci00000000000000from collections.abc import Iterable from hdmf.utils import docval, popargs, call_docval_func from . import register_class, CORE_NAMESPACE from .core import NWBContainer, NWBDataInterface class AImage(NWBContainer): """ """ __nwbfields__ = ('data', 'bits_per_pixel', 'dimension', 'format', 'field_of_view', 'focal_depth') @docval({'name': 'name', 'type': str, 'doc': 'the name of this axis map'}, {'name': 'data', 'type': Iterable, 'doc': 'Data field.'}, {'name': 'bits_per_pixel', 'type': int, 'doc': 'Number of bits used to represent each value. This is necessary to determine maximum ' '(white) pixel value.'}, {'name': 'dimension', 'type': Iterable, 'doc': 'Number of rows and columns in the image.'}, {'name': 'format', 'type': Iterable, 'doc': 'Format of image. Right now only "raw" supported.'}, {'name': 'field_of_view', 'type': Iterable, 'doc': 'Size of viewing area, in meters.'}, {'name': 'focal_depth', 'type': 'float', 'doc': 'Focal depth offset, in meters.'}) def __init__(self, **kwargs): data, bits_per_pixel, dimension, format, field_of_view = popargs( 'data', 'bits_per_pixel', 'dimension', 'format', 'field_of_view', kwargs) call_docval_func(super(AImage, self).__init__, kwargs) self.data = data self.bits_per_pixel = bits_per_pixel self.dimension = format self.field_of_view = field_of_view class AxisMap(NWBContainer): """ """ __nwbfields__ = ('data', 'field_of_view', 'unit', 'dimension') @docval({'name': 'name', 'type': str, 'doc': 'the name of this axis map'}, {'name': 'data', 'type': Iterable, 'shape': (None, None), 'doc': 'data field.'}, {'name': 'field_of_view', 'type': Iterable, 'doc': 'Size of viewing area, in meters.'}, {'name': 'unit', 'type': str, 'doc': 'Unit that axis data is stored in (e.g., degrees)'}, {'name': 'dimension', 'type': Iterable, 'shape': (None, ), 'doc': 'Number of rows and columns in the image'}) def __init__(self, **kwargs): data, field_of_view, unit, dimension = popargs('data', 'field_of_view', 'unit', 'dimension', kwargs) call_docval_func(super(AxisMap, self).__init__, kwargs) self.data = data self.field_of_view = field_of_view self.unit = unit self.dimension = dimension @register_class('ImagingRetinotopy', CORE_NAMESPACE) class ImagingRetinotopy(NWBDataInterface): """ Intrinsic signal optical imaging or widefield imaging for measuring retinotopy. Stores orthogonal maps (e.g., altitude/azimuth; radius/theta) of responses to specific stimuli and a combined polarity map from which to identify visual areas. Note: for data consistency, all images and arrays are stored in the format [row][column] and [row, col], which equates to [y][x]. Field of view and dimension arrays may appear backward (i.e., y before x). """ __nwbfields__ = ('sign_map', 'axis_1_phase_map', 'axis_1_power_map', 'axis_2_phase_map', 'axis_2_power_map', 'axis_descriptions', 'focal_depth_image', 'vasculature_image',) @docval({'name': 'sign_map', 'type': AxisMap, 'doc': 'Sine of the angle between the direction of the gradient in axis_1 and axis_2.'}, {'name': 'axis_1_phase_map', 'type': AxisMap, 'doc': 'Phase response to stimulus on the first measured axis.'}, {'name': 'axis_1_power_map', 'type': AxisMap, 'doc': 'Power response on the first measured axis. Response is scaled so 0.0 is no power in ' 'the response and 1.0 is maximum relative power.'}, {'name': 'axis_2_phase_map', 'type': AxisMap, 'doc': 'Phase response to stimulus on the second measured axis.'}, {'name': 'axis_2_power_map', 'type': AxisMap, 'doc': 'Power response on the second measured axis. Response is scaled so 0.0 is no ' 'power in the response and 1.0 is maximum relative power.'}, {'name': 'axis_descriptions', 'type': Iterable, 'doc': 'Two-element array describing the contents of the two response axis fields. ' 'Description should be something like ["altitude", "azimuth"] or ["radius", "theta"].'}, {'name': 'focal_depth_image', 'type': AImage, 'doc': 'Gray-scale image taken with same settings/parameters (e.g., focal depth, wavelength) ' 'as data collection. Array format: [rows][columns].'}, {'name': 'vasculature_image', 'type': AImage, 'doc': 'Gray-scale anatomical image of cortical surface. Array structure: [rows][columns].'}, {'name': 'name', 'type': str, 'doc': 'the name of this container', 'default': 'ImagingRetinotopy'}) def __init__(self, **kwargs): axis_1_phase_map, axis_1_power_map, axis_2_phase_map, axis_2_power_map, axis_descriptions, \ focal_depth_image, sign_map, vasculature_image = popargs( 'axis_1_phase_map', 'axis_1_power_map', 'axis_2_phase_map', 'axis_2_power_map', 'axis_descriptions', 'focal_depth_image', 'sign_map', 'vasculature_image', kwargs) call_docval_func(super(ImagingRetinotopy, self).__init__, kwargs) self.axis_1_phase_map = axis_1_phase_map self.axis_1_power_map = axis_1_power_map self.axis_2_phase_map = axis_2_phase_map self.axis_2_power_map = axis_2_power_map self.axis_descriptions = axis_descriptions self.focal_depth_image = focal_depth_image self.sign_map = sign_map self.vasculature_image = vasculature_image pynwb-1.2.1/src/pynwb/base.py0000644000655200065520000002531613612200244017453 0ustar circlecicircleci00000000000000from warnings import warn from collections.abc import Iterable from hdmf.utils import docval, getargs, popargs, call_docval_func from hdmf.common import DynamicTable from . import register_class, CORE_NAMESPACE from .core import NWBDataInterface, MultiContainerInterface, NWBData @register_class('ProcessingModule', CORE_NAMESPACE) class ProcessingModule(MultiContainerInterface): """ Processing module. This is a container for one or more containers that provide data at intermediate levels of analysis ProcessingModules should be created through calls to NWB.create_module(). They should not be instantiated directly """ __nwbfields__ = ('description',) __clsconf__ = { 'attr': 'data_interfaces', 'add': 'add', 'type': (NWBDataInterface, DynamicTable), 'get': 'get' } @docval({'name': 'name', 'type': str, 'doc': 'The name of this processing module'}, {'name': 'description', 'type': str, 'doc': 'Description of this processing module'}, {'name': 'data_interfaces', 'type': (list, tuple, dict), 'doc': 'NWBDataInterfacess that belong to this ProcessingModule', 'default': None}) def __init__(self, **kwargs): call_docval_func(super(ProcessingModule, self).__init__, kwargs) self.description = popargs('description', kwargs) self.data_interfaces = popargs('data_interfaces', kwargs) @property def containers(self): return self.data_interfaces def __getitem__(self, arg): return self.get(arg) @docval({'name': 'container', 'type': (NWBDataInterface, DynamicTable), 'doc': 'the NWBDataInterface to add to this Module'}) def add_container(self, **kwargs): ''' Add an NWBContainer to this ProcessingModule ''' container = getargs('container', kwargs) warn(PendingDeprecationWarning('add_container will be replaced by add')) self.add(container) @docval({'name': 'container_name', 'type': str, 'doc': 'the name of the NWBContainer to retrieve'}) def get_container(self, **kwargs): ''' Retrieve an NWBContainer from this ProcessingModule ''' container_name = getargs('container_name', kwargs) warn(PendingDeprecationWarning('get_container will be replaced by get')) return self.get(container_name) @docval({'name': 'NWBDataInterface', 'type': (NWBDataInterface, DynamicTable), 'doc': 'the NWBDataInterface to add to this Module'}) def add_data_interface(self, **kwargs): NWBDataInterface = getargs('NWBDataInterface', kwargs) warn(PendingDeprecationWarning('add_data_interface will be replaced by add')) self.add(NWBDataInterface) @docval({'name': 'data_interface_name', 'type': str, 'doc': 'the name of the NWBContainer to retrieve'}) def get_data_interface(self, **kwargs): data_interface_name = getargs('data_interface_name', kwargs) warn(PendingDeprecationWarning('get_data_interface will be replaced by get')) return self.get(data_interface_name) @register_class('TimeSeries', CORE_NAMESPACE) class TimeSeries(NWBDataInterface): """A generic base class for time series data""" __nwbfields__ = ("comments", "description", "data", "resolution", "conversion", "unit", "timestamps", "timestamps_unit", "interval", "starting_time", "rate", "starting_time_unit", "control", "control_description") __time_unit = "seconds" @docval({'name': 'name', 'type': str, 'doc': 'The name of this TimeSeries dataset'}, # required {'name': 'data', 'type': ('array_data', 'data', 'TimeSeries'), 'doc': 'The data this TimeSeries dataset stores. Can also store binary data e.g. image frames', 'default': None}, {'name': 'unit', 'type': str, 'doc': 'The base unit of measurement (should be SI unit)', 'default': None}, {'name': 'resolution', 'type': (str, 'float'), 'doc': 'The smallest meaningful difference (in specified unit) between values in data', 'default': -1.0}, {'name': 'conversion', 'type': (str, 'float'), 'doc': 'Scalar to multiply each element in data to convert it to the specified unit', 'default': 1.0}, {'name': 'timestamps', 'type': ('array_data', 'data', 'TimeSeries'), 'shape': (None,), 'doc': 'Timestamps for samples stored in data', 'default': None}, {'name': 'starting_time', 'type': 'float', 'doc': 'The timestamp of the first sample', 'default': None}, {'name': 'rate', 'type': 'float', 'doc': 'Sampling rate in Hz', 'default': None}, {'name': 'comments', 'type': str, 'doc': 'Human-readable comments about this TimeSeries dataset', 'default': 'no comments'}, {'name': 'description', 'type': str, 'doc': 'Description of this TimeSeries dataset', 'default': 'no description'}, {'name': 'control', 'type': Iterable, 'doc': 'Numerical labels that apply to each element in data', 'default': None}, {'name': 'control_description', 'type': Iterable, 'doc': 'Description of each control value', 'default': None}) def __init__(self, **kwargs): """Create a TimeSeries object """ call_docval_func(super(TimeSeries, self).__init__, kwargs) keys = ("resolution", "comments", "description", "conversion", "unit", "control", "control_description") for key in keys: val = kwargs.get(key) if val is not None: setattr(self, key, val) data = getargs('data', kwargs) self.fields['data'] = data timestamps = kwargs.get('timestamps') starting_time = kwargs.get('starting_time') rate = kwargs.get('rate') if timestamps is not None: if rate is not None: raise ValueError('Specifying rate and timestamps is not supported.') if starting_time is not None: raise ValueError('Specifying starting_time and timestamps is not supported.') self.fields['timestamps'] = timestamps self.timestamps_unit = self.__time_unit self.interval = 1 if isinstance(timestamps, TimeSeries): timestamps.__add_link('timestamp_link', self) elif rate is not None: self.rate = rate if starting_time is not None: self.starting_time = starting_time else: self.starting_time = 0.0 self.starting_time_unit = self.__time_unit else: raise TypeError("either 'timestamps' or 'rate' must be specified") @property def num_samples(self): ''' Tries to return the number of data samples. If this cannot be assessed, returns None. ''' def unreadable_warning(attr): return ( 'The {} attribute on this TimeSeries (named: {}) has a __len__, ' 'but it cannot be read'.format(attr, self.name) ) def no_len_warning(attr): return 'The {} attribute on this TimeSeries (named: {}) has no __len__'.format(attr, self.name) if hasattr(self.data, '__len__'): try: return len(self.data) # for an ndarray this will return the first element of shape except TypeError: warn(unreadable_warning('data'), UserWarning) else: warn(no_len_warning('data'), UserWarning) if hasattr(self, 'timestamps'): if hasattr(self.timestamps, '__len__'): try: return len(self.timestamps) except TypeError: warn(unreadable_warning('timestamps'), UserWarning) elif not (hasattr(self, 'rate') and hasattr(self, 'starting_time')): warn(no_len_warning('timestamps'), UserWarning) @property def data(self): if isinstance(self.fields['data'], TimeSeries): return self.fields['data'].data else: return self.fields['data'] @property def data_link(self): return self.__get_links('data_link') @property def timestamps(self): if 'timestamps' not in self.fields: return None if isinstance(self.fields['timestamps'], TimeSeries): return self.fields['timestamps'].timestamps else: return self.fields['timestamps'] @property def timestamp_link(self): return self.__get_links('timestamp_link') def __get_links(self, links): ret = self.fields.get(links, list()) if ret is not None: ret = set(ret) return ret def __add_link(self, links_key, link): self.fields.setdefault(links_key, list()).append(link) @property def time_unit(self): return self.__time_unit @register_class('Image', CORE_NAMESPACE) class Image(NWBData): __nwbfields__ = ('data', 'resolution', 'description') @docval({'name': 'name', 'type': str, 'doc': 'The name of this TimeSeries dataset'}, {'name': 'data', 'type': ('array_data', 'data'), 'doc': 'data of image', 'shape': ((None, None), (None, None, 3), (None, None, 4))}, {'name': 'resolution', 'type': 'float', 'doc': 'pixels / cm', 'default': None}, {'name': 'description', 'type': str, 'doc': 'description of image', 'default': None}) def __init__(self, **kwargs): call_docval_func(super(Image, self).__init__, kwargs) self.resolution = kwargs['resolution'] self.description = kwargs['description'] @register_class('Images', CORE_NAMESPACE) class Images(MultiContainerInterface): __nwbfields__ = ('description',) __clsconf__ = { 'attr': 'images', 'add': 'add_image', 'type': Image, 'get': 'get_image', 'create': 'create_image' } @docval({'name': 'name', 'type': str, 'doc': 'The name of this set of images'}, {'name': 'images', 'type': 'array_data', 'doc': 'image objects', 'default': None}, {'name': 'description', 'type': str, 'doc': 'description of images', 'default': 'no description'}) def __init__(self, **kwargs): name, description, images = popargs('name', 'description', 'images', kwargs) super(Images, self).__init__(name, **kwargs) self.description = description self.images = images pynwb-1.2.1/src/pynwb/legacy/0000755000655200065520000000000013612200376017432 5ustar circlecicircleci00000000000000pynwb-1.2.1/src/pynwb/legacy/__init__.py0000644000655200065520000000252113612200244021535 0ustar circlecicircleci00000000000000from hdmf.utils import docval, getargs from .. import get_type_map, NWBContainer from .map import ObjectMapperLegacy as ObjectMapper __TYPE_MAP = get_type_map() # Register new ObjectMapper with the new TypeMap: __TYPE_MAP.register_map(NWBContainer, ObjectMapper) def get_type_map(**kwargs): """ Get a TypeMap to use for I/O for Allen Institute Brain Observatory files (NWB v1.0.6) """ return __TYPE_MAP # a function to register an object mapper for a container class @docval({"name": "container_cls", "type": type, "doc": "the Container class for which the given ObjectMapper class gets used for"}, {"name": "mapper_cls", "type": type, "doc": "the ObjectMapper class to use to map", 'default': None}, is_method=False) def register_map(**kwargs): """Register an ObjectMapper to use for a Container class type If mapper_cls is not specified, returns a decorator for registering an ObjectMapper class as the mapper for container_cls. If mapper_cls specified, register the class as the mapper for container_cls """ container_cls, mapper_cls = getargs('container_cls', 'mapper_cls', kwargs) def _dec(cls): __TYPE_MAP.register_map(container_cls, cls) return cls if mapper_cls is None: return _dec else: _dec(mapper_cls) from . import io # noqa: F401 pynwb-1.2.1/src/pynwb/legacy/map.py0000644000655200065520000001353213612200244020557 0ustar circlecicircleci00000000000000 from hdmf.build import ObjectMapper, TypeMap from hdmf.build.builders import GroupBuilder def decode(val): if isinstance(val, bytes): return val.decode('UTF-8') else: return val class ObjectMapperLegacy(ObjectMapper): @ObjectMapper.constructor_arg('source') def source_gettr(self, builder, manager): if 'source' in builder.attributes: return builder.attributes['source'] else: return 'No known source' class TypeMapLegacy(TypeMap): def get_builder_dt(self, builder): # noqa: C901 ''' For a given builder, return the neurodata_type. In this legacy TypeMap, the builder may have out-of-spec neurodata_type; this function coerces this to a 2.0 compatible version. ''' if builder.name == 'root': return 'NWBFile' elif builder.name == 'subject' and builder.parent.name == 'general': return 'Subject' else: attrs = builder.attributes ndt = attrs.get('neurodata_type') if ndt == 'Module': return 'ProcessingModule' elif ndt == 'Interface': return builder.name elif ndt == 'Epoch': return 'Epoch' elif ndt == 'TimeSeries': ancestry = decode(attrs['ancestry'][-1]) if ancestry == 'TwoPhotonSeries' and decode(builder.name) == 'corrected': return 'ImageSeries' else: return ancestry elif ndt == 'Custom': parent_ndt = self.get_builder_dt(builder.parent) if parent_ndt == 'ImageSegmentation' and builder.name in ('roi_ids', 'cell_specimen_ids'): return None elif parent_ndt == 'PlaneSegmentation' and builder.name in ('roi_list', 'imaging_plane_name'): return None elif parent_ndt == 'IntervalSeries' and builder.name in ('frame_duration',): return None elif parent_ndt == 'TimeSeries' and builder.name in ('feature_description', 'bits_per_pixel', 'dimension', 'field_of_view', 'format'): return None elif parent_ndt == 'ImagingPlane' and builder.parent.name in ('imaging_plane_1',): return None elif parent_ndt == 'AbstractFeatureSeries' and builder.name in ('frame_duration',): return None elif parent_ndt == 'IndexSeries' and builder.name in ('frame_duration',): return None elif builder.parent.name == 'general': return None elif parent_ndt == 'RoiResponseSeries' and builder.name in ('r', 'neuropil_traces_path', 'rmse', 'comments'): return None elif parent_ndt == 'SpatialSeries' and builder.name in ('features'): return None else: raise RuntimeError(('Unable to determine neurodata_type: attrs["neurodata_type"]: "Custom",' 'parent.neurodata_type: %s' % parent_ndt)) else: parent_ndt = self.get_builder_dt(builder.parent) if parent_ndt == 'Epoch': return 'EpochTimeSeries' elif parent_ndt == 'MotionCorrection': return 'CorrectedImageStack' elif parent_ndt == 'ImagingPlane' and isinstance(builder, GroupBuilder): return 'OpticalChannel' elif parent_ndt == 'ImageSegmentation': return 'PlaneSegmentation' elif parent_ndt == 'PlaneSegmentation': if builder.name in ('roi_list', 'imaging_plane_name'): return None else: return 'ROI' else: parent_names = { 'extracellular_ephys': 'ElectrodeGroup', 'intracellular_ephys': 'IntracellularElectrodeGroup', 'optophysiology': 'ImagingPlane', 'optogenetics': 'OptogeneticStimulusSite', 'root': None, 'xy_translation': None, 'imaging_plane_1': None, 'running_speed': None, 'general': None, '2p_image_series': None, 'natural_movie_one_stimulus': None, 'natural_scenes_stimulus': None, 'devices': None, 'spontaneous_stimulus': None, 'static_gratings_stimulus': None, 'maximum_intensity_projection_image': None, 'imaging_plane_1_neuropil_response': None, 'imaging_plane_1_demixed_signal': None, 'corrected': None, 'running_speed_index': None, 'pupil_size_index': None, 'pupil_size': None, 'pupil_location': None, 'pupil_location_spherical': None } return decode(parent_names.get(builder.parent.name)) def get_builder_ns(self, builder): return 'core' pynwb-1.2.1/src/pynwb/legacy/io/0000755000655200065520000000000013612200376020041 5ustar circlecicircleci00000000000000pynwb-1.2.1/src/pynwb/legacy/io/image.py0000644000655200065520000000052713612200244021473 0ustar circlecicircleci00000000000000import numpy as np from pynwb.image import ImageSeries from .. import ObjectMapper, register_map @register_map(ImageSeries) class ImageSeriesMap(ObjectMapper): @ObjectMapper.constructor_arg('data') def carg_data(self, *args): builder = args[0] if builder.name in ('corrected',): return np.array([-1.]) pynwb-1.2.1/src/pynwb/legacy/io/file.py0000644000655200065520000000330613612200244021326 0ustar circlecicircleci00000000000000 from pynwb.file import NWBFile from .. import ObjectMapper, register_map @register_map(NWBFile) class NWBFileMap(ObjectMapper): def __init__(self, spec): super(NWBFileMap, self).__init__(spec) raw_ts_spec = self.spec.get_group('acquisition').get_neurodata_type('NWBDataInterface') self.map_spec('acquisition', raw_ts_spec) stimulus_spec = self.spec.get_group('stimulus') presentation_ts_spec = stimulus_spec.get_group('presentation').get_neurodata_type('TimeSeries') self.map_spec('stimulus', presentation_ts_spec) stimulus_ts_spec = stimulus_spec.get_group('templates').get_neurodata_type('TimeSeries') self.map_spec('stimulus_template', stimulus_ts_spec) epochs_spec = self.spec.get_group('epochs') self.map_spec('epochs', epochs_spec.get_neurodata_type('Epoch')) general_spec = self.spec.get_group('general') self.map_spec( 'ic_electrodes', general_spec.get_group('intracellular_ephys').get_neurodata_type('IntracellularElectrode')) self.map_spec( 'ec_electrodes', general_spec.get_group('extracellular_ephys').get_neurodata_type('ElectrodeGroup')) self.map_spec( 'optogenetic_sites', general_spec.get_group('optogenetics').get_neurodata_type('OptogeneticStimulusSite')) self.map_spec( 'imaging_planes', general_spec.get_group('optophysiology').get_neurodata_type('ImagingPlane')) self.map_spec('modules', self.spec.get_group('processing').get_neurodata_type('ProcessingModule')) self.unmap(general_spec.get_dataset('stimulus')) @ObjectMapper.constructor_arg('file_name') def name(self, builder): return builder.name pynwb-1.2.1/src/pynwb/legacy/io/epoch.py0000644000655200065520000000162313612200244021505 0ustar circlecicircleci00000000000000# from pynwb.epoch import Epochs, EpochTimeSeries from .. import ObjectMapper # from .. import register_map # @register_map(Epoch) class EpochMap(ObjectMapper): def __init__(self, spec): super(EpochMap, self).__init__(spec) start_spec = self.spec.get_dataset('start_time') stop_spec = self.spec.get_dataset('stop_time') self.map_const_arg('start', start_spec) self.map_const_arg('stop', stop_spec) epts_spec = self.spec.get_neurodata_type('EpochTimeSeries') self.map_spec('timeseries', epts_spec) @ObjectMapper.constructor_arg('name') def name(self, builder): return builder.name # @register_map(EpochTimeSeries) class EpochTimeSeriesMap(ObjectMapper): def __init__(self, spec): super(EpochTimeSeriesMap, self).__init__(spec) ts_spec = self.spec.get_link('timeseries') self.map_const_arg('ts', ts_spec) pynwb-1.2.1/src/pynwb/legacy/io/__init__.py0000644000655200065520000000054513612200244022150 0ustar circlecicircleci00000000000000from . import base as __base from . import behavior as __behavior from . import ecephys as __ecephys from . import epoch as __epoch from . import file as __file from . import icephys as __icephys from . import image as __image from . import misc as __misc from . import ogen as __ogen from . import ophys as __ophys from . import retinotopy as __retinotopy pynwb-1.2.1/src/pynwb/legacy/io/behavior.py0000644000655200065520000000235413612200244022210 0ustar circlecicircleci00000000000000from pynwb.behavior import BehavioralTimeSeries, PupilTracking from pynwb.image import IndexSeries from .. import ObjectMapper, register_map @register_map(BehavioralTimeSeries) class BehavioralTimeSeriesMap(ObjectMapper): @ObjectMapper.constructor_arg('time_series') def carg_time_series(self, *args): builder = args[0] manager = args[1] subspecs = self.hack_get_subspec_values(builder, self.spec, manager) for subspec, value in subspecs.items(): const_arg = self.get_const_arg(subspec) if const_arg == 'time_series': for x in value: if not isinstance(x, IndexSeries): return x @register_map(PupilTracking) class PupilTrackingMap(ObjectMapper): @ObjectMapper.constructor_arg('time_series') def carg_time_series(self, *args): builder = args[0] manager = args[1] subspecs = self.hack_get_subspec_values(builder, self.spec, manager) for subspec, value in subspecs.items(): const_arg = self.get_const_arg(subspec) if const_arg == 'time_series': for x in value: if not isinstance(x, IndexSeries): return x pynwb-1.2.1/src/pynwb/legacy/io/retinotopy.py0000644000655200065520000000000013612200244022607 0ustar circlecicircleci00000000000000pynwb-1.2.1/src/pynwb/legacy/io/base.py0000644000655200065520000000520313612200244021317 0ustar circlecicircleci00000000000000from pynwb.base import TimeSeries, ProcessingModule from .. import ObjectMapper, register_map legacy_TimeSeries_missing_time_info_name_list = ('natural_movie_one_image_stack', 'natural_movie_two_image_stack', 'natural_movie_three_image_stack', 'natural_scenes_image_stack', 'locally_sparse_noise_image_stack', 'locally_sparse_noise_8deg_image_stack', 'locally_sparse_noise_4deg_image_stack') @register_map(ProcessingModule) class ModuleMap(ObjectMapper): def __init__(self, spec): super(ModuleMap, self).__init__(spec) containers_spec = self.spec.get_neurodata_type('NWBDataInterface') self.map_spec('containers', containers_spec) @ObjectMapper.constructor_arg('name') def name(self, *args): builder = args[0] return builder.name @ObjectMapper.constructor_arg('description') def carg_description(self, *args): return 'Brain Observatory Processing Module' @register_map(TimeSeries) class TimeSeriesMap(ObjectMapper): def __init__(self, spec): super(TimeSeriesMap, self).__init__(spec) data_spec = self.spec.get_dataset('data') self.map_attr('unit', data_spec.get_attribute('unit')) self.map_const_arg('unit', data_spec.get_attribute('unit')) self.map_attr('resolution', data_spec.get_attribute('resolution')) self.map_attr('conversion', data_spec.get_attribute('conversion')) timestamps_spec = self.spec.get_dataset('timestamps') self.map_attr('timestamps_unit', timestamps_spec.get_attribute('unit')) # self.map_attr('interval', timestamps_spec.get_attribute('interval')) starting_time_spec = self.spec.get_dataset('starting_time') self.map_attr('starting_time_unit', starting_time_spec.get_attribute('unit')) self.map_attr('rate', starting_time_spec.get_attribute('rate')) @ObjectMapper.constructor_arg('name') def carg_name(self, *args): builder = args[0] return builder.name @ObjectMapper.constructor_arg('starting_time') def carg_starting_time(self, *args): builder = args[0] if builder.name in legacy_TimeSeries_missing_time_info_name_list: return -1.0 @ObjectMapper.constructor_arg('rate') def carg_rate(self, *args): builder = args[0] if builder.name in legacy_TimeSeries_missing_time_info_name_list: return -1.0 pynwb-1.2.1/src/pynwb/legacy/io/ophys.py0000644000655200065520000000413313612200244021550 0ustar circlecicircleci00000000000000import numpy as np from pynwb.ophys import PlaneSegmentation, TwoPhotonSeries from .. import ObjectMapper, register_map @register_map(PlaneSegmentation) class PlaneSegmentationMap(ObjectMapper): # This might be needed for 2.0 as well def __init__(self, spec): super(PlaneSegmentationMap, self).__init__(spec) reference_images_spec = self.spec.get_group('reference_images').get_neurodata_type('ImageSeries') self.map_spec('reference_images', reference_images_spec) @ObjectMapper.constructor_arg('imaging_plane') def carg_imaging_plane(self, *args): builder = args[0] if len(args) < 2: return builder.name # I think this is the hack you had in there before manager = args[1] root = builder parent = root.parent while parent is not None: root = parent parent = root.parent ip_name = builder['imaging_plane_name']['data'] ip_builder = root['general/optophysiology/%s' % ip_name] imaging_plane = manager.construct(ip_builder) return imaging_plane @register_map(TwoPhotonSeries) class TwoPhotonSeriesMap(ObjectMapper): @ObjectMapper.constructor_arg('data') def carg_data(self, *args): builder = args[0] if builder.name in ('2p_image_series',): return np.array([-1.]) @ObjectMapper.constructor_arg('unit') def carg_unit(self, *args): builder = args[0] if builder.name in ('2p_image_series',): return 'None' @ObjectMapper.constructor_arg('imaging_plane') def carg_imaging_plane(self, *args): builder = args[0] if len(args) < 2: return builder.name # I think this is the hack you had in there before manager = args[1] root = builder parent = root.parent while parent is not None: root = parent parent = root.parent ip_name = builder['imaging_plane']['data'] ip_builder = root['general/optophysiology/%s' % ip_name] imaging_plane = manager.construct(ip_builder) return imaging_plane pynwb-1.2.1/src/pynwb/legacy/io/ogen.py0000644000655200065520000000114313612200244021334 0ustar circlecicircleci00000000000000from pynwb.ogen import OptogeneticSeries from .. import ObjectMapper, register_map @register_map(OptogeneticSeries) class OptogeneticSeriesMap(ObjectMapper): @ObjectMapper.constructor_arg('site') def carg_site(self, *args): builder = args[0] manager = args[1] root = builder parent = root.parent while parent is not None: root = parent parent = root.parent site_name = builder['site']['data'] site_builder = root['general/optogenetics/%s' % site_name] site = manager.construct(site_builder) return site pynwb-1.2.1/src/pynwb/legacy/io/ecephys.py0000644000655200065520000000000013612200244022033 0ustar circlecicircleci00000000000000pynwb-1.2.1/src/pynwb/legacy/io/misc.py0000644000655200065520000000046213612200244021342 0ustar circlecicircleci00000000000000from pynwb.misc import AbstractFeatureSeries from .. import ObjectMapper, register_map @register_map(AbstractFeatureSeries) class AbstractFeatureSeriesMap(ObjectMapper): @ObjectMapper.constructor_arg('feature_units') def carg_feature_units(self, *args): return ['None', 'None', 'None'] pynwb-1.2.1/src/pynwb/legacy/io/icephys.py0000644000655200065520000000121013612200244022043 0ustar circlecicircleci00000000000000from pynwb.icephys import PatchClampSeries from .. import ObjectMapper, register_map @register_map(PatchClampSeries) class PatchClampSeriesMap(ObjectMapper): @ObjectMapper.constructor_arg('electrode') def carg_electrode(self, *args): builder = args[0] manager = args[1] root = builder parent = root.parent while parent is not None: root = parent parent = root.parent elec_name = builder['electrode_name']['data'] elec_builder = root['general/intracellular_ephys/%s' % elec_name] electrode = manager.construct(elec_builder) return electrode pynwb-1.2.1/src/pynwb/ophys.py0000644000655200065520000004107513612200244017703 0ustar circlecicircleci00000000000000from collections.abc import Iterable from hdmf.utils import docval, getargs, popargs, call_docval_func, get_docval from . import register_class, CORE_NAMESPACE from .base import TimeSeries from .image import ImageSeries from .core import NWBContainer, MultiContainerInterface, NWBDataInterface from hdmf.common import DynamicTable, DynamicTableRegion from .device import Device import numpy as np @register_class('OpticalChannel', CORE_NAMESPACE) class OpticalChannel(NWBContainer): """An optical channel used to record from an imaging plane.""" __nwbfields__ = ('description', 'emission_lambda') @docval({'name': 'name', 'type': str, 'doc': 'the name of this electrode'}, # required {'name': 'description', 'type': str, 'doc': 'Any notes or comments about the channel.'}, # required {'name': 'emission_lambda', 'type': 'float', 'doc': 'Emission lambda for channel.'}) # required def __init__(self, **kwargs): description, emission_lambda = popargs("description", "emission_lambda", kwargs) call_docval_func(super(OpticalChannel, self).__init__, kwargs) self.description = description self.emission_lambda = emission_lambda @register_class('ImagingPlane', CORE_NAMESPACE) class ImagingPlane(NWBContainer): """An imaging plane and its metadata.""" __nwbfields__ = ({'name': 'optical_channel', 'child': True}, 'description', 'device', 'excitation_lambda', 'imaging_rate', 'indicator', 'location', 'manifold', 'conversion', 'unit', 'reference_frame') @docval(*get_docval(NWBContainer.__init__, 'name'), # required {'name': 'optical_channel', 'type': (list, OpticalChannel), # required 'doc': 'One of possibly many groups storing channelspecific data.'}, {'name': 'description', 'type': str, 'doc': 'Description of this ImagingPlane.'}, # required {'name': 'device', 'type': Device, 'doc': 'the device that was used to record'}, # required {'name': 'excitation_lambda', 'type': 'float', 'doc': 'Excitation wavelength in nm.'}, # required {'name': 'imaging_rate', 'type': 'float', 'doc': 'Rate images are acquired, in Hz.'}, # required {'name': 'indicator', 'type': str, 'doc': 'Calcium indicator'}, # required {'name': 'location', 'type': str, 'doc': 'Location of image plane.'}, # required {'name': 'manifold', 'type': Iterable, 'doc': 'Physical position of each pixel. size=("height", "width", "xyz").', 'default': None}, {'name': 'conversion', 'type': 'float', 'doc': 'Multiplier to get from stored values to specified unit (e.g., 1e-3 for millimeters)', 'default': 1.0}, {'name': 'unit', 'type': str, 'doc': 'Base unit that coordinates are stored in (e.g., Meters).', 'default': 'meters'}, {'name': 'reference_frame', 'type': str, 'doc': 'Describes position and reference frame of manifold based on position of first element ' 'in manifold.', 'default': None}) def __init__(self, **kwargs): optical_channel, description, device, excitation_lambda, imaging_rate, \ indicator, location, manifold, conversion, unit, reference_frame = popargs( 'optical_channel', 'description', 'device', 'excitation_lambda', 'imaging_rate', 'indicator', 'location', 'manifold', 'conversion', 'unit', 'reference_frame', kwargs) call_docval_func(super(ImagingPlane, self).__init__, kwargs) self.optical_channel = optical_channel if isinstance(optical_channel, list) else [optical_channel] self.description = description self.device = device self.excitation_lambda = excitation_lambda self.imaging_rate = imaging_rate self.indicator = indicator self.location = location self.manifold = manifold self.conversion = conversion self.unit = unit self.reference_frame = reference_frame @register_class('TwoPhotonSeries', CORE_NAMESPACE) class TwoPhotonSeries(ImageSeries): """Image stack recorded over time from 2-photon microscope.""" __nwbfields__ = ('field_of_view', 'imaging_plane', 'pmt_gain', 'scan_line_rate') @docval(*get_docval(ImageSeries.__init__, 'name'), # required {'name': 'imaging_plane', 'type': ImagingPlane, 'doc': 'Imaging plane class/pointer.'}, # required {'name': 'data', 'type': ('array_data', 'data', TimeSeries), 'shape': ([None] * 3, [None] * 4), 'doc': 'The data this TimeSeries dataset stores. Can also store binary data e.g. image frames', 'default': None}, *get_docval(ImageSeries.__init__, 'unit', 'format'), {'name': 'field_of_view', 'type': (Iterable, TimeSeries), 'shape': ((2, ), (3, )), 'doc': 'Width, height and depth of image, or imaged area (meters).', 'default': None}, {'name': 'pmt_gain', 'type': 'float', 'doc': 'Photomultiplier gain.', 'default': None}, {'name': 'scan_line_rate', 'type': 'float', 'doc': 'Lines imaged per second. This is also stored in /general/optophysiology but is kept ' 'here as it is useful information for analysis, and so good to be stored w/ the actual data.', 'default': None}, *get_docval(ImageSeries.__init__, 'external_file', 'starting_frame', 'bits_per_pixel', 'dimension', 'resolution', 'conversion', 'timestamps', 'starting_time', 'rate', 'comments', 'description', 'control', 'control_description')) def __init__(self, **kwargs): field_of_view, imaging_plane, pmt_gain, scan_line_rate = popargs( 'field_of_view', 'imaging_plane', 'pmt_gain', 'scan_line_rate', kwargs) call_docval_func(super(TwoPhotonSeries, self).__init__, kwargs) self.field_of_view = field_of_view self.imaging_plane = imaging_plane self.pmt_gain = pmt_gain self.scan_line_rate = scan_line_rate @register_class('CorrectedImageStack', CORE_NAMESPACE) class CorrectedImageStack(NWBDataInterface): """ An image stack where all frames are shifted (registered) to a common coordinate system, to account for movement and drift between frames. Note: each frame at each point in time is assumed to be 2-D (has only x & y dimensions). """ __nwbfields__ = ('corrected', 'original', 'xy_translation') @docval({'name': 'name', 'type': str, 'doc': 'The name of this CorrectedImageStack container', 'default': 'CorrectedImageStack'}, {'name': 'corrected', 'type': ImageSeries, 'doc': 'Image stack with frames shifted to the common coordinates.'}, {'name': 'original', 'type': ImageSeries, 'doc': 'Link to image series that is being registered.'}, {'name': 'xy_translation', 'type': TimeSeries, 'doc': 'Stores the x,y delta necessary to align each frame to the common coordinates, ' 'for example, to align each frame to a reference image.'}) def __init__(self, **kwargs): corrected, original, xy_translation = popargs('corrected', 'original', 'xy_translation', kwargs) call_docval_func(super(CorrectedImageStack, self).__init__, kwargs) self.corrected = corrected self.original = original self.xy_translation = xy_translation @register_class('MotionCorrection', CORE_NAMESPACE) class MotionCorrection(MultiContainerInterface): """ A collection of corrected images stacks. """ __clsconf__ = { 'add': 'add_corrected_image_stack', 'get': 'get_corrected_image_stack', 'create': 'create_corrected_image_stack', 'type': CorrectedImageStack, 'attr': 'corrected_images_stacks' } @register_class('PlaneSegmentation', CORE_NAMESPACE) class PlaneSegmentation(DynamicTable): """ Stores pixels in an image that represent different regions of interest (ROIs) or masks. All segmentation for a given imaging plane is stored together, with storage for multiple imaging planes (masks) supported. Each ROI is stored in its own subgroup, with the ROI group containing both a 2D mask and a list of pixels that make up this mask. Segments can also be used for masking neuropil. If segmentation is allowed to change with time, a new imaging plane (or module) is required and ROI names should remain consistent between them. """ __fields__ = ('imaging_plane', {'name': 'reference_images', 'child': True}) __columns__ = ( {'name': 'image_mask', 'description': 'Image masks for each ROI'}, {'name': 'pixel_mask', 'description': 'Pixel masks for each ROI', 'index': True}, {'name': 'voxel_mask', 'description': 'Voxel masks for each ROI', 'index': True} ) @docval({'name': 'description', 'type': str, # required 'doc': 'Description of image plane, recording wavelength, depth, etc.'}, {'name': 'imaging_plane', 'type': ImagingPlane, # required 'doc': 'the ImagingPlane this ROI applies to'}, {'name': 'name', 'type': str, 'doc': 'name of PlaneSegmentation.', 'default': None}, {'name': 'reference_images', 'type': (ImageSeries, list, dict, tuple), 'default': None, 'doc': 'One or more image stacks that the masks apply to (can be oneelement stack).'}, *get_docval(DynamicTable.__init__, 'id', 'columns', 'colnames')) def __init__(self, **kwargs): imaging_plane, reference_images = popargs('imaging_plane', 'reference_images', kwargs) if kwargs.get('name') is None: kwargs['name'] = imaging_plane.name columns, colnames = getargs('columns', 'colnames', kwargs) call_docval_func(super(PlaneSegmentation, self).__init__, kwargs) self.imaging_plane = imaging_plane if isinstance(reference_images, ImageSeries): reference_images = (reference_images,) self.reference_images = reference_images @docval({'name': 'pixel_mask', 'type': 'array_data', 'default': None, 'doc': 'pixel mask for 2D ROIs: [(x1, y1, weight1), (x2, y2, weight2), ...]', 'shape': (None, 3)}, {'name': 'voxel_mask', 'type': 'array_data', 'default': None, 'doc': 'voxel mask for 3D ROIs: [(x1, y1, z1, weight1), (x2, y2, z2, weight2), ...]', 'shape': (None, 4)}, {'name': 'image_mask', 'type': 'array_data', 'default': None, 'doc': 'image with the same size of image where positive values mark this ROI', 'shape': [[None]*2, [None]*3]}, {'name': 'id', 'type': int, 'doc': 'the ID for the ROI', 'default': None}, allow_extra=True) def add_roi(self, **kwargs): """Add a Region Of Interest (ROI) data to this""" pixel_mask, voxel_mask, image_mask = popargs('pixel_mask', 'voxel_mask', 'image_mask', kwargs) if image_mask is None and pixel_mask is None and voxel_mask is None: raise ValueError("Must provide 'image_mask' and/or 'pixel_mask'") rkwargs = dict(kwargs) if image_mask is not None: rkwargs['image_mask'] = image_mask if pixel_mask is not None: rkwargs['pixel_mask'] = pixel_mask if voxel_mask is not None: rkwargs['voxel_mask'] = voxel_mask return super(PlaneSegmentation, self).add_row(**rkwargs) @staticmethod def pixel_to_image(pixel_mask): """Converts a 2D pixel_mask of a ROI into an image_mask.""" image_matrix = np.zeros(np.shape(pixel_mask)) npmask = np.asarray(pixel_mask) x_coords = npmask[:, 0].astype(np.int) y_coords = npmask[:, 1].astype(np.int) weights = npmask[:, -1] image_matrix[y_coords, x_coords] = weights return image_matrix @staticmethod def image_to_pixel(image_mask): """Converts an image_mask of a ROI into a pixel_mask""" pixel_mask = [] it = np.nditer(image_mask, flags=['multi_index']) while not it.finished: weight = it[0][()] if weight > 0: x = it.multi_index[0] y = it.multi_index[1] pixel_mask.append([x, y, weight]) it.iternext() return pixel_mask @docval({'name': 'description', 'type': str, 'doc': 'a brief description of what the region is'}, {'name': 'region', 'type': (slice, list, tuple), 'doc': 'the indices of the table', 'default': slice(None)}, {'name': 'name', 'type': str, 'doc': 'the name of the ROITableRegion', 'default': 'rois'}) def create_roi_table_region(self, **kwargs): return call_docval_func(self.create_region, kwargs) @register_class('ImageSegmentation', CORE_NAMESPACE) class ImageSegmentation(MultiContainerInterface): """ Stores pixels in an image that represent different regions of interest (ROIs) or masks. All segmentation for a given imaging plane is stored together, with storage for multiple imaging planes (masks) supported. Each ROI is stored in its own subgroup, with the ROI group containing both a 2D mask and a list of pixels that make up this mask. Segments can also be used for masking neuropil. If segmentation is allowed to change with time, a new imaging plane (or module) is required and ROI names should remain consistent between them. """ __clsconf__ = { 'attr': 'plane_segmentations', 'type': PlaneSegmentation, 'add': 'add_plane_segmentation', 'get': 'get_plane_segmentation', 'create': 'create_plane_segmentation' } @docval({'name': 'imaging_plane', 'type': ImagingPlane, 'doc': 'the ImagingPlane this ROI applies to'}, {'name': 'description', 'type': str, 'doc': 'Description of image plane, recording wavelength, depth, etc.', 'default': None}, {'name': 'name', 'type': str, 'doc': 'name of PlaneSegmentation.', 'default': None}) def add_segmentation(self, **kwargs): kwargs.setdefault('description', kwargs['imaging_plane'].description) return self.create_plane_segmentation(**kwargs) @register_class('RoiResponseSeries', CORE_NAMESPACE) class RoiResponseSeries(TimeSeries): ''' ROI responses over an imaging plane. Each column in data should correspond to the signal from one ROI. ''' __nwbfields__ = ({'name': 'rois', 'child': True},) @docval(*get_docval(TimeSeries.__init__, 'name'), # required {'name': 'data', 'type': ('array_data', 'data', TimeSeries), # required 'shape': ((None, ), (None, None)), 'doc': 'The data this TimeSeries dataset stores. Can also store binary data e.g. image frames'}, *get_docval(TimeSeries.__init__, 'unit'), {'name': 'rois', 'type': DynamicTableRegion, # required 'doc': 'a table region corresponding to the ROIs that were used to generate this data'}, *get_docval(TimeSeries.__init__, 'resolution', 'conversion', 'timestamps', 'starting_time', 'rate', 'comments', 'description', 'control', 'control_description')) def __init__(self, **kwargs): rois = popargs('rois', kwargs) call_docval_func(super(RoiResponseSeries, self).__init__, kwargs) self.rois = rois @register_class('DfOverF', CORE_NAMESPACE) class DfOverF(MultiContainerInterface): """ dF/F information about a region of interest (ROI). Storage hierarchy of dF/F should be the same as for segmentation (ie, same names for ROIs and for image planes). """ __clsconf__ = { 'attr': 'roi_response_series', 'type': RoiResponseSeries, 'add': 'add_roi_response_series', 'get': 'get_roi_response_series', 'create': 'create_roi_response_series' } @register_class('Fluorescence', CORE_NAMESPACE) class Fluorescence(MultiContainerInterface): """ Fluorescence information about a region of interest (ROI). Storage hierarchy of fluorescence should be the same as for segmentation (ie, same names for ROIs and for image planes). """ __clsconf__ = { 'attr': 'roi_response_series', 'type': RoiResponseSeries, 'add': 'add_roi_response_series', 'get': 'get_roi_response_series', 'create': 'create_roi_response_series' } pynwb-1.2.1/src/pynwb/validate.py0000644000655200065520000001025313612200244020324 0ustar circlecicircleci00000000000000import os import sys from argparse import ArgumentParser from hdmf.spec import NamespaceCatalog from hdmf.build import BuildManager from hdmf.build import TypeMap as TypeMap from hdmf.backends.hdf5 import HDF5IO from pynwb import validate, available_namespaces, NWBHDF5IO from pynwb.spec import NWBDatasetSpec, NWBGroupSpec, NWBNamespace def _print_errors(validation_errors): if validation_errors: print(' - found the following errors:', file=sys.stderr) for err in validation_errors: print(str(err), file=sys.stderr) else: print(' - no errors found.') def _validate_helper(**kwargs): errors = validate(**kwargs) _print_errors(errors) return (errors is not None and len(errors) > 0) def main(): ep = """ use --nspath to validate against an extension. If --ns is not specified, validate against all namespaces in namespace file. """ parser = ArgumentParser(description="Validate an NWB file", epilog=ep) parser.add_argument("paths", type=str, nargs='+', help="NWB file paths") parser.add_argument('-p', '--nspath', type=str, help="the path to the namespace YAML file") parser.add_argument("-n", "--ns", type=str, help="the namespace to validate against") feature_parser = parser.add_mutually_exclusive_group(required=False) feature_parser.add_argument("--cached-namespace", dest="cached_namespace", action='store_true', help="Use the cached namespace (default).") feature_parser.add_argument('--no-cached-namespace', dest="cached_namespace", action='store_false', help="Don't use the cached namespace.") parser.set_defaults(cached_namespace=True) args = parser.parse_args() ret = 0 if args.nspath: if not os.path.isfile(args.nspath): print("The namespace file {} is not a valid file.".format(args.nspath), file=sys.stderr) sys.exit(1) if args.cached_namespace: print("Turning off validation against cached namespace information" "as --nspath was passed.", file=sys.stderr) args.cached_namespace = False for path in args.paths: if not os.path.isfile(path): print("The file {} does not exist.".format(path), file=sys.stderr) ret = 1 continue if args.cached_namespace: catalog = NamespaceCatalog(NWBGroupSpec, NWBDatasetSpec, NWBNamespace) namespaces = HDF5IO.load_namespaces(catalog, path).keys() if len(namespaces) > 0: tm = TypeMap(catalog) manager = BuildManager(tm) specloc = "cached namespace information" else: manager = None namespaces = available_namespaces() specloc = "pynwb namespace information" print("The file {} has no cached namespace information. " "Falling back to {}.".format(path, specloc), file=sys.stderr) elif args.nspath: catalog = NamespaceCatalog(NWBGroupSpec, NWBDatasetSpec, NWBNamespace) namespaces = catalog.load_namespaces(args.nspath) if len(namespaces) == 0: print("Could not load namespaces from file {}.".format(args.nspath), file=sys.stderr) sys.exit(1) tm = TypeMap(catalog) manager = BuildManager(tm) specloc = "--nspath namespace information" else: manager = None namespaces = available_namespaces() specloc = "pynwb namespace information" if args.ns: if args.ns in namespaces: namespaces = [args.ns] else: print("The namespace {} could not be found in {}.".format(args.ns, specloc), file=sys.stderr) ret = 1 continue with NWBHDF5IO(path, mode='r', manager=manager) as io: for ns in namespaces: print("Validating {} against {} using namespace {}.".format(path, specloc, ns)) ret = ret or _validate_helper(io=io, namespace=ns) sys.exit(ret) if __name__ == '__main__': # pragma: no cover main() pynwb-1.2.1/src/pynwb/ogen.py0000644000655200065520000000444613612200244017472 0ustar circlecicircleci00000000000000from hdmf.utils import docval, popargs, get_docval, call_docval_func from . import register_class, CORE_NAMESPACE from .base import TimeSeries from .core import NWBContainer from .device import Device @register_class('OptogeneticStimulusSite', CORE_NAMESPACE) class OptogeneticStimulusSite(NWBContainer): ''' ''' __nwbfields__ = ('device', 'description', 'excitation_lambda', 'location') @docval({'name': 'name', 'type': str, 'doc': 'The name of this stimulus site'}, {'name': 'device', 'type': Device, 'doc': 'the device that was used'}, {'name': 'description', 'type': str, 'doc': 'Description of site.'}, {'name': 'excitation_lambda', 'type': 'float', 'doc': 'Excitation wavelength in nm.'}, {'name': 'location', 'type': str, 'doc': 'Location of stimulation site.'}) def __init__(self, **kwargs): device, description, excitation_lambda, location = popargs( 'device', 'description', 'excitation_lambda', 'location', kwargs) call_docval_func(super(OptogeneticStimulusSite, self).__init__, kwargs) self.device = device self.description = description self.excitation_lambda = excitation_lambda self.location = location @register_class('OptogeneticSeries', CORE_NAMESPACE) class OptogeneticSeries(TimeSeries): ''' Optogenetic stimulus. The data field is in unit of watts. ''' __nwbfields__ = ('site',) @docval(*get_docval(TimeSeries.__init__, 'name'), # required {'name': 'data', 'type': ('array_data', 'data', TimeSeries), 'shape': (None, ), # required 'doc': 'The data this TimeSeries dataset stores. Can also store binary data e.g. image frames'}, {'name': 'site', 'type': OptogeneticStimulusSite, # required 'doc': 'The site to which this stimulus was applied.'}, *get_docval(TimeSeries.__init__, 'resolution', 'conversion', 'timestamps', 'starting_time', 'rate', 'comments', 'description', 'control', 'control_description')) def __init__(self, **kwargs): name, data, site = popargs('name', 'data', 'site', kwargs) super(OptogeneticSeries, self).__init__(name, data, 'watts', **kwargs) self.site = site pynwb-1.2.1/src/pynwb/core.py0000644000655200065520000005705013612200244017471 0ustar circlecicircleci00000000000000from h5py import RegionReference import numpy as np import pandas as pd from hdmf.utils import docval, getargs, ExtenderMeta, call_docval_func, popargs, get_docval, fmt_docval_args from hdmf import Container, Data, DataRegion, get_region_slicer from hdmf.container import AbstractContainer from hdmf.common import DynamicTable # NOQA from . import CORE_NAMESPACE, register_class def _not_parent(arg): return arg['name'] != 'parent' def prepend_string(string, prepend=' '): return prepend + prepend.join(string.splitlines(True)) class NWBMixin(AbstractContainer): _data_type_attr = 'neurodata_type' @docval({'name': 'neurodata_type', 'type': str, 'doc': 'the data_type to search for', 'default': None}) def get_ancestor(self, **kwargs): """ Traverse parent hierarchy and return first instance of the specified data_type """ neurodata_type = getargs('neurodata_type', kwargs) return super().get_ancestor(data_type=neurodata_type) @register_class('NWBContainer', CORE_NAMESPACE) class NWBContainer(NWBMixin, Container): _fieldsname = '__nwbfields__' __nwbfields__ = tuple() @docval({'name': 'name', 'type': str, 'doc': 'the name of this container'}) def __init__(self, **kwargs): call_docval_func(super(NWBContainer, self).__init__, kwargs) def _to_dict(self, arg, label="NULL"): return_dict = LabelledDict(label) if arg is None: return return_dict else: for i in arg: assert i.name is not None # If a container doesn't have a name, it gets lost! assert i.name not in return_dict return_dict[i.name] = i return return_dict @register_class('NWBDataInterface', CORE_NAMESPACE) class NWBDataInterface(NWBContainer): @docval(*get_docval(NWBContainer.__init__)) def __init__(self, **kwargs): call_docval_func(super(NWBDataInterface, self).__init__, kwargs) @register_class('NWBData', CORE_NAMESPACE) class NWBData(NWBMixin, Data): @docval({'name': 'name', 'type': str, 'doc': 'the name of this container'}, {'name': 'data', 'type': ('array_data', 'data', Data), 'doc': 'the source of the data'}) def __init__(self, **kwargs): call_docval_func(super(NWBData, self).__init__, kwargs) self.__data = getargs('data', kwargs) @property def data(self): return self.__data def __len__(self): return len(self.__data) def __getitem__(self, args): if isinstance(self.data, (tuple, list)) and isinstance(args, (tuple, list)): return [self.data[i] for i in args] return self.data[args] def append(self, arg): if isinstance(self.data, list): self.data.append(arg) elif isinstance(self.data, np.ndarray): self.__data = np.append(self.__data, [arg]) else: msg = "NWBData cannot append to object of type '%s'" % type(self.__data) raise ValueError(msg) def extend(self, arg): if isinstance(self.data, list): self.data.extend(arg) elif isinstance(self.data, np.ndarray): self.__data = np.append(self.__data, [arg]) else: msg = "NWBData cannot extend object of type '%s'" % type(self.__data) raise ValueError(msg) @register_class('ScratchData', CORE_NAMESPACE) class ScratchData(NWBData): __nwbfields__ = ('notes',) @docval({'name': 'name', 'type': str, 'doc': 'the name of this container'}, {'name': 'data', 'type': ('array_data', 'data', Data), 'doc': 'the source of the data'}, {'name': 'notes', 'type': str, 'doc': 'notes about the data', 'default': ''}) def __init__(self, **kwargs): call_docval_func(super(ScratchData, self).__init__, kwargs) self.notes = getargs('notes', kwargs) class NWBTable(NWBData): r''' Subclasses should specify the class attribute \_\_columns\_\_. This should be a list of dictionaries with the following keys: - ``name`` the column name - ``type`` the type of data in this column - ``doc`` a brief description of what gets stored in this column For reference, this list of dictionaries will be used with docval to autogenerate the ``add_row`` method for adding data to this table. If \_\_columns\_\_ is not specified, no custom ``add_row`` method will be added. The class attribute __defaultname__ can also be set to specify a default name for the table class. If \_\_defaultname\_\_ is not specified, then ``name`` will need to be specified when the class is instantiated. ''' @ExtenderMeta.pre_init def __build_table_class(cls, name, bases, classdict): if hasattr(cls, '__columns__'): columns = getattr(cls, '__columns__') idx = dict() for i, col in enumerate(columns): idx[col['name']] = i setattr(cls, '__colidx__', idx) if cls.__init__ == bases[-1].__init__: # check if __init__ is overridden name = {'name': 'name', 'type': str, 'doc': 'the name of this table'} defname = getattr(cls, '__defaultname__', None) if defname is not None: name['default'] = defname @docval(name, {'name': 'data', 'type': ('array_data', 'data'), 'doc': 'the data in this table', 'default': list()}) def __init__(self, **kwargs): name, data = getargs('name', 'data', kwargs) colnames = [i['name'] for i in columns] super(cls, self).__init__(colnames, name, data) setattr(cls, '__init__', __init__) if cls.add_row == bases[-1].add_row: # check if add_row is overridden @docval(*columns) def add_row(self, **kwargs): return super(cls, self).add_row(kwargs) setattr(cls, 'add_row', add_row) @docval({'name': 'columns', 'type': (list, tuple), 'doc': 'a list of the columns in this table'}, {'name': 'name', 'type': str, 'doc': 'the name of this container'}, {'name': 'data', 'type': ('array_data', 'data'), 'doc': 'the source of the data', 'default': list()}) def __init__(self, **kwargs): self.__columns = tuple(popargs('columns', kwargs)) self.__col_index = {name: idx for idx, name in enumerate(self.__columns)} call_docval_func(super(NWBTable, self).__init__, kwargs) @property def columns(self): return self.__columns @docval({'name': 'values', 'type': dict, 'doc': 'the values for each column'}) def add_row(self, **kwargs): values = getargs('values', kwargs) if not isinstance(self.data, list): msg = 'Cannot append row to %s' % type(self.data) raise ValueError(msg) ret = len(self.data) self.data.append(tuple(values[col] for col in self.columns)) return ret def which(self, **kwargs): ''' Query a table ''' if len(kwargs) != 1: raise ValueError("only one column can be queried") colname, value = kwargs.popitem() idx = self.__colidx__.get(colname) if idx is None: msg = "no '%s' column in %s" % (colname, self.__class__.__name__) raise KeyError(msg) ret = list() for i in range(len(self.data)): row = self.data[i] row_val = row[idx] if row_val == value: ret.append(i) return ret def __len__(self): return len(self.data) def __getitem__(self, args): idx = args col = None if isinstance(args, tuple): idx = args[1] if isinstance(args[0], str): col = self.__col_index.get(args[0]) elif isinstance(args[0], int): col = args[0] else: raise KeyError('first argument must be a column name or index') return self.data[idx][col] elif isinstance(args, str): col = self.__col_index.get(args) if col is None: raise KeyError(args) return [row[col] for row in self.data] else: return self.data[idx] def to_dataframe(self): '''Produce a pandas DataFrame containing this table's data. ''' data = {colname: self[colname] for ii, colname in enumerate(self.columns)} return pd.DataFrame(data) @classmethod @docval( {'name': 'df', 'type': pd.DataFrame, 'doc': 'input data'}, {'name': 'name', 'type': str, 'doc': 'the name of this container', 'default': None}, { 'name': 'extra_ok', 'type': bool, 'doc': 'accept (and ignore) unexpected columns on the input dataframe', 'default': False }, ) def from_dataframe(cls, **kwargs): '''Construct an instance of NWBTable (or a subclass) from a pandas DataFrame. The columns of the dataframe should match the columns defined on the NWBTable subclass. ''' df, name, extra_ok = getargs('df', 'name', 'extra_ok', kwargs) cls_cols = list([col['name'] for col in getattr(cls, '__columns__')]) df_cols = list(df.columns) missing_columns = set(cls_cols) - set(df_cols) extra_columns = set(df_cols) - set(cls_cols) if extra_columns: raise ValueError( 'unrecognized column(s) {} for table class {} (columns {})'.format( extra_columns, cls.__name__, cls_cols ) ) use_index = False if len(missing_columns) == 1 and list(missing_columns)[0] == df.index.name: use_index = True elif missing_columns: raise ValueError( 'missing column(s) {} for table class {} (columns {}, provided {})'.format( missing_columns, cls.__name__, cls_cols, df_cols ) ) data = [] for index, row in df.iterrows(): if use_index: data.append([ row[colname] if colname != df.index.name else index for colname in cls_cols ]) else: data.append([row[colname] for colname in cls_cols]) if name is None: return cls(data=data) return cls(name=name, data=data) # diamond inheritance class NWBTableRegion(NWBData, DataRegion): ''' A class for representing regions i.e. slices or indices into an NWBTable ''' @docval({'name': 'name', 'type': str, 'doc': 'the name of this container'}, {'name': 'table', 'type': NWBTable, 'doc': 'the ElectrodeTable this region applies to'}, {'name': 'region', 'type': (slice, list, tuple, RegionReference), 'doc': 'the indices of the table'}) def __init__(self, **kwargs): table, region = getargs('table', 'region', kwargs) self.__table = table self.__region = region name = getargs('name', kwargs) super(NWBTableRegion, self).__init__(name, table) self.__regionslicer = get_region_slicer(self.__table.data, self.__region) @property def table(self): '''The ElectrodeTable this region applies to''' return self.__table @property def region(self): '''The indices into table''' return self.__region def __len__(self): return len(self.__regionslicer) def __getitem__(self, idx): return self.__regionslicer[idx] class MultiContainerInterface(NWBDataInterface): ''' A class for dynamically defining a API classes that represent NWBDataInterfaces that contain multiple Containers of the same type To use, extend this class, and create a dictionary as a class attribute with the following keys: * 'add' to name the method for adding Container instances * 'create' to name the method fo creating Container instances * 'get' to name the method for getting Container instances * 'attr' to name the attribute that stores the Container instances * 'type' to provide the Container object type See LFP or Position for an example of how to use this. ''' @docval(*get_docval(NWBDataInterface.__init__)) def __init__(self, **kwargs): call_docval_func(super(MultiContainerInterface, self).__init__, kwargs) if isinstance(self.__clsconf__, dict): attr_name = self.__clsconf__['attr'] self.fields[attr_name] = LabelledDict(attr_name) else: for d in self.__clsconf__: attr_name = d['attr'] self.fields[attr_name] = LabelledDict(attr_name) @staticmethod def __add_article(noun): if isinstance(noun, tuple): noun = noun[0] if isinstance(noun, type): noun = noun.__name__ if noun[0] in ('aeiouAEIOU'): return 'an %s' % noun return 'a %s' % noun @staticmethod def __join(argtype): def tostr(x): return x.__name__ if isinstance(x, type) else x if isinstance(argtype, (list, tuple)): args = [tostr(x) for x in argtype] if len(args) == 1: return args[0].__name__ else: ", ".join(tostr(x) for x in args[:-1]) + ' or ' + args[-1] else: return tostr(argtype) @classmethod def __make_get(cls, func_name, attr_name, container_type): doc = "Get %s from this %s" % (cls.__add_article(container_type), cls.__name__) @docval({'name': 'name', 'type': str, 'doc': 'the name of the %s' % cls.__join(container_type), 'default': None}, rtype=container_type, returns='the %s with the given name' % cls.__join(container_type), func_name=func_name, doc=doc) def _func(self, **kwargs): name = getargs('name', kwargs) d = getattr(self, attr_name) ret = None if name is None: if len(d) > 1: msg = "more than one element in %s of %s '%s' -- must specify a name" % \ (attr_name, cls.__name__, self.name) raise ValueError(msg) elif len(d) == 0: msg = "%s of %s '%s' is empty" % (attr_name, cls.__name__, self.name) raise ValueError(msg) elif len(d) == 1: for v in d.values(): ret = v else: ret = d.get(name) if ret is None: msg = "'%s' not found in %s of %s '%s'" % (name, attr_name, cls.__name__, self.name) raise KeyError(msg) return ret return _func @classmethod def __make_add(cls, func_name, attr_name, container_type): doc = "Add %s to this %s" % (cls.__add_article(container_type), cls.__name__) @docval({'name': attr_name, 'type': (list, tuple, dict, container_type), 'doc': 'the %s to add' % cls.__join(container_type)}, func_name=func_name, doc=doc) def _func(self, **kwargs): container = getargs(attr_name, kwargs) if isinstance(container, container_type): containers = [container] elif isinstance(container, dict): containers = container.values() else: containers = container d = getattr(self, attr_name) for tmp in containers: if not isinstance(tmp.parent, Container): tmp.parent = self # else, the ObjectMapper will create a link from self (parent) to tmp (child with existing parent) if tmp.name in d: msg = "'%s' already exists in '%s'" % (tmp.name, self.name) raise ValueError(msg) d[tmp.name] = tmp return container return _func @classmethod def __make_create(cls, func_name, add_name, container_type): doc = "Create %s and add it to this %s" % (cls.__add_article(container_type), cls.__name__) @docval(*filter(_not_parent, get_docval(container_type.__init__)), func_name=func_name, doc=doc, returns="the %s object that was created" % cls.__join(container_type), rtype=container_type) def _func(self, **kwargs): cargs, ckwargs = fmt_docval_args(container_type.__init__, kwargs) ret = container_type(*cargs, **ckwargs) getattr(self, add_name)(ret) return ret return _func @classmethod def __make_constructor(cls, clsconf): args = list() for conf in clsconf: attr_name = conf['attr'] container_type = conf['type'] args.append({'name': attr_name, 'type': (list, tuple, dict, container_type), 'doc': '%s to store in this interface' % cls.__join(container_type), 'default': dict()}) args.append({'name': 'name', 'type': str, 'doc': 'the name of this container', 'default': cls.__name__}) @docval(*args, func_name='__init__') def _func(self, **kwargs): call_docval_func(super(cls, self).__init__, kwargs) for conf in clsconf: attr_name = conf['attr'] add_name = conf['add'] container = popargs(attr_name, kwargs) add = getattr(self, add_name) add(container) return _func @classmethod def __make_getitem(cls, attr_name, container_type): doc = "Get %s from this %s" % (cls.__add_article(container_type), cls.__name__) @docval({'name': 'name', 'type': str, 'doc': 'the name of the %s' % cls.__join(container_type), 'default': None}, rtype=container_type, returns='the %s with the given name' % cls.__join(container_type), func_name='__getitem__', doc=doc) def _func(self, **kwargs): name = getargs('name', kwargs) d = getattr(self, attr_name) if len(d) == 0: msg = "%s '%s' is empty" % (cls.__name__, self.name) raise ValueError(msg) if len(d) > 1 and name is None: msg = "more than one %s in this %s -- must specify a name" % cls.__join(container_type), cls.__name__ raise ValueError(msg) ret = None if len(d) == 1: for v in d.values(): ret = v else: ret = d.get(name) if ret is None: msg = "'%s' not found in %s '%s'" % (name, cls.__name__, self.name) raise KeyError(msg) return ret return _func @classmethod def __make_setter(cls, nwbfield, add_name): @docval({'name': 'val', 'type': (list, tuple, dict), 'doc': 'the sub items to add', 'default': None}) def nwbbt_setter(self, **kwargs): val = getargs('val', kwargs) if val is None: return getattr(self, add_name)(val) return nwbbt_setter @ExtenderMeta.pre_init def __build_class(cls, name, bases, classdict): ''' This classmethod will be called during class declaration in the metaclass to automatically create setters and getters for NWB fields that need to be exported ''' if not hasattr(cls, '__clsconf__'): return multi = False if isinstance(cls.__clsconf__, dict): clsconf = [cls.__clsconf__] elif isinstance(cls.__clsconf__, list): multi = True clsconf = cls.__clsconf__ else: raise TypeError("'__clsconf__' must be a dict or a list of dicts") for i, d in enumerate(clsconf): # get add method name add = d.get('add') if add is None: msg = "MultiContainerInterface subclass '%s' is missing 'add' key in __clsconf__" % cls.__name__ if multi: msg += " at element %d" % i raise ValueError(msg) # get container attribute name attr = d.get('attr') if attr is None: msg = "MultiContainerInterface subclass '%s' is missing 'attr' key in __clsconf__" % cls.__name__ if multi: msg += " at element %d" % i raise ValueError(msg) # get container type container_type = d.get('type') if container_type is None: msg = "MultiContainerInterface subclass '%s' is missing 'type' key in __clsconf__" % cls.__name__ if multi: msg += " at element %d" % i raise ValueError(msg) # create property with the name given in 'attr' if not hasattr(cls, attr): aconf = cls._check_field_spec(attr) getter = cls._getter(aconf) doc = "a dictionary containing the %s in this %s container" % \ (cls.__join(container_type), cls.__name__) setattr(cls, attr, property(getter, cls.__make_setter(aconf, add), None, doc)) # create the add method setattr(cls, add, cls.__make_add(add, attr, container_type)) # get create method name create = d.get('create') if create is not None: setattr(cls, create, cls.__make_create(create, add, container_type)) get = d.get('get') if get is not None: setattr(cls, get, cls.__make_get(get, attr, container_type)) if len(clsconf) == 1: setattr(cls, '__getitem__', cls.__make_getitem(attr, container_type)) # create the constructor, only if it has not been overridden # i.e. it is the same method as the parent class constructor if cls.__init__ == MultiContainerInterface.__init__: setattr(cls, '__init__', cls.__make_constructor(clsconf)) class LabelledDict(dict): ''' A dict wrapper class for aggregating Timeseries from the standard locations ''' @docval({'name': 'label', 'type': str, 'doc': 'the label on this dictionary'}, {'name': 'def_key_name', 'type': str, 'doc': 'the default key name', 'default': 'name'}) def __init__(self, **kwargs): label, def_key_name = getargs('label', 'def_key_name', kwargs) self.__label = label self.__defkey = def_key_name @property def label(self): return self.__label def __getitem__(self, args): key = args if '==' in args: key, val = args.split("==") key = key.strip() val = val.strip() if key != self.__defkey: ret = list() for item in self.values(): if getattr(item, key, None) == val: ret.append(item) return ret if len(ret) else None key = val return super(LabelledDict, self).__getitem__(key) @docval({'name': 'container', 'type': (NWBData, NWBContainer), 'doc': 'the container to add to this LabelledDict'}) def add(self, **kwargs): ''' Add a container to this LabelledDict ''' container = getargs('container', kwargs) key = getattr(container, self.__defkey, None) if key is None: msg = "container '%s' does not have attribute '%s'" % (container.name, self.__defkey) raise ValueError(msg) self[key] = container pynwb-1.2.1/src/pynwb/ecephys.py0000644000655200065520000004036613612200244020203 0ustar circlecicircleci00000000000000from collections.abc import Iterable from hdmf.utils import docval, getargs, popargs, call_docval_func, get_docval from hdmf.data_utils import DataChunkIterator, assertEqualShape from . import register_class, CORE_NAMESPACE from .base import TimeSeries from .core import NWBContainer, NWBDataInterface, MultiContainerInterface from hdmf.common import DynamicTableRegion from .device import Device @register_class('ElectrodeGroup', CORE_NAMESPACE) class ElectrodeGroup(NWBContainer): """ """ __nwbfields__ = ('name', 'description', 'location', 'device') @docval({'name': 'name', 'type': str, 'doc': 'the name of this electrode'}, {'name': 'description', 'type': str, 'doc': 'description of this electrode group'}, {'name': 'location', 'type': str, 'doc': 'description of location of this electrode group'}, {'name': 'device', 'type': Device, 'doc': 'the device that was used to record from this electrode group'}) def __init__(self, **kwargs): call_docval_func(super(ElectrodeGroup, self).__init__, kwargs) description, location, device = popargs("description", "location", "device", kwargs) self.description = description self.location = location self.device = device @register_class('ElectricalSeries', CORE_NAMESPACE) class ElectricalSeries(TimeSeries): """ Stores acquired voltage data from extracellular recordings. The data field of an ElectricalSeries is an int or float array storing data in Volts. TimeSeries::data array structure: [num times] [num channels] (or [num_times] for single electrode). """ __nwbfields__ = ({'name': 'electrodes', 'required_name': 'electrodes', 'doc': 'the electrodes that generated this electrical series', 'child': True}, 'channel_conversion') @docval(*get_docval(TimeSeries.__init__, 'name'), # required {'name': 'data', 'type': ('array_data', 'data', TimeSeries), # required 'shape': ((None, ), (None, None), (None, None, None)), 'doc': 'The data this TimeSeries dataset stores. Can also store binary data e.g. image frames'}, {'name': 'electrodes', 'type': DynamicTableRegion, # required 'doc': 'the table region corresponding to the electrodes from which this series was recorded'}, {'name': 'channel_conversion', 'type': ('array_data', 'data'), 'shape': (None,), 'doc': "Channel-specific conversion factor. Multiply the data in the 'data' dataset by these values along the " "channel axis (as indicated by axis attribute) AND by the global conversion factor in the 'conversion' " "attribute of 'data' to get the data values in Volts, i.e, data in Volts = data * data.conversion * " "channel_conversion. This approach allows for both global and per-channel data conversion factors needed " "to support the storage of electrical recordings as native values generated by data acquisition systems. " "If this dataset is not present, then there is no channel-specific conversion factor, i.e. it is 1 for all" " channels.", 'default': None}, *get_docval(TimeSeries.__init__, 'resolution', 'conversion', 'timestamps', 'starting_time', 'rate', 'comments', 'description', 'control', 'control_description')) def __init__(self, **kwargs): name, electrodes, data, channel_conversion = popargs('name', 'electrodes', 'data', 'channel_conversion', kwargs) super(ElectricalSeries, self).__init__(name, data, 'volts', **kwargs) self.electrodes = electrodes self.channel_conversion = channel_conversion @register_class('SpikeEventSeries', CORE_NAMESPACE) class SpikeEventSeries(ElectricalSeries): """ Stores "snapshots" of spike events (i.e., threshold crossings) in data. This may also be raw data, as reported by ephys hardware. If so, the TimeSeries::description field should describing how events were detected. All SpikeEventSeries should reside in a module (under EventWaveform interface) even if the spikes were reported and stored by hardware. All events span the same recording channels and store snapshots of equal duration. TimeSeries::data array structure: [num events] [num channels] [num samples] (or [num events] [num samples] for single electrode). """ __nwbfields__ = () @docval(*get_docval(ElectricalSeries.__init__, 'name', 'data'), # required {'name': 'timestamps', 'type': ('array_data', 'data', TimeSeries), # required 'doc': 'Timestamps for samples stored in data'}, *get_docval(ElectricalSeries.__init__, 'electrodes'), # required *get_docval(ElectricalSeries.__init__, 'resolution', 'conversion', 'comments', 'description', 'control', 'control_description')) def __init__(self, **kwargs): name, data, electrodes = popargs('name', 'data', 'electrodes', kwargs) timestamps = getargs('timestamps', kwargs) if not (isinstance(data, TimeSeries) or isinstance(timestamps, TimeSeries)): if not (isinstance(data, DataChunkIterator) or isinstance(timestamps, DataChunkIterator)): if len(data) != len(timestamps): raise Exception('Must provide the same number of timestamps and spike events') else: # TODO: add check when we have DataChunkIterators pass super(SpikeEventSeries, self).__init__(name, data, electrodes, **kwargs) @register_class('EventDetection', CORE_NAMESPACE) class EventDetection(NWBDataInterface): """ Detected spike events from voltage trace(s). """ __nwbfields__ = ('detection_method', 'source_electricalseries', 'source_idx', 'times') @docval({'name': 'detection_method', 'type': str, 'doc': 'Description of how events were detected, such as voltage threshold, or dV/dT threshold, ' 'as well as relevant values.'}, {'name': 'source_electricalseries', 'type': ElectricalSeries, 'doc': 'The source electrophysiology data'}, {'name': 'source_idx', 'type': ('array_data', 'data'), 'doc': 'Indices (zero-based) into source ElectricalSeries::data array corresponding ' 'to time of event. Module description should define what is meant by time of event ' '(e.g., .25msec before action potential peak, zero-crossing time, etc). ' 'The index points to each event from the raw data'}, {'name': 'times', 'type': ('array_data', 'data'), 'doc': 'Timestamps of events, in Seconds'}, {'name': 'name', 'type': str, 'doc': 'the name of this container', 'default': 'EventDetection'}) def __init__(self, **kwargs): detection_method, source_electricalseries, source_idx, times = popargs( 'detection_method', 'source_electricalseries', 'source_idx', 'times', kwargs) super(EventDetection, self).__init__(**kwargs) self.detection_method = detection_method self.source_electricalseries = source_electricalseries self.source_idx = source_idx self.times = times self.unit = 'seconds' @register_class('EventWaveform', CORE_NAMESPACE) class EventWaveform(MultiContainerInterface): """ Spike data for spike events detected in raw data stored in this NWBFile, or events detect at acquisition """ __clsconf__ = { 'attr': 'spike_event_series', 'type': SpikeEventSeries, 'add': 'add_spike_event_series', 'get': 'get_spike_event_series', 'create': 'create_spike_event_series' } @register_class('Clustering', CORE_NAMESPACE) class Clustering(NWBDataInterface): """ DEPRECATED in favor of :py:meth:`~pynwb.misc.Units`. Specifies cluster event times and cluster metric for maximum ratio of waveform peak to RMS on any channel in cluster. """ __nwbfields__ = ( 'description', 'num', 'peak_over_rms', 'times' ) @docval({'name': 'description', 'type': str, 'doc': 'Description of clusters or clustering, (e.g. cluster 0 is noise, ' 'clusters curated using Klusters, etc).'}, {'name': 'num', 'type': ('array_data', 'data'), 'doc': 'Cluster number of each event.', 'shape': (None, )}, {'name': 'peak_over_rms', 'type': Iterable, 'shape': (None, ), 'doc': 'Maximum ratio of waveform peak to RMS on any channel in the cluster' '(provides a basic clustering metric).'}, {'name': 'times', 'type': ('array_data', 'data'), 'doc': 'Times of clustered events, in seconds.', 'shape': (None,)}, {'name': 'name', 'type': str, 'doc': 'the name of this container', 'default': 'Clustering'}) def __init__(self, **kwargs): import warnings warnings.warn("use pynwb.misc.Units or NWBFile.units instead", DeprecationWarning) description, num, peak_over_rms, times = popargs( 'description', 'num', 'peak_over_rms', 'times', kwargs) super(Clustering, self).__init__(**kwargs) self.description = description self.num = num self.peak_over_rms = list(peak_over_rms) self.times = times @register_class('ClusterWaveforms', CORE_NAMESPACE) class ClusterWaveforms(NWBDataInterface): """ DEPRECATED. `ClusterWaveforms` was deprecated in Oct 27, 2018 and will be removed in a future release. Please use the `Units` table to store waveform mean and standard deviation e.g. `NWBFile.units.add_unit(..., waveform_mean=..., waveform_sd=...)` Describe cluster waveforms by mean and standard deviation for at each sample. """ __nwbfields__ = ('clustering_interface', 'waveform_filtering', 'waveform_mean', 'waveform_sd') @docval({'name': 'clustering_interface', 'type': Clustering, 'doc': 'the clustered spike data used as input for computing waveforms'}, {'name': 'waveform_filtering', 'type': str, 'doc': 'filter applied to data before calculating mean and standard deviation'}, {'name': 'waveform_mean', 'type': Iterable, 'shape': (None, None), 'doc': 'the mean waveform for each cluster'}, {'name': 'waveform_sd', 'type': Iterable, 'shape': (None, None), 'doc': 'the standard deviations of waveforms for each cluster'}, {'name': 'name', 'type': str, 'doc': 'the name of this container', 'default': 'ClusterWaveforms'}) def __init__(self, **kwargs): import warnings warnings.warn("use pynwb.misc.Units or NWBFile.units instead", DeprecationWarning) clustering_interface, waveform_filtering, waveform_mean, waveform_sd = popargs( 'clustering_interface', 'waveform_filtering', 'waveform_mean', 'waveform_sd', kwargs) super(ClusterWaveforms, self).__init__(**kwargs) self.clustering_interface = clustering_interface self.waveform_filtering = waveform_filtering self.waveform_mean = waveform_mean self.waveform_sd = waveform_sd @register_class('LFP', CORE_NAMESPACE) class LFP(MultiContainerInterface): """ LFP data from one or more channels. The electrode map in each published ElectricalSeries will identify which channels are providing LFP data. Filter properties should be noted in the ElectricalSeries description or comments field. """ __clsconf__ = [ {'attr': 'electrical_series', 'type': ElectricalSeries, 'add': 'add_electrical_series', 'get': 'get_electrical_series', 'create': 'create_electrical_series'}] @register_class('FilteredEphys', CORE_NAMESPACE) class FilteredEphys(MultiContainerInterface): """ Ephys data from one or more channels that has been subjected to filtering. Examples of filtered data include Theta and Gamma (LFP has its own interface). FilteredEphys modules publish an ElectricalSeries for each filtered channel or set of channels. The name of each ElectricalSeries is arbitrary but should be informative. The source of the filtered data, whether this is from analysis of another time series or as acquired by hardware, should be noted in each's TimeSeries::description field. There is no assumed 1::1 correspondence between filtered ephys signals and electrodes, as a single signal can apply to many nearby electrodes, and one electrode may have different filtered (e.g., theta and/or gamma) signals represented. """ __clsconf__ = { 'attr': 'electrical_series', 'type': ElectricalSeries, 'add': 'add_electrical_series', 'get': 'get_electrical_series', 'create': 'create_electrical_series' } @register_class('FeatureExtraction', CORE_NAMESPACE) class FeatureExtraction(NWBDataInterface): """ Features, such as PC1 and PC2, that are extracted from signals stored in a SpikeEvent TimeSeries or other source. """ __nwbfields__ = ('description', {'name': 'electrodes', 'child': True}, 'times', 'features') @docval({'name': 'electrodes', 'type': DynamicTableRegion, 'doc': 'the table region corresponding to the electrodes from which this series was recorded'}, {'name': 'description', 'type': ('array_data', 'data'), 'doc': 'A description for each feature extracted', 'shape': (None, )}, {'name': 'times', 'type': ('array_data', 'data'), 'shape': (None, ), 'doc': 'The times of events that features correspond to'}, {'name': 'features', 'type': ('array_data', 'data'), 'shape': (None, None, None), 'doc': 'Features for each channel'}, {'name': 'name', 'type': str, 'doc': 'the name of this container', 'default': 'FeatureExtraction'}) def __init__(self, **kwargs): # get the inputs electrodes, description, times, features = popargs( 'electrodes', 'description', 'times', 'features', kwargs) # Validate the shape of the inputs # Validate event times compared to features shape_validators = [] shape_validators.append(assertEqualShape(data1=features, data2=times, axes1=0, axes2=0, name1='feature_shape', name2='times', ignore_undetermined=True)) # Validate electrodes compared to features shape_validators.append(assertEqualShape(data1=features, data2=electrodes, axes1=1, axes2=0, name1='feature_shape', name2='electrodes', ignore_undetermined=True)) # Valided description compared to features shape_validators.append(assertEqualShape(data1=features, data2=description, axes1=2, axes2=0, name1='feature_shape', name2='description', ignore_undetermined=True)) # Raise an error if any of the shapes do not match raise_error = False error_msg = "" for sv in shape_validators: raise_error |= not sv.result if not sv.result: error_msg += sv.message + "\n" if raise_error: raise ValueError(error_msg) # Initialize the object super(FeatureExtraction, self).__init__(**kwargs) self.electrodes = electrodes self.description = description self.times = list(times) self.features = features pynwb-1.2.1/src/pynwb/_version.py0000644000655200065520000000076113612200376020370 0ustar circlecicircleci00000000000000 # This file was generated by 'versioneer.py' (0.18) from # revision-control system data, or from the parent directory name of an # unpacked source archive. Distribution tarballs contain a pre-generated copy # of this file. import json version_json = ''' { "date": "2020-01-22T17:18:54-0800", "dirty": false, "error": null, "full-revisionid": "30f6c4c3677cd3c220ff44a3409334e8bbf318f9", "version": "1.2.1" } ''' # END VERSION_JSON def get_versions(): return json.loads(version_json) pynwb-1.2.1/src/pynwb/misc.py0000644000655200065520000003457713612200244017505 0ustar circlecicircleci00000000000000import numpy as np from collections.abc import Iterable import warnings from bisect import bisect_left, bisect_right from hdmf.utils import docval, getargs, popargs, call_docval_func, get_docval from . import register_class, CORE_NAMESPACE from .base import TimeSeries from hdmf.common import DynamicTable @register_class('AnnotationSeries', CORE_NAMESPACE) class AnnotationSeries(TimeSeries): """ Stores text-based records about the experiment. To use the AnnotationSeries, add records individually through add_annotation() and then call finalize(). Alternatively, if all annotations are already stored in a list, use set_data() and set_timestamps() """ __nwbfields__ = () @docval(*get_docval(TimeSeries.__init__, 'name'), # required {'name': 'data', 'type': ('array_data', 'data', TimeSeries), 'shape': (None,), 'doc': 'The data this TimeSeries dataset stores. Can also store binary data e.g. image frames', 'default': list()}, *get_docval(TimeSeries.__init__, 'timestamps', 'comments', 'description')) def __init__(self, **kwargs): name, data, timestamps = popargs('name', 'data', 'timestamps', kwargs) super(AnnotationSeries, self).__init__(name, data, 'n/a', resolution=-1.0, timestamps=timestamps, **kwargs) @docval({'name': 'time', 'type': 'float', 'doc': 'The time for the annotation'}, {'name': 'annotation', 'type': str, 'doc': 'the annotation'}) def add_annotation(self, **kwargs): ''' Add an annotation ''' time, annotation = getargs('time', 'annotation', kwargs) self.fields['timestamps'].append(time) self.fields['data'].append(annotation) @register_class('AbstractFeatureSeries', CORE_NAMESPACE) class AbstractFeatureSeries(TimeSeries): """ Represents the salient features of a data stream. Typically this will be used for things like a visual grating stimulus, where the bulk of data (each frame sent to the graphics card) is bulky and not of high value, while the salient characteristics (eg, orientation, spatial frequency, contrast, etc) are what important and are what are used for analysis """ __nwbfields__ = ('feature_units', 'features') @docval(*get_docval(TimeSeries.__init__, 'name'), # required {'name': 'feature_units', 'type': Iterable, 'shape': (None, ), # required 'doc': 'The unit of each feature'}, {'name': 'features', 'type': Iterable, 'shape': (None, ), # required 'doc': 'Description of each feature'}, {'name': 'data', 'type': ('array_data', 'data', TimeSeries), 'shape': ((None,), (None, None)), 'doc': 'The data this TimeSeries dataset stores. Can also store binary data e.g. image frames', 'default': list()}, *get_docval(TimeSeries.__init__, 'resolution', 'conversion', 'timestamps', 'starting_time', 'rate', 'comments', 'description', 'control', 'control_description')) def __init__(self, **kwargs): name, data, features, feature_units = popargs('name', 'data', 'features', 'feature_units', kwargs) super(AbstractFeatureSeries, self).__init__(name, data, "see 'feature_units'", **kwargs) self.features = features self.feature_units = feature_units @docval({'name': 'time', 'type': 'float', 'doc': 'the time point of this feature'}, {'name': 'features', 'type': (list, np.ndarray), 'doc': 'the feature values for this time point'}) def add_features(self, **kwargs): time, features = getargs('time', 'features', kwargs) if type(self.timestamps) == list and type(self.data) is list: self.timestamps.append(time) self.data.append(features) else: raise ValueError('Can only add feature if timestamps and data are lists') @register_class('IntervalSeries', CORE_NAMESPACE) class IntervalSeries(TimeSeries): """ 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. """ __nwbfields__ = () @docval(*get_docval(TimeSeries.__init__, 'name'), # required {'name': 'data', 'type': ('array_data', 'data', TimeSeries), 'shape': (None,), 'doc': '>0 if interval started, <0 if interval ended.', 'default': list()}, *get_docval(TimeSeries.__init__, 'timestamps', 'comments', 'description', 'control', 'control_description')) def __init__(self, **kwargs): name, data, timestamps = popargs('name', 'data', 'timestamps', kwargs) self.__interval_timestamps = timestamps self.__interval_data = data super(IntervalSeries, self).__init__(name, data, 'n/a', resolution=-1.0, timestamps=timestamps, **kwargs) @docval({'name': 'start', 'type': 'float', 'doc': 'The name of this TimeSeries dataset'}, {'name': 'stop', 'type': 'float', 'doc': 'The name of this TimeSeries dataset'}) def add_interval(self, **kwargs): start, stop = getargs('start', 'stop', kwargs) self.__interval_timestamps.append(start) self.__interval_timestamps.append(stop) self.__interval_data.append(1) self.__interval_data.append(-1) @property def data(self): return self.__interval_data @property def timestamps(self): return self.__interval_timestamps @register_class('Units', CORE_NAMESPACE) class Units(DynamicTable): """ Event times of observed units (e.g. cell, synapse, etc.). """ __columns__ = ( {'name': 'spike_times', 'description': 'the spike times for each unit', 'index': True}, {'name': 'obs_intervals', 'description': 'the observation intervals for each unit', 'index': True}, {'name': 'electrodes', 'description': 'the electrodes that each spike unit came from', 'index': True, 'table': True}, {'name': 'electrode_group', 'description': 'the electrode group that each spike unit came from'}, {'name': 'waveform_mean', 'description': 'the spike waveform mean for each spike unit'}, {'name': 'waveform_sd', 'description': 'the spike waveform standard deviation for each spike unit'} ) @docval({'name': 'name', 'type': str, 'doc': 'Name of this Units interface', 'default': 'Units'}, *get_docval(DynamicTable.__init__, 'id', 'columns', 'colnames'), {'name': 'description', 'type': str, 'doc': 'a description of what is in this table', 'default': None}, {'name': 'electrode_table', 'type': DynamicTable, 'doc': 'the table that the *electrodes* column indexes', 'default': None}) def __init__(self, **kwargs): if kwargs.get('description', None) is None: kwargs['description'] = "data on spiking units" call_docval_func(super(Units, self).__init__, kwargs) if 'spike_times' not in self.colnames: self.__has_spike_times = False self.__electrode_table = getargs('electrode_table', kwargs) @docval({'name': 'spike_times', 'type': 'array_data', 'doc': 'the spike times for each unit', 'default': None, 'shape': (None,)}, {'name': 'obs_intervals', 'type': 'array_data', 'doc': 'the observation intervals (valid times) for each unit. All spike_times for a given unit ' + 'should fall within these intervals. [[start1, end1], [start2, end2], ...]', 'default': None, 'shape': (None, 2)}, {'name': 'electrodes', 'type': 'array_data', 'doc': 'the electrodes that each unit came from', 'default': None}, {'name': 'electrode_group', 'type': 'ElectrodeGroup', 'default': None, 'doc': 'the electrode group that each unit came from'}, {'name': 'waveform_mean', 'type': 'array_data', 'doc': 'the spike waveform mean for each unit. Shape is (time,) or (time, electrodes)', 'default': None}, {'name': 'waveform_sd', 'type': 'array_data', 'default': None, 'doc': 'the spike waveform standard deviation for each unit. Shape is (time,) or (time, electrodes)'}, {'name': 'id', 'type': int, 'default': None, 'doc': 'the id for each unit'}, allow_extra=True) def add_unit(self, **kwargs): """ Add a unit to this table """ super(Units, self).add_row(**kwargs) if 'electrodes' in self: elec_col = self['electrodes'].target if elec_col.table is None: if self.__electrode_table is None: nwbfile = self.get_ancestor(data_type='NWBFile') elec_col.table = nwbfile.electrodes if elec_col.table is None: warnings.warn('Reference to electrode table that does not yet exist') else: elec_col.table = self.__electrode_table @docval({'name': 'index', 'type': (int, list, tuple, np.ndarray), 'doc': 'the index of the unit in unit_ids to retrieve spike times for'}, {'name': 'in_interval', 'type': (tuple, list), 'doc': 'only return values within this interval', 'default': None, 'shape': (2,)}) def get_unit_spike_times(self, **kwargs): index, in_interval = getargs('index', 'in_interval', kwargs) if type(index) in (list, tuple): return [self.get_unit_spike_times(i, in_interval=in_interval) for i in index] if in_interval is None: return np.asarray(self['spike_times'][index]) else: st = self['spike_times'] unit_start = 0 if index == 0 else st.data[index - 1] unit_stop = st.data[index] start_time, stop_time = in_interval ind_start = bisect_left(st.target, start_time, unit_start, unit_stop) ind_stop = bisect_right(st.target, stop_time, ind_start, unit_stop) return np.asarray(st.target[ind_start:ind_stop]) @docval({'name': 'index', 'type': int, 'doc': 'the index of the unit in unit_ids to retrieve observation intervals for'}) def get_unit_obs_intervals(self, **kwargs): index = getargs('index', kwargs) return np.asarray(self['obs_intervals'][index]) @register_class('DecompositionSeries', CORE_NAMESPACE) class DecompositionSeries(TimeSeries): """ Stores product of spectral analysis """ __nwbfields__ = ('metric', {'name': 'source_timeseries', 'child': False, 'doc': 'the input TimeSeries from this analysis'}, {'name': 'bands', 'doc': 'the bands that the signal is decomposed into', 'child': True}) @docval(*get_docval(TimeSeries.__init__, 'name'), # required {'name': 'data', 'type': ('array_data', 'data', TimeSeries), # required 'doc': 'dims: num_times * num_channels * num_bands', 'shape': (None, None, None)}, *get_docval(TimeSeries.__init__, 'description'), {'name': 'metric', 'type': str, # required 'doc': "metric of analysis. recommended: 'phase', 'amplitude', 'power'"}, {'name': 'unit', 'type': str, 'doc': 'SI unit of measurement', 'default': 'no unit'}, {'name': 'bands', 'type': DynamicTable, 'doc': 'a table for describing the frequency bands that the signal was decomposed into', 'default': None}, {'name': 'source_timeseries', 'type': TimeSeries, 'doc': 'the input TimeSeries from this analysis', 'default': None}, *get_docval(TimeSeries.__init__, 'resolution', 'conversion', 'timestamps', 'starting_time', 'rate', 'comments', 'control', 'control_description')) def __init__(self, **kwargs): metric, source_timeseries, bands = popargs('metric', 'source_timeseries', 'bands', kwargs) super(DecompositionSeries, self).__init__(**kwargs) self.source_timeseries = source_timeseries if self.source_timeseries is None: warnings.warn("It is best practice to set `source_timeseries` if it is present to document " "where the DecompositionSeries was derived from. (Optional)") self.metric = metric if bands is None: bands = DynamicTable("bands", "data about the frequency bands that the signal was decomposed into") self.bands = bands def __check_column(self, name, desc): if name not in self.bands.colnames: self.bands.add_column(name, desc) @docval({'name': 'band_name', 'type': str, 'doc': 'the name of the frequency band', 'default': None}, {'name': 'band_limits', 'type': ('array_data', 'data'), 'default': None, 'doc': 'low and high frequencies of bandpass filter in Hz'}, {'name': 'band_mean', 'type': 'float', 'doc': 'the mean of Gaussian filters in Hz', 'default': None}, {'name': 'band_stdev', 'type': 'float', 'doc': 'the standard deviation of Gaussian filters in Hz', 'default': None}, allow_extra=True) def add_band(self, **kwargs): """ Add ROI data to this """ band_name, band_limits, band_mean, band_stdev = getargs('band_name', 'band_limits', 'band_mean', 'band_stdev', kwargs) if band_name is not None: self.__check_column('band_name', "the name of the frequency band (recommended: 'alpha', 'beta', 'gamma', " "'delta', 'high gamma'") if band_name is not None: self.__check_column('band_limits', 'low and high frequencies of bandpass filter in Hz') if band_mean is not None: self.__check_column('band_mean', 'the mean of Gaussian filters in Hz') if band_stdev is not None: self.__check_column('band_stdev', 'the standard deviation of Gaussian filters in Hz') self.bands.add_row({k: v for k, v in kwargs.items() if v is not None}) pynwb-1.2.1/src/pynwb/icephys.py0000644000655200065520000003470513612200244020207 0ustar circlecicircleci00000000000000from hdmf.utils import docval, popargs, call_docval_func, get_docval from . import register_class, CORE_NAMESPACE from .base import TimeSeries from .core import NWBContainer from .device import Device from hdmf.common import DynamicTable @register_class('IntracellularElectrode', CORE_NAMESPACE) class IntracellularElectrode(NWBContainer): ''' ''' __nwbfields__ = ('slice', 'seal', 'description', 'location', 'resistance', 'filtering', 'initial_access_resistance', 'device') @docval({'name': 'name', 'type': str, 'doc': 'the name of this electrode'}, {'name': 'device', 'type': Device, 'doc': 'the device that was used to record from this electrode'}, {'name': 'description', 'type': str, 'doc': 'Recording description, description of electrode (e.g., whole-cell, sharp, etc) ' 'COMMENT: Free-form text (can be from Methods)'}, {'name': 'slice', 'type': str, 'doc': 'Information about slice used for recording.', 'default': None}, {'name': 'seal', 'type': str, 'doc': 'Information about seal used for recording.', 'default': None}, {'name': 'location', 'type': str, 'doc': 'Area, layer, comments on estimation, stereotaxis coordinates (if in vivo, etc).', 'default': None}, {'name': 'resistance', 'type': str, 'doc': 'Electrode resistance COMMENT: unit: Ohm.', 'default': None}, {'name': 'filtering', 'type': str, 'doc': 'Electrode specific filtering.', 'default': None}, {'name': 'initial_access_resistance', 'type': str, 'doc': 'Initial access resistance.', 'default': None}, ) def __init__(self, **kwargs): slice, seal, description, location, resistance, filtering, initial_access_resistance, device = popargs( 'slice', 'seal', 'description', 'location', 'resistance', 'filtering', 'initial_access_resistance', 'device', kwargs) call_docval_func(super(IntracellularElectrode, self).__init__, kwargs) self.slice = slice self.seal = seal self.description = description self.location = location self.resistance = resistance self.filtering = filtering self.initial_access_resistance = initial_access_resistance self.device = device @register_class('PatchClampSeries', CORE_NAMESPACE) class PatchClampSeries(TimeSeries): ''' Stores stimulus or response current or voltage. Superclass definition for patch-clamp data (this class should not be instantiated directly). ''' __nwbfields__ = ('electrode', 'gain', 'stimulus_description', 'sweep_number') @docval(*get_docval(TimeSeries.__init__, 'name'), # required {'name': 'data', 'type': ('array_data', 'data', TimeSeries), # required 'doc': 'The data this TimeSeries dataset stores. Can also store binary data e.g. image frames'}, {'name': 'unit', 'type': str, 'doc': 'The base unit of measurement (should be SI unit)'}, # required {'name': 'electrode', 'type': IntracellularElectrode, # required 'doc': 'IntracellularElectrode group that describes the electrode that was used to apply ' 'or record this data.'}, {'name': 'gain', 'type': 'float', 'doc': 'Units: Volt/Amp (v-clamp) or Volt/Volt (c-clamp)'}, # required {'name': 'stimulus_description', 'type': str, 'doc': 'the stimulus name/protocol', 'default': "NA"}, *get_docval(TimeSeries.__init__, 'resolution', 'conversion', 'timestamps', 'starting_time', 'rate', 'comments', 'description', 'control', 'control_description'), {'name': 'sweep_number', 'type': (int, 'uint32', 'uint64'), 'doc': 'Sweep number, allows for grouping different PatchClampSeries together ' 'via the sweep_table', 'default': None}) def __init__(self, **kwargs): name, data, unit, stimulus_description = popargs('name', 'data', 'unit', 'stimulus_description', kwargs) electrode, gain, sweep_number = popargs('electrode', 'gain', 'sweep_number', kwargs) super(PatchClampSeries, self).__init__(name, data, unit, **kwargs) self.electrode = electrode self.gain = gain self.stimulus_description = stimulus_description if sweep_number is not None: if not (sweep_number >= 0): raise ValueError("sweep_number must be a non-negative integer") self.sweep_number = sweep_number @register_class('CurrentClampSeries', CORE_NAMESPACE) class CurrentClampSeries(PatchClampSeries): ''' Stores voltage data recorded from intracellular current-clamp recordings. A corresponding CurrentClampStimulusSeries (stored separately as a stimulus) is used to store the current injected. ''' __nwbfields__ = ('bias_current', 'bridge_balance', 'capacitance_compensation') @docval(*get_docval(PatchClampSeries.__init__, 'name', 'data', 'electrode'), # required {'name': 'gain', 'type': 'float', 'doc': 'Units: Volt/Volt'}, *get_docval(PatchClampSeries.__init__, 'stimulus_description'), {'name': 'bias_current', 'type': 'float', 'doc': 'Unit: Amp', 'default': None}, {'name': 'bridge_balance', 'type': 'float', 'doc': 'Unit: Ohm', 'default': None}, {'name': 'capacitance_compensation', 'type': 'float', 'doc': 'Unit: Farad', 'default': None}, *get_docval(PatchClampSeries.__init__, 'resolution', 'conversion', 'timestamps', 'starting_time', 'rate', 'comments', 'description', 'control', 'control_description', 'sweep_number')) def __init__(self, **kwargs): name, data, electrode, gain = popargs('name', 'data', 'electrode', 'gain', kwargs) unit = 'volts' bias_current, bridge_balance, capacitance_compensation = popargs( 'bias_current', 'bridge_balance', 'capacitance_compensation', kwargs) super(CurrentClampSeries, self).__init__(name, data, unit, electrode, gain, **kwargs) self.bias_current = bias_current self.bridge_balance = bridge_balance self.capacitance_compensation = capacitance_compensation @register_class('IZeroClampSeries', CORE_NAMESPACE) class IZeroClampSeries(CurrentClampSeries): ''' Stores recorded voltage data from intracellular recordings when all current and amplifier settings are off (i.e., CurrentClampSeries fields will be zero). There is no CurrentClampStimulusSeries associated with an IZero series because the amplifier is disconnected and no stimulus can reach the cell. ''' __nwbfields__ = () @docval(*get_docval(CurrentClampSeries.__init__, 'name', 'data', 'electrode'), # required {'name': 'gain', 'type': 'float', 'doc': 'Units: Volt/Volt'}, # required *get_docval(CurrentClampSeries.__init__, 'stimulus_description', 'resolution', 'conversion', 'timestamps', 'starting_time', 'rate', 'comments', 'description', 'control', 'control_description', 'sweep_number')) def __init__(self, **kwargs): name, data, electrode, gain = popargs('name', 'data', 'electrode', 'gain', kwargs) bias_current, bridge_balance, capacitance_compensation = (0.0, 0.0, 0.0) super(IZeroClampSeries, self).__init__(name, data, electrode, gain, bias_current, bridge_balance, capacitance_compensation, **kwargs) @register_class('CurrentClampStimulusSeries', CORE_NAMESPACE) class CurrentClampStimulusSeries(PatchClampSeries): ''' Alias to standard PatchClampSeries. Its functionality is to better tag PatchClampSeries for machine (and human) readability of the file. ''' __nwbfields__ = () @docval(*get_docval(PatchClampSeries.__init__, 'name', 'data', 'electrode', 'gain'), # required *get_docval(PatchClampSeries.__init__, 'stimulus_description', 'resolution', 'conversion', 'timestamps', 'starting_time', 'rate', 'comments', 'description', 'control', 'control_description', 'sweep_number')) def __init__(self, **kwargs): name, data, electrode, gain = popargs('name', 'data', 'electrode', 'gain', kwargs) unit = 'amperes' super(CurrentClampStimulusSeries, self).__init__(name, data, unit, electrode, gain, **kwargs) @register_class('VoltageClampSeries', CORE_NAMESPACE) class VoltageClampSeries(PatchClampSeries): ''' Stores current data recorded from intracellular voltage-clamp recordings. A corresponding VoltageClampStimulusSeries (stored separately as a stimulus) is used to store the voltage injected. ''' __nwbfields__ = ('capacitance_fast', 'capacitance_slow', 'resistance_comp_bandwidth', 'resistance_comp_correction', 'resistance_comp_prediction', 'whole_cell_capacitance_comp', 'whole_cell_series_resistance_comp') @docval(*get_docval(PatchClampSeries.__init__, 'name', 'data', 'electrode'), # required {'name': 'gain', 'type': 'float', 'doc': 'Units: Volt/Amp'}, # required *get_docval(PatchClampSeries.__init__, 'stimulus_description'), {'name': 'capacitance_fast', 'type': 'float', 'doc': 'Unit: Farad', 'default': None}, {'name': 'capacitance_slow', 'type': 'float', 'doc': 'Unit: Farad', 'default': None}, {'name': 'resistance_comp_bandwidth', 'type': 'float', 'doc': 'Unit: Hz', 'default': None}, {'name': 'resistance_comp_correction', 'type': 'float', 'doc': 'Unit: percent', 'default': None}, {'name': 'resistance_comp_prediction', 'type': 'float', 'doc': 'Unit: percent', 'default': None}, {'name': 'whole_cell_capacitance_comp', 'type': 'float', 'doc': 'Unit: Farad', 'default': None}, {'name': 'whole_cell_series_resistance_comp', 'type': 'float', 'doc': 'Unit: Ohm', 'default': None}, *get_docval(PatchClampSeries.__init__, 'resolution', 'conversion', 'timestamps', 'starting_time', 'rate', 'comments', 'description', 'control', 'control_description', 'sweep_number')) def __init__(self, **kwargs): name, data, electrode, gain = popargs('name', 'data', 'electrode', 'gain', kwargs) unit = 'amperes' capacitance_fast, capacitance_slow, resistance_comp_bandwidth, resistance_comp_correction, \ resistance_comp_prediction, whole_cell_capacitance_comp, whole_cell_series_resistance_comp = popargs( 'capacitance_fast', 'capacitance_slow', 'resistance_comp_bandwidth', 'resistance_comp_correction', 'resistance_comp_prediction', 'whole_cell_capacitance_comp', 'whole_cell_series_resistance_comp', kwargs) super(VoltageClampSeries, self).__init__(name, data, unit, electrode, gain, **kwargs) self.capacitance_fast = capacitance_fast self.capacitance_slow = capacitance_slow self.resistance_comp_bandwidth = resistance_comp_bandwidth self.resistance_comp_correction = resistance_comp_correction self.resistance_comp_prediction = resistance_comp_prediction self.whole_cell_capacitance_comp = whole_cell_capacitance_comp self.whole_cell_series_resistance_comp = whole_cell_series_resistance_comp @register_class('VoltageClampStimulusSeries', CORE_NAMESPACE) class VoltageClampStimulusSeries(PatchClampSeries): ''' Alias to standard PatchClampSeries. Its functionality is to better tag PatchClampSeries for machine (and human) readability of the file. ''' __nwbfields__ = () @docval(*get_docval(PatchClampSeries.__init__, 'name', 'data', 'electrode', 'gain'), # required *get_docval(PatchClampSeries.__init__, 'stimulus_description', 'resolution', 'conversion', 'timestamps', 'starting_time', 'rate', 'comments', 'description', 'control', 'control_description', 'sweep_number')) def __init__(self, **kwargs): name, data, electrode, gain = popargs('name', 'data', 'electrode', 'gain', kwargs) unit = 'volts' super(VoltageClampStimulusSeries, self).__init__(name, data, unit, electrode, gain, **kwargs) @register_class('SweepTable', CORE_NAMESPACE) class SweepTable(DynamicTable): """ A SweepTable allows to group PatchClampSeries together which stem from the same sweep. A sweep is a group of PatchClampSeries which have the same starting point in time. """ __columns__ = ( {'name': 'series', 'description': 'PatchClampSeries with the same sweep number', 'required': True, 'index': True}, {'name': 'sweep_number', 'description': 'Sweep number of the entries in that row', 'required': True} ) @docval({'name': 'name', 'type': str, 'doc': 'name of this SweepTable', 'default': 'sweep_table'}, {'name': 'description', 'type': str, 'doc': 'Description of this SweepTable', 'default': "A sweep table groups different PatchClampSeries together."}, *get_docval(DynamicTable.__init__, 'id', 'columns', 'colnames')) def __init__(self, **kwargs): call_docval_func(super(SweepTable, self).__init__, kwargs) @docval({'name': 'pcs', 'type': PatchClampSeries, 'doc': 'PatchClampSeries to add to the table must have a valid sweep_number'}) def add_entry(self, pcs): """ Add the passed PatchClampSeries to the sweep table. """ kwargs = {'sweep_number': pcs.sweep_number, 'series': [pcs]} # FIXME appending to an existing entry would be nicer # but this seems to be not possible self.add_row(**kwargs) def get_series(self, sweep_number): """ Return a list of PatchClampSeries for the given sweep number. """ ids = self.__get_row_ids(sweep_number) if len(ids) == 0: return None matches = [] for x in ids: for y in self[(x, 'series')]: matches.append(y) return matches def __get_row_ids(self, sweep_number): """ Return the row ids for the given sweep number. """ return [index for index, elem in enumerate(self['sweep_number'].data) if elem == sweep_number] pynwb-1.2.1/src/pynwb/spec.py0000644000655200065520000001500613612200244017466 0ustar circlecicircleci00000000000000from copy import copy, deepcopy from hdmf.spec import LinkSpec, GroupSpec, DatasetSpec, SpecNamespace,\ NamespaceBuilder, AttributeSpec, DtypeSpec, RefSpec from hdmf.spec.write import export_spec # noqa: F401 from hdmf.utils import docval, get_docval, call_docval_func from . import CORE_NAMESPACE def __swap_inc_def(cls): args = get_docval(cls.__init__) clsname = 'NWB%s' % cls.__name__ ret = list() for arg in args: if arg['name'] == 'data_type_def': ret.append({'name': 'neurodata_type_def', 'type': str, 'doc': 'the NWB data type this spec defines', 'default': None}) elif arg['name'] == 'data_type_inc': ret.append({'name': 'neurodata_type_inc', 'type': (clsname, str), 'doc': 'the NWB data type this spec includes', 'default': None}) else: ret.append(copy(arg)) return ret _ref_docval = __swap_inc_def(RefSpec) class NWBRefSpec(RefSpec): @docval(*_ref_docval) def __init__(self, **kwargs): call_docval_func(super(NWBRefSpec, self).__init__, kwargs) _attr_docval = __swap_inc_def(AttributeSpec) class NWBAttributeSpec(AttributeSpec): @docval(*_attr_docval) def __init__(self, **kwargs): call_docval_func(super(NWBAttributeSpec, self).__init__, kwargs) _link_docval = __swap_inc_def(LinkSpec) class NWBLinkSpec(LinkSpec): @docval(*_link_docval) def __init__(self, **kwargs): call_docval_func(super(NWBLinkSpec, self).__init__, kwargs) @property def neurodata_type_inc(self): ''' The neurodata type of target specification ''' return self.data_type_inc class BaseStorageOverride(object): ''' This class is used for the purpose of overriding BaseStorageSpec classmethods, without creating diamond inheritance hierarchies. ''' __type_key = 'neurodata_type' __inc_key = 'neurodata_type_inc' __def_key = 'neurodata_type_def' @classmethod def type_key(cls): ''' Get the key used to store data type on an instance''' return cls.__type_key @classmethod def inc_key(cls): ''' Get the key used to define a data_type include.''' return cls.__inc_key @classmethod def def_key(cls): ''' Get the key used to define a data_type definition.''' return cls.__def_key @property def neurodata_type_inc(self): return self.data_type_inc @property def neurodata_type_def(self): return self.data_type_def @classmethod def build_const_args(cls, spec_dict): """Extend base functionality to remap data_type_def and data_type_inc keys""" spec_dict = copy(spec_dict) proxy = super(BaseStorageOverride, cls) if proxy.inc_key() in spec_dict: spec_dict[cls.inc_key()] = spec_dict.pop(proxy.inc_key()) if proxy.def_key() in spec_dict: spec_dict[cls.def_key()] = spec_dict.pop(proxy.def_key()) ret = proxy.build_const_args(spec_dict) return ret @classmethod def _translate_kwargs(cls, kwargs): """Swap neurodata_type_def and neurodata_type_inc for data_type_def and data_type_inc, respectively""" proxy = super(BaseStorageOverride, cls) kwargs[proxy.def_key()] = kwargs.pop(cls.def_key()) kwargs[proxy.inc_key()] = kwargs.pop(cls.inc_key()) args = [kwargs.pop(x['name']) for x in get_docval(proxy.__init__) if 'default' not in x] return args, kwargs _dtype_docval = __swap_inc_def(DtypeSpec) class NWBDtypeSpec(DtypeSpec): @docval(*_dtype_docval) def __init__(self, **kwargs): call_docval_func(super(NWBDtypeSpec, self).__init__, kwargs) _dataset_docval = __swap_inc_def(DatasetSpec) class NWBDatasetSpec(BaseStorageOverride, DatasetSpec): ''' The Spec class to use for NWB specifications ''' @docval(*_dataset_docval) def __init__(self, **kwargs): args, kwargs = self._translate_kwargs(kwargs) super(NWBDatasetSpec, self).__init__(*args, **kwargs) _group_docval = __swap_inc_def(GroupSpec) class NWBGroupSpec(BaseStorageOverride, GroupSpec): ''' The Spec class to use for NWB specifications ''' @docval(*_group_docval) def __init__(self, **kwargs): args, kwargs = self._translate_kwargs(kwargs) super(NWBGroupSpec, self).__init__(*args, **kwargs) @classmethod def dataset_spec_cls(cls): return NWBDatasetSpec @docval({'name': 'neurodata_type', 'type': str, 'doc': 'the neurodata_type to retrieve'}) def get_neurodata_type(self, **kwargs): ''' Get a specification by "data_type" ''' return super(NWBGroupSpec, self).get_data_type(kwargs['neurodata_type']) @docval(*deepcopy(_group_docval)) def add_group(self, **kwargs): ''' Add a new specification for a subgroup to this group specification ''' doc = kwargs.pop('doc') spec = NWBGroupSpec(doc, **kwargs) self.set_group(spec) return spec @docval(*deepcopy(_dataset_docval)) def add_dataset(self, **kwargs): ''' Add a new specification for a subgroup to this group specification ''' doc = kwargs.pop('doc') spec = NWBDatasetSpec(doc, **kwargs) self.set_dataset(spec) return spec class NWBNamespace(SpecNamespace): ''' A Namespace class for NWB ''' __types_key = 'neurodata_types' @classmethod def types_key(cls): return cls.__types_key class NWBNamespaceBuilder(NamespaceBuilder): ''' A class for writing namespace and spec files for extensions of types in the NWB core namespace ''' @docval({'name': 'doc', 'type': str, 'doc': 'a description about what this namespace represents'}, {'name': 'name', 'type': str, 'doc': 'the name of this namespace'}, {'name': 'full_name', 'type': str, 'doc': 'extended full name of this namespace', 'default': None}, {'name': 'version', 'type': (str, tuple, list), 'doc': 'Version number of the namespace', 'default': None}, {'name': 'author', 'type': (str, list), 'doc': 'Author or list of authors.', 'default': None}, {'name': 'contact', 'type': (str, list), 'doc': 'List of emails. Ordering should be the same as for author', 'default': None}) def __init__(self, **kwargs): ''' Create a NWBNamespaceBuilder ''' kwargs['namespace_cls'] = NWBNamespace call_docval_func(super(NWBNamespaceBuilder, self).__init__, kwargs) self.include_namespace(CORE_NAMESPACE) pynwb-1.2.1/src/pynwb/io/0000755000655200065520000000000013612200376016575 5ustar circlecicircleci00000000000000pynwb-1.2.1/src/pynwb/io/image.py0000644000655200065520000000062113612200244020222 0ustar circlecicircleci00000000000000from .. import register_map from ..image import ImageSeries from .base import TimeSeriesMap @register_map(ImageSeries) class ImageSeriesMap(TimeSeriesMap): def __init__(self, spec): super(ImageSeriesMap, self).__init__(spec) external_file_spec = self.spec.get_dataset('external_file') self.map_spec('starting_frame', external_file_spec.get_attribute('starting_frame')) pynwb-1.2.1/src/pynwb/io/file.py0000644000655200065520000002060313612200244020061 0ustar circlecicircleci00000000000000from dateutil.parser import parse as dateutil_parse from hdmf.build import ObjectMapper from .. import register_map from ..file import NWBFile, Subject from ..core import ScratchData @register_map(NWBFile) class NWBFileMap(ObjectMapper): def __init__(self, spec): super(NWBFileMap, self).__init__(spec) acq_spec = self.spec.get_group('acquisition') self.unmap(acq_spec) self.map_spec('acquisition', acq_spec.get_neurodata_type('NWBDataInterface')) self.map_spec('acquisition', acq_spec.get_neurodata_type('DynamicTable')) # TODO: note that double mapping "acquisition" means __carg2spec and __attr2spec (both unused) # map "acquisition" to the last spec, in this case, DynamicTable ana_spec = self.spec.get_group('analysis') self.unmap(ana_spec) self.map_spec('analysis', ana_spec.get_neurodata_type('NWBContainer')) self.map_spec('analysis', ana_spec.get_neurodata_type('DynamicTable')) # map constructor arg and property 'stimulus' -> stimulus__presentation stimulus_spec = self.spec.get_group('stimulus') self.unmap(stimulus_spec) self.unmap(stimulus_spec.get_group('presentation')) self.unmap(stimulus_spec.get_group('templates')) self.map_spec('stimulus', stimulus_spec.get_group('presentation').get_neurodata_type('TimeSeries')) self.map_spec('stimulus_template', stimulus_spec.get_group('templates').get_neurodata_type('TimeSeries')) intervals_spec = self.spec.get_group('intervals') self.unmap(intervals_spec) self.map_spec('intervals', intervals_spec.get_neurodata_type('TimeIntervals')) epochs_spec = intervals_spec.get_group('epochs') self.map_spec('epochs', epochs_spec) trials_spec = intervals_spec.get_group('trials') self.map_spec('trials', trials_spec) invalid_times_spec = intervals_spec.get_group('invalid_times') self.map_spec('invalid_times', invalid_times_spec) general_spec = self.spec.get_group('general') self.unmap(general_spec) icephys_spec = general_spec.get_group('intracellular_ephys') self.unmap(icephys_spec) self.map_spec('ic_electrodes', icephys_spec.get_neurodata_type('IntracellularElectrode')) self.map_spec('sweep_table', icephys_spec.get_neurodata_type('SweepTable')) # TODO map the filtering dataset to something or deprecate it self.unmap(icephys_spec.get_dataset('filtering')) ecephys_spec = general_spec.get_group('extracellular_ephys') self.unmap(ecephys_spec) self.map_spec('electrodes', ecephys_spec.get_group('electrodes')) self.map_spec('electrode_groups', ecephys_spec.get_neurodata_type('ElectrodeGroup')) ogen_spec = general_spec.get_group('optogenetics') self.unmap(ogen_spec) self.map_spec('ogen_sites', ogen_spec.get_neurodata_type('OptogeneticStimulusSite')) ophys_spec = general_spec.get_group('optophysiology') self.unmap(ophys_spec) self.map_spec('imaging_planes', ophys_spec.get_neurodata_type('ImagingPlane')) general_datasets = ['data_collection', 'experiment_description', 'experimenter', 'institution', 'keywords', 'lab', 'notes', 'pharmacology', 'protocol', 'related_publications', 'session_id', 'slices', 'source_script', 'stimulus', 'surgery', 'virus'] for dataset_name in general_datasets: self.map_spec(dataset_name, general_spec.get_dataset(dataset_name)) # note: constructor arg and property 'stimulus' is already mapped above, so use a different name here self.map_spec('stimulus_notes', general_spec.get_dataset('stimulus')) self.map_spec('source_script_file_name', general_spec.get_dataset('source_script').get_attribute('file_name')) self.map_spec('subject', general_spec.get_group('subject')) device_spec = general_spec.get_group('devices') self.unmap(device_spec) self.map_spec('devices', device_spec.get_neurodata_type('Device')) self.map_spec('lab_meta_data', general_spec.get_neurodata_type('LabMetaData')) proc_spec = self.spec.get_group('processing') self.unmap(proc_spec) self.map_spec('processing', proc_spec.get_neurodata_type('ProcessingModule')) scratch_spec = self.spec.get_group('scratch') self.unmap(scratch_spec) self.map_spec('scratch_datas', scratch_spec.get_neurodata_type('ScratchData')) self.map_spec('scratch_containers', scratch_spec.get_neurodata_type('NWBContainer')) self.map_spec('scratch_containers', scratch_spec.get_neurodata_type('DynamicTable')) @ObjectMapper.object_attr('scratch_datas') def scratch_datas(self, container, manager): scratch = container.scratch ret = list() for s in scratch.values(): if isinstance(s, ScratchData): ret.append(s) return ret @ObjectMapper.object_attr('scratch_containers') def scratch_containers(self, container, manager): scratch = container.scratch ret = list() for s in scratch.values(): if not isinstance(s, ScratchData): ret.append(s) return ret @ObjectMapper.constructor_arg('scratch') def scratch(self, builder, manager): scratch = builder.get('scratch') ret = list() if scratch is not None: for g in scratch.groups.values(): ret.append(manager.construct(g)) for d in scratch.datasets.values(): ret.append(manager.construct(d)) return tuple(ret) if len(ret) > 0 else None @ObjectMapper.constructor_arg('session_start_time') def dateconversion(self, builder, manager): datestr = builder.get('session_start_time').data date = dateutil_parse(datestr) return date @ObjectMapper.constructor_arg('timestamps_reference_time') def dateconversion_trt(self, builder, manager): datestr = builder.get('timestamps_reference_time').data date = dateutil_parse(datestr) return date @ObjectMapper.constructor_arg('file_create_date') def dateconversion_list(self, builder, manager): datestr = builder.get('file_create_date').data dates = list(map(dateutil_parse, datestr)) return dates @ObjectMapper.constructor_arg('file_name') def name(self, builder, manager): return builder.name @ObjectMapper.constructor_arg('experimenter') def experimenter_carg(self, builder, manager): ret = None exp_bldr = builder['general'].get('experimenter') if exp_bldr is not None: if isinstance(exp_bldr.data, str): ret = (exp_bldr.data,) else: ret = tuple(exp_bldr.data) return ret @ObjectMapper.object_attr('experimenter') def experimenter_obj_attr(self, container, manager): ret = None if isinstance(container.experimenter, str): ret = (container.experimenter,) return ret @ObjectMapper.constructor_arg('related_publications') def publications_carg(self, builder, manager): ret = None pubs_bldr = builder['general'].get('related_publications') if pubs_bldr is not None: if isinstance(pubs_bldr.data, str): ret = (pubs_bldr.data,) else: ret = tuple(pubs_bldr.data) return ret @ObjectMapper.object_attr('related_publications') def publication_obj_attr(self, container, manager): ret = None if isinstance(container.related_publications, str): ret = (container.related_publications,) return ret @register_map(Subject) class SubjectMap(ObjectMapper): @ObjectMapper.constructor_arg('date_of_birth') def dateconversion(self, builder, manager): dob_builder = builder.get('date_of_birth') if dob_builder is None: return else: datestr = dob_builder.data date = dateutil_parse(datestr) return date pynwb-1.2.1/src/pynwb/io/epoch.py0000644000655200065520000000030513612200244020235 0ustar circlecicircleci00000000000000from .. import register_map from pynwb.epoch import TimeIntervals from hdmf.common.io.table import DynamicTableMap @register_map(TimeIntervals) class TimeIntervalsMap(DynamicTableMap): pass pynwb-1.2.1/src/pynwb/io/__init__.py0000644000655200065520000000060213612200244020676 0ustar circlecicircleci00000000000000from . import base as __base from . import core as __core from . import file as __file from . import behavior as __behavior from . import ecephys as __ecephys from . import epoch as __epoch from . import icephys as __icephys from . import image as __image from . import misc as __misc from . import ogen as __ogen from . import ophys as __ophys from . import retinotopy as __retinotopy pynwb-1.2.1/src/pynwb/io/behavior.py0000644000655200065520000000000013612200244020726 0ustar circlecicircleci00000000000000pynwb-1.2.1/src/pynwb/io/retinotopy.py0000644000655200065520000000000013612200244021343 0ustar circlecicircleci00000000000000pynwb-1.2.1/src/pynwb/io/base.py0000644000655200065520000000615713612200244020064 0ustar circlecicircleci00000000000000from .core import NWBContainerMapper from .. import register_map from ..base import TimeSeries, ProcessingModule from hdmf.build import LinkBuilder @register_map(ProcessingModule) class ModuleMap(NWBContainerMapper): def __init__(self, spec): super(ModuleMap, self).__init__(spec) containers_spec = self.spec.get_neurodata_type('NWBDataInterface') table_spec = self.spec.get_neurodata_type('DynamicTable') self.map_spec('data_interfaces', containers_spec) self.map_spec('data_interfaces', table_spec) @NWBContainerMapper.constructor_arg('name') def name(self, builder, manager): return builder.name @register_map(TimeSeries) class TimeSeriesMap(NWBContainerMapper): def __init__(self, spec): super(TimeSeriesMap, self).__init__(spec) data_spec = self.spec.get_dataset('data') self.map_spec('unit', data_spec.get_attribute('unit')) self.map_spec('resolution', data_spec.get_attribute('resolution')) self.map_spec('conversion', data_spec.get_attribute('conversion')) timestamps_spec = self.spec.get_dataset('timestamps') self.map_spec('timestamps_unit', timestamps_spec.get_attribute('unit')) self.map_spec('interval', timestamps_spec.get_attribute('interval')) startingtime_spec = self.spec.get_dataset('starting_time') self.map_spec('starting_time_unit', startingtime_spec.get_attribute('unit')) self.map_spec('rate', startingtime_spec.get_attribute('rate')) # TODO map the sync group to something sync_spec = self.spec.get_group('sync') self.unmap(sync_spec) @NWBContainerMapper.constructor_arg('name') def name(self, builder, manager): return builder.name @NWBContainerMapper.object_attr("timestamps") def timestamps_attr(self, container, manager): ret = container.fields.get('timestamps') if isinstance(ret, TimeSeries): owner = ret curr = owner.fields.get('timestamps') while isinstance(curr, TimeSeries): owner = curr curr = owner.fields.get('timestamps') ts_builder = manager.build(owner) tstamps_builder = ts_builder['timestamps'] ret = LinkBuilder(tstamps_builder, 'timestamps') return ret @NWBContainerMapper.constructor_arg("timestamps") def timestamps_carg(self, builder, manager): tstamps_builder = builder.get('timestamps') if tstamps_builder is None: return None if isinstance(tstamps_builder, LinkBuilder): # if the parent of our target is available, return the parent object # Otherwise, return the dataset in the target builder # # NOTE: it is not available when data is externally linked # and we haven't explicitly read that file if tstamps_builder.builder.parent is not None: target = tstamps_builder.builder return manager.construct(target.parent) else: return tstamps_builder.builder.data else: return tstamps_builder.data pynwb-1.2.1/src/pynwb/io/ophys.py0000644000655200065520000000154313612200244020306 0ustar circlecicircleci00000000000000from .. import register_map from ..ophys import PlaneSegmentation, ImagingPlane from .core import NWBContainerMapper from hdmf.common.io.table import DynamicTableMap @register_map(PlaneSegmentation) class PlaneSegmentationMap(DynamicTableMap): def __init__(self, spec): super(PlaneSegmentationMap, self).__init__(spec) reference_images_spec = self.spec.get_group('reference_images').get_neurodata_type('ImageSeries') self.map_spec('reference_images', reference_images_spec) @register_map(ImagingPlane) class ImagingPlaneMap(NWBContainerMapper): def __init__(self, spec): super(ImagingPlaneMap, self).__init__(spec) manifold_spec = self.spec.get_dataset('manifold') self.map_spec('unit', manifold_spec.get_attribute('unit')) self.map_spec('conversion', manifold_spec.get_attribute('conversion')) pynwb-1.2.1/src/pynwb/io/ogen.py0000644000655200065520000000000013612200244020057 0ustar circlecicircleci00000000000000pynwb-1.2.1/src/pynwb/io/core.py0000644000655200065520000000230113612200244020065 0ustar circlecicircleci00000000000000from hdmf.build import ObjectMapper, RegionBuilder from .. import register_map from pynwb.file import NWBFile from pynwb.core import NWBData, NWBContainer class NWBBaseTypeMapper(ObjectMapper): @staticmethod def get_nwb_file(container): curr = container while curr is not None: if isinstance(curr, NWBFile): return curr curr = container.parent @register_map(NWBContainer) class NWBContainerMapper(NWBBaseTypeMapper): pass @register_map(NWBData) class NWBDataMap(NWBBaseTypeMapper): @ObjectMapper.constructor_arg('name') def carg_name(self, builder, manager): return builder.name @ObjectMapper.constructor_arg('data') def carg_data(self, builder, manager): return builder.data class NWBTableRegionMap(NWBDataMap): @ObjectMapper.constructor_arg('table') def carg_table(self, builder, manager): return manager.construct(builder.data.builder) @ObjectMapper.constructor_arg('region') def carg_region(self, builder, manager): if not isinstance(builder.data, RegionBuilder): raise ValueError("'builder' must be a RegionBuilder") return builder.data.region pynwb-1.2.1/src/pynwb/io/ecephys.py0000644000655200065520000000000013612200244020567 0ustar circlecicircleci00000000000000pynwb-1.2.1/src/pynwb/io/misc.py0000644000655200065520000000103413612200244020072 0ustar circlecicircleci00000000000000from .. import register_map from hdmf.common.io.table import DynamicTableMap from pynwb.misc import Units @register_map(Units) class UnitsMap(DynamicTableMap): @DynamicTableMap.object_attr("electrodes") def electrodes_column(self, container, manager): ret = container.get('electrodes') if ret is None: return ret # set the electrode table if it hasn't been set yet if ret.target.table is None: ret.target.table = self.get_nwb_file(container).electrodes return ret pynwb-1.2.1/src/pynwb/io/icephys.py0000644000655200065520000000172213612200244020607 0ustar circlecicircleci00000000000000from .. import register_map from pynwb.icephys import SweepTable, VoltageClampSeries from hdmf.common.io.table import DynamicTableMap from .base import TimeSeriesMap @register_map(SweepTable) class SweepTableMap(DynamicTableMap): pass @register_map(VoltageClampSeries) class VoltageClampSeriesMap(TimeSeriesMap): def __init__(self, spec): super(VoltageClampSeriesMap, self).__init__(spec) fields_with_unit = ('capacitance_fast', 'capacitance_slow', 'resistance_comp_bandwidth', 'resistance_comp_correction', 'resistance_comp_prediction', 'whole_cell_capacitance_comp', 'whole_cell_series_resistance_comp') for field in fields_with_unit: field_spec = self.spec.get_dataset(field) self.map_spec('%s__unit' % field, field_spec.get_attribute('unit')) pynwb-1.2.1/src/pynwb.egg-info/0000755000655200065520000000000013612200376017660 5ustar circlecicircleci00000000000000pynwb-1.2.1/src/pynwb.egg-info/dependency_links.txt0000644000655200065520000000000113612200376023726 0ustar circlecicircleci00000000000000 pynwb-1.2.1/src/pynwb.egg-info/requires.txt0000644000655200065520000000010713612200376022256 0ustar circlecicircleci00000000000000h5py>=2.9 hdmf<2,>=1.5.4 numpy>=1.16 pandas>=0.23 python-dateutil>=2.7 pynwb-1.2.1/src/pynwb.egg-info/not-zip-safe0000644000655200065520000000000113612200275022104 0ustar circlecicircleci00000000000000 pynwb-1.2.1/src/pynwb.egg-info/SOURCES.txt0000644000655200065520000000710313612200376021545 0ustar circlecicircleci00000000000000Legal.txt MANIFEST.in README.rst license.txt requirements-dev.txt requirements-doc.txt requirements-min.txt requirements.txt setup.cfg setup.py test.py tox.ini versioneer.py src/pynwb/__init__.py src/pynwb/_version.py src/pynwb/base.py src/pynwb/behavior.py src/pynwb/core.py src/pynwb/device.py src/pynwb/ecephys.py src/pynwb/epoch.py src/pynwb/file.py src/pynwb/icephys.py src/pynwb/image.py src/pynwb/misc.py src/pynwb/ogen.py src/pynwb/ophys.py src/pynwb/retinotopy.py src/pynwb/spec.py src/pynwb/validate.py src/pynwb.egg-info/PKG-INFO src/pynwb.egg-info/SOURCES.txt src/pynwb.egg-info/dependency_links.txt src/pynwb.egg-info/not-zip-safe src/pynwb.egg-info/requires.txt src/pynwb.egg-info/top_level.txt src/pynwb/io/__init__.py src/pynwb/io/base.py src/pynwb/io/behavior.py src/pynwb/io/core.py src/pynwb/io/ecephys.py src/pynwb/io/epoch.py src/pynwb/io/file.py src/pynwb/io/icephys.py src/pynwb/io/image.py src/pynwb/io/misc.py src/pynwb/io/ogen.py src/pynwb/io/ophys.py src/pynwb/io/retinotopy.py src/pynwb/legacy/__init__.py src/pynwb/legacy/map.py src/pynwb/legacy/io/__init__.py src/pynwb/legacy/io/base.py src/pynwb/legacy/io/behavior.py src/pynwb/legacy/io/ecephys.py src/pynwb/legacy/io/epoch.py src/pynwb/legacy/io/file.py src/pynwb/legacy/io/icephys.py src/pynwb/legacy/io/image.py src/pynwb/legacy/io/misc.py src/pynwb/legacy/io/ogen.py src/pynwb/legacy/io/ophys.py src/pynwb/legacy/io/retinotopy.py src/pynwb/nwb-schema/core/nwb.base.yaml src/pynwb/nwb-schema/core/nwb.behavior.yaml src/pynwb/nwb-schema/core/nwb.ecephys.yaml src/pynwb/nwb-schema/core/nwb.epoch.yaml src/pynwb/nwb-schema/core/nwb.file.yaml src/pynwb/nwb-schema/core/nwb.icephys.yaml src/pynwb/nwb-schema/core/nwb.image.yaml src/pynwb/nwb-schema/core/nwb.misc.yaml src/pynwb/nwb-schema/core/nwb.namespace.yaml src/pynwb/nwb-schema/core/nwb.ogen.yaml src/pynwb/nwb-schema/core/nwb.ophys.yaml src/pynwb/nwb-schema/core/nwb.retinotopy.yaml src/pynwb/testing/__init__.py src/pynwb/testing/make_test_files.py src/pynwb/testing/testh5io.py src/pynwb/testing/utils.py tests/__init__.py tests/coloredtestrunner.py tests/back_compat/1.0.2_nwbfile.nwb tests/back_compat/1.0.2_str_experimenter.nwb tests/back_compat/1.0.2_str_pub.nwb tests/back_compat/1.0.3_nwbfile.nwb tests/back_compat/1.0.3_str_experimenter.nwb tests/back_compat/1.0.3_str_pub.nwb tests/back_compat/1.1.0_nwbfile.nwb tests/back_compat/1.1.0_str_experimenter.nwb tests/back_compat/1.1.0_str_pub.nwb tests/back_compat/1.1.2_nwbfile.nwb tests/back_compat/1.1.2_str_experimenter.nwb tests/back_compat/1.1.2_str_pub.nwb tests/back_compat/__init__.py tests/back_compat/test_read.py tests/coverage/runCoverage tests/integration/__init__.py tests/integration/test_io.py tests/integration/hdf5/__init__.py tests/integration/hdf5/test_base.py tests/integration/hdf5/test_device.py tests/integration/hdf5/test_ecephys.py tests/integration/hdf5/test_icephys.py tests/integration/hdf5/test_image.py tests/integration/hdf5/test_misc.py tests/integration/hdf5/test_modular_storage.py tests/integration/hdf5/test_nwbfile.py tests/integration/hdf5/test_ogen.py tests/integration/hdf5/test_ophys.py tests/integration/hdf5/test_scratch.py tests/unit/__init__.py tests/unit/test_MultiContainerInterface.py tests/unit/test_base.py tests/unit/test_behavior.py tests/unit/test_core.py tests/unit/test_core_NWBContainer.py tests/unit/test_device.py tests/unit/test_ecephys.py tests/unit/test_epoch.py tests/unit/test_extension.py tests/unit/test_file.py tests/unit/test_icephys.py tests/unit/test_image.py tests/unit/test_misc.py tests/unit/test_ogen.py tests/unit/test_ophys.py tests/unit/test_retinotopy.py tests/unit/test_spec.pypynwb-1.2.1/src/pynwb.egg-info/top_level.txt0000644000655200065520000000000613612200376022406 0ustar circlecicircleci00000000000000pynwb pynwb-1.2.1/src/pynwb.egg-info/PKG-INFO0000644000655200065520000002064413612200376020763 0ustar circlecicircleci00000000000000Metadata-Version: 2.1 Name: pynwb Version: 1.2.1 Summary: Package for working with Neurodata stored in the NWB format Home-page: https://github.com/NeurodataWithoutBorders/pynwb Author: Andrew Tritt Author-email: ajtritt@lbl.gov License: BSD Description: ===== PyNWB ===== Documentation of PyNWB can be found at https://pynwb.readthedocs.io Latest Release ============== .. image:: https://badge.fury.io/py/pynwb.svg :target: https://badge.fury.io/py/pynwb .. image:: https://anaconda.org/conda-forge/pynwb/badges/version.svg :target: https://anaconda.org/conda-forge/pynwb Build Status ============ .. table:: +-----------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------+ | Linux | Windows and MacOS | +=========================================================================================+=================================================================================================================================+ | .. image:: https://circleci.com/gh/NeurodataWithoutBorders/pynwb.svg?style=shield | .. image:: https://dev.azure.com/NeurodataWithoutBorders/pynwb/_apis/build/status/NeurodataWithoutBorders.pynwb?branchName=dev | | :target: https://circleci.com/gh/NeurodataWithoutBorders/pynwb | :target: https://dev.azure.com/NeurodataWithoutBorders/pynwb/_build/latest?definitionId=3&branchName=dev | +-----------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------+ **Conda** .. image:: https://circleci.com/gh/conda-forge/pynwb-feedstock.svg?style=shield :target: https://circleci.com/gh/conda-forge/pynwb-feedstocks Overall Health ============== .. image:: https://codecov.io/gh/NeurodataWithoutBorders/pynwb/branch/dev/graph/badge.svg :target: https://codecov.io/gh/NeurodataWithoutBorders/pynwb .. image:: https://requires.io/github/NeurodataWithoutBorders/pynwb/requirements.svg?branch=dev :target: https://requires.io/github/NeurodataWithoutBorders/pynwb/requirements/?branch=dev :alt: Requirements Status NWB Format API ============== PyNWB is a Python package for working with NWB files. It provides a high-level API for efficiently working with Neurodata stored in the `NWB format `_. `Neurodata Without Borders: Neurophysiology (NWB:N) `_ is a project to develop a unified data format for cellular-based neurophysiology data, focused on the dynamics of groups of neurons measured under a large range of experimental conditions. The NWB:N team consists of neuroscientists and software developers who recognize that adoption of a unified data format is an important step toward breaking down the barriers to data sharing in neuroscience. Installation ============ See the PyNWB documentation for details http://pynwb.readthedocs.io/en/latest/getting_started.html#installation Code of Conduct =============== This project and everyone participating in it is governed by our `code of conduct guidelines <.github/CODE_OF_CONDUCT.rst>`_. By participating, you are expected to uphold this code. Contributing ============ For details on how to contribute to PyNWB see our `contribution guidelines `_. LICENSE ======= "pynwb" Copyright (c) 2017-2019, The Regents of the University of California, through Lawrence Berkeley National Laboratory (subject to receipt of any required approvals from the U.S. Dept. of Energy). All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: (1) Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. (2) Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. (3) Neither the name of the University of California, Lawrence Berkeley National Laboratory, U.S. Dept. of Energy nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. You are under no obligation whatsoever to provide any bug fixes, patches, or upgrades to the features, functionality or performance of the source code ("Enhancements") to anyone; however, if you choose to make your Enhancements available either publicly, or directly to Lawrence Berkeley National Laboratory, without imposing a separate written license agreement for such Enhancements, then you hereby grant the following license: a non-exclusive, royalty-free perpetual license to install, use, modify, prepare derivative works, incorporate into other computer software, distribute, and sublicense such enhancements or derivative works thereof, in binary and source code form. COPYRIGHT ========= "pynwb" Copyright (c) 2017-2019, The Regents of the University of California, through Lawrence Berkeley National Laboratory (subject to receipt of any required approvals from the U.S. Dept. of Energy). All rights reserved. If you have questions about your rights to use or distribute this software, please contact Berkeley Lab's Innovation & Partnerships Office at IPO@lbl.gov. NOTICE. This Software was developed under funding from the U.S. Department of Energy and the U.S. Government consequently retains certain rights. As such, the U.S. Government has been granted for itself and others acting on its behalf a paid-up, nonexclusive, irrevocable, worldwide license in the Software to reproduce, distribute copies to the public, prepare derivative works, and perform publicly and display publicly, and to permit other to do so. Keywords: Neuroscience python HDF HDF5 cross-platform open-data data-format open-source open-science reproducible-research PyNWB NWB NWB:N NeurodataWithoutBorders Platform: UNKNOWN Classifier: Programming Language :: Python Classifier: Programming Language :: Python :: 3.5 Classifier: Programming Language :: Python :: 3.6 Classifier: Programming Language :: Python :: 3.7 Classifier: License :: OSI Approved :: BSD License Classifier: Development Status :: 2 - Pre-Alpha Classifier: Intended Audience :: Developers Classifier: Intended Audience :: Science/Research Classifier: Operating System :: Microsoft :: Windows Classifier: Operating System :: MacOS Classifier: Operating System :: Unix Classifier: Topic :: Scientific/Engineering :: Medical Science Apps. Description-Content-Type: text/x-rst; charset=UTF-8 pynwb-1.2.1/requirements-doc.txt0000644000655200065520000000010213612200244020252 0ustar circlecicircleci00000000000000sphinx matplotlib sphinx_rtd_theme sphinx-gallery allensdk==1.3.2 pynwb-1.2.1/requirements.txt0000644000655200065520000000011513612200244017513 0ustar circlecicircleci00000000000000h5py==2.10.0 hdmf==1.5.4 numpy==1.18.1 pandas==0.25.3 python-dateutil==2.8.0 pynwb-1.2.1/requirements-min.txt0000644000655200065520000000033313612200244020276 0ustar circlecicircleci00000000000000# these minimum requirements specify '==' for testing; setup.py replaces '==' with '>=' h5py==2.9 # support for setting attrs to lists of utf-8 added in 2.9 hdmf==1.5.4,<2 numpy==1.16 pandas==0.23 python-dateutil==2.7 pynwb-1.2.1/PKG-INFO0000644000655200065520000002064413612200376015343 0ustar circlecicircleci00000000000000Metadata-Version: 2.1 Name: pynwb Version: 1.2.1 Summary: Package for working with Neurodata stored in the NWB format Home-page: https://github.com/NeurodataWithoutBorders/pynwb Author: Andrew Tritt Author-email: ajtritt@lbl.gov License: BSD Description: ===== PyNWB ===== Documentation of PyNWB can be found at https://pynwb.readthedocs.io Latest Release ============== .. image:: https://badge.fury.io/py/pynwb.svg :target: https://badge.fury.io/py/pynwb .. image:: https://anaconda.org/conda-forge/pynwb/badges/version.svg :target: https://anaconda.org/conda-forge/pynwb Build Status ============ .. table:: +-----------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------+ | Linux | Windows and MacOS | +=========================================================================================+=================================================================================================================================+ | .. image:: https://circleci.com/gh/NeurodataWithoutBorders/pynwb.svg?style=shield | .. image:: https://dev.azure.com/NeurodataWithoutBorders/pynwb/_apis/build/status/NeurodataWithoutBorders.pynwb?branchName=dev | | :target: https://circleci.com/gh/NeurodataWithoutBorders/pynwb | :target: https://dev.azure.com/NeurodataWithoutBorders/pynwb/_build/latest?definitionId=3&branchName=dev | +-----------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------+ **Conda** .. image:: https://circleci.com/gh/conda-forge/pynwb-feedstock.svg?style=shield :target: https://circleci.com/gh/conda-forge/pynwb-feedstocks Overall Health ============== .. image:: https://codecov.io/gh/NeurodataWithoutBorders/pynwb/branch/dev/graph/badge.svg :target: https://codecov.io/gh/NeurodataWithoutBorders/pynwb .. image:: https://requires.io/github/NeurodataWithoutBorders/pynwb/requirements.svg?branch=dev :target: https://requires.io/github/NeurodataWithoutBorders/pynwb/requirements/?branch=dev :alt: Requirements Status NWB Format API ============== PyNWB is a Python package for working with NWB files. It provides a high-level API for efficiently working with Neurodata stored in the `NWB format `_. `Neurodata Without Borders: Neurophysiology (NWB:N) `_ is a project to develop a unified data format for cellular-based neurophysiology data, focused on the dynamics of groups of neurons measured under a large range of experimental conditions. The NWB:N team consists of neuroscientists and software developers who recognize that adoption of a unified data format is an important step toward breaking down the barriers to data sharing in neuroscience. Installation ============ See the PyNWB documentation for details http://pynwb.readthedocs.io/en/latest/getting_started.html#installation Code of Conduct =============== This project and everyone participating in it is governed by our `code of conduct guidelines <.github/CODE_OF_CONDUCT.rst>`_. By participating, you are expected to uphold this code. Contributing ============ For details on how to contribute to PyNWB see our `contribution guidelines `_. LICENSE ======= "pynwb" Copyright (c) 2017-2019, The Regents of the University of California, through Lawrence Berkeley National Laboratory (subject to receipt of any required approvals from the U.S. Dept. of Energy). All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: (1) Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. (2) Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. (3) Neither the name of the University of California, Lawrence Berkeley National Laboratory, U.S. Dept. of Energy nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. You are under no obligation whatsoever to provide any bug fixes, patches, or upgrades to the features, functionality or performance of the source code ("Enhancements") to anyone; however, if you choose to make your Enhancements available either publicly, or directly to Lawrence Berkeley National Laboratory, without imposing a separate written license agreement for such Enhancements, then you hereby grant the following license: a non-exclusive, royalty-free perpetual license to install, use, modify, prepare derivative works, incorporate into other computer software, distribute, and sublicense such enhancements or derivative works thereof, in binary and source code form. COPYRIGHT ========= "pynwb" Copyright (c) 2017-2019, The Regents of the University of California, through Lawrence Berkeley National Laboratory (subject to receipt of any required approvals from the U.S. Dept. of Energy). All rights reserved. If you have questions about your rights to use or distribute this software, please contact Berkeley Lab's Innovation & Partnerships Office at IPO@lbl.gov. NOTICE. This Software was developed under funding from the U.S. Department of Energy and the U.S. Government consequently retains certain rights. As such, the U.S. Government has been granted for itself and others acting on its behalf a paid-up, nonexclusive, irrevocable, worldwide license in the Software to reproduce, distribute copies to the public, prepare derivative works, and perform publicly and display publicly, and to permit other to do so. Keywords: Neuroscience python HDF HDF5 cross-platform open-data data-format open-source open-science reproducible-research PyNWB NWB NWB:N NeurodataWithoutBorders Platform: UNKNOWN Classifier: Programming Language :: Python Classifier: Programming Language :: Python :: 3.5 Classifier: Programming Language :: Python :: 3.6 Classifier: Programming Language :: Python :: 3.7 Classifier: License :: OSI Approved :: BSD License Classifier: Development Status :: 2 - Pre-Alpha Classifier: Intended Audience :: Developers Classifier: Intended Audience :: Science/Research Classifier: Operating System :: Microsoft :: Windows Classifier: Operating System :: MacOS Classifier: Operating System :: Unix Classifier: Topic :: Scientific/Engineering :: Medical Science Apps. Description-Content-Type: text/x-rst; charset=UTF-8 pynwb-1.2.1/tests/0000755000655200065520000000000013612200376015402 5ustar circlecicircleci00000000000000pynwb-1.2.1/tests/coverage/0000755000655200065520000000000013612200376017175 5ustar circlecicircleci00000000000000pynwb-1.2.1/tests/coverage/runCoverage0000755000655200065520000000044713612200244021402 0ustar circlecicircleci00000000000000#!/bin/ksh # use default coverage name COV=coverage3 cd ../.. echo "" echo "Running Tests with Coverage:" ${COV} run --source=. test.py echo "" echo "Creating HTML output:" ${COV} html -d tests/coverage/htmlcov echo "" echo "Open /coverage/htmlcov/index.html to see results." echo "" pynwb-1.2.1/tests/__init__.py0000644000655200065520000000000013612200244017473 0ustar circlecicircleci00000000000000pynwb-1.2.1/tests/unit/0000755000655200065520000000000013612200376016361 5ustar circlecicircleci00000000000000pynwb-1.2.1/tests/unit/test_behavior.py0000644000655200065520000000455513612200244021574 0ustar circlecicircleci00000000000000import numpy as np from pynwb import TimeSeries from pynwb.misc import IntervalSeries from pynwb.behavior import SpatialSeries, BehavioralEpochs, BehavioralEvents, BehavioralTimeSeries, PupilTracking, \ EyeTracking, CompassDirection, Position from pynwb.testing import TestCase class SpatialSeriesConstructor(TestCase): def test_init(self): sS = SpatialSeries('test_sS', np.ones((2, 2)), 'reference_frame', timestamps=[1., 2., 3.]) self.assertEqual(sS.name, 'test_sS') self.assertEqual(sS.unit, 'meters') self.assertEqual(sS.reference_frame, 'reference_frame') class BehavioralEpochsConstructor(TestCase): def test_init(self): data = [0, 1, 0, 1] iS = IntervalSeries('test_iS', data, timestamps=[1., 2., 3.]) bE = BehavioralEpochs(iS) self.assertEqual(bE.interval_series['test_iS'], iS) class BehavioralEventsConstructor(TestCase): def test_init(self): ts = TimeSeries('test_ts', np.ones((2, 2)), 'unit', timestamps=[1., 2., 3.]) bE = BehavioralEvents(ts) self.assertEqual(bE.time_series['test_ts'], ts) class BehavioralTimeSeriesConstructor(TestCase): def test_init(self): ts = TimeSeries('test_ts', np.ones((2, 2)), 'unit', timestamps=[1., 2., 3.]) bts = BehavioralTimeSeries(ts) self.assertEqual(bts.time_series['test_ts'], ts) class PupilTrackingConstructor(TestCase): def test_init(self): ts = TimeSeries('test_ts', np.ones((2, 2)), 'unit', timestamps=[1., 2., 3.]) pt = PupilTracking(ts) self.assertEqual(pt.time_series['test_ts'], ts) class EyeTrackingConstructor(TestCase): def test_init(self): sS = SpatialSeries('test_sS', np.ones((2, 2)), 'reference_frame', timestamps=[1., 2., 3.]) et = EyeTracking(sS) self.assertEqual(et.spatial_series['test_sS'], sS) class CompassDirectionConstructor(TestCase): def test_init(self): sS = SpatialSeries('test_sS', np.ones((2, 2)), 'reference_frame', timestamps=[1., 2., 3.]) cd = CompassDirection(sS) self.assertEqual(cd.spatial_series['test_sS'], sS) class PositionConstructor(TestCase): def test_init(self): sS = SpatialSeries('test_sS', np.ones((2, 2)), 'reference_frame', timestamps=[1., 2., 3.]) pc = Position(sS) self.assertEqual(pc.spatial_series.get('test_sS'), sS) pynwb-1.2.1/tests/unit/test_MultiContainerInterface.py0000644000655200065520000000255513612200244024551 0ustar circlecicircleci00000000000000from hdmf.utils import docval, get_docval from pynwb.file import MultiContainerInterface, NWBDataInterface from pynwb.testing import TestCase class Node(NWBDataInterface): __nwbfields__ = ('name',) @docval({'name': 'name', 'type': str, 'doc': 'the name of this node'}) def __init__(self, **kwargs): super(Node, self).__init__(name=kwargs['name']) class Edge(NWBDataInterface): __nwbfields__ = ('name',) @docval({'name': 'name', 'type': str, 'doc': 'the name of this edge'}) def __init__(self, **kwargs): super(Edge, self).__init__(name=kwargs['name']) class Graph(MultiContainerInterface): """A multicontainer of nodes and undirected edges.""" __nwbfields__ = ('name', 'edges', 'nodes') __clsconf__ = [ { 'attr': 'nodes', 'type': Node, 'add': 'add_node', 'get': 'get_node' }, { 'attr': 'edges', 'type': Edge, 'add': 'add_edge', 'get': 'get_edge' } ] class MCITests(TestCase): def test_constructor(self): dv = get_docval(Graph.__init__) self.assertEqual(dv[0]['name'], 'nodes') self.assertEqual(dv[1]['name'], 'edges') self.assertTupleEqual(dv[0]['type'], (list, tuple, dict, Node)) self.assertTupleEqual(dv[1]['type'], (list, tuple, dict, Edge)) pynwb-1.2.1/tests/unit/test_device.py0000644000655200065520000000035013612200244021221 0ustar circlecicircleci00000000000000from pynwb.device import Device from pynwb.testing import TestCase class DeviceConstructorBoth(TestCase): def test_init(self): device = Device(name='device_name') self.assertEqual(device.name, 'device_name') pynwb-1.2.1/tests/unit/test_epoch.py0000644000655200065520000000701413612200244021064 0ustar circlecicircleci00000000000000import numpy as np import pandas as pd from datetime import datetime from dateutil import tz from pynwb.epoch import TimeIntervals from pynwb import TimeSeries, NWBFile from pynwb.testing import TestCase class TimeIntervalsTest(TestCase): def test_init(self): tstamps = np.arange(1.0, 100.0, 0.1, dtype=np.float) ts = TimeSeries("test_ts", list(range(len(tstamps))), 'unit', timestamps=tstamps) ept = TimeIntervals('epochs', "TimeIntervals unittest") self.assertEqual(ept.name, 'epochs') ept.add_interval(10.0, 20.0, ["test", "unittest", "pynwb"], ts) row = ept[0] self.assertEqual(row.index[0], 0) self.assertEqual(row.loc[0]['start_time'], 10.0) self.assertEqual(row.loc[0]['stop_time'], 20.0) self.assertEqual(row.loc[0]['tags'], ["test", "unittest", "pynwb"]) self.assertEqual(row.loc[0]['timeseries'], [(90, 100, ts)]) def get_timeseries(self): return [ TimeSeries(name='a', timestamps=np.linspace(0, 1, 11)), TimeSeries(name='b', timestamps=np.linspace(0.1, 5, 13)), ] def get_dataframe(self): tsa, tsb = self.get_timeseries() return pd.DataFrame({ 'foo': [1, 2, 3, 4], 'bar': ['fish', 'fowl', 'dog', 'cat'], 'start_time': [0.2, 0.25, 0.30, 0.35], 'stop_time': [0.25, 0.30, 0.40, 0.45], 'timeseries': [[tsa], [tsb], [], [tsb, tsa]], 'keys': ['q', 'w', 'e', 'r'], 'tags': [[], [], ['fizz', 'buzz'], ['qaz']] }) def test_dataframe_roundtrip(self): df = self.get_dataframe() epochs = TimeIntervals.from_dataframe(df, name='test epochs') obtained = epochs.to_dataframe() self.assertIs(obtained.loc[3, 'timeseries'][1], df.loc[3, 'timeseries'][1]) self.assertEqual(obtained.loc[2, 'foo'], df.loc[2, 'foo']) def test_dataframe_roundtrip_drop_ts(self): df = self.get_dataframe() epochs = TimeIntervals.from_dataframe(df, name='test epochs') obtained = epochs.to_dataframe(exclude=set(['timeseries', 'timeseries_index'])) self.assertNotIn('timeseries', obtained.columns) self.assertEqual(obtained.loc[2, 'foo'], df.loc[2, 'foo']) def test_no_tags(self): nwbfile = NWBFile("a file with header data", "NB123A", datetime(1970, 1, 1, tzinfo=tz.tzutc())) df = self.get_dataframe() for i, row in df.iterrows(): nwbfile.add_epoch(start_time=row['start_time'], stop_time=row['stop_time']) def test_from_dataframe(self): df = pd.DataFrame({'start_time': [1., 2., 3.], 'stop_time': [2., 3., 4.], 'label': ['a', 'b', 'c']}, columns=('start_time', 'stop_time', 'label')) ti = TimeIntervals.from_dataframe(df, name='ti_name') self.assertEqual(ti.colnames, ('start_time', 'stop_time', 'label')) self.assertEqual(ti.columns[0].data, [1.0, 2.0, 3.0]) self.assertEqual(ti.columns[2].data, ['a', 'b', 'c']) def test_from_dataframe_missing_required_cols(self): df = pd.DataFrame({'start_time': [1., 2., 3.], 'label': ['a', 'b', 'c']}) with self.assertRaises(ValueError): TimeIntervals.from_dataframe(df, name='ti_name') def test_frorm_dataframe_missing_supplied_col(self): df = pd.DataFrame({'start_time': [1., 2., 3.], 'stop_time': [2., 3., 4.], 'label': ['a', 'b', 'c']}) with self.assertRaises(ValueError): TimeIntervals.from_dataframe(df, name='ti_name', columns=[{'name': 'not there'}]) pynwb-1.2.1/tests/unit/test_retinotopy.py0000644000655200065520000000364713612200244022212 0ustar circlecicircleci00000000000000import numpy as np from pynwb.retinotopy import ImagingRetinotopy, AxisMap, AImage from pynwb.testing import TestCase class ImageRetinotopyConstructor(TestCase): def test_init(self): data = np.ones((2, 2)) field_of_view = [1, 2, 3] dimension = [1, 2, 3] sign_map = AxisMap('sign_map', data, field_of_view, 'unit', dimension) axis_1_phase_map = AxisMap('axis_1_phase', data, field_of_view, 'unit', dimension) axis_1_power_map = AxisMap('axis_1_power', data, field_of_view, 'unit', dimension) axis_2_phase_map = AxisMap('axis_2_phase', data, field_of_view, 'unit', dimension) axis_2_power_map = AxisMap('axis_2_power', data, field_of_view, 'unit', dimension) axis_descriptions = ['altitude', 'azimuth'] data = list() bits_per_pixel = 8 dimension = [3, 4] format = 'raw' field_of_view = [1, 2, 3] focal_depth = 1.0 focal_depth_image = AImage('focal_depth_image', data, bits_per_pixel, dimension, format, field_of_view, focal_depth) vasculature_image = AImage('vasculature', data, bits_per_pixel, dimension, format, field_of_view, focal_depth) ir = ImagingRetinotopy(sign_map, axis_1_phase_map, axis_1_power_map, axis_2_phase_map, axis_2_power_map, axis_descriptions, focal_depth_image, vasculature_image) self.assertEqual(ir.sign_map, sign_map) self.assertEqual(ir.axis_1_phase_map, axis_1_phase_map) self.assertEqual(ir.axis_1_power_map, axis_1_power_map) self.assertEqual(ir.axis_2_phase_map, axis_2_phase_map) self.assertEqual(ir.axis_2_power_map, axis_2_power_map) self.assertEqual(ir.axis_descriptions, axis_descriptions) self.assertEqual(ir.focal_depth_image, focal_depth_image) self.assertEqual(ir.vasculature_image, vasculature_image) pynwb-1.2.1/tests/unit/test_spec.py0000644000655200065520000000160713612200244020722 0ustar circlecicircleci00000000000000''' Tests for NWB specific Spec classes This should really test to make sure neurodata_type_def and neurodata_type_inc gets mapped appropriately when constructors and methods are invoked ''' import json from pynwb.spec import NWBNamespaceBuilder, NWBRefSpec from pynwb.testing import TestCase class NWBNamespaceTest(TestCase): def test_constructor(self): self.ns_builder = NWBNamespaceBuilder("Frank Laboratory NWB Extensions", "franklab", version='0.1') class NWBRefSpecTests(TestCase): def test_constructor(self): spec = NWBRefSpec('TimeSeries', 'object') self.assertEqual(spec.target_type, 'TimeSeries') self.assertEqual(spec.reftype, 'object') json.dumps(spec) # to ensure there are no circular links def test_wrong_reference_type(self): with self.assertRaises(ValueError): NWBRefSpec('TimeSeries', 'unknownreftype') pynwb-1.2.1/tests/unit/test_ecephys.py0000644000655200065520000002431013612200244021424 0ustar circlecicircleci00000000000000import numpy as np from pynwb.ecephys import ElectricalSeries, SpikeEventSeries, EventDetection, Clustering, EventWaveform,\ ClusterWaveforms, LFP, FilteredEphys, FeatureExtraction, ElectrodeGroup from pynwb.device import Device from pynwb.file import ElectrodeTable from pynwb.testing import TestCase from hdmf.common import DynamicTableRegion def make_electrode_table(): table = ElectrodeTable() dev1 = Device('dev1') group = ElectrodeGroup('tetrode1', 'tetrode description', 'tetrode location', dev1) table.add_row(id=1, x=1.0, y=2.0, z=3.0, imp=-1.0, location='CA1', filtering='none', group=group, group_name='tetrode1') table.add_row(id=2, x=1.0, y=2.0, z=3.0, imp=-2.0, location='CA1', filtering='none', group=group, group_name='tetrode1') table.add_row(id=3, x=1.0, y=2.0, z=3.0, imp=-3.0, location='CA1', filtering='none', group=group, group_name='tetrode1') table.add_row(id=4, x=1.0, y=2.0, z=3.0, imp=-4.0, location='CA1', filtering='none', group=group, group_name='tetrode1') return table class ElectricalSeriesConstructor(TestCase): def test_init(self): data = list(range(10)) ts = [0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0] table = make_electrode_table() region = DynamicTableRegion('electrodes', [0, 2], 'the first and third electrodes', table) eS = ElectricalSeries('test_eS', data, region, channel_conversion=[2., 6.3], timestamps=ts) self.assertEqual(eS.name, 'test_eS') self.assertEqual(eS.data, data) self.assertEqual(eS.timestamps, ts) def test_link(self): table = make_electrode_table() region = DynamicTableRegion('electrodes', [0, 2], 'the first and third electrodes', table) ts1 = ElectricalSeries('test_ts1', [0, 1, 2, 3, 4, 5], region, timestamps=[0.0, 0.1, 0.2, 0.3, 0.4, 0.5]) ts2 = ElectricalSeries('test_ts2', ts1, region, timestamps=ts1) ts3 = ElectricalSeries('test_ts3', ts2, region, timestamps=ts2) self.assertEqual(ts2.data, [0, 1, 2, 3, 4, 5]) self.assertEqual(ts2.timestamps, [0.0, 0.1, 0.2, 0.3, 0.4, 0.5]) self.assertEqual(ts3.data, [0, 1, 2, 3, 4, 5]) self.assertEqual(ts3.timestamps, [0.0, 0.1, 0.2, 0.3, 0.4, 0.5]) def test_invalid_data_shape(self): table = make_electrode_table() region = DynamicTableRegion('electrodes', [0, 2], 'the first and third electrodes', table) with self.assertRaisesWith(ValueError, ("ElectricalSeries.__init__: incorrect shape for 'data' (got '(2, 2, 2, " "2)', expected '((None,), (None, None), (None, None, None))')")): ElectricalSeries('test_ts1', np.ones((2, 2, 2, 2)), region, timestamps=[0.0, 0.1, 0.2, 0.3, 0.4, 0.5]) class SpikeEventSeriesConstructor(TestCase): def test_init(self): table = make_electrode_table() region = DynamicTableRegion('electrodes', [1, 3], 'the second and fourth electrodes', table) data = ((1, 1, 1), (2, 2, 2)) timestamps = np.arange(2) sES = SpikeEventSeries('test_sES', data, timestamps, region) self.assertEqual(sES.name, 'test_sES') # self.assertListEqual(sES.data, data) np.testing.assert_array_equal(sES.data, data) np.testing.assert_array_equal(sES.timestamps, timestamps) def test_no_rate(self): table = make_electrode_table() region = DynamicTableRegion('electrodes', [1, 3], 'the second and fourth electrodes', table) data = ((1, 1, 1), (2, 2, 2)) with self.assertRaises(TypeError): SpikeEventSeries('test_sES', data, region, rate=1.) class ElectrodeGroupConstructor(TestCase): def test_init(self): dev1 = Device('dev1') group = ElectrodeGroup('elec1', 'electrode description', 'electrode location', dev1) self.assertEqual(group.name, 'elec1') self.assertEqual(group.description, 'electrode description') self.assertEqual(group.location, 'electrode location') self.assertEqual(group.device, dev1) class EventDetectionConstructor(TestCase): def test_init(self): data = list(range(10)) ts = [0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0] table = make_electrode_table() region = DynamicTableRegion('electrodes', [0, 2], 'the first and third electrodes', table) eS = ElectricalSeries('test_eS', data, region, timestamps=ts) eD = EventDetection('detection_method', eS, (1, 2, 3), (0.1, 0.2, 0.3)) self.assertEqual(eD.detection_method, 'detection_method') self.assertEqual(eD.source_electricalseries, eS) self.assertEqual(eD.source_idx, (1, 2, 3)) self.assertEqual(eD.times, (0.1, 0.2, 0.3)) self.assertEqual(eD.unit, 'seconds') class EventWaveformConstructor(TestCase): def test_init(self): table = make_electrode_table() region = DynamicTableRegion('electrodes', [0, 2], 'the first and third electrodes', table) sES = SpikeEventSeries('test_sES', list(range(10)), list(range(10)), region) ew = EventWaveform(sES) self.assertEqual(ew.spike_event_series['test_sES'], sES) self.assertEqual(ew['test_sES'], ew.spike_event_series['test_sES']) class ClusteringConstructor(TestCase): def test_init(self): times = [1.3, 2.3] num = [3, 4] peak_over_rms = [5.3, 6.3] with self.assertWarnsWith(DeprecationWarning, 'use pynwb.misc.Units or NWBFile.units instead'): cc = Clustering('description', num, peak_over_rms, times) self.assertEqual(cc.description, 'description') self.assertEqual(cc.num, num) self.assertEqual(cc.peak_over_rms, peak_over_rms) self.assertEqual(cc.times, times) class ClusterWaveformsConstructor(TestCase): def test_init(self): times = [1.3, 2.3] num = [3, 4] peak_over_rms = [5.3, 6.3] with self.assertWarnsWith(DeprecationWarning, 'use pynwb.misc.Units or NWBFile.units instead'): cc = Clustering('description', num, peak_over_rms, times) means = [[7.3, 7.3]] stdevs = [[8.3, 8.3]] with self.assertWarnsWith(DeprecationWarning, 'use pynwb.misc.Units or NWBFile.units instead'): cw = ClusterWaveforms(cc, 'filtering', means, stdevs) self.assertEqual(cw.clustering_interface, cc) self.assertEqual(cw.waveform_filtering, 'filtering') self.assertEqual(cw.waveform_mean, means) self.assertEqual(cw.waveform_sd, stdevs) class LFPTest(TestCase): def test_add_electrical_series(self): lfp = LFP() table = make_electrode_table() region = DynamicTableRegion('electrodes', [0, 2], 'the first and third electrodes', table) eS = ElectricalSeries('test_eS', [0, 1, 2, 3], region, timestamps=[0.1, 0.2, 0.3, 0.4]) lfp.add_electrical_series(eS) self.assertEqual(lfp.electrical_series.get('test_eS'), eS) class FilteredEphysTest(TestCase): def test_init(self): table = make_electrode_table() region = DynamicTableRegion('electrodes', [0, 2], 'the first and third electrodes', table) eS = ElectricalSeries('test_eS', [0, 1, 2, 3], region, timestamps=[0.1, 0.2, 0.3, 0.4]) fe = FilteredEphys(eS) self.assertEqual(fe.electrical_series.get('test_eS'), eS) self.assertEqual(fe['test_eS'], fe.electrical_series.get('test_eS')) def test_add_electrical_series(self): fe = FilteredEphys() table = make_electrode_table() region = DynamicTableRegion('electrodes', [0, 2], 'the first and third electrodes', table) eS = ElectricalSeries('test_eS', [0, 1, 2, 3], region, timestamps=[0.1, 0.2, 0.3, 0.4]) fe.add_electrical_series(eS) self.assertEqual(fe.electrical_series.get('test_eS'), eS) self.assertEqual(fe['test_eS'], fe.electrical_series.get('test_eS')) class FeatureExtractionConstructor(TestCase): def test_init(self): event_times = [1.9, 3.5] table = make_electrode_table() region = DynamicTableRegion('electrodes', [0, 2], 'the first and third electrodes', table) description = ['desc1', 'desc2', 'desc3'] features = [[[0, 1, 2], [3, 4, 5]], [[6, 7, 8], [9, 10, 11]]] fe = FeatureExtraction(region, description, event_times, features) self.assertEqual(fe.description, description) self.assertEqual(fe.times, event_times) self.assertEqual(fe.features, features) def test_invalid_init_mismatched_event_times(self): event_times = [] # Need 1 event time but give 0 table = make_electrode_table() electrodes = DynamicTableRegion('electrodes', [0, 2], 'the first and third electrodes', table) description = ['desc1', 'desc2', 'desc3'] features = [[[0, 1, 2], [3, 4, 5]]] self.assertRaises(ValueError, FeatureExtraction, electrodes, description, event_times, features) def test_invalid_init_mismatched_electrodes(self): event_times = [1] table = make_electrode_table() electrodes = DynamicTableRegion('electrodes', [0], 'the first electrodes', table) description = ['desc1', 'desc2', 'desc3'] features = [[[0, 1, 2], [3, 4, 5]]] self.assertRaises(ValueError, FeatureExtraction, electrodes, description, event_times, features) def test_invalid_init_mismatched_description(self): event_times = [1] table = make_electrode_table() electrodes = DynamicTableRegion('electrodes', [0, 2], 'the first and third electrodes', table) description = ['desc1', 'desc2', 'desc3', 'desc4'] # Need 3 descriptions but give 4 features = [[[0, 1, 2], [3, 4, 5]]] self.assertRaises(ValueError, FeatureExtraction, electrodes, description, event_times, features) def test_invalid_init_mismatched_description2(self): event_times = [1] table = make_electrode_table() electrodes = DynamicTableRegion('electrodes', [0, 2], 'the first and third electrodes', table) description = ['desc1', 'desc2', 'desc3'] features = [[0, 1, 2], [3, 4, 5]] # Need 3D feature array but give only 2D array self.assertRaises(ValueError, FeatureExtraction, electrodes, description, event_times, features) pynwb-1.2.1/tests/unit/test_icephys.py0000644000655200065520000001655113612200244021440 0ustar circlecicircleci00000000000000import numpy as np from pynwb.icephys import PatchClampSeries, CurrentClampSeries, IZeroClampSeries, CurrentClampStimulusSeries, \ VoltageClampSeries, VoltageClampStimulusSeries, IntracellularElectrode from pynwb.device import Device from pynwb.testing import TestCase def GetElectrode(): device = Device(name='device_name') elec = IntracellularElectrode('test_iS', device, 'description', 'slice', 'seal', 'location', 'resistance', 'filtering', 'initial_access_resistance') return elec class IntracellularElectrodeConstructor(TestCase): def test_constructor(self): device = Device(name='device_name') elec = IntracellularElectrode('test_iS', device, 'description', 'slice', 'seal', 'location', 'resistance', 'filtering', 'initial_access_resistance') self.assertEqual(elec.name, 'test_iS') self.assertEqual(elec.device, device) self.assertEqual(elec.description, 'description') self.assertEqual(elec.slice, 'slice') self.assertEqual(elec.seal, 'seal') self.assertEqual(elec.location, 'location') self.assertEqual(elec.resistance, 'resistance') self.assertEqual(elec.filtering, 'filtering') self.assertEqual(elec.initial_access_resistance, 'initial_access_resistance') class PatchClampSeriesConstructor(TestCase): def test_default(self): electrode_name = GetElectrode() pCS = PatchClampSeries('test_pCS', list(), 'unit', electrode_name, 1.0, timestamps=list()) self.assertEqual(pCS.name, 'test_pCS') self.assertEqual(pCS.unit, 'unit') self.assertEqual(pCS.electrode, electrode_name) self.assertEqual(pCS.gain, 1.0) def test_sweepNumber_valid(self): electrode_name = GetElectrode() pCS = PatchClampSeries('test_pCS', list(), 'unit', electrode_name, 1.0, timestamps=list(), sweep_number=4711) self.assertEqual(pCS.name, 'test_pCS') self.assertEqual(pCS.unit, 'unit') self.assertEqual(pCS.electrode, electrode_name) self.assertEqual(pCS.gain, 1.0) self.assertEqual(pCS.sweep_number, 4711) def test_sweepNumber_valid_np(self): electrode_name = GetElectrode() pCS = PatchClampSeries('test_pCS', list(), 'unit', electrode_name, 1.0, timestamps=list(), sweep_number=1) self.assertEqual(pCS.name, 'test_pCS') self.assertEqual(pCS.unit, 'unit') self.assertEqual(pCS.electrode, electrode_name) self.assertEqual(pCS.gain, 1.0) self.assertEqual(pCS.sweep_number, np.uint32(1)) def test_sweepNumber_large_and_valid(self): electrode_name = GetElectrode() pCS = PatchClampSeries('test_pCS', list(), 'unit', electrode_name, 1.0, timestamps=list(), sweep_number=np.uint64(2**63-1)) self.assertEqual(pCS.name, 'test_pCS') self.assertEqual(pCS.unit, 'unit') self.assertEqual(pCS.electrode, electrode_name) self.assertEqual(pCS.gain, 1.0) self.assertEqual(pCS.sweep_number, 2**63-1) def test_sweepNumber_throws_with_negative(self): electrode_name = GetElectrode() with self.assertRaises(ValueError): PatchClampSeries('test_pCS', list(), 'unit', electrode_name, 1.0, timestamps=list(), sweep_number=-1) def test_sweepNumber_throws_with_NaN(self): electrode_name = GetElectrode() with self.assertRaises(TypeError): PatchClampSeries('test_pCS', list(), 'unit', electrode_name, 1.0, timestamps=list(), sweep_number=float('nan')) def test_sweepNumber_throws_with_Float(self): electrode_name = GetElectrode() with self.assertRaises(TypeError): PatchClampSeries('test_pCS', list(), 'unit', electrode_name, 1.0, timestamps=list(), sweep_number=1.5) class CurrentClampSeriesConstructor(TestCase): def test_init(self): electrode_name = GetElectrode() cCS = CurrentClampSeries('test_cCS', list(), electrode_name, 1.0, "stimset", 2.0, 3.0, 4.0, timestamps=list()) self.assertEqual(cCS.name, 'test_cCS') self.assertEqual(cCS.unit, 'volts') self.assertEqual(cCS.electrode, electrode_name) self.assertEqual(cCS.stimulus_description, "stimset") self.assertEqual(cCS.gain, 1.0) self.assertEqual(cCS.bias_current, 2.0) self.assertEqual(cCS.bridge_balance, 3.0) self.assertEqual(cCS.capacitance_compensation, 4.0) class IZeroClampSeriesConstructor(TestCase): def test_init(self): electrode_name = GetElectrode() iZCS = IZeroClampSeries('test_iZCS', list(), electrode_name, 1.0, timestamps=list()) self.assertEqual(iZCS.name, 'test_iZCS') self.assertEqual(iZCS.unit, 'volts') self.assertEqual(iZCS.electrode, electrode_name) self.assertEqual(iZCS.gain, 1.0) self.assertEqual(iZCS.bias_current, 0.0) self.assertEqual(iZCS.bridge_balance, 0.0) self.assertEqual(iZCS.capacitance_compensation, 0.0) class CurrentClampStimulusSeriesConstructor(TestCase): def test_init(self): electrode_name = GetElectrode() cCSS = CurrentClampStimulusSeries('test_cCSS', list(), electrode_name, 1.0, timestamps=list()) self.assertEqual(cCSS.name, 'test_cCSS') self.assertEqual(cCSS.unit, 'amperes') self.assertEqual(cCSS.electrode, electrode_name) self.assertEqual(cCSS.gain, 1.0) class VoltageClampSeriesConstructor(TestCase): def test_init(self): electrode_name = GetElectrode() vCS = VoltageClampSeries('test_vCS', list(), electrode_name, 1.0, "stimset", 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, timestamps=list()) self.assertEqual(vCS.name, 'test_vCS') self.assertEqual(vCS.unit, 'amperes') self.assertEqual(vCS.electrode, electrode_name) self.assertEqual(vCS.stimulus_description, "stimset") self.assertEqual(vCS.gain, 1.0) self.assertEqual(vCS.capacitance_fast, 2.0) self.assertEqual(vCS.capacitance_slow, 3.0) self.assertEqual(vCS.resistance_comp_bandwidth, 4.0) self.assertEqual(vCS.resistance_comp_correction, 5.0) self.assertEqual(vCS.resistance_comp_prediction, 6.0) self.assertEqual(vCS.whole_cell_capacitance_comp, 7.0) self.assertEqual(vCS.whole_cell_series_resistance_comp, 8.0) class VoltageClampStimulusSeriesConstructor(TestCase): def test_init(self): electrode_name = GetElectrode() vCSS = VoltageClampStimulusSeries('test_vCSS', list(), electrode_name, 1.0, timestamps=list()) self.assertEqual(vCSS.name, 'test_vCSS') self.assertEqual(vCSS.unit, 'volts') self.assertEqual(vCSS.electrode, electrode_name) pynwb-1.2.1/tests/unit/__init__.py0000644000655200065520000000000013612200244020452 0ustar circlecicircleci00000000000000pynwb-1.2.1/tests/unit/test_ophys.py0000644000655200065520000002601113612200244021126 0ustar circlecicircleci00000000000000import numpy as np from pynwb.ophys import TwoPhotonSeries, RoiResponseSeries, DfOverF, Fluorescence, PlaneSegmentation, \ ImageSegmentation, OpticalChannel, ImagingPlane, MotionCorrection, CorrectedImageStack from pynwb.image import ImageSeries from pynwb.base import TimeSeries from pynwb.device import Device from pynwb.base import ProcessingModule from pynwb.testing import TestCase def CreatePlaneSegmentation(): w, h = 5, 5 img_mask = [[[1.0 for x in range(w)] for y in range(h)], [[2.0 for x in range(w)] for y in range(h)]] pix_mask = [[1, 2, 1.0], [3, 4, 1.0], [5, 6, 1.0], [7, 8, 2.0], [9, 10, 2.0]] iSS = ImageSeries(name='test_iS', data=np.ones((2, 2, 2)), unit='unit', external_file=['external_file'], starting_frame=[1, 2, 3], format='tiff', timestamps=[1., 2.]) oc = OpticalChannel('test_optical_channel', 'description', 500.) device = Device(name='device_name') ip = ImagingPlane('test_imaging_plane', oc, 'description', device, 600., 300., 'indicator', 'location', (1, 2, 1, 2, 3), 4.0, 'unit', 'reference_frame') pS = PlaneSegmentation('description', ip, 'test_name', iSS) pS.add_roi(pixel_mask=pix_mask[0:3], image_mask=img_mask[0]) pS.add_roi(pixel_mask=pix_mask[3:5], image_mask=img_mask[1]) return pS class TwoPhotonSeriesConstructor(TestCase): def test_init(self): oc = OpticalChannel('test_name', 'description', 500.) self.assertEqual(oc.description, 'description') self.assertEqual(oc.emission_lambda, 500.) device = Device(name='device_name') ip = ImagingPlane('test_imaging_plane', oc, 'description', device, 600., 300., 'indicator', 'location', (50, 100, 3), 4.0, 'unit', 'reference_frame') self.assertEqual(ip.optical_channel[0], oc) self.assertEqual(ip.device, device) self.assertEqual(ip.excitation_lambda, 600.) self.assertEqual(ip.imaging_rate, 300.) self.assertEqual(ip.indicator, 'indicator') self.assertEqual(ip.location, 'location') self.assertEqual(ip.manifold, (50, 100, 3)) self.assertEqual(ip.conversion, 4.0) self.assertEqual(ip.unit, 'unit') self.assertEqual(ip.reference_frame, 'reference_frame') tPS = TwoPhotonSeries('test_tPS', unit='unit', field_of_view=[2., 3.], imaging_plane=ip, pmt_gain=1.0, scan_line_rate=2.0, external_file=['external_file'], starting_frame=[1, 2, 3], format='tiff', timestamps=list()) self.assertEqual(tPS.name, 'test_tPS') self.assertEqual(tPS.unit, 'unit') self.assertEqual(tPS.field_of_view, [2., 3.]) self.assertEqual(tPS.imaging_plane, ip) self.assertEqual(tPS.pmt_gain, 1.0) self.assertEqual(tPS.scan_line_rate, 2.0) self.assertEqual(tPS.external_file, ['external_file']) self.assertEqual(tPS.starting_frame, [1, 2, 3]) self.assertEqual(tPS.format, 'tiff') self.assertIsNone(tPS.dimension) def test_args(self): oc = OpticalChannel('test_name', 'description', 500.) device = Device(name='device_name') ip = ImagingPlane('test_imaging_plane', oc, 'description', device, 600., 300., 'indicator', 'location', (50, 100, 3), 4.0, 'unit', 'reference_frame') with self.assertRaises(ValueError): # no data or external file TwoPhotonSeries('test_tPS', unit='unit', field_of_view=[2., 3.], imaging_plane=ip, pmt_gain=1.0, scan_line_rate=2.0, starting_frame=[1, 2, 3], format='tiff', timestamps=[1., 2.]) class MotionCorrectionConstructor(TestCase): def test_init(self): MotionCorrection(list()) class CorrectedImageStackConstructor(TestCase): def test_init(self): is1 = ImageSeries(name='is1', data=np.ones((2, 2, 2)), unit='unit', external_file=['external_file'], starting_frame=[1, 2, 3], format='tiff', timestamps=[1., 2.]) is2 = ImageSeries(name='is2', data=np.ones((2, 2, 2)), unit='unit', external_file=['external_file'], starting_frame=[1, 2, 3], format='tiff', timestamps=[1., 2.]) tstamps = np.arange(1.0, 100.0, 0.1, dtype=np.float) ts = TimeSeries("test_ts", list(range(len(tstamps))), 'unit', timestamps=tstamps) cis = CorrectedImageStack(is1, is2, ts) ProcessingModule('name', 'description').add(cis) self.assertEqual(cis.corrected, is1) self.assertEqual(cis.original, is2) self.assertEqual(cis.xy_translation, ts) class RoiResponseSeriesConstructor(TestCase): def test_init(self): ip = CreatePlaneSegmentation() rt_region = ip.create_roi_table_region('the second ROI', region=[0]) ts = RoiResponseSeries('test_ts', list(), rt_region, unit='unit', timestamps=list()) self.assertEqual(ts.name, 'test_ts') self.assertEqual(ts.unit, 'unit') self.assertEqual(ts.rois, rt_region) class DfOverFConstructor(TestCase): def test_init(self): ip = CreatePlaneSegmentation() rt_region = ip.create_roi_table_region('the second ROI', region=[1]) rrs = RoiResponseSeries('test_ts', list(), rt_region, unit='unit', timestamps=list()) dof = DfOverF(rrs) self.assertEqual(dof.roi_response_series['test_ts'], rrs) class FluorescenceConstructor(TestCase): def test_init(self): ip = CreatePlaneSegmentation() rt_region = ip.create_roi_table_region('the second ROI', region=[1]) ts = RoiResponseSeries('test_ts', list(), rt_region, unit='unit', timestamps=list()) ff = Fluorescence(ts) self.assertEqual(ff.roi_response_series['test_ts'], ts) self.assertEqual(ff.roi_response_series['test_ts'], ts) class ImageSegmentationConstructor(TestCase): def test_init(self): ps = CreatePlaneSegmentation() iS = ImageSegmentation(ps, name='test_iS') self.assertEqual(iS.name, 'test_iS') self.assertEqual(iS.plane_segmentations[ps.name], ps) self.assertEqual(iS[ps.name], iS.plane_segmentations[ps.name]) class PlaneSegmentationConstructor(TestCase): def getBoilerPlateObjects(self): iSS = ImageSeries(name='test_iS', data=np.ones((2, 2, 2)), unit='unit', external_file=['external_file'], starting_frame=[1, 2, 3], format='tiff', timestamps=list()) device = Device(name='device_name') oc = OpticalChannel('test_optical_channel', 'description', 500.) ip = ImagingPlane('test_imaging_plane', oc, 'description', device, 600., 300., 'indicator', 'location', (1, 2, 1, 2, 3), 4.0, 'unit', 'reference_frame') return iSS, ip def create_basic_plane_segmentation(self): """Creates a basic plane segmentation used for testing""" iSS, ip = self.getBoilerPlateObjects() return PlaneSegmentation('description', ip, 'test_name', iSS) def test_init(self): w, h = 5, 5 img_mask = [[[1.0 for x in range(w)] for y in range(h)], [[2.0 for x in range(w)] for y in range(h)]] pix_mask = [[1, 2, 1.0], [3, 4, 1.0], [5, 6, 1.0], [7, 8, 2.0], [9, 10, 2.0]] iSS, ip = self.getBoilerPlateObjects() pS = PlaneSegmentation('description', ip, 'test_name', iSS) pS.add_roi(pixel_mask=pix_mask[0:3], image_mask=img_mask[0]) pS.add_roi(pixel_mask=pix_mask[3:5], image_mask=img_mask[1]) self.assertEqual(pS.description, 'description') self.assertEqual(pS.imaging_plane, ip) self.assertEqual(pS.reference_images, (iSS,)) self.assertEqual(pS['pixel_mask'].target.data, pix_mask) self.assertEqual(pS['pixel_mask'][0], pix_mask[0:3]) self.assertEqual(pS['pixel_mask'][1], pix_mask[3:5]) self.assertEqual(pS['image_mask'].data, img_mask) def test_init_pixel_mask(self): pix_mask = [[1, 2, 1.0], [3, 4, 1.0], [5, 6, 1.0], [7, 8, 2.0], [9, 10, 2.0]] iSS, ip = self.getBoilerPlateObjects() pS = PlaneSegmentation('description', ip, 'test_name', iSS) pS.add_roi(pixel_mask=pix_mask[0:3]) pS.add_roi(pixel_mask=pix_mask[3:5]) self.assertEqual(pS.description, 'description') self.assertEqual(pS.imaging_plane, ip) self.assertEqual(pS.reference_images, (iSS,)) self.assertEqual(pS['pixel_mask'].target.data, pix_mask) self.assertEqual(pS['pixel_mask'][0], pix_mask[0:3]) self.assertEqual(pS['pixel_mask'][1], pix_mask[3:5]) def test_init_voxel_mask(self): vox_mask = [[1, 2, 3, 1.0], [3, 4, 1, 1.0], [5, 6, 3, 1.0], [7, 8, 3, 2.0], [9, 10, 2, 2.0]] iSS, ip = self.getBoilerPlateObjects() pS = PlaneSegmentation('description', ip, 'test_name', iSS) pS.add_roi(voxel_mask=vox_mask[0:3]) pS.add_roi(voxel_mask=vox_mask[3:5]) self.assertEqual(pS.description, 'description') self.assertEqual(pS.imaging_plane, ip) self.assertEqual(pS.reference_images, (iSS,)) self.assertEqual(pS['voxel_mask'].target.data, vox_mask) self.assertEqual(pS['voxel_mask'][0], vox_mask[0:3]) self.assertEqual(pS['voxel_mask'][1], vox_mask[3:5]) def test_init_3d_image_mask(self): img_masks = np.random.randn(2, 20, 30, 4) pS = self.create_basic_plane_segmentation() pS.add_roi(image_mask=img_masks[0]) pS.add_roi(image_mask=img_masks[1]) self.assertTrue(np.allclose(pS['image_mask'][0], img_masks[0])) self.assertTrue(np.allclose(pS['image_mask'][1], img_masks[1])) def test_conversion_of_2d_pixel_mask_to_image_mask(self): pixel_mask = [[0, 0, 1.0], [1, 0, 2.0], [2, 0, 2.0]] pS = self.create_basic_plane_segmentation() img_mask = pS.pixel_to_image(pixel_mask) np.testing.assert_allclose(img_mask, np.asarray([[1, 2, 2.0], [0, 0, 0.0], [0, 0, 0.0]])) def test_conversion_of_2d_image_mask_to_pixel_mask(self): image_mask = np.asarray([[1.0, 0.0, 0.0], [0.0, 1.0, 0.0], [0.0, 0.0, 1.0]]) pS = self.create_basic_plane_segmentation() pixel_mask = pS.image_to_pixel(image_mask) np.testing.assert_allclose(pixel_mask, np.asarray([[0, 0, 1.0], [1, 1, 1.0], [2, 2, 1.0]])) def test_init_image_mask(self): w, h = 5, 5 img_mask = [[[1.0 for x in range(w)] for y in range(h)], [[2.0 for x in range(w)] for y in range(h)]] iSS, ip = self.getBoilerPlateObjects() pS = PlaneSegmentation('description', ip, 'test_name', iSS) pS.add_roi(image_mask=img_mask[0]) pS.add_roi(image_mask=img_mask[1]) self.assertEqual(pS.description, 'description') self.assertEqual(pS.imaging_plane, ip) self.assertEqual(pS.reference_images, (iSS,)) self.assertEqual(pS['image_mask'].data, img_mask) pynwb-1.2.1/tests/unit/test_file.py0000644000655200065520000005576713612200244020727 0ustar circlecicircleci00000000000000import numpy as np import os import pandas as pd from datetime import datetime from dateutil.tz import tzlocal, tzutc from pynwb import NWBFile, TimeSeries, NWBHDF5IO from pynwb.file import Subject, ElectrodeTable from pynwb.epoch import TimeIntervals from pynwb.ecephys import ElectricalSeries from pynwb.testing import TestCase class NWBFileTest(TestCase): def setUp(self): self.start = datetime(2017, 5, 1, 12, 0, 0, tzinfo=tzlocal()) self.ref_time = datetime(1979, 1, 1, 0, tzinfo=tzutc()) self.create = [datetime(2017, 5, 1, 12, tzinfo=tzlocal()), datetime(2017, 5, 2, 13, 0, 0, 1, tzinfo=tzutc()), datetime(2017, 5, 2, 14, tzinfo=tzutc())] self.path = 'nwbfile_test.h5' self.nwbfile = NWBFile('a test session description for a test NWBFile', 'FILE123', self.start, file_create_date=self.create, timestamps_reference_time=self.ref_time, experimenter='A test experimenter', lab='a test lab', institution='a test institution', experiment_description='a test experiment description', session_id='test1', notes='my notes', pharmacology='drugs', protocol='protocol', related_publications='my pubs', slices='my slices', surgery='surgery', virus='a virus', source_script='noscript', source_script_file_name='nofilename', stimulus_notes='test stimulus notes', data_collection='test data collection notes', keywords=('these', 'are', 'keywords')) def test_constructor(self): self.assertEqual(self.nwbfile.session_description, 'a test session description for a test NWBFile') self.assertEqual(self.nwbfile.identifier, 'FILE123') self.assertEqual(self.nwbfile.session_start_time, self.start) self.assertEqual(self.nwbfile.file_create_date, self.create) self.assertEqual(self.nwbfile.lab, 'a test lab') self.assertEqual(self.nwbfile.experimenter, ('A test experimenter',)) self.assertEqual(self.nwbfile.institution, 'a test institution') self.assertEqual(self.nwbfile.experiment_description, 'a test experiment description') self.assertEqual(self.nwbfile.session_id, 'test1') self.assertEqual(self.nwbfile.stimulus_notes, 'test stimulus notes') self.assertEqual(self.nwbfile.data_collection, 'test data collection notes') self.assertEqual(self.nwbfile.related_publications, ('my pubs',)) self.assertEqual(self.nwbfile.source_script, 'noscript') self.assertEqual(self.nwbfile.source_script_file_name, 'nofilename') self.assertEqual(self.nwbfile.keywords, ('these', 'are', 'keywords')) self.assertEqual(self.nwbfile.timestamps_reference_time, self.ref_time) def test_create_electrode_group(self): name = 'example_electrode_group' desc = 'An example electrode' loc = 'an example location' d = self.nwbfile.create_device('a fake device') elecgrp = self.nwbfile.create_electrode_group(name, desc, loc, d) self.assertEqual(elecgrp.description, desc) self.assertEqual(elecgrp.location, loc) self.assertIs(elecgrp.device, d) def test_create_custom_intervals(self): df_words = pd.DataFrame({'start_time': [.1, 2.], 'stop_time': [.8, 2.3], 'label': ['hello', 'there']}) words = TimeIntervals.from_dataframe(df_words, name='words') self.nwbfile.add_time_intervals(words) self.assertEqual(self.nwbfile.intervals['words'], words) def test_create_electrode_group_invalid_index(self): """ Test the case where the user creates an electrode table region with indexes that are out of range of the amount of electrodes added. """ nwbfile = NWBFile('a', 'b', datetime.now(tzlocal())) device = nwbfile.create_device('a') elecgrp = nwbfile.create_electrode_group('a', 'b', device=device, location='a') for i in range(4): nwbfile.add_electrode(np.nan, np.nan, np.nan, np.nan, 'a', 'a', elecgrp, id=i) with self.assertRaises(IndexError): nwbfile.create_electrode_table_region(list(range(6)), 'test') def test_access_group_after_io(self): """ Motivated by #739 """ nwbfile = NWBFile('a', 'b', datetime.now(tzlocal())) device = nwbfile.create_device('a') elecgrp = nwbfile.create_electrode_group('a', 'b', device=device, location='a') nwbfile.add_electrode(np.nan, np.nan, np.nan, np.nan, 'a', 'a', elecgrp, id=0) with NWBHDF5IO('electrodes_mwe.nwb', 'w') as io: io.write(nwbfile) with NWBHDF5IO('electrodes_mwe.nwb', 'a') as io: nwbfile_i = io.read() for aa, bb in zip(nwbfile_i.electrodes['group'][:], nwbfile.electrodes['group'][:]): self.assertEqual(aa.name, bb.name) for i in range(4): nwbfile.add_electrode(np.nan, np.nan, np.nan, np.nan, 'a', 'a', elecgrp, id=i + 1) with NWBHDF5IO('electrodes_mwe.nwb', 'w') as io: io.write(nwbfile) with NWBHDF5IO('electrodes_mwe.nwb', 'a') as io: nwbfile_i = io.read() for aa, bb in zip(nwbfile_i.electrodes['group'][:], nwbfile.electrodes['group'][:]): self.assertEqual(aa.name, bb.name) os.remove("electrodes_mwe.nwb") def test_access_processing(self): self.nwbfile.create_processing_module('test_mod', 'test_description') # test deprecate .modules with self.assertWarnsWith(DeprecationWarning, 'replaced by NWBFile.processing'): modules = self.nwbfile.modules['test_mod'] self.assertIs(self.nwbfile.processing['test_mod'], modules) def test_epoch_tags(self): tags1 = ['t1', 't2'] tags2 = ['t3', 't4'] tstamps = np.arange(1.0, 100.0, 0.1, dtype=np.float) ts = TimeSeries("test_ts", list(range(len(tstamps))), 'unit', timestamps=tstamps) expected_tags = tags1 + tags2 self.nwbfile.add_epoch(0.0, 1.0, tags1, ts) self.nwbfile.add_epoch(0.0, 1.0, tags2, ts) tags = self.nwbfile.epoch_tags self.assertEqual(set(expected_tags), set(tags)) def test_add_acquisition(self): self.nwbfile.add_acquisition(TimeSeries('test_ts', [0, 1, 2, 3, 4, 5], 'grams', timestamps=[0.0, 0.1, 0.2, 0.3, 0.4, 0.5])) self.assertEqual(len(self.nwbfile.acquisition), 1) def test_add_stimulus(self): self.nwbfile.add_stimulus(TimeSeries('test_ts', [0, 1, 2, 3, 4, 5], 'grams', timestamps=[0.0, 0.1, 0.2, 0.3, 0.4, 0.5])) self.assertEqual(len(self.nwbfile.stimulus), 1) def test_add_stimulus_template(self): self.nwbfile.add_stimulus_template(TimeSeries('test_ts', [0, 1, 2, 3, 4, 5], 'grams', timestamps=[0.0, 0.1, 0.2, 0.3, 0.4, 0.5])) self.assertEqual(len(self.nwbfile.stimulus_template), 1) def test_add_analysis(self): self.nwbfile.add_analysis(TimeSeries('test_ts', [0, 1, 2, 3, 4, 5], 'grams', timestamps=[0.0, 0.1, 0.2, 0.3, 0.4, 0.5])) self.assertEqual(len(self.nwbfile.analysis), 1) def test_add_acquisition_check_dups(self): self.nwbfile.add_acquisition(TimeSeries('test_ts', [0, 1, 2, 3, 4, 5], 'grams', timestamps=[0.0, 0.1, 0.2, 0.3, 0.4, 0.5])) with self.assertRaises(ValueError): self.nwbfile.add_acquisition(TimeSeries('test_ts', [0, 1, 2, 3, 4, 5], 'grams', timestamps=[0.0, 0.1, 0.2, 0.3, 0.4, 0.5])) def test_get_acquisition_empty(self): with self.assertRaisesWith(ValueError, "acquisition of NWBFile 'root' is empty"): self.nwbfile.get_acquisition() def test_get_acquisition_multiple_elements(self): self.nwbfile.add_acquisition(TimeSeries('test_ts1', [0, 1, 2, 3, 4, 5], 'grams', timestamps=[0.0, 0.1, 0.2, 0.3, 0.4, 0.5])) self.nwbfile.add_acquisition(TimeSeries('test_ts2', [0, 1, 2, 3, 4, 5], 'grams', timestamps=[0.0, 0.1, 0.2, 0.3, 0.4, 0.5])) msg = "more than one element in acquisition of NWBFile 'root' -- must specify a name" with self.assertRaisesWith(ValueError, msg): self.nwbfile.get_acquisition() def test_add_acquisition_invalid_name(self): self.nwbfile.add_acquisition(TimeSeries('test_ts', [0, 1, 2, 3, 4, 5], 'grams', timestamps=[0.0, 0.1, 0.2, 0.3, 0.4, 0.5])) msg = "\"'TEST_TS' not found in acquisition of NWBFile 'root'\"" with self.assertRaisesWith(KeyError, msg): self.nwbfile.get_acquisition("TEST_TS") def test_set_electrode_table(self): table = ElectrodeTable() dev1 = self.nwbfile.create_device('dev1') group = self.nwbfile.create_electrode_group('tetrode1', 'tetrode description', 'tetrode location', dev1) table.add_row(x=1.0, y=2.0, z=3.0, imp=-1.0, location='CA1', filtering='none', group=group, group_name='tetrode1') table.add_row(x=1.0, y=2.0, z=3.0, imp=-2.0, location='CA1', filtering='none', group=group, group_name='tetrode1') table.add_row(x=1.0, y=2.0, z=3.0, imp=-3.0, location='CA1', filtering='none', group=group, group_name='tetrode1') table.add_row(x=1.0, y=2.0, z=3.0, imp=-4.0, location='CA1', filtering='none', group=group, group_name='tetrode1') self.nwbfile.set_electrode_table(table) self.assertIs(self.nwbfile.electrodes, table) self.assertIs(table.parent, self.nwbfile) def test_add_unit_column(self): self.nwbfile.add_unit_column('unit_type', 'the type of unit') self.assertEqual(self.nwbfile.units.colnames, ('unit_type',)) def test_add_unit(self): self.nwbfile.add_unit(id=1) self.assertEqual(len(self.nwbfile.units), 1) self.nwbfile.add_unit(id=2) self.nwbfile.add_unit(id=3) self.assertEqual(len(self.nwbfile.units), 3) def test_add_trial_column(self): self.nwbfile.add_trial_column('trial_type', 'the type of trial') self.assertEqual(self.nwbfile.trials.colnames, ('start_time', 'stop_time', 'trial_type')) def test_add_trial(self): self.nwbfile.add_trial(start_time=10.0, stop_time=20.0) self.assertEqual(len(self.nwbfile.trials), 1) self.nwbfile.add_trial(start_time=30.0, stop_time=40.0) self.nwbfile.add_trial(start_time=50.0, stop_time=70.0) self.assertEqual(len(self.nwbfile.trials), 3) def test_add_invalid_times_column(self): self.nwbfile.add_invalid_times_column('comments', 'description of reason for omitting time') self.assertEqual(self.nwbfile.invalid_times.colnames, ('start_time', 'stop_time', 'comments')) def test_add_invalid_time_interval(self): self.nwbfile.add_invalid_time_interval(start_time=0.0, stop_time=12.0) self.assertEqual(len(self.nwbfile.invalid_times), 1) self.nwbfile.add_invalid_time_interval(start_time=15.0, stop_time=16.0) self.nwbfile.add_invalid_time_interval(start_time=17.0, stop_time=20.5) self.assertEqual(len(self.nwbfile.invalid_times), 3) def test_add_invalid_time_w_ts(self): ts = TimeSeries(name='name', data=[1.2], rate=1.0, unit='na') self.nwbfile.add_invalid_time_interval(start_time=18.0, stop_time=20.6, timeseries=ts, tags=('hi', 'there')) def test_add_electrode(self): dev1 = self.nwbfile.create_device('dev1') group = self.nwbfile.create_electrode_group('tetrode1', 'tetrode description', 'tetrode location', dev1) self.nwbfile.add_electrode(1.0, 2.0, 3.0, -1.0, 'CA1', 'none', group=group, id=1) elec = self.nwbfile.electrodes[0] self.assertEqual(elec.index[0], 1) self.assertEqual(elec.iloc[0]['x'], 1.0) self.assertEqual(elec.iloc[0]['y'], 2.0) self.assertEqual(elec.iloc[0]['z'], 3.0) self.assertEqual(elec.iloc[0]['location'], 'CA1') self.assertEqual(elec.iloc[0]['filtering'], 'none') self.assertEqual(elec.iloc[0]['group'], group) def test_all_children(self): ts1 = TimeSeries('test_ts1', [0, 1, 2, 3, 4, 5], 'grams', timestamps=[0.0, 0.1, 0.2, 0.3, 0.4, 0.5]) ts2 = TimeSeries('test_ts2', [0, 1, 2, 3, 4, 5], 'grams', timestamps=[0.0, 0.1, 0.2, 0.3, 0.4, 0.5]) self.nwbfile.add_acquisition(ts1) self.nwbfile.add_acquisition(ts2) name = 'example_electrode_group' desc = 'An example electrode' loc = 'an example location' device = self.nwbfile.create_device('a fake device') elecgrp = self.nwbfile.create_electrode_group(name, desc, loc, device) children = self.nwbfile.all_children() self.assertIn(ts1, children) self.assertIn(ts2, children) self.assertIn(device, children) self.assertIn(elecgrp, children) def test_fail_if_source_script_file_name_without_source_script(self): with self.assertRaises(ValueError): # <-- source_script_file_name without source_script is not allowed NWBFile('a test session description for a test NWBFile', 'FILE123', self.start, source_script=None, source_script_file_name='nofilename') def test_get_neurodata_type(self): ts1 = TimeSeries('test_ts1', [0, 1, 2, 3, 4, 5], 'grams', timestamps=[0.0, 0.1, 0.2, 0.3, 0.4, 0.5]) ts2 = TimeSeries('test_ts2', [0, 1, 2, 3, 4, 5], 'grams', timestamps=[0.0, 0.1, 0.2, 0.3, 0.4, 0.5]) self.nwbfile.add_acquisition(ts1) self.nwbfile.add_acquisition(ts2) p1 = ts1.get_ancestor(neurodata_type='NWBFile') self.assertIs(p1, self.nwbfile) p2 = ts2.get_ancestor(neurodata_type='NWBFile') self.assertIs(p2, self.nwbfile) def test_print_units(self): self.nwbfile.add_unit(spike_times=[1., 2., 3.]) expected = """units pynwb.misc.Units at 0x%d Fields: colnames: ['spike_times'] columns: ( spike_times_index , spike_times ) description: Autogenerated by NWBFile id: id """ expected = expected % id(self.nwbfile.units) self.assertEqual(str(self.nwbfile.units), expected) def test_copy(self): self.nwbfile.add_unit(spike_times=[1., 2., 3.]) device = self.nwbfile.create_device('a') elecgrp = self.nwbfile.create_electrode_group('a', 'b', device=device, location='a') self.nwbfile.add_electrode(np.nan, np.nan, np.nan, np.nan, 'a', 'a', elecgrp, id=0) self.nwbfile.add_electrode(np.nan, np.nan, np.nan, np.nan, 'b', 'b', elecgrp) elec_region = self.nwbfile.create_electrode_table_region([1], 'name') ts1 = TimeSeries('test_ts1', [0, 1, 2, 3, 4, 5], 'grams', timestamps=[0.0, 0.1, 0.2, 0.3, 0.4, 0.5]) ts2 = ElectricalSeries('test_ts2', [0, 1, 2, 3, 4, 5], electrodes=elec_region, timestamps=[0.0, 0.1, 0.2, 0.3, 0.4, 0.5]) self.nwbfile.add_acquisition(ts1) self.nwbfile.add_acquisition(ts2) self.nwbfile.add_trial(start_time=50.0, stop_time=70.0) self.nwbfile.add_invalid_times_column('comments', 'description of reason for omitting time') self.nwbfile.create_processing_module('test_mod', 'test_description') self.nwbfile.create_time_intervals('custom_interval', 'a custom time interval') self.nwbfile.intervals['custom_interval'].add_interval(start_time=10., stop_time=20.) newfile = self.nwbfile.copy() # test dictionaries self.assertIs(self.nwbfile.devices['a'], newfile.devices['a']) self.assertIs(self.nwbfile.acquisition['test_ts1'], newfile.acquisition['test_ts1']) self.assertIs(self.nwbfile.acquisition['test_ts2'], newfile.acquisition['test_ts2']) self.assertIs(self.nwbfile.processing['test_mod'], newfile.processing['test_mod']) # test dynamic tables self.assertIsNot(self.nwbfile.electrodes, newfile.electrodes) self.assertIs(self.nwbfile.electrodes['x'], newfile.electrodes['x']) self.assertIsNot(self.nwbfile.units, newfile.units) self.assertIs(self.nwbfile.units['spike_times'], newfile.units['spike_times']) self.assertIsNot(self.nwbfile.trials, newfile.trials) self.assertIsNot(self.nwbfile.trials.parent, newfile.trials.parent) self.assertIs(self.nwbfile.trials.id, newfile.trials.id) self.assertIs(self.nwbfile.trials['start_time'], newfile.trials['start_time']) self.assertIs(self.nwbfile.trials['stop_time'], newfile.trials['stop_time']) self.assertIsNot(self.nwbfile.invalid_times, newfile.invalid_times) self.assertTupleEqual(self.nwbfile.invalid_times.colnames, newfile.invalid_times.colnames) self.assertIsNot(self.nwbfile.intervals['custom_interval'], newfile.intervals['custom_interval']) self.assertTupleEqual(self.nwbfile.intervals['custom_interval'].colnames, newfile.intervals['custom_interval'].colnames) self.assertIs(self.nwbfile.intervals['custom_interval']['start_time'], newfile.intervals['custom_interval']['start_time']) self.assertIs(self.nwbfile.intervals['custom_interval']['stop_time'], newfile.intervals['custom_interval']['stop_time']) def test_multi_experimenters(self): self.nwbfile = NWBFile('a test session description for a test NWBFile', 'FILE123', self.start, experimenter=('experimenter1', 'experimenter2')) self.assertTupleEqual(self.nwbfile.experimenter, ('experimenter1', 'experimenter2')) def test_multi_publications(self): self.nwbfile = NWBFile('a test session description for a test NWBFile', 'FILE123', self.start, related_publications=('pub1', 'pub2')) self.assertTupleEqual(self.nwbfile.related_publications, ('pub1', 'pub2')) class SubjectTest(TestCase): def setUp(self): self.subject = Subject(age='12 mo', description='An unfortunate rat', genotype='WT', sex='M', species='Rattus norvegicus', subject_id='RAT123', weight='2 lbs', date_of_birth=datetime(2017, 5, 1, 12, tzinfo=tzlocal())) self.start = datetime(2017, 5, 1, 12, tzinfo=tzlocal()) self.path = 'nwbfile_test.h5' self.nwbfile = NWBFile('a test session description for a test NWBFile', 'FILE123', self.start, experimenter='A test experimenter', lab='a test lab', institution='a test institution', experiment_description='a test experiment description', session_id='test1', subject=self.subject) def test_constructor(self): self.assertEqual(self.subject.age, '12 mo') self.assertEqual(self.subject.description, 'An unfortunate rat') self.assertEqual(self.subject.genotype, 'WT') self.assertEqual(self.subject.sex, 'M') self.assertEqual(self.subject.species, 'Rattus norvegicus') self.assertEqual(self.subject.subject_id, 'RAT123') self.assertEqual(self.subject.weight, '2 lbs') def test_nwbfile_constructor(self): self.assertIs(self.nwbfile.subject, self.subject) class TestCacheSpec(TestCase): def setUp(self): self.path = 'unittest_cached_spec.nwb' def tearDown(self): if os.path.exists(self.path): os.remove(self.path) def test_simple(self): nwbfile = NWBFile(' ', ' ', datetime.now(tzlocal()), file_create_date=datetime.now(tzlocal()), institution='University of California, San Francisco', lab='Chang Lab') with NWBHDF5IO(self.path, 'w') as io: io.write(nwbfile) with self.assertWarnsRegex(UserWarning, r"ignoring namespace '\S+' because it already exists"): with NWBHDF5IO(self.path, 'r', load_namespaces=True) as reader: nwbfile = reader.read() class TestNoCacheSpec(TestCase): def setUp(self): self.path = 'unittest_cached_spec.nwb' def tearDown(self): if os.path.exists(self.path): os.remove(self.path) def test_simple(self): nwbfile = NWBFile(' ', ' ', datetime.now(tzlocal()), file_create_date=datetime.now(tzlocal()), institution='University of California, San Francisco', lab='Chang Lab') with NWBHDF5IO(self.path, 'w') as io: io.write(nwbfile, cache_spec=False) with self.assertWarnsWith(UserWarning, "No cached namespaces found in %s" % self.path): with NWBHDF5IO(self.path, 'r', load_namespaces=True) as reader: nwbfile = reader.read() class TestTimestampsRefDefault(TestCase): def setUp(self): self.start_time = datetime(2017, 5, 1, 12, 0, 0, tzinfo=tzlocal()) self.nwbfile = NWBFile('test session description', 'TEST123', self.start_time) def test_reftime_default(self): # 'timestamps_reference_time' should default to 'session_start_time' self.assertEqual(self.nwbfile.timestamps_reference_time, self.start_time) class TestTimestampsRefAware(TestCase): def setUp(self): self.start_time = datetime(2017, 5, 1, 12, 0, 0, tzinfo=tzlocal()) self.ref_time_notz = datetime(1979, 1, 1, 0, 0, 0) def test_reftime_tzaware(self): with self.assertRaises(ValueError): # 'timestamps_reference_time' must be a timezone-aware datetime NWBFile('test session description', 'TEST124', self.start_time, timestamps_reference_time=self.ref_time_notz) pynwb-1.2.1/tests/unit/test_extension.py0000644000655200065520000002206613612200244022006 0ustar circlecicircleci00000000000000import os import random import string from datetime import datetime from dateutil.tz import tzlocal from tempfile import gettempdir from hdmf.spec import RefSpec from hdmf.utils import get_docval, docval, popargs from pynwb import get_type_map, TimeSeries, NWBFile, register_class, load_namespaces, get_class from pynwb.spec import NWBNamespaceBuilder, NWBGroupSpec, NWBAttributeSpec, NWBDatasetSpec from pynwb.file import LabMetaData from pynwb.testing import TestCase def id_generator(N=10): """ Generator a random string of characters. """ return ''.join(random.choice(string.ascii_uppercase + string.digits) for _ in range(N)) class TestExtension(TestCase): def setUp(self): self.tempdir = gettempdir() self.prefix = id_generator() self.ext_source = '%s_extension.yaml' % self.prefix self.ns_path = '%s_namespace.yaml' % self.prefix def tearDown(self): for f in (self.ext_source, self.ns_path): path = os.path.join(self.tempdir, f) os.remove(path) def test_export(self): ns_builder = NWBNamespaceBuilder('Extension for use in my Lab', self.prefix, version='0.1.0') ext1 = NWBGroupSpec('A custom ElectricalSeries for my lab', attributes=[NWBAttributeSpec(name='trode_id', doc='the tetrode id', dtype='int')], neurodata_type_inc='ElectricalSeries', neurodata_type_def='TetrodeSeries') ns_builder.add_spec(self.ext_source, ext1) ns_builder.export(self.ns_path, outdir=self.tempdir) def test_load_namespace(self): self.test_export() get_type_map(extensions=os.path.join(self.tempdir, self.ns_path)) def test_get_class(self): self.test_export() type_map = get_type_map(extensions=os.path.join(self.tempdir, self.ns_path)) type_map.get_container_cls(self.prefix, 'TetrodeSeries') def test_load_namespace_with_reftype_attribute(self): ns_builder = NWBNamespaceBuilder('Extension for use in my Lab', self.prefix, version='0.1.0') test_ds_ext = NWBDatasetSpec(doc='test dataset to add an attr', name='test_data', shape=(None,), attributes=[NWBAttributeSpec(name='target_ds', doc='the target the dataset applies to', dtype=RefSpec('TimeSeries', 'object'))], neurodata_type_def='my_new_type') ns_builder.add_spec(self.ext_source, test_ds_ext) ns_builder.export(self.ns_path, outdir=self.tempdir) get_type_map(extensions=os.path.join(self.tempdir, self.ns_path)) def test_load_namespace_with_reftype_attribute_check_autoclass_const(self): ns_builder = NWBNamespaceBuilder('Extension for use in my Lab', self.prefix, version='0.1.0') test_ds_ext = NWBDatasetSpec(doc='test dataset to add an attr', name='test_data', shape=(None,), attributes=[NWBAttributeSpec(name='target_ds', doc='the target the dataset applies to', dtype=RefSpec('TimeSeries', 'object'))], neurodata_type_def='my_new_type') ns_builder.add_spec(self.ext_source, test_ds_ext) ns_builder.export(self.ns_path, outdir=self.tempdir) type_map = get_type_map(extensions=os.path.join(self.tempdir, self.ns_path)) my_new_type = type_map.get_container_cls(self.prefix, 'my_new_type') docval = None for tmp in get_docval(my_new_type.__init__): if tmp['name'] == 'target_ds': docval = tmp break self.assertIsNotNone(docval) self.assertEqual(docval['type'], TimeSeries) def test_lab_meta(self): ns_builder = NWBNamespaceBuilder('Extension for use in my Lab', self.prefix, version='0.1.0') test_meta_ext = NWBGroupSpec( neurodata_type_def='MyTestMetaData', neurodata_type_inc='LabMetaData', doc='my test meta data', attributes=[ NWBAttributeSpec(name='test_attr', dtype='float', doc='test_dtype')]) ns_builder.add_spec(self.ext_source, test_meta_ext) ns_builder.export(self.ns_path, outdir=self.tempdir) ns_abs_path = os.path.join(self.tempdir, self.ns_path) load_namespaces(ns_abs_path) @register_class('MyTestMetaData', self.prefix) class MyTestMetaData(LabMetaData): __nwbfields__ = ('test_attr',) @docval({'name': 'name', 'type': str, 'doc': 'name'}, {'name': 'test_attr', 'type': float, 'doc': 'test attribute'}) def __init__(self, **kwargs): test_attr = popargs('test_attr', kwargs) super(MyTestMetaData, self).__init__(**kwargs) self.test_attr = test_attr nwbfile = NWBFile("a file with header data", "NB123A", datetime(2017, 5, 1, 12, 0, 0, tzinfo=tzlocal())) nwbfile.add_lab_meta_data(MyTestMetaData(name='test_name', test_attr=5.)) def test_lab_meta_auto(self): ns_builder = NWBNamespaceBuilder('Extension for use in my Lab', self.prefix, version='0.1.0') test_meta_ext = NWBGroupSpec( neurodata_type_def='MyTestMetaData', neurodata_type_inc='LabMetaData', doc='my test meta data', attributes=[ NWBAttributeSpec(name='test_attr', dtype='float', doc='test_dtype')]) ns_builder.add_spec(self.ext_source, test_meta_ext) ns_builder.export(self.ns_path, outdir=self.tempdir) ns_abs_path = os.path.join(self.tempdir, self.ns_path) load_namespaces(ns_abs_path) MyTestMetaData = get_class('MyTestMetaData', self.prefix) nwbfile = NWBFile("a file with header data", "NB123A", datetime(2017, 5, 1, 12, 0, 0, tzinfo=tzlocal())) nwbfile.add_lab_meta_data(MyTestMetaData(name='test_name', test_attr=5.)) class TestCatchDupNS(TestCase): def setUp(self): self.tempdir = gettempdir() self.prefix = id_generator() self.ext_source1 = '%s_extension1.yaml' % self.prefix self.ns_path1 = '%s_namespace1.yaml' % self.prefix self.ext_source2 = '%s_extension2.yaml' % self.prefix self.ns_path2 = '%s_namespace2.yaml' % self.prefix def tearDown(self): files = (self.ext_source1, self.ns_path1, self.ext_source2, self.ns_path2) for f in files: path = os.path.join(self.tempdir, f) os.remove(path) def test_catch_dup_name(self): ns_builder1 = NWBNamespaceBuilder('Extension for us in my Lab', "pynwb_test_extension1", version='0.1.0') ext1 = NWBGroupSpec('A custom ElectricalSeries for my lab', attributes=[NWBAttributeSpec(name='trode_id', doc='the tetrode id', dtype='int')], neurodata_type_inc='ElectricalSeries', neurodata_type_def='TetrodeSeries') ns_builder1.add_spec(self.ext_source1, ext1) ns_builder1.export(self.ns_path1, outdir=self.tempdir) ns_builder2 = NWBNamespaceBuilder('Extension for us in my Lab', "pynwb_test_extension1", version='0.1.0') ext2 = NWBGroupSpec('A custom ElectricalSeries for my lab', attributes=[NWBAttributeSpec(name='trode_id', doc='the tetrode id', dtype='int')], neurodata_type_inc='ElectricalSeries', neurodata_type_def='TetrodeSeries') ns_builder2.add_spec(self.ext_source2, ext2) ns_builder2.export(self.ns_path2, outdir=self.tempdir) type_map = get_type_map(extensions=os.path.join(self.tempdir, self.ns_path1)) with self.assertWarnsRegex(UserWarning, r"ignoring namespace '\S+' because it already exists"): type_map.load_namespaces(os.path.join(self.tempdir, self.ns_path2)) class TestCatchDuplicateSpec(TestCase): def setUp(self): self.prefix = id_generator() self.ext_source = '%s_extension3.yaml' % self.prefix def tearDown(self): pass def test_catch_duplicate_spec(self): spec1 = NWBGroupSpec("This is my new group 1", "Group1", neurodata_type_inc="NWBDataInterface", neurodata_type_def="Group1") spec2 = NWBGroupSpec("This is my new group 2", "Group2", groups=[spec1], neurodata_type_inc="NWBDataInterface", neurodata_type_def="Group2") ns_builder = NWBNamespaceBuilder("Example namespace", "pynwb_test_ext", version='0.1.0') ns_builder.add_spec(self.ext_source, spec1) with self.assertRaises(ValueError): ns_builder.add_spec(self.ext_source, spec2) pynwb-1.2.1/tests/unit/test_ogen.py0000644000655200065520000000140513612200244020714 0ustar circlecicircleci00000000000000from pynwb.ogen import OptogeneticSeries, OptogeneticStimulusSite from pynwb.ecephys import Device from pynwb.testing import TestCase class OptogeneticSeriesConstructor(TestCase): def test_init(self): device = Device('name') oS = OptogeneticStimulusSite('site1', device, 'description', 300., 'location') self.assertEqual(oS.name, 'site1') self.assertEqual(oS.device, device) self.assertEqual(oS.description, 'description') self.assertEqual(oS.excitation_lambda, 300.) self.assertEqual(oS.location, 'location') iS = OptogeneticSeries('test_iS', list(), oS, timestamps=list()) self.assertEqual(iS.name, 'test_iS') self.assertEqual(iS.unit, 'watts') self.assertEqual(iS.site, oS) pynwb-1.2.1/tests/unit/test_core_NWBContainer.py0000644000655200065520000000162313612200244023267 0ustar circlecicircleci00000000000000import unittest from pynwb.core import NWBContainer from hdmf.utils import docval, call_docval_func class MyTestClass(NWBContainer): __nwbfields__ = ('prop1', 'prop2') @docval({'name': 'name', 'type': str, 'doc': 'The name of this container'}) def __init__(self, **kwargs): call_docval_func(super(MyTestClass, self).__init__, kwargs) self.prop1 = 'test1' class TestNWBContainer(unittest.TestCase): def test_constructor(self): """Test constructor """ obj = MyTestClass('obj1') self.assertEqual(obj.name, 'obj1') obj.prop2 = 'test2' def test_nwbfields(self): """Test that getters and setters work for nwbfields """ obj = MyTestClass('obj1') obj.prop2 = 'test2' self.assertEqual(obj.prop1, 'test1') self.assertEqual(obj.prop2, 'test2') if __name__ == '__main__': unittest.main() pynwb-1.2.1/tests/unit/test_base.py0000644000655200065520000002101513612200244020675 0ustar circlecicircleci00000000000000import numpy as np from pynwb.base import ProcessingModule, TimeSeries, Images, Image from pynwb.testing import TestCase from hdmf.data_utils import DataChunkIterator from hdmf.backends.hdf5 import H5DataIO class TestProcessingModule(TestCase): def setUp(self): self.pm = ProcessingModule('test_procmod', 'a fake processing module') def test_init(self): self.assertEqual(self.pm.name, 'test_procmod') self.assertEqual(self.pm.description, 'a fake processing module') def test_add_data_interface(self): ts = TimeSeries('test_ts', [0, 1, 2, 3, 4, 5], 'grams', timestamps=[0.0, 0.1, 0.2, 0.3, 0.4, 0.5]) self.pm.add(ts) self.assertIn(ts.name, self.pm.containers) self.assertIs(ts, self.pm.containers[ts.name]) def test_deprecated_add_data_interface(self): ts = TimeSeries('test_ts', [0, 1, 2, 3, 4, 5], 'grams', timestamps=[0.0, 0.1, 0.2, 0.3, 0.4, 0.5]) with self.assertWarnsWith(PendingDeprecationWarning, 'add_data_interface will be replaced by add'): self.pm.add_data_interface(ts) self.assertIn(ts.name, self.pm.containers) self.assertIs(ts, self.pm.containers[ts.name]) def test_deprecated_add_container(self): ts = TimeSeries('test_ts', [0, 1, 2, 3, 4, 5], 'grams', timestamps=[0.0, 0.1, 0.2, 0.3, 0.4, 0.5]) with self.assertWarnsWith(PendingDeprecationWarning, 'add_container will be replaced by add'): self.pm.add_container(ts) self.assertIn(ts.name, self.pm.containers) self.assertIs(ts, self.pm.containers[ts.name]) def test_get_data_interface(self): ts = TimeSeries('test_ts', [0, 1, 2, 3, 4, 5], 'grams', timestamps=[0.0, 0.1, 0.2, 0.3, 0.4, 0.5]) self.pm.add(ts) tmp = self.pm.get('test_ts') self.assertIs(tmp, ts) self.assertIs(self.pm['test_ts'], self.pm.get('test_ts')) def test_deprecated_get_data_interface(self): ts = TimeSeries('test_ts', [0, 1, 2, 3, 4, 5], 'grams', timestamps=[0.0, 0.1, 0.2, 0.3, 0.4, 0.5]) self.pm.add(ts) with self.assertWarnsWith(PendingDeprecationWarning, 'get_data_interface will be replaced by get'): tmp = self.pm.get_data_interface('test_ts') self.assertIs(tmp, ts) def test_deprecated_get_container(self): ts = TimeSeries('test_ts', [0, 1, 2, 3, 4, 5], 'grams', timestamps=[0.0, 0.1, 0.2, 0.3, 0.4, 0.5]) self.pm.add(ts) with self.assertWarnsWith(PendingDeprecationWarning, 'get_container will be replaced by get'): tmp = self.pm.get_container('test_ts') self.assertIs(tmp, ts) def test_getitem(self): ts = TimeSeries('test_ts', [0, 1, 2, 3, 4, 5], 'grams', timestamps=[0.0, 0.1, 0.2, 0.3, 0.4, 0.5]) self.pm.add(ts) tmp = self.pm['test_ts'] self.assertIs(tmp, ts) class TestTimeSeries(TestCase): def test_init_no_parent(self): ts = TimeSeries('test_ts', list(), 'unit', timestamps=list()) self.assertEqual(ts.name, 'test_ts') self.assertIsNone(ts.parent) def test_init_datalink_set(self): ts = TimeSeries('test_ts', list(), 'unit', timestamps=list()) self.assertIsInstance(ts.data_link, set) self.assertEqual(len(ts.data_link), 0) def test_init_timestampslink_set(self): ts = TimeSeries('test_ts', list(), 'unit', timestamps=list()) self.assertIsInstance(ts.timestamp_link, set) self.assertEqual(len(ts.timestamp_link), 0) def test_init_data(self): dat = [0, 1, 2, 3, 4] ts = TimeSeries('test_ts', dat, 'volts', timestamps=[0.1, 0.2, 0.3, 0.4]) self.assertIs(ts.data, dat) self.assertEqual(ts.conversion, 1.0) self.assertEqual(ts.resolution, -1.0) self.assertEqual(ts.unit, 'volts') def test_init_timestamps(self): dat = [0, 1, 2, 3, 4] tstamps = [0.1, 0.2, 0.3, 0.4] ts = TimeSeries('test_ts', dat, 'unit', timestamps=tstamps) self.assertIs(ts.timestamps, tstamps) self.assertEqual(ts.interval, 1) self.assertEqual(ts.time_unit, "seconds") def test_init_rate(self): ts = TimeSeries('test_ts', list(), 'unit', starting_time=0.0, rate=1.0) self.assertEqual(ts.starting_time, 0.0) self.assertEqual(ts.rate, 1.0) self.assertEqual(ts.time_unit, "seconds") def test_data_timeseries(self): ts1 = TimeSeries('test_ts1', [0, 1, 2, 3, 4, 5], 'grams', timestamps=[0.0, 0.1, 0.2, 0.3, 0.4, 0.5]) ts2 = TimeSeries('test_ts2', ts1, 'grams', timestamps=[1.0, 1.1, 1.2, 1.3, 1.4, 1.5]) self.assertEqual(ts2.data, [0, 1, 2, 3, 4, 5]) self.assertEqual(ts1.num_samples, ts2.num_samples) def test_timestamps_timeseries(self): ts1 = TimeSeries('test_ts1', [0, 1, 2, 3, 4, 5], 'grams', timestamps=[0.0, 0.1, 0.2, 0.3, 0.4, 0.5]) ts2 = TimeSeries('test_ts2', [10, 11, 12, 13, 14, 15], 'grams', timestamps=ts1) self.assertEqual(ts2.timestamps, [0.0, 0.1, 0.2, 0.3, 0.4, 0.5]) def test_nodata(self): ts1 = TimeSeries('test_ts1', starting_time=0.0, rate=0.1) with self.assertWarns(UserWarning): self.assertIs(ts1.num_samples, None) def test_dataio_list_data(self): length = 100 data = list(range(length)) ts1 = TimeSeries('test_ts1', H5DataIO(data), 'grams', starting_time=0.0, rate=0.1) self.assertEqual(ts1.num_samples, length) assert data == list(ts1.data) def test_dataio_dci_data(self): def generator_factory(): return (i for i in range(100)) data = H5DataIO(DataChunkIterator(data=generator_factory())) ts1 = TimeSeries('test_ts1', data, 'grams', starting_time=0.0, rate=0.1) with self.assertWarnsWith(UserWarning, 'The data attribute on this TimeSeries (named: test_ts1) has a ' '__len__, but it cannot be read'): self.assertIs(ts1.num_samples, None) for xi, yi in zip(data, generator_factory()): assert np.allclose(xi, yi) def test_dci_data(self): def generator_factory(): return (i for i in range(100)) data = DataChunkIterator(data=generator_factory()) ts1 = TimeSeries('test_ts1', data, 'grams', starting_time=0.0, rate=0.1) with self.assertWarnsWith(UserWarning, 'The data attribute on this TimeSeries (named: test_ts1) has no ' '__len__'): self.assertIs(ts1.num_samples, None) for xi, yi in zip(data, generator_factory()): assert np.allclose(xi, yi) def test_dci_data_arr(self): def generator_factory(): return (np.array([i, i+1]) for i in range(100)) data = DataChunkIterator(data=generator_factory()) ts1 = TimeSeries('test_ts1', data, 'grams', starting_time=0.0, rate=0.1) # with self.assertWarnsRegex(UserWarning, r'.*name: \'test_ts1\'.*'): with self.assertWarns(UserWarning): self.assertIs(ts1.num_samples, None) for xi, yi in zip(data, generator_factory()): assert np.allclose(xi, yi) def test_no_time(self): with self.assertRaisesWith(TypeError, "either 'timestamps' or 'rate' must be specified"): TimeSeries('test_ts2', [10, 11, 12, 13, 14, 15], 'grams') def test_no_starting_time(self): # if no starting_time is given, 0.0 is assumed ts1 = TimeSeries('test_ts1', rate=0.1) self.assertEqual(ts1.starting_time, 0.0) def test_conflicting_time_args(self): with self.assertRaises(ValueError): TimeSeries('test_ts2', [10, 11, 12, 13, 14, 15], 'grams', rate=30., timestamps=[.3, .4, .5, .6, .7, .8]) with self.assertRaises(ValueError): TimeSeries('test_ts2', [10, 11, 12, 13, 14, 15], 'grams', starting_time=30., timestamps=[.3, .4, .5, .6, .7, .8]) class TestImage(TestCase): def test_image(self): Image(name='test_image', data=np.ones((10, 10))) class TestImages(TestCase): def test_images(self): image = Image(name='test_image', data=np.ones((10, 10))) image2 = Image(name='test_image2', data=np.ones((10, 10))) Images(name='images_name', images=[image, image2]) pynwb-1.2.1/tests/unit/test_core.py0000644000655200065520000000602713612200244020721 0ustar circlecicircleci00000000000000from datetime import datetime from dateutil.tz import tzlocal from hdmf.utils import docval, call_docval_func from pynwb import NWBFile, TimeSeries, available_namespaces from pynwb.core import NWBContainer, LabelledDict from pynwb.testing import TestCase class MyTestClass(NWBContainer): __nwbfields__ = ('prop1', 'prop2') @docval({'name': 'name', 'type': str, 'doc': 'The name of this container'}) def __init__(self, **kwargs): call_docval_func(super(MyTestClass, self).__init__, kwargs) self.prop1 = 'test1' class TestNWBContainer(TestCase): def test_constructor(self): """Test constructor """ obj = MyTestClass('obj1') self.assertEqual(obj.name, 'obj1') obj.prop2 = 'test2' def test_nwbfields(self): """Test that getters and setters work for nwbfields """ obj = MyTestClass('obj1') obj.prop2 = 'test2' self.assertEqual(obj.prop1, 'test1') self.assertEqual(obj.prop2, 'test2') class TestPrint(TestCase): def test_print_file(self): nwbfile = NWBFile(session_description='session_description', identifier='identifier', session_start_time=datetime.now(tzlocal())) ts = TimeSeries('name', [1., 2., 3.] * 1000, timestamps=[1, 2, 3]) ts2 = TimeSeries('name2', [1, 2, 3] * 1000, timestamps=[1, 2, 3]) expected = """name pynwb.base.TimeSeries at 0x%d Fields: comments: no comments conversion: 1.0 data: [1. 2. 3. ... 1. 2. 3.] description: no description interval: 1 resolution: -1.0 timestamps: [1 2 3] timestamps_unit: seconds """ expected %= id(ts) self.assertEqual(str(ts), expected) nwbfile.add_acquisition(ts) nwbfile.add_acquisition(ts2) nwbfile.add_epoch(start_time=1.0, stop_time=10.0, tags=['tag1', 'tag2']) expected_re = r"""root pynwb\.file\.NWBFile at 0x\d+ Fields: acquisition: { name , name2 } epoch_tags: { tag1, tag2 } epochs: epochs file_create_date: \[datetime.datetime\(.*\)\] identifier: identifier session_description: session_description session_start_time: .* timestamps_reference_time: .* """ self.assertRegex(str(nwbfile), expected_re) class TestAvailableNamespaces(TestCase): def test_available_namespaces(self): self.assertEqual(available_namespaces(), ('hdmf-common', 'core')) class TestLabelledDict(TestCase): def setUp(self): self.name = 'name' self.container = TimeSeries(self.name, [1., 2., 3.] * 1000, timestamps=[1, 2, 3]) self.object_id = self.container.object_id def test_add_default(self): ld = LabelledDict('test_dict') ld.add(self.container) self.assertIs(ld[self.name], self.container) def test_add_nondefault(self): ld = LabelledDict('test_dict', def_key_name='object_id') ld.add(self.container) self.assertIs(ld[self.object_id], self.container) pynwb-1.2.1/tests/unit/test_misc.py0000644000655200065520000001776213612200244020734 0ustar circlecicircleci00000000000000import numpy as np from hdmf.common import DynamicTable, VectorData from pynwb.misc import AnnotationSeries, AbstractFeatureSeries, IntervalSeries, Units, DecompositionSeries from pynwb.file import TimeSeries from pynwb.device import Device from pynwb.ecephys import ElectrodeGroup from pynwb.testing import TestCase class AnnotationSeriesConstructor(TestCase): def test_init(self): aS = AnnotationSeries('test_aS', timestamps=list()) self.assertEqual(aS.name, 'test_aS') aS.add_annotation(2.0, 'comment') class AbstractFeatureSeriesConstructor(TestCase): def test_init(self): aFS = AbstractFeatureSeries('test_aFS', ['feature units'], ['features'], timestamps=list()) self.assertEqual(aFS.name, 'test_aFS') self.assertEqual(aFS.feature_units, ['feature units']) self.assertEqual(aFS.features, ['features']) aFS.add_features(2.0, [1.]) class DecompositionSeriesConstructor(TestCase): def test_init(self): timeseries = TimeSeries(name='dummy timeseries', description='desc', data=np.ones((3, 3)), unit='Volts', timestamps=np.ones((3,))) bands = DynamicTable(name='bands', description='band info for LFPSpectralAnalysis', columns=[ VectorData(name='band_name', description='name of bands', data=['alpha', 'beta', 'gamma']), VectorData(name='band_limits', description='low and high cutoffs in Hz', data=np.ones((3, 2))) ]) spec_anal = DecompositionSeries(name='LFPSpectralAnalysis', description='my description', data=np.ones((3, 3, 3)), timestamps=np.ones((3,)), source_timeseries=timeseries, metric='amplitude', bands=bands) self.assertEqual(spec_anal.name, 'LFPSpectralAnalysis') self.assertEqual(spec_anal.description, 'my description') np.testing.assert_equal(spec_anal.data, np.ones((3, 3, 3))) np.testing.assert_equal(spec_anal.timestamps, np.ones((3,))) self.assertEqual(spec_anal.bands['band_name'].data, ['alpha', 'beta', 'gamma']) np.testing.assert_equal(spec_anal.bands['band_limits'].data, np.ones((3, 2))) self.assertEqual(spec_anal.source_timeseries, timeseries) self.assertEqual(spec_anal.metric, 'amplitude') def test_init_delayed_bands(self): timeseries = TimeSeries(name='dummy timeseries', description='desc', data=np.ones((3, 3)), unit='Volts', timestamps=np.ones((3,))) spec_anal = DecompositionSeries(name='LFPSpectralAnalysis', description='my description', data=np.ones((3, 3, 3)), timestamps=np.ones((3,)), source_timeseries=timeseries, metric='amplitude') for band_name in ['alpha', 'beta', 'gamma']: spec_anal.add_band(band_name=band_name, band_limits=(1., 1.), band_mean=1., band_stdev=1.) self.assertEqual(spec_anal.name, 'LFPSpectralAnalysis') self.assertEqual(spec_anal.description, 'my description') np.testing.assert_equal(spec_anal.data, np.ones((3, 3, 3))) np.testing.assert_equal(spec_anal.timestamps, np.ones((3,))) self.assertEqual(spec_anal.bands['band_name'].data, ['alpha', 'beta', 'gamma']) np.testing.assert_equal(spec_anal.bands['band_limits'].data, np.ones((3, 2))) self.assertEqual(spec_anal.source_timeseries, timeseries) self.assertEqual(spec_anal.metric, 'amplitude') class IntervalSeriesConstructor(TestCase): def test_init(self): data = [1.0, -1.0, 1.0, -1.0] timestamps = [0.0, 1.0, 2.0, 3.0] iS = IntervalSeries('test_iS', data=data, timestamps=timestamps) self.assertEqual(iS.name, 'test_iS') self.assertEqual(iS.data, data) self.assertEqual(iS.timestamps, timestamps) def test_add_interval(self): data = [1.0, -1.0, 1.0, -1.0] timestamps = [0.0, 1.0, 2.0, 3.0] iS = IntervalSeries('test_iS', data=data, timestamps=timestamps) iS.add_interval(4.0, 5.0) data.append(1.0) data.append(-1.0) timestamps.append(4.0) timestamps.append(5.0) self.assertEqual(iS.data, data) self.assertEqual(iS.timestamps, timestamps) class UnitsTests(TestCase): def test_init(self): ut = Units() self.assertEqual(ut.name, 'Units') self.assertFalse(ut.columns) def test_add_spike_times(self): ut = Units() ut.add_unit(spike_times=[0, 1, 2]) ut.add_unit(spike_times=[3, 4, 5]) self.assertEqual(ut.id.data, [0, 1]) self.assertEqual(ut['spike_times'].target.data, [0, 1, 2, 3, 4, 5]) self.assertEqual(ut['spike_times'].data, [3, 6]) self.assertEqual(ut['spike_times'][0], [0, 1, 2]) self.assertEqual(ut['spike_times'][1], [3, 4, 5]) def test_get_spike_times(self): ut = Units() ut.add_unit(spike_times=[0, 1, 2]) ut.add_unit(spike_times=[3, 4, 5]) self.assertTrue(all(ut.get_unit_spike_times(0) == np.array([0, 1, 2]))) self.assertTrue(all(ut.get_unit_spike_times(1) == np.array([3, 4, 5]))) @staticmethod def test_get_spike_times_interval(): ut = Units() ut.add_unit(spike_times=[0, 1, 2]) ut.add_unit(spike_times=[3, 4, 5]) np.testing.assert_array_equal(ut.get_unit_spike_times(0, (.5, 3)), [1, 2]) np.testing.assert_array_equal(ut.get_unit_spike_times(0, (-.5, 1.1)), [0, 1]) def test_get_spike_times_multi(self): ut = Units() ut.add_unit(spike_times=[0, 1, 2]) ut.add_unit(spike_times=[3, 4, 5]) np.testing.assert_array_equal(ut.get_unit_spike_times((0, 1)), [[0, 1, 2], [3, 4, 5]]) def test_get_spike_times_multi_interval(self): ut = Units() ut.add_unit(spike_times=[0, 1, 2]) ut.add_unit(spike_times=[3, 4, 5]) np.testing.assert_array_equal(ut.get_unit_spike_times((0, 1), (1.5, 3.5)), [[2], [3]]) def test_times(self): ut = Units() ut.add_unit(spike_times=[0, 1, 2]) ut.add_unit(spike_times=[3, 4, 5]) self.assertTrue(all(ut['spike_times'][0] == np.array([0, 1, 2]))) self.assertTrue(all(ut['spike_times'][1] == np.array([3, 4, 5]))) def test_get_obs_intervals(self): ut = Units() ut.add_unit(obs_intervals=[[0, 1]]) ut.add_unit(obs_intervals=[[2, 3], [4, 5]]) self.assertTrue(np.all(ut.get_unit_obs_intervals(0) == np.array([[0, 1]]))) self.assertTrue(np.all(ut.get_unit_obs_intervals(1) == np.array([[2, 3], [4, 5]]))) def test_obs_intervals(self): ut = Units() ut.add_unit(obs_intervals=[[0, 1]]) ut.add_unit(obs_intervals=[[2, 3], [4, 5]]) self.assertTrue(np.all(ut['obs_intervals'][0] == np.array([[0, 1]]))) self.assertTrue(np.all(ut['obs_intervals'][1] == np.array([[2, 3], [4, 5]]))) def test_times_and_intervals(self): ut = Units() ut.add_unit(spike_times=[0, 1, 2], obs_intervals=[[0, 2]]) ut.add_unit(spike_times=[3, 4, 5], obs_intervals=[[2, 3], [4, 5]]) self.assertTrue(all(ut['spike_times'][0] == np.array([0, 1, 2]))) self.assertTrue(all(ut['spike_times'][1] == np.array([3, 4, 5]))) self.assertTrue(np.all(ut['obs_intervals'][0] == np.array([[0, 2]]))) self.assertTrue(np.all(ut['obs_intervals'][1] == np.array([[2, 3], [4, 5]]))) def test_electrode_group(self): ut = Units() device = Device('test_device') electrode_group = ElectrodeGroup('test_electrode_group', 'description', 'location', device) ut.add_unit(electrode_group=electrode_group) self.assertEqual(ut['electrode_group'][0], electrode_group) pynwb-1.2.1/tests/unit/test_image.py0000644000655200065520000000602513612200244021051 0ustar circlecicircleci00000000000000import numpy as np from pynwb import TimeSeries from pynwb.image import ImageSeries, IndexSeries, ImageMaskSeries, OpticalSeries, \ GrayscaleImage, RGBImage, RGBAImage from pynwb.testing import TestCase class ImageSeriesConstructor(TestCase): def test_init(self): iS = ImageSeries(name='test_iS', data=np.ones((3, 3, 3)), unit='unit', external_file=['external_file'], starting_frame=[1, 2, 3], format='tiff', timestamps=list()) self.assertEqual(iS.name, 'test_iS') self.assertEqual(iS.unit, 'unit') self.assertEqual(iS.external_file, ['external_file']) self.assertEqual(iS.starting_frame, [1, 2, 3]) self.assertEqual(iS.format, 'tiff') # self.assertEqual(iS.bits_per_pixel, np.nan) class IndexSeriesConstructor(TestCase): def test_init(self): ts = TimeSeries('test_ts', list(), 'unit', timestamps=list()) iS = IndexSeries('test_iS', list(), ts, unit='unit', timestamps=list()) self.assertEqual(iS.name, 'test_iS') self.assertEqual(iS.unit, 'unit') self.assertEqual(iS.indexed_timeseries, ts) class ImageMaskSeriesConstructor(TestCase): def test_init(self): iS = ImageSeries(name='test_iS', data=np.ones((2, 2, 2)), unit='unit', external_file=['external_file'], starting_frame=[1, 2, 3], format='tiff', timestamps=[1., .2]) ims = ImageMaskSeries(name='test_ims', data=np.ones((2, 2, 2)), unit='unit', masked_imageseries=iS, external_file=['external_file'], starting_frame=[1, 2, 3], format='tiff', timestamps=[1., 2.]) self.assertEqual(ims.name, 'test_ims') self.assertEqual(ims.unit, 'unit') self.assertEqual(ims.masked_imageseries, iS) self.assertEqual(ims.external_file, ['external_file']) self.assertEqual(ims.starting_frame, [1, 2, 3]) self.assertEqual(ims.format, 'tiff') class OpticalSeriesConstructor(TestCase): def test_init(self): ts = OpticalSeries(name='test_ts', data=np.ones((2, 2, 2)), unit='unit', distance=1.0, field_of_view=[4, 5], orientation='orientation', external_file=['external_file'], starting_frame=[1, 2, 3], format='tiff', timestamps=[1., 2.]) self.assertEqual(ts.name, 'test_ts') self.assertEqual(ts.unit, 'unit') self.assertEqual(ts.distance, 1.0) self.assertEqual(ts.field_of_view, [4, 5]) self.assertEqual(ts.orientation, 'orientation') self.assertEqual(ts.external_file, ['external_file']) self.assertEqual(ts.starting_frame, [1, 2, 3]) self.assertEqual(ts.format, 'tiff') class TestImageSubtypes(TestCase): def test_grayscale_image(self): GrayscaleImage(name='test_grayscale_image', data=np.ones((2, 2))) def test_rgb_image(self): RGBImage(name='test_rgb_image', data=np.ones((2, 2, 3))) def test_rgba_image(self): RGBAImage('test_rgba_image', np.ones((2, 2, 4))) pynwb-1.2.1/tests/back_compat/0000755000655200065520000000000013612200376017645 5ustar circlecicircleci00000000000000pynwb-1.2.1/tests/back_compat/1.1.0_str_pub.nwb0000644000655200065520000042740013612200244022551 0ustar circlecicircleci00000000000000HDF  /` TREEH1HEAP`H0 0 .speclocpHhTREEHEAPXPSNOD Hh(Pp P,H0XxPp TREEHEAPX P 0 TREEHEAPXP P TREE(HEAPX(presentationtemplates0TREEHEAPXPSNODhpTREEHEAPXPXxTREEHEAPX related_publications8 H nwb_version<=0?#]xSNODGCOLone publication 2019-11-27T17:32:34.921967-08:00ADDMEADDME 2019-11-27T17:32:34.920969-08:00 2019-11-27T17:32:34.920969-08:002.1.0core NWBFile $d5544a2d-b296-4855-b7c2-9018c980a428 G{"groups":[{"datasets":[{"dtype":"float","name":"start_time","doc":"Start time of epoch, in seconds.","neurodata_type_inc":"VectorData"},{"dtype":"float","name":"stop_time","doc":"Stop time of epoch, in seconds.","neurodata_type_inc":"VectorData"},{"dtype":"text","name":"tags","doc":"User-defined tags that identify or categorize events.","quantity":"?","neurodata_type_inc":"VectorData"},{"name":"tags_index","doc":"Index for tags.","quantity":"?","neurodata_type_inc":"VectorIndex"},{"dtype":[{"doc":"Start index into the TimeSeries 'data' and 'timestamp' datasets of the referenced TimeSeries. The first dimension of those arrays is always time.","name":"idx_start","dtype":"int32"},{"doc":"Number of data samples available in this time series, during this epoch.","name":"count","dtype":"int32"},{"doc":"the TimeSeries that this index applies to.","name":"timeseries","dtype":{"target_type":"TimeSeries","reftype":"object"}}],"name":"timeseries","doc":"An index into a TimeSeries object.","quantity":"?","neurodata_type_inc":"VectorData"},{"name":"timeseries_index","doc":"Index for timeseries.","quantity":"?","neurodata_type_inc":"VectorIndex"}],"doc":"A container for aggregating epoch data and the TimeSeries that each epoch applies to.","neurodata_type_inc":"DynamicTable","neurodata_type_def":"TimeIntervals","attributes":[{"name":"colnames","doc":"The names of the columns in this table. This should be used to specify an order to the columns.","dtype":"ascii","shape":[null],"dims":["num_columns"]},{"name":"description","doc":"Description of what is in this dynamic table.","dtype":"text"}]}]}84#]x4#](4#]84#]acquisitionanalysisprocessingstimulusgeneralfile_create_dateidentifiersession_descriptionsession_start_timetimestamps_reference_timespecificationsSNODh-(  0 x(.8/p=0?8  2H4#]   S'HG y(@x:@x,1@x@x0GBG~ @x,GGUG H namespace Hneurodata_type H object_id$ PTREEhBHEAPXP?coreH?ATREEpFHEAPXB2.1.0HSNOD??ACETREE@pBHEAP`vSNODCCEX4#]GCOLx'S'{"datasets":[{"doc":"An abstract data type for a dataset.","neurodata_type_def":"NWBData"},{"doc":"Pointers that index data values.","neurodata_type_inc":"NWBData","neurodata_type_def":"Index","attributes":[{"name":"target","doc":"Target dataset that this index applies to.","dtype":{"target_type":"NWBData","reftype":"object"}}]},{"doc":"A 1-dimensional dataset. This can be indexed using a VectorIndex to encode a 2-dimensional ragged array in 1 dimension. The first vector is at VectorData[0:VectorIndex(0)+1]. The second vector is at VectorData[VectorIndex(0)+1:VectorIndex(1)+1]. And so on.","neurodata_type_inc":"NWBData","neurodata_type_def":"VectorData","attributes":[{"name":"description","doc":"Description of what these vectors represent.","dtype":"text"}]},{"doc":"An array of indices into the first dimension of the target VectorData. Can be used with VectorData to encode a 2-dimensional ragged array in 1 dimension.","neurodata_type_inc":"Index","neurodata_type_def":"VectorIndex","attributes":[{"name":"target","doc":"Reference to the target dataset that this index applies to.","dtype":{"target_type":"VectorData","reftype":"object"}}]},{"shape":[null],"dims":["num_elements"],"dtype":"int","doc":"A list of unique identifiers for values within a dataset, e.g. rows of a DynamicTable.","default_name":"element_id","neurodata_type_inc":"NWBData","neurodata_type_def":"ElementIdentifiers"},{"dtype":"int","doc":"A region/index into a DynamicTable.","neurodata_type_inc":"VectorData","neurodata_type_def":"DynamicTableRegion","attributes":[{"name":"table","doc":"Reference to the DynamicTable object that this region applies to.","dtype":{"target_type":"DynamicTable","reftype":"object"}},{"name":"description","doc":"Description of what this table region points to.","dtype":"text"}]},{"shape":[[null,null],[null,null,3],[null,null,4]],"dims":[["num_x","num_y"],["num_x","num_y","(r, g, b)"],["num_x","num_y","(r, g, b, a)"]],"doc":"An abstract data type for an image. Shape can be 2-D (x, y), or 3-D where the third dimension can have three or four elements, e.g. (x, y, (r, g, b)) or (x, y, (r, g, b, a)).","neurodata_type_inc":"NWBData","neurodata_type_def":"Image","attributes":[{"name":"resolution","doc":"Pixel resolution of the image, in pixels per centimeter.","required":false,"dtype":"float"},{"name":"description","doc":"Description of the image.","required":false,"dtype":"text"}]}],"groups":[{"doc":"An abstract data type for a generic container storing collections of data and metadata. Base type for all data and metadata containers.","neurodata_type_def":"NWBContainer"},{"doc":"An abstract data type for a generic container storing collections of data, as opposed to metadata.","neurodata_type_inc":"NWBContainer","neurodata_type_def":"NWBDataInterface"},{"groups":[{"name":"sync","doc":"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. 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.","quantity":"?"}],"datasets":[{"shape":[[null],[null,null],[null,null,null],[null,null,null,null]],"dims":[["num_times"],["num_times","num_DIM2"],["num_times","num_DIM2","num_DIM3"],["num_times","num_DIM2","num_DIM3","num_DIM4"]],"name":"data","doc":"Data values. Data can be in 1-D, 2-D, 3-D, or 4-D. The first dimension should always represent time. This can also be used to store binary data (e.g., image frames). This can also be a link to data stored in an external file.","attributes":[{"name":"conversion","doc":"Scalar to multiply each element in data to convert it to the specified 'unit'. If the data are stored in acquisition system units or other units that require a conversion to be interpretable, multiply the data by 'conversion' to convert the data to the specified 'unit'. e.g. if the data acquisition system stores values in this object as signed 16-bit integers (int16 range -32,768 to 32,767) that correspond to a 5V range (-2.5V to 2.5V), and the data acquisition system gain is 8000X, then the 'conversion' multiplier to get from raw data acquisition values to recorded volts is 2.5/32768/8000 = 9.5367e-9.","required":false,"dtype":"float32","default_value":1.0},{"name":"resolution","doc":"Smallest meaningful difference between values in data, stored in the specified by unit, 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 -1.0.","required":false,"dtype":"float32","default_value":-1.0},{"name":"unit","doc":"Base unit of measurement for working with the data. Actual stored values are not necessarily stored in these units. To access the data in these units, multiply 'data' by 'conversion'.","dtype":"text"}]},{"dtype":"float64","name":"starting_time","doc":"Timestamp of the first sample in seconds. When timestamps are uniformly spaced, the timestamp of the first sample can be specified and all subsequent ones calculated from the sampling rate attribute.","quantity":"?","attributes":[{"name":"rate","doc":"Sampling rate, in Hz.","dtype":"float32"},{"name":"unit","doc":"Unit of measurement for time, which is fixed to 'seconds'.","dtype":"text","value":"seconds"}]},{"shape":[null],"dims":["num_times"],"dtype":"float64","name":"timestamps","doc":"Timestamps for samples stored in data, in seconds, relative to the common experiment master-clock stored in NWBFile.timestamps_reference_time.","quantity":"?","attributes":[{"name":"interval","doc":"Value is '1'","dtype":"int32","value":1},{"name":"unit","doc":"Unit of measurement for timestamps, which is fixed to 'seconds'.","dtype":"text","value":"seconds"}]},{"shape":[null],"dims":["num_times"],"dtype":"uint8","name":"control","doc":"Numerical labels that apply to each time point in data for the purpose of querying and slicing data by these values. If present, the length of this array should be the same size as the first dimension of data.","quantity":"?"},{"shape":[null],"dims":["num_control_values"],"dtype":"text","name":"control_description","doc":"Description of each control value. Must be present if control is present. If present, control_description[0] should describe time points where control == 0.","quantity":"?"}],"doc":"General purpose time series.","neurodata_type_inc":"NWBDataInterface","neurodata_type_def":"TimeSeries","attributes":[{"name":"description","doc":"Description of the time series.","required":false,"dtype":"text","default_value":"no description"},{"name":"comments","doc":"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.","required":false,"dtype":"text","default_value":"no comments"}]},{"groups":[{"doc":"Data objects stored in this collection.","quantity":"*","neurodata_type_inc":"NWBDataInterface"}],"doc":"A collection of processed data.","neurodata_type_inc":"NWBContainer","neurodata_type_def":"ProcessingModule","attributes":[{"name":"description","doc":"Description of this collection of processed data.","dtype":"text"}]},{"datasets":[{"doc":"Images stored in this collection.","quantity":"+","neurodata_type_inc":"Image"}],"doc":"A collection of images.","default_name":"Images","neurodata_type_inc":"NWBDataInterface","neurodata_type_def":"Images","attributes":[{"name":"description","doc":"Description of this collection of images.","dtype":"text"}]},{"datasets":[{"shape":[null],"dims":["num_rows"],"dtype":"int","name":"id","doc":"Array of unique identifiers for the rows of this dynamic table.","neurodata_type_inc":"ElementIdentifiers"},{"doc":"Vector columns of this dynamic table.","quantity":"*","neurodata_type_inc":"VectorData"},{"doc":"Indices for the vector columns of this dynamic table.","quantity":"*","neurodata_type_inc":"VectorIndex"}],"doc":"A group containing multiple datasets that are aligned on the first dimension (Currently, this requirement if left up to APIs to check and enforce). Apart from a column that contains unique identifiers for each row there are no other required datasets. Users are free to add any number of VectorData objects here. Table functionality is already supported through compound types, which is analogous to storing an array-of-structs. DynamicTable can be thought of as a struct-of-arrays. This provides an alternative structure to choose from when optimizing storage for anticipated access patterns. Additionally, this type provides a way of creating a table without having to define a compound type up front. Although this convenience may be attractive, users should think carefully about how data will be accessed. DynamicTable is more appropriate for column-centric access, whereas a dataset with a compound type would be more appropriate for row-centric access. Finally, data size should also be taken into account. For small tables, performance loss may be an acceptable trade-off for the flexibility of a DynamicTable. For example, DynamicTable was originally developed for storing trial data and spike unit metadata. Both of these use cases are expected to produce relatively small tables, so the spatial locality of multiple datasets present in a DynamicTable is not expected to have a significant performance impact. Additionally, requirements of trial and unit metadata tables are sufficiently diverse that performance implications can be overlooked in favor of usability.","neurodata_type_inc":"NWBDataInterface","neurodata_type_def":"DynamicTable","attributes":[{"name":"colnames","doc":"The names of the columns in this table. This should be used to specify an order to the columns.","dtype":"ascii","shape":[null],"dims":["num_columns"]},{"name":"description","doc":"Description of what is in this dynamic table.","dtype":"text"}]}]}SNOD(FGXuh?qh4#]x4#]4#]4#]4#]nwb.basenwb.epochnwb.imagenwb.filenwb.miscnwb.behaviornwb.ecephysnwb.icephysnwb.ogennwb.ophysnwb.retinotopynamespaceGCOLPy({"datasets":[{"shape":[null,null],"dims":["y","x"],"doc":"A grayscale image.","neurodata_type_inc":"Image","neurodata_type_def":"GrayscaleImage","attributes":[{"name":"resolution","doc":"Pixel resolution of the image, in pixels per centimeter.","required":false,"dtype":"float"},{"name":"description","doc":"Description of the image.","required":false,"dtype":"text"}]},{"shape":[null,null,3],"dims":["y","x","R, G, B"],"doc":"A color image.","neurodata_type_inc":"Image","neurodata_type_def":"RGBImage","attributes":[{"name":"resolution","doc":"Pixel resolution of the image, in pixels per centimeter.","required":false,"dtype":"float"},{"name":"description","doc":"Description of the image.","required":false,"dtype":"text"}]},{"shape":[null,null,4],"dims":["y","x","R, G, B, A"],"doc":"A color image with transparency.","neurodata_type_inc":"Image","neurodata_type_def":"RGBAImage","attributes":[{"name":"resolution","doc":"Pixel resolution of the image, in pixels per centimeter.","required":false,"dtype":"float"},{"name":"description","doc":"Description of the image.","required":false,"dtype":"text"}]}],"groups":[{"datasets":[{"shape":[[null,null,null],[null,null,null,null]],"dims":[["frame","y","x"],["frame","z","y","x"]],"dtype":"numeric","name":"data","doc":"Binary data representing images across frames.","quantity":"?","attributes":[{"name":"conversion","doc":"Scalar to multiply each element in data to convert it to the specified 'unit'. If the data are stored in acquisition system units or other units that require a conversion to be interpretable, multiply the data by 'conversion' to convert the data to the specified 'unit'. e.g. if the data acquisition system stores values in this object as signed 16-bit integers (int16 range -32,768 to 32,767) that correspond to a 5V range (-2.5V to 2.5V), and the data acquisition system gain is 8000X, then the 'conversion' multiplier to get from raw data acquisition values to recorded volts is 2.5/32768/8000 = 9.5367e-9.","required":false,"dtype":"float32","default_value":1.0},{"name":"resolution","doc":"Smallest meaningful difference between values in data, stored in the specified by unit, 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 -1.0.","required":false,"dtype":"float32","default_value":-1.0},{"name":"unit","doc":"Base unit of measurement for working with the data. Actual stored values are not necessarily stored in these units. To access the data in these units, multiply 'data' by 'conversion'.","dtype":"text"}]},{"shape":[null],"dims":["rank"],"dtype":"int32","name":"dimension","doc":"Number of pixels on x, y, (and z) axes.","quantity":"?"},{"shape":[null],"dims":["num_files"],"dtype":"text","name":"external_file","doc":"Paths to one or more external file(s). The field is only present if format='external'. This is only relevant if the image series is stored in the file system as one or more image file(s). This field should NOT be used if the image is stored in another NWB file and that file is linked to this file.","quantity":"?","attributes":[{"name":"starting_frame","doc":"Each external image may contain one or more consecutive frames of the full ImageSeries. This attribute serves as an index to indicate which frames each file contains, to faciliate random access. The 'starting_frame' attribute, hence, contains a list of frame numbers within the full ImageSeries of the first frame of each file listed in the parent 'external_file' dataset. Zero-based indexing is used (hence, the first element will always be zero). For example, if the 'external_file' dataset has three paths to files and the first file has 5 frames, the second file has 10 frames, and the third file has 20 frames, then this attribute will have values [0, 5, 15]. If there is a single external file that holds all of the frames of the ImageSeries (and so there is a single element in the 'external_file' dataset), then this attribute should have value [0].","dtype":"int","shape":[null],"dims":["num_files"]}]},{"dtype":"text","name":"format","doc":"Format of image. If this is 'external', then the attribute 'external_file' contains the path information to the image files. If this is 'raw', then the raw (single-channel) binary data is stored in the 'data' dataset. If this attribute is not present, then the default format='raw' case is assumed.","quantity":"?","default_value":"raw"}],"doc":"General image data that is common between acquisition and stimulus time series. Sometimes the image data is stored in the file in a raw format while other times it will be stored as a series of external image files in the host file system. The data field will either be binary data, if the data is stored in the NWB file, or empty, if the data is stored in an external image stack. [frame][y][x] or [frame][z][y][x].","neurodata_type_inc":"TimeSeries","neurodata_type_def":"ImageSeries","attributes":[{"name":"description","doc":"Description of the time series.","required":false,"dtype":"text","default_value":"no description"},{"name":"comments","doc":"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.","required":false,"dtype":"text","default_value":"no comments"}]},{"links":[{"name":"masked_imageseries","doc":"Link to ImageSeries object that this image mask is applied to.","target_type":"ImageSeries"}],"doc":"An alpha mask that is applied to a presented visual stimulus. The 'data' array contains an array of mask values that are applied to the displayed image. Mask values are stored as RGBA. Mask can vary with time. The timestamps array indicates the starting time of a mask, and that mask pattern continues until it's explicitly changed.","neurodata_type_inc":"ImageSeries","neurodata_type_def":"ImageMaskSeries","attributes":[{"name":"description","doc":"Description of the time series.","required":false,"dtype":"text","default_value":"no description"},{"name":"comments","doc":"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.","required":false,"dtype":"text","default_value":"no comments"}]},{"datasets":[{"dtype":"float32","name":"distance","doc":"Distance from camera/monitor to target/eye.","quantity":"?"},{"shape":[[2],[3]],"dims":[["width, height"],["width, height, depth"]],"dtype":"float32","name":"field_of_view","doc":"Width, height and depth of image, or imaged area, in meters.","quantity":"?"},{"dtype":"text","name":"orientation","doc":"Description of image relative to some reference frame (e.g., which way is up). Must also specify frame of reference.","quantity":"?"}],"doc":"Image data that is presented or recorded. A stimulus template movie will be stored only as an image. When the image is presented as stimulus, additional data is required, such as field of view (e.g., how much of the visual field the image covers, or how what is the area of the target being imaged). If the OpticalSeries represents acquired imaging data, orientation is also important.","neurodata_type_inc":"ImageSeries","neurodata_type_def":"OpticalSeries","attributes":[{"name":"description","doc":"Description of the time series.","required":false,"dtype":"text","default_value":"no description"},{"name":"comments","doc":"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.","required":false,"dtype":"text","default_value":"no comments"}]},{"datasets":[{"shape":[null],"dims":["num_times"],"dtype":"int","name":"data","doc":"Index of the frame in the referenced ImageSeries.","attributes":[{"name":"conversion","doc":"Scalar to multiply each element in data to convert it to the specified 'unit'. If the data are stored in acquisition system units or other units that require a conversion to be interpretable, multiply the data by 'conversion' to convert the data to the specified 'unit'. e.g. if the data acquisition system stores values in this object as signed 16-bit integers (int16 range -32,768 to 32,767) that correspond to a 5V range (-2.5V to 2.5V), and the data acquisition system gain is 8000X, then the 'conversion' multiplier to get from raw data acquisition values to recorded volts is 2.5/32768/8000 = 9.5367e-9.","required":false,"dtype":"float32","default_value":1.0},{"name":"resolution","doc":"Smallest meaningful difference between values in data, stored in the specified by unit, 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 -1.0.","required":false,"dtype":"float32","default_value":-1.0},{"name":"unit","doc":"Base unit of measurement for working with the data. Actual stored values are not necessarily stored in these units. To access the data in these units, multiply 'data' by 'conversion'.","dtype":"text"}]}],"links":[{"name":"indexed_timeseries","doc":"Link to ImageSeries object containing images that are indexed.","target_type":"ImageSeries"}],"doc":"Stores indices to image frames stored in an ImageSeries. The purpose of the ImageIndexSeries 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 ImageSeries, and the timestamps array indicates when that image was displayed.","neurodata_type_inc":"TimeSeries","neurodata_type_def":"IndexSeries","attributes":[{"name":"description","doc":"Description of the time series.","required":false,"dtype":"text","default_value":"no description"},{"name":"comments","doc":"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.","required":false,"dtype":"text","default_value":"no comments"}]}]}:{"groups":[{"groups":[{"groups":[{"doc":"Acquired, raw data.","quantity":"*","neurodata_type_inc":"NWBDataInterface"}],"name":"acquisition","doc":"Data streams recorded from the system, including ephys, ophys, tracking, etc. This group should be 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 NWB files. This will allow keeping bulky raw data out of the file while preserving the option of keeping some/all in the file. Acquired data includes tracking and experimental data streams (i.e., everything measured from the system). If bulky data is stored in the /acquisition group, the data can exist in a separate NWB file that is linked to by the file being used for processing and analysis."},{"groups":[{"doc":"Custom analysis results.","quantity":"*","neurodata_type_inc":"NWBContainer"}],"name":"analysis","doc":"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. To facilitate sharing analysis data between labs, the contents here should be stored in standard types (e.g., neurodata_types) and appropriately documented. 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 could be shared with other labs."},{"groups":[{"doc":"Any one-off containers","quantity":"*","neurodata_type_inc":"NWBContainer"}],"datasets":[{"doc":"Any one-off datasets","quantity":"*","neurodata_type_inc":"NWBData","neurodata_type_def":"ScratchData","attributes":[{"name":"notes","doc":"Any notes the user has about the dataset being stored","dtype":"text"}]}],"name":"scratch","doc":"A place to store one-off analysis results. Data placed here is not intended for sharing. By placing data here, users acknowledge that there is no guarantee that their data meets any standard.","quantity":"?"},{"groups":[{"doc":"Intermediate analysis of acquired data.","quantity":"*","neurodata_type_inc":"ProcessingModule"}],"name":"processing","doc":"The home for ProcessingModules. 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. ProcessingModules 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. 'Processing' refers to intermediate analysis of the acquired data to make it more amenable to scientific analysis."},{"groups":[{"groups":[{"doc":"TimeSeries objects containing data of presented stimuli.","quantity":"*","neurodata_type_inc":"TimeSeries"}],"name":"presentation","doc":"Stimuli presented during the experiment."},{"groups":[{"doc":"TimeSeries objects containing template data of presented stimuli.","quantity":"*","neurodata_type_inc":"TimeSeries"}],"name":"templates","doc":"Template stimuli. Timestamps 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."}],"name":"stimulus","doc":"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). This group should be made 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. 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 linked to a remote library file."},{"groups":[{"doc":"Place-holder than can be extended so that lab-specific meta-data can be placed in /general.","quantity":"*","neurodata_type_inc":"NWBContainer","neurodata_type_def":"LabMetaData"},{"groups":[{"doc":"A data acquisition device, e.g. recording system.","quantity":"+","neurodata_type_inc":"NWBContainer","neurodata_type_def":"Device"}],"name":"devices","doc":"Description of hardware devices used during experiment, e.g., monitors, ADC boards, microscopes, etc.","quantity":"?"},{"datasets":[{"dtype":"text","name":"age","doc":"Age of subject. Can be supplied instead of 'date_of_birth'.","quantity":"?"},{"dtype":"isodatetime","name":"date_of_birth","doc":"Date of birth of subject. Can be supplied instead of 'age'.","quantity":"?"},{"dtype":"text","name":"description","doc":"Description of subject and where subject came from (e.g., breeder, if animal).","quantity":"?"},{"dtype":"text","name":"genotype","doc":"Genetic strain. If absent, assume Wild Type (WT).","quantity":"?"},{"dtype":"text","name":"sex","doc":"Gender of subject.","quantity":"?"},{"dtype":"text","name":"species","doc":"Species of subject.","quantity":"?"},{"dtype":"text","name":"subject_id","doc":"ID of animal/person used/participating in experiment (lab convention).","quantity":"?"},{"dtype":"text","name":"weight","doc":"Weight at time of experiment, at time of surgery and at other important times.","quantity":"?"}],"name":"subject","doc":"Information about the animal or person from which the data was measured.","quantity":"?","neurodata_type_inc":"NWBContainer","neurodata_type_def":"Subject"},{"groups":[{"doc":"Physical group of electrodes.","quantity":"*","neurodata_type_inc":"ElectrodeGroup"},{"datasets":[{"dtype":"float","name":"x","doc":"x coordinate of the channel location.","neurodata_type_inc":"VectorData"},{"dtype":"float","name":"y","doc":"y coordinate of the channel location.","neurodata_type_inc":"VectorData"},{"dtype":"float","name":"z","doc":"z coordinate of the channel location.","neurodata_type_inc":"VectorData"},{"dtype":"float","name":"imp","doc":"Impedance of the channel.","neurodata_type_inc":"VectorData"},{"dtype":"ascii","name":"location","doc":"Location of the electrode (channel). Specify the area, layer, comments on estimation of area/layer, stereotaxic coordinates if in vivo, etc. Use standard atlas names for anatomical regions when possible.","neurodata_type_inc":"VectorData"},{"dtype":"float","name":"filtering","doc":"Description of hardware filtering.","neurodata_type_inc":"VectorData"},{"dtype":{"target_type":"ElectrodeGroup","reftype":"object"},"name":"group","doc":"Reference to the ElectrodeGroup this electrode is a part of.","neurodata_type_inc":"VectorData"},{"dtype":"ascii","name":"group_name","doc":"Name of the ElectrodeGroup this electrode is a part of.","neurodata_type_inc":"VectorData"}],"name":"electrodes","doc":"A table of all electrodes (i.e. channels) used for recording.","quantity":"?","neurodata_type_inc":"DynamicTable"}],"name":"extracellular_ephys","doc":"Metadata related to extracellular electrophysiology.","quantity":"?"},{"groups":[{"doc":"An intracellular electrode.","quantity":"*","neurodata_type_inc":"IntracellularElectrode"},{"name":"sweep_table","doc":"The table which groups different PatchClampSeries together.","quantity":"?","neurodata_type_inc":"SweepTable"}],"datasets":[{"dtype":"text","name":"filtering","doc":"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.","quantity":"?"}],"name":"intracellular_ephys","doc":"Metadata related to intracellular electrophysiology.","quantity":"?"},{"groups":[{"doc":"An optogenetic stimulation site.","quantity":"*","neurodata_type_inc":"OptogeneticStimulusSite"}],"name":"optogenetics","doc":"Metadata describing optogenetic stimuluation.","quantity":"?"},{"groups":[{"doc":"An imaging plane.","quantity":"*","neurodata_type_inc":"ImagingPlane"}],"name":"optophysiology","doc":"Metadata related to optophysiology.","quantity":"?"}],"datasets":[{"dtype":"text","name":"data_collection","doc":"Notes about data collection and analysis.","quantity":"?"},{"dtype":"text","name":"experiment_description","doc":"General description of the experiment.","quantity":"?"},{"shape":[null],"dims":["num_experimenters"],"dtype":"text","name":"experimenter","doc":"Name of person(s) who performed the experiment. Can also specify roles of different people involved.","quantity":"?"},{"dtype":"text","name":"institution","doc":"Institution(s) where experiment was performed.","quantity":"?"},{"shape":[null],"dims":["num_keywords"],"dtype":"text","name":"keywords","doc":"Terms to search over.","quantity":"?"},{"dtype":"text","name":"lab","doc":"Laboratory where experiment was performed.","quantity":"?"},{"dtype":"text","name":"notes","doc":"Notes about the experiment.","quantity":"?"},{"dtype":"text","name":"pharmacology","doc":"Description of drugs used, including how and when they were administered. Anesthesia(s), painkiller(s), etc., plus dosage, concentration, etc.","quantity":"?"},{"dtype":"text","name":"protocol","doc":"Experimental protocol, if applicable. e.g., include IACUC protocol number.","quantity":"?"},{"shape":[null],"dims":["num_publications"],"dtype":"text","name":"related_publications","doc":"Publication information. PMID, DOI, URL, etc.","quantity":"?"},{"dtype":"text","name":"session_id","doc":"Lab-specific ID for the session.","quantity":"?"},{"dtype":"text","name":"slices","doc":"Description of slices, including information about preparation thickness, orientation, temperature, and bath solution.","quantity":"?"},{"dtype":"text","name":"source_script","doc":"Script file or link to public source code used to create this NWB file.","quantity":"?","attributes":[{"name":"file_name","doc":"Name of script file.","dtype":"text"}]},{"dtype":"text","name":"stimulus","doc":"Notes about stimuli, such as how and where they were presented.","quantity":"?"},{"dtype":"text","name":"surgery","doc":"Narrative description about surgery/surgeries, including date(s) and who performed surgery.","quantity":"?"},{"dtype":"text","name":"virus","doc":"Information about virus(es) used in experiments, including virus ID, source, date made, injection location, volume, etc.","quantity":"?"}],"name":"general","doc":"Experimental metadata, including protocol, notes and description of hardware device(s). The metadata stored in this section should be used to describe the experiment. Metadata necessary for interpreting the data is stored with the data. 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 (e.g., 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. 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."},{"groups":[{"name":"epochs","doc":"Divisions in time marking experimental stages or sub-divisions of a single recording session.","quantity":"?","neurodata_type_inc":"TimeIntervals"},{"name":"trials","doc":"Repeated experimental events that have a logical grouping.","quantity":"?","neurodata_type_inc":"TimeIntervals"},{"name":"invalid_times","doc":"Time intervals that should be removed from analysis.","quantity":"?","neurodata_type_inc":"TimeIntervals"},{"doc":"Optional additional table(s) for describing other experimental time intervals.","quantity":"*","neurodata_type_inc":"TimeIntervals"}],"name":"intervals","doc":"Experimental intervals, whether that be logically distinct sub-experiments having a particular scientific goal, trials (see trials subgroup) during an experiment, or epochs (see epochs subgroup) deriving from analysis of data.","quantity":"?"},{"name":"units","doc":"Data about sorted spike units.","quantity":"?","neurodata_type_inc":"Units"}],"datasets":[{"shape":[null],"dims":["num_modifications"],"dtype":"isodatetime","name":"file_create_date","doc":"A record of the date the file was created and of subsequent modifications. The date is stored in UTC with local timezone offset as ISO 8601 extended formatted strings: 2018-09-28T14:43:54.123+02:00. Dates stored in UTC end in \"Z\" with no timezone offset. Date accuracy is up to milliseconds. The file can be created after the experiment was run, so this may differ from the experiment start time. Each modification to the nwb file adds a new entry to the array."},{"dtype":"text","name":"identifier","doc":"A unique text identifier for the file. For example, 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."},{"dtype":"text","name":"session_description","doc":"A description of the experimental session and data in the file."},{"dtype":"isodatetime","name":"session_start_time","doc":"Date and time of the experiment/session start. The date is stored in UTC with local timezone offset as ISO 8601 extended formatted string: 2018-09-28T14:43:54.123+02:00. Dates stored in UTC end in \"Z\" with no timezone offset. Date accuracy is up to milliseconds."},{"dtype":"isodatetime","name":"timestamps_reference_time","doc":"Date and time corresponding to time zero of all timestamps. The date is stored in UTC with local timezone offset as ISO 8601 extended formatted string: 2018-09-28T14:43:54.123+02:00. Dates stored in UTC end in \"Z\" with no timezone offset. Date accuracy is up to milliseconds. All times stored in the file use this time as reference (i.e., time zero)."}],"name":"root","doc":"An NWB:N file storing cellular-based neurophysiology data from a single experimental session.","neurodata_type_inc":"NWBContainer","neurodata_type_def":"NWBFile","attributes":[{"name":"nwb_version","doc":"File version string. Use semantic versioning, e.g. 1.2.1. This will be the name of the format with trailing major, minor and patch numbers.","dtype":"text","value":"2.1.0"}]}]},1{"groups":[{"datasets":[{"shape":[[null],[null,null]],"dims":[["num_times"],["num_times","num_features"]],"dtype":"numeric","name":"data","doc":"Values of each feature at each time.","attributes":[{"name":"unit","doc":"Since there can be different units for different features, store the units in 'feature_units'. The default value for this attribute is \"see 'feature_units'\".","required":false,"dtype":"text","default_value":"see 'feature_units'"},{"name":"conversion","doc":"Scalar to multiply each element in data to convert it to the specified 'unit'. If the data are stored in acquisition system units or other units that require a conversion to be interpretable, multiply the data by 'conversion' to convert the data to the specified 'unit'. e.g. if the data acquisition system stores values in this object as signed 16-bit integers (int16 range -32,768 to 32,767) that correspond to a 5V range (-2.5V to 2.5V), and the data acquisition system gain is 8000X, then the 'conversion' multiplier to get from raw data acquisition values to recorded volts is 2.5/32768/8000 = 9.5367e-9.","required":false,"dtype":"float32","default_value":1.0},{"name":"resolution","doc":"Smallest meaningful difference between values in data, stored in the specified by unit, 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 -1.0.","required":false,"dtype":"float32","default_value":-1.0}]},{"shape":[null],"dims":["num_features"],"dtype":"text","name":"feature_units","doc":"Units of each feature.","quantity":"?"},{"shape":[null],"dims":["num_features"],"dtype":"text","name":"features","doc":"Description of the features represented in TimeSeries::data."}],"doc":"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. This is useful when storing the raw stimulus is impractical.","neurodata_type_inc":"TimeSeries","neurodata_type_def":"AbstractFeatureSeries","attributes":[{"name":"description","doc":"Description of the time series.","required":false,"dtype":"text","default_value":"no description"},{"name":"comments","doc":"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.","required":false,"dtype":"text","default_value":"no comments"}]},{"datasets":[{"shape":[null],"dims":["num_times"],"dtype":"text","name":"data","doc":"Annotations made during an experiment.","attributes":[{"name":"resolution","doc":"Smallest meaningful difference between values in data. Annotations have no units, so the value is fixed to -1.0.","dtype":"float","value":-1.0},{"name":"unit","doc":"Base unit of measurement for working with the data. Annotations have no units, so the value is fixed to 'n/a'.","dtype":"text","value":"n/a"},{"name":"conversion","doc":"Scalar to multiply each element in data to convert it to the specified 'unit'. If the data are stored in acquisition system units or other units that require a conversion to be interpretable, multiply the data by 'conversion' to convert the data to the specified 'unit'. e.g. if the data acquisition system stores values in this object as signed 16-bit integers (int16 range -32,768 to 32,767) that correspond to a 5V range (-2.5V to 2.5V), and the data acquisition system gain is 8000X, then the 'conversion' multiplier to get from raw data acquisition values to recorded volts is 2.5/32768/8000 = 9.5367e-9.","required":false,"dtype":"float32","default_value":1.0}]}],"doc":"Stores user annotations made during an experiment. The 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.","neurodata_type_inc":"TimeSeries","neurodata_type_def":"AnnotationSeries","attributes":[{"name":"description","doc":"Description of the time series.","required":false,"dtype":"text","default_value":"no description"},{"name":"comments","doc":"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.","required":false,"dtype":"text","default_value":"no comments"}]},{"datasets":[{"shape":[null],"dims":["num_times"],"dtype":"int8","name":"data","doc":"Use values >0 if interval started, <0 if interval ended.","attributes":[{"name":"resolution","doc":"Smallest meaningful difference between values in data. Annotations have no units, so the value is fixed to -1.0.","dtype":"float","value":-1.0},{"name":"unit","doc":"Base unit of measurement for working with the data. Annotations have no units, so the value is fixed to 'n/a'.","dtype":"text","value":"n/a"},{"name":"conversion","doc":"Scalar to multiply each element in data to convert it to the specified 'unit'. If the data are stored in acquisition system units or other units that require a conversion to be interpretable, multiply the data by 'conversion' to convert the data to the specified 'unit'. e.g. if the data acquisition system stores values in this object as signed 16-bit integers (int16 range -32,768 to 32,767) that correspond to a 5V range (-2.5V to 2.5V), and the data acquisition system gain is 8000X, then the 'conversion' multiplier to get from raw data acquisition values to recorded volts is 2.5/32768/8000 = 9.5367e-9.","required":false,"dtype":"float32","default_value":1.0}]}],"doc":"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.","neurodata_type_inc":"TimeSeries","neurodata_type_def":"IntervalSeries","attributes":[{"name":"description","doc":"Description of the time series.","required":false,"dtype":"text","default_value":"no description"},{"name":"comments","doc":"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.","required":false,"dtype":"text","default_value":"no comments"}]},{"groups":[{"datasets":[{"dtype":"text","name":"band_name","doc":"Name of the band, e.g. theta.","neurodata_type_inc":"VectorData"},{"shape":[null,2],"dims":["num_bands","low, high"],"dtype":"float","name":"band_limits","doc":"Low and high limit of each band in Hz. If it is a Gaussian filter, use 2 SD on either side of the center.","neurodata_type_inc":"VectorData"},{"shape":[null],"dims":["num_bands"],"dtype":"float","name":"band_mean","doc":"The mean Gaussian filters, in Hz.","neurodata_type_inc":"VectorData"},{"shape":[null],"dims":["num_bands"],"dtype":"float","name":"band_stdev","doc":"The standard deviation of Gaussian filters, in Hz.","neurodata_type_inc":"VectorData"}],"name":"bands","doc":"Table for describing the bands that this series was generated from. There should be one row in this table for each band.","neurodata_type_inc":"DynamicTable"}],"datasets":[{"shape":[null,null,null],"dims":["num_times","num_channels","num_bands"],"dtype":"numeric","name":"data","doc":"Data decomposed into frequency bands.","attributes":[{"name":"unit","doc":"Base unit of measurement for working with the data. Actual stored values are not necessarily stored in these units. To access the data in these units, multiply 'data' by 'conversion'.","required":false,"dtype":"text","default_value":"no unit"},{"name":"conversion","doc":"Scalar to multiply each element in data to convert it to the specified 'unit'. If the data are stored in acquisition system units or other units that require a conversion to be interpretable, multiply the data by 'conversion' to convert the data to the specified 'unit'. e.g. if the data acquisition system stores values in this object as signed 16-bit integers (int16 range -32,768 to 32,767) that correspond to a 5V range (-2.5V to 2.5V), and the data acquisition system gain is 8000X, then the 'conversion' multiplier to get from raw data acquisition values to recorded volts is 2.5/32768/8000 = 9.5367e-9.","required":false,"dtype":"float32","default_value":1.0},{"name":"resolution","doc":"Smallest meaningful difference between values in data, stored in the specified by unit, 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 -1.0.","required":false,"dtype":"float32","default_value":-1.0}]},{"dtype":"text","name":"metric","doc":"The metric used, e.g. phase, amplitude, power."}],"links":[{"name":"source_timeseries","doc":"Link to TimeSeries object that this data was calculated from. Metadata about electrodes and their position can be read from that ElectricalSeries so it is not necessary to store that information here.","target_type":"TimeSeries","quantity":"?"}],"doc":"Spectral analysis of a time series, e.g. of an LFP or a speech signal.","neurodata_type_inc":"TimeSeries","neurodata_type_def":"DecompositionSeries","attributes":[{"name":"description","doc":"Description of the time series.","required":false,"dtype":"text","default_value":"no description"},{"name":"comments","doc":"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.","required":false,"dtype":"text","default_value":"no comments"}]},{"datasets":[{"name":"spike_times_index","doc":"Index into the spike_times dataset.","quantity":"?","neurodata_type_inc":"VectorIndex"},{"dtype":"double","name":"spike_times","doc":"Spike times for each unit.","quantity":"?","neurodata_type_inc":"VectorData"},{"name":"obs_intervals_index","doc":"Index into the obs_intervals dataset.","quantity":"?","neurodata_type_inc":"VectorIndex"},{"shape":[null,2],"dims":["num_intervals","start|end"],"dtype":"double","name":"obs_intervals","doc":"Observation intervals for each unit.","quantity":"?","neurodata_type_inc":"VectorData"},{"name":"electrodes_index","doc":"Index into electrodes.","quantity":"?","neurodata_type_inc":"VectorIndex"},{"name":"electrodes","doc":"Electrode that each spike unit came from, specified using a DynamicTableRegion.","quantity":"?","neurodata_type_inc":"DynamicTableRegion"},{"dtype":{"target_type":"ElectrodeGroup","reftype":"object"},"name":"electrode_group","doc":"Electrode group that each spike unit came from.","quantity":"?","neurodata_type_inc":"VectorData"},{"shape":[[null,null],[null,null,null]],"dims":[["num_units","num_samples"],["num_units","num_samples","num_electrodes"]],"dtype":"float","name":"waveform_mean","doc":"Spike waveform mean for each spike unit.","quantity":"?","neurodata_type_inc":"VectorData"},{"shape":[[null,null],[null,null,null]],"dims":[["num_units","num_samples"],["num_units","num_samples","num_electrodes"]],"dtype":"float","name":"waveform_sd","doc":"Spike waveform standard deviation for each spike unit.","quantity":"?","neurodata_type_inc":"VectorData"}],"doc":"Data about spiking units. Event times of observed units (e.g. cell, synapse, etc.) should be concatenated and stored in spike_times.","default_name":"Units","neurodata_type_inc":"DynamicTable","neurodata_type_def":"Units","attributes":[{"name":"colnames","doc":"The names of the columns in this table. This should be used to specify an order to the columns.","dtype":"ascii","shape":[null],"dims":["num_columns"]},{"name":"description","doc":"Description of what is in this dynamic table.","dtype":"text"}]}]}{"groups":[{"datasets":[{"shape":[[null],[null,null]],"dims":[["num_times"],["num_times","num_features"]],"dtype":"numeric","name":"data","doc":"1-D or 2-D array storing position or direction relative to some reference frame.","attributes":[{"name":"unit","doc":"Base unit of measurement for working with the data. The default value is 'meters'. Actual stored values are not necessarily stored in these units. To access the data in these units, multiply 'data' by 'conversion'.","required":false,"dtype":"text","default_value":"meters"},{"name":"conversion","doc":"Scalar to multiply each element in data to convert it to the specified 'unit'. If the data are stored in acquisition system units or other units that require a conversion to be interpretable, multiply the data by 'conversion' to convert the data to the specified 'unit'. e.g. if the data acquisition system stores values in this object as signed 16-bit integers (int16 range -32,768 to 32,767) that correspond to a 5V range (-2.5V to 2.5V), and the data acquisition system gain is 8000X, then the 'conversion' multiplier to get from raw data acquisition values to recorded volts is 2.5/32768/8000 = 9.5367e-9.","required":false,"dtype":"float32","default_value":1.0},{"name":"resolution","doc":"Smallest meaningful difference between values in data, stored in the specified by unit, 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 -1.0.","required":false,"dtype":"float32","default_value":-1.0}]},{"dtype":"text","name":"reference_frame","doc":"Description defining what exactly 'straight-ahead' means.","quantity":"?"}],"doc":"Direction, e.g., of gaze or travel, or position. The TimeSeries::data field is a 2D array storing position or direction relative to some reference frame. Array structure: [num measurements] [num dimensions]. Each SpatialSeries has a text dataset reference_frame that indicates the zero-position, or the zero-axes for direction. For example, if representing gaze direction, 'straight-ahead' might be a specific pixel on the monitor, or some other point in space. For position data, the 0,0 point might be the top-left corner of an enclosure, as viewed from the tracking camera. The unit of data will indicate how to interpret SpatialSeries values.","neurodata_type_inc":"TimeSeries","neurodata_type_def":"SpatialSeries","attributes":[{"name":"description","doc":"Description of the time series.","required":false,"dtype":"text","default_value":"no description"},{"name":"comments","doc":"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.","required":false,"dtype":"text","default_value":"no comments"}]},{"groups":[{"doc":"IntervalSeries object containing start and stop times of epochs.","quantity":"*","neurodata_type_inc":"IntervalSeries"}],"doc":"TimeSeries for storing behavioral epochs. The objective of this and the other two Behavioral interfaces (e.g. BehavioralEvents and BehavioralTimeSeries) is to provide generic hooks for software tools/scripts. This allows a tool/script to take the output one specific interface (e.g., UnitTimes) and plot that data relative to another data modality (e.g., behavioral events) without having to define all possible modalities in advance. Declaring one of these interfaces means that one or more TimeSeries of the specified type is published. These TimeSeries should reside in a group having the same name as the interface. For example, if a BehavioralTimeSeries interface is declared, the module will have one or more TimeSeries defined in the module sub-group 'BehavioralTimeSeries'. BehavioralEpochs should use IntervalSeries. BehavioralEvents is used for irregular events. BehavioralTimeSeries is for continuous data.","default_name":"BehavioralEpochs","neurodata_type_inc":"NWBDataInterface","neurodata_type_def":"BehavioralEpochs"},{"groups":[{"doc":"TimeSeries object containing behavioral events.","quantity":"*","neurodata_type_inc":"TimeSeries"}],"doc":"TimeSeries for storing behavioral events. See description of BehavioralEpochs for more details.","default_name":"BehavioralEvents","neurodata_type_inc":"NWBDataInterface","neurodata_type_def":"BehavioralEvents"},{"groups":[{"doc":"TimeSeries object containing continuous behavioral data.","quantity":"*","neurodata_type_inc":"TimeSeries"}],"doc":"TimeSeries for storing Behavoioral time series data. See description of BehavioralEpochs for more details.","default_name":"BehavioralTimeSeries","neurodata_type_inc":"NWBDataInterface","neurodata_type_def":"BehavioralTimeSeries"},{"groups":[{"doc":"TimeSeries object containing time series data on pupil size.","quantity":"+","neurodata_type_inc":"TimeSeries"}],"doc":"Eye-tracking data, representing pupil size.","default_name":"PupilTracking","neurodata_type_inc":"NWBDataInterface","neurodata_type_def":"PupilTracking"},{"groups":[{"doc":"SpatialSeries object containing data measuring direction of gaze.","quantity":"*","neurodata_type_inc":"SpatialSeries"}],"doc":"Eye-tracking data, representing direction of gaze.","default_name":"EyeTracking","neurodata_type_inc":"NWBDataInterface","neurodata_type_def":"EyeTracking"},{"groups":[{"doc":"SpatialSeries object containing direction of gaze travel.","quantity":"*","neurodata_type_inc":"SpatialSeries"}],"doc":"With a CompassDirection interface, a module publishes a SpatialSeries object representing a floating point value for theta. The SpatialSeries::reference_frame field should indicate what direction corresponds to 0 and which is the direction of rotation (this should be clockwise). The si_unit for the SpatialSeries should be radians or degrees.","default_name":"CompassDirection","neurodata_type_inc":"NWBDataInterface","neurodata_type_def":"CompassDirection"},{"groups":[{"doc":"SpatialSeries object containing position data.","quantity":"+","neurodata_type_inc":"SpatialSeries"}],"doc":"Position data, whether along the x, x/y or x/y/z axis.","default_name":"Position","neurodata_type_inc":"NWBDataInterface","neurodata_type_def":"Position"}]}~ {"groups":[{"datasets":[{"shape":[null],"dims":["num_times"],"dtype":"numeric","name":"data","doc":"Applied power for optogenetic stimulus, in watts.","attributes":[{"name":"unit","doc":"Unit of measurement for data, which is fixed to 'watts'.","dtype":"text","value":"watts"},{"name":"conversion","doc":"Scalar to multiply each element in data to convert it to the specified 'unit'. If the data are stored in acquisition system units or other units that require a conversion to be interpretable, multiply the data by 'conversion' to convert the data to the specified 'unit'. e.g. if the data acquisition system stores values in this object as signed 16-bit integers (int16 range -32,768 to 32,767) that correspond to a 5V range (-2.5V to 2.5V), and the data acquisition system gain is 8000X, then the 'conversion' multiplier to get from raw data acquisition values to recorded volts is 2.5/32768/8000 = 9.5367e-9.","required":false,"dtype":"float32","default_value":1.0},{"name":"resolution","doc":"Smallest meaningful difference between values in data, stored in the specified by unit, 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 -1.0.","required":false,"dtype":"float32","default_value":-1.0}]}],"links":[{"name":"site","doc":"Link to OptogeneticStimulusSite object that describes the site to which this stimulus was applied.","target_type":"OptogeneticStimulusSite"}],"doc":"An optogenetic stimulus.","neurodata_type_inc":"TimeSeries","neurodata_type_def":"OptogeneticSeries","attributes":[{"name":"description","doc":"Description of the time series.","required":false,"dtype":"text","default_value":"no description"},{"name":"comments","doc":"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.","required":false,"dtype":"text","default_value":"no comments"}]},{"datasets":[{"dtype":"text","name":"description","doc":"Description of stimulation site."},{"dtype":"float","name":"excitation_lambda","doc":"Excitation wavelength, in nm."},{"dtype":"text","name":"location","doc":"Location of the stimulation site. Specify the area, layer, comments on estimation of area/layer, stereotaxic coordinates if in vivo, etc. Use standard atlas names for anatomical regions when possible."}],"links":[{"name":"device","doc":"Device that generated the stimulus.","target_type":"Device"}],"doc":"A site of optogenetic stimulation.","quantity":"*","neurodata_type_inc":"NWBContainer","neurodata_type_def":"OptogeneticStimulusSite"}]}04#]4#]4#]SNOD8sx@(rHtADE4#]4#]5#]GCOLp0{"groups":[{"datasets":[{"shape":[[null],[null,null],[null,null,null]],"dims":[["num_times"],["num_times","num_channels"],["num_times","num_channels","num_samples"]],"dtype":"numeric","name":"data","doc":"Recorded voltage data.","attributes":[{"name":"unit","doc":"Base unit of measurement for working with the data. This value is fixed to 'volts'. Actual stored values are not necessarily stored in these units. To access the data in these units, multiply 'data' by 'conversion'.","dtype":"text","value":"volts"},{"name":"conversion","doc":"Scalar to multiply each element in data to convert it to the specified 'unit'. If the data are stored in acquisition system units or other units that require a conversion to be interpretable, multiply the data by 'conversion' to convert the data to the specified 'unit'. e.g. if the data acquisition system stores values in this object as signed 16-bit integers (int16 range -32,768 to 32,767) that correspond to a 5V range (-2.5V to 2.5V), and the data acquisition system gain is 8000X, then the 'conversion' multiplier to get from raw data acquisition values to recorded volts is 2.5/32768/8000 = 9.5367e-9.","required":false,"dtype":"float32","default_value":1.0},{"name":"resolution","doc":"Smallest meaningful difference between values in data, stored in the specified by unit, 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 -1.0.","required":false,"dtype":"float32","default_value":-1.0}]},{"name":"electrodes","doc":"DynamicTableRegion pointer to the electrodes that this time series was generated from.","neurodata_type_inc":"DynamicTableRegion"}],"doc":"A time series of acquired voltage data from extracellular recordings. The data field is an int or float array storing data in volts. The first dimension should always represent time. The second dimension, if present, should represent channels.","neurodata_type_inc":"TimeSeries","neurodata_type_def":"ElectricalSeries","attributes":[{"name":"description","doc":"Description of the time series.","required":false,"dtype":"text","default_value":"no description"},{"name":"comments","doc":"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.","required":false,"dtype":"text","default_value":"no comments"}]},{"datasets":[{"shape":[[null,null],[null,null,null]],"dims":[["num_events","num_samples"],["num_events","num_channels","num_samples"]],"dtype":"numeric","name":"data","doc":"Spike waveforms.","attributes":[{"name":"unit","doc":"Unit of measurement for waveforms, which is fixed to 'volts'.","dtype":"text","value":"volts"},{"name":"conversion","doc":"Scalar to multiply each element in data to convert it to the specified 'unit'. If the data are stored in acquisition system units or other units that require a conversion to be interpretable, multiply the data by 'conversion' to convert the data to the specified 'unit'. e.g. if the data acquisition system stores values in this object as signed 16-bit integers (int16 range -32,768 to 32,767) that correspond to a 5V range (-2.5V to 2.5V), and the data acquisition system gain is 8000X, then the 'conversion' multiplier to get from raw data acquisition values to recorded volts is 2.5/32768/8000 = 9.5367e-9.","required":false,"dtype":"float32","default_value":1.0},{"name":"resolution","doc":"Smallest meaningful difference between values in data, stored in the specified by unit, 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 -1.0.","required":false,"dtype":"float32","default_value":-1.0}]},{"shape":[null],"dims":["num_times"],"dtype":"float64","name":"timestamps","doc":"Timestamps for samples stored in data, in seconds, relative to the common experiment master-clock stored in NWBFile.timestamps_reference_time. Timestamps are required for the events. Unlike for TimeSeries, timestamps are required for SpikeEventSeries and are thus re-specified here.","attributes":[{"name":"interval","doc":"Value is '1'","dtype":"int32","value":1},{"name":"unit","doc":"Unit of measurement for timestamps, which is fixed to 'seconds'.","dtype":"text","value":"seconds"}]}],"doc":"Stores snapshots/snippets of recorded spike events (i.e., threshold crossings). This may also be raw data, as reported by ephys hardware. If so, the TimeSeries::description field should describe how events were detected. All SpikeEventSeries should reside in a module (under EventWaveform interface) even if the spikes were reported and stored by hardware. All events span the same recording channels and store snapshots of equal duration. TimeSeries::data array structure: [num events] [num channels] [num samples] (or [num events] [num samples] for single electrode).","neurodata_type_inc":"ElectricalSeries","neurodata_type_def":"SpikeEventSeries","attributes":[{"name":"description","doc":"Description of the time series.","required":false,"dtype":"text","default_value":"no description"},{"name":"comments","doc":"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.","required":false,"dtype":"text","default_value":"no comments"}]},{"datasets":[{"shape":[null],"dims":["num_features"],"dtype":"text","name":"description","doc":"Description of features (eg, ''PC1'') for each of the extracted features."},{"shape":[null,null,null],"dims":["num_events","num_channels","num_features"],"dtype":"float32","name":"features","doc":"Multi-dimensional array of features extracted from each event."},{"shape":[null],"dims":["num_events"],"dtype":"float64","name":"times","doc":"Times of events that features correspond to (can be a link)."},{"name":"electrodes","doc":"DynamicTableRegion pointer to the electrodes that this time series was generated from.","neurodata_type_inc":"DynamicTableRegion"}],"doc":"Features, such as PC1 and PC2, that are extracted from signals stored in a SpikeEventSeries or other source.","default_name":"FeatureExtraction","neurodata_type_inc":"NWBDataInterface","neurodata_type_def":"FeatureExtraction"},{"datasets":[{"dtype":"text","name":"detection_method","doc":"Description of how events were detected, such as voltage threshold, or dV/dT threshold, as well as relevant values."},{"shape":[null],"dims":["num_events"],"dtype":"int32","name":"source_idx","doc":"Indices (zero-based) into source ElectricalSeries::data array corresponding to time of event. ''description'' should define what is meant by time of event (e.g., .25 ms before action potential peak, zero-crossing time, etc). The index points to each event from the raw data."},{"shape":[null],"dims":["num_events"],"dtype":"float64","name":"times","doc":"Timestamps of events, in seconds.","attributes":[{"name":"unit","doc":"Unit of measurement for event times, which is fixed to 'seconds'.","dtype":"text","value":"seconds"}]}],"links":[{"name":"source_electricalseries","doc":"Link to the ElectricalSeries that this data was calculated from. Metadata about electrodes and their position can be read from that ElectricalSeries so it's not necessary to include that information here.","target_type":"ElectricalSeries"}],"doc":"Detected spike events from voltage trace(s).","default_name":"EventDetection","neurodata_type_inc":"NWBDataInterface","neurodata_type_def":"EventDetection"},{"groups":[{"doc":"SpikeEventSeries object(s) containing detected spike event waveforms.","quantity":"*","neurodata_type_inc":"SpikeEventSeries"}],"doc":"Represents either the waveforms of detected events, as extracted from a raw data trace in /acquisition, or the event waveforms that were stored during experiment acquisition.","default_name":"EventWaveform","neurodata_type_inc":"NWBDataInterface","neurodata_type_def":"EventWaveform"},{"groups":[{"doc":"ElectricalSeries object(s) containing filtered electrophysiology data.","quantity":"+","neurodata_type_inc":"ElectricalSeries"}],"doc":"Electrophysiology data from one or more channels that has been subjected to filtering. Examples of filtered data include Theta and Gamma (LFP has its own interface). FilteredEphys modules publish an ElectricalSeries for each filtered channel or set of channels. The name of each ElectricalSeries is arbitrary but should be informative. The source of the filtered data, whether this is from analysis of another time series or as acquired by hardware, should be noted in each's TimeSeries::description field. There is no assumed 1::1 correspondence between filtered ephys signals and electrodes, as a single signal can apply to many nearby electrodes, and one electrode may have different filtered (e.g., theta and/or gamma) signals represented. Filter properties should be noted in the ElectricalSeries.","default_name":"FilteredEphys","neurodata_type_inc":"NWBDataInterface","neurodata_type_def":"FilteredEphys"},{"groups":[{"doc":"ElectricalSeries object(s) containing LFP data for one or more channels.","quantity":"+","neurodata_type_inc":"ElectricalSeries"}],"doc":"LFP data from one or more channels. The electrode map in each published ElectricalSeries will identify which channels are providing LFP data. Filter properties should be noted in the ElectricalSeries description or comments field.","default_name":"LFP","neurodata_type_inc":"NWBDataInterface","neurodata_type_def":"LFP"},{"links":[{"name":"device","doc":"Link to the device that was used to record from this electrode group.","target_type":"Device"}],"doc":"A physical grouping of electrodes, e.g. a shank of an array.","neurodata_type_inc":"NWBContainer","neurodata_type_def":"ElectrodeGroup","attributes":[{"name":"description","doc":"Description of this electrode group.","dtype":"text"},{"name":"location","doc":"Location of electrode group. Specify the area, layer, comments on estimation of area/layer, stereotaxic coordinates if in vivo, etc. Use standard atlas names for anatomical regions when possible.","dtype":"text"}]},{"datasets":[{"dtype":"text","name":"waveform_filtering","doc":"Filtering applied to data before generating mean/sd"},{"shape":[null,null],"dims":["num_clusters","num_samples"],"dtype":"float32","name":"waveform_mean","doc":"The mean waveform for each cluster, using the same indices for each wave as cluster numbers in the associated Clustering module (i.e, cluster 3 is in array slot [3]). Waveforms corresponding to gaps in cluster sequence should be empty (e.g., zero- filled)"},{"shape":[null,null],"dims":["num_clusters","num_samples"],"dtype":"float32","name":"waveform_sd","doc":"Stdev of waveforms for each cluster, using the same indices as in mean"}],"links":[{"name":"clustering_interface","doc":"Link to Clustering interface that was the source of the clustered data","target_type":"Clustering"}],"doc":"DEPRECATED The mean waveform shape, including standard deviation, of the different clusters. Ideally, the waveform analysis should be performed on data that is only high-pass filtered. This is a separate module because it is expected to require updating. For example, IMEC probes may require different storage requirements to store/display mean waveforms, requiring a new interface or an extension of this one.","default_name":"ClusterWaveforms","neurodata_type_inc":"NWBDataInterface","neurodata_type_def":"ClusterWaveforms"},{"datasets":[{"dtype":"text","name":"description","doc":"Description of clusters or clustering, (e.g. cluster 0 is noise, clusters curated using Klusters, etc)"},{"shape":[null],"dims":["num_events"],"dtype":"int32","name":"num","doc":"Cluster number of each event"},{"shape":[null],"dims":["num_clusters"],"dtype":"float32","name":"peak_over_rms","doc":"Maximum ratio of waveform peak to RMS on any channel in the cluster (provides a basic clustering metric)."},{"shape":[null],"dims":["num_events"],"dtype":"float64","name":"times","doc":"Times of clustered events, in seconds. This may be a link to times field in associated FeatureExtraction module."}],"doc":"DEPRECATED Clustered spike data, whether from automatic clustering tools (e.g., klustakwik) or as a result of manual sorting.","default_name":"Clustering","neurodata_type_inc":"NWBDataInterface","neurodata_type_def":"Clustering"}]}B{"groups":[{"datasets":[{"shape":[null],"dims":["num_times"],"dtype":"numeric","name":"data","doc":"Recorded voltage or current.","attributes":[{"name":"unit","doc":"Base unit of measurement for working with the data. Actual stored values are not necessarily stored in these units. To access the data in these units, multiply 'data' by 'conversion'.","dtype":"text"},{"name":"conversion","doc":"Scalar to multiply each element in data to convert it to the specified 'unit'. If the data are stored in acquisition system units or other units that require a conversion to be interpretable, multiply the data by 'conversion' to convert the data to the specified 'unit'. e.g. if the data acquisition system stores values in this object as signed 16-bit integers (int16 range -32,768 to 32,767) that correspond to a 5V range (-2.5V to 2.5V), and the data acquisition system gain is 8000X, then the 'conversion' multiplier to get from raw data acquisition values to recorded volts is 2.5/32768/8000 = 9.5367e-9.","required":false,"dtype":"float32","default_value":1.0},{"name":"resolution","doc":"Smallest meaningful difference between values in data, stored in the specified by unit, 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 -1.0.","required":false,"dtype":"float32","default_value":-1.0}]},{"dtype":"float","name":"gain","doc":"Gain of the recording, in units Volt/Amp (v-clamp) or Volt/Volt (c-clamp).","quantity":"?"}],"links":[{"name":"electrode","doc":"Link to IntracellularElectrode object that describes the electrode that was used to apply or record this data.","target_type":"IntracellularElectrode"}],"doc":"An abstract base class for patch-clamp data - stimulus or response, current or voltage.","neurodata_type_inc":"TimeSeries","neurodata_type_def":"PatchClampSeries","attributes":[{"name":"stimulus_description","doc":"Protocol/stimulus name for this patch-clamp dataset.","dtype":"text"},{"name":"sweep_number","doc":"Sweep number, allows to group different PatchClampSeries together.","required":false,"dtype":"uint64"},{"name":"description","doc":"Description of the time series.","required":false,"dtype":"text","default_value":"no description"},{"name":"comments","doc":"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.","required":false,"dtype":"text","default_value":"no comments"}]},{"datasets":[{"name":"data","doc":"Recorded voltage.","attributes":[{"name":"unit","doc":"Base unit of measurement for working with the data. which is fixed to 'volts'. Actual stored values are not necessarily stored in these units. To access the data in these units, multiply 'data' by 'conversion'.","dtype":"text","value":"volts"},{"name":"conversion","doc":"Scalar to multiply each element in data to convert it to the specified 'unit'. If the data are stored in acquisition system units or other units that require a conversion to be interpretable, multiply the data by 'conversion' to convert the data to the specified 'unit'. e.g. if the data acquisition system stores values in this object as signed 16-bit integers (int16 range -32,768 to 32,767) that correspond to a 5V range (-2.5V to 2.5V), and the data acquisition system gain is 8000X, then the 'conversion' multiplier to get from raw data acquisition values to recorded volts is 2.5/32768/8000 = 9.5367e-9.","required":false,"dtype":"float32","default_value":1.0},{"name":"resolution","doc":"Smallest meaningful difference between values in data, stored in the specified by unit, 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 -1.0.","required":false,"dtype":"float32","default_value":-1.0}]},{"dtype":"float32","name":"bias_current","doc":"Bias current, in amps.","quantity":"?"},{"dtype":"float32","name":"bridge_balance","doc":"Bridge balance, in ohms.","quantity":"?"},{"dtype":"float32","name":"capacitance_compensation","doc":"Capacitance compensation, in farads.","quantity":"?"}],"doc":"Voltage data from an intracellular current-clamp recording. A corresponding CurrentClampStimulusSeries (stored separately as a stimulus) is used to store the current injected.","neurodata_type_inc":"PatchClampSeries","neurodata_type_def":"CurrentClampSeries","attributes":[{"name":"stimulus_description","doc":"Protocol/stimulus name for this patch-clamp dataset.","dtype":"text"},{"name":"sweep_number","doc":"Sweep number, allows to group different PatchClampSeries together.","required":false,"dtype":"uint64"},{"name":"description","doc":"Description of the time series.","required":false,"dtype":"text","default_value":"no description"},{"name":"comments","doc":"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.","required":false,"dtype":"text","default_value":"no comments"}]},{"datasets":[{"dtype":"float32","name":"bias_current","doc":"Bias current, in amps, fixed to 0.0."},{"dtype":"float32","name":"bridge_balance","doc":"Bridge balance, in ohms, fixed to 0.0."},{"dtype":"float32","name":"capacitance_compensation","doc":"Capacitance compensation, in farads, fixed to 0.0."}],"doc":"Voltage data from an intracellular recording when all current and amplifier settings are off (i.e., CurrentClampSeries fields will be zero). There is no CurrentClampStimulusSeries associated with an IZero series because the amplifier is disconnected and no stimulus can reach the cell.","neurodata_type_inc":"CurrentClampSeries","neurodata_type_def":"IZeroClampSeries","attributes":[{"name":"stimulus_description","doc":"Protocol/stimulus name for this patch-clamp dataset.","dtype":"text"},{"name":"sweep_number","doc":"Sweep number, allows to group different PatchClampSeries together.","required":false,"dtype":"uint64"},{"name":"description","doc":"Description of the time series.","required":false,"dtype":"text","default_value":"no description"},{"name":"comments","doc":"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.","required":false,"dtype":"text","default_value":"no comments"}]},{"datasets":[{"name":"data","doc":"Stimulus current applied.","attributes":[{"name":"unit","doc":"Base unit of measurement for working with the data. which is fixed to 'amperes'. Actual stored values are not necessarily stored in these units. To access the data in these units, multiply 'data' by 'conversion'.","dtype":"text","value":"amperes"},{"name":"conversion","doc":"Scalar to multiply each element in data to convert it to the specified 'unit'. If the data are stored in acquisition system units or other units that require a conversion to be interpretable, multiply the data by 'conversion' to convert the data to the specified 'unit'. e.g. if the data acquisition system stores values in this object as signed 16-bit integers (int16 range -32,768 to 32,767) that correspond to a 5V range (-2.5V to 2.5V), and the data acquisition system gain is 8000X, then the 'conversion' multiplier to get from raw data acquisition values to recorded volts is 2.5/32768/8000 = 9.5367e-9.","required":false,"dtype":"float32","default_value":1.0},{"name":"resolution","doc":"Smallest meaningful difference between values in data, stored in the specified by unit, 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 -1.0.","required":false,"dtype":"float32","default_value":-1.0}]}],"doc":"Stimulus current applied during current clamp recording.","neurodata_type_inc":"PatchClampSeries","neurodata_type_def":"CurrentClampStimulusSeries","attributes":[{"name":"stimulus_description","doc":"Protocol/stimulus name for this patch-clamp dataset.","dtype":"text"},{"name":"sweep_number","doc":"Sweep number, allows to group different PatchClampSeries together.","required":false,"dtype":"uint64"},{"name":"description","doc":"Description of the time series.","required":false,"dtype":"text","default_value":"no description"},{"name":"comments","doc":"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.","required":false,"dtype":"text","default_value":"no comments"}]},{"datasets":[{"name":"data","doc":"Recorded current.","attributes":[{"name":"unit","doc":"Base unit of measurement for working with the data. which is fixed to 'amperes'. Actual stored values are not necessarily stored in these units. To access the data in these units, multiply 'data' by 'conversion'.","dtype":"text","value":"amperes"},{"name":"conversion","doc":"Scalar to multiply each element in data to convert it to the specified 'unit'. If the data are stored in acquisition system units or other units that require a conversion to be interpretable, multiply the data by 'conversion' to convert the data to the specified 'unit'. e.g. if the data acquisition system stores values in this object as signed 16-bit integers (int16 range -32,768 to 32,767) that correspond to a 5V range (-2.5V to 2.5V), and the data acquisition system gain is 8000X, then the 'conversion' multiplier to get from raw data acquisition values to recorded volts is 2.5/32768/8000 = 9.5367e-9.","required":false,"dtype":"float32","default_value":1.0},{"name":"resolution","doc":"Smallest meaningful difference between values in data, stored in the specified by unit, 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 -1.0.","required":false,"dtype":"float32","default_value":-1.0}]},{"dtype":"float32","name":"capacitance_fast","doc":"Fast capacitance, in farads.","quantity":"?","attributes":[{"name":"unit","doc":"Unit of measurement for capacitance_fast, which is fixed to 'farads'.","dtype":"text","value":"farads"}]},{"dtype":"float32","name":"capacitance_slow","doc":"Slow capacitance, in farads.","quantity":"?","attributes":[{"name":"unit","doc":"Unit of measurement for capacitance_fast, which is fixed to 'farads'.","dtype":"text","value":"farads"}]},{"dtype":"float32","name":"resistance_comp_bandwidth","doc":"Resistance compensation bandwidth, in hertz.","quantity":"?","attributes":[{"name":"unit","doc":"Unit of measurement for resistance_comp_bandwidth, which is fixed to 'hertz'.","dtype":"text","value":"hertz"}]},{"dtype":"float32","name":"resistance_comp_correction","doc":"Resistance compensation correction, in percent.","quantity":"?","attributes":[{"name":"unit","doc":"Unit of measurement for resistance_comp_correction, which is fixed to 'percent'.","dtype":"text","value":"percent"}]},{"dtype":"float32","name":"resistance_comp_prediction","doc":"Resistance compensation prediction, in percent.","quantity":"?","attributes":[{"name":"unit","doc":"Unit of measurement for resistance_comp_prediction, which is fixed to 'percent'.","dtype":"text","value":"percent"}]},{"dtype":"float32","name":"whole_cell_capacitance_comp","doc":"Whole cell capacitance compensation, in farads.","quantity":"?","attributes":[{"name":"unit","doc":"Unit of measurement for whole_cell_capacitance_comp, which is fixed to 'farads'.","dtype":"text","value":"farads"}]},{"dtype":"float32","name":"whole_cell_series_resistance_comp","doc":"Whole cell series resistance compensation, in ohms.","quantity":"?","attributes":[{"name":"unit","doc":"Unit of measurement for whole_cell_series_resistance_comp, which is fixed to 'ohms'.","dtype":"text","value":"ohms"}]}],"doc":"Current data from an intracellular voltage-clamp recording. A corresponding VoltageClampStimulusSeries (stored separately as a stimulus) is used to store the voltage injected.","neurodata_type_inc":"PatchClampSeries","neurodata_type_def":"VoltageClampSeries","attributes":[{"name":"stimulus_description","doc":"Protocol/stimulus name for this patch-clamp dataset.","dtype":"text"},{"name":"sweep_number","doc":"Sweep number, allows to group different PatchClampSeries together.","required":false,"dtype":"uint64"},{"name":"description","doc":"Description of the time series.","required":false,"dtype":"text","default_value":"no description"},{"name":"comments","doc":"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.","required":false,"dtype":"text","default_value":"no comments"}]},{"datasets":[{"name":"data","doc":"Stimulus voltage applied.","attributes":[{"name":"unit","doc":"Base unit of measurement for working with the data. which is fixed to 'volts'. Actual stored values are not necessarily stored in these units. To access the data in these units, multiply 'data' by 'conversion'.","dtype":"text","value":"volts"},{"name":"conversion","doc":"Scalar to multiply each element in data to convert it to the specified 'unit'. If the data are stored in acquisition system units or other units that require a conversion to be interpretable, multiply the data by 'conversion' to convert the data to the specified 'unit'. e.g. if the data acquisition system stores values in this object as signed 16-bit integers (int16 range -32,768 to 32,767) that correspond to a 5V range (-2.5V to 2.5V), and the data acquisition system gain is 8000X, then the 'conversion' multiplier to get from raw data acquisition values to recorded volts is 2.5/32768/8000 = 9.5367e-9.","required":false,"dtype":"float32","default_value":1.0},{"name":"resolution","doc":"Smallest meaningful difference between values in data, stored in the specified by unit, 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 -1.0.","required":false,"dtype":"float32","default_value":-1.0}]}],"doc":"Stimulus voltage applied during a voltage clamp recording.","neurodata_type_inc":"PatchClampSeries","neurodata_type_def":"VoltageClampStimulusSeries","attributes":[{"name":"stimulus_description","doc":"Protocol/stimulus name for this patch-clamp dataset.","dtype":"text"},{"name":"sweep_number","doc":"Sweep number, allows to group different PatchClampSeries together.","required":false,"dtype":"uint64"},{"name":"description","doc":"Description of the time series.","required":false,"dtype":"text","default_value":"no description"},{"name":"comments","doc":"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.","required":false,"dtype":"text","default_value":"no comments"}]},{"datasets":[{"dtype":"text","name":"description","doc":"Description of electrode (e.g., whole-cell, sharp, etc.)."},{"dtype":"text","name":"filtering","doc":"Electrode specific filtering.","quantity":"?"},{"dtype":"text","name":"initial_access_resistance","doc":"Initial access resistance.","quantity":"?"},{"dtype":"text","name":"location","doc":"Location of the electrode. Specify the area, layer, comments on estimation of area/layer, stereotaxic coordinates if in vivo, etc. Use standard atlas names for anatomical regions when possible.","quantity":"?"},{"dtype":"text","name":"resistance","doc":"Electrode resistance, in ohms.","quantity":"?"},{"dtype":"text","name":"seal","doc":"Information about seal used for recording.","quantity":"?"},{"dtype":"text","name":"slice","doc":"Information about slice used for recording.","quantity":"?"}],"links":[{"name":"device","doc":"Device that was used to record from this electrode.","target_type":"Device"}],"doc":"An intracellular electrode and its metadata.","neurodata_type_inc":"NWBContainer","neurodata_type_def":"IntracellularElectrode"},{"datasets":[{"dtype":"uint64","name":"sweep_number","doc":"Sweep number of the PatchClampSeries in that row.","neurodata_type_inc":"VectorData"},{"dtype":{"target_type":"PatchClampSeries","reftype":"object"},"name":"series","doc":"The PatchClampSeries with the sweep number in that row.","neurodata_type_inc":"VectorData"},{"name":"series_index","doc":"Index for series.","neurodata_type_inc":"VectorIndex"}],"doc":"The table which groups different PatchClampSeries together.","neurodata_type_inc":"DynamicTable","neurodata_type_def":"SweepTable","attributes":[{"name":"colnames","doc":"The names of the columns in this table. This should be used to specify an order to the columns.","dtype":"ascii","shape":[null],"dims":["num_columns"]},{"name":"description","doc":"Description of what is in this dynamic table.","dtype":"text"}]}]},{"groups":[{"datasets":[{"shape":[[2],[3]],"dims":["width|height","width|height|depth"],"dtype":"float32","name":"field_of_view","doc":"Width, height and depth of image, or imaged area, in meters.","quantity":"?"}],"links":[{"name":"imaging_plane","doc":"Link to ImagingPlane object from which this TimeSeries data was generated.","target_type":"ImagingPlane"}],"doc":"Image stack recorded over time from 2-photon microscope.","neurodata_type_inc":"ImageSeries","neurodata_type_def":"TwoPhotonSeries","attributes":[{"name":"pmt_gain","doc":"Photomultiplier gain.","required":false,"dtype":"float32"},{"name":"scan_line_rate","doc":"Lines imaged per second. This is also stored in /general/optophysiology but is kept here as it is useful information for analysis, and so good to be stored w/ the actual data.","required":false,"dtype":"float32"},{"name":"description","doc":"Description of the time series.","required":false,"dtype":"text","default_value":"no description"},{"name":"comments","doc":"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.","required":false,"dtype":"text","default_value":"no comments"}]},{"datasets":[{"shape":[[null],[null,null]],"dims":[["num_times"],["num_times","num_ROIs"]],"dtype":"numeric","name":"data","doc":"Signals from ROIs.","attributes":[{"name":"conversion","doc":"Scalar to multiply each element in data to convert it to the specified 'unit'. If the data are stored in acquisition system units or other units that require a conversion to be interpretable, multiply the data by 'conversion' to convert the data to the specified 'unit'. e.g. if the data acquisition system stores values in this object as signed 16-bit integers (int16 range -32,768 to 32,767) that correspond to a 5V range (-2.5V to 2.5V), and the data acquisition system gain is 8000X, then the 'conversion' multiplier to get from raw data acquisition values to recorded volts is 2.5/32768/8000 = 9.5367e-9.","required":false,"dtype":"float32","default_value":1.0},{"name":"resolution","doc":"Smallest meaningful difference between values in data, stored in the specified by unit, 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 -1.0.","required":false,"dtype":"float32","default_value":-1.0},{"name":"unit","doc":"Base unit of measurement for working with the data. Actual stored values are not necessarily stored in these units. To access the data in these units, multiply 'data' by 'conversion'.","dtype":"text"}]},{"name":"rois","doc":"DynamicTableRegion referencing into an ROITable containing information on the ROIs stored in this timeseries.","neurodata_type_inc":"DynamicTableRegion"}],"doc":"ROI responses over an imaging plane. Each row in data should correspond to the signal from one ROI. Each element on the second dimension of data should correspond to the signal from one ROI.","neurodata_type_inc":"TimeSeries","neurodata_type_def":"RoiResponseSeries","attributes":[{"name":"description","doc":"Description of the time series.","required":false,"dtype":"text","default_value":"no description"},{"name":"comments","doc":"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.","required":false,"dtype":"text","default_value":"no comments"}]},{"groups":[{"doc":"RoiResponseSeries object(s) containing dF/F for a ROI.","quantity":"+","neurodata_type_inc":"RoiResponseSeries"}],"doc":"dF/F information about a region of interest (ROI). Storage hierarchy of dF/F should be the same as for segmentation (i.e., same names for ROIs and for image planes).","default_name":"DfOverF","neurodata_type_inc":"NWBDataInterface","neurodata_type_def":"DfOverF"},{"groups":[{"doc":"RoiResponseSeries object(s) containing fluorescence data for a ROI.","quantity":"+","neurodata_type_inc":"RoiResponseSeries"}],"doc":"Fluorescence information about a region of interest (ROI). Storage hierarchy of fluorescence should be the same as for segmentation (ie, same names for ROIs and for image planes).","default_name":"Fluorescence","neurodata_type_inc":"NWBDataInterface","neurodata_type_def":"Fluorescence"},{"groups":[{"groups":[{"groups":[{"doc":"One or more image stacks that the masks apply to (can be one-element stack).","quantity":"*","neurodata_type_inc":"ImageSeries"}],"name":"reference_images","doc":"Image stacks that the segmentation masks apply to."}],"datasets":[{"shape":[[null,null,null],[null,null,null,null]],"dims":[["num_roi","num_x","num_y"],["num_roi","num_x","num_y","num_z"]],"name":"image_mask","doc":"ROI masks for each ROI. Each image mask is the size of the original imaging plane (or volume) and members of the ROI are finite non-zero.","quantity":"?","neurodata_type_inc":"VectorData"},{"name":"pixel_mask_index","doc":"Index into pixel_mask.","quantity":"?","neurodata_type_inc":"VectorIndex"},{"dtype":[{"doc":"Pixel x-coordinate.","name":"x","dtype":"uint"},{"doc":"Pixel y-coordinate.","name":"y","dtype":"uint"},{"doc":"Weight of the pixel.","name":"weight","dtype":"float"}],"name":"pixel_mask","doc":"Pixel masks for each ROI: a list of indices and weights for the ROI. Pixel masks are concatenated and parsing of this dataset is maintained by the PlaneSegmentation","quantity":"?","neurodata_type_inc":"VectorData"},{"name":"voxel_mask_index","doc":"Index into voxel_mask.","quantity":"?","neurodata_type_inc":"VectorIndex"},{"dtype":[{"doc":"Voxel x-coordinate.","name":"x","dtype":"uint"},{"doc":"Voxel y-coordinate.","name":"y","dtype":"uint"},{"doc":"Voxel z-coordinate.","name":"z","dtype":"uint"},{"doc":"Weight of the voxel.","name":"weight","dtype":"float"}],"name":"voxel_mask","doc":"Voxel masks for each ROI: a list of indices and weights for the ROI. Voxel masks are concatenated and parsing of this dataset is maintained by the PlaneSegmentation","quantity":"?","neurodata_type_inc":"VectorData"},{"shape":[null],"dims":["num_rows"],"dtype":"int","name":"id","doc":"Array of unique identifiers for the rows of this dynamic table.","neurodata_type_inc":"ElementIdentifiers"},{"doc":"Vector columns of this dynamic table.","quantity":"*","neurodata_type_inc":"VectorData"},{"doc":"Indices for the vector columns of this dynamic table.","quantity":"*","neurodata_type_inc":"VectorIndex"}],"links":[{"name":"imaging_plane","doc":"Link to ImagingPlane object from which this data was generated.","target_type":"ImagingPlane"}],"doc":"Results from image segmentation of a specific imaging plane.","quantity":"+","neurodata_type_inc":"DynamicTable","neurodata_type_def":"PlaneSegmentation","attributes":[{"name":"colnames","doc":"The names of the columns in this table. This should be used to specify an order to the columns.","dtype":"ascii","shape":[null],"dims":["num_columns"]},{"name":"description","doc":"Description of what is in this dynamic table.","dtype":"text"}]}],"doc":"Stores pixels in an image that represent different regions of interest (ROIs) or masks. All segmentation for a given imaging plane is stored together, with storage for multiple imaging planes (masks) supported. Each ROI is stored in its own subgroup, with the ROI group containing both a 2D mask and a list of pixels that make up this mask. Segments can also be used for masking neuropil. If segmentation is allowed to change with time, a new imaging plane (or module) is required and ROI names should remain consistent between them.","default_name":"ImageSegmentation","neurodata_type_inc":"NWBDataInterface","neurodata_type_def":"ImageSegmentation"},{"groups":[{"datasets":[{"dtype":"text","name":"description","doc":"Description or other notes about the channel."},{"dtype":"float","name":"emission_lambda","doc":"Emission wavelength for channel, in nm."}],"doc":"An optical channel used to record from an imaging plane.","neurodata_type_inc":"NWBContainer","neurodata_type_def":"OpticalChannel"}],"datasets":[{"dtype":"text","name":"description","doc":"Description of the imaging plane.","quantity":"?"},{"dtype":"float","name":"excitation_lambda","doc":"Excitation wavelength, in nm."},{"dtype":"float","name":"imaging_rate","doc":"Rate that images are acquired, in Hz."},{"dtype":"text","name":"indicator","doc":"Calcium indicator."},{"dtype":"text","name":"location","doc":"Location of the imaging plane. Specify the area, layer, comments on estimation of area/layer, stereotaxic coordinates if in vivo, etc. Use standard atlas names for anatomical regions when possible."},{"shape":[[null,null,3],[null,null,null,3]],"dims":[["height","width","x|y|z"],["height","width","depth","x|y|z"]],"dtype":"float32","name":"manifold","doc":"Physical position of each pixel. 'xyz' represents the position of the pixel relative to the defined coordinate space.","quantity":"?","attributes":[{"name":"conversion","doc":"Scalar to multiply each element in data to convert it to the specified 'unit'. If the data are stored in acquisition system units or other units that require a conversion to be interpretable, multiply the data by 'conversion' to convert the data to the specified 'unit'. e.g. if the data acquisition system stores values in this object as pixels from x = -500 to 499, y = -500 to 499 that correspond to a 2 m x 2 m range, then the 'conversion' multiplier to get from raw data acquisition pixel units to meters is 2/1000.","required":false,"dtype":"float","default_value":1.0},{"name":"unit","doc":"Base unit of measurement for working with the data. The default value is 'meters'.","required":false,"dtype":"text","default_value":"meters"}]},{"dtype":"text","name":"reference_frame","doc":"Describes position and reference frame of manifold based on position of first element in manifold. For example, text description of anatomical location or vectors needed to rotate to common anatomical axis (eg, AP/DV/ML). This field is necessary to interpret manifold. If manifold is not present then this field is not required.","quantity":"?"}],"links":[{"name":"device","doc":"Link to the Device object that was used to record from this electrode.","target_type":"Device"}],"doc":"An imaging plane and its metadata.","quantity":"*","neurodata_type_inc":"NWBContainer","neurodata_type_def":"ImagingPlane"},{"groups":[{"groups":[{"name":"corrected","doc":"Image stack with frames shifted to the common coordinates.","neurodata_type_inc":"ImageSeries"},{"name":"xy_translation","doc":"Stores the x,y delta necessary to align each frame to the common coordinates, for example, to align each frame to a reference image.","neurodata_type_inc":"TimeSeries"}],"links":[{"name":"original","doc":"Link to ImageSeries object that is being registered.","target_type":"ImageSeries"}],"doc":"Reuslts from motion correction of an image stack.","quantity":"+","neurodata_type_inc":"NWBDataInterface","neurodata_type_def":"CorrectedImageStack"}],"doc":"An image stack where all frames are shifted (registered) to a common coordinate system, to account for movement and drift between frames. Note: each frame at each point in time is assumed to be 2-D (has only x & y dimensions).","default_name":"MotionCorrection","neurodata_type_inc":"NWBDataInterface","neurodata_type_def":"MotionCorrection"}]}{"groups":[{"datasets":[{"shape":[null,null],"dims":["num_rows","num_cols"],"dtype":"float32","name":"axis_1_phase_map","doc":"Phase response to stimulus on the first measured axis.","attributes":[{"name":"dimension","doc":"Number of rows and columns in the image. NOTE: row, column representation is equivalent to height,width.","dtype":"int32","shape":[null],"dims":["row_col"]},{"name":"field_of_view","doc":"Size of viewing area, in meters.","dtype":"float","shape":[null],"dims":["row|column"]},{"name":"unit","doc":"Unit that axis data is stored in (e.g., degrees).","dtype":"text"}]},{"shape":[null,null],"dims":["num_rows","num_cols"],"dtype":"float32","name":"axis_1_power_map","doc":"Power response on the first measured axis. Response is scaled so 0.0 is no power in the response and 1.0 is maximum relative power.","quantity":"?","attributes":[{"name":"dimension","doc":"Number of rows and columns in the image. NOTE: row, column representation is equivalent to height,width.","dtype":"int32","shape":[null],"dims":["row_col"]},{"name":"field_of_view","doc":"Size of viewing area, in meters.","dtype":"float","shape":[null],"dims":["row_col"]},{"name":"unit","doc":"Unit that axis data is stored in (e.g., degrees).","dtype":"text"}]},{"shape":[null,null],"dims":["num_rows","num_cols"],"dtype":"float32","name":"axis_2_phase_map","doc":"Phase response to stimulus on the second measured axis.","attributes":[{"name":"dimension","doc":"Number of rows and columns in the image. NOTE: row, column representation is equivalent to height,width.","dtype":"int32","shape":[null],"dims":["row_col"]},{"name":"field_of_view","doc":"Size of viewing area, in meters.","dtype":"float","shape":[null],"dims":["row_col"]},{"name":"unit","doc":"Unit that axis data is stored in (e.g., degrees).","dtype":"text"}]},{"shape":[null,null],"dims":["num_rows","num_cols"],"dtype":"float32","name":"axis_2_power_map","doc":"Power response on the second measured axis. Response is scaled so 0.0 is no power in the response and 1.0 is maximum relative power.","quantity":"?","attributes":[{"name":"dimension","doc":"Number of rows and columns in the image. NOTE: row, column representation is equivalent to height,width.","dtype":"int32","shape":[null],"dims":["row_col"]},{"name":"field_of_view","doc":"Size of viewing area, in meters.","dtype":"float","shape":[null],"dims":["row_col"]},{"name":"unit","doc":"Unit that axis data is stored in (e.g., degrees).","dtype":"text"}]},{"shape":[2],"dims":["names"],"dtype":"text","name":"axis_descriptions","doc":"Two-element array describing the contents of the two response axis fields. Description should be something like ['altitude', 'azimuth'] or '['radius', 'theta']."},{"shape":[null,null],"dims":["num_rows","num_cols"],"dtype":"uint16","name":"focal_depth_image","doc":"Gray-scale image taken with same settings/parameters (e.g., focal depth, wavelength) as data collection. Array format: [rows][columns].","attributes":[{"name":"bits_per_pixel","doc":"Number of bits used to represent each value. This is necessary to determine maximum (white) pixel value.","dtype":"int32"},{"name":"dimension","doc":"Number of rows and columns in the image. NOTE: row, column representation is equivalent to height,width.","dtype":"int32","shape":[null],"dims":["row_col"]},{"name":"field_of_view","doc":"Size of viewing area, in meters.","dtype":"float","shape":[null],"dims":["row_col"]},{"name":"focal_depth","doc":"Focal depth offset, in meters.","dtype":"float"},{"name":"format","doc":"Format of image. Right now only 'raw' is supported.","dtype":"text"}]},{"shape":[null,null],"dims":["num_rows","num_cols"],"dtype":"float32","name":"sign_map","doc":"Sine of the angle between the direction of the gradient in axis_1 and axis_2.","attributes":[{"name":"dimension","doc":"Number of rows and columns in the image. NOTE: row, column representation is equivalent to height,width.","dtype":"int32","shape":[null],"dims":["row_col"]},{"name":"field_of_view","doc":"Size of viewing area, in meters.","dtype":"float","shape":[null],"dims":["row_col"]}]},{"shape":[null,null],"dims":["num_rows","num_cols"],"dtype":"uint16","name":"vasculature_image","doc":"Gray-scale anatomical image of cortical surface. Array structure: [rows][columns]","attributes":[{"name":"bits_per_pixel","doc":"Number of bits used to represent each value. This is necessary to determine maximum (white) pixel value","dtype":"int32"},{"name":"dimension","doc":"Number of rows and columns in the image. NOTE: row, column representation is equivalent to height,width.","dtype":"int32","shape":[null],"dims":["row_col"]},{"name":"field_of_view","doc":"Size of viewing area, in meters.","dtype":"float","shape":[null],"dims":["row_col"]},{"name":"format","doc":"Format of image. Right now only 'raw' is supported.","dtype":"text"}]}],"doc":"Intrinsic signal optical imaging or widefield imaging for measuring retinotopy. Stores orthogonal maps (e.g., altitude/azimuth; radius/theta) of responses to specific stimuli and a combined polarity map from which to identify visual areas. Note: for data consistency, all images and arrays are stored in the format [row][column] and [row, col], which equates to [y][x]. Field of view and dimension arrays may appear backward (i.e., y before x).","default_name":"ImagingRetinotopy","neurodata_type_inc":"NWBDataInterface","neurodata_type_def":"ImagingRetinotopy"}]}U{"namespaces":[{"doc":"NWB namespace","schema":[{"source":"nwb.base"},{"source":"nwb.epoch"},{"source":"nwb.image"},{"source":"nwb.file"},{"source":"nwb.misc"},{"source":"nwb.behavior"},{"source":"nwb.ecephys"},{"source":"nwb.icephys"},{"source":"nwb.ogen"},{"source":"nwb.ophys"},{"source":"nwb.retinotopy"}],"name":"core","full_name":"NWB core","version":"2.1.0","author":["Andrew Tritt","Oliver Ruebel","Ryan Ly","Ben Dichter","Keith Godfrey","Jeff Teeters"],"contact":["ajtritt@lbl.gov","oruebel@lbl.gov","rly@lbl.gov","bdichter@lbl.gov","keithg@alleninstitute.org","jteeters@berkeley.edu"]}]}P/pynwb-1.2.1/tests/back_compat/1.1.2_str_pub.nwb0000644000655200065520000044262013612200244022554 0ustar circlecicircleci00000000000000HDF  E` TREEH1HEAP`H0 0 .speclocpHhTREEHEAPXPSNOD Hh(Pp P,H0XxPp TREEHEAPX P 0 TREEHEAPXP P TREE(HEAPX(presentationtemplates0TREEHEAPXPSNODhpTREEHEAPXPXxTREEHEAPX related_publications8 H nwb_version<=0?F'^xSNODGCOLone publication 2020-01-21T17:58:30.813577-08:00ADDMEADDME 2020-01-21T17:58:30.811582-08:00 2020-01-21T17:58:30.811582-08:002.1.0core NWBFile $643f1ae4-e31c-4349-a1ee-f3a09b7fd312 {"groups":[{"datasets":[{"shape":[null],"dtype":"int","name":"indices","doc":"column indices"},{"shape":[null],"dtype":"int","name":"indptr","doc":"index pointer"},{"shape":[null],"name":"data","doc":"values in the matrix"}],"doc":"a compressed sparse row matrix","data_type_def":"CSRMatrix","attributes":[{"name":"shape","doc":"the shape of this sparse matrix","dtype":"int","shape":[2]}]}]} H{"namespaces":[{"doc":"Common data structures provided by HDMF","schema":[{"source":"table"},{"source":"sparse"}],"name":"hdmf-common","full_name":"HDMF Common","version":"1.0.0","author":["Andrew Tritt","Oliver Ruebel","Ryan Ly","Ben Dichter"],"contact":["ajtritt@lbl.gov","oruebel@lbl.gov","rly@lbl.gov","bdichter@lbl.gov"]}]} G{"groups":[{"datasets":[{"dtype":"float","name":"start_time","doc":"Start time of epoch, in seconds.","neurodata_type_inc":"VectorData"},{"dtype":"float","name":"stop_time","doc":"Stop time of epoch, in seconds.","neurodata_type_inc":"VectorData"},{"dtype":"text","name":"tags","doc":"User-defined tags that identify or categorize events.","quantity":"?","neurodata_type_inc":"VectorData"},{"name":"tags_index","doc":"Index for tags.","quantity":"?","neurodata_type_inc":"VectorIndex"},{"dtype":[{"doc":"Start index into the TimeSeries 'data' and 'timestamp' datasets of the referenced TimeSeries. The first dimension of those arrays is always time.","name":"idx_start","dtype":"int32"},{"doc":"Number of data samples available in this time series, during this epoch.","name":"count","dtype":"int32"},{"doc":"the TimeSeries that this index applies to.","name":"timeseries","dtype":{"target_type":"TimeSeries","reftype":"object"}}],"name":"timeseries","doc":"An index into a TimeSeries object.","quantity":"?","neurodata_type_inc":"VectorData"},{"name":"timeseries_index","doc":"Index for timeseries.","quantity":"?","neurodata_type_inc":"VectorIndex"}],"doc":"A container for aggregating epoch data and the TimeSeries that each epoch applies to.","neurodata_type_inc":"DynamicTable","neurodata_type_def":"TimeIntervals","attributes":[{"name":"colnames","doc":"The names of the columns in this table. This should be used to specify an order to the columns.","dtype":"ascii","shape":[null],"dims":["num_columns"]},{"name":"description","doc":"Description of what is in this dynamic table.","dtype":"text"}]}]}H4F'^x4F'^(4F'^84F'^acquisitionanalysisprocessingstimulusgeneralfile_create_dateidentifiersession_descriptionsession_start_timetimestamps_reference_timespecificationsSNODh-(  0 x(.8/p=0?8  2H4F'^   H H dG y("<,1w4VBV~ ,VVqV H namespace Hneurodata_type H object_id$ PTREEhBHEAPX P?hdmf-commoncore8?ATREEpFHEAPXB1.0.0HSNOD\](_??ACETREExYHEAPX(Ftablesparsenamespace0SNODCCEX4F'^GCOL{"datasets":[{"doc":"An abstract data type for a dataset.","data_type_def":"Data"},{"doc":"Pointers that index data values.","data_type_inc":"Data","data_type_def":"Index","attributes":[{"name":"target","doc":"Target dataset that this index applies to.","dtype":{"target_type":"Data","reftype":"object"}}]},{"doc":"A 1-dimensional dataset. This can be indexed using a VectorIndex to encode a 2-dimensional ragged array in 1 dimension. The first vector is at VectorData[0:VectorIndex(0)+1]. The second vector is at VectorData[VectorIndex(0)+1:VectorIndex(1)+1]. And so on.","data_type_inc":"Data","data_type_def":"VectorData","attributes":[{"name":"description","doc":"Description of what these vectors represent.","dtype":"text"}]},{"doc":"An array of indices into the first dimension of the target VectorData. Can be used with VectorData to encode a 2-dimensional ragged array in 1 dimension.","data_type_inc":"Index","data_type_def":"VectorIndex","attributes":[{"name":"target","doc":"Reference to the target dataset that this index applies to.","dtype":{"target_type":"VectorData","reftype":"object"}}]},{"shape":[null],"dims":["num_elements"],"dtype":"int","doc":"A list of unique identifiers for values within a dataset, e.g. rows of a DynamicTable.","default_name":"element_id","data_type_inc":"Data","data_type_def":"ElementIdentifiers"},{"dtype":"int","doc":"A region/index into a DynamicTable.","data_type_inc":"VectorData","data_type_def":"DynamicTableRegion","attributes":[{"name":"table","doc":"Reference to the DynamicTable object that this region applies to.","dtype":{"target_type":"DynamicTable","reftype":"object"}},{"name":"description","doc":"Description of what this table region points to.","dtype":"text"}]}],"groups":[{"doc":"An abstract data type for a generic container storing collections of data and metadata. Base type for all data and metadata containers.","data_type_def":"Container"},{"datasets":[{"shape":[null],"dims":["num_rows"],"dtype":"int","name":"id","doc":"Array of unique identifiers for the rows of this dynamic table.","data_type_inc":"ElementIdentifiers"},{"doc":"Vector columns of this dynamic table.","quantity":"*","data_type_inc":"VectorData"},{"doc":"Indices for the vector columns of this dynamic table.","quantity":"*","data_type_inc":"VectorIndex"}],"doc":"A group containing multiple datasets that are aligned on the first dimension (Currently, this requirement if left up to APIs to check and enforce). Apart from a column that contains unique identifiers for each row there are no other required datasets. Users are free to add any number of VectorData objects here. Table functionality is already supported through compound types, which is analogous to storing an array-of-structs. DynamicTable can be thought of as a struct-of-arrays. This provides an alternative structure to choose from when optimizing storage for anticipated access patterns. Additionally, this type provides a way of creating a table without having to define a compound type up front. Although this convenience may be attractive, users should think carefully about how data will be accessed. DynamicTable is more appropriate for column-centric access, whereas a dataset with a compound type would be more appropriate for row-centric access. Finally, data size should also be taken into account. For small tables, performance loss may be an acceptable trade-off for the flexibility of a DynamicTable. For example, DynamicTable was originally developed for storing trial data and spike unit metadata. Both of these use cases are expected to produce relatively small tables, so the spatial locality of multiple datasets present in a DynamicTable is not expected to have a significant performance impact. Additionally, requirements of trial and unit metadata tables are sufficiently diverse that performance implications can be overlooked in favor of usability.","data_type_inc":"Container","data_type_def":"DynamicTable","attributes":[{"name":"colnames","doc":"The names of the columns in this table. This should be used to specify an order to the columns.","dtype":"ascii","shape":[null],"dims":["num_columns"]},{"name":"description","doc":"Description of what is in this dynamic table.","dtype":"text"}]}]}SNOD[ZGh4F'^x4F'^](_TREE`bHEAPXH_2.1.0H_aTREE|QHEAP`SNOD__a4H'^GCOL8{"datasets":[{"doc":"An abstract data type for a dataset.","neurodata_type_inc":"Data","neurodata_type_def":"NWBData"},{"shape":[[null,null],[null,null,3],[null,null,4]],"dims":[["num_x","num_y"],["num_x","num_y","(r, g, b)"],["num_x","num_y","(r, g, b, a)"]],"doc":"An abstract data type for an image. Shape can be 2-D (x, y), or 3-D where the third dimension can have three or four elements, e.g. (x, y, (r, g, b)) or (x, y, (r, g, b, a)).","neurodata_type_inc":"NWBData","neurodata_type_def":"Image","attributes":[{"name":"resolution","doc":"Pixel resolution of the image, in pixels per centimeter.","required":false,"dtype":"float"},{"name":"description","doc":"Description of the image.","required":false,"dtype":"text"}]}],"groups":[{"doc":"An abstract data type for a generic container storing collections of data and metadata. Base type for all data and metadata containers.","neurodata_type_inc":"Container","neurodata_type_def":"NWBContainer"},{"doc":"An abstract data type for a generic container storing collections of data, as opposed to metadata.","neurodata_type_inc":"NWBContainer","neurodata_type_def":"NWBDataInterface"},{"groups":[{"name":"sync","doc":"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. 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.","quantity":"?"}],"datasets":[{"shape":[[null],[null,null],[null,null,null],[null,null,null,null]],"dims":[["num_times"],["num_times","num_DIM2"],["num_times","num_DIM2","num_DIM3"],["num_times","num_DIM2","num_DIM3","num_DIM4"]],"name":"data","doc":"Data values. Data can be in 1-D, 2-D, 3-D, or 4-D. The first dimension should always represent time. This can also be used to store binary data (e.g., image frames). This can also be a link to data stored in an external file.","attributes":[{"name":"conversion","doc":"Scalar to multiply each element in data to convert it to the specified 'unit'. If the data are stored in acquisition system units or other units that require a conversion to be interpretable, multiply the data by 'conversion' to convert the data to the specified 'unit'. e.g. if the data acquisition system stores values in this object as signed 16-bit integers (int16 range -32,768 to 32,767) that correspond to a 5V range (-2.5V to 2.5V), and the data acquisition system gain is 8000X, then the 'conversion' multiplier to get from raw data acquisition values to recorded volts is 2.5/32768/8000 = 9.5367e-9.","required":false,"dtype":"float32","default_value":1.0},{"name":"resolution","doc":"Smallest meaningful difference between values in data, stored in the specified by unit, 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 -1.0.","required":false,"dtype":"float32","default_value":-1.0},{"name":"unit","doc":"Base unit of measurement for working with the data. Actual stored values are not necessarily stored in these units. To access the data in these units, multiply 'data' by 'conversion'.","dtype":"text"}]},{"dtype":"float64","name":"starting_time","doc":"Timestamp of the first sample in seconds. When timestamps are uniformly spaced, the timestamp of the first sample can be specified and all subsequent ones calculated from the sampling rate attribute.","quantity":"?","attributes":[{"name":"rate","doc":"Sampling rate, in Hz.","dtype":"float32"},{"name":"unit","doc":"Unit of measurement for time, which is fixed to 'seconds'.","dtype":"text","value":"seconds"}]},{"shape":[null],"dims":["num_times"],"dtype":"float64","name":"timestamps","doc":"Timestamps for samples stored in data, in seconds, relative to the common experiment master-clock stored in NWBFile.timestamps_reference_time.","quantity":"?","attributes":[{"name":"interval","doc":"Value is '1'","dtype":"int32","value":1},{"name":"unit","doc":"Unit of measurement for timestamps, which is fixed to 'seconds'.","dtype":"text","value":"seconds"}]},{"shape":[null],"dims":["num_times"],"dtype":"uint8","name":"control","doc":"Numerical labels that apply to each time point in data for the purpose of querying and slicing data by these values. If present, the length of this array should be the same size as the first dimension of data.","quantity":"?"},{"shape":[null],"dims":["num_control_values"],"dtype":"text","name":"control_description","doc":"Description of each control value. Must be present if control is present. If present, control_description[0] should describe time points where control == 0.","quantity":"?"}],"doc":"General purpose time series.","neurodata_type_inc":"NWBDataInterface","neurodata_type_def":"TimeSeries","attributes":[{"name":"description","doc":"Description of the time series.","required":false,"dtype":"text","default_value":"no description"},{"name":"comments","doc":"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.","required":false,"dtype":"text","default_value":"no comments"}]},{"groups":[{"doc":"Data objects stored in this collection.","quantity":"*","neurodata_type_inc":"NWBDataInterface"},{"doc":"Tables stored in this collection.","quantity":"*","neurodata_type_inc":"DynamicTable"}],"doc":"A collection of processed data.","neurodata_type_inc":"NWBContainer","neurodata_type_def":"ProcessingModule","attributes":[{"name":"description","doc":"Description of this collection of processed data.","dtype":"text"}]},{"datasets":[{"doc":"Images stored in this collection.","quantity":"+","neurodata_type_inc":"Image"}],"doc":"A collection of images.","default_name":"Images","neurodata_type_inc":"NWBDataInterface","neurodata_type_def":"Images","attributes":[{"name":"description","doc":"Description of this collection of images.","dtype":"text"}]}]}SNOD8UcXxhN8~4H'^4H'^4H'^4H'^4H'^nwb.basenwb.epochnwb.imagenwb.filenwb.miscnwb.behaviornwb.ecephysnwb.icephysnwb.ogennwb.ophysnwb.retinotopynamespaceGCOLy({"datasets":[{"shape":[null,null],"dims":["y","x"],"doc":"A grayscale image.","neurodata_type_inc":"Image","neurodata_type_def":"GrayscaleImage","attributes":[{"name":"resolution","doc":"Pixel resolution of the image, in pixels per centimeter.","required":false,"dtype":"float"},{"name":"description","doc":"Description of the image.","required":false,"dtype":"text"}]},{"shape":[null,null,3],"dims":["y","x","R, G, B"],"doc":"A color image.","neurodata_type_inc":"Image","neurodata_type_def":"RGBImage","attributes":[{"name":"resolution","doc":"Pixel resolution of the image, in pixels per centimeter.","required":false,"dtype":"float"},{"name":"description","doc":"Description of the image.","required":false,"dtype":"text"}]},{"shape":[null,null,4],"dims":["y","x","R, G, B, A"],"doc":"A color image with transparency.","neurodata_type_inc":"Image","neurodata_type_def":"RGBAImage","attributes":[{"name":"resolution","doc":"Pixel resolution of the image, in pixels per centimeter.","required":false,"dtype":"float"},{"name":"description","doc":"Description of the image.","required":false,"dtype":"text"}]}],"groups":[{"datasets":[{"shape":[[null,null,null],[null,null,null,null]],"dims":[["frame","y","x"],["frame","z","y","x"]],"dtype":"numeric","name":"data","doc":"Binary data representing images across frames.","quantity":"?","attributes":[{"name":"conversion","doc":"Scalar to multiply each element in data to convert it to the specified 'unit'. If the data are stored in acquisition system units or other units that require a conversion to be interpretable, multiply the data by 'conversion' to convert the data to the specified 'unit'. e.g. if the data acquisition system stores values in this object as signed 16-bit integers (int16 range -32,768 to 32,767) that correspond to a 5V range (-2.5V to 2.5V), and the data acquisition system gain is 8000X, then the 'conversion' multiplier to get from raw data acquisition values to recorded volts is 2.5/32768/8000 = 9.5367e-9.","required":false,"dtype":"float32","default_value":1.0},{"name":"resolution","doc":"Smallest meaningful difference between values in data, stored in the specified by unit, 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 -1.0.","required":false,"dtype":"float32","default_value":-1.0},{"name":"unit","doc":"Base unit of measurement for working with the data. Actual stored values are not necessarily stored in these units. To access the data in these units, multiply 'data' by 'conversion'.","dtype":"text"}]},{"shape":[null],"dims":["rank"],"dtype":"int32","name":"dimension","doc":"Number of pixels on x, y, (and z) axes.","quantity":"?"},{"shape":[null],"dims":["num_files"],"dtype":"text","name":"external_file","doc":"Paths to one or more external file(s). The field is only present if format='external'. This is only relevant if the image series is stored in the file system as one or more image file(s). This field should NOT be used if the image is stored in another NWB file and that file is linked to this file.","quantity":"?","attributes":[{"name":"starting_frame","doc":"Each external image may contain one or more consecutive frames of the full ImageSeries. This attribute serves as an index to indicate which frames each file contains, to faciliate random access. The 'starting_frame' attribute, hence, contains a list of frame numbers within the full ImageSeries of the first frame of each file listed in the parent 'external_file' dataset. Zero-based indexing is used (hence, the first element will always be zero). For example, if the 'external_file' dataset has three paths to files and the first file has 5 frames, the second file has 10 frames, and the third file has 20 frames, then this attribute will have values [0, 5, 15]. If there is a single external file that holds all of the frames of the ImageSeries (and so there is a single element in the 'external_file' dataset), then this attribute should have value [0].","dtype":"int","shape":[null],"dims":["num_files"]}]},{"dtype":"text","name":"format","doc":"Format of image. If this is 'external', then the attribute 'external_file' contains the path information to the image files. If this is 'raw', then the raw (single-channel) binary data is stored in the 'data' dataset. If this attribute is not present, then the default format='raw' case is assumed.","quantity":"?","default_value":"raw"}],"doc":"General image data that is common between acquisition and stimulus time series. Sometimes the image data is stored in the file in a raw format while other times it will be stored as a series of external image files in the host file system. The data field will either be binary data, if the data is stored in the NWB file, or empty, if the data is stored in an external image stack. [frame][y][x] or [frame][z][y][x].","neurodata_type_inc":"TimeSeries","neurodata_type_def":"ImageSeries","attributes":[{"name":"description","doc":"Description of the time series.","required":false,"dtype":"text","default_value":"no description"},{"name":"comments","doc":"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.","required":false,"dtype":"text","default_value":"no comments"}]},{"links":[{"name":"masked_imageseries","doc":"Link to ImageSeries object that this image mask is applied to.","target_type":"ImageSeries"}],"doc":"An alpha mask that is applied to a presented visual stimulus. The 'data' array contains an array of mask values that are applied to the displayed image. Mask values are stored as RGBA. Mask can vary with time. The timestamps array indicates the starting time of a mask, and that mask pattern continues until it's explicitly changed.","neurodata_type_inc":"ImageSeries","neurodata_type_def":"ImageMaskSeries","attributes":[{"name":"description","doc":"Description of the time series.","required":false,"dtype":"text","default_value":"no description"},{"name":"comments","doc":"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.","required":false,"dtype":"text","default_value":"no comments"}]},{"datasets":[{"dtype":"float32","name":"distance","doc":"Distance from camera/monitor to target/eye.","quantity":"?"},{"shape":[[2],[3]],"dims":[["width, height"],["width, height, depth"]],"dtype":"float32","name":"field_of_view","doc":"Width, height and depth of image, or imaged area, in meters.","quantity":"?"},{"dtype":"text","name":"orientation","doc":"Description of image relative to some reference frame (e.g., which way is up). Must also specify frame of reference.","quantity":"?"}],"doc":"Image data that is presented or recorded. A stimulus template movie will be stored only as an image. When the image is presented as stimulus, additional data is required, such as field of view (e.g., how much of the visual field the image covers, or how what is the area of the target being imaged). If the OpticalSeries represents acquired imaging data, orientation is also important.","neurodata_type_inc":"ImageSeries","neurodata_type_def":"OpticalSeries","attributes":[{"name":"description","doc":"Description of the time series.","required":false,"dtype":"text","default_value":"no description"},{"name":"comments","doc":"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.","required":false,"dtype":"text","default_value":"no comments"}]},{"datasets":[{"shape":[null],"dims":["num_times"],"dtype":"int","name":"data","doc":"Index of the frame in the referenced ImageSeries.","attributes":[{"name":"conversion","doc":"Scalar to multiply each element in data to convert it to the specified 'unit'. If the data are stored in acquisition system units or other units that require a conversion to be interpretable, multiply the data by 'conversion' to convert the data to the specified 'unit'. e.g. if the data acquisition system stores values in this object as signed 16-bit integers (int16 range -32,768 to 32,767) that correspond to a 5V range (-2.5V to 2.5V), and the data acquisition system gain is 8000X, then the 'conversion' multiplier to get from raw data acquisition values to recorded volts is 2.5/32768/8000 = 9.5367e-9.","required":false,"dtype":"float32","default_value":1.0},{"name":"resolution","doc":"Smallest meaningful difference between values in data, stored in the specified by unit, 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 -1.0.","required":false,"dtype":"float32","default_value":-1.0},{"name":"unit","doc":"Base unit of measurement for working with the data. Actual stored values are not necessarily stored in these units. To access the data in these units, multiply 'data' by 'conversion'.","dtype":"text"}]}],"links":[{"name":"indexed_timeseries","doc":"Link to ImageSeries object containing images that are indexed.","target_type":"ImageSeries"}],"doc":"Stores indices to image frames stored in an ImageSeries. The purpose of the ImageIndexSeries 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 ImageSeries, and the timestamps array indicates when that image was displayed.","neurodata_type_inc":"TimeSeries","neurodata_type_def":"IndexSeries","attributes":[{"name":"description","doc":"Description of the time series.","required":false,"dtype":"text","default_value":"no description"},{"name":"comments","doc":"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.","required":false,"dtype":"text","default_value":"no comments"}]}]}"<{"groups":[{"groups":[{"groups":[{"doc":"Acquired, raw data.","quantity":"*","neurodata_type_inc":"NWBDataInterface"},{"doc":"Tabular data that is relevent to acquisition","quantity":"*","neurodata_type_inc":"DynamicTable"}],"name":"acquisition","doc":"Data streams recorded from the system, including ephys, ophys, tracking, etc. This group should be 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 NWB files. This will allow keeping bulky raw data out of the file while preserving the option of keeping some/all in the file. Acquired data includes tracking and experimental data streams (i.e., everything measured from the system). If bulky data is stored in the /acquisition group, the data can exist in a separate NWB file that is linked to by the file being used for processing and analysis."},{"groups":[{"doc":"Custom analysis results.","quantity":"*","neurodata_type_inc":"NWBContainer"},{"doc":"Tabular data that is relevent to data stored in analysis","quantity":"*","neurodata_type_inc":"DynamicTable"}],"name":"analysis","doc":"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. To facilitate sharing analysis data between labs, the contents here should be stored in standard types (e.g., neurodata_types) and appropriately documented. 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 could be shared with other labs."},{"groups":[{"doc":"Any one-off containers","quantity":"*","neurodata_type_inc":"NWBContainer"},{"doc":"Any one-off tables","quantity":"*","neurodata_type_inc":"DynamicTable"}],"datasets":[{"doc":"Any one-off datasets","quantity":"*","neurodata_type_inc":"NWBData","neurodata_type_def":"ScratchData","attributes":[{"name":"notes","doc":"Any notes the user has about the dataset being stored","dtype":"text"}]}],"name":"scratch","doc":"A place to store one-off analysis results. Data placed here is not intended for sharing. By placing data here, users acknowledge that there is no guarantee that their data meets any standard.","quantity":"?"},{"groups":[{"doc":"Intermediate analysis of acquired data.","quantity":"*","neurodata_type_inc":"ProcessingModule"}],"name":"processing","doc":"The home for ProcessingModules. 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. ProcessingModules 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. 'Processing' refers to intermediate analysis of the acquired data to make it more amenable to scientific analysis."},{"groups":[{"groups":[{"doc":"TimeSeries objects containing data of presented stimuli.","quantity":"*","neurodata_type_inc":"TimeSeries"}],"name":"presentation","doc":"Stimuli presented during the experiment."},{"groups":[{"doc":"TimeSeries objects containing template data of presented stimuli.","quantity":"*","neurodata_type_inc":"TimeSeries"}],"name":"templates","doc":"Template stimuli. Timestamps 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."}],"name":"stimulus","doc":"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). This group should be made 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. 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 linked to a remote library file."},{"groups":[{"doc":"Place-holder than can be extended so that lab-specific meta-data can be placed in /general.","quantity":"*","neurodata_type_inc":"NWBContainer","neurodata_type_def":"LabMetaData"},{"groups":[{"doc":"A data acquisition device, e.g. recording system.","quantity":"+","neurodata_type_inc":"NWBContainer","neurodata_type_def":"Device"}],"name":"devices","doc":"Description of hardware devices used during experiment, e.g., monitors, ADC boards, microscopes, etc.","quantity":"?"},{"datasets":[{"dtype":"text","name":"age","doc":"Age of subject. Can be supplied instead of 'date_of_birth'.","quantity":"?"},{"dtype":"isodatetime","name":"date_of_birth","doc":"Date of birth of subject. Can be supplied instead of 'age'.","quantity":"?"},{"dtype":"text","name":"description","doc":"Description of subject and where subject came from (e.g., breeder, if animal).","quantity":"?"},{"dtype":"text","name":"genotype","doc":"Genetic strain. If absent, assume Wild Type (WT).","quantity":"?"},{"dtype":"text","name":"sex","doc":"Gender of subject.","quantity":"?"},{"dtype":"text","name":"species","doc":"Species of subject.","quantity":"?"},{"dtype":"text","name":"subject_id","doc":"ID of animal/person used/participating in experiment (lab convention).","quantity":"?"},{"dtype":"text","name":"weight","doc":"Weight at time of experiment, at time of surgery and at other important times.","quantity":"?"}],"name":"subject","doc":"Information about the animal or person from which the data was measured.","quantity":"?","neurodata_type_inc":"NWBContainer","neurodata_type_def":"Subject"},{"groups":[{"doc":"Physical group of electrodes.","quantity":"*","neurodata_type_inc":"ElectrodeGroup"},{"datasets":[{"dtype":"float","name":"x","doc":"x coordinate of the channel location.","neurodata_type_inc":"VectorData"},{"dtype":"float","name":"y","doc":"y coordinate of the channel location.","neurodata_type_inc":"VectorData"},{"dtype":"float","name":"z","doc":"z coordinate of the channel location.","neurodata_type_inc":"VectorData"},{"dtype":"float","name":"imp","doc":"Impedance of the channel.","neurodata_type_inc":"VectorData"},{"dtype":"ascii","name":"location","doc":"Location of the electrode (channel). Specify the area, layer, comments on estimation of area/layer, stereotaxic coordinates if in vivo, etc. Use standard atlas names for anatomical regions when possible.","neurodata_type_inc":"VectorData"},{"dtype":"float","name":"filtering","doc":"Description of hardware filtering.","neurodata_type_inc":"VectorData"},{"dtype":{"target_type":"ElectrodeGroup","reftype":"object"},"name":"group","doc":"Reference to the ElectrodeGroup this electrode is a part of.","neurodata_type_inc":"VectorData"},{"dtype":"ascii","name":"group_name","doc":"Name of the ElectrodeGroup this electrode is a part of.","neurodata_type_inc":"VectorData"}],"name":"electrodes","doc":"A table of all electrodes (i.e. channels) used for recording.","quantity":"?","neurodata_type_inc":"DynamicTable"}],"name":"extracellular_ephys","doc":"Metadata related to extracellular electrophysiology.","quantity":"?"},{"groups":[{"doc":"An intracellular electrode.","quantity":"*","neurodata_type_inc":"IntracellularElectrode"},{"name":"sweep_table","doc":"The table which groups different PatchClampSeries together.","quantity":"?","neurodata_type_inc":"SweepTable"}],"datasets":[{"dtype":"text","name":"filtering","doc":"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.","quantity":"?"}],"name":"intracellular_ephys","doc":"Metadata related to intracellular electrophysiology.","quantity":"?"},{"groups":[{"doc":"An optogenetic stimulation site.","quantity":"*","neurodata_type_inc":"OptogeneticStimulusSite"}],"name":"optogenetics","doc":"Metadata describing optogenetic stimuluation.","quantity":"?"},{"groups":[{"doc":"An imaging plane.","quantity":"*","neurodata_type_inc":"ImagingPlane"}],"name":"optophysiology","doc":"Metadata related to optophysiology.","quantity":"?"}],"datasets":[{"dtype":"text","name":"data_collection","doc":"Notes about data collection and analysis.","quantity":"?"},{"dtype":"text","name":"experiment_description","doc":"General description of the experiment.","quantity":"?"},{"shape":[null],"dims":["num_experimenters"],"dtype":"text","name":"experimenter","doc":"Name of person(s) who performed the experiment. Can also specify roles of different people involved.","quantity":"?"},{"dtype":"text","name":"institution","doc":"Institution(s) where experiment was performed.","quantity":"?"},{"shape":[null],"dims":["num_keywords"],"dtype":"text","name":"keywords","doc":"Terms to search over.","quantity":"?"},{"dtype":"text","name":"lab","doc":"Laboratory where experiment was performed.","quantity":"?"},{"dtype":"text","name":"notes","doc":"Notes about the experiment.","quantity":"?"},{"dtype":"text","name":"pharmacology","doc":"Description of drugs used, including how and when they were administered. Anesthesia(s), painkiller(s), etc., plus dosage, concentration, etc.","quantity":"?"},{"dtype":"text","name":"protocol","doc":"Experimental protocol, if applicable. e.g., include IACUC protocol number.","quantity":"?"},{"shape":[null],"dims":["num_publications"],"dtype":"text","name":"related_publications","doc":"Publication information. PMID, DOI, URL, etc.","quantity":"?"},{"dtype":"text","name":"session_id","doc":"Lab-specific ID for the session.","quantity":"?"},{"dtype":"text","name":"slices","doc":"Description of slices, including information about preparation thickness, orientation, temperature, and bath solution.","quantity":"?"},{"dtype":"text","name":"source_script","doc":"Script file or link to public source code used to create this NWB file.","quantity":"?","attributes":[{"name":"file_name","doc":"Name of script file.","dtype":"text"}]},{"dtype":"text","name":"stimulus","doc":"Notes about stimuli, such as how and where they were presented.","quantity":"?"},{"dtype":"text","name":"surgery","doc":"Narrative description about surgery/surgeries, including date(s) and who performed surgery.","quantity":"?"},{"dtype":"text","name":"virus","doc":"Information about virus(es) used in experiments, including virus ID, source, date made, injection location, volume, etc.","quantity":"?"}],"name":"general","doc":"Experimental metadata, including protocol, notes and description of hardware device(s). The metadata stored in this section should be used to describe the experiment. Metadata necessary for interpreting the data is stored with the data. 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 (e.g., 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. 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."},{"groups":[{"name":"epochs","doc":"Divisions in time marking experimental stages or sub-divisions of a single recording session.","quantity":"?","neurodata_type_inc":"TimeIntervals"},{"name":"trials","doc":"Repeated experimental events that have a logical grouping.","quantity":"?","neurodata_type_inc":"TimeIntervals"},{"name":"invalid_times","doc":"Time intervals that should be removed from analysis.","quantity":"?","neurodata_type_inc":"TimeIntervals"},{"doc":"Optional additional table(s) for describing other experimental time intervals.","quantity":"*","neurodata_type_inc":"TimeIntervals"}],"name":"intervals","doc":"Experimental intervals, whether that be logically distinct sub-experiments having a particular scientific goal, trials (see trials subgroup) during an experiment, or epochs (see epochs subgroup) deriving from analysis of data.","quantity":"?"},{"name":"units","doc":"Data about sorted spike units.","quantity":"?","neurodata_type_inc":"Units"}],"datasets":[{"shape":[null],"dims":["num_modifications"],"dtype":"isodatetime","name":"file_create_date","doc":"A record of the date the file was created and of subsequent modifications. The date is stored in UTC with local timezone offset as ISO 8601 extended formatted strings: 2018-09-28T14:43:54.123+02:00. Dates stored in UTC end in \"Z\" with no timezone offset. Date accuracy is up to milliseconds. The file can be created after the experiment was run, so this may differ from the experiment start time. Each modification to the nwb file adds a new entry to the array."},{"dtype":"text","name":"identifier","doc":"A unique text identifier for the file. For example, 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."},{"dtype":"text","name":"session_description","doc":"A description of the experimental session and data in the file."},{"dtype":"isodatetime","name":"session_start_time","doc":"Date and time of the experiment/session start. The date is stored in UTC with local timezone offset as ISO 8601 extended formatted string: 2018-09-28T14:43:54.123+02:00. Dates stored in UTC end in \"Z\" with no timezone offset. Date accuracy is up to milliseconds."},{"dtype":"isodatetime","name":"timestamps_reference_time","doc":"Date and time corresponding to time zero of all timestamps. The date is stored in UTC with local timezone offset as ISO 8601 extended formatted string: 2018-09-28T14:43:54.123+02:00. Dates stored in UTC end in \"Z\" with no timezone offset. Date accuracy is up to milliseconds. All times stored in the file use this time as reference (i.e., time zero)."}],"name":"root","doc":"An NWB:N file storing cellular-based neurophysiology data from a single experimental session.","neurodata_type_inc":"NWBContainer","neurodata_type_def":"NWBFile","attributes":[{"name":"nwb_version","doc":"File version string. Use semantic versioning, e.g. 1.2.1. This will be the name of the format with trailing major, minor and patch numbers.","dtype":"text","value":"2.1.0"}]}]},1{"groups":[{"datasets":[{"shape":[[null],[null,null]],"dims":[["num_times"],["num_times","num_features"]],"dtype":"numeric","name":"data","doc":"Values of each feature at each time.","attributes":[{"name":"unit","doc":"Since there can be different units for different features, store the units in 'feature_units'. The default value for this attribute is \"see 'feature_units'\".","required":false,"dtype":"text","default_value":"see 'feature_units'"},{"name":"conversion","doc":"Scalar to multiply each element in data to convert it to the specified 'unit'. If the data are stored in acquisition system units or other units that require a conversion to be interpretable, multiply the data by 'conversion' to convert the data to the specified 'unit'. e.g. if the data acquisition system stores values in this object as signed 16-bit integers (int16 range -32,768 to 32,767) that correspond to a 5V range (-2.5V to 2.5V), and the data acquisition system gain is 8000X, then the 'conversion' multiplier to get from raw data acquisition values to recorded volts is 2.5/32768/8000 = 9.5367e-9.","required":false,"dtype":"float32","default_value":1.0},{"name":"resolution","doc":"Smallest meaningful difference between values in data, stored in the specified by unit, 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 -1.0.","required":false,"dtype":"float32","default_value":-1.0}]},{"shape":[null],"dims":["num_features"],"dtype":"text","name":"feature_units","doc":"Units of each feature.","quantity":"?"},{"shape":[null],"dims":["num_features"],"dtype":"text","name":"features","doc":"Description of the features represented in TimeSeries::data."}],"doc":"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. This is useful when storing the raw stimulus is impractical.","neurodata_type_inc":"TimeSeries","neurodata_type_def":"AbstractFeatureSeries","attributes":[{"name":"description","doc":"Description of the time series.","required":false,"dtype":"text","default_value":"no description"},{"name":"comments","doc":"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.","required":false,"dtype":"text","default_value":"no comments"}]},{"datasets":[{"shape":[null],"dims":["num_times"],"dtype":"text","name":"data","doc":"Annotations made during an experiment.","attributes":[{"name":"resolution","doc":"Smallest meaningful difference between values in data. Annotations have no units, so the value is fixed to -1.0.","dtype":"float","value":-1.0},{"name":"unit","doc":"Base unit of measurement for working with the data. Annotations have no units, so the value is fixed to 'n/a'.","dtype":"text","value":"n/a"},{"name":"conversion","doc":"Scalar to multiply each element in data to convert it to the specified 'unit'. If the data are stored in acquisition system units or other units that require a conversion to be interpretable, multiply the data by 'conversion' to convert the data to the specified 'unit'. e.g. if the data acquisition system stores values in this object as signed 16-bit integers (int16 range -32,768 to 32,767) that correspond to a 5V range (-2.5V to 2.5V), and the data acquisition system gain is 8000X, then the 'conversion' multiplier to get from raw data acquisition values to recorded volts is 2.5/32768/8000 = 9.5367e-9.","required":false,"dtype":"float32","default_value":1.0}]}],"doc":"Stores user annotations made during an experiment. The 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.","neurodata_type_inc":"TimeSeries","neurodata_type_def":"AnnotationSeries","attributes":[{"name":"description","doc":"Description of the time series.","required":false,"dtype":"text","default_value":"no description"},{"name":"comments","doc":"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.","required":false,"dtype":"text","default_value":"no comments"}]},{"datasets":[{"shape":[null],"dims":["num_times"],"dtype":"int8","name":"data","doc":"Use values >0 if interval started, <0 if interval ended.","attributes":[{"name":"resolution","doc":"Smallest meaningful difference between values in data. Annotations have no units, so the value is fixed to -1.0.","dtype":"float","value":-1.0},{"name":"unit","doc":"Base unit of measurement for working with the data. Annotations have no units, so the value is fixed to 'n/a'.","dtype":"text","value":"n/a"},{"name":"conversion","doc":"Scalar to multiply each element in data to convert it to the specified 'unit'. If the data are stored in acquisition system units or other units that require a conversion to be interpretable, multiply the data by 'conversion' to convert the data to the specified 'unit'. e.g. if the data acquisition system stores values in this object as signed 16-bit integers (int16 range -32,768 to 32,767) that correspond to a 5V range (-2.5V to 2.5V), and the data acquisition system gain is 8000X, then the 'conversion' multiplier to get from raw data acquisition values to recorded volts is 2.5/32768/8000 = 9.5367e-9.","required":false,"dtype":"float32","default_value":1.0}]}],"doc":"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.","neurodata_type_inc":"TimeSeries","neurodata_type_def":"IntervalSeries","attributes":[{"name":"description","doc":"Description of the time series.","required":false,"dtype":"text","default_value":"no description"},{"name":"comments","doc":"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.","required":false,"dtype":"text","default_value":"no comments"}]},{"groups":[{"datasets":[{"dtype":"text","name":"band_name","doc":"Name of the band, e.g. theta.","neurodata_type_inc":"VectorData"},{"shape":[null,2],"dims":["num_bands","low, high"],"dtype":"float","name":"band_limits","doc":"Low and high limit of each band in Hz. If it is a Gaussian filter, use 2 SD on either side of the center.","neurodata_type_inc":"VectorData"},{"shape":[null],"dims":["num_bands"],"dtype":"float","name":"band_mean","doc":"The mean Gaussian filters, in Hz.","neurodata_type_inc":"VectorData"},{"shape":[null],"dims":["num_bands"],"dtype":"float","name":"band_stdev","doc":"The standard deviation of Gaussian filters, in Hz.","neurodata_type_inc":"VectorData"}],"name":"bands","doc":"Table for describing the bands that this series was generated from. There should be one row in this table for each band.","neurodata_type_inc":"DynamicTable"}],"datasets":[{"shape":[null,null,null],"dims":["num_times","num_channels","num_bands"],"dtype":"numeric","name":"data","doc":"Data decomposed into frequency bands.","attributes":[{"name":"unit","doc":"Base unit of measurement for working with the data. Actual stored values are not necessarily stored in these units. To access the data in these units, multiply 'data' by 'conversion'.","required":false,"dtype":"text","default_value":"no unit"},{"name":"conversion","doc":"Scalar to multiply each element in data to convert it to the specified 'unit'. If the data are stored in acquisition system units or other units that require a conversion to be interpretable, multiply the data by 'conversion' to convert the data to the specified 'unit'. e.g. if the data acquisition system stores values in this object as signed 16-bit integers (int16 range -32,768 to 32,767) that correspond to a 5V range (-2.5V to 2.5V), and the data acquisition system gain is 8000X, then the 'conversion' multiplier to get from raw data acquisition values to recorded volts is 2.5/32768/8000 = 9.5367e-9.","required":false,"dtype":"float32","default_value":1.0},{"name":"resolution","doc":"Smallest meaningful difference between values in data, stored in the specified by unit, 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 -1.0.","required":false,"dtype":"float32","default_value":-1.0}]},{"dtype":"text","name":"metric","doc":"The metric used, e.g. phase, amplitude, power."}],"links":[{"name":"source_timeseries","doc":"Link to TimeSeries object that this data was calculated from. Metadata about electrodes and their position can be read from that ElectricalSeries so it is not necessary to store that information here.","target_type":"TimeSeries","quantity":"?"}],"doc":"Spectral analysis of a time series, e.g. of an LFP or a speech signal.","neurodata_type_inc":"TimeSeries","neurodata_type_def":"DecompositionSeries","attributes":[{"name":"description","doc":"Description of the time series.","required":false,"dtype":"text","default_value":"no description"},{"name":"comments","doc":"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.","required":false,"dtype":"text","default_value":"no comments"}]},{"datasets":[{"name":"spike_times_index","doc":"Index into the spike_times dataset.","quantity":"?","neurodata_type_inc":"VectorIndex"},{"dtype":"double","name":"spike_times","doc":"Spike times for each unit.","quantity":"?","neurodata_type_inc":"VectorData"},{"name":"obs_intervals_index","doc":"Index into the obs_intervals dataset.","quantity":"?","neurodata_type_inc":"VectorIndex"},{"shape":[null,2],"dims":["num_intervals","start|end"],"dtype":"double","name":"obs_intervals","doc":"Observation intervals for each unit.","quantity":"?","neurodata_type_inc":"VectorData"},{"name":"electrodes_index","doc":"Index into electrodes.","quantity":"?","neurodata_type_inc":"VectorIndex"},{"name":"electrodes","doc":"Electrode that each spike unit came from, specified using a DynamicTableRegion.","quantity":"?","neurodata_type_inc":"DynamicTableRegion"},{"dtype":{"target_type":"ElectrodeGroup","reftype":"object"},"name":"electrode_group","doc":"Electrode group that each spike unit came from.","quantity":"?","neurodata_type_inc":"VectorData"},{"shape":[[null,null],[null,null,null]],"dims":[["num_units","num_samples"],["num_units","num_samples","num_electrodes"]],"dtype":"float","name":"waveform_mean","doc":"Spike waveform mean for each spike unit.","quantity":"?","neurodata_type_inc":"VectorData"},{"shape":[[null,null],[null,null,null]],"dims":[["num_units","num_samples"],["num_units","num_samples","num_electrodes"]],"dtype":"float","name":"waveform_sd","doc":"Spike waveform standard deviation for each spike unit.","quantity":"?","neurodata_type_inc":"VectorData"}],"doc":"Data about spiking units. Event times of observed units (e.g. cell, synapse, etc.) should be concatenated and stored in spike_times.","default_name":"Units","neurodata_type_inc":"DynamicTable","neurodata_type_def":"Units","attributes":[{"name":"colnames","doc":"The names of the columns in this table. This should be used to specify an order to the columns.","dtype":"ascii","shape":[null],"dims":["num_columns"]},{"name":"description","doc":"Description of what is in this dynamic table.","dtype":"text"}]}]}{"groups":[{"datasets":[{"shape":[[null],[null,null]],"dims":[["num_times"],["num_times","num_features"]],"dtype":"numeric","name":"data","doc":"1-D or 2-D array storing position or direction relative to some reference frame.","attributes":[{"name":"unit","doc":"Base unit of measurement for working with the data. The default value is 'meters'. Actual stored values are not necessarily stored in these units. To access the data in these units, multiply 'data' by 'conversion'.","required":false,"dtype":"text","default_value":"meters"},{"name":"conversion","doc":"Scalar to multiply each element in data to convert it to the specified 'unit'. If the data are stored in acquisition system units or other units that require a conversion to be interpretable, multiply the data by 'conversion' to convert the data to the specified 'unit'. e.g. if the data acquisition system stores values in this object as signed 16-bit integers (int16 range -32,768 to 32,767) that correspond to a 5V range (-2.5V to 2.5V), and the data acquisition system gain is 8000X, then the 'conversion' multiplier to get from raw data acquisition values to recorded volts is 2.5/32768/8000 = 9.5367e-9.","required":false,"dtype":"float32","default_value":1.0},{"name":"resolution","doc":"Smallest meaningful difference between values in data, stored in the specified by unit, 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 -1.0.","required":false,"dtype":"float32","default_value":-1.0}]},{"dtype":"text","name":"reference_frame","doc":"Description defining what exactly 'straight-ahead' means.","quantity":"?"}],"doc":"Direction, e.g., of gaze or travel, or position. The TimeSeries::data field is a 2D array storing position or direction relative to some reference frame. Array structure: [num measurements] [num dimensions]. Each SpatialSeries has a text dataset reference_frame that indicates the zero-position, or the zero-axes for direction. For example, if representing gaze direction, 'straight-ahead' might be a specific pixel on the monitor, or some other point in space. For position data, the 0,0 point might be the top-left corner of an enclosure, as viewed from the tracking camera. The unit of data will indicate how to interpret SpatialSeries values.","neurodata_type_inc":"TimeSeries","neurodata_type_def":"SpatialSeries","attributes":[{"name":"description","doc":"Description of the time series.","required":false,"dtype":"text","default_value":"no description"},{"name":"comments","doc":"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.","required":false,"dtype":"text","default_value":"no comments"}]},{"groups":[{"doc":"IntervalSeries object containing start and stop times of epochs.","quantity":"*","neurodata_type_inc":"IntervalSeries"}],"doc":"TimeSeries for storing behavioral epochs. The objective of this and the other two Behavioral interfaces (e.g. BehavioralEvents and BehavioralTimeSeries) is to provide generic hooks for software tools/scripts. This allows a tool/script to take the output one specific interface (e.g., UnitTimes) and plot that data relative to another data modality (e.g., behavioral events) without having to define all possible modalities in advance. Declaring one of these interfaces means that one or more TimeSeries of the specified type is published. These TimeSeries should reside in a group having the same name as the interface. For example, if a BehavioralTimeSeries interface is declared, the module will have one or more TimeSeries defined in the module sub-group 'BehavioralTimeSeries'. BehavioralEpochs should use IntervalSeries. BehavioralEvents is used for irregular events. BehavioralTimeSeries is for continuous data.","default_name":"BehavioralEpochs","neurodata_type_inc":"NWBDataInterface","neurodata_type_def":"BehavioralEpochs"},{"groups":[{"doc":"TimeSeries object containing behavioral events.","quantity":"*","neurodata_type_inc":"TimeSeries"}],"doc":"TimeSeries for storing behavioral events. See description of BehavioralEpochs for more details.","default_name":"BehavioralEvents","neurodata_type_inc":"NWBDataInterface","neurodata_type_def":"BehavioralEvents"},{"groups":[{"doc":"TimeSeries object containing continuous behavioral data.","quantity":"*","neurodata_type_inc":"TimeSeries"}],"doc":"TimeSeries for storing Behavoioral time series data. See description of BehavioralEpochs for more details.","default_name":"BehavioralTimeSeries","neurodata_type_inc":"NWBDataInterface","neurodata_type_def":"BehavioralTimeSeries"},{"groups":[{"doc":"TimeSeries object containing time series data on pupil size.","quantity":"+","neurodata_type_inc":"TimeSeries"}],"doc":"Eye-tracking data, representing pupil size.","default_name":"PupilTracking","neurodata_type_inc":"NWBDataInterface","neurodata_type_def":"PupilTracking"},{"groups":[{"doc":"SpatialSeries object containing data measuring direction of gaze.","quantity":"*","neurodata_type_inc":"SpatialSeries"}],"doc":"Eye-tracking data, representing direction of gaze.","default_name":"EyeTracking","neurodata_type_inc":"NWBDataInterface","neurodata_type_def":"EyeTracking"},{"groups":[{"doc":"SpatialSeries object containing direction of gaze travel.","quantity":"*","neurodata_type_inc":"SpatialSeries"}],"doc":"With a CompassDirection interface, a module publishes a SpatialSeries object representing a floating point value for theta. The SpatialSeries::reference_frame field should indicate what direction corresponds to 0 and which is the direction of rotation (this should be clockwise). The si_unit for the SpatialSeries should be radians or degrees.","default_name":"CompassDirection","neurodata_type_inc":"NWBDataInterface","neurodata_type_def":"CompassDirection"},{"groups":[{"doc":"SpatialSeries object containing position data.","quantity":"+","neurodata_type_inc":"SpatialSeries"}],"doc":"Position data, whether along the x, x/y or x/y/z axis.","default_name":"Position","neurodata_type_inc":"NWBDataInterface","neurodata_type_def":"Position"}]}~ {"groups":[{"datasets":[{"shape":[null],"dims":["num_times"],"dtype":"numeric","name":"data","doc":"Applied power for optogenetic stimulus, in watts.","attributes":[{"name":"unit","doc":"Unit of measurement for data, which is fixed to 'watts'.","dtype":"text","value":"watts"},{"name":"conversion","doc":"Scalar to multiply each element in data to convert it to the specified 'unit'. If the data are stored in acquisition system units or other units that require a conversion to be interpretable, multiply the data by 'conversion' to convert the data to the specified 'unit'. e.g. if the data acquisition system stores values in this object as signed 16-bit integers (int16 range -32,768 to 32,767) that correspond to a 5V range (-2.5V to 2.5V), and the data acquisition system gain is 8000X, then the 'conversion' multiplier to get from raw data acquisition values to recorded volts is 2.5/32768/8000 = 9.5367e-9.","required":false,"dtype":"float32","default_value":1.0},{"name":"resolution","doc":"Smallest meaningful difference between values in data, stored in the specified by unit, 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 -1.0.","required":false,"dtype":"float32","default_value":-1.0}]}],"links":[{"name":"site","doc":"Link to OptogeneticStimulusSite object that describes the site to which this stimulus was applied.","target_type":"OptogeneticStimulusSite"}],"doc":"An optogenetic stimulus.","neurodata_type_inc":"TimeSeries","neurodata_type_def":"OptogeneticSeries","attributes":[{"name":"description","doc":"Description of the time series.","required":false,"dtype":"text","default_value":"no description"},{"name":"comments","doc":"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.","required":false,"dtype":"text","default_value":"no comments"}]},{"datasets":[{"dtype":"text","name":"description","doc":"Description of stimulation site."},{"dtype":"float","name":"excitation_lambda","doc":"Excitation wavelength, in nm."},{"dtype":"text","name":"location","doc":"Location of the stimulation site. Specify the area, layer, comments on estimation of area/layer, stereotaxic coordinates if in vivo, etc. Use standard atlas names for anatomical regions when possible."}],"links":[{"name":"device","doc":"Device that generated the stimulus.","target_type":"Device"}],"doc":"A site of optogenetic stimulation.","quantity":"*","neurodata_type_inc":"NWBContainer","neurodata_type_def":"OptogeneticStimulusSite"}]}`4H'^4H'^5H'^SNOD8XxO(HHhPS(T5H'^(5H'^85H'^GCOLw4{"groups":[{"datasets":[{"shape":[[null],[null,null],[null,null,null]],"dims":[["num_times"],["num_times","num_channels"],["num_times","num_channels","num_samples"]],"dtype":"numeric","name":"data","doc":"Recorded voltage data.","attributes":[{"name":"unit","doc":"Base unit of measurement for working with the data. This value is fixed to 'volts'. Actual stored values are not necessarily stored in these units. To access the data in these units, multiply 'data' by 'conversion' and 'channel_conversion' (if present).","dtype":"text","value":"volts"},{"name":"conversion","doc":"Scalar to multiply each element in data to convert it to the specified 'unit'. If the data are stored in acquisition system units or other units that require a conversion to be interpretable, multiply the data by 'conversion' to convert the data to the specified 'unit'. e.g. if the data acquisition system stores values in this object as signed 16-bit integers (int16 range -32,768 to 32,767) that correspond to a 5V range (-2.5V to 2.5V), and the data acquisition system gain is 8000X, then the 'conversion' multiplier to get from raw data acquisition values to recorded volts is 2.5/32768/8000 = 9.5367e-9.","required":false,"dtype":"float32","default_value":1.0},{"name":"resolution","doc":"Smallest meaningful difference between values in data, stored in the specified by unit, 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 -1.0.","required":false,"dtype":"float32","default_value":-1.0}]},{"name":"electrodes","doc":"DynamicTableRegion pointer to the electrodes that this time series was generated from.","neurodata_type_inc":"DynamicTableRegion"},{"shape":[null],"dims":["num_channels"],"dtype":"float","name":"channel_conversion","doc":"Channel-specific conversion factor. Multiply the data in the 'data' dataset by these values along the channel axis (as indicated by axis attribute) AND by the global conversion factor in the 'conversion' attribute of 'data' to get the data values in Volts, i.e, data in Volts = data * data.conversion * channel_conversion. This approach allows for both global and per-channel data conversion factors needed to support the storage of electrical recordings as native values generated by data acquisition systems. If this dataset is not present, then there is no channel-specific conversion factor, i.e. it is 1 for all channels.","quantity":"?","attributes":[{"name":"axis","doc":"The zero-indexed axis of the 'data' dataset that the channel-specific conversion factor corresponds to. This value is fixed to 1.","dtype":"int","value":1}]}],"doc":"A time series of acquired voltage data from extracellular recordings. The data field is an int or float array storing data in volts. The first dimension should always represent time. The second dimension, if present, should represent channels.","neurodata_type_inc":"TimeSeries","neurodata_type_def":"ElectricalSeries","attributes":[{"name":"description","doc":"Description of the time series.","required":false,"dtype":"text","default_value":"no description"},{"name":"comments","doc":"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.","required":false,"dtype":"text","default_value":"no comments"}]},{"datasets":[{"shape":[[null,null],[null,null,null]],"dims":[["num_events","num_samples"],["num_events","num_channels","num_samples"]],"dtype":"numeric","name":"data","doc":"Spike waveforms.","attributes":[{"name":"unit","doc":"Unit of measurement for waveforms, which is fixed to 'volts'.","dtype":"text","value":"volts"},{"name":"conversion","doc":"Scalar to multiply each element in data to convert it to the specified 'unit'. If the data are stored in acquisition system units or other units that require a conversion to be interpretable, multiply the data by 'conversion' to convert the data to the specified 'unit'. e.g. if the data acquisition system stores values in this object as signed 16-bit integers (int16 range -32,768 to 32,767) that correspond to a 5V range (-2.5V to 2.5V), and the data acquisition system gain is 8000X, then the 'conversion' multiplier to get from raw data acquisition values to recorded volts is 2.5/32768/8000 = 9.5367e-9.","required":false,"dtype":"float32","default_value":1.0},{"name":"resolution","doc":"Smallest meaningful difference between values in data, stored in the specified by unit, 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 -1.0.","required":false,"dtype":"float32","default_value":-1.0}]},{"shape":[null],"dims":["num_times"],"dtype":"float64","name":"timestamps","doc":"Timestamps for samples stored in data, in seconds, relative to the common experiment master-clock stored in NWBFile.timestamps_reference_time. Timestamps are required for the events. Unlike for TimeSeries, timestamps are required for SpikeEventSeries and are thus re-specified here.","attributes":[{"name":"interval","doc":"Value is '1'","dtype":"int32","value":1},{"name":"unit","doc":"Unit of measurement for timestamps, which is fixed to 'seconds'.","dtype":"text","value":"seconds"}]}],"doc":"Stores snapshots/snippets of recorded spike events (i.e., threshold crossings). This may also be raw data, as reported by ephys hardware. If so, the TimeSeries::description field should describe how events were detected. All SpikeEventSeries should reside in a module (under EventWaveform interface) even if the spikes were reported and stored by hardware. All events span the same recording channels and store snapshots of equal duration. TimeSeries::data array structure: [num events] [num channels] [num samples] (or [num events] [num samples] for single electrode).","neurodata_type_inc":"ElectricalSeries","neurodata_type_def":"SpikeEventSeries","attributes":[{"name":"description","doc":"Description of the time series.","required":false,"dtype":"text","default_value":"no description"},{"name":"comments","doc":"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.","required":false,"dtype":"text","default_value":"no comments"}]},{"datasets":[{"shape":[null],"dims":["num_features"],"dtype":"text","name":"description","doc":"Description of features (eg, ''PC1'') for each of the extracted features."},{"shape":[null,null,null],"dims":["num_events","num_channels","num_features"],"dtype":"float32","name":"features","doc":"Multi-dimensional array of features extracted from each event."},{"shape":[null],"dims":["num_events"],"dtype":"float64","name":"times","doc":"Times of events that features correspond to (can be a link)."},{"name":"electrodes","doc":"DynamicTableRegion pointer to the electrodes that this time series was generated from.","neurodata_type_inc":"DynamicTableRegion"}],"doc":"Features, such as PC1 and PC2, that are extracted from signals stored in a SpikeEventSeries or other source.","default_name":"FeatureExtraction","neurodata_type_inc":"NWBDataInterface","neurodata_type_def":"FeatureExtraction"},{"datasets":[{"dtype":"text","name":"detection_method","doc":"Description of how events were detected, such as voltage threshold, or dV/dT threshold, as well as relevant values."},{"shape":[null],"dims":["num_events"],"dtype":"int32","name":"source_idx","doc":"Indices (zero-based) into source ElectricalSeries::data array corresponding to time of event. ''description'' should define what is meant by time of event (e.g., .25 ms before action potential peak, zero-crossing time, etc). The index points to each event from the raw data."},{"shape":[null],"dims":["num_events"],"dtype":"float64","name":"times","doc":"Timestamps of events, in seconds.","attributes":[{"name":"unit","doc":"Unit of measurement for event times, which is fixed to 'seconds'.","dtype":"text","value":"seconds"}]}],"links":[{"name":"source_electricalseries","doc":"Link to the ElectricalSeries that this data was calculated from. Metadata about electrodes and their position can be read from that ElectricalSeries so it's not necessary to include that information here.","target_type":"ElectricalSeries"}],"doc":"Detected spike events from voltage trace(s).","default_name":"EventDetection","neurodata_type_inc":"NWBDataInterface","neurodata_type_def":"EventDetection"},{"groups":[{"doc":"SpikeEventSeries object(s) containing detected spike event waveforms.","quantity":"*","neurodata_type_inc":"SpikeEventSeries"}],"doc":"Represents either the waveforms of detected events, as extracted from a raw data trace in /acquisition, or the event waveforms that were stored during experiment acquisition.","default_name":"EventWaveform","neurodata_type_inc":"NWBDataInterface","neurodata_type_def":"EventWaveform"},{"groups":[{"doc":"ElectricalSeries object(s) containing filtered electrophysiology data.","quantity":"+","neurodata_type_inc":"ElectricalSeries"}],"doc":"Electrophysiology data from one or more channels that has been subjected to filtering. Examples of filtered data include Theta and Gamma (LFP has its own interface). FilteredEphys modules publish an ElectricalSeries for each filtered channel or set of channels. The name of each ElectricalSeries is arbitrary but should be informative. The source of the filtered data, whether this is from analysis of another time series or as acquired by hardware, should be noted in each's TimeSeries::description field. There is no assumed 1::1 correspondence between filtered ephys signals and electrodes, as a single signal can apply to many nearby electrodes, and one electrode may have different filtered (e.g., theta and/or gamma) signals represented. Filter properties should be noted in the ElectricalSeries.","default_name":"FilteredEphys","neurodata_type_inc":"NWBDataInterface","neurodata_type_def":"FilteredEphys"},{"groups":[{"doc":"ElectricalSeries object(s) containing LFP data for one or more channels.","quantity":"+","neurodata_type_inc":"ElectricalSeries"}],"doc":"LFP data from one or more channels. The electrode map in each published ElectricalSeries will identify which channels are providing LFP data. Filter properties should be noted in the ElectricalSeries description or comments field.","default_name":"LFP","neurodata_type_inc":"NWBDataInterface","neurodata_type_def":"LFP"},{"links":[{"name":"device","doc":"Link to the device that was used to record from this electrode group.","target_type":"Device"}],"doc":"A physical grouping of electrodes, e.g. a shank of an array.","neurodata_type_inc":"NWBContainer","neurodata_type_def":"ElectrodeGroup","attributes":[{"name":"description","doc":"Description of this electrode group.","dtype":"text"},{"name":"location","doc":"Location of electrode group. Specify the area, layer, comments on estimation of area/layer, stereotaxic coordinates if in vivo, etc. Use standard atlas names for anatomical regions when possible.","dtype":"text"}]},{"datasets":[{"dtype":"text","name":"waveform_filtering","doc":"Filtering applied to data before generating mean/sd"},{"shape":[null,null],"dims":["num_clusters","num_samples"],"dtype":"float32","name":"waveform_mean","doc":"The mean waveform for each cluster, using the same indices for each wave as cluster numbers in the associated Clustering module (i.e, cluster 3 is in array slot [3]). Waveforms corresponding to gaps in cluster sequence should be empty (e.g., zero- filled)"},{"shape":[null,null],"dims":["num_clusters","num_samples"],"dtype":"float32","name":"waveform_sd","doc":"Stdev of waveforms for each cluster, using the same indices as in mean"}],"links":[{"name":"clustering_interface","doc":"Link to Clustering interface that was the source of the clustered data","target_type":"Clustering"}],"doc":"DEPRECATED The mean waveform shape, including standard deviation, of the different clusters. Ideally, the waveform analysis should be performed on data that is only high-pass filtered. This is a separate module because it is expected to require updating. For example, IMEC probes may require different storage requirements to store/display mean waveforms, requiring a new interface or an extension of this one.","default_name":"ClusterWaveforms","neurodata_type_inc":"NWBDataInterface","neurodata_type_def":"ClusterWaveforms"},{"datasets":[{"dtype":"text","name":"description","doc":"Description of clusters or clustering, (e.g. cluster 0 is noise, clusters curated using Klusters, etc)"},{"shape":[null],"dims":["num_events"],"dtype":"int32","name":"num","doc":"Cluster number of each event"},{"shape":[null],"dims":["num_clusters"],"dtype":"float32","name":"peak_over_rms","doc":"Maximum ratio of waveform peak to RMS on any channel in the cluster (provides a basic clustering metric)."},{"shape":[null],"dims":["num_events"],"dtype":"float64","name":"times","doc":"Times of clustered events, in seconds. This may be a link to times field in associated FeatureExtraction module."}],"doc":"DEPRECATED Clustered spike data, whether from automatic clustering tools (e.g., klustakwik) or as a result of manual sorting.","default_name":"Clustering","neurodata_type_inc":"NWBDataInterface","neurodata_type_def":"Clustering"}]}B{"groups":[{"datasets":[{"shape":[null],"dims":["num_times"],"dtype":"numeric","name":"data","doc":"Recorded voltage or current.","attributes":[{"name":"unit","doc":"Base unit of measurement for working with the data. Actual stored values are not necessarily stored in these units. To access the data in these units, multiply 'data' by 'conversion'.","dtype":"text"},{"name":"conversion","doc":"Scalar to multiply each element in data to convert it to the specified 'unit'. If the data are stored in acquisition system units or other units that require a conversion to be interpretable, multiply the data by 'conversion' to convert the data to the specified 'unit'. e.g. if the data acquisition system stores values in this object as signed 16-bit integers (int16 range -32,768 to 32,767) that correspond to a 5V range (-2.5V to 2.5V), and the data acquisition system gain is 8000X, then the 'conversion' multiplier to get from raw data acquisition values to recorded volts is 2.5/32768/8000 = 9.5367e-9.","required":false,"dtype":"float32","default_value":1.0},{"name":"resolution","doc":"Smallest meaningful difference between values in data, stored in the specified by unit, 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 -1.0.","required":false,"dtype":"float32","default_value":-1.0}]},{"dtype":"float","name":"gain","doc":"Gain of the recording, in units Volt/Amp (v-clamp) or Volt/Volt (c-clamp).","quantity":"?"}],"links":[{"name":"electrode","doc":"Link to IntracellularElectrode object that describes the electrode that was used to apply or record this data.","target_type":"IntracellularElectrode"}],"doc":"An abstract base class for patch-clamp data - stimulus or response, current or voltage.","neurodata_type_inc":"TimeSeries","neurodata_type_def":"PatchClampSeries","attributes":[{"name":"stimulus_description","doc":"Protocol/stimulus name for this patch-clamp dataset.","dtype":"text"},{"name":"sweep_number","doc":"Sweep number, allows to group different PatchClampSeries together.","required":false,"dtype":"uint64"},{"name":"description","doc":"Description of the time series.","required":false,"dtype":"text","default_value":"no description"},{"name":"comments","doc":"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.","required":false,"dtype":"text","default_value":"no comments"}]},{"datasets":[{"name":"data","doc":"Recorded voltage.","attributes":[{"name":"unit","doc":"Base unit of measurement for working with the data. which is fixed to 'volts'. Actual stored values are not necessarily stored in these units. To access the data in these units, multiply 'data' by 'conversion'.","dtype":"text","value":"volts"},{"name":"conversion","doc":"Scalar to multiply each element in data to convert it to the specified 'unit'. If the data are stored in acquisition system units or other units that require a conversion to be interpretable, multiply the data by 'conversion' to convert the data to the specified 'unit'. e.g. if the data acquisition system stores values in this object as signed 16-bit integers (int16 range -32,768 to 32,767) that correspond to a 5V range (-2.5V to 2.5V), and the data acquisition system gain is 8000X, then the 'conversion' multiplier to get from raw data acquisition values to recorded volts is 2.5/32768/8000 = 9.5367e-9.","required":false,"dtype":"float32","default_value":1.0},{"name":"resolution","doc":"Smallest meaningful difference between values in data, stored in the specified by unit, 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 -1.0.","required":false,"dtype":"float32","default_value":-1.0}]},{"dtype":"float32","name":"bias_current","doc":"Bias current, in amps.","quantity":"?"},{"dtype":"float32","name":"bridge_balance","doc":"Bridge balance, in ohms.","quantity":"?"},{"dtype":"float32","name":"capacitance_compensation","doc":"Capacitance compensation, in farads.","quantity":"?"}],"doc":"Voltage data from an intracellular current-clamp recording. A corresponding CurrentClampStimulusSeries (stored separately as a stimulus) is used to store the current injected.","neurodata_type_inc":"PatchClampSeries","neurodata_type_def":"CurrentClampSeries","attributes":[{"name":"stimulus_description","doc":"Protocol/stimulus name for this patch-clamp dataset.","dtype":"text"},{"name":"sweep_number","doc":"Sweep number, allows to group different PatchClampSeries together.","required":false,"dtype":"uint64"},{"name":"description","doc":"Description of the time series.","required":false,"dtype":"text","default_value":"no description"},{"name":"comments","doc":"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.","required":false,"dtype":"text","default_value":"no comments"}]},{"datasets":[{"dtype":"float32","name":"bias_current","doc":"Bias current, in amps, fixed to 0.0."},{"dtype":"float32","name":"bridge_balance","doc":"Bridge balance, in ohms, fixed to 0.0."},{"dtype":"float32","name":"capacitance_compensation","doc":"Capacitance compensation, in farads, fixed to 0.0."}],"doc":"Voltage data from an intracellular recording when all current and amplifier settings are off (i.e., CurrentClampSeries fields will be zero). There is no CurrentClampStimulusSeries associated with an IZero series because the amplifier is disconnected and no stimulus can reach the cell.","neurodata_type_inc":"CurrentClampSeries","neurodata_type_def":"IZeroClampSeries","attributes":[{"name":"stimulus_description","doc":"Protocol/stimulus name for this patch-clamp dataset.","dtype":"text"},{"name":"sweep_number","doc":"Sweep number, allows to group different PatchClampSeries together.","required":false,"dtype":"uint64"},{"name":"description","doc":"Description of the time series.","required":false,"dtype":"text","default_value":"no description"},{"name":"comments","doc":"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.","required":false,"dtype":"text","default_value":"no comments"}]},{"datasets":[{"name":"data","doc":"Stimulus current applied.","attributes":[{"name":"unit","doc":"Base unit of measurement for working with the data. which is fixed to 'amperes'. Actual stored values are not necessarily stored in these units. To access the data in these units, multiply 'data' by 'conversion'.","dtype":"text","value":"amperes"},{"name":"conversion","doc":"Scalar to multiply each element in data to convert it to the specified 'unit'. If the data are stored in acquisition system units or other units that require a conversion to be interpretable, multiply the data by 'conversion' to convert the data to the specified 'unit'. e.g. if the data acquisition system stores values in this object as signed 16-bit integers (int16 range -32,768 to 32,767) that correspond to a 5V range (-2.5V to 2.5V), and the data acquisition system gain is 8000X, then the 'conversion' multiplier to get from raw data acquisition values to recorded volts is 2.5/32768/8000 = 9.5367e-9.","required":false,"dtype":"float32","default_value":1.0},{"name":"resolution","doc":"Smallest meaningful difference between values in data, stored in the specified by unit, 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 -1.0.","required":false,"dtype":"float32","default_value":-1.0}]}],"doc":"Stimulus current applied during current clamp recording.","neurodata_type_inc":"PatchClampSeries","neurodata_type_def":"CurrentClampStimulusSeries","attributes":[{"name":"stimulus_description","doc":"Protocol/stimulus name for this patch-clamp dataset.","dtype":"text"},{"name":"sweep_number","doc":"Sweep number, allows to group different PatchClampSeries together.","required":false,"dtype":"uint64"},{"name":"description","doc":"Description of the time series.","required":false,"dtype":"text","default_value":"no description"},{"name":"comments","doc":"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.","required":false,"dtype":"text","default_value":"no comments"}]},{"datasets":[{"name":"data","doc":"Recorded current.","attributes":[{"name":"unit","doc":"Base unit of measurement for working with the data. which is fixed to 'amperes'. Actual stored values are not necessarily stored in these units. To access the data in these units, multiply 'data' by 'conversion'.","dtype":"text","value":"amperes"},{"name":"conversion","doc":"Scalar to multiply each element in data to convert it to the specified 'unit'. If the data are stored in acquisition system units or other units that require a conversion to be interpretable, multiply the data by 'conversion' to convert the data to the specified 'unit'. e.g. if the data acquisition system stores values in this object as signed 16-bit integers (int16 range -32,768 to 32,767) that correspond to a 5V range (-2.5V to 2.5V), and the data acquisition system gain is 8000X, then the 'conversion' multiplier to get from raw data acquisition values to recorded volts is 2.5/32768/8000 = 9.5367e-9.","required":false,"dtype":"float32","default_value":1.0},{"name":"resolution","doc":"Smallest meaningful difference between values in data, stored in the specified by unit, 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 -1.0.","required":false,"dtype":"float32","default_value":-1.0}]},{"dtype":"float32","name":"capacitance_fast","doc":"Fast capacitance, in farads.","quantity":"?","attributes":[{"name":"unit","doc":"Unit of measurement for capacitance_fast, which is fixed to 'farads'.","dtype":"text","value":"farads"}]},{"dtype":"float32","name":"capacitance_slow","doc":"Slow capacitance, in farads.","quantity":"?","attributes":[{"name":"unit","doc":"Unit of measurement for capacitance_fast, which is fixed to 'farads'.","dtype":"text","value":"farads"}]},{"dtype":"float32","name":"resistance_comp_bandwidth","doc":"Resistance compensation bandwidth, in hertz.","quantity":"?","attributes":[{"name":"unit","doc":"Unit of measurement for resistance_comp_bandwidth, which is fixed to 'hertz'.","dtype":"text","value":"hertz"}]},{"dtype":"float32","name":"resistance_comp_correction","doc":"Resistance compensation correction, in percent.","quantity":"?","attributes":[{"name":"unit","doc":"Unit of measurement for resistance_comp_correction, which is fixed to 'percent'.","dtype":"text","value":"percent"}]},{"dtype":"float32","name":"resistance_comp_prediction","doc":"Resistance compensation prediction, in percent.","quantity":"?","attributes":[{"name":"unit","doc":"Unit of measurement for resistance_comp_prediction, which is fixed to 'percent'.","dtype":"text","value":"percent"}]},{"dtype":"float32","name":"whole_cell_capacitance_comp","doc":"Whole cell capacitance compensation, in farads.","quantity":"?","attributes":[{"name":"unit","doc":"Unit of measurement for whole_cell_capacitance_comp, which is fixed to 'farads'.","dtype":"text","value":"farads"}]},{"dtype":"float32","name":"whole_cell_series_resistance_comp","doc":"Whole cell series resistance compensation, in ohms.","quantity":"?","attributes":[{"name":"unit","doc":"Unit of measurement for whole_cell_series_resistance_comp, which is fixed to 'ohms'.","dtype":"text","value":"ohms"}]}],"doc":"Current data from an intracellular voltage-clamp recording. A corresponding VoltageClampStimulusSeries (stored separately as a stimulus) is used to store the voltage injected.","neurodata_type_inc":"PatchClampSeries","neurodata_type_def":"VoltageClampSeries","attributes":[{"name":"stimulus_description","doc":"Protocol/stimulus name for this patch-clamp dataset.","dtype":"text"},{"name":"sweep_number","doc":"Sweep number, allows to group different PatchClampSeries together.","required":false,"dtype":"uint64"},{"name":"description","doc":"Description of the time series.","required":false,"dtype":"text","default_value":"no description"},{"name":"comments","doc":"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.","required":false,"dtype":"text","default_value":"no comments"}]},{"datasets":[{"name":"data","doc":"Stimulus voltage applied.","attributes":[{"name":"unit","doc":"Base unit of measurement for working with the data. which is fixed to 'volts'. Actual stored values are not necessarily stored in these units. To access the data in these units, multiply 'data' by 'conversion'.","dtype":"text","value":"volts"},{"name":"conversion","doc":"Scalar to multiply each element in data to convert it to the specified 'unit'. If the data are stored in acquisition system units or other units that require a conversion to be interpretable, multiply the data by 'conversion' to convert the data to the specified 'unit'. e.g. if the data acquisition system stores values in this object as signed 16-bit integers (int16 range -32,768 to 32,767) that correspond to a 5V range (-2.5V to 2.5V), and the data acquisition system gain is 8000X, then the 'conversion' multiplier to get from raw data acquisition values to recorded volts is 2.5/32768/8000 = 9.5367e-9.","required":false,"dtype":"float32","default_value":1.0},{"name":"resolution","doc":"Smallest meaningful difference between values in data, stored in the specified by unit, 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 -1.0.","required":false,"dtype":"float32","default_value":-1.0}]}],"doc":"Stimulus voltage applied during a voltage clamp recording.","neurodata_type_inc":"PatchClampSeries","neurodata_type_def":"VoltageClampStimulusSeries","attributes":[{"name":"stimulus_description","doc":"Protocol/stimulus name for this patch-clamp dataset.","dtype":"text"},{"name":"sweep_number","doc":"Sweep number, allows to group different PatchClampSeries together.","required":false,"dtype":"uint64"},{"name":"description","doc":"Description of the time series.","required":false,"dtype":"text","default_value":"no description"},{"name":"comments","doc":"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.","required":false,"dtype":"text","default_value":"no comments"}]},{"datasets":[{"dtype":"text","name":"description","doc":"Description of electrode (e.g., whole-cell, sharp, etc.)."},{"dtype":"text","name":"filtering","doc":"Electrode specific filtering.","quantity":"?"},{"dtype":"text","name":"initial_access_resistance","doc":"Initial access resistance.","quantity":"?"},{"dtype":"text","name":"location","doc":"Location of the electrode. Specify the area, layer, comments on estimation of area/layer, stereotaxic coordinates if in vivo, etc. Use standard atlas names for anatomical regions when possible.","quantity":"?"},{"dtype":"text","name":"resistance","doc":"Electrode resistance, in ohms.","quantity":"?"},{"dtype":"text","name":"seal","doc":"Information about seal used for recording.","quantity":"?"},{"dtype":"text","name":"slice","doc":"Information about slice used for recording.","quantity":"?"}],"links":[{"name":"device","doc":"Device that was used to record from this electrode.","target_type":"Device"}],"doc":"An intracellular electrode and its metadata.","neurodata_type_inc":"NWBContainer","neurodata_type_def":"IntracellularElectrode"},{"datasets":[{"dtype":"uint64","name":"sweep_number","doc":"Sweep number of the PatchClampSeries in that row.","neurodata_type_inc":"VectorData"},{"dtype":{"target_type":"PatchClampSeries","reftype":"object"},"name":"series","doc":"The PatchClampSeries with the sweep number in that row.","neurodata_type_inc":"VectorData"},{"name":"series_index","doc":"Index for series.","neurodata_type_inc":"VectorIndex"}],"doc":"The table which groups different PatchClampSeries together.","neurodata_type_inc":"DynamicTable","neurodata_type_def":"SweepTable","attributes":[{"name":"colnames","doc":"The names of the columns in this table. This should be used to specify an order to the columns.","dtype":"ascii","shape":[null],"dims":["num_columns"]},{"name":"description","doc":"Description of what is in this dynamic table.","dtype":"text"}]}]},{"groups":[{"datasets":[{"shape":[[2],[3]],"dims":["width|height","width|height|depth"],"dtype":"float32","name":"field_of_view","doc":"Width, height and depth of image, or imaged area, in meters.","quantity":"?"}],"links":[{"name":"imaging_plane","doc":"Link to ImagingPlane object from which this TimeSeries data was generated.","target_type":"ImagingPlane"}],"doc":"Image stack recorded over time from 2-photon microscope.","neurodata_type_inc":"ImageSeries","neurodata_type_def":"TwoPhotonSeries","attributes":[{"name":"pmt_gain","doc":"Photomultiplier gain.","required":false,"dtype":"float32"},{"name":"scan_line_rate","doc":"Lines imaged per second. This is also stored in /general/optophysiology but is kept here as it is useful information for analysis, and so good to be stored w/ the actual data.","required":false,"dtype":"float32"},{"name":"description","doc":"Description of the time series.","required":false,"dtype":"text","default_value":"no description"},{"name":"comments","doc":"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.","required":false,"dtype":"text","default_value":"no comments"}]},{"datasets":[{"shape":[[null],[null,null]],"dims":[["num_times"],["num_times","num_ROIs"]],"dtype":"numeric","name":"data","doc":"Signals from ROIs.","attributes":[{"name":"conversion","doc":"Scalar to multiply each element in data to convert it to the specified 'unit'. If the data are stored in acquisition system units or other units that require a conversion to be interpretable, multiply the data by 'conversion' to convert the data to the specified 'unit'. e.g. if the data acquisition system stores values in this object as signed 16-bit integers (int16 range -32,768 to 32,767) that correspond to a 5V range (-2.5V to 2.5V), and the data acquisition system gain is 8000X, then the 'conversion' multiplier to get from raw data acquisition values to recorded volts is 2.5/32768/8000 = 9.5367e-9.","required":false,"dtype":"float32","default_value":1.0},{"name":"resolution","doc":"Smallest meaningful difference between values in data, stored in the specified by unit, 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 -1.0.","required":false,"dtype":"float32","default_value":-1.0},{"name":"unit","doc":"Base unit of measurement for working with the data. Actual stored values are not necessarily stored in these units. To access the data in these units, multiply 'data' by 'conversion'.","dtype":"text"}]},{"name":"rois","doc":"DynamicTableRegion referencing into an ROITable containing information on the ROIs stored in this timeseries.","neurodata_type_inc":"DynamicTableRegion"}],"doc":"ROI responses over an imaging plane. Each row in data should correspond to the signal from one ROI. Each element on the second dimension of data should correspond to the signal from one ROI.","neurodata_type_inc":"TimeSeries","neurodata_type_def":"RoiResponseSeries","attributes":[{"name":"description","doc":"Description of the time series.","required":false,"dtype":"text","default_value":"no description"},{"name":"comments","doc":"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.","required":false,"dtype":"text","default_value":"no comments"}]},{"groups":[{"doc":"RoiResponseSeries object(s) containing dF/F for a ROI.","quantity":"+","neurodata_type_inc":"RoiResponseSeries"}],"doc":"dF/F information about a region of interest (ROI). Storage hierarchy of dF/F should be the same as for segmentation (i.e., same names for ROIs and for image planes).","default_name":"DfOverF","neurodata_type_inc":"NWBDataInterface","neurodata_type_def":"DfOverF"},{"groups":[{"doc":"RoiResponseSeries object(s) containing fluorescence data for a ROI.","quantity":"+","neurodata_type_inc":"RoiResponseSeries"}],"doc":"Fluorescence information about a region of interest (ROI). Storage hierarchy of fluorescence should be the same as for segmentation (ie, same names for ROIs and for image planes).","default_name":"Fluorescence","neurodata_type_inc":"NWBDataInterface","neurodata_type_def":"Fluorescence"},{"groups":[{"groups":[{"groups":[{"doc":"One or more image stacks that the masks apply to (can be one-element stack).","quantity":"*","neurodata_type_inc":"ImageSeries"}],"name":"reference_images","doc":"Image stacks that the segmentation masks apply to."}],"datasets":[{"shape":[[null,null,null],[null,null,null,null]],"dims":[["num_roi","num_x","num_y"],["num_roi","num_x","num_y","num_z"]],"name":"image_mask","doc":"ROI masks for each ROI. Each image mask is the size of the original imaging plane (or volume) and members of the ROI are finite non-zero.","quantity":"?","neurodata_type_inc":"VectorData"},{"name":"pixel_mask_index","doc":"Index into pixel_mask.","quantity":"?","neurodata_type_inc":"VectorIndex"},{"dtype":[{"doc":"Pixel x-coordinate.","name":"x","dtype":"uint"},{"doc":"Pixel y-coordinate.","name":"y","dtype":"uint"},{"doc":"Weight of the pixel.","name":"weight","dtype":"float"}],"name":"pixel_mask","doc":"Pixel masks for each ROI: a list of indices and weights for the ROI. Pixel masks are concatenated and parsing of this dataset is maintained by the PlaneSegmentation","quantity":"?","neurodata_type_inc":"VectorData"},{"name":"voxel_mask_index","doc":"Index into voxel_mask.","quantity":"?","neurodata_type_inc":"VectorIndex"},{"dtype":[{"doc":"Voxel x-coordinate.","name":"x","dtype":"uint"},{"doc":"Voxel y-coordinate.","name":"y","dtype":"uint"},{"doc":"Voxel z-coordinate.","name":"z","dtype":"uint"},{"doc":"Weight of the voxel.","name":"weight","dtype":"float"}],"name":"voxel_mask","doc":"Voxel masks for each ROI: a list of indices and weights for the ROI. Voxel masks are concatenated and parsing of this dataset is maintained by the PlaneSegmentation","quantity":"?","neurodata_type_inc":"VectorData"},{"shape":[null],"dims":["num_rows"],"dtype":"int","name":"id","doc":"Array of unique identifiers for the rows of this dynamic table.","neurodata_type_inc":"ElementIdentifiers"},{"doc":"Vector columns of this dynamic table.","quantity":"*","neurodata_type_inc":"VectorData"},{"doc":"Indices for the vector columns of this dynamic table.","quantity":"*","neurodata_type_inc":"VectorIndex"}],"links":[{"name":"imaging_plane","doc":"Link to ImagingPlane object from which this data was generated.","target_type":"ImagingPlane"}],"doc":"Results from image segmentation of a specific imaging plane.","quantity":"+","neurodata_type_inc":"DynamicTable","neurodata_type_def":"PlaneSegmentation","attributes":[{"name":"colnames","doc":"The names of the columns in this table. This should be used to specify an order to the columns.","dtype":"ascii","shape":[null],"dims":["num_columns"]},{"name":"description","doc":"Description of what is in this dynamic table.","dtype":"text"}]}],"doc":"Stores pixels in an image that represent different regions of interest (ROIs) or masks. All segmentation for a given imaging plane is stored together, with storage for multiple imaging planes (masks) supported. Each ROI is stored in its own subgroup, with the ROI group containing both a 2D mask and a list of pixels that make up this mask. Segments can also be used for masking neuropil. If segmentation is allowed to change with time, a new imaging plane (or module) is required and ROI names should remain consistent between them.","default_name":"ImageSegmentation","neurodata_type_inc":"NWBDataInterface","neurodata_type_def":"ImageSegmentation"},{"groups":[{"datasets":[{"dtype":"text","name":"description","doc":"Description or other notes about the channel."},{"dtype":"float","name":"emission_lambda","doc":"Emission wavelength for channel, in nm."}],"doc":"An optical channel used to record from an imaging plane.","neurodata_type_inc":"NWBContainer","neurodata_type_def":"OpticalChannel"}],"datasets":[{"dtype":"text","name":"description","doc":"Description of the imaging plane.","quantity":"?"},{"dtype":"float","name":"excitation_lambda","doc":"Excitation wavelength, in nm."},{"dtype":"float","name":"imaging_rate","doc":"Rate that images are acquired, in Hz."},{"dtype":"text","name":"indicator","doc":"Calcium indicator."},{"dtype":"text","name":"location","doc":"Location of the imaging plane. Specify the area, layer, comments on estimation of area/layer, stereotaxic coordinates if in vivo, etc. Use standard atlas names for anatomical regions when possible."},{"shape":[[null,null,3],[null,null,null,3]],"dims":[["height","width","x|y|z"],["height","width","depth","x|y|z"]],"dtype":"float32","name":"manifold","doc":"Physical position of each pixel. 'xyz' represents the position of the pixel relative to the defined coordinate space.","quantity":"?","attributes":[{"name":"conversion","doc":"Scalar to multiply each element in data to convert it to the specified 'unit'. If the data are stored in acquisition system units or other units that require a conversion to be interpretable, multiply the data by 'conversion' to convert the data to the specified 'unit'. e.g. if the data acquisition system stores values in this object as pixels from x = -500 to 499, y = -500 to 499 that correspond to a 2 m x 2 m range, then the 'conversion' multiplier to get from raw data acquisition pixel units to meters is 2/1000.","required":false,"dtype":"float","default_value":1.0},{"name":"unit","doc":"Base unit of measurement for working with the data. The default value is 'meters'.","required":false,"dtype":"text","default_value":"meters"}]},{"dtype":"text","name":"reference_frame","doc":"Describes position and reference frame of manifold based on position of first element in manifold. For example, text description of anatomical location or vectors needed to rotate to common anatomical axis (eg, AP/DV/ML). This field is necessary to interpret manifold. If manifold is not present then this field is not required.","quantity":"?"}],"links":[{"name":"device","doc":"Link to the Device object that was used to record from this electrode.","target_type":"Device"}],"doc":"An imaging plane and its metadata.","quantity":"*","neurodata_type_inc":"NWBContainer","neurodata_type_def":"ImagingPlane"},{"groups":[{"groups":[{"name":"corrected","doc":"Image stack with frames shifted to the common coordinates.","neurodata_type_inc":"ImageSeries"},{"name":"xy_translation","doc":"Stores the x,y delta necessary to align each frame to the common coordinates, for example, to align each frame to a reference image.","neurodata_type_inc":"TimeSeries"}],"links":[{"name":"original","doc":"Link to ImageSeries object that is being registered.","target_type":"ImageSeries"}],"doc":"Reuslts from motion correction of an image stack.","quantity":"+","neurodata_type_inc":"NWBDataInterface","neurodata_type_def":"CorrectedImageStack"}],"doc":"An image stack where all frames are shifted (registered) to a common coordinate system, to account for movement and drift between frames. Note: each frame at each point in time is assumed to be 2-D (has only x & y dimensions).","default_name":"MotionCorrection","neurodata_type_inc":"NWBDataInterface","neurodata_type_def":"MotionCorrection"}]}{"groups":[{"datasets":[{"shape":[null,null],"dims":["num_rows","num_cols"],"dtype":"float32","name":"axis_1_phase_map","doc":"Phase response to stimulus on the first measured axis.","attributes":[{"name":"dimension","doc":"Number of rows and columns in the image. NOTE: row, column representation is equivalent to height,width.","dtype":"int32","shape":[null],"dims":["row_col"]},{"name":"field_of_view","doc":"Size of viewing area, in meters.","dtype":"float","shape":[null],"dims":["row|column"]},{"name":"unit","doc":"Unit that axis data is stored in (e.g., degrees).","dtype":"text"}]},{"shape":[null,null],"dims":["num_rows","num_cols"],"dtype":"float32","name":"axis_1_power_map","doc":"Power response on the first measured axis. Response is scaled so 0.0 is no power in the response and 1.0 is maximum relative power.","quantity":"?","attributes":[{"name":"dimension","doc":"Number of rows and columns in the image. NOTE: row, column representation is equivalent to height,width.","dtype":"int32","shape":[null],"dims":["row_col"]},{"name":"field_of_view","doc":"Size of viewing area, in meters.","dtype":"float","shape":[null],"dims":["row_col"]},{"name":"unit","doc":"Unit that axis data is stored in (e.g., degrees).","dtype":"text"}]},{"shape":[null,null],"dims":["num_rows","num_cols"],"dtype":"float32","name":"axis_2_phase_map","doc":"Phase response to stimulus on the second measured axis.","attributes":[{"name":"dimension","doc":"Number of rows and columns in the image. NOTE: row, column representation is equivalent to height,width.","dtype":"int32","shape":[null],"dims":["row_col"]},{"name":"field_of_view","doc":"Size of viewing area, in meters.","dtype":"float","shape":[null],"dims":["row_col"]},{"name":"unit","doc":"Unit that axis data is stored in (e.g., degrees).","dtype":"text"}]},{"shape":[null,null],"dims":["num_rows","num_cols"],"dtype":"float32","name":"axis_2_power_map","doc":"Power response on the second measured axis. Response is scaled so 0.0 is no power in the response and 1.0 is maximum relative power.","quantity":"?","attributes":[{"name":"dimension","doc":"Number of rows and columns in the image. NOTE: row, column representation is equivalent to height,width.","dtype":"int32","shape":[null],"dims":["row_col"]},{"name":"field_of_view","doc":"Size of viewing area, in meters.","dtype":"float","shape":[null],"dims":["row_col"]},{"name":"unit","doc":"Unit that axis data is stored in (e.g., degrees).","dtype":"text"}]},{"shape":[2],"dims":["names"],"dtype":"text","name":"axis_descriptions","doc":"Two-element array describing the contents of the two response axis fields. Description should be something like ['altitude', 'azimuth'] or '['radius', 'theta']."},{"shape":[null,null],"dims":["num_rows","num_cols"],"dtype":"uint16","name":"focal_depth_image","doc":"Gray-scale image taken with same settings/parameters (e.g., focal depth, wavelength) as data collection. Array format: [rows][columns].","attributes":[{"name":"bits_per_pixel","doc":"Number of bits used to represent each value. This is necessary to determine maximum (white) pixel value.","dtype":"int32"},{"name":"dimension","doc":"Number of rows and columns in the image. NOTE: row, column representation is equivalent to height,width.","dtype":"int32","shape":[null],"dims":["row_col"]},{"name":"field_of_view","doc":"Size of viewing area, in meters.","dtype":"float","shape":[null],"dims":["row_col"]},{"name":"focal_depth","doc":"Focal depth offset, in meters.","dtype":"float"},{"name":"format","doc":"Format of image. Right now only 'raw' is supported.","dtype":"text"}]},{"shape":[null,null],"dims":["num_rows","num_cols"],"dtype":"float32","name":"sign_map","doc":"Sine of the angle between the direction of the gradient in axis_1 and axis_2.","attributes":[{"name":"dimension","doc":"Number of rows and columns in the image. NOTE: row, column representation is equivalent to height,width.","dtype":"int32","shape":[null],"dims":["row_col"]},{"name":"field_of_view","doc":"Size of viewing area, in meters.","dtype":"float","shape":[null],"dims":["row_col"]}]},{"shape":[null,null],"dims":["num_rows","num_cols"],"dtype":"uint16","name":"vasculature_image","doc":"Gray-scale anatomical image of cortical surface. Array structure: [rows][columns]","attributes":[{"name":"bits_per_pixel","doc":"Number of bits used to represent each value. This is necessary to determine maximum (white) pixel value","dtype":"int32"},{"name":"dimension","doc":"Number of rows and columns in the image. NOTE: row, column representation is equivalent to height,width.","dtype":"int32","shape":[null],"dims":["row_col"]},{"name":"field_of_view","doc":"Size of viewing area, in meters.","dtype":"float","shape":[null],"dims":["row_col"]},{"name":"format","doc":"Format of image. Right now only 'raw' is supported.","dtype":"text"}]}],"doc":"Intrinsic signal optical imaging or widefield imaging for measuring retinotopy. Stores orthogonal maps (e.g., altitude/azimuth; radius/theta) of responses to specific stimuli and a combined polarity map from which to identify visual areas. Note: for data consistency, all images and arrays are stored in the format [row][column] and [row, col], which equates to [y][x]. Field of view and dimension arrays may appear backward (i.e., y before x).","default_name":"ImagingRetinotopy","neurodata_type_inc":"NWBDataInterface","neurodata_type_def":"ImagingRetinotopy"}]}q{"namespaces":[{"doc":"NWB namespace","schema":[{"namespace":"hdmf-common"},{"source":"nwb.base"},{"source":"nwb.epoch"},{"source":"nwb.image"},{"source":"nwb.file"},{"source":"nwb.misc"},{"source":"nwb.behavior"},{"source":"nwb.ecephys"},{"source":"nwb.icephys"},{"source":"nwb.ogen"},{"source":"nwb.ophys"},{"source":"nwb.retinotopy"}],"name":"core","full_name":"NWB core","version":"2.1.0","author":["Andrew Tritt","Oliver Ruebel","Ryan Ly","Ben Dichter","Keith Godfrey","Jeff Teeters"],"contact":["ajtritt@lbl.gov","oruebel@lbl.gov","rly@lbl.gov","bdichter@lbl.gov","keithg@alleninstitute.org","jteeters@berkeley.edu"]}]}2pynwb-1.2.1/tests/back_compat/1.0.3_str_experimenter.nwb0000644000655200065520000043134013612200244024472 0ustar circlecicircleci00000000000000HDF  2` TREEH:HEAP`H0 0 .speclocpHhTREEHEAPXPSNOD Hh(Pp P,H0XxPp TREEHEAPX P 0 TREEHEAPXP P TREE(HEAPX(presentationtemplates0TREEHEAPXPSNODhpTREEHEAPXPXxTREE*HEAPXexperimenter@ @help=<=0?#]GCOLone experimenter 2019-11-27T17:32:05.899608-08:00ADDMEADDME 2019-11-27T17:32:05.899608-08:00 2019-11-27T17:32:05.899608-08:00=an NWB:N file for storing cellular-based neurophysiology data2.0.2 core NWBFile  {"groups":[{"datasets":[{"dtype":"float","name":"start_time","doc":"Start time of epoch, in seconds","neurodata_type_inc":"VectorData","attributes":[{"name":"description","doc":"value is 'start time of the epoch, in seconds'","dtype":"text","value":"start time of the epoch, in seconds"}]},{"dtype":"float","name":"stop_time","doc":"Stop time of epoch, in seconds","neurodata_type_inc":"VectorData","attributes":[{"name":"description","doc":"value is 'stop time of the epoch, in seconds'","dtype":"text","value":"stop time of the epoch, in seconds"}]},{"dtype":"text","name":"tags","doc":"User-defined tags that identify events. Tags are to help identify or categorize events.","quantity":"?","neurodata_type_inc":"VectorData","attributes":[{"name":"description","doc":"value is 'user-defined tags'","dtype":"text","value":"user-defined tags"}]},{"name":"tags_index","doc":"Index for tags","quantity":"?","neurodata_type_inc":"VectorIndex"},{"dtype":[{"doc":"Start index into the TimeSeries data[] field. COMMENT: This can be used to calculate location in TimeSeries timestamp[] field","name":"idx_start","dtype":"int32"},{"doc":"Number of data samples available in this time series, during this epoch.","name":"count","dtype":"int32"},{"doc":"the TimeSeries that this index applies to","name":"timeseries","dtype":{"target_type":"TimeSeries","reftype":"object"}}],"name":"timeseries","doc":"An index into a TimeSeries object","quantity":"?","neurodata_type_inc":"VectorData","attributes":[{"name":"help","doc":"Value is 'Data on how an epoch applies to a time series'","dtype":"text","value":"Data on how an epoch applies to a time series"}]},{"name":"timeseries_index","doc":"Index for timeseries","quantity":"?","neurodata_type_inc":"VectorIndex"}],"doc":"A container for aggregating epoch data and the TimeSeries that each epoch applies to","neurodata_type_inc":"DynamicTable","neurodata_type_def":"TimeIntervals","attributes":[{"name":"help","doc":"Value is 'A general epoch object'","dtype":"text","value":"A general epoch object"},{"name":"colnames","doc":"The names of the columns in this table. This should be used to specifying an order to the columns","dtype":"ascii","shape":[null],"dims":["num_columns"]},{"name":"description","doc":"Description of what is in this dynamic table","dtype":"text"}]}]}`SNOD2#]x2#]2#]2#]acquisitionanalysisprocessingstimulusgeneralfile_create_dateidentifiersession_descriptionsession_start_timetimestamps_reference_timespecifications3#]   *H  &{B{-{{5@V#8@VS {]1@V@VU@VSNODh-(  0 x(.8/p=0?8  1 H nwb_version H namespace Hneurodata_type PTREEhBHEAPXP?coreH?ATREEpFHEAPXB2.0.2HSNOD??ACETREEspQHEAP`ySNODCCE3#]GCOL8**{"datasets":[{"doc":"An abstract data type for a dataset","neurodata_type_def":"NWBData","attributes":[{"name":"help","doc":"Short description of what this type of Interface contains.","dtype":"text"}]},{"doc":"Pointers that index data values","neurodata_type_inc":"NWBData","neurodata_type_def":"Index","attributes":[{"name":"help","doc":"a help string","dtype":"text","value":"indexes into a list of values for a list of elements"},{"name":"target","doc":"the target dataset that this index applies to","dtype":{"target_type":"NWBData","reftype":"object"}}]},{"doc":"Data values indexed by pointer","neurodata_type_inc":"NWBData","neurodata_type_def":"VectorData","attributes":[{"name":"help","doc":"a help string","dtype":"text","value":"Values for a list of elements"},{"name":"description","doc":"A short description of what these vectors are","dtype":"text"}]},{"doc":"Pointers that index data values","neurodata_type_inc":"Index","neurodata_type_def":"VectorIndex","attributes":[{"name":"target","doc":"the target dataset that this index applies to","dtype":{"target_type":"VectorData","reftype":"object"}},{"name":"help","doc":"a help string","dtype":"text","value":"indexes into a list of values for a list of elements"}]},{"shape":[null],"dims":["num_elements"],"dtype":"int","doc":"a unique identifier for each element","default_name":"element_id","neurodata_type_inc":"NWBData","neurodata_type_def":"ElementIdentifiers","attributes":[{"name":"help","doc":"a help string","dtype":"text","value":"unique identifiers for a list of elements"}]},{"dtype":"int","doc":"a region/index into a DynamicTable","neurodata_type_inc":"VectorData","neurodata_type_def":"DynamicTableRegion","attributes":[{"name":"help","doc":"value is 'a subset (i.e. slice or region) of a DynamicTable'","dtype":"text","value":"a subset (i.e. slice or region) of a DynamicTable"},{"name":"table","doc":"a reference to the DynamicTable this region applies to","dtype":{"target_type":"DynamicTable","reftype":"object"}},{"name":"description","doc":"Description of what this table region points to","dtype":"text"}]},{"shape":[[null,null],[null,null,3],[null,null,4]],"dims":[["num_x","num_y"],["num_x","num_y","(r, g, b)"],["num_x","num_y","(r, g, b, a)"]],"doc":"Image base type.","neurodata_type_inc":"NWBData","neurodata_type_def":"Image","attributes":[{"name":"help","doc":"base image (use GrayscaleImage, RGBImage, RGBAImage, etc.)","dtype":"text"},{"name":"resolution","doc":"pixels / cm","required":false,"dtype":"float"},{"name":"description","doc":"description of image","required":false,"dtype":"text"}]}],"groups":[{"doc":"An abstract data type for a generic container storing collections of data and metadata. Base type for all data and metadata containers.","neurodata_type_def":"NWBContainer","attributes":[{"name":"help","doc":"Short description of what this type of NWBContainer contains.","dtype":"text"}]},{"doc":"An abstract data type for a generic container storing collections of data, as opposed to metadata.","neurodata_type_inc":"NWBContainer","neurodata_type_def":"NWBDataInterface","attributes":[{"name":"help","doc":"Short description of what this type of NWBContainer contains.","dtype":"text"}]},{"groups":[{"name":"sync","doc":"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.","quantity":"?"}],"datasets":[{"shape":[null],"dims":["num_times"],"dtype":"uint8","name":"control","doc":"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[].","quantity":"?"},{"shape":[null],"dims":["num_control_values"],"dtype":"text","name":"control_description","doc":"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.","quantity":"?"},{"shape":[[null],[null,null],[null,null,null],[null,null,null,null]],"dims":[["num_times"],["num_times","num_DIM2"],["num_times","num_DIM2","num_DIM3"],["num_times","num_DIM2","num_DIM3","num_DIM4"]],"name":"data","doc":"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":[{"name":"conversion","doc":"Scalar to multiply each element in data to convert it to the specified unit","required":false,"dtype":"float32","default_value":1.0},{"name":"resolution","doc":"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 -1.0","required":false,"dtype":"float32","default_value":0.0},{"name":"unit","doc":"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.","dtype":"text"}]},{"dtype":"float64","name":"starting_time","doc":"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.","quantity":"?","attributes":[{"name":"rate","doc":"Sampling rate, in Hz COMMENT: Rate information is stored in Hz","dtype":"float32"},{"name":"unit","doc":"Value is 'Seconds'","dtype":"text","value":"Seconds"}]},{"shape":[null],"dims":["num_times"],"dtype":"float64","name":"timestamps","doc":"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.","quantity":"?","attributes":[{"name":"interval","doc":"Value is '1'","dtype":"int32","value":1},{"name":"unit","doc":"Value is 'Seconds'","dtype":"text","value":"Seconds"}]}],"doc":"General purpose time series.","neurodata_type_inc":"NWBDataInterface","neurodata_type_def":"TimeSeries","attributes":[{"name":"comments","doc":"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.","required":false,"dtype":"text","default_value":"no comments"},{"name":"description","doc":"Description of TimeSeries","required":false,"dtype":"text","default_value":"no description"},{"name":"help","doc":"Value is 'General time series object'","dtype":"text","value":"General time series object"}]},{"groups":[{"doc":"Interface objects containing data output from processing steps","quantity":"*","neurodata_type_inc":"NWBDataInterface"}],"doc":"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.","neurodata_type_inc":"NWBContainer","neurodata_type_def":"ProcessingModule","attributes":[{"name":"description","doc":"Description of Module","dtype":"text"},{"name":"help","doc":"Value is 'A collection of analysis outputs from processing of data'","dtype":"text","value":"A collection of analysis outputs from processing of data"}]},{"datasets":[{"doc":"Images stored in this NWBDataInterface","quantity":"+","neurodata_type_inc":"Image"}],"doc":"A NWBDataInterface for storing images that have some relationship","default_name":"Images","neurodata_type_inc":"NWBDataInterface","neurodata_type_def":"Images","attributes":[{"name":"description","doc":"Description of images in this container","dtype":"text"},{"name":"help","doc":"Value is 'A collection of images that have some meaningful relationship'","dtype":"text","value":"A collection of images that have some meaningful relationship"}]},{"datasets":[{"shape":[null],"dims":["num_rows"],"dtype":"int","name":"id","doc":"The unique identifier for the rows in this dynamic table","neurodata_type_inc":"ElementIdentifiers"},{"doc":"The vector columns in this dynamic table","quantity":"*","neurodata_type_inc":"VectorData"},{"doc":"The indices for the vector columns in this dynamic table","quantity":"*","neurodata_type_inc":"VectorIndex"}],"doc":"A group containing multiple datasets that are aligned on the first dimension (Currently, this requirement if left up to APIs to check and enforce). Apart from a column that contains unique identifiers for each row there are no other required datasets. Users are free to add any number of VectorData objects here. Table functionality is already supported through compound types, which is analogous to storing an array-of-structs. DynamicTable can be thought of as a struct-of-arrays. This provides an alternative structure to choose from when optimizing storage for anticipated access patterns. Additionally, this type provides a way of creating a table without having to define a compound type up front. Although this convenience may be attractive, users should think carefully about how data will be accessed. DynamicTable is more appropriate for column-centric access, whereas a dataset with a compound type would be more appropriate for row-centric access. Finally, data size should also be taken into account. For small tables, performance loss may be an acceptable trade-off for the flexibility of a DynamicTable. For example, DynamicTable was originally developed for storing trial data and spike unit metadata. Both of these use cases are expected to produce relatively small tables, so the spatial locality of multiple datasets present in a DynamicTable is not expected to have a significant performance impact. Additionally, requirements of trial and unit metadata tables are sufficiently diverse that performance implications can be overlooked in favor of usability.","neurodata_type_inc":"NWBDataInterface","neurodata_type_def":"DynamicTable","attributes":[{"name":"help","doc":"Value is 'A column-centric table'","dtype":"text","value":"A column-centric table"},{"name":"colnames","doc":"The names of the columns in this table. This should be used to specifying an order to the columns","dtype":"ascii","shape":[null],"dims":["num_columns"]},{"name":"description","doc":"Description of what is in this dynamic table","dtype":"text"}]}]}SNODTGXxh@NHt 3#]03#]@3#]P3#]`3#]nwb.basenwb.epochnwb.imagenwb.filenwb.miscnwb.behaviornwb.ecephysnwb.icephysnwb.ogennwb.ophysnwb.retinotopynamespaceGCOL@&{"datasets":[{"shape":[null,null],"dims":["y","x"],"doc":"Grayscale image","neurodata_type_inc":"Image","neurodata_type_def":"GrayscaleImage","attributes":[{"name":"help","doc":"base image (use GrayscaleImage, RGBImage, RGBAImage, etc.)","dtype":"text"},{"name":"resolution","doc":"pixels / cm","required":false,"dtype":"float"},{"name":"description","doc":"description of image","required":false,"dtype":"text"}]},{"shape":[null,null,3],"dims":["y","x","R,G,B"],"doc":"Color image","neurodata_type_inc":"Image","neurodata_type_def":"RGBImage","attributes":[{"name":"help","doc":"base image (use GrayscaleImage, RGBImage, RGBAImage, etc.)","dtype":"text"},{"name":"resolution","doc":"pixels / cm","required":false,"dtype":"float"},{"name":"description","doc":"description of image","required":false,"dtype":"text"}]},{"shape":[null,null,4],"dims":["y","x","R,G,B,A"],"doc":"Color image with transparency","neurodata_type_inc":"Image","neurodata_type_def":"RGBAImage","attributes":[{"name":"help","doc":"base image (use GrayscaleImage, RGBImage, RGBAImage, etc.)","dtype":"text"},{"name":"resolution","doc":"pixels / cm","required":false,"dtype":"float"},{"name":"description","doc":"description of image","required":false,"dtype":"text"}]}],"groups":[{"datasets":[{"shape":[[null,null,null],[null,null,null,null]],"dims":[["frame","y","x"],["frame","z","y","x"]],"dtype":"numeric","name":"data","doc":"Either binary data containing image or empty.","quantity":"?","attributes":[{"name":"conversion","doc":"Scalar to multiply each element in data to convert it to the specified unit","required":false,"dtype":"float32","default_value":1.0},{"name":"resolution","doc":"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 -1.0","required":false,"dtype":"float32","default_value":0.0},{"name":"unit","doc":"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.","dtype":"text"}]},{"shape":[null],"dims":["rank"],"dtype":"int32","name":"dimension","doc":"Number of pixels on x, y, (and z) axes.","quantity":"?"},{"shape":[null],"dims":["num_files"],"dtype":"text","name":"external_file","doc":"Path or URL to one or more external file(s). Field only present if format=external. NOTE: this is only relevant if the image is stored in the file system as one or more image file(s). This field should NOT be used if the image is stored in another HDF5 file and that file is HDF5 linked to this file.","quantity":"?","attributes":[{"name":"starting_frame","doc":"Each entry is the frame number (within the full ImageSeries) of the first frame in the corresponding external_file entry. This serves as an index to what frames each file contains, allowing random access.Zero-based indexing is used. (The first element will always be zero).","dtype":"int","shape":[null],"dims":["num_files"]}]},{"dtype":"text","name":"format","doc":"Format of image. If this is 'external' then the field external_file contains the path or URL information to that file. For tiff, png, jpg, etc, the binary representation of the image is stored in data. If the format is raw then the fields bit_per_pixel and dimension are used. For raw images, only a single channel is stored (eg, red).","quantity":"?"}],"doc":"General image data that is common between acquisition and stimulus time series. Sometimes the image data is stored in the HDF5 file in a raw format while other times it will be stored as an external image file in the host file system. The data field will either be binary data or empty. TimeSeries::data array structure: [frame] [y][x] or [frame][z][y][x].","neurodata_type_inc":"TimeSeries","neurodata_type_def":"ImageSeries","attributes":[{"name":"help","doc":"Value is 'Storage object for time-series 2-D image data'","dtype":"text","value":"Storage object for time-series 2-D image data"},{"name":"comments","doc":"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.","required":false,"dtype":"text","default_value":"no comments"},{"name":"description","doc":"Description of TimeSeries","required":false,"dtype":"text","default_value":"no description"}]},{"links":[{"name":"masked_imageseries","doc":"Link to ImageSeries that mask is applied to.","target_type":"ImageSeries"}],"doc":"An alpha mask that is applied to a presented visual stimulus. The data[] array contains an array of mask values that are applied to the displayed image. Mask values are stored as RGBA. Mask can vary with time. The timestamps array indicates the starting time of a mask, and that mask pattern continues until it's explicitly changed.","neurodata_type_inc":"ImageSeries","neurodata_type_def":"ImageMaskSeries","attributes":[{"name":"help","doc":"Value is 'An alpha mask that is applied to a presented visual stimulus'","dtype":"text","value":"An alpha mask that is applied to a presented visual stimulus"},{"name":"comments","doc":"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.","required":false,"dtype":"text","default_value":"no comments"},{"name":"description","doc":"Description of TimeSeries","required":false,"dtype":"text","default_value":"no description"}]},{"datasets":[{"dtype":"float32","name":"distance","doc":"Distance from camera/monitor to target/eye.","quantity":"?"},{"shape":[[2],[3]],"dims":[["width|height"],["width|height|depth"]],"dtype":"float32","name":"field_of_view","doc":"Width, height and depth of image, or imaged area (meters).","quantity":"?"},{"dtype":"text","name":"orientation","doc":"Description of image relative to some reference frame (e.g., which way is up). Must also specify frame of reference.","quantity":"?"}],"doc":"Image data that is presented or recorded. A stimulus template movie will be stored only as an image. When the image is presented as stimulus, additional data is required, such as field of view (eg, how much of the visual field the image covers, or how what is the area of the target being imaged). If the OpticalSeries represents acquired imaging data, orientation is also important.","neurodata_type_inc":"ImageSeries","neurodata_type_def":"OpticalSeries","attributes":[{"name":"help","doc":"Value is 'Time-series image stack for optical recording or stimulus'","dtype":"text","value":"Time-series image stack for optical recording or stimulus"},{"name":"comments","doc":"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.","required":false,"dtype":"text","default_value":"no comments"},{"name":"description","doc":"Description of TimeSeries","required":false,"dtype":"text","default_value":"no description"}]},{"datasets":[{"shape":[null],"dims":["num_times"],"dtype":"int","name":"data","doc":"Index of the frame in the referenced ImageSeries.","attributes":[{"name":"conversion","doc":"Scalar to multiply each element in data to convert it to the specified unit","required":false,"dtype":"float32","default_value":1.0},{"name":"resolution","doc":"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 -1.0","required":false,"dtype":"float32","default_value":0.0},{"name":"unit","doc":"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.","dtype":"text"}]}],"links":[{"name":"indexed_timeseries","doc":"HDF5 link to TimeSeries containing images that are indexed.","target_type":"ImageSeries"}],"doc":"Stores indices to image frames stored in an ImageSeries. The purpose of the ImageIndexSeries 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 ImageSeries, and the timestamps array indicates when that image was displayed.","neurodata_type_inc":"TimeSeries","neurodata_type_def":"IndexSeries","attributes":[{"name":"help","doc":"Value is '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'","dtype":"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"},{"name":"comments","doc":"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.","required":false,"dtype":"text","default_value":"no comments"},{"name":"description","doc":"Description of TimeSeries","required":false,"dtype":"text","default_value":"no description"}]}]}B{"groups":[{"groups":[{"groups":[{"doc":"Any objects representing acquired data","quantity":"*","neurodata_type_inc":"NWBDataInterface"}],"name":"acquisition","doc":"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."},{"groups":[{"doc":"Custom analysis results","quantity":"*","neurodata_type_inc":"NWBContainer"}],"name":"analysis","doc":"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 could be shared with other labs."},{"groups":[{"doc":"Intermediate analysis of acquired data","quantity":"*","neurodata_type_inc":"ProcessingModule"}],"name":"processing","doc":"The home for ProcessingModules. 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."},{"groups":[{"groups":[{"doc":"TimeSeries objects containing data of presented stimuli","quantity":"*","neurodata_type_inc":"TimeSeries"}],"name":"presentation","doc":"Stimuli presented during the experiment."},{"groups":[{"doc":"TimeSeries objects containing template data of presented stimuli","quantity":"*","neurodata_type_inc":"TimeSeries"}],"name":"templates","doc":"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."}],"name":"stimulus","doc":"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."},{"groups":[{"doc":"place-holder than can be extended so that lab-specific meta-data can be placed in /general","quantity":"*","neurodata_type_inc":"NWBContainer","neurodata_type_def":"LabMetaData","attributes":[{"name":"help","doc":"Short description of what this type of NWBContainer contains.","dtype":"text"}]},{"groups":[{"doc":"One of possibly many. Information about device and device description.","quantity":"+","neurodata_type_inc":"NWBContainer","neurodata_type_def":"Device","attributes":[{"name":"help","doc":"Value is 'A recording device e.g. amplifier'.","dtype":"text","value":"A recording device e.g. amplifier"}]}],"name":"devices","doc":"Description of hardware devices used during experiment. COMMENT: Eg, monitors, ADC boards, microscopes, etc","quantity":"?"},{"datasets":[{"dtype":"text","name":"age","doc":"Age of subject","quantity":"?"},{"dtype":"isodatetime","name":"date_of_birth","doc":"can be supplied instead of age","quantity":"?"},{"dtype":"text","name":"description","doc":"Description of subject and where subject came from (e.g., breeder, if animal).","quantity":"?"},{"dtype":"text","name":"genotype","doc":"Genetic strain COMMENT: If absent, assume Wild Type (WT)","quantity":"?"},{"dtype":"text","name":"sex","doc":"Gender of subject","quantity":"?"},{"dtype":"text","name":"species","doc":"Species of subject","quantity":"?"},{"dtype":"text","name":"subject_id","doc":"ID of animal/person used/participating in experiment (lab convention)","quantity":"?"},{"dtype":"text","name":"weight","doc":"Weight at time of experiment, at time of surgery and at other important times","quantity":"?"}],"name":"subject","doc":"Information about the animal or person from which the data was measured.","quantity":"?","neurodata_type_inc":"NWBContainer","neurodata_type_def":"Subject","attributes":[{"name":"help","doc":"Value is 'Information about the subject'","dtype":"text","value":"Information about the subject"}]},{"groups":[{"doc":"One of possibly many groups, one for each electrode group.","quantity":"*","neurodata_type_inc":"ElectrodeGroup"},{"datasets":[{"dtype":"float","name":"x","doc":"the x coordinate of the channel location","neurodata_type_inc":"VectorData","attributes":[{"name":"description","doc":"value is 'the x coordinate of the channel location'","dtype":"text","value":"the x coordinate of the channel location"}]},{"dtype":"float","name":"y","doc":"the y coordinate of the channel location","neurodata_type_inc":"VectorData","attributes":[{"name":"description","doc":"value is 'the y coordinate of the channel location'","dtype":"text","value":"the y coordinate of the channel location"}]},{"dtype":"float","name":"z","doc":"the z coordinate of the channel location","neurodata_type_inc":"VectorData","attributes":[{"name":"description","doc":"value is 'the z coordinate of the channel location'","dtype":"text","value":"the z coordinate of the channel location"}]},{"dtype":"float","name":"imp","doc":"the impedance of the channel","neurodata_type_inc":"VectorData","attributes":[{"name":"description","doc":"value is 'the impedance of the channel'","dtype":"text","value":"the impedance of the channel"}]},{"dtype":"ascii","name":"location","doc":"the location of channel within the subject e.g. brain region","neurodata_type_inc":"VectorData","attributes":[{"name":"description","doc":"value is 'the location of channel within the subject e.g. brain region'","dtype":"text","value":"the location of channel within the subject e.g. brain region"}]},{"dtype":"float","name":"filtering","doc":"description of hardware filtering","neurodata_type_inc":"VectorData","attributes":[{"name":"description","doc":"value is 'description of hardware filtering'","dtype":"text","value":"description of hardware filtering"}]},{"dtype":{"target_type":"ElectrodeGroup","reftype":"object"},"name":"group","doc":"a reference to the ElectrodeGroup this electrode is a part of","neurodata_type_inc":"VectorData","attributes":[{"name":"description","doc":"value is 'a reference to the ElectrodeGroup this electrode is a part of'","dtype":"text","value":"a reference to the ElectrodeGroup this electrode is a part of"}]},{"dtype":"ascii","name":"group_name","doc":"name of the ElectrodeGroup this electrode is a part of","neurodata_type_inc":"VectorData","attributes":[{"name":"description","doc":"value is 'the name of the ElectrodeGroup this electrode is a part of'","dtype":"text","value":"the name of the ElectrodeGroup this electrode is a part of"}]}],"name":"electrodes","doc":"A table of all electrodes (i.e. channels) used for recording.","quantity":"?","neurodata_type_inc":"DynamicTable"}],"name":"extracellular_ephys","doc":"Metadata related to extracellular electrophysiology.","quantity":"?"},{"groups":[{"doc":"One of possibly many. COMMENT: Name should be informative.","quantity":"*","neurodata_type_inc":"IntracellularElectrode"},{"name":"sweep_table","doc":"The table which groups different PatchClampSeries together.","quantity":"?","neurodata_type_inc":"SweepTable"}],"datasets":[{"dtype":"text","name":"filtering","doc":"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.","quantity":"?"}],"name":"intracellular_ephys","doc":"Metadata related to intracellular electrophysiology","quantity":"?"},{"groups":[{"doc":"One of possibly many groups describing an optogenetic stimulation site. COMMENT: Name is arbitrary but should be meaningful. Name is referenced by OptogeneticSeries.","quantity":"*","neurodata_type_inc":"OptogeneticStimulusSite"}],"name":"optogenetics","doc":"Metadata describing optogenetic stimuluation","quantity":"?"},{"groups":[{"doc":"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.","quantity":"*","neurodata_type_inc":"ImagingPlane"}],"name":"optophysiology","doc":"Metadata related to optophysiology.","quantity":"?"}],"datasets":[{"dtype":"text","name":"data_collection","doc":"Notes about data collection and analysis.COMMENT: Can be from Methods","quantity":"?"},{"dtype":"text","name":"experiment_description","doc":"General description of the experiment.COMMENT: Can be from Methods","quantity":"?"},{"dtype":"text","name":"experimenter","doc":"Name of person who performed the experiment.COMMENT: More than one person OK. Can specify roles of different people involved.","quantity":"?"},{"dtype":"text","name":"institution","doc":"Institution(s) where experiment was performed","quantity":"?"},{"shape":[null],"dims":["num_keywords"],"dtype":"text","name":"keywords","doc":"Terms to search over","quantity":"?"},{"dtype":"text","name":"lab","doc":"Lab where experiment was performed","quantity":"?"},{"dtype":"text","name":"notes","doc":"Notes about the experiment. COMMENT: Things particular to this experiment","quantity":"?"},{"dtype":"text","name":"pharmacology","doc":"Description of drugs used, including how and when they were administered. COMMENT: Anesthesia(s), painkiller(s), etc., plus dosage, concentration, etc.","quantity":"?"},{"dtype":"text","name":"protocol","doc":"Experimental protocol, if applicable. COMMENT: E.g., include IACUC protocol.","quantity":"?"},{"dtype":"text","name":"related_publications","doc":"Publication information. COMMENT: PMID, DOI, URL, etc. If multiple, concatenate together and describe which is which. such as PMID, DOI, URL, etc","quantity":"?"},{"dtype":"text","name":"session_id","doc":"Lab-specific ID for the session.COMMENT: Only 1 session_id per file, with all time aligned to experiment start time.","quantity":"?"},{"dtype":"text","name":"slices","doc":"Description of slices, including information about preparation thickness, orientation, temperature and bath solution","quantity":"?"},{"dtype":"text","name":"source_script","doc":"Script file used to create this NWB file.","quantity":"?","attributes":[{"name":"file_name","doc":"Name of script file","dtype":"text"}]},{"dtype":"text","name":"stimulus","doc":"Notes about stimuli, such as how and where presented. COMMENT: Can be from Methods.","quantity":"?"},{"dtype":"text","name":"surgery","doc":"Narrative description about surgery/surgeries, including date(s) and who performed surgery. COMMENT: Much can be copied from Methods.","quantity":"?"},{"dtype":"text","name":"virus","doc":"Information about virus(es) used in experiments, including virus ID, source, date made, injection location, volume, etc.","quantity":"?"}],"name":"general","doc":"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 (e.g., 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. 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."},{"groups":[{"name":"epochs","doc":"divisions in time marking experimental stages or sub-divisions of a single recording session","quantity":"?","neurodata_type_inc":"TimeIntervals"},{"name":"trials","doc":"repeated experimental events that have a logical grouping","quantity":"?","neurodata_type_inc":"TimeIntervals"},{"name":"invalid_times","doc":"time intervals that should be removed from analysis","quantity":"?","neurodata_type_inc":"TimeIntervals"},{"doc":"an optional additional table for describing other experimental time intervals","quantity":"*","neurodata_type_inc":"TimeIntervals"}],"name":"intervals","doc":"Experimental intervals, whether that be logically distinct sub-experiments having a particular scientific goal, trials (see trials subgroup) during an experiment, or epochs (see epochs subgroup) deriving from analysis of data.","quantity":"?"},{"name":"units","doc":"Data about units","quantity":"?","neurodata_type_inc":"Units"}],"datasets":[{"shape":[null],"dims":["num_modifications"],"dtype":"isodatetime","name":"file_create_date","doc":"A record of the date the file was created and of subsequent modifications. COMMENT: - The date is stored in UTC with local timezone offset as ISO 8601 extended formatted strings: 2018-09-28T14:43:54.123+02:00 - Dates stored in UTC end in \"Z\" with no timezone offset. - Date accuracy is up to milliseconds. - The file can be created after the experiment was run, so this may differ from the experiment start time. - Each modification to the nwb file adds a new entry to the array."},{"dtype":"text","name":"identifier","doc":"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."},{"dtype":"text","name":"session_description","doc":"One or two sentences describing the experiment and data in the file."},{"dtype":"isodatetime","name":"session_start_time","doc":"Date and time of the experiment/session start. COMMENT: - The date is stored in UTC with local timezone offset as ISO 8601 extended formatted string: 2018-09-28T14:43:54.123+02:00 - Dates stored in UTC end in \"Z\" with no timezone offset. - Date accuracy is up to milliseconds."},{"dtype":"isodatetime","name":"timestamps_reference_time","doc":"Date and time corresponding to time zero of all timestamps. COMMENT: - The date is stored in UTC with local timezone offset as ISO 8601 extended formatted string: 2018-09-28T14:43:54.123+02:00 - Dates stored in UTC end in \"Z\" with no timezone offset. - Date accuracy is up to milliseconds. - All times stored in the file use this time as reference (ie, time zero)."}],"name":"root","doc":"Top level of NWB file.","neurodata_type_inc":"NWBContainer","neurodata_type_def":"NWBFile","attributes":[{"name":"help","doc":"Value is 'an NWB:N file for storing cellular-based neurophysiology data'","dtype":"text","value":"an NWB:N file for storing cellular-based neurophysiology data"},{"name":"nwb_version","doc":"File version string. COMMENT: Eg, NWB-1.0.0. This will be the name of the format with trailing major, minor and patch numbers.","dtype":"text","value":"2.0.2"}]}]}-{"groups":[{"datasets":[{"shape":[[null],[null,null]],"dims":[["num_times"],["num_times","num_features"]],"dtype":"numeric","name":"data","doc":"Values of each feature at each time.","attributes":[{"name":"unit","doc":"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.","required":false,"dtype":"text","default_value":"see 'feature_units'"},{"name":"conversion","doc":"Scalar to multiply each element in data to convert it to the specified unit","required":false,"dtype":"float32","default_value":1.0},{"name":"resolution","doc":"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 -1.0","required":false,"dtype":"float32","default_value":0.0}]},{"shape":[null],"dims":["num_features"],"dtype":"text","name":"feature_units","doc":"Units of each feature.","quantity":"?"},{"shape":[null],"dims":["num_features"],"dtype":"text","name":"features","doc":"Description of the features represented in TimeSeries::data."}],"doc":"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.","neurodata_type_inc":"TimeSeries","neurodata_type_def":"AbstractFeatureSeries","attributes":[{"name":"help","doc":"Value is 'Features of an applied stimulus. This is useful when storing the raw stimulus is impractical'","dtype":"text","value":"Features of an applied stimulus. This is useful when storing the raw stimulus is impractical"},{"name":"comments","doc":"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.","required":false,"dtype":"text","default_value":"no comments"},{"name":"description","doc":"Description of TimeSeries","required":false,"dtype":"text","default_value":"no description"}]},{"datasets":[{"shape":[null],"dims":["num_times"],"dtype":"text","name":"data","doc":"Annotations made during an experiment.","attributes":[{"name":"resolution","doc":"Value is -1.0","dtype":"float","value":-1.0},{"name":"unit","doc":"Value is 'n/a'","dtype":"text","value":"n/a"},{"name":"conversion","doc":"Scalar to multiply each element in data to convert it to the specified unit","required":false,"dtype":"float32","default_value":1.0}]}],"doc":"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.","neurodata_type_inc":"TimeSeries","neurodata_type_def":"AnnotationSeries","attributes":[{"name":"help","doc":"Value is 'Time-stamped annotations about an experiment'","dtype":"text","value":"Time-stamped annotations about an experiment"},{"name":"comments","doc":"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.","required":false,"dtype":"text","default_value":"no comments"},{"name":"description","doc":"Description of TimeSeries","required":false,"dtype":"text","default_value":"no description"}]},{"datasets":[{"shape":[null],"dims":["num_times"],"dtype":"int8","name":"data","doc":">0 if interval started, <0 if interval ended.","attributes":[{"name":"resolution","doc":"Value is -1.0","dtype":"float","value":-1.0},{"name":"unit","doc":"Value is 'n/a'","dtype":"text","value":"n/a"},{"name":"conversion","doc":"Scalar to multiply each element in data to convert it to the specified unit","required":false,"dtype":"float32","default_value":1.0}]}],"doc":"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.","neurodata_type_inc":"TimeSeries","neurodata_type_def":"IntervalSeries","attributes":[{"name":"help","doc":"Value is 'Stores the start and stop times for events'","dtype":"text","value":"Stores the start and stop times for events"},{"name":"comments","doc":"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.","required":false,"dtype":"text","default_value":"no comments"},{"name":"description","doc":"Description of TimeSeries","required":false,"dtype":"text","default_value":"no description"}]},{"groups":[{"datasets":[{"dtype":"text","name":"band_name","doc":"the name of the band e.g. theta","neurodata_type_inc":"VectorData","attributes":[{"name":"description","doc":"value is 'the name of the band e.g. theta'","dtype":"text","value":"the name of the band e.g. theta"}]},{"shape":[null,2],"dims":["num_bands","low, high"],"dtype":"float","name":"band_limits","doc":"Low and high limit of each band in Hz. If it is a Gaussian filter, use 2 SD on either side of the center","neurodata_type_inc":"VectorData","attributes":[{"name":"description","doc":"value is 'Low and high limit of each band in Hz. If it is a Gaussian filter, use 2 SD on either side of the center'","dtype":"text","value":"Low and high limit of each band in Hz. If it is a Gaussian filter, use 2 SD on either side of the center"}]},{"shape":[null],"dims":["num_bands"],"dtype":"float","name":"band_mean","doc":"The mean Gaussian filters in Hz","neurodata_type_inc":"VectorData","attributes":[{"name":"description","doc":"The mean Gaussian filters in Hz","dtype":"text","value":"The mean Gaussian filters in Hz"}]},{"shape":[null],"dims":["num_bands"],"dtype":"float","name":"band_stdev","doc":"The standard devaition of Gaussian filters in Hz","neurodata_type_inc":"VectorData","attributes":[{"name":"description","doc":"The standard devaition of Gaussian filters in Hz","dtype":"text","value":"The standard devaition of Gaussian filters in Hz"}]}],"name":"bands","doc":"A table for describing the bands that this series was generated from. There should be one row in this table for each band","neurodata_type_inc":"DynamicTable"}],"datasets":[{"shape":[null,null,null],"dims":["num_times","num_channels","num_bands"],"dtype":"numeric","name":"data","doc":"The data goes here","attributes":[{"name":"conversion","doc":"Scalar to multiply each element in data to convert it to the specified unit","required":false,"dtype":"float32","default_value":1.0},{"name":"resolution","doc":"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 -1.0","required":false,"dtype":"float32","default_value":0.0},{"name":"unit","doc":"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.","dtype":"text"}]},{"dtype":"text","name":"metric","doc":"recommended: phase, amplitude, power"}],"links":[{"name":"source_timeseries","doc":"HDF5 link to TimesSeries that this data was calculated from. Metadata about electrodes and their position can be read from that ElectricalSeries so it is not necessary to store that information here","target_type":"TimeSeries","quantity":"?"}],"doc":"Holds spectral analysis of a timeseries. For instance of LFP or a speech signal","neurodata_type_inc":"TimeSeries","neurodata_type_def":"DecompositionSeries","attributes":[{"name":"comments","doc":"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.","required":false,"dtype":"text","default_value":"no comments"},{"name":"description","doc":"Description of TimeSeries","required":false,"dtype":"text","default_value":"no description"},{"name":"help","doc":"Value is 'General time series object'","dtype":"text","value":"General time series object"}]},{"datasets":[{"name":"spike_times_index","doc":"the index into the spike_times dataset","quantity":"?","neurodata_type_inc":"VectorIndex"},{"dtype":"double","name":"spike_times","doc":"the spike times for each unit","quantity":"?","neurodata_type_inc":"VectorData"},{"name":"obs_intervals_index","doc":"the index into the obs_intervals dataset","quantity":"?","neurodata_type_inc":"VectorIndex"},{"shape":[null,2],"dims":["num_intervals","start|end"],"dtype":"double","name":"obs_intervals","doc":"the observation intervals for each unit","quantity":"?","neurodata_type_inc":"VectorData"},{"name":"electrodes_index","doc":"the index into electrodes","quantity":"?","neurodata_type_inc":"VectorIndex"},{"name":"electrodes","doc":"the electrode that each spike unit came from","quantity":"?","neurodata_type_inc":"DynamicTableRegion"},{"dtype":{"target_type":"ElectrodeGroup","reftype":"object"},"name":"electrode_group","doc":"the electrode group that each spike unit came from","quantity":"?","neurodata_type_inc":"VectorData"},{"shape":[[null,null],[null,null,null]],"dims":[["num_units","num_samples"],["num_units","num_samples","num_electrodes"]],"dtype":"float","name":"waveform_mean","doc":"the spike waveform mean for each spike unit","quantity":"?","neurodata_type_inc":"VectorData"},{"shape":[[null,null],[null,null,null]],"dims":[["num_units","num_samples"],["num_units","num_samples","num_electrodes"]],"dtype":"float","name":"waveform_sd","doc":"the spike waveform standard deviation for each spike unit","quantity":"?","neurodata_type_inc":"VectorData"}],"doc":"Data about spiking units. Event times of observed units (e.g. cell, synapse, etc.) should be concatenated and stored in spike_times.","default_name":"Units","neurodata_type_inc":"DynamicTable","neurodata_type_def":"Units","attributes":[{"name":"help","doc":"Value is 'Data about spiking units'","dtype":"text","value":"Data about spiking units"},{"name":"colnames","doc":"The names of the columns in this table. This should be used to specifying an order to the columns","dtype":"ascii","shape":[null],"dims":["num_columns"]},{"name":"description","doc":"Description of what is in this dynamic table","dtype":"text"}]}]}{"groups":[{"datasets":[{"shape":[[null],[null,null]],"dims":[["num_times"],["num_times","num_features"]],"dtype":"numeric","name":"data","doc":"2-D array storing position or direction relative to some reference frame.","attributes":[{"name":"unit","doc":"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.","required":false,"dtype":"text","default_value":"meter"},{"name":"conversion","doc":"Scalar to multiply each element in data to convert it to the specified unit","required":false,"dtype":"float32","default_value":1.0},{"name":"resolution","doc":"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 -1.0","required":false,"dtype":"float32","default_value":0.0}]},{"dtype":"text","name":"reference_frame","doc":"Description defining what exactly 'straight-ahead' means.","quantity":"?"}],"doc":"Direction, e.g., of gaze or travel, or position. The TimeSeries::data field is a 2D array storing position or direction relative to some reference frame. Array structure: [num measurements] [num dimensions]. Each SpatialSeries has a text dataset reference_frame that indicates the zero-position, or the zero-axes for direction. For example, if representing gaze direction, 'straight-ahead' might be a specific pixel on the monitor, or some other point in space. For position data, the 0,0 point might be the top-left corner of an enclosure, as viewed from the tracking camera. The unit of data will indicate how to interpret SpatialSeries values.","neurodata_type_inc":"TimeSeries","neurodata_type_def":"SpatialSeries","attributes":[{"name":"help","doc":"Value is: Stores points in space over time. The data[] array structure is [num samples][num spatial dimensions]","dtype":"text","value":"Stores points in space over time. The data[] array structure is [num samples][num spatial dimensions]"},{"name":"comments","doc":"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.","required":false,"dtype":"text","default_value":"no comments"},{"name":"description","doc":"Description of TimeSeries","required":false,"dtype":"text","default_value":"no description"}]},{"groups":[{"doc":"IntervalSeries object containing start and stop times of epochs","quantity":"*","neurodata_type_inc":"IntervalSeries"}],"doc":"TimeSeries for storing behavioral epochs. The objective of this and the other two Behavioral interfaces (e.g. BehavioralEvents and BehavioralTimeSeries) is to provide generic hooks for software tools/scripts. This allows a tool/script to take the output one specific interface (e.g., UnitTimes) and plot that data relative to another data modality (e.g., behavioral events) without having to define all possible modalities in advance. Declaring one of these interfaces means that one or more TimeSeries of the specified type is published. These TimeSeries should reside in a group having the same name as the interface. For example, if a BehavioralTimeSeries interface is declared, the module will have one or more TimeSeries defined in the module sub-group 'BehavioralTimeSeries'. BehavioralEpochs should use IntervalSeries. BehavioralEvents is used for irregular events. BehavioralTimeSeries is for continuous data.","default_name":"BehavioralEpochs","neurodata_type_inc":"NWBDataInterface","neurodata_type_def":"BehavioralEpochs","attributes":[{"name":"help","doc":"Value is 'General container for storing behavioral epochs'","dtype":"text","value":"General container for storing behavioral epochs"}]},{"groups":[{"doc":"TimeSeries object containing irregular behavioral events","quantity":"*","neurodata_type_inc":"TimeSeries"}],"doc":"TimeSeries for storing behavioral events. See description of BehavioralEpochs for more details.","default_name":"BehavioralEvents","neurodata_type_inc":"NWBDataInterface","neurodata_type_def":"BehavioralEvents","attributes":[{"name":"help","doc":"Value is 'Position data, whether along the x, xy or xyz axis'","dtype":"text","value":"Position data, whether along the x, xy or xyz axis"}]},{"groups":[{"doc":"TimeSeries object containing continuous behavioral data","quantity":"*","neurodata_type_inc":"TimeSeries"}],"doc":"TimeSeries for storing Behavoioral time series data.See description of BehavioralEpochs for more details.","default_name":"BehavioralTimeSeries","neurodata_type_inc":"NWBDataInterface","neurodata_type_def":"BehavioralTimeSeries","attributes":[{"name":"help","doc":"Value is 'General container for storing continuously sampled behavioral data.'","dtype":"text","value":"General container for storing continuously sampled behavioral data."}]},{"groups":[{"doc":"TimeSeries object containing time series data on pupil size","quantity":"+","neurodata_type_inc":"TimeSeries"}],"doc":"Eye-tracking data, representing pupil size.","default_name":"PupilTracking","neurodata_type_inc":"NWBDataInterface","neurodata_type_def":"PupilTracking","attributes":[{"name":"help","doc":"Value is 'Eye-tracking data, representing pupil size'","dtype":"text","value":"Eye-tracking data, representing pupil size"}]},{"groups":[{"doc":"SpatialSeries object containing data measuring direction of gaze","quantity":"*","neurodata_type_inc":"SpatialSeries"}],"doc":"Eye-tracking data, representing direction of gaze.","default_name":"EyeTracking","neurodata_type_inc":"NWBDataInterface","neurodata_type_def":"EyeTracking","attributes":[{"name":"help","doc":"Value is 'Eye-tracking data, representing direction of gaze'","dtype":"text","value":"Eye-tracking data, representing direction of gaze"}]},{"groups":[{"doc":"SpatialSeries object containing direction of gaze travel","quantity":"*","neurodata_type_inc":"SpatialSeries"}],"doc":"With a CompassDirection interface, a module publishes a SpatialSeries object representing a floating point value for theta. The SpatialSeries::reference_frame field should indicate what direction corresponds to 0 and which is the direction of rotation (this should be clockwise). The si_unit for the SpatialSeries should be radians or degrees.","default_name":"CompassDirection","neurodata_type_inc":"NWBDataInterface","neurodata_type_def":"CompassDirection","attributes":[{"name":"help","doc":"Value is 'Direction as measured radially. Spatial series reference frame should indicate which direction corresponds to zero and what is the direction of positive rotation'","dtype":"text","value":"Direction as measured radially. Spatial series reference frame should indicate which direction corresponds to zero and what is the direction of positive rotation"}]},{"groups":[{"doc":"SpatialSeries object containing position data","quantity":"+","neurodata_type_inc":"SpatialSeries"}],"doc":"Position data, whether along the x, x/y or x/y/z axis.","default_name":"Position","neurodata_type_inc":"NWBDataInterface","neurodata_type_def":"Position","attributes":[{"name":"help","doc":"Value is 'Position data, whether along the x, xy or xyz axis'","dtype":"text","value":"Position data, whether along the x, xy or xyz axis"}]}]}S {"groups":[{"datasets":[{"shape":[null],"dims":["num_times"],"dtype":"numeric","name":"data","doc":"Applied power for optogenetic stimulus.","attributes":[{"name":"unit","doc":"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.","required":false,"dtype":"text","default_value":"watt"},{"name":"conversion","doc":"Scalar to multiply each element in data to convert it to the specified unit","required":false,"dtype":"float32","default_value":1.0},{"name":"resolution","doc":"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 -1.0","required":false,"dtype":"float32","default_value":0.0}]}],"links":[{"name":"site","doc":"link to OptogeneticStimulusSite group that describes the site to which this stimulus was applied","target_type":"OptogeneticStimulusSite"}],"doc":"Optogenetic stimulus. The data[] field is in unit of watts.","neurodata_type_inc":"TimeSeries","neurodata_type_def":"OptogeneticSeries","attributes":[{"name":"help","doc":"Value is 'Optogenetic stimulus'","dtype":"text","value":"Optogenetic stimulus"},{"name":"comments","doc":"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.","required":false,"dtype":"text","default_value":"no comments"},{"name":"description","doc":"Description of TimeSeries","required":false,"dtype":"text","default_value":"no description"}]},{"datasets":[{"dtype":"text","name":"description","doc":"Description of site"},{"dtype":"float","name":"excitation_lambda","doc":"Excitation wavelength in nm"},{"dtype":"text","name":"location","doc":"Location of stimulation site"}],"links":[{"name":"device","doc":"Device that generated the stimulus","target_type":"Device"}],"doc":"One of possibly many groups describing an optogenetic stimulation site. COMMENT: Name is arbitrary but should be meaningful. Name is referenced by OptogeneticSeries","quantity":"*","neurodata_type_inc":"NWBContainer","neurodata_type_def":"OptogeneticStimulusSite","attributes":[{"name":"help","doc":"Value is 'Metadata about an optogenetic stimulus site'","dtype":"text","value":"Metadata about an optogenetic stimulus site"}]}]}p3#]3#]3#]SNOD8hvxPO(XuHxw`PRS3#]3#]3#]GCOL5{"groups":[{"datasets":[{"shape":[[null],[null,null],[null,null,null]],"dims":[["num_times"],["num_times","num_channels"],["num_times","num_channels","num_samples"]],"dtype":"numeric","name":"data","doc":"Recorded voltage data.","attributes":[{"name":"unit","doc":"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.","required":false,"dtype":"text","default_value":"volt"},{"name":"conversion","doc":"Scalar to multiply each element in data to convert it to the specified unit","required":false,"dtype":"float32","default_value":1.0},{"name":"resolution","doc":"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 -1.0","required":false,"dtype":"float32","default_value":0.0}]},{"name":"electrodes","doc":"the electrodes that this series was generated from","neurodata_type_inc":"DynamicTableRegion"}],"doc":"Stores acquired voltage data from extracellular recordings. The data field of an ElectricalSeries is an int or float array storing data in Volts. TimeSeries::data array structure: :blue:`[num times] [num channels] (or [num_times] for single electrode).`","neurodata_type_inc":"TimeSeries","neurodata_type_def":"ElectricalSeries","attributes":[{"name":"help","doc":"Value is 'Stores acquired voltage data from extracellular recordings'","dtype":"text","value":"Stores acquired voltage data from extracellular recordings"},{"name":"comments","doc":"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.","required":false,"dtype":"text","default_value":"no comments"},{"name":"description","doc":"Description of TimeSeries","required":false,"dtype":"text","default_value":"no description"}]},{"datasets":[{"shape":[[null,null],[null,null,null]],"dims":[["num_events","num_samples"],["num_events","num_channels","num_samples"]],"dtype":"numeric","name":"data","doc":"Spike waveforms.","attributes":[{"name":"unit","doc":"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.","required":false,"dtype":"text","default_value":"volt"},{"name":"conversion","doc":"Scalar to multiply each element in data to convert it to the specified unit","required":false,"dtype":"float32","default_value":1.0},{"name":"resolution","doc":"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 -1.0","required":false,"dtype":"float32","default_value":0.0}]},{"shape":[null],"dims":["num_times"],"dtype":"float64","name":"timestamps","doc":"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. This is added here so that the timestamps is required for SpikeEventTimes.","attributes":[{"name":"interval","doc":"Value is '1'","dtype":"int32","value":1},{"name":"unit","doc":"Value is 'Seconds'","dtype":"text","value":"Seconds"}]}],"doc":"Stores 'snapshots' of spike events (i.e., threshold crossings) in data. This may also be raw data, as reported by ephys hardware. If so, the TimeSeries::description field should describing how events were detected. All SpikeEventSeries should reside in a module (under EventWaveform interface) even if the spikes were reported and stored by hardware. All events span the same recording channels and store snapshots of equal duration. TimeSeries::data array structure: [num events] [num channels] [num samples] (or [num events] [num samples] for single electrode).","neurodata_type_inc":"ElectricalSeries","neurodata_type_def":"SpikeEventSeries","attributes":[{"name":"help","doc":"Value is 'Snapshots of spike events from data.'","dtype":"text","value":"Snapshots of spike events from data."},{"name":"comments","doc":"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.","required":false,"dtype":"text","default_value":"no comments"},{"name":"description","doc":"Description of TimeSeries","required":false,"dtype":"text","default_value":"no description"}]},{"datasets":[{"dtype":"text","name":"waveform_filtering","doc":"Filtering applied to data before generating mean/sd"},{"shape":[null,null],"dims":["num_clusters","num_samples"],"dtype":"float32","name":"waveform_mean","doc":"The mean waveform for each cluster, using the same indices for each wave as cluster numbers in the associated Clustering module (i.e, cluster 3 is in array slot [3]). Waveforms corresponding to gaps in cluster sequence should be empty (e.g., zero- filled)"},{"shape":[null,null],"dims":["num_clusters","num_samples"],"dtype":"float32","name":"waveform_sd","doc":"Stdev of waveforms for each cluster, using the same indices as in mean"}],"links":[{"name":"clustering_interface","doc":"HDF5 link to Clustering interface that was the source of the clustered data","target_type":"Clustering"}],"doc":"DEPRECATED The mean waveform shape, including standard deviation, of the different clusters. Ideally, the waveform analysis should be performed on data that is only high-pass filtered. This is a separate module because it is expected to require updating. For example, IMEC probes may require different storage requirements to store/display mean waveforms, requiring a new interface or an extension of this one.","default_name":"ClusterWaveforms","neurodata_type_inc":"NWBDataInterface","neurodata_type_def":"ClusterWaveforms","attributes":[{"name":"help","doc":"Value is 'Mean waveform shape of clusters. Waveforms should be high-pass filtered (ie, not the same bandpass filter used waveform analysis and clustering)'","dtype":"text","value":"DEPRECATED Mean waveform shape of clusters. Waveforms should be high-pass filtered (ie, not the same bandpass filter used waveform analysis and clustering)"}]},{"datasets":[{"dtype":"text","name":"description","doc":"Description of clusters or clustering, (e.g. cluster 0 is noise, clusters curated using Klusters, etc)"},{"shape":[null],"dims":["num_events"],"dtype":"int32","name":"num","doc":"Cluster number of each event"},{"shape":[null],"dims":["num_clusters"],"dtype":"float32","name":"peak_over_rms","doc":"Maximum ratio of waveform peak to RMS on any channel in the cluster (provides a basic clustering metric)."},{"shape":[null],"dims":["num_events"],"dtype":"float64","name":"times","doc":"Times of clustered events, in seconds. This may be a link to times field in associated FeatureExtraction module."}],"doc":"DEPRECATED Clustered spike data, whether from automatic clustering tools (e.g., klustakwik) or as a result of manual sorting.","default_name":"Clustering","neurodata_type_inc":"NWBDataInterface","neurodata_type_def":"Clustering","attributes":[{"name":"help","doc":"Value is 'Clustered spike data, whether from automatic clustering tools (eg, klustakwik) or as a result of manual sorting'","dtype":"text","value":"DEPRECATED Clustered spike data, whether from automatic clustering tools (eg, klustakwik) or as a result of manual sorting"}]},{"datasets":[{"shape":[null],"dims":["num_features"],"dtype":"text","name":"description","doc":"Description of features (eg, ''PC1'') for each of the extracted features."},{"shape":[null,null,null],"dims":["num_events","num_channels","num_features"],"dtype":"float32","name":"features","doc":"Multi-dimensional array of features extracted from each event."},{"shape":[null],"dims":["num_events"],"dtype":"float64","name":"times","doc":"Times of events that features correspond to (can be a link)."},{"name":"electrodes","doc":"the electrodes that this series was generated from","neurodata_type_inc":"DynamicTableRegion"}],"doc":"Features, such as PC1 and PC2, that are extracted from signals stored in a SpikeEvent TimeSeries or other source.","default_name":"FeatureExtraction","neurodata_type_inc":"NWBDataInterface","neurodata_type_def":"FeatureExtraction","attributes":[{"name":"help","doc":"Value is 'Container for salient features of detected events'","dtype":"text","value":"Container for salient features of detected events"}]},{"datasets":[{"dtype":"text","name":"detection_method","doc":"Description of how events were detected, such as voltage threshold, or dV/dT threshold, as well as relevant values."},{"shape":[null],"dims":["num_events"],"dtype":"int32","name":"source_idx","doc":"Indices (zero-based) into source ElectricalSeries::data array corresponding to time of event. Module description should define what is meant by time of event (e.g., .25msec before action potential peak, zero-crossing time, etc). The index points to each event from the raw data"},{"shape":[null],"dims":["num_events"],"dtype":"float64","name":"times","doc":"Timestamps of events, in Seconds","attributes":[{"name":"unit","doc":"The string ''Seconds''","required":false,"dtype":"text","default_value":"Seconds"}]}],"links":[{"name":"source_electricalseries","doc":"HDF5 link to ElectricalSeries that this data was calculated from. Metadata about electrodes and their position can be read from that ElectricalSeries so it's not necessary to mandate that information be stored here","target_type":"ElectricalSeries"}],"doc":"Detected spike events from voltage trace(s).","default_name":"EventDetection","neurodata_type_inc":"NWBDataInterface","neurodata_type_def":"EventDetection","attributes":[{"name":"help","doc":"Value is 'Detected spike events from voltage trace(s)'","dtype":"text","value":"Detected spike events from voltage trace(s)"}]},{"groups":[{"doc":"SpikeEventSeries object containing detected spike event waveforms","quantity":"*","neurodata_type_inc":"SpikeEventSeries"}],"doc":"Represents either the waveforms of detected events, as extracted from a raw data trace in /acquisition, or the event waveforms that were stored during experiment acquisition.","default_name":"EventWaveform","neurodata_type_inc":"NWBDataInterface","neurodata_type_def":"EventWaveform","attributes":[{"name":"help","doc":"Value is 'Waveform of detected extracellularly recorded spike events'","dtype":"text","value":"Waveform of detected extracellularly recorded spike events"}]},{"groups":[{"doc":"ElectricalSeries object containing filtered electrophysiology data","quantity":"+","neurodata_type_inc":"ElectricalSeries"}],"doc":"Ephys data from one or more channels that has been subjected to filtering. Examples of filtered data include Theta and Gamma (LFP has its own interface). FilteredEphys modules publish an ElectricalSeries for each filtered channel or set of channels. The name of each ElectricalSeries is arbitrary but should be informative. The source of the filtered data, whether this is from analysis of another time series or as acquired by hardware, should be noted in each's TimeSeries::description field. There is no assumed 1::1 correspondence between filtered ephys signals and electrodes, as a single signal can apply to many nearby electrodes, and one electrode may have different filtered (e.g., theta and/or gamma) signals represented.","default_name":"FilteredEphys","neurodata_type_inc":"NWBDataInterface","neurodata_type_def":"FilteredEphys","attributes":[{"name":"help","doc":"Value is 'Ephys data from one or more channels that is subjected to filtering, such as for gamma or theta oscillations (LFP has its own interface). Filter properties should be noted in the ElectricalSeries'","dtype":"text","value":"Ephys data from one or more channels that is subjected to filtering, such as for gamma or theta oscillations (LFP has its own interface). Filter properties should be noted in the ElectricalSeries"}]},{"groups":[{"doc":"ElectricalSeries object containing LFP data for one or more channels","quantity":"+","neurodata_type_inc":"ElectricalSeries"}],"doc":"LFP data from one or more channels. The electrode map in each published ElectricalSeries will identify which channels are providing LFP data. Filter properties should be noted in the ElectricalSeries description or comments field.","default_name":"LFP","neurodata_type_inc":"NWBDataInterface","neurodata_type_def":"LFP","attributes":[{"name":"help","doc":"Value is 'LFP data from one or more channels. Filter properties should be noted in the ElectricalSeries'","dtype":"text","value":"LFP data from one or more channels. Filter properties should be noted in the ElectricalSeries"}]},{"links":[{"name":"device","doc":"the device that was used to record from this electrode group","target_type":"Device","quantity":"?"}],"doc":"One of possibly many groups, one for each electrode group.","neurodata_type_inc":"NWBContainer","neurodata_type_def":"ElectrodeGroup","attributes":[{"name":"help","doc":"Value is 'Metadata about a physical grouping of channels'","dtype":"text","value":"A physical grouping of channels"},{"name":"description","doc":"description of this electrode group","dtype":"text"},{"name":"location","doc":"description of location of this electrode group","dtype":"text"}]}]}#8{"groups":[{"datasets":[{"shape":[null],"dims":["num_times"],"dtype":"numeric","name":"data","doc":"Recorded voltage or current.","attributes":[{"name":"conversion","doc":"Scalar to multiply each element in data to convert it to the specified unit","required":false,"dtype":"float32","default_value":1.0},{"name":"resolution","doc":"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 -1.0","required":false,"dtype":"float32","default_value":0.0},{"name":"unit","doc":"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.","dtype":"text"}]},{"dtype":"float","name":"gain","doc":"Units: Volt/Amp (v-clamp) or Volt/Volt (c-clamp)","quantity":"?"}],"links":[{"name":"electrode","doc":"link to IntracellularElectrode group that describes th electrode that was used to apply or record this data","target_type":"IntracellularElectrode"}],"doc":"Stores stimulus or response current or voltage. Superclass definition for patch-clamp data (this class should not be instantiated directly).","neurodata_type_inc":"TimeSeries","neurodata_type_def":"PatchClampSeries","attributes":[{"name":"help","doc":"Value is 'Superclass definition for patch-clamp data'","dtype":"text","value":"Superclass definition for patch-clamp data"},{"name":"stimulus_description","doc":"the protocol/stimulus name for this patch-clamp dataset","dtype":"text"},{"name":"sweep_number","doc":"Sweep number, allows to group different PatchClampSeries together.","required":false,"dtype":"uint64"},{"name":"comments","doc":"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.","required":false,"dtype":"text","default_value":"no comments"},{"name":"description","doc":"Description of TimeSeries","required":false,"dtype":"text","default_value":"no description"}]},{"datasets":[{"dtype":"float32","name":"bias_current","doc":"Unit: Amp","quantity":"?"},{"dtype":"float32","name":"bridge_balance","doc":"Unit: Ohm","quantity":"?"},{"dtype":"float32","name":"capacitance_compensation","doc":"Unit: Farad","quantity":"?"}],"doc":"Stores voltage data recorded from intracellular current-clamp recordings. A corresponding CurrentClampStimulusSeries (stored separately as a stimulus) is used to store the current injected.","neurodata_type_inc":"PatchClampSeries","neurodata_type_def":"CurrentClampSeries","attributes":[{"name":"help","doc":"Value is 'Voltage recorded from cell during current-clamp recording'","dtype":"text","value":"Voltage recorded from cell during current-clamp recording"},{"name":"stimulus_description","doc":"the protocol/stimulus name for this patch-clamp dataset","dtype":"text"},{"name":"sweep_number","doc":"Sweep number, allows to group different PatchClampSeries together.","required":false,"dtype":"uint64"},{"name":"comments","doc":"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.","required":false,"dtype":"text","default_value":"no comments"},{"name":"description","doc":"Description of TimeSeries","required":false,"dtype":"text","default_value":"no description"}]},{"doc":"Stores recorded voltage data from intracellular recordings when all current and amplifier settings are off (i.e., CurrentClampSeries fields will be zero). There is no CurrentClampStimulusSeries associated with an IZero series because the amplifier is disconnected and no stimulus can reach the cell.","neurodata_type_inc":"CurrentClampSeries","neurodata_type_def":"IZeroClampSeries","attributes":[{"name":"help","doc":"Value is 'Voltage from intracellular recordings when all current and amplifier settings are off'","dtype":"text","value":"Voltage from intracellular recordings when all current and amplifier settings are off"},{"name":"stimulus_description","doc":"the protocol/stimulus name for this patch-clamp dataset","dtype":"text"},{"name":"sweep_number","doc":"Sweep number, allows to group different PatchClampSeries together.","required":false,"dtype":"uint64"},{"name":"comments","doc":"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.","required":false,"dtype":"text","default_value":"no comments"},{"name":"description","doc":"Description of TimeSeries","required":false,"dtype":"text","default_value":"no description"}]},{"doc":"Aliases to standard PatchClampSeries. Its functionality is to better tag PatchClampSeries for machine (and human) readability of the file.","neurodata_type_inc":"PatchClampSeries","neurodata_type_def":"CurrentClampStimulusSeries","attributes":[{"name":"help","doc":"Value is 'Stimulus current applied during current clamp recording'","dtype":"text","value":"Stimulus current applied during current clamp recording"},{"name":"stimulus_description","doc":"the protocol/stimulus name for this patch-clamp dataset","dtype":"text"},{"name":"sweep_number","doc":"Sweep number, allows to group different PatchClampSeries together.","required":false,"dtype":"uint64"},{"name":"comments","doc":"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.","required":false,"dtype":"text","default_value":"no comments"},{"name":"description","doc":"Description of TimeSeries","required":false,"dtype":"text","default_value":"no description"}]},{"datasets":[{"dtype":"float32","name":"capacitance_fast","doc":"Unit: Farad","quantity":"?","attributes":[{"name":"unit","doc":"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.","required":false,"dtype":"text","default_value":"Farad"}]},{"dtype":"float32","name":"capacitance_slow","doc":"Unit: Farad","quantity":"?","attributes":[{"name":"unit","doc":"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.","required":false,"dtype":"text","default_value":"Farad"}]},{"dtype":"float32","name":"resistance_comp_bandwidth","doc":"Unit: Hz","quantity":"?","attributes":[{"name":"unit","doc":"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.","required":false,"dtype":"text","default_value":"Hz"}]},{"dtype":"float32","name":"resistance_comp_correction","doc":"Unit: %","quantity":"?","attributes":[{"name":"unit","doc":"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.","required":false,"dtype":"text","default_value":"percent"}]},{"dtype":"float32","name":"resistance_comp_prediction","doc":"Unit: %","quantity":"?","attributes":[{"name":"unit","doc":"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.","required":false,"dtype":"text","default_value":"percent"}]},{"dtype":"float32","name":"whole_cell_capacitance_comp","doc":"Unit: Farad","quantity":"?","attributes":[{"name":"unit","doc":"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.","required":false,"dtype":"text","default_value":"Farad"}]},{"dtype":"float32","name":"whole_cell_series_resistance_comp","doc":"Unit: Ohm","quantity":"?","attributes":[{"name":"unit","doc":"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.","required":false,"dtype":"text","default_value":"Ohm"}]}],"doc":"Stores current data recorded from intracellular voltage-clamp recordings. A corresponding VoltageClampStimulusSeries (stored separately as a stimulus) is used to store the voltage injected.","neurodata_type_inc":"PatchClampSeries","neurodata_type_def":"VoltageClampSeries","attributes":[{"name":"help","doc":"Value is 'Current recorded from cell during voltage-clamp recording'","dtype":"text","value":"Current recorded from cell during voltage-clamp recording"},{"name":"stimulus_description","doc":"the protocol/stimulus name for this patch-clamp dataset","dtype":"text"},{"name":"sweep_number","doc":"Sweep number, allows to group different PatchClampSeries together.","required":false,"dtype":"uint64"},{"name":"comments","doc":"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.","required":false,"dtype":"text","default_value":"no comments"},{"name":"description","doc":"Description of TimeSeries","required":false,"dtype":"text","default_value":"no description"}]},{"doc":"Aliases to standard PatchClampSeries. Its functionality is to better tag PatchClampSeries for machine (and human) readability of the file.","neurodata_type_inc":"PatchClampSeries","neurodata_type_def":"VoltageClampStimulusSeries","attributes":[{"name":"help","doc":"Value is 'Stimulus voltage applied during voltage clamp recording'","dtype":"text","value":"Stimulus voltage applied during voltage clamp recording"},{"name":"stimulus_description","doc":"the protocol/stimulus name for this patch-clamp dataset","dtype":"text"},{"name":"sweep_number","doc":"Sweep number, allows to group different PatchClampSeries together.","required":false,"dtype":"uint64"},{"name":"comments","doc":"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.","required":false,"dtype":"text","default_value":"no comments"},{"name":"description","doc":"Description of TimeSeries","required":false,"dtype":"text","default_value":"no description"}]},{"datasets":[{"dtype":"text","name":"description","doc":"Recording description, description of electrode (e.g., whole-cell, sharp, etc)COMMENT: Free-form text (can be from Methods)"},{"dtype":"text","name":"filtering","doc":"Electrode specific filtering.","quantity":"?"},{"dtype":"text","name":"initial_access_resistance","doc":"Initial access resistance","quantity":"?"},{"dtype":"text","name":"location","doc":"Area, layer, comments on estimation, stereotaxis coordinates (if in vivo, etc)","quantity":"?"},{"dtype":"text","name":"resistance","doc":"Electrode resistance COMMENT: unit: Ohm","quantity":"?"},{"dtype":"text","name":"seal","doc":"Information about seal used for recording","quantity":"?"},{"dtype":"text","name":"slice","doc":"Information about slice used for recording","quantity":"?"}],"links":[{"name":"device","doc":"the device that was used to record from this electrode","target_type":"Device"}],"doc":"One of possibly many. COMMENT: Name should be informative.","neurodata_type_inc":"NWBContainer","neurodata_type_def":"IntracellularElectrode","attributes":[{"name":"help","doc":"Value is 'Metadata about an intracellular electrode'","dtype":"text","value":"Metadata about an intracellular electrode"}]},{"datasets":[{"dtype":"uint64","name":"sweep_number","doc":"The sweep number of the PatchClampSeries in that row.","neurodata_type_inc":"VectorData","attributes":[{"name":"description","doc":"value is 'The sweep number of the PatchClampSeries in that row'","dtype":"text","value":"The sweep number of the PatchClampSeries in that row"}]},{"dtype":{"target_type":"PatchClampSeries","reftype":"object"},"name":"series","doc":"The PatchClampSeries with the sweep number in that row","neurodata_type_inc":"VectorData","attributes":[{"name":"help","doc":"Value is 'The PatchClampSeries with the sweep number in that row'","dtype":"text","value":"The PatchClampSeries with the sweep number in that row"}]},{"name":"series_index","doc":"Index for series","neurodata_type_inc":"VectorIndex"}],"doc":"The table which groups different PatchClampSeries together.","neurodata_type_inc":"DynamicTable","neurodata_type_def":"SweepTable","attributes":[{"name":"help","doc":"Value is 'The table which groups different PatchClampSeries together'","dtype":"text","value":"The table which groups different PatchClampSeries together"},{"name":"colnames","doc":"The names of the columns in this table. This should be used to specifying an order to the columns","dtype":"ascii","shape":[null],"dims":["num_columns"]},{"name":"description","doc":"Description of what is in this dynamic table","dtype":"text"}]}]}]1{"groups":[{"datasets":[{"shape":[[2],[3]],"dims":["width|height","width|height|depth"],"dtype":"float32","name":"field_of_view","doc":"Width, height and depth of image, or imaged area (meters).","quantity":"?"}],"links":[{"name":"imaging_plane","doc":"link to ImagingPlane group from which this TimeSeries data was generated","target_type":"ImagingPlane"}],"doc":"A special case of optical imaging.","neurodata_type_inc":"ImageSeries","neurodata_type_def":"TwoPhotonSeries","attributes":[{"name":"help","doc":"Value is 'Image stack recorded from 2-photon microscope'","dtype":"text","value":"Image stack recorded from 2-photon microscope"},{"name":"pmt_gain","doc":"Photomultiplier gain","required":false,"dtype":"float32"},{"name":"scan_line_rate","doc":"Lines imaged per second. This is also stored in /general/optophysiology but is kept here as it is useful information for analysis, and so good to be stored w/ the actual data.","required":false,"dtype":"float32"},{"name":"comments","doc":"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.","required":false,"dtype":"text","default_value":"no comments"},{"name":"description","doc":"Description of TimeSeries","required":false,"dtype":"text","default_value":"no description"}]},{"datasets":[{"shape":[[null],[null,null]],"dims":[["num_times"],["num_times","num_ROIs"]],"dtype":"numeric","name":"data","doc":"Signals from ROIs","attributes":[{"name":"conversion","doc":"Scalar to multiply each element in data to convert it to the specified unit","required":false,"dtype":"float32","default_value":1.0},{"name":"resolution","doc":"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 -1.0","required":false,"dtype":"float32","default_value":0.0},{"name":"unit","doc":"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.","dtype":"text"}]},{"name":"rois","doc":"a dataset referencing into an ROITable containing information on the ROIs stored in this timeseries","neurodata_type_inc":"DynamicTableRegion"}],"doc":"ROI responses over an imaging plane. Each row in data[] should correspond to the signal from one ROI.","neurodata_type_inc":"TimeSeries","neurodata_type_def":"RoiResponseSeries","attributes":[{"name":"help","doc":"Value is 'ROI responses over an imaging plane. Each element on the second dimension of data[] should correspond to the signal from one ROI'","dtype":"text","value":"ROI responses over an imaging plane. Each element on the second dimension of data[] should correspond to the signal from one ROI"},{"name":"comments","doc":"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.","required":false,"dtype":"text","default_value":"no comments"},{"name":"description","doc":"Description of TimeSeries","required":false,"dtype":"text","default_value":"no description"}]},{"groups":[{"doc":"RoiResponseSeries object containing dF/F for a ROI","quantity":"+","neurodata_type_inc":"RoiResponseSeries"}],"doc":"dF/F information about a region of interest (ROI). Storage hierarchy of dF/F should be the same as for segmentation (ie, same names for ROIs and for image planes).","default_name":"DfOverF","neurodata_type_inc":"NWBDataInterface","neurodata_type_def":"DfOverF","attributes":[{"name":"help","doc":"Value is 'Df/f over time of one or more ROIs. TimeSeries names should correspond to imaging plane names'","dtype":"text","value":"Df/f over time of one or more ROIs. TimeSeries names should correspond to imaging plane names"}]},{"groups":[{"doc":"RoiResponseSeries object containing fluorescence data for a ROI","quantity":"+","neurodata_type_inc":"RoiResponseSeries"}],"doc":"Fluorescence information about a region of interest (ROI). Storage hierarchy of fluorescence should be the same as for segmentation (ie, same names for ROIs and for image planes).","default_name":"Fluorescence","neurodata_type_inc":"NWBDataInterface","neurodata_type_def":"Fluorescence","attributes":[{"name":"help","doc":"Value is 'Fluorescence over time of one or more ROIs. TimeSeries names should correspond to imaging plane names'","dtype":"text","value":"Fluorescence over time of one or more ROIs. TimeSeries names should correspond to imaging plane names"}]},{"groups":[{"groups":[{"groups":[{"doc":"One or more image stacks that the masks apply to (can be one-element stack)","quantity":"*","neurodata_type_inc":"ImageSeries"}],"name":"reference_images","doc":"Stores image stacks segmentation mask apply to."}],"datasets":[{"shape":[[null,null,null],[null,null,null,null]],"dims":[["num_roi","num_x","num_y"],["num_roi","num_x","num_y","num_z"]],"name":"image_mask","doc":"ROI masks for each ROI. Each image mask is the size of the original imaging plane (or volume) and members of the ROI are finite non-zero","quantity":"?","neurodata_type_inc":"VectorData"},{"name":"pixel_mask_index","doc":"index into pixel_mask","quantity":"?","neurodata_type_inc":"VectorIndex"},{"dtype":[{"doc":"the pixel x-coordinate","name":"x","dtype":"uint"},{"doc":"the pixel y-coordinate","name":"y","dtype":"uint"},{"doc":"the weight of the pixel","name":"weight","dtype":"float"}],"name":"pixel_mask","doc":"Pixel masks for each ROI: a list of indices and weights for the ROI. Pixel masks are concatenated and parsing of this dataset is maintained by the PlaneSegmentation","quantity":"?","neurodata_type_inc":"VectorData"},{"name":"voxel_mask_index","doc":"index into voxel_mask","quantity":"?","neurodata_type_inc":"VectorIndex"},{"dtype":[{"doc":"the voxel x-coordinate","name":"x","dtype":"uint"},{"doc":"the voxel y-coordinate","name":"y","dtype":"uint"},{"doc":"the voxel y-coordinate","name":"z","dtype":"uint"},{"doc":"the weight of the voxel","name":"weight","dtype":"float"}],"name":"voxel_mask","doc":"Voxel masks for each ROI: a list of indices and weights for the ROI. Voxel masks are concatenated and parsing of this dataset is maintained by the PlaneSegmentation","quantity":"?","neurodata_type_inc":"VectorData"},{"shape":[null],"dims":["num_rows"],"dtype":"int","name":"id","doc":"The unique identifier for the rows in this dynamic table","neurodata_type_inc":"ElementIdentifiers"},{"doc":"The vector columns in this dynamic table","quantity":"*","neurodata_type_inc":"VectorData"},{"doc":"The indices for the vector columns in this dynamic table","quantity":"*","neurodata_type_inc":"VectorIndex"}],"links":[{"name":"imaging_plane","doc":"link to ImagingPlane group from which this TimeSeries data was generated","target_type":"ImagingPlane"}],"doc":"results for image segmentation of a specific imaging plane","quantity":"+","neurodata_type_inc":"DynamicTable","neurodata_type_def":"PlaneSegmentation","attributes":[{"name":"help","doc":"Value is 'Results from segmentation of an imaging plane'","dtype":"text","value":"Results from segmentation of an imaging plane"},{"name":"colnames","doc":"The names of the columns in this table. This should be used to specifying an order to the columns","dtype":"ascii","shape":[null],"dims":["num_columns"]},{"name":"description","doc":"Description of what is in this dynamic table","dtype":"text"}]}],"doc":"Stores pixels in an image that represent different regions of interest (ROIs) or masks. All segmentation for a given imaging plane is stored together, with storage for multiple imaging planes (masks) supported. Each ROI is stored in its own subgroup, with the ROI group containing both a 2D mask and a list of pixels that make up this mask. Segments can also be used for masking neuropil. If segmentation is allowed to change with time, a new imaging plane (or module) is required and ROI names should remain consistent between them.","default_name":"ImageSegmentation","neurodata_type_inc":"NWBDataInterface","neurodata_type_def":"ImageSegmentation","attributes":[{"name":"help","doc":"Value is 'Stores groups of pixels that define regions of interest from one or more imaging planes'","dtype":"text","value":"Stores groups of pixels that define regions of interest from one or more imaging planes"}]},{"groups":[{"datasets":[{"dtype":"text","name":"description","doc":"Any notes or comments about the channel"},{"dtype":"float","name":"emission_lambda","doc":"Emission wavelength for channel in nm"}],"doc":"One of possibly many groups storing channel-specific data COMMENT: Name is arbitrary but should be meaningful","neurodata_type_inc":"NWBContainer","neurodata_type_def":"OpticalChannel","attributes":[{"name":"help","doc":"Value is 'Metadata about an optical channel used to record from an imaging plane'","dtype":"text","value":"Metadata about an optical channel used to record from an imaging plane"}]}],"datasets":[{"dtype":"text","name":"description","doc":"Description of image_plane_X","quantity":"?"},{"dtype":"float","name":"excitation_lambda","doc":"Excitation wavelength in nm"},{"dtype":"float","name":"imaging_rate","doc":"Rate images are acquired, in Hz."},{"dtype":"text","name":"indicator","doc":"Calcium indicator"},{"dtype":"text","name":"location","doc":"Location of image plane"},{"shape":[[null,null,3],[null,null,null,3]],"dims":[["height","width","x|y|z"],["height","width","depth","x|y|z"]],"dtype":"float32","name":"manifold","doc":"Physical position of each pixel. COMMENT: 'xyz' represents the position of the pixel relative to the defined coordinate space","quantity":"?","attributes":[{"name":"conversion","doc":"Multiplier to get from stored values to specified unit (e.g., 1e-3 for millimeters)","required":false,"dtype":"float","default_value":1.0},{"name":"unit","doc":"Base unit that coordinates are stored in (e.g., Meters)","required":false,"dtype":"text","default_value":"Meter"}]},{"dtype":"text","name":"reference_frame","doc":"Describes position and reference frame of manifold based on position of first element in manifold. For example, text description of anatomical location or vectors needed to rotate to common anatomical axis (eg, AP/DV/ML). COMMENT: This field is necessary to interpret manifold. If manifold is not present then this field is not required","quantity":"?"}],"links":[{"name":"device","doc":"the device that was used to record from this electrode","target_type":"Device"}],"doc":"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","quantity":"*","neurodata_type_inc":"NWBContainer","neurodata_type_def":"ImagingPlane","attributes":[{"name":"help","doc":"Value is 'Metadata about an imaging plane'","dtype":"text","value":"Metadata about an imaging plane"}]},{"groups":[{"groups":[{"name":"corrected","doc":"Image stack with frames shifted to the common coordinates.","neurodata_type_inc":"ImageSeries"},{"name":"xy_translation","doc":"Stores the x,y delta necessary to align each frame to the common coordinates, for example, to align each frame to a reference image.","neurodata_type_inc":"TimeSeries"}],"links":[{"name":"original","doc":"HDF5 Link to image series that is being registered.","target_type":"ImageSeries"}],"doc":"One of possibly many. Name should be informative.","quantity":"+","neurodata_type_inc":"NWBDataInterface","neurodata_type_def":"CorrectedImageStack","attributes":[{"name":"help","doc":"Value is 'Reuslts from motion correction of an image stack'","dtype":"text","value":"Reuslts from motion correction of an image stack"}]}],"doc":"An image stack where all frames are shifted (registered) to a common coordinate system, to account for movement and drift between frames. Note: each frame at each point in time is assumed to be 2-D (has only x & y dimensions).","default_name":"MotionCorrection","neurodata_type_inc":"NWBDataInterface","neurodata_type_def":"MotionCorrection","attributes":[{"name":"help","doc":"Value is 'Image stacks whose frames have been shifted (registered) to account for motion'","dtype":"text","value":"Image stacks whose frames have been shifted (registered) to account for motion"}]}]}{"groups":[{"datasets":[{"shape":[null,null],"dims":["num_rows","num_cols"],"dtype":"float32","name":"axis_1_phase_map","doc":"Phase response to stimulus on the first measured axis","attributes":[{"name":"dimension","doc":"Number of rows and columns in the image. NOTE: row, column representation is equivalent to height,width.","dtype":"int32","shape":[null],"dims":["row_col"]},{"name":"field_of_view","doc":"Size of viewing area, in meters","dtype":"float","shape":[null],"dims":["row|column"]},{"name":"unit","doc":"Unit that axis data is stored in (e.g., degrees)","dtype":"text"}]},{"shape":[null,null],"dims":["num_rows","num_cols"],"dtype":"float32","name":"axis_1_power_map","doc":"Power response on the first measured axis. Response is scaled so 0.0 is no power in the response and 1.0 is maximum relative power.","quantity":"?","attributes":[{"name":"dimension","doc":"Number of rows and columns in the image. NOTE: row, column representation is equivalent to height,width.","dtype":"int32","shape":[null],"dims":["row_col"]},{"name":"field_of_view","doc":"Size of viewing area, in meters","dtype":"float","shape":[null],"dims":["row_col"]},{"name":"unit","doc":"Unit that axis data is stored in (e.g., degrees)","dtype":"text"}]},{"shape":[null,null],"dims":["num_rows","num_cols"],"dtype":"float32","name":"axis_2_phase_map","doc":"Phase response to stimulus on the second measured axis","attributes":[{"name":"dimension","doc":"Number of rows and columns in the image. NOTE: row, column representation is equivalent to height,width.","dtype":"int32","shape":[null],"dims":["row_col"]},{"name":"field_of_view","doc":"Size of viewing area, in meters","dtype":"float","shape":[null],"dims":["row_col"]},{"name":"unit","doc":"Unit that axis data is stored in (e.g., degrees)","dtype":"text"}]},{"shape":[null,null],"dims":["num_rows","num_cols"],"dtype":"float32","name":"axis_2_power_map","doc":"Power response on the second measured axis. Response is scaled so 0.0 is no power in the response and 1.0 is maximum relative power.","quantity":"?","attributes":[{"name":"dimension","doc":"Number of rows and columns in the image. NOTE: row, column representation is equivalent to height,width.","dtype":"int32","shape":[null],"dims":["row_col"]},{"name":"field_of_view","doc":"Size of viewing area, in meters","dtype":"float","shape":[null],"dims":["row_col"]},{"name":"unit","doc":"Unit that axis data is stored in (e.g., degrees)","dtype":"text"}]},{"shape":[null],"dims":["2"],"dtype":"text","name":"axis_descriptions","doc":"Two-element array describing the contents of the two response axis fields. Description should be something like ['altitude', 'azimuth'] or '['radius', 'theta']"},{"shape":[null,null],"dims":["num_rows","num_cols"],"dtype":"uint16","name":"focal_depth_image","doc":"Gray-scale image taken with same settings/parameters (e.g., focal depth, wavelength) as data collection. Array format: [rows][columns]","attributes":[{"name":"bits_per_pixel","doc":"Number of bits used to represent each value. This is necessary to determine maximum (white) pixel value","dtype":"int32"},{"name":"dimension","doc":"Number of rows and columns in the image. NOTE: row, column representation is equivalent to height,width.","dtype":"int32","shape":[null],"dims":["row_col"]},{"name":"field_of_view","doc":"Size of viewing area, in meters","dtype":"float","shape":[null],"dims":["row_col"]},{"name":"focal_depth","doc":"Focal depth offset, in meters","dtype":"float"},{"name":"format","doc":"Format of image. Right now only 'raw' supported","dtype":"text"}]},{"shape":[null,null],"dims":["num_rows","num_cols"],"dtype":"float32","name":"sign_map","doc":"Sine of the angle between the direction of the gradient in axis_1 and axis_2","attributes":[{"name":"dimension","doc":"Number of rows and columns in the image. NOTE: row, column representation is equivalent to height,width.","dtype":"int32","shape":[null],"dims":["row_col"]},{"name":"field_of_view","doc":"Size of viewing area, in meters.","dtype":"float","shape":[null],"dims":["row_col"]}]},{"shape":[null,null],"dims":["num_rows","num_cols"],"dtype":"uint16","name":"vasculature_image","doc":"Gray-scale anatomical image of cortical surface. Array structure: [rows][columns]","attributes":[{"name":"bits_per_pixel","doc":"Number of bits used to represent each value. This is necessary to determine maximum (white) pixel value","dtype":"int32"},{"name":"dimension","doc":"Number of rows and columns in the image. NOTE: row, column representation is equivalent to height,width.","dtype":"int32","shape":[null],"dims":["row_col"]},{"name":"field_of_view","doc":"Size of viewing area, in meters","dtype":"float","shape":[null],"dims":["row_col"]},{"name":"format","doc":"Format of image. Right now only 'raw' supported","dtype":"text"}]}],"doc":"Intrinsic signal optical imaging or widefield imaging for measuring retinotopy. Stores orthogonal maps (e.g., altitude/azimuth; radius/theta) of responses to specific stimuli and a combined polarity map from which to identify visual areas.
Note: for data consistency, all images and arrays are stored in the format [row][column] and [row, col], which equates to [y][x]. Field of view and dimension arrays may appear backward (i.e., y before x).","default_name":"ImagingRetinotopy","neurodata_type_inc":"NWBDataInterface","neurodata_type_def":"ImagingRetinotopy","attributes":[{"name":"help","doc":"Value is 'Intrinsic signal optical imaging or Widefield imaging for measuring retinotopy'","dtype":"text","value":"Intrinsic signal optical imaging or Widefield imaging for measuring retinotopy"}]}]}U{"namespaces":[{"doc":"NWB namespace","schema":[{"source":"nwb.base"},{"source":"nwb.epoch"},{"source":"nwb.image"},{"source":"nwb.file"},{"source":"nwb.misc"},{"source":"nwb.behavior"},{"source":"nwb.ecephys"},{"source":"nwb.icephys"},{"source":"nwb.ogen"},{"source":"nwb.ophys"},{"source":"nwb.retinotopy"}],"name":"core","full_name":"NWB core","version":"2.0.2","author":["Andrew Tritt","Oliver Ruebel","Ryan Ly","Ben Dichter","Keith Godfrey","Jeff Teeters"],"contact":["ajtritt@lbl.gov","oruebel@lbl.gov","rly@lbl.gov","bdichter@lbl.gov","keithg@alleninstitute.org","jteeters@berkeley.edu"]}]}x$pynwb-1.2.1/tests/back_compat/1.0.2_str_pub.nwb0000644000655200065520000003642013612200244022550 0ustar circlecicircleci00000000000000HDF  =` TREEH:HEAP`H0HhTREEHEAPXPSNOD Hh(Pp P,H0XxPp TREEHEAPX P 0 TREEHEAPXP P TREE(HEAPX(presentationtemplates0TREEHEAPXPSNODhpTREEHEAPXPXxTREE*HEAPX related_publications8 @help=<"]GCOLone publication 2019-11-27T17:28:28.258339-08:00ADDMEADDME 2019-11-27T17:28:28.257615-08:00 2019-11-27T17:28:28.257615-08:00=an NWB:N file for storing cellular-based neurophysiology data2.0b core NWBFilexSNOD2"]x2"]2"]2"]acquisitionanalysisprocessingstimulusgeneralfile_create_dateidentifiersession_descriptionsession_start_timetimestamps_reference_time3"]   SNODh-(  0 x(.8/8  1 H nwb_version H namespace Hneurodata_type pynwb-1.2.1/tests/back_compat/test_read.py0000644000655200065520000000202013612200244022155 0ustar circlecicircleci00000000000000from pathlib import Path import warnings from pynwb import NWBHDF5IO, validate from pynwb.testing import TestCase class TestReadOldVersions(TestCase): def test_read(self): """ Attempt to read and validate all NWB files in the same folder as this file. The folder should contain NWB files from previous versions of NWB. See src/pynwb/testing/make_test_files.py for code to generate the NWB files. """ dir_path = Path(__file__).parent nwb_files = dir_path.glob('*.nwb') for f in nwb_files: with self.subTest(file=f.name): with NWBHDF5IO(str(f), 'r') as io: errors = validate(io) io.read() if errors: for e in errors: warnings.warn('%s: %s' % (f.name, e)) # TODO uncomment below when validation errors have been fixed # raise Exception('%d validation error(s). See warnings.' % len(errors)) pynwb-1.2.1/tests/back_compat/1.1.0_str_experimenter.nwb0000644000655200065520000042740013612200244024472 0ustar circlecicircleci00000000000000HDF  /` TREEH1HEAP`H0 0 .speclocpHhTREEHEAPXPSNOD Hh(Pp P,H0XxPp TREEHEAPX P 0 TREEHEAPXP P TREE(HEAPX(presentationtemplates0TREEHEAPXPSNODhpTREEHEAPXPXxTREEHEAPXexperimenter@ H nwb_version<=0?#]xSNODGCOLone experimenter 2019-11-27T17:32:33.693364-08:00ADDMEADDME 2019-11-27T17:32:33.692366-08:00 2019-11-27T17:32:33.692366-08:002.1.0core NWBFile $09c170b8-34a8-4768-8868-213051b95f41 G{"groups":[{"datasets":[{"dtype":"float","name":"start_time","doc":"Start time of epoch, in seconds.","neurodata_type_inc":"VectorData"},{"dtype":"float","name":"stop_time","doc":"Stop time of epoch, in seconds.","neurodata_type_inc":"VectorData"},{"dtype":"text","name":"tags","doc":"User-defined tags that identify or categorize events.","quantity":"?","neurodata_type_inc":"VectorData"},{"name":"tags_index","doc":"Index for tags.","quantity":"?","neurodata_type_inc":"VectorIndex"},{"dtype":[{"doc":"Start index into the TimeSeries 'data' and 'timestamp' datasets of the referenced TimeSeries. The first dimension of those arrays is always time.","name":"idx_start","dtype":"int32"},{"doc":"Number of data samples available in this time series, during this epoch.","name":"count","dtype":"int32"},{"doc":"the TimeSeries that this index applies to.","name":"timeseries","dtype":{"target_type":"TimeSeries","reftype":"object"}}],"name":"timeseries","doc":"An index into a TimeSeries object.","quantity":"?","neurodata_type_inc":"VectorData"},{"name":"timeseries_index","doc":"Index for timeseries.","quantity":"?","neurodata_type_inc":"VectorIndex"}],"doc":"A container for aggregating epoch data and the TimeSeries that each epoch applies to.","neurodata_type_inc":"DynamicTable","neurodata_type_def":"TimeIntervals","attributes":[{"name":"colnames","doc":"The names of the columns in this table. This should be used to specify an order to the columns.","dtype":"ascii","shape":[null],"dims":["num_columns"]},{"name":"description","doc":"Description of what is in this dynamic table.","dtype":"text"}]}]}84#]x4#](4#]84#]acquisitionanalysisprocessingstimulusgeneralfile_create_dateidentifiersession_descriptionsession_start_timetimestamps_reference_timespecificationsSNODh-(  0 x(.8/p=0?8  2H4#]   S'HG y(@x:@x,1@x@x0GBG~ @x,GGUG H namespace Hneurodata_type H object_id$ PTREEhBHEAPXP?coreH?ATREEpFHEAPXB2.1.0HSNOD??ACETREE@pBHEAP`vSNODCCEX4#]GCOLx'S'{"datasets":[{"doc":"An abstract data type for a dataset.","neurodata_type_def":"NWBData"},{"doc":"Pointers that index data values.","neurodata_type_inc":"NWBData","neurodata_type_def":"Index","attributes":[{"name":"target","doc":"Target dataset that this index applies to.","dtype":{"target_type":"NWBData","reftype":"object"}}]},{"doc":"A 1-dimensional dataset. This can be indexed using a VectorIndex to encode a 2-dimensional ragged array in 1 dimension. The first vector is at VectorData[0:VectorIndex(0)+1]. The second vector is at VectorData[VectorIndex(0)+1:VectorIndex(1)+1]. And so on.","neurodata_type_inc":"NWBData","neurodata_type_def":"VectorData","attributes":[{"name":"description","doc":"Description of what these vectors represent.","dtype":"text"}]},{"doc":"An array of indices into the first dimension of the target VectorData. Can be used with VectorData to encode a 2-dimensional ragged array in 1 dimension.","neurodata_type_inc":"Index","neurodata_type_def":"VectorIndex","attributes":[{"name":"target","doc":"Reference to the target dataset that this index applies to.","dtype":{"target_type":"VectorData","reftype":"object"}}]},{"shape":[null],"dims":["num_elements"],"dtype":"int","doc":"A list of unique identifiers for values within a dataset, e.g. rows of a DynamicTable.","default_name":"element_id","neurodata_type_inc":"NWBData","neurodata_type_def":"ElementIdentifiers"},{"dtype":"int","doc":"A region/index into a DynamicTable.","neurodata_type_inc":"VectorData","neurodata_type_def":"DynamicTableRegion","attributes":[{"name":"table","doc":"Reference to the DynamicTable object that this region applies to.","dtype":{"target_type":"DynamicTable","reftype":"object"}},{"name":"description","doc":"Description of what this table region points to.","dtype":"text"}]},{"shape":[[null,null],[null,null,3],[null,null,4]],"dims":[["num_x","num_y"],["num_x","num_y","(r, g, b)"],["num_x","num_y","(r, g, b, a)"]],"doc":"An abstract data type for an image. Shape can be 2-D (x, y), or 3-D where the third dimension can have three or four elements, e.g. (x, y, (r, g, b)) or (x, y, (r, g, b, a)).","neurodata_type_inc":"NWBData","neurodata_type_def":"Image","attributes":[{"name":"resolution","doc":"Pixel resolution of the image, in pixels per centimeter.","required":false,"dtype":"float"},{"name":"description","doc":"Description of the image.","required":false,"dtype":"text"}]}],"groups":[{"doc":"An abstract data type for a generic container storing collections of data and metadata. Base type for all data and metadata containers.","neurodata_type_def":"NWBContainer"},{"doc":"An abstract data type for a generic container storing collections of data, as opposed to metadata.","neurodata_type_inc":"NWBContainer","neurodata_type_def":"NWBDataInterface"},{"groups":[{"name":"sync","doc":"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. 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.","quantity":"?"}],"datasets":[{"shape":[[null],[null,null],[null,null,null],[null,null,null,null]],"dims":[["num_times"],["num_times","num_DIM2"],["num_times","num_DIM2","num_DIM3"],["num_times","num_DIM2","num_DIM3","num_DIM4"]],"name":"data","doc":"Data values. Data can be in 1-D, 2-D, 3-D, or 4-D. The first dimension should always represent time. This can also be used to store binary data (e.g., image frames). This can also be a link to data stored in an external file.","attributes":[{"name":"conversion","doc":"Scalar to multiply each element in data to convert it to the specified 'unit'. If the data are stored in acquisition system units or other units that require a conversion to be interpretable, multiply the data by 'conversion' to convert the data to the specified 'unit'. e.g. if the data acquisition system stores values in this object as signed 16-bit integers (int16 range -32,768 to 32,767) that correspond to a 5V range (-2.5V to 2.5V), and the data acquisition system gain is 8000X, then the 'conversion' multiplier to get from raw data acquisition values to recorded volts is 2.5/32768/8000 = 9.5367e-9.","required":false,"dtype":"float32","default_value":1.0},{"name":"resolution","doc":"Smallest meaningful difference between values in data, stored in the specified by unit, 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 -1.0.","required":false,"dtype":"float32","default_value":-1.0},{"name":"unit","doc":"Base unit of measurement for working with the data. Actual stored values are not necessarily stored in these units. To access the data in these units, multiply 'data' by 'conversion'.","dtype":"text"}]},{"dtype":"float64","name":"starting_time","doc":"Timestamp of the first sample in seconds. When timestamps are uniformly spaced, the timestamp of the first sample can be specified and all subsequent ones calculated from the sampling rate attribute.","quantity":"?","attributes":[{"name":"rate","doc":"Sampling rate, in Hz.","dtype":"float32"},{"name":"unit","doc":"Unit of measurement for time, which is fixed to 'seconds'.","dtype":"text","value":"seconds"}]},{"shape":[null],"dims":["num_times"],"dtype":"float64","name":"timestamps","doc":"Timestamps for samples stored in data, in seconds, relative to the common experiment master-clock stored in NWBFile.timestamps_reference_time.","quantity":"?","attributes":[{"name":"interval","doc":"Value is '1'","dtype":"int32","value":1},{"name":"unit","doc":"Unit of measurement for timestamps, which is fixed to 'seconds'.","dtype":"text","value":"seconds"}]},{"shape":[null],"dims":["num_times"],"dtype":"uint8","name":"control","doc":"Numerical labels that apply to each time point in data for the purpose of querying and slicing data by these values. If present, the length of this array should be the same size as the first dimension of data.","quantity":"?"},{"shape":[null],"dims":["num_control_values"],"dtype":"text","name":"control_description","doc":"Description of each control value. Must be present if control is present. If present, control_description[0] should describe time points where control == 0.","quantity":"?"}],"doc":"General purpose time series.","neurodata_type_inc":"NWBDataInterface","neurodata_type_def":"TimeSeries","attributes":[{"name":"description","doc":"Description of the time series.","required":false,"dtype":"text","default_value":"no description"},{"name":"comments","doc":"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.","required":false,"dtype":"text","default_value":"no comments"}]},{"groups":[{"doc":"Data objects stored in this collection.","quantity":"*","neurodata_type_inc":"NWBDataInterface"}],"doc":"A collection of processed data.","neurodata_type_inc":"NWBContainer","neurodata_type_def":"ProcessingModule","attributes":[{"name":"description","doc":"Description of this collection of processed data.","dtype":"text"}]},{"datasets":[{"doc":"Images stored in this collection.","quantity":"+","neurodata_type_inc":"Image"}],"doc":"A collection of images.","default_name":"Images","neurodata_type_inc":"NWBDataInterface","neurodata_type_def":"Images","attributes":[{"name":"description","doc":"Description of this collection of images.","dtype":"text"}]},{"datasets":[{"shape":[null],"dims":["num_rows"],"dtype":"int","name":"id","doc":"Array of unique identifiers for the rows of this dynamic table.","neurodata_type_inc":"ElementIdentifiers"},{"doc":"Vector columns of this dynamic table.","quantity":"*","neurodata_type_inc":"VectorData"},{"doc":"Indices for the vector columns of this dynamic table.","quantity":"*","neurodata_type_inc":"VectorIndex"}],"doc":"A group containing multiple datasets that are aligned on the first dimension (Currently, this requirement if left up to APIs to check and enforce). Apart from a column that contains unique identifiers for each row there are no other required datasets. Users are free to add any number of VectorData objects here. Table functionality is already supported through compound types, which is analogous to storing an array-of-structs. DynamicTable can be thought of as a struct-of-arrays. This provides an alternative structure to choose from when optimizing storage for anticipated access patterns. Additionally, this type provides a way of creating a table without having to define a compound type up front. Although this convenience may be attractive, users should think carefully about how data will be accessed. DynamicTable is more appropriate for column-centric access, whereas a dataset with a compound type would be more appropriate for row-centric access. Finally, data size should also be taken into account. For small tables, performance loss may be an acceptable trade-off for the flexibility of a DynamicTable. For example, DynamicTable was originally developed for storing trial data and spike unit metadata. Both of these use cases are expected to produce relatively small tables, so the spatial locality of multiple datasets present in a DynamicTable is not expected to have a significant performance impact. Additionally, requirements of trial and unit metadata tables are sufficiently diverse that performance implications can be overlooked in favor of usability.","neurodata_type_inc":"NWBDataInterface","neurodata_type_def":"DynamicTable","attributes":[{"name":"colnames","doc":"The names of the columns in this table. This should be used to specify an order to the columns.","dtype":"ascii","shape":[null],"dims":["num_columns"]},{"name":"description","doc":"Description of what is in this dynamic table.","dtype":"text"}]}]}SNOD(FGXuh?qh4#]x4#]4#]4#]4#]nwb.basenwb.epochnwb.imagenwb.filenwb.miscnwb.behaviornwb.ecephysnwb.icephysnwb.ogennwb.ophysnwb.retinotopynamespaceGCOLPy({"datasets":[{"shape":[null,null],"dims":["y","x"],"doc":"A grayscale image.","neurodata_type_inc":"Image","neurodata_type_def":"GrayscaleImage","attributes":[{"name":"resolution","doc":"Pixel resolution of the image, in pixels per centimeter.","required":false,"dtype":"float"},{"name":"description","doc":"Description of the image.","required":false,"dtype":"text"}]},{"shape":[null,null,3],"dims":["y","x","R, G, B"],"doc":"A color image.","neurodata_type_inc":"Image","neurodata_type_def":"RGBImage","attributes":[{"name":"resolution","doc":"Pixel resolution of the image, in pixels per centimeter.","required":false,"dtype":"float"},{"name":"description","doc":"Description of the image.","required":false,"dtype":"text"}]},{"shape":[null,null,4],"dims":["y","x","R, G, B, A"],"doc":"A color image with transparency.","neurodata_type_inc":"Image","neurodata_type_def":"RGBAImage","attributes":[{"name":"resolution","doc":"Pixel resolution of the image, in pixels per centimeter.","required":false,"dtype":"float"},{"name":"description","doc":"Description of the image.","required":false,"dtype":"text"}]}],"groups":[{"datasets":[{"shape":[[null,null,null],[null,null,null,null]],"dims":[["frame","y","x"],["frame","z","y","x"]],"dtype":"numeric","name":"data","doc":"Binary data representing images across frames.","quantity":"?","attributes":[{"name":"conversion","doc":"Scalar to multiply each element in data to convert it to the specified 'unit'. If the data are stored in acquisition system units or other units that require a conversion to be interpretable, multiply the data by 'conversion' to convert the data to the specified 'unit'. e.g. if the data acquisition system stores values in this object as signed 16-bit integers (int16 range -32,768 to 32,767) that correspond to a 5V range (-2.5V to 2.5V), and the data acquisition system gain is 8000X, then the 'conversion' multiplier to get from raw data acquisition values to recorded volts is 2.5/32768/8000 = 9.5367e-9.","required":false,"dtype":"float32","default_value":1.0},{"name":"resolution","doc":"Smallest meaningful difference between values in data, stored in the specified by unit, 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 -1.0.","required":false,"dtype":"float32","default_value":-1.0},{"name":"unit","doc":"Base unit of measurement for working with the data. Actual stored values are not necessarily stored in these units. To access the data in these units, multiply 'data' by 'conversion'.","dtype":"text"}]},{"shape":[null],"dims":["rank"],"dtype":"int32","name":"dimension","doc":"Number of pixels on x, y, (and z) axes.","quantity":"?"},{"shape":[null],"dims":["num_files"],"dtype":"text","name":"external_file","doc":"Paths to one or more external file(s). The field is only present if format='external'. This is only relevant if the image series is stored in the file system as one or more image file(s). This field should NOT be used if the image is stored in another NWB file and that file is linked to this file.","quantity":"?","attributes":[{"name":"starting_frame","doc":"Each external image may contain one or more consecutive frames of the full ImageSeries. This attribute serves as an index to indicate which frames each file contains, to faciliate random access. The 'starting_frame' attribute, hence, contains a list of frame numbers within the full ImageSeries of the first frame of each file listed in the parent 'external_file' dataset. Zero-based indexing is used (hence, the first element will always be zero). For example, if the 'external_file' dataset has three paths to files and the first file has 5 frames, the second file has 10 frames, and the third file has 20 frames, then this attribute will have values [0, 5, 15]. If there is a single external file that holds all of the frames of the ImageSeries (and so there is a single element in the 'external_file' dataset), then this attribute should have value [0].","dtype":"int","shape":[null],"dims":["num_files"]}]},{"dtype":"text","name":"format","doc":"Format of image. If this is 'external', then the attribute 'external_file' contains the path information to the image files. If this is 'raw', then the raw (single-channel) binary data is stored in the 'data' dataset. If this attribute is not present, then the default format='raw' case is assumed.","quantity":"?","default_value":"raw"}],"doc":"General image data that is common between acquisition and stimulus time series. Sometimes the image data is stored in the file in a raw format while other times it will be stored as a series of external image files in the host file system. The data field will either be binary data, if the data is stored in the NWB file, or empty, if the data is stored in an external image stack. [frame][y][x] or [frame][z][y][x].","neurodata_type_inc":"TimeSeries","neurodata_type_def":"ImageSeries","attributes":[{"name":"description","doc":"Description of the time series.","required":false,"dtype":"text","default_value":"no description"},{"name":"comments","doc":"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.","required":false,"dtype":"text","default_value":"no comments"}]},{"links":[{"name":"masked_imageseries","doc":"Link to ImageSeries object that this image mask is applied to.","target_type":"ImageSeries"}],"doc":"An alpha mask that is applied to a presented visual stimulus. The 'data' array contains an array of mask values that are applied to the displayed image. Mask values are stored as RGBA. Mask can vary with time. The timestamps array indicates the starting time of a mask, and that mask pattern continues until it's explicitly changed.","neurodata_type_inc":"ImageSeries","neurodata_type_def":"ImageMaskSeries","attributes":[{"name":"description","doc":"Description of the time series.","required":false,"dtype":"text","default_value":"no description"},{"name":"comments","doc":"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.","required":false,"dtype":"text","default_value":"no comments"}]},{"datasets":[{"dtype":"float32","name":"distance","doc":"Distance from camera/monitor to target/eye.","quantity":"?"},{"shape":[[2],[3]],"dims":[["width, height"],["width, height, depth"]],"dtype":"float32","name":"field_of_view","doc":"Width, height and depth of image, or imaged area, in meters.","quantity":"?"},{"dtype":"text","name":"orientation","doc":"Description of image relative to some reference frame (e.g., which way is up). Must also specify frame of reference.","quantity":"?"}],"doc":"Image data that is presented or recorded. A stimulus template movie will be stored only as an image. When the image is presented as stimulus, additional data is required, such as field of view (e.g., how much of the visual field the image covers, or how what is the area of the target being imaged). If the OpticalSeries represents acquired imaging data, orientation is also important.","neurodata_type_inc":"ImageSeries","neurodata_type_def":"OpticalSeries","attributes":[{"name":"description","doc":"Description of the time series.","required":false,"dtype":"text","default_value":"no description"},{"name":"comments","doc":"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.","required":false,"dtype":"text","default_value":"no comments"}]},{"datasets":[{"shape":[null],"dims":["num_times"],"dtype":"int","name":"data","doc":"Index of the frame in the referenced ImageSeries.","attributes":[{"name":"conversion","doc":"Scalar to multiply each element in data to convert it to the specified 'unit'. If the data are stored in acquisition system units or other units that require a conversion to be interpretable, multiply the data by 'conversion' to convert the data to the specified 'unit'. e.g. if the data acquisition system stores values in this object as signed 16-bit integers (int16 range -32,768 to 32,767) that correspond to a 5V range (-2.5V to 2.5V), and the data acquisition system gain is 8000X, then the 'conversion' multiplier to get from raw data acquisition values to recorded volts is 2.5/32768/8000 = 9.5367e-9.","required":false,"dtype":"float32","default_value":1.0},{"name":"resolution","doc":"Smallest meaningful difference between values in data, stored in the specified by unit, 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 -1.0.","required":false,"dtype":"float32","default_value":-1.0},{"name":"unit","doc":"Base unit of measurement for working with the data. Actual stored values are not necessarily stored in these units. To access the data in these units, multiply 'data' by 'conversion'.","dtype":"text"}]}],"links":[{"name":"indexed_timeseries","doc":"Link to ImageSeries object containing images that are indexed.","target_type":"ImageSeries"}],"doc":"Stores indices to image frames stored in an ImageSeries. The purpose of the ImageIndexSeries 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 ImageSeries, and the timestamps array indicates when that image was displayed.","neurodata_type_inc":"TimeSeries","neurodata_type_def":"IndexSeries","attributes":[{"name":"description","doc":"Description of the time series.","required":false,"dtype":"text","default_value":"no description"},{"name":"comments","doc":"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.","required":false,"dtype":"text","default_value":"no comments"}]}]}:{"groups":[{"groups":[{"groups":[{"doc":"Acquired, raw data.","quantity":"*","neurodata_type_inc":"NWBDataInterface"}],"name":"acquisition","doc":"Data streams recorded from the system, including ephys, ophys, tracking, etc. This group should be 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 NWB files. This will allow keeping bulky raw data out of the file while preserving the option of keeping some/all in the file. Acquired data includes tracking and experimental data streams (i.e., everything measured from the system). If bulky data is stored in the /acquisition group, the data can exist in a separate NWB file that is linked to by the file being used for processing and analysis."},{"groups":[{"doc":"Custom analysis results.","quantity":"*","neurodata_type_inc":"NWBContainer"}],"name":"analysis","doc":"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. To facilitate sharing analysis data between labs, the contents here should be stored in standard types (e.g., neurodata_types) and appropriately documented. 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 could be shared with other labs."},{"groups":[{"doc":"Any one-off containers","quantity":"*","neurodata_type_inc":"NWBContainer"}],"datasets":[{"doc":"Any one-off datasets","quantity":"*","neurodata_type_inc":"NWBData","neurodata_type_def":"ScratchData","attributes":[{"name":"notes","doc":"Any notes the user has about the dataset being stored","dtype":"text"}]}],"name":"scratch","doc":"A place to store one-off analysis results. Data placed here is not intended for sharing. By placing data here, users acknowledge that there is no guarantee that their data meets any standard.","quantity":"?"},{"groups":[{"doc":"Intermediate analysis of acquired data.","quantity":"*","neurodata_type_inc":"ProcessingModule"}],"name":"processing","doc":"The home for ProcessingModules. 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. ProcessingModules 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. 'Processing' refers to intermediate analysis of the acquired data to make it more amenable to scientific analysis."},{"groups":[{"groups":[{"doc":"TimeSeries objects containing data of presented stimuli.","quantity":"*","neurodata_type_inc":"TimeSeries"}],"name":"presentation","doc":"Stimuli presented during the experiment."},{"groups":[{"doc":"TimeSeries objects containing template data of presented stimuli.","quantity":"*","neurodata_type_inc":"TimeSeries"}],"name":"templates","doc":"Template stimuli. Timestamps 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."}],"name":"stimulus","doc":"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). This group should be made 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. 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 linked to a remote library file."},{"groups":[{"doc":"Place-holder than can be extended so that lab-specific meta-data can be placed in /general.","quantity":"*","neurodata_type_inc":"NWBContainer","neurodata_type_def":"LabMetaData"},{"groups":[{"doc":"A data acquisition device, e.g. recording system.","quantity":"+","neurodata_type_inc":"NWBContainer","neurodata_type_def":"Device"}],"name":"devices","doc":"Description of hardware devices used during experiment, e.g., monitors, ADC boards, microscopes, etc.","quantity":"?"},{"datasets":[{"dtype":"text","name":"age","doc":"Age of subject. Can be supplied instead of 'date_of_birth'.","quantity":"?"},{"dtype":"isodatetime","name":"date_of_birth","doc":"Date of birth of subject. Can be supplied instead of 'age'.","quantity":"?"},{"dtype":"text","name":"description","doc":"Description of subject and where subject came from (e.g., breeder, if animal).","quantity":"?"},{"dtype":"text","name":"genotype","doc":"Genetic strain. If absent, assume Wild Type (WT).","quantity":"?"},{"dtype":"text","name":"sex","doc":"Gender of subject.","quantity":"?"},{"dtype":"text","name":"species","doc":"Species of subject.","quantity":"?"},{"dtype":"text","name":"subject_id","doc":"ID of animal/person used/participating in experiment (lab convention).","quantity":"?"},{"dtype":"text","name":"weight","doc":"Weight at time of experiment, at time of surgery and at other important times.","quantity":"?"}],"name":"subject","doc":"Information about the animal or person from which the data was measured.","quantity":"?","neurodata_type_inc":"NWBContainer","neurodata_type_def":"Subject"},{"groups":[{"doc":"Physical group of electrodes.","quantity":"*","neurodata_type_inc":"ElectrodeGroup"},{"datasets":[{"dtype":"float","name":"x","doc":"x coordinate of the channel location.","neurodata_type_inc":"VectorData"},{"dtype":"float","name":"y","doc":"y coordinate of the channel location.","neurodata_type_inc":"VectorData"},{"dtype":"float","name":"z","doc":"z coordinate of the channel location.","neurodata_type_inc":"VectorData"},{"dtype":"float","name":"imp","doc":"Impedance of the channel.","neurodata_type_inc":"VectorData"},{"dtype":"ascii","name":"location","doc":"Location of the electrode (channel). Specify the area, layer, comments on estimation of area/layer, stereotaxic coordinates if in vivo, etc. Use standard atlas names for anatomical regions when possible.","neurodata_type_inc":"VectorData"},{"dtype":"float","name":"filtering","doc":"Description of hardware filtering.","neurodata_type_inc":"VectorData"},{"dtype":{"target_type":"ElectrodeGroup","reftype":"object"},"name":"group","doc":"Reference to the ElectrodeGroup this electrode is a part of.","neurodata_type_inc":"VectorData"},{"dtype":"ascii","name":"group_name","doc":"Name of the ElectrodeGroup this electrode is a part of.","neurodata_type_inc":"VectorData"}],"name":"electrodes","doc":"A table of all electrodes (i.e. channels) used for recording.","quantity":"?","neurodata_type_inc":"DynamicTable"}],"name":"extracellular_ephys","doc":"Metadata related to extracellular electrophysiology.","quantity":"?"},{"groups":[{"doc":"An intracellular electrode.","quantity":"*","neurodata_type_inc":"IntracellularElectrode"},{"name":"sweep_table","doc":"The table which groups different PatchClampSeries together.","quantity":"?","neurodata_type_inc":"SweepTable"}],"datasets":[{"dtype":"text","name":"filtering","doc":"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.","quantity":"?"}],"name":"intracellular_ephys","doc":"Metadata related to intracellular electrophysiology.","quantity":"?"},{"groups":[{"doc":"An optogenetic stimulation site.","quantity":"*","neurodata_type_inc":"OptogeneticStimulusSite"}],"name":"optogenetics","doc":"Metadata describing optogenetic stimuluation.","quantity":"?"},{"groups":[{"doc":"An imaging plane.","quantity":"*","neurodata_type_inc":"ImagingPlane"}],"name":"optophysiology","doc":"Metadata related to optophysiology.","quantity":"?"}],"datasets":[{"dtype":"text","name":"data_collection","doc":"Notes about data collection and analysis.","quantity":"?"},{"dtype":"text","name":"experiment_description","doc":"General description of the experiment.","quantity":"?"},{"shape":[null],"dims":["num_experimenters"],"dtype":"text","name":"experimenter","doc":"Name of person(s) who performed the experiment. Can also specify roles of different people involved.","quantity":"?"},{"dtype":"text","name":"institution","doc":"Institution(s) where experiment was performed.","quantity":"?"},{"shape":[null],"dims":["num_keywords"],"dtype":"text","name":"keywords","doc":"Terms to search over.","quantity":"?"},{"dtype":"text","name":"lab","doc":"Laboratory where experiment was performed.","quantity":"?"},{"dtype":"text","name":"notes","doc":"Notes about the experiment.","quantity":"?"},{"dtype":"text","name":"pharmacology","doc":"Description of drugs used, including how and when they were administered. Anesthesia(s), painkiller(s), etc., plus dosage, concentration, etc.","quantity":"?"},{"dtype":"text","name":"protocol","doc":"Experimental protocol, if applicable. e.g., include IACUC protocol number.","quantity":"?"},{"shape":[null],"dims":["num_publications"],"dtype":"text","name":"related_publications","doc":"Publication information. PMID, DOI, URL, etc.","quantity":"?"},{"dtype":"text","name":"session_id","doc":"Lab-specific ID for the session.","quantity":"?"},{"dtype":"text","name":"slices","doc":"Description of slices, including information about preparation thickness, orientation, temperature, and bath solution.","quantity":"?"},{"dtype":"text","name":"source_script","doc":"Script file or link to public source code used to create this NWB file.","quantity":"?","attributes":[{"name":"file_name","doc":"Name of script file.","dtype":"text"}]},{"dtype":"text","name":"stimulus","doc":"Notes about stimuli, such as how and where they were presented.","quantity":"?"},{"dtype":"text","name":"surgery","doc":"Narrative description about surgery/surgeries, including date(s) and who performed surgery.","quantity":"?"},{"dtype":"text","name":"virus","doc":"Information about virus(es) used in experiments, including virus ID, source, date made, injection location, volume, etc.","quantity":"?"}],"name":"general","doc":"Experimental metadata, including protocol, notes and description of hardware device(s). The metadata stored in this section should be used to describe the experiment. Metadata necessary for interpreting the data is stored with the data. 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 (e.g., 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. 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."},{"groups":[{"name":"epochs","doc":"Divisions in time marking experimental stages or sub-divisions of a single recording session.","quantity":"?","neurodata_type_inc":"TimeIntervals"},{"name":"trials","doc":"Repeated experimental events that have a logical grouping.","quantity":"?","neurodata_type_inc":"TimeIntervals"},{"name":"invalid_times","doc":"Time intervals that should be removed from analysis.","quantity":"?","neurodata_type_inc":"TimeIntervals"},{"doc":"Optional additional table(s) for describing other experimental time intervals.","quantity":"*","neurodata_type_inc":"TimeIntervals"}],"name":"intervals","doc":"Experimental intervals, whether that be logically distinct sub-experiments having a particular scientific goal, trials (see trials subgroup) during an experiment, or epochs (see epochs subgroup) deriving from analysis of data.","quantity":"?"},{"name":"units","doc":"Data about sorted spike units.","quantity":"?","neurodata_type_inc":"Units"}],"datasets":[{"shape":[null],"dims":["num_modifications"],"dtype":"isodatetime","name":"file_create_date","doc":"A record of the date the file was created and of subsequent modifications. The date is stored in UTC with local timezone offset as ISO 8601 extended formatted strings: 2018-09-28T14:43:54.123+02:00. Dates stored in UTC end in \"Z\" with no timezone offset. Date accuracy is up to milliseconds. The file can be created after the experiment was run, so this may differ from the experiment start time. Each modification to the nwb file adds a new entry to the array."},{"dtype":"text","name":"identifier","doc":"A unique text identifier for the file. For example, 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."},{"dtype":"text","name":"session_description","doc":"A description of the experimental session and data in the file."},{"dtype":"isodatetime","name":"session_start_time","doc":"Date and time of the experiment/session start. The date is stored in UTC with local timezone offset as ISO 8601 extended formatted string: 2018-09-28T14:43:54.123+02:00. Dates stored in UTC end in \"Z\" with no timezone offset. Date accuracy is up to milliseconds."},{"dtype":"isodatetime","name":"timestamps_reference_time","doc":"Date and time corresponding to time zero of all timestamps. The date is stored in UTC with local timezone offset as ISO 8601 extended formatted string: 2018-09-28T14:43:54.123+02:00. Dates stored in UTC end in \"Z\" with no timezone offset. Date accuracy is up to milliseconds. All times stored in the file use this time as reference (i.e., time zero)."}],"name":"root","doc":"An NWB:N file storing cellular-based neurophysiology data from a single experimental session.","neurodata_type_inc":"NWBContainer","neurodata_type_def":"NWBFile","attributes":[{"name":"nwb_version","doc":"File version string. Use semantic versioning, e.g. 1.2.1. This will be the name of the format with trailing major, minor and patch numbers.","dtype":"text","value":"2.1.0"}]}]},1{"groups":[{"datasets":[{"shape":[[null],[null,null]],"dims":[["num_times"],["num_times","num_features"]],"dtype":"numeric","name":"data","doc":"Values of each feature at each time.","attributes":[{"name":"unit","doc":"Since there can be different units for different features, store the units in 'feature_units'. The default value for this attribute is \"see 'feature_units'\".","required":false,"dtype":"text","default_value":"see 'feature_units'"},{"name":"conversion","doc":"Scalar to multiply each element in data to convert it to the specified 'unit'. If the data are stored in acquisition system units or other units that require a conversion to be interpretable, multiply the data by 'conversion' to convert the data to the specified 'unit'. e.g. if the data acquisition system stores values in this object as signed 16-bit integers (int16 range -32,768 to 32,767) that correspond to a 5V range (-2.5V to 2.5V), and the data acquisition system gain is 8000X, then the 'conversion' multiplier to get from raw data acquisition values to recorded volts is 2.5/32768/8000 = 9.5367e-9.","required":false,"dtype":"float32","default_value":1.0},{"name":"resolution","doc":"Smallest meaningful difference between values in data, stored in the specified by unit, 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 -1.0.","required":false,"dtype":"float32","default_value":-1.0}]},{"shape":[null],"dims":["num_features"],"dtype":"text","name":"feature_units","doc":"Units of each feature.","quantity":"?"},{"shape":[null],"dims":["num_features"],"dtype":"text","name":"features","doc":"Description of the features represented in TimeSeries::data."}],"doc":"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. This is useful when storing the raw stimulus is impractical.","neurodata_type_inc":"TimeSeries","neurodata_type_def":"AbstractFeatureSeries","attributes":[{"name":"description","doc":"Description of the time series.","required":false,"dtype":"text","default_value":"no description"},{"name":"comments","doc":"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.","required":false,"dtype":"text","default_value":"no comments"}]},{"datasets":[{"shape":[null],"dims":["num_times"],"dtype":"text","name":"data","doc":"Annotations made during an experiment.","attributes":[{"name":"resolution","doc":"Smallest meaningful difference between values in data. Annotations have no units, so the value is fixed to -1.0.","dtype":"float","value":-1.0},{"name":"unit","doc":"Base unit of measurement for working with the data. Annotations have no units, so the value is fixed to 'n/a'.","dtype":"text","value":"n/a"},{"name":"conversion","doc":"Scalar to multiply each element in data to convert it to the specified 'unit'. If the data are stored in acquisition system units or other units that require a conversion to be interpretable, multiply the data by 'conversion' to convert the data to the specified 'unit'. e.g. if the data acquisition system stores values in this object as signed 16-bit integers (int16 range -32,768 to 32,767) that correspond to a 5V range (-2.5V to 2.5V), and the data acquisition system gain is 8000X, then the 'conversion' multiplier to get from raw data acquisition values to recorded volts is 2.5/32768/8000 = 9.5367e-9.","required":false,"dtype":"float32","default_value":1.0}]}],"doc":"Stores user annotations made during an experiment. The 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.","neurodata_type_inc":"TimeSeries","neurodata_type_def":"AnnotationSeries","attributes":[{"name":"description","doc":"Description of the time series.","required":false,"dtype":"text","default_value":"no description"},{"name":"comments","doc":"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.","required":false,"dtype":"text","default_value":"no comments"}]},{"datasets":[{"shape":[null],"dims":["num_times"],"dtype":"int8","name":"data","doc":"Use values >0 if interval started, <0 if interval ended.","attributes":[{"name":"resolution","doc":"Smallest meaningful difference between values in data. Annotations have no units, so the value is fixed to -1.0.","dtype":"float","value":-1.0},{"name":"unit","doc":"Base unit of measurement for working with the data. Annotations have no units, so the value is fixed to 'n/a'.","dtype":"text","value":"n/a"},{"name":"conversion","doc":"Scalar to multiply each element in data to convert it to the specified 'unit'. If the data are stored in acquisition system units or other units that require a conversion to be interpretable, multiply the data by 'conversion' to convert the data to the specified 'unit'. e.g. if the data acquisition system stores values in this object as signed 16-bit integers (int16 range -32,768 to 32,767) that correspond to a 5V range (-2.5V to 2.5V), and the data acquisition system gain is 8000X, then the 'conversion' multiplier to get from raw data acquisition values to recorded volts is 2.5/32768/8000 = 9.5367e-9.","required":false,"dtype":"float32","default_value":1.0}]}],"doc":"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.","neurodata_type_inc":"TimeSeries","neurodata_type_def":"IntervalSeries","attributes":[{"name":"description","doc":"Description of the time series.","required":false,"dtype":"text","default_value":"no description"},{"name":"comments","doc":"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.","required":false,"dtype":"text","default_value":"no comments"}]},{"groups":[{"datasets":[{"dtype":"text","name":"band_name","doc":"Name of the band, e.g. theta.","neurodata_type_inc":"VectorData"},{"shape":[null,2],"dims":["num_bands","low, high"],"dtype":"float","name":"band_limits","doc":"Low and high limit of each band in Hz. If it is a Gaussian filter, use 2 SD on either side of the center.","neurodata_type_inc":"VectorData"},{"shape":[null],"dims":["num_bands"],"dtype":"float","name":"band_mean","doc":"The mean Gaussian filters, in Hz.","neurodata_type_inc":"VectorData"},{"shape":[null],"dims":["num_bands"],"dtype":"float","name":"band_stdev","doc":"The standard deviation of Gaussian filters, in Hz.","neurodata_type_inc":"VectorData"}],"name":"bands","doc":"Table for describing the bands that this series was generated from. There should be one row in this table for each band.","neurodata_type_inc":"DynamicTable"}],"datasets":[{"shape":[null,null,null],"dims":["num_times","num_channels","num_bands"],"dtype":"numeric","name":"data","doc":"Data decomposed into frequency bands.","attributes":[{"name":"unit","doc":"Base unit of measurement for working with the data. Actual stored values are not necessarily stored in these units. To access the data in these units, multiply 'data' by 'conversion'.","required":false,"dtype":"text","default_value":"no unit"},{"name":"conversion","doc":"Scalar to multiply each element in data to convert it to the specified 'unit'. If the data are stored in acquisition system units or other units that require a conversion to be interpretable, multiply the data by 'conversion' to convert the data to the specified 'unit'. e.g. if the data acquisition system stores values in this object as signed 16-bit integers (int16 range -32,768 to 32,767) that correspond to a 5V range (-2.5V to 2.5V), and the data acquisition system gain is 8000X, then the 'conversion' multiplier to get from raw data acquisition values to recorded volts is 2.5/32768/8000 = 9.5367e-9.","required":false,"dtype":"float32","default_value":1.0},{"name":"resolution","doc":"Smallest meaningful difference between values in data, stored in the specified by unit, 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 -1.0.","required":false,"dtype":"float32","default_value":-1.0}]},{"dtype":"text","name":"metric","doc":"The metric used, e.g. phase, amplitude, power."}],"links":[{"name":"source_timeseries","doc":"Link to TimeSeries object that this data was calculated from. Metadata about electrodes and their position can be read from that ElectricalSeries so it is not necessary to store that information here.","target_type":"TimeSeries","quantity":"?"}],"doc":"Spectral analysis of a time series, e.g. of an LFP or a speech signal.","neurodata_type_inc":"TimeSeries","neurodata_type_def":"DecompositionSeries","attributes":[{"name":"description","doc":"Description of the time series.","required":false,"dtype":"text","default_value":"no description"},{"name":"comments","doc":"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.","required":false,"dtype":"text","default_value":"no comments"}]},{"datasets":[{"name":"spike_times_index","doc":"Index into the spike_times dataset.","quantity":"?","neurodata_type_inc":"VectorIndex"},{"dtype":"double","name":"spike_times","doc":"Spike times for each unit.","quantity":"?","neurodata_type_inc":"VectorData"},{"name":"obs_intervals_index","doc":"Index into the obs_intervals dataset.","quantity":"?","neurodata_type_inc":"VectorIndex"},{"shape":[null,2],"dims":["num_intervals","start|end"],"dtype":"double","name":"obs_intervals","doc":"Observation intervals for each unit.","quantity":"?","neurodata_type_inc":"VectorData"},{"name":"electrodes_index","doc":"Index into electrodes.","quantity":"?","neurodata_type_inc":"VectorIndex"},{"name":"electrodes","doc":"Electrode that each spike unit came from, specified using a DynamicTableRegion.","quantity":"?","neurodata_type_inc":"DynamicTableRegion"},{"dtype":{"target_type":"ElectrodeGroup","reftype":"object"},"name":"electrode_group","doc":"Electrode group that each spike unit came from.","quantity":"?","neurodata_type_inc":"VectorData"},{"shape":[[null,null],[null,null,null]],"dims":[["num_units","num_samples"],["num_units","num_samples","num_electrodes"]],"dtype":"float","name":"waveform_mean","doc":"Spike waveform mean for each spike unit.","quantity":"?","neurodata_type_inc":"VectorData"},{"shape":[[null,null],[null,null,null]],"dims":[["num_units","num_samples"],["num_units","num_samples","num_electrodes"]],"dtype":"float","name":"waveform_sd","doc":"Spike waveform standard deviation for each spike unit.","quantity":"?","neurodata_type_inc":"VectorData"}],"doc":"Data about spiking units. Event times of observed units (e.g. cell, synapse, etc.) should be concatenated and stored in spike_times.","default_name":"Units","neurodata_type_inc":"DynamicTable","neurodata_type_def":"Units","attributes":[{"name":"colnames","doc":"The names of the columns in this table. This should be used to specify an order to the columns.","dtype":"ascii","shape":[null],"dims":["num_columns"]},{"name":"description","doc":"Description of what is in this dynamic table.","dtype":"text"}]}]}{"groups":[{"datasets":[{"shape":[[null],[null,null]],"dims":[["num_times"],["num_times","num_features"]],"dtype":"numeric","name":"data","doc":"1-D or 2-D array storing position or direction relative to some reference frame.","attributes":[{"name":"unit","doc":"Base unit of measurement for working with the data. The default value is 'meters'. Actual stored values are not necessarily stored in these units. To access the data in these units, multiply 'data' by 'conversion'.","required":false,"dtype":"text","default_value":"meters"},{"name":"conversion","doc":"Scalar to multiply each element in data to convert it to the specified 'unit'. If the data are stored in acquisition system units or other units that require a conversion to be interpretable, multiply the data by 'conversion' to convert the data to the specified 'unit'. e.g. if the data acquisition system stores values in this object as signed 16-bit integers (int16 range -32,768 to 32,767) that correspond to a 5V range (-2.5V to 2.5V), and the data acquisition system gain is 8000X, then the 'conversion' multiplier to get from raw data acquisition values to recorded volts is 2.5/32768/8000 = 9.5367e-9.","required":false,"dtype":"float32","default_value":1.0},{"name":"resolution","doc":"Smallest meaningful difference between values in data, stored in the specified by unit, 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 -1.0.","required":false,"dtype":"float32","default_value":-1.0}]},{"dtype":"text","name":"reference_frame","doc":"Description defining what exactly 'straight-ahead' means.","quantity":"?"}],"doc":"Direction, e.g., of gaze or travel, or position. The TimeSeries::data field is a 2D array storing position or direction relative to some reference frame. Array structure: [num measurements] [num dimensions]. Each SpatialSeries has a text dataset reference_frame that indicates the zero-position, or the zero-axes for direction. For example, if representing gaze direction, 'straight-ahead' might be a specific pixel on the monitor, or some other point in space. For position data, the 0,0 point might be the top-left corner of an enclosure, as viewed from the tracking camera. The unit of data will indicate how to interpret SpatialSeries values.","neurodata_type_inc":"TimeSeries","neurodata_type_def":"SpatialSeries","attributes":[{"name":"description","doc":"Description of the time series.","required":false,"dtype":"text","default_value":"no description"},{"name":"comments","doc":"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.","required":false,"dtype":"text","default_value":"no comments"}]},{"groups":[{"doc":"IntervalSeries object containing start and stop times of epochs.","quantity":"*","neurodata_type_inc":"IntervalSeries"}],"doc":"TimeSeries for storing behavioral epochs. The objective of this and the other two Behavioral interfaces (e.g. BehavioralEvents and BehavioralTimeSeries) is to provide generic hooks for software tools/scripts. This allows a tool/script to take the output one specific interface (e.g., UnitTimes) and plot that data relative to another data modality (e.g., behavioral events) without having to define all possible modalities in advance. Declaring one of these interfaces means that one or more TimeSeries of the specified type is published. These TimeSeries should reside in a group having the same name as the interface. For example, if a BehavioralTimeSeries interface is declared, the module will have one or more TimeSeries defined in the module sub-group 'BehavioralTimeSeries'. BehavioralEpochs should use IntervalSeries. BehavioralEvents is used for irregular events. BehavioralTimeSeries is for continuous data.","default_name":"BehavioralEpochs","neurodata_type_inc":"NWBDataInterface","neurodata_type_def":"BehavioralEpochs"},{"groups":[{"doc":"TimeSeries object containing behavioral events.","quantity":"*","neurodata_type_inc":"TimeSeries"}],"doc":"TimeSeries for storing behavioral events. See description of BehavioralEpochs for more details.","default_name":"BehavioralEvents","neurodata_type_inc":"NWBDataInterface","neurodata_type_def":"BehavioralEvents"},{"groups":[{"doc":"TimeSeries object containing continuous behavioral data.","quantity":"*","neurodata_type_inc":"TimeSeries"}],"doc":"TimeSeries for storing Behavoioral time series data. See description of BehavioralEpochs for more details.","default_name":"BehavioralTimeSeries","neurodata_type_inc":"NWBDataInterface","neurodata_type_def":"BehavioralTimeSeries"},{"groups":[{"doc":"TimeSeries object containing time series data on pupil size.","quantity":"+","neurodata_type_inc":"TimeSeries"}],"doc":"Eye-tracking data, representing pupil size.","default_name":"PupilTracking","neurodata_type_inc":"NWBDataInterface","neurodata_type_def":"PupilTracking"},{"groups":[{"doc":"SpatialSeries object containing data measuring direction of gaze.","quantity":"*","neurodata_type_inc":"SpatialSeries"}],"doc":"Eye-tracking data, representing direction of gaze.","default_name":"EyeTracking","neurodata_type_inc":"NWBDataInterface","neurodata_type_def":"EyeTracking"},{"groups":[{"doc":"SpatialSeries object containing direction of gaze travel.","quantity":"*","neurodata_type_inc":"SpatialSeries"}],"doc":"With a CompassDirection interface, a module publishes a SpatialSeries object representing a floating point value for theta. The SpatialSeries::reference_frame field should indicate what direction corresponds to 0 and which is the direction of rotation (this should be clockwise). The si_unit for the SpatialSeries should be radians or degrees.","default_name":"CompassDirection","neurodata_type_inc":"NWBDataInterface","neurodata_type_def":"CompassDirection"},{"groups":[{"doc":"SpatialSeries object containing position data.","quantity":"+","neurodata_type_inc":"SpatialSeries"}],"doc":"Position data, whether along the x, x/y or x/y/z axis.","default_name":"Position","neurodata_type_inc":"NWBDataInterface","neurodata_type_def":"Position"}]}~ {"groups":[{"datasets":[{"shape":[null],"dims":["num_times"],"dtype":"numeric","name":"data","doc":"Applied power for optogenetic stimulus, in watts.","attributes":[{"name":"unit","doc":"Unit of measurement for data, which is fixed to 'watts'.","dtype":"text","value":"watts"},{"name":"conversion","doc":"Scalar to multiply each element in data to convert it to the specified 'unit'. If the data are stored in acquisition system units or other units that require a conversion to be interpretable, multiply the data by 'conversion' to convert the data to the specified 'unit'. e.g. if the data acquisition system stores values in this object as signed 16-bit integers (int16 range -32,768 to 32,767) that correspond to a 5V range (-2.5V to 2.5V), and the data acquisition system gain is 8000X, then the 'conversion' multiplier to get from raw data acquisition values to recorded volts is 2.5/32768/8000 = 9.5367e-9.","required":false,"dtype":"float32","default_value":1.0},{"name":"resolution","doc":"Smallest meaningful difference between values in data, stored in the specified by unit, 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 -1.0.","required":false,"dtype":"float32","default_value":-1.0}]}],"links":[{"name":"site","doc":"Link to OptogeneticStimulusSite object that describes the site to which this stimulus was applied.","target_type":"OptogeneticStimulusSite"}],"doc":"An optogenetic stimulus.","neurodata_type_inc":"TimeSeries","neurodata_type_def":"OptogeneticSeries","attributes":[{"name":"description","doc":"Description of the time series.","required":false,"dtype":"text","default_value":"no description"},{"name":"comments","doc":"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.","required":false,"dtype":"text","default_value":"no comments"}]},{"datasets":[{"dtype":"text","name":"description","doc":"Description of stimulation site."},{"dtype":"float","name":"excitation_lambda","doc":"Excitation wavelength, in nm."},{"dtype":"text","name":"location","doc":"Location of the stimulation site. Specify the area, layer, comments on estimation of area/layer, stereotaxic coordinates if in vivo, etc. Use standard atlas names for anatomical regions when possible."}],"links":[{"name":"device","doc":"Device that generated the stimulus.","target_type":"Device"}],"doc":"A site of optogenetic stimulation.","quantity":"*","neurodata_type_inc":"NWBContainer","neurodata_type_def":"OptogeneticStimulusSite"}]}04#]4#]4#]SNOD8sx@(rHtADE4#]4#]5#]GCOLp0{"groups":[{"datasets":[{"shape":[[null],[null,null],[null,null,null]],"dims":[["num_times"],["num_times","num_channels"],["num_times","num_channels","num_samples"]],"dtype":"numeric","name":"data","doc":"Recorded voltage data.","attributes":[{"name":"unit","doc":"Base unit of measurement for working with the data. This value is fixed to 'volts'. Actual stored values are not necessarily stored in these units. To access the data in these units, multiply 'data' by 'conversion'.","dtype":"text","value":"volts"},{"name":"conversion","doc":"Scalar to multiply each element in data to convert it to the specified 'unit'. If the data are stored in acquisition system units or other units that require a conversion to be interpretable, multiply the data by 'conversion' to convert the data to the specified 'unit'. e.g. if the data acquisition system stores values in this object as signed 16-bit integers (int16 range -32,768 to 32,767) that correspond to a 5V range (-2.5V to 2.5V), and the data acquisition system gain is 8000X, then the 'conversion' multiplier to get from raw data acquisition values to recorded volts is 2.5/32768/8000 = 9.5367e-9.","required":false,"dtype":"float32","default_value":1.0},{"name":"resolution","doc":"Smallest meaningful difference between values in data, stored in the specified by unit, 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 -1.0.","required":false,"dtype":"float32","default_value":-1.0}]},{"name":"electrodes","doc":"DynamicTableRegion pointer to the electrodes that this time series was generated from.","neurodata_type_inc":"DynamicTableRegion"}],"doc":"A time series of acquired voltage data from extracellular recordings. The data field is an int or float array storing data in volts. The first dimension should always represent time. The second dimension, if present, should represent channels.","neurodata_type_inc":"TimeSeries","neurodata_type_def":"ElectricalSeries","attributes":[{"name":"description","doc":"Description of the time series.","required":false,"dtype":"text","default_value":"no description"},{"name":"comments","doc":"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.","required":false,"dtype":"text","default_value":"no comments"}]},{"datasets":[{"shape":[[null,null],[null,null,null]],"dims":[["num_events","num_samples"],["num_events","num_channels","num_samples"]],"dtype":"numeric","name":"data","doc":"Spike waveforms.","attributes":[{"name":"unit","doc":"Unit of measurement for waveforms, which is fixed to 'volts'.","dtype":"text","value":"volts"},{"name":"conversion","doc":"Scalar to multiply each element in data to convert it to the specified 'unit'. If the data are stored in acquisition system units or other units that require a conversion to be interpretable, multiply the data by 'conversion' to convert the data to the specified 'unit'. e.g. if the data acquisition system stores values in this object as signed 16-bit integers (int16 range -32,768 to 32,767) that correspond to a 5V range (-2.5V to 2.5V), and the data acquisition system gain is 8000X, then the 'conversion' multiplier to get from raw data acquisition values to recorded volts is 2.5/32768/8000 = 9.5367e-9.","required":false,"dtype":"float32","default_value":1.0},{"name":"resolution","doc":"Smallest meaningful difference between values in data, stored in the specified by unit, 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 -1.0.","required":false,"dtype":"float32","default_value":-1.0}]},{"shape":[null],"dims":["num_times"],"dtype":"float64","name":"timestamps","doc":"Timestamps for samples stored in data, in seconds, relative to the common experiment master-clock stored in NWBFile.timestamps_reference_time. Timestamps are required for the events. Unlike for TimeSeries, timestamps are required for SpikeEventSeries and are thus re-specified here.","attributes":[{"name":"interval","doc":"Value is '1'","dtype":"int32","value":1},{"name":"unit","doc":"Unit of measurement for timestamps, which is fixed to 'seconds'.","dtype":"text","value":"seconds"}]}],"doc":"Stores snapshots/snippets of recorded spike events (i.e., threshold crossings). This may also be raw data, as reported by ephys hardware. If so, the TimeSeries::description field should describe how events were detected. All SpikeEventSeries should reside in a module (under EventWaveform interface) even if the spikes were reported and stored by hardware. All events span the same recording channels and store snapshots of equal duration. TimeSeries::data array structure: [num events] [num channels] [num samples] (or [num events] [num samples] for single electrode).","neurodata_type_inc":"ElectricalSeries","neurodata_type_def":"SpikeEventSeries","attributes":[{"name":"description","doc":"Description of the time series.","required":false,"dtype":"text","default_value":"no description"},{"name":"comments","doc":"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.","required":false,"dtype":"text","default_value":"no comments"}]},{"datasets":[{"shape":[null],"dims":["num_features"],"dtype":"text","name":"description","doc":"Description of features (eg, ''PC1'') for each of the extracted features."},{"shape":[null,null,null],"dims":["num_events","num_channels","num_features"],"dtype":"float32","name":"features","doc":"Multi-dimensional array of features extracted from each event."},{"shape":[null],"dims":["num_events"],"dtype":"float64","name":"times","doc":"Times of events that features correspond to (can be a link)."},{"name":"electrodes","doc":"DynamicTableRegion pointer to the electrodes that this time series was generated from.","neurodata_type_inc":"DynamicTableRegion"}],"doc":"Features, such as PC1 and PC2, that are extracted from signals stored in a SpikeEventSeries or other source.","default_name":"FeatureExtraction","neurodata_type_inc":"NWBDataInterface","neurodata_type_def":"FeatureExtraction"},{"datasets":[{"dtype":"text","name":"detection_method","doc":"Description of how events were detected, such as voltage threshold, or dV/dT threshold, as well as relevant values."},{"shape":[null],"dims":["num_events"],"dtype":"int32","name":"source_idx","doc":"Indices (zero-based) into source ElectricalSeries::data array corresponding to time of event. ''description'' should define what is meant by time of event (e.g., .25 ms before action potential peak, zero-crossing time, etc). The index points to each event from the raw data."},{"shape":[null],"dims":["num_events"],"dtype":"float64","name":"times","doc":"Timestamps of events, in seconds.","attributes":[{"name":"unit","doc":"Unit of measurement for event times, which is fixed to 'seconds'.","dtype":"text","value":"seconds"}]}],"links":[{"name":"source_electricalseries","doc":"Link to the ElectricalSeries that this data was calculated from. Metadata about electrodes and their position can be read from that ElectricalSeries so it's not necessary to include that information here.","target_type":"ElectricalSeries"}],"doc":"Detected spike events from voltage trace(s).","default_name":"EventDetection","neurodata_type_inc":"NWBDataInterface","neurodata_type_def":"EventDetection"},{"groups":[{"doc":"SpikeEventSeries object(s) containing detected spike event waveforms.","quantity":"*","neurodata_type_inc":"SpikeEventSeries"}],"doc":"Represents either the waveforms of detected events, as extracted from a raw data trace in /acquisition, or the event waveforms that were stored during experiment acquisition.","default_name":"EventWaveform","neurodata_type_inc":"NWBDataInterface","neurodata_type_def":"EventWaveform"},{"groups":[{"doc":"ElectricalSeries object(s) containing filtered electrophysiology data.","quantity":"+","neurodata_type_inc":"ElectricalSeries"}],"doc":"Electrophysiology data from one or more channels that has been subjected to filtering. Examples of filtered data include Theta and Gamma (LFP has its own interface). FilteredEphys modules publish an ElectricalSeries for each filtered channel or set of channels. The name of each ElectricalSeries is arbitrary but should be informative. The source of the filtered data, whether this is from analysis of another time series or as acquired by hardware, should be noted in each's TimeSeries::description field. There is no assumed 1::1 correspondence between filtered ephys signals and electrodes, as a single signal can apply to many nearby electrodes, and one electrode may have different filtered (e.g., theta and/or gamma) signals represented. Filter properties should be noted in the ElectricalSeries.","default_name":"FilteredEphys","neurodata_type_inc":"NWBDataInterface","neurodata_type_def":"FilteredEphys"},{"groups":[{"doc":"ElectricalSeries object(s) containing LFP data for one or more channels.","quantity":"+","neurodata_type_inc":"ElectricalSeries"}],"doc":"LFP data from one or more channels. The electrode map in each published ElectricalSeries will identify which channels are providing LFP data. Filter properties should be noted in the ElectricalSeries description or comments field.","default_name":"LFP","neurodata_type_inc":"NWBDataInterface","neurodata_type_def":"LFP"},{"links":[{"name":"device","doc":"Link to the device that was used to record from this electrode group.","target_type":"Device"}],"doc":"A physical grouping of electrodes, e.g. a shank of an array.","neurodata_type_inc":"NWBContainer","neurodata_type_def":"ElectrodeGroup","attributes":[{"name":"description","doc":"Description of this electrode group.","dtype":"text"},{"name":"location","doc":"Location of electrode group. Specify the area, layer, comments on estimation of area/layer, stereotaxic coordinates if in vivo, etc. Use standard atlas names for anatomical regions when possible.","dtype":"text"}]},{"datasets":[{"dtype":"text","name":"waveform_filtering","doc":"Filtering applied to data before generating mean/sd"},{"shape":[null,null],"dims":["num_clusters","num_samples"],"dtype":"float32","name":"waveform_mean","doc":"The mean waveform for each cluster, using the same indices for each wave as cluster numbers in the associated Clustering module (i.e, cluster 3 is in array slot [3]). Waveforms corresponding to gaps in cluster sequence should be empty (e.g., zero- filled)"},{"shape":[null,null],"dims":["num_clusters","num_samples"],"dtype":"float32","name":"waveform_sd","doc":"Stdev of waveforms for each cluster, using the same indices as in mean"}],"links":[{"name":"clustering_interface","doc":"Link to Clustering interface that was the source of the clustered data","target_type":"Clustering"}],"doc":"DEPRECATED The mean waveform shape, including standard deviation, of the different clusters. Ideally, the waveform analysis should be performed on data that is only high-pass filtered. This is a separate module because it is expected to require updating. For example, IMEC probes may require different storage requirements to store/display mean waveforms, requiring a new interface or an extension of this one.","default_name":"ClusterWaveforms","neurodata_type_inc":"NWBDataInterface","neurodata_type_def":"ClusterWaveforms"},{"datasets":[{"dtype":"text","name":"description","doc":"Description of clusters or clustering, (e.g. cluster 0 is noise, clusters curated using Klusters, etc)"},{"shape":[null],"dims":["num_events"],"dtype":"int32","name":"num","doc":"Cluster number of each event"},{"shape":[null],"dims":["num_clusters"],"dtype":"float32","name":"peak_over_rms","doc":"Maximum ratio of waveform peak to RMS on any channel in the cluster (provides a basic clustering metric)."},{"shape":[null],"dims":["num_events"],"dtype":"float64","name":"times","doc":"Times of clustered events, in seconds. This may be a link to times field in associated FeatureExtraction module."}],"doc":"DEPRECATED Clustered spike data, whether from automatic clustering tools (e.g., klustakwik) or as a result of manual sorting.","default_name":"Clustering","neurodata_type_inc":"NWBDataInterface","neurodata_type_def":"Clustering"}]}B{"groups":[{"datasets":[{"shape":[null],"dims":["num_times"],"dtype":"numeric","name":"data","doc":"Recorded voltage or current.","attributes":[{"name":"unit","doc":"Base unit of measurement for working with the data. Actual stored values are not necessarily stored in these units. To access the data in these units, multiply 'data' by 'conversion'.","dtype":"text"},{"name":"conversion","doc":"Scalar to multiply each element in data to convert it to the specified 'unit'. If the data are stored in acquisition system units or other units that require a conversion to be interpretable, multiply the data by 'conversion' to convert the data to the specified 'unit'. e.g. if the data acquisition system stores values in this object as signed 16-bit integers (int16 range -32,768 to 32,767) that correspond to a 5V range (-2.5V to 2.5V), and the data acquisition system gain is 8000X, then the 'conversion' multiplier to get from raw data acquisition values to recorded volts is 2.5/32768/8000 = 9.5367e-9.","required":false,"dtype":"float32","default_value":1.0},{"name":"resolution","doc":"Smallest meaningful difference between values in data, stored in the specified by unit, 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 -1.0.","required":false,"dtype":"float32","default_value":-1.0}]},{"dtype":"float","name":"gain","doc":"Gain of the recording, in units Volt/Amp (v-clamp) or Volt/Volt (c-clamp).","quantity":"?"}],"links":[{"name":"electrode","doc":"Link to IntracellularElectrode object that describes the electrode that was used to apply or record this data.","target_type":"IntracellularElectrode"}],"doc":"An abstract base class for patch-clamp data - stimulus or response, current or voltage.","neurodata_type_inc":"TimeSeries","neurodata_type_def":"PatchClampSeries","attributes":[{"name":"stimulus_description","doc":"Protocol/stimulus name for this patch-clamp dataset.","dtype":"text"},{"name":"sweep_number","doc":"Sweep number, allows to group different PatchClampSeries together.","required":false,"dtype":"uint64"},{"name":"description","doc":"Description of the time series.","required":false,"dtype":"text","default_value":"no description"},{"name":"comments","doc":"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.","required":false,"dtype":"text","default_value":"no comments"}]},{"datasets":[{"name":"data","doc":"Recorded voltage.","attributes":[{"name":"unit","doc":"Base unit of measurement for working with the data. which is fixed to 'volts'. Actual stored values are not necessarily stored in these units. To access the data in these units, multiply 'data' by 'conversion'.","dtype":"text","value":"volts"},{"name":"conversion","doc":"Scalar to multiply each element in data to convert it to the specified 'unit'. If the data are stored in acquisition system units or other units that require a conversion to be interpretable, multiply the data by 'conversion' to convert the data to the specified 'unit'. e.g. if the data acquisition system stores values in this object as signed 16-bit integers (int16 range -32,768 to 32,767) that correspond to a 5V range (-2.5V to 2.5V), and the data acquisition system gain is 8000X, then the 'conversion' multiplier to get from raw data acquisition values to recorded volts is 2.5/32768/8000 = 9.5367e-9.","required":false,"dtype":"float32","default_value":1.0},{"name":"resolution","doc":"Smallest meaningful difference between values in data, stored in the specified by unit, 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 -1.0.","required":false,"dtype":"float32","default_value":-1.0}]},{"dtype":"float32","name":"bias_current","doc":"Bias current, in amps.","quantity":"?"},{"dtype":"float32","name":"bridge_balance","doc":"Bridge balance, in ohms.","quantity":"?"},{"dtype":"float32","name":"capacitance_compensation","doc":"Capacitance compensation, in farads.","quantity":"?"}],"doc":"Voltage data from an intracellular current-clamp recording. A corresponding CurrentClampStimulusSeries (stored separately as a stimulus) is used to store the current injected.","neurodata_type_inc":"PatchClampSeries","neurodata_type_def":"CurrentClampSeries","attributes":[{"name":"stimulus_description","doc":"Protocol/stimulus name for this patch-clamp dataset.","dtype":"text"},{"name":"sweep_number","doc":"Sweep number, allows to group different PatchClampSeries together.","required":false,"dtype":"uint64"},{"name":"description","doc":"Description of the time series.","required":false,"dtype":"text","default_value":"no description"},{"name":"comments","doc":"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.","required":false,"dtype":"text","default_value":"no comments"}]},{"datasets":[{"dtype":"float32","name":"bias_current","doc":"Bias current, in amps, fixed to 0.0."},{"dtype":"float32","name":"bridge_balance","doc":"Bridge balance, in ohms, fixed to 0.0."},{"dtype":"float32","name":"capacitance_compensation","doc":"Capacitance compensation, in farads, fixed to 0.0."}],"doc":"Voltage data from an intracellular recording when all current and amplifier settings are off (i.e., CurrentClampSeries fields will be zero). There is no CurrentClampStimulusSeries associated with an IZero series because the amplifier is disconnected and no stimulus can reach the cell.","neurodata_type_inc":"CurrentClampSeries","neurodata_type_def":"IZeroClampSeries","attributes":[{"name":"stimulus_description","doc":"Protocol/stimulus name for this patch-clamp dataset.","dtype":"text"},{"name":"sweep_number","doc":"Sweep number, allows to group different PatchClampSeries together.","required":false,"dtype":"uint64"},{"name":"description","doc":"Description of the time series.","required":false,"dtype":"text","default_value":"no description"},{"name":"comments","doc":"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.","required":false,"dtype":"text","default_value":"no comments"}]},{"datasets":[{"name":"data","doc":"Stimulus current applied.","attributes":[{"name":"unit","doc":"Base unit of measurement for working with the data. which is fixed to 'amperes'. Actual stored values are not necessarily stored in these units. To access the data in these units, multiply 'data' by 'conversion'.","dtype":"text","value":"amperes"},{"name":"conversion","doc":"Scalar to multiply each element in data to convert it to the specified 'unit'. If the data are stored in acquisition system units or other units that require a conversion to be interpretable, multiply the data by 'conversion' to convert the data to the specified 'unit'. e.g. if the data acquisition system stores values in this object as signed 16-bit integers (int16 range -32,768 to 32,767) that correspond to a 5V range (-2.5V to 2.5V), and the data acquisition system gain is 8000X, then the 'conversion' multiplier to get from raw data acquisition values to recorded volts is 2.5/32768/8000 = 9.5367e-9.","required":false,"dtype":"float32","default_value":1.0},{"name":"resolution","doc":"Smallest meaningful difference between values in data, stored in the specified by unit, 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 -1.0.","required":false,"dtype":"float32","default_value":-1.0}]}],"doc":"Stimulus current applied during current clamp recording.","neurodata_type_inc":"PatchClampSeries","neurodata_type_def":"CurrentClampStimulusSeries","attributes":[{"name":"stimulus_description","doc":"Protocol/stimulus name for this patch-clamp dataset.","dtype":"text"},{"name":"sweep_number","doc":"Sweep number, allows to group different PatchClampSeries together.","required":false,"dtype":"uint64"},{"name":"description","doc":"Description of the time series.","required":false,"dtype":"text","default_value":"no description"},{"name":"comments","doc":"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.","required":false,"dtype":"text","default_value":"no comments"}]},{"datasets":[{"name":"data","doc":"Recorded current.","attributes":[{"name":"unit","doc":"Base unit of measurement for working with the data. which is fixed to 'amperes'. Actual stored values are not necessarily stored in these units. To access the data in these units, multiply 'data' by 'conversion'.","dtype":"text","value":"amperes"},{"name":"conversion","doc":"Scalar to multiply each element in data to convert it to the specified 'unit'. If the data are stored in acquisition system units or other units that require a conversion to be interpretable, multiply the data by 'conversion' to convert the data to the specified 'unit'. e.g. if the data acquisition system stores values in this object as signed 16-bit integers (int16 range -32,768 to 32,767) that correspond to a 5V range (-2.5V to 2.5V), and the data acquisition system gain is 8000X, then the 'conversion' multiplier to get from raw data acquisition values to recorded volts is 2.5/32768/8000 = 9.5367e-9.","required":false,"dtype":"float32","default_value":1.0},{"name":"resolution","doc":"Smallest meaningful difference between values in data, stored in the specified by unit, 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 -1.0.","required":false,"dtype":"float32","default_value":-1.0}]},{"dtype":"float32","name":"capacitance_fast","doc":"Fast capacitance, in farads.","quantity":"?","attributes":[{"name":"unit","doc":"Unit of measurement for capacitance_fast, which is fixed to 'farads'.","dtype":"text","value":"farads"}]},{"dtype":"float32","name":"capacitance_slow","doc":"Slow capacitance, in farads.","quantity":"?","attributes":[{"name":"unit","doc":"Unit of measurement for capacitance_fast, which is fixed to 'farads'.","dtype":"text","value":"farads"}]},{"dtype":"float32","name":"resistance_comp_bandwidth","doc":"Resistance compensation bandwidth, in hertz.","quantity":"?","attributes":[{"name":"unit","doc":"Unit of measurement for resistance_comp_bandwidth, which is fixed to 'hertz'.","dtype":"text","value":"hertz"}]},{"dtype":"float32","name":"resistance_comp_correction","doc":"Resistance compensation correction, in percent.","quantity":"?","attributes":[{"name":"unit","doc":"Unit of measurement for resistance_comp_correction, which is fixed to 'percent'.","dtype":"text","value":"percent"}]},{"dtype":"float32","name":"resistance_comp_prediction","doc":"Resistance compensation prediction, in percent.","quantity":"?","attributes":[{"name":"unit","doc":"Unit of measurement for resistance_comp_prediction, which is fixed to 'percent'.","dtype":"text","value":"percent"}]},{"dtype":"float32","name":"whole_cell_capacitance_comp","doc":"Whole cell capacitance compensation, in farads.","quantity":"?","attributes":[{"name":"unit","doc":"Unit of measurement for whole_cell_capacitance_comp, which is fixed to 'farads'.","dtype":"text","value":"farads"}]},{"dtype":"float32","name":"whole_cell_series_resistance_comp","doc":"Whole cell series resistance compensation, in ohms.","quantity":"?","attributes":[{"name":"unit","doc":"Unit of measurement for whole_cell_series_resistance_comp, which is fixed to 'ohms'.","dtype":"text","value":"ohms"}]}],"doc":"Current data from an intracellular voltage-clamp recording. A corresponding VoltageClampStimulusSeries (stored separately as a stimulus) is used to store the voltage injected.","neurodata_type_inc":"PatchClampSeries","neurodata_type_def":"VoltageClampSeries","attributes":[{"name":"stimulus_description","doc":"Protocol/stimulus name for this patch-clamp dataset.","dtype":"text"},{"name":"sweep_number","doc":"Sweep number, allows to group different PatchClampSeries together.","required":false,"dtype":"uint64"},{"name":"description","doc":"Description of the time series.","required":false,"dtype":"text","default_value":"no description"},{"name":"comments","doc":"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.","required":false,"dtype":"text","default_value":"no comments"}]},{"datasets":[{"name":"data","doc":"Stimulus voltage applied.","attributes":[{"name":"unit","doc":"Base unit of measurement for working with the data. which is fixed to 'volts'. Actual stored values are not necessarily stored in these units. To access the data in these units, multiply 'data' by 'conversion'.","dtype":"text","value":"volts"},{"name":"conversion","doc":"Scalar to multiply each element in data to convert it to the specified 'unit'. If the data are stored in acquisition system units or other units that require a conversion to be interpretable, multiply the data by 'conversion' to convert the data to the specified 'unit'. e.g. if the data acquisition system stores values in this object as signed 16-bit integers (int16 range -32,768 to 32,767) that correspond to a 5V range (-2.5V to 2.5V), and the data acquisition system gain is 8000X, then the 'conversion' multiplier to get from raw data acquisition values to recorded volts is 2.5/32768/8000 = 9.5367e-9.","required":false,"dtype":"float32","default_value":1.0},{"name":"resolution","doc":"Smallest meaningful difference between values in data, stored in the specified by unit, 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 -1.0.","required":false,"dtype":"float32","default_value":-1.0}]}],"doc":"Stimulus voltage applied during a voltage clamp recording.","neurodata_type_inc":"PatchClampSeries","neurodata_type_def":"VoltageClampStimulusSeries","attributes":[{"name":"stimulus_description","doc":"Protocol/stimulus name for this patch-clamp dataset.","dtype":"text"},{"name":"sweep_number","doc":"Sweep number, allows to group different PatchClampSeries together.","required":false,"dtype":"uint64"},{"name":"description","doc":"Description of the time series.","required":false,"dtype":"text","default_value":"no description"},{"name":"comments","doc":"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.","required":false,"dtype":"text","default_value":"no comments"}]},{"datasets":[{"dtype":"text","name":"description","doc":"Description of electrode (e.g., whole-cell, sharp, etc.)."},{"dtype":"text","name":"filtering","doc":"Electrode specific filtering.","quantity":"?"},{"dtype":"text","name":"initial_access_resistance","doc":"Initial access resistance.","quantity":"?"},{"dtype":"text","name":"location","doc":"Location of the electrode. Specify the area, layer, comments on estimation of area/layer, stereotaxic coordinates if in vivo, etc. Use standard atlas names for anatomical regions when possible.","quantity":"?"},{"dtype":"text","name":"resistance","doc":"Electrode resistance, in ohms.","quantity":"?"},{"dtype":"text","name":"seal","doc":"Information about seal used for recording.","quantity":"?"},{"dtype":"text","name":"slice","doc":"Information about slice used for recording.","quantity":"?"}],"links":[{"name":"device","doc":"Device that was used to record from this electrode.","target_type":"Device"}],"doc":"An intracellular electrode and its metadata.","neurodata_type_inc":"NWBContainer","neurodata_type_def":"IntracellularElectrode"},{"datasets":[{"dtype":"uint64","name":"sweep_number","doc":"Sweep number of the PatchClampSeries in that row.","neurodata_type_inc":"VectorData"},{"dtype":{"target_type":"PatchClampSeries","reftype":"object"},"name":"series","doc":"The PatchClampSeries with the sweep number in that row.","neurodata_type_inc":"VectorData"},{"name":"series_index","doc":"Index for series.","neurodata_type_inc":"VectorIndex"}],"doc":"The table which groups different PatchClampSeries together.","neurodata_type_inc":"DynamicTable","neurodata_type_def":"SweepTable","attributes":[{"name":"colnames","doc":"The names of the columns in this table. This should be used to specify an order to the columns.","dtype":"ascii","shape":[null],"dims":["num_columns"]},{"name":"description","doc":"Description of what is in this dynamic table.","dtype":"text"}]}]},{"groups":[{"datasets":[{"shape":[[2],[3]],"dims":["width|height","width|height|depth"],"dtype":"float32","name":"field_of_view","doc":"Width, height and depth of image, or imaged area, in meters.","quantity":"?"}],"links":[{"name":"imaging_plane","doc":"Link to ImagingPlane object from which this TimeSeries data was generated.","target_type":"ImagingPlane"}],"doc":"Image stack recorded over time from 2-photon microscope.","neurodata_type_inc":"ImageSeries","neurodata_type_def":"TwoPhotonSeries","attributes":[{"name":"pmt_gain","doc":"Photomultiplier gain.","required":false,"dtype":"float32"},{"name":"scan_line_rate","doc":"Lines imaged per second. This is also stored in /general/optophysiology but is kept here as it is useful information for analysis, and so good to be stored w/ the actual data.","required":false,"dtype":"float32"},{"name":"description","doc":"Description of the time series.","required":false,"dtype":"text","default_value":"no description"},{"name":"comments","doc":"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.","required":false,"dtype":"text","default_value":"no comments"}]},{"datasets":[{"shape":[[null],[null,null]],"dims":[["num_times"],["num_times","num_ROIs"]],"dtype":"numeric","name":"data","doc":"Signals from ROIs.","attributes":[{"name":"conversion","doc":"Scalar to multiply each element in data to convert it to the specified 'unit'. If the data are stored in acquisition system units or other units that require a conversion to be interpretable, multiply the data by 'conversion' to convert the data to the specified 'unit'. e.g. if the data acquisition system stores values in this object as signed 16-bit integers (int16 range -32,768 to 32,767) that correspond to a 5V range (-2.5V to 2.5V), and the data acquisition system gain is 8000X, then the 'conversion' multiplier to get from raw data acquisition values to recorded volts is 2.5/32768/8000 = 9.5367e-9.","required":false,"dtype":"float32","default_value":1.0},{"name":"resolution","doc":"Smallest meaningful difference between values in data, stored in the specified by unit, 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 -1.0.","required":false,"dtype":"float32","default_value":-1.0},{"name":"unit","doc":"Base unit of measurement for working with the data. Actual stored values are not necessarily stored in these units. To access the data in these units, multiply 'data' by 'conversion'.","dtype":"text"}]},{"name":"rois","doc":"DynamicTableRegion referencing into an ROITable containing information on the ROIs stored in this timeseries.","neurodata_type_inc":"DynamicTableRegion"}],"doc":"ROI responses over an imaging plane. Each row in data should correspond to the signal from one ROI. Each element on the second dimension of data should correspond to the signal from one ROI.","neurodata_type_inc":"TimeSeries","neurodata_type_def":"RoiResponseSeries","attributes":[{"name":"description","doc":"Description of the time series.","required":false,"dtype":"text","default_value":"no description"},{"name":"comments","doc":"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.","required":false,"dtype":"text","default_value":"no comments"}]},{"groups":[{"doc":"RoiResponseSeries object(s) containing dF/F for a ROI.","quantity":"+","neurodata_type_inc":"RoiResponseSeries"}],"doc":"dF/F information about a region of interest (ROI). Storage hierarchy of dF/F should be the same as for segmentation (i.e., same names for ROIs and for image planes).","default_name":"DfOverF","neurodata_type_inc":"NWBDataInterface","neurodata_type_def":"DfOverF"},{"groups":[{"doc":"RoiResponseSeries object(s) containing fluorescence data for a ROI.","quantity":"+","neurodata_type_inc":"RoiResponseSeries"}],"doc":"Fluorescence information about a region of interest (ROI). Storage hierarchy of fluorescence should be the same as for segmentation (ie, same names for ROIs and for image planes).","default_name":"Fluorescence","neurodata_type_inc":"NWBDataInterface","neurodata_type_def":"Fluorescence"},{"groups":[{"groups":[{"groups":[{"doc":"One or more image stacks that the masks apply to (can be one-element stack).","quantity":"*","neurodata_type_inc":"ImageSeries"}],"name":"reference_images","doc":"Image stacks that the segmentation masks apply to."}],"datasets":[{"shape":[[null,null,null],[null,null,null,null]],"dims":[["num_roi","num_x","num_y"],["num_roi","num_x","num_y","num_z"]],"name":"image_mask","doc":"ROI masks for each ROI. Each image mask is the size of the original imaging plane (or volume) and members of the ROI are finite non-zero.","quantity":"?","neurodata_type_inc":"VectorData"},{"name":"pixel_mask_index","doc":"Index into pixel_mask.","quantity":"?","neurodata_type_inc":"VectorIndex"},{"dtype":[{"doc":"Pixel x-coordinate.","name":"x","dtype":"uint"},{"doc":"Pixel y-coordinate.","name":"y","dtype":"uint"},{"doc":"Weight of the pixel.","name":"weight","dtype":"float"}],"name":"pixel_mask","doc":"Pixel masks for each ROI: a list of indices and weights for the ROI. Pixel masks are concatenated and parsing of this dataset is maintained by the PlaneSegmentation","quantity":"?","neurodata_type_inc":"VectorData"},{"name":"voxel_mask_index","doc":"Index into voxel_mask.","quantity":"?","neurodata_type_inc":"VectorIndex"},{"dtype":[{"doc":"Voxel x-coordinate.","name":"x","dtype":"uint"},{"doc":"Voxel y-coordinate.","name":"y","dtype":"uint"},{"doc":"Voxel z-coordinate.","name":"z","dtype":"uint"},{"doc":"Weight of the voxel.","name":"weight","dtype":"float"}],"name":"voxel_mask","doc":"Voxel masks for each ROI: a list of indices and weights for the ROI. Voxel masks are concatenated and parsing of this dataset is maintained by the PlaneSegmentation","quantity":"?","neurodata_type_inc":"VectorData"},{"shape":[null],"dims":["num_rows"],"dtype":"int","name":"id","doc":"Array of unique identifiers for the rows of this dynamic table.","neurodata_type_inc":"ElementIdentifiers"},{"doc":"Vector columns of this dynamic table.","quantity":"*","neurodata_type_inc":"VectorData"},{"doc":"Indices for the vector columns of this dynamic table.","quantity":"*","neurodata_type_inc":"VectorIndex"}],"links":[{"name":"imaging_plane","doc":"Link to ImagingPlane object from which this data was generated.","target_type":"ImagingPlane"}],"doc":"Results from image segmentation of a specific imaging plane.","quantity":"+","neurodata_type_inc":"DynamicTable","neurodata_type_def":"PlaneSegmentation","attributes":[{"name":"colnames","doc":"The names of the columns in this table. This should be used to specify an order to the columns.","dtype":"ascii","shape":[null],"dims":["num_columns"]},{"name":"description","doc":"Description of what is in this dynamic table.","dtype":"text"}]}],"doc":"Stores pixels in an image that represent different regions of interest (ROIs) or masks. All segmentation for a given imaging plane is stored together, with storage for multiple imaging planes (masks) supported. Each ROI is stored in its own subgroup, with the ROI group containing both a 2D mask and a list of pixels that make up this mask. Segments can also be used for masking neuropil. If segmentation is allowed to change with time, a new imaging plane (or module) is required and ROI names should remain consistent between them.","default_name":"ImageSegmentation","neurodata_type_inc":"NWBDataInterface","neurodata_type_def":"ImageSegmentation"},{"groups":[{"datasets":[{"dtype":"text","name":"description","doc":"Description or other notes about the channel."},{"dtype":"float","name":"emission_lambda","doc":"Emission wavelength for channel, in nm."}],"doc":"An optical channel used to record from an imaging plane.","neurodata_type_inc":"NWBContainer","neurodata_type_def":"OpticalChannel"}],"datasets":[{"dtype":"text","name":"description","doc":"Description of the imaging plane.","quantity":"?"},{"dtype":"float","name":"excitation_lambda","doc":"Excitation wavelength, in nm."},{"dtype":"float","name":"imaging_rate","doc":"Rate that images are acquired, in Hz."},{"dtype":"text","name":"indicator","doc":"Calcium indicator."},{"dtype":"text","name":"location","doc":"Location of the imaging plane. Specify the area, layer, comments on estimation of area/layer, stereotaxic coordinates if in vivo, etc. Use standard atlas names for anatomical regions when possible."},{"shape":[[null,null,3],[null,null,null,3]],"dims":[["height","width","x|y|z"],["height","width","depth","x|y|z"]],"dtype":"float32","name":"manifold","doc":"Physical position of each pixel. 'xyz' represents the position of the pixel relative to the defined coordinate space.","quantity":"?","attributes":[{"name":"conversion","doc":"Scalar to multiply each element in data to convert it to the specified 'unit'. If the data are stored in acquisition system units or other units that require a conversion to be interpretable, multiply the data by 'conversion' to convert the data to the specified 'unit'. e.g. if the data acquisition system stores values in this object as pixels from x = -500 to 499, y = -500 to 499 that correspond to a 2 m x 2 m range, then the 'conversion' multiplier to get from raw data acquisition pixel units to meters is 2/1000.","required":false,"dtype":"float","default_value":1.0},{"name":"unit","doc":"Base unit of measurement for working with the data. The default value is 'meters'.","required":false,"dtype":"text","default_value":"meters"}]},{"dtype":"text","name":"reference_frame","doc":"Describes position and reference frame of manifold based on position of first element in manifold. For example, text description of anatomical location or vectors needed to rotate to common anatomical axis (eg, AP/DV/ML). This field is necessary to interpret manifold. If manifold is not present then this field is not required.","quantity":"?"}],"links":[{"name":"device","doc":"Link to the Device object that was used to record from this electrode.","target_type":"Device"}],"doc":"An imaging plane and its metadata.","quantity":"*","neurodata_type_inc":"NWBContainer","neurodata_type_def":"ImagingPlane"},{"groups":[{"groups":[{"name":"corrected","doc":"Image stack with frames shifted to the common coordinates.","neurodata_type_inc":"ImageSeries"},{"name":"xy_translation","doc":"Stores the x,y delta necessary to align each frame to the common coordinates, for example, to align each frame to a reference image.","neurodata_type_inc":"TimeSeries"}],"links":[{"name":"original","doc":"Link to ImageSeries object that is being registered.","target_type":"ImageSeries"}],"doc":"Reuslts from motion correction of an image stack.","quantity":"+","neurodata_type_inc":"NWBDataInterface","neurodata_type_def":"CorrectedImageStack"}],"doc":"An image stack where all frames are shifted (registered) to a common coordinate system, to account for movement and drift between frames. Note: each frame at each point in time is assumed to be 2-D (has only x & y dimensions).","default_name":"MotionCorrection","neurodata_type_inc":"NWBDataInterface","neurodata_type_def":"MotionCorrection"}]}{"groups":[{"datasets":[{"shape":[null,null],"dims":["num_rows","num_cols"],"dtype":"float32","name":"axis_1_phase_map","doc":"Phase response to stimulus on the first measured axis.","attributes":[{"name":"dimension","doc":"Number of rows and columns in the image. NOTE: row, column representation is equivalent to height,width.","dtype":"int32","shape":[null],"dims":["row_col"]},{"name":"field_of_view","doc":"Size of viewing area, in meters.","dtype":"float","shape":[null],"dims":["row|column"]},{"name":"unit","doc":"Unit that axis data is stored in (e.g., degrees).","dtype":"text"}]},{"shape":[null,null],"dims":["num_rows","num_cols"],"dtype":"float32","name":"axis_1_power_map","doc":"Power response on the first measured axis. Response is scaled so 0.0 is no power in the response and 1.0 is maximum relative power.","quantity":"?","attributes":[{"name":"dimension","doc":"Number of rows and columns in the image. NOTE: row, column representation is equivalent to height,width.","dtype":"int32","shape":[null],"dims":["row_col"]},{"name":"field_of_view","doc":"Size of viewing area, in meters.","dtype":"float","shape":[null],"dims":["row_col"]},{"name":"unit","doc":"Unit that axis data is stored in (e.g., degrees).","dtype":"text"}]},{"shape":[null,null],"dims":["num_rows","num_cols"],"dtype":"float32","name":"axis_2_phase_map","doc":"Phase response to stimulus on the second measured axis.","attributes":[{"name":"dimension","doc":"Number of rows and columns in the image. NOTE: row, column representation is equivalent to height,width.","dtype":"int32","shape":[null],"dims":["row_col"]},{"name":"field_of_view","doc":"Size of viewing area, in meters.","dtype":"float","shape":[null],"dims":["row_col"]},{"name":"unit","doc":"Unit that axis data is stored in (e.g., degrees).","dtype":"text"}]},{"shape":[null,null],"dims":["num_rows","num_cols"],"dtype":"float32","name":"axis_2_power_map","doc":"Power response on the second measured axis. Response is scaled so 0.0 is no power in the response and 1.0 is maximum relative power.","quantity":"?","attributes":[{"name":"dimension","doc":"Number of rows and columns in the image. NOTE: row, column representation is equivalent to height,width.","dtype":"int32","shape":[null],"dims":["row_col"]},{"name":"field_of_view","doc":"Size of viewing area, in meters.","dtype":"float","shape":[null],"dims":["row_col"]},{"name":"unit","doc":"Unit that axis data is stored in (e.g., degrees).","dtype":"text"}]},{"shape":[2],"dims":["names"],"dtype":"text","name":"axis_descriptions","doc":"Two-element array describing the contents of the two response axis fields. Description should be something like ['altitude', 'azimuth'] or '['radius', 'theta']."},{"shape":[null,null],"dims":["num_rows","num_cols"],"dtype":"uint16","name":"focal_depth_image","doc":"Gray-scale image taken with same settings/parameters (e.g., focal depth, wavelength) as data collection. Array format: [rows][columns].","attributes":[{"name":"bits_per_pixel","doc":"Number of bits used to represent each value. This is necessary to determine maximum (white) pixel value.","dtype":"int32"},{"name":"dimension","doc":"Number of rows and columns in the image. NOTE: row, column representation is equivalent to height,width.","dtype":"int32","shape":[null],"dims":["row_col"]},{"name":"field_of_view","doc":"Size of viewing area, in meters.","dtype":"float","shape":[null],"dims":["row_col"]},{"name":"focal_depth","doc":"Focal depth offset, in meters.","dtype":"float"},{"name":"format","doc":"Format of image. Right now only 'raw' is supported.","dtype":"text"}]},{"shape":[null,null],"dims":["num_rows","num_cols"],"dtype":"float32","name":"sign_map","doc":"Sine of the angle between the direction of the gradient in axis_1 and axis_2.","attributes":[{"name":"dimension","doc":"Number of rows and columns in the image. NOTE: row, column representation is equivalent to height,width.","dtype":"int32","shape":[null],"dims":["row_col"]},{"name":"field_of_view","doc":"Size of viewing area, in meters.","dtype":"float","shape":[null],"dims":["row_col"]}]},{"shape":[null,null],"dims":["num_rows","num_cols"],"dtype":"uint16","name":"vasculature_image","doc":"Gray-scale anatomical image of cortical surface. Array structure: [rows][columns]","attributes":[{"name":"bits_per_pixel","doc":"Number of bits used to represent each value. This is necessary to determine maximum (white) pixel value","dtype":"int32"},{"name":"dimension","doc":"Number of rows and columns in the image. NOTE: row, column representation is equivalent to height,width.","dtype":"int32","shape":[null],"dims":["row_col"]},{"name":"field_of_view","doc":"Size of viewing area, in meters.","dtype":"float","shape":[null],"dims":["row_col"]},{"name":"format","doc":"Format of image. Right now only 'raw' is supported.","dtype":"text"}]}],"doc":"Intrinsic signal optical imaging or widefield imaging for measuring retinotopy. Stores orthogonal maps (e.g., altitude/azimuth; radius/theta) of responses to specific stimuli and a combined polarity map from which to identify visual areas. Note: for data consistency, all images and arrays are stored in the format [row][column] and [row, col], which equates to [y][x]. Field of view and dimension arrays may appear backward (i.e., y before x).","default_name":"ImagingRetinotopy","neurodata_type_inc":"NWBDataInterface","neurodata_type_def":"ImagingRetinotopy"}]}U{"namespaces":[{"doc":"NWB namespace","schema":[{"source":"nwb.base"},{"source":"nwb.epoch"},{"source":"nwb.image"},{"source":"nwb.file"},{"source":"nwb.misc"},{"source":"nwb.behavior"},{"source":"nwb.ecephys"},{"source":"nwb.icephys"},{"source":"nwb.ogen"},{"source":"nwb.ophys"},{"source":"nwb.retinotopy"}],"name":"core","full_name":"NWB core","version":"2.1.0","author":["Andrew Tritt","Oliver Ruebel","Ryan Ly","Ben Dichter","Keith Godfrey","Jeff Teeters"],"contact":["ajtritt@lbl.gov","oruebel@lbl.gov","rly@lbl.gov","bdichter@lbl.gov","keithg@alleninstitute.org","jteeters@berkeley.edu"]}]}P/pynwb-1.2.1/tests/back_compat/1.0.3_str_pub.nwb0000644000655200065520000043134013612200244022551 0ustar circlecicircleci00000000000000HDF  2` TREEH:HEAP`H0 0 .speclocpHhTREEHEAPXPSNOD Hh(Pp P,H0XxPp TREEHEAPX P 0 TREEHEAPXP P TREE(HEAPX(presentationtemplates0TREEHEAPXPSNODhpTREEHEAPXPXxTREE*HEAPX related_publications8 @help=<=0?#]GCOLone publication 2019-11-27T17:32:07.247036-08:00ADDMEADDME 2019-11-27T17:32:07.246039-08:00 2019-11-27T17:32:07.246039-08:00=an NWB:N file for storing cellular-based neurophysiology data2.0.2 core NWBFile  {"groups":[{"datasets":[{"dtype":"float","name":"start_time","doc":"Start time of epoch, in seconds","neurodata_type_inc":"VectorData","attributes":[{"name":"description","doc":"value is 'start time of the epoch, in seconds'","dtype":"text","value":"start time of the epoch, in seconds"}]},{"dtype":"float","name":"stop_time","doc":"Stop time of epoch, in seconds","neurodata_type_inc":"VectorData","attributes":[{"name":"description","doc":"value is 'stop time of the epoch, in seconds'","dtype":"text","value":"stop time of the epoch, in seconds"}]},{"dtype":"text","name":"tags","doc":"User-defined tags that identify events. Tags are to help identify or categorize events.","quantity":"?","neurodata_type_inc":"VectorData","attributes":[{"name":"description","doc":"value is 'user-defined tags'","dtype":"text","value":"user-defined tags"}]},{"name":"tags_index","doc":"Index for tags","quantity":"?","neurodata_type_inc":"VectorIndex"},{"dtype":[{"doc":"Start index into the TimeSeries data[] field. COMMENT: This can be used to calculate location in TimeSeries timestamp[] field","name":"idx_start","dtype":"int32"},{"doc":"Number of data samples available in this time series, during this epoch.","name":"count","dtype":"int32"},{"doc":"the TimeSeries that this index applies to","name":"timeseries","dtype":{"target_type":"TimeSeries","reftype":"object"}}],"name":"timeseries","doc":"An index into a TimeSeries object","quantity":"?","neurodata_type_inc":"VectorData","attributes":[{"name":"help","doc":"Value is 'Data on how an epoch applies to a time series'","dtype":"text","value":"Data on how an epoch applies to a time series"}]},{"name":"timeseries_index","doc":"Index for timeseries","quantity":"?","neurodata_type_inc":"VectorIndex"}],"doc":"A container for aggregating epoch data and the TimeSeries that each epoch applies to","neurodata_type_inc":"DynamicTable","neurodata_type_def":"TimeIntervals","attributes":[{"name":"help","doc":"Value is 'A general epoch object'","dtype":"text","value":"A general epoch object"},{"name":"colnames","doc":"The names of the columns in this table. This should be used to specifying an order to the columns","dtype":"ascii","shape":[null],"dims":["num_columns"]},{"name":"description","doc":"Description of what is in this dynamic table","dtype":"text"}]}]}`SNOD2#]x2#]2#]2#]acquisitionanalysisprocessingstimulusgeneralfile_create_dateidentifiersession_descriptionsession_start_timetimestamps_reference_timespecifications3#]   *H  &{B{-{{5@V#8@VS {]1@V@VU@VSNODh-(  0 x(.8/p=0?8  1 H nwb_version H namespace Hneurodata_type PTREEhBHEAPXP?coreH?ATREEpFHEAPXB2.0.2HSNOD??ACETREEspQHEAP`ySNODCCE3#]GCOL8**{"datasets":[{"doc":"An abstract data type for a dataset","neurodata_type_def":"NWBData","attributes":[{"name":"help","doc":"Short description of what this type of Interface contains.","dtype":"text"}]},{"doc":"Pointers that index data values","neurodata_type_inc":"NWBData","neurodata_type_def":"Index","attributes":[{"name":"help","doc":"a help string","dtype":"text","value":"indexes into a list of values for a list of elements"},{"name":"target","doc":"the target dataset that this index applies to","dtype":{"target_type":"NWBData","reftype":"object"}}]},{"doc":"Data values indexed by pointer","neurodata_type_inc":"NWBData","neurodata_type_def":"VectorData","attributes":[{"name":"help","doc":"a help string","dtype":"text","value":"Values for a list of elements"},{"name":"description","doc":"A short description of what these vectors are","dtype":"text"}]},{"doc":"Pointers that index data values","neurodata_type_inc":"Index","neurodata_type_def":"VectorIndex","attributes":[{"name":"target","doc":"the target dataset that this index applies to","dtype":{"target_type":"VectorData","reftype":"object"}},{"name":"help","doc":"a help string","dtype":"text","value":"indexes into a list of values for a list of elements"}]},{"shape":[null],"dims":["num_elements"],"dtype":"int","doc":"a unique identifier for each element","default_name":"element_id","neurodata_type_inc":"NWBData","neurodata_type_def":"ElementIdentifiers","attributes":[{"name":"help","doc":"a help string","dtype":"text","value":"unique identifiers for a list of elements"}]},{"dtype":"int","doc":"a region/index into a DynamicTable","neurodata_type_inc":"VectorData","neurodata_type_def":"DynamicTableRegion","attributes":[{"name":"help","doc":"value is 'a subset (i.e. slice or region) of a DynamicTable'","dtype":"text","value":"a subset (i.e. slice or region) of a DynamicTable"},{"name":"table","doc":"a reference to the DynamicTable this region applies to","dtype":{"target_type":"DynamicTable","reftype":"object"}},{"name":"description","doc":"Description of what this table region points to","dtype":"text"}]},{"shape":[[null,null],[null,null,3],[null,null,4]],"dims":[["num_x","num_y"],["num_x","num_y","(r, g, b)"],["num_x","num_y","(r, g, b, a)"]],"doc":"Image base type.","neurodata_type_inc":"NWBData","neurodata_type_def":"Image","attributes":[{"name":"help","doc":"base image (use GrayscaleImage, RGBImage, RGBAImage, etc.)","dtype":"text"},{"name":"resolution","doc":"pixels / cm","required":false,"dtype":"float"},{"name":"description","doc":"description of image","required":false,"dtype":"text"}]}],"groups":[{"doc":"An abstract data type for a generic container storing collections of data and metadata. Base type for all data and metadata containers.","neurodata_type_def":"NWBContainer","attributes":[{"name":"help","doc":"Short description of what this type of NWBContainer contains.","dtype":"text"}]},{"doc":"An abstract data type for a generic container storing collections of data, as opposed to metadata.","neurodata_type_inc":"NWBContainer","neurodata_type_def":"NWBDataInterface","attributes":[{"name":"help","doc":"Short description of what this type of NWBContainer contains.","dtype":"text"}]},{"groups":[{"name":"sync","doc":"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.","quantity":"?"}],"datasets":[{"shape":[null],"dims":["num_times"],"dtype":"uint8","name":"control","doc":"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[].","quantity":"?"},{"shape":[null],"dims":["num_control_values"],"dtype":"text","name":"control_description","doc":"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.","quantity":"?"},{"shape":[[null],[null,null],[null,null,null],[null,null,null,null]],"dims":[["num_times"],["num_times","num_DIM2"],["num_times","num_DIM2","num_DIM3"],["num_times","num_DIM2","num_DIM3","num_DIM4"]],"name":"data","doc":"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":[{"name":"conversion","doc":"Scalar to multiply each element in data to convert it to the specified unit","required":false,"dtype":"float32","default_value":1.0},{"name":"resolution","doc":"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 -1.0","required":false,"dtype":"float32","default_value":0.0},{"name":"unit","doc":"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.","dtype":"text"}]},{"dtype":"float64","name":"starting_time","doc":"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.","quantity":"?","attributes":[{"name":"rate","doc":"Sampling rate, in Hz COMMENT: Rate information is stored in Hz","dtype":"float32"},{"name":"unit","doc":"Value is 'Seconds'","dtype":"text","value":"Seconds"}]},{"shape":[null],"dims":["num_times"],"dtype":"float64","name":"timestamps","doc":"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.","quantity":"?","attributes":[{"name":"interval","doc":"Value is '1'","dtype":"int32","value":1},{"name":"unit","doc":"Value is 'Seconds'","dtype":"text","value":"Seconds"}]}],"doc":"General purpose time series.","neurodata_type_inc":"NWBDataInterface","neurodata_type_def":"TimeSeries","attributes":[{"name":"comments","doc":"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.","required":false,"dtype":"text","default_value":"no comments"},{"name":"description","doc":"Description of TimeSeries","required":false,"dtype":"text","default_value":"no description"},{"name":"help","doc":"Value is 'General time series object'","dtype":"text","value":"General time series object"}]},{"groups":[{"doc":"Interface objects containing data output from processing steps","quantity":"*","neurodata_type_inc":"NWBDataInterface"}],"doc":"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.","neurodata_type_inc":"NWBContainer","neurodata_type_def":"ProcessingModule","attributes":[{"name":"description","doc":"Description of Module","dtype":"text"},{"name":"help","doc":"Value is 'A collection of analysis outputs from processing of data'","dtype":"text","value":"A collection of analysis outputs from processing of data"}]},{"datasets":[{"doc":"Images stored in this NWBDataInterface","quantity":"+","neurodata_type_inc":"Image"}],"doc":"A NWBDataInterface for storing images that have some relationship","default_name":"Images","neurodata_type_inc":"NWBDataInterface","neurodata_type_def":"Images","attributes":[{"name":"description","doc":"Description of images in this container","dtype":"text"},{"name":"help","doc":"Value is 'A collection of images that have some meaningful relationship'","dtype":"text","value":"A collection of images that have some meaningful relationship"}]},{"datasets":[{"shape":[null],"dims":["num_rows"],"dtype":"int","name":"id","doc":"The unique identifier for the rows in this dynamic table","neurodata_type_inc":"ElementIdentifiers"},{"doc":"The vector columns in this dynamic table","quantity":"*","neurodata_type_inc":"VectorData"},{"doc":"The indices for the vector columns in this dynamic table","quantity":"*","neurodata_type_inc":"VectorIndex"}],"doc":"A group containing multiple datasets that are aligned on the first dimension (Currently, this requirement if left up to APIs to check and enforce). Apart from a column that contains unique identifiers for each row there are no other required datasets. Users are free to add any number of VectorData objects here. Table functionality is already supported through compound types, which is analogous to storing an array-of-structs. DynamicTable can be thought of as a struct-of-arrays. This provides an alternative structure to choose from when optimizing storage for anticipated access patterns. Additionally, this type provides a way of creating a table without having to define a compound type up front. Although this convenience may be attractive, users should think carefully about how data will be accessed. DynamicTable is more appropriate for column-centric access, whereas a dataset with a compound type would be more appropriate for row-centric access. Finally, data size should also be taken into account. For small tables, performance loss may be an acceptable trade-off for the flexibility of a DynamicTable. For example, DynamicTable was originally developed for storing trial data and spike unit metadata. Both of these use cases are expected to produce relatively small tables, so the spatial locality of multiple datasets present in a DynamicTable is not expected to have a significant performance impact. Additionally, requirements of trial and unit metadata tables are sufficiently diverse that performance implications can be overlooked in favor of usability.","neurodata_type_inc":"NWBDataInterface","neurodata_type_def":"DynamicTable","attributes":[{"name":"help","doc":"Value is 'A column-centric table'","dtype":"text","value":"A column-centric table"},{"name":"colnames","doc":"The names of the columns in this table. This should be used to specifying an order to the columns","dtype":"ascii","shape":[null],"dims":["num_columns"]},{"name":"description","doc":"Description of what is in this dynamic table","dtype":"text"}]}]}SNODTGXxh@NHt 3#]03#]@3#]P3#]`3#]nwb.basenwb.epochnwb.imagenwb.filenwb.miscnwb.behaviornwb.ecephysnwb.icephysnwb.ogennwb.ophysnwb.retinotopynamespaceGCOL@&{"datasets":[{"shape":[null,null],"dims":["y","x"],"doc":"Grayscale image","neurodata_type_inc":"Image","neurodata_type_def":"GrayscaleImage","attributes":[{"name":"help","doc":"base image (use GrayscaleImage, RGBImage, RGBAImage, etc.)","dtype":"text"},{"name":"resolution","doc":"pixels / cm","required":false,"dtype":"float"},{"name":"description","doc":"description of image","required":false,"dtype":"text"}]},{"shape":[null,null,3],"dims":["y","x","R,G,B"],"doc":"Color image","neurodata_type_inc":"Image","neurodata_type_def":"RGBImage","attributes":[{"name":"help","doc":"base image (use GrayscaleImage, RGBImage, RGBAImage, etc.)","dtype":"text"},{"name":"resolution","doc":"pixels / cm","required":false,"dtype":"float"},{"name":"description","doc":"description of image","required":false,"dtype":"text"}]},{"shape":[null,null,4],"dims":["y","x","R,G,B,A"],"doc":"Color image with transparency","neurodata_type_inc":"Image","neurodata_type_def":"RGBAImage","attributes":[{"name":"help","doc":"base image (use GrayscaleImage, RGBImage, RGBAImage, etc.)","dtype":"text"},{"name":"resolution","doc":"pixels / cm","required":false,"dtype":"float"},{"name":"description","doc":"description of image","required":false,"dtype":"text"}]}],"groups":[{"datasets":[{"shape":[[null,null,null],[null,null,null,null]],"dims":[["frame","y","x"],["frame","z","y","x"]],"dtype":"numeric","name":"data","doc":"Either binary data containing image or empty.","quantity":"?","attributes":[{"name":"conversion","doc":"Scalar to multiply each element in data to convert it to the specified unit","required":false,"dtype":"float32","default_value":1.0},{"name":"resolution","doc":"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 -1.0","required":false,"dtype":"float32","default_value":0.0},{"name":"unit","doc":"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.","dtype":"text"}]},{"shape":[null],"dims":["rank"],"dtype":"int32","name":"dimension","doc":"Number of pixels on x, y, (and z) axes.","quantity":"?"},{"shape":[null],"dims":["num_files"],"dtype":"text","name":"external_file","doc":"Path or URL to one or more external file(s). Field only present if format=external. NOTE: this is only relevant if the image is stored in the file system as one or more image file(s). This field should NOT be used if the image is stored in another HDF5 file and that file is HDF5 linked to this file.","quantity":"?","attributes":[{"name":"starting_frame","doc":"Each entry is the frame number (within the full ImageSeries) of the first frame in the corresponding external_file entry. This serves as an index to what frames each file contains, allowing random access.Zero-based indexing is used. (The first element will always be zero).","dtype":"int","shape":[null],"dims":["num_files"]}]},{"dtype":"text","name":"format","doc":"Format of image. If this is 'external' then the field external_file contains the path or URL information to that file. For tiff, png, jpg, etc, the binary representation of the image is stored in data. If the format is raw then the fields bit_per_pixel and dimension are used. For raw images, only a single channel is stored (eg, red).","quantity":"?"}],"doc":"General image data that is common between acquisition and stimulus time series. Sometimes the image data is stored in the HDF5 file in a raw format while other times it will be stored as an external image file in the host file system. The data field will either be binary data or empty. TimeSeries::data array structure: [frame] [y][x] or [frame][z][y][x].","neurodata_type_inc":"TimeSeries","neurodata_type_def":"ImageSeries","attributes":[{"name":"help","doc":"Value is 'Storage object for time-series 2-D image data'","dtype":"text","value":"Storage object for time-series 2-D image data"},{"name":"comments","doc":"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.","required":false,"dtype":"text","default_value":"no comments"},{"name":"description","doc":"Description of TimeSeries","required":false,"dtype":"text","default_value":"no description"}]},{"links":[{"name":"masked_imageseries","doc":"Link to ImageSeries that mask is applied to.","target_type":"ImageSeries"}],"doc":"An alpha mask that is applied to a presented visual stimulus. The data[] array contains an array of mask values that are applied to the displayed image. Mask values are stored as RGBA. Mask can vary with time. The timestamps array indicates the starting time of a mask, and that mask pattern continues until it's explicitly changed.","neurodata_type_inc":"ImageSeries","neurodata_type_def":"ImageMaskSeries","attributes":[{"name":"help","doc":"Value is 'An alpha mask that is applied to a presented visual stimulus'","dtype":"text","value":"An alpha mask that is applied to a presented visual stimulus"},{"name":"comments","doc":"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.","required":false,"dtype":"text","default_value":"no comments"},{"name":"description","doc":"Description of TimeSeries","required":false,"dtype":"text","default_value":"no description"}]},{"datasets":[{"dtype":"float32","name":"distance","doc":"Distance from camera/monitor to target/eye.","quantity":"?"},{"shape":[[2],[3]],"dims":[["width|height"],["width|height|depth"]],"dtype":"float32","name":"field_of_view","doc":"Width, height and depth of image, or imaged area (meters).","quantity":"?"},{"dtype":"text","name":"orientation","doc":"Description of image relative to some reference frame (e.g., which way is up). Must also specify frame of reference.","quantity":"?"}],"doc":"Image data that is presented or recorded. A stimulus template movie will be stored only as an image. When the image is presented as stimulus, additional data is required, such as field of view (eg, how much of the visual field the image covers, or how what is the area of the target being imaged). If the OpticalSeries represents acquired imaging data, orientation is also important.","neurodata_type_inc":"ImageSeries","neurodata_type_def":"OpticalSeries","attributes":[{"name":"help","doc":"Value is 'Time-series image stack for optical recording or stimulus'","dtype":"text","value":"Time-series image stack for optical recording or stimulus"},{"name":"comments","doc":"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.","required":false,"dtype":"text","default_value":"no comments"},{"name":"description","doc":"Description of TimeSeries","required":false,"dtype":"text","default_value":"no description"}]},{"datasets":[{"shape":[null],"dims":["num_times"],"dtype":"int","name":"data","doc":"Index of the frame in the referenced ImageSeries.","attributes":[{"name":"conversion","doc":"Scalar to multiply each element in data to convert it to the specified unit","required":false,"dtype":"float32","default_value":1.0},{"name":"resolution","doc":"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 -1.0","required":false,"dtype":"float32","default_value":0.0},{"name":"unit","doc":"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.","dtype":"text"}]}],"links":[{"name":"indexed_timeseries","doc":"HDF5 link to TimeSeries containing images that are indexed.","target_type":"ImageSeries"}],"doc":"Stores indices to image frames stored in an ImageSeries. The purpose of the ImageIndexSeries 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 ImageSeries, and the timestamps array indicates when that image was displayed.","neurodata_type_inc":"TimeSeries","neurodata_type_def":"IndexSeries","attributes":[{"name":"help","doc":"Value is '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'","dtype":"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"},{"name":"comments","doc":"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.","required":false,"dtype":"text","default_value":"no comments"},{"name":"description","doc":"Description of TimeSeries","required":false,"dtype":"text","default_value":"no description"}]}]}B{"groups":[{"groups":[{"groups":[{"doc":"Any objects representing acquired data","quantity":"*","neurodata_type_inc":"NWBDataInterface"}],"name":"acquisition","doc":"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."},{"groups":[{"doc":"Custom analysis results","quantity":"*","neurodata_type_inc":"NWBContainer"}],"name":"analysis","doc":"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 could be shared with other labs."},{"groups":[{"doc":"Intermediate analysis of acquired data","quantity":"*","neurodata_type_inc":"ProcessingModule"}],"name":"processing","doc":"The home for ProcessingModules. 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."},{"groups":[{"groups":[{"doc":"TimeSeries objects containing data of presented stimuli","quantity":"*","neurodata_type_inc":"TimeSeries"}],"name":"presentation","doc":"Stimuli presented during the experiment."},{"groups":[{"doc":"TimeSeries objects containing template data of presented stimuli","quantity":"*","neurodata_type_inc":"TimeSeries"}],"name":"templates","doc":"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."}],"name":"stimulus","doc":"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."},{"groups":[{"doc":"place-holder than can be extended so that lab-specific meta-data can be placed in /general","quantity":"*","neurodata_type_inc":"NWBContainer","neurodata_type_def":"LabMetaData","attributes":[{"name":"help","doc":"Short description of what this type of NWBContainer contains.","dtype":"text"}]},{"groups":[{"doc":"One of possibly many. Information about device and device description.","quantity":"+","neurodata_type_inc":"NWBContainer","neurodata_type_def":"Device","attributes":[{"name":"help","doc":"Value is 'A recording device e.g. amplifier'.","dtype":"text","value":"A recording device e.g. amplifier"}]}],"name":"devices","doc":"Description of hardware devices used during experiment. COMMENT: Eg, monitors, ADC boards, microscopes, etc","quantity":"?"},{"datasets":[{"dtype":"text","name":"age","doc":"Age of subject","quantity":"?"},{"dtype":"isodatetime","name":"date_of_birth","doc":"can be supplied instead of age","quantity":"?"},{"dtype":"text","name":"description","doc":"Description of subject and where subject came from (e.g., breeder, if animal).","quantity":"?"},{"dtype":"text","name":"genotype","doc":"Genetic strain COMMENT: If absent, assume Wild Type (WT)","quantity":"?"},{"dtype":"text","name":"sex","doc":"Gender of subject","quantity":"?"},{"dtype":"text","name":"species","doc":"Species of subject","quantity":"?"},{"dtype":"text","name":"subject_id","doc":"ID of animal/person used/participating in experiment (lab convention)","quantity":"?"},{"dtype":"text","name":"weight","doc":"Weight at time of experiment, at time of surgery and at other important times","quantity":"?"}],"name":"subject","doc":"Information about the animal or person from which the data was measured.","quantity":"?","neurodata_type_inc":"NWBContainer","neurodata_type_def":"Subject","attributes":[{"name":"help","doc":"Value is 'Information about the subject'","dtype":"text","value":"Information about the subject"}]},{"groups":[{"doc":"One of possibly many groups, one for each electrode group.","quantity":"*","neurodata_type_inc":"ElectrodeGroup"},{"datasets":[{"dtype":"float","name":"x","doc":"the x coordinate of the channel location","neurodata_type_inc":"VectorData","attributes":[{"name":"description","doc":"value is 'the x coordinate of the channel location'","dtype":"text","value":"the x coordinate of the channel location"}]},{"dtype":"float","name":"y","doc":"the y coordinate of the channel location","neurodata_type_inc":"VectorData","attributes":[{"name":"description","doc":"value is 'the y coordinate of the channel location'","dtype":"text","value":"the y coordinate of the channel location"}]},{"dtype":"float","name":"z","doc":"the z coordinate of the channel location","neurodata_type_inc":"VectorData","attributes":[{"name":"description","doc":"value is 'the z coordinate of the channel location'","dtype":"text","value":"the z coordinate of the channel location"}]},{"dtype":"float","name":"imp","doc":"the impedance of the channel","neurodata_type_inc":"VectorData","attributes":[{"name":"description","doc":"value is 'the impedance of the channel'","dtype":"text","value":"the impedance of the channel"}]},{"dtype":"ascii","name":"location","doc":"the location of channel within the subject e.g. brain region","neurodata_type_inc":"VectorData","attributes":[{"name":"description","doc":"value is 'the location of channel within the subject e.g. brain region'","dtype":"text","value":"the location of channel within the subject e.g. brain region"}]},{"dtype":"float","name":"filtering","doc":"description of hardware filtering","neurodata_type_inc":"VectorData","attributes":[{"name":"description","doc":"value is 'description of hardware filtering'","dtype":"text","value":"description of hardware filtering"}]},{"dtype":{"target_type":"ElectrodeGroup","reftype":"object"},"name":"group","doc":"a reference to the ElectrodeGroup this electrode is a part of","neurodata_type_inc":"VectorData","attributes":[{"name":"description","doc":"value is 'a reference to the ElectrodeGroup this electrode is a part of'","dtype":"text","value":"a reference to the ElectrodeGroup this electrode is a part of"}]},{"dtype":"ascii","name":"group_name","doc":"name of the ElectrodeGroup this electrode is a part of","neurodata_type_inc":"VectorData","attributes":[{"name":"description","doc":"value is 'the name of the ElectrodeGroup this electrode is a part of'","dtype":"text","value":"the name of the ElectrodeGroup this electrode is a part of"}]}],"name":"electrodes","doc":"A table of all electrodes (i.e. channels) used for recording.","quantity":"?","neurodata_type_inc":"DynamicTable"}],"name":"extracellular_ephys","doc":"Metadata related to extracellular electrophysiology.","quantity":"?"},{"groups":[{"doc":"One of possibly many. COMMENT: Name should be informative.","quantity":"*","neurodata_type_inc":"IntracellularElectrode"},{"name":"sweep_table","doc":"The table which groups different PatchClampSeries together.","quantity":"?","neurodata_type_inc":"SweepTable"}],"datasets":[{"dtype":"text","name":"filtering","doc":"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.","quantity":"?"}],"name":"intracellular_ephys","doc":"Metadata related to intracellular electrophysiology","quantity":"?"},{"groups":[{"doc":"One of possibly many groups describing an optogenetic stimulation site. COMMENT: Name is arbitrary but should be meaningful. Name is referenced by OptogeneticSeries.","quantity":"*","neurodata_type_inc":"OptogeneticStimulusSite"}],"name":"optogenetics","doc":"Metadata describing optogenetic stimuluation","quantity":"?"},{"groups":[{"doc":"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.","quantity":"*","neurodata_type_inc":"ImagingPlane"}],"name":"optophysiology","doc":"Metadata related to optophysiology.","quantity":"?"}],"datasets":[{"dtype":"text","name":"data_collection","doc":"Notes about data collection and analysis.COMMENT: Can be from Methods","quantity":"?"},{"dtype":"text","name":"experiment_description","doc":"General description of the experiment.COMMENT: Can be from Methods","quantity":"?"},{"dtype":"text","name":"experimenter","doc":"Name of person who performed the experiment.COMMENT: More than one person OK. Can specify roles of different people involved.","quantity":"?"},{"dtype":"text","name":"institution","doc":"Institution(s) where experiment was performed","quantity":"?"},{"shape":[null],"dims":["num_keywords"],"dtype":"text","name":"keywords","doc":"Terms to search over","quantity":"?"},{"dtype":"text","name":"lab","doc":"Lab where experiment was performed","quantity":"?"},{"dtype":"text","name":"notes","doc":"Notes about the experiment. COMMENT: Things particular to this experiment","quantity":"?"},{"dtype":"text","name":"pharmacology","doc":"Description of drugs used, including how and when they were administered. COMMENT: Anesthesia(s), painkiller(s), etc., plus dosage, concentration, etc.","quantity":"?"},{"dtype":"text","name":"protocol","doc":"Experimental protocol, if applicable. COMMENT: E.g., include IACUC protocol.","quantity":"?"},{"dtype":"text","name":"related_publications","doc":"Publication information. COMMENT: PMID, DOI, URL, etc. If multiple, concatenate together and describe which is which. such as PMID, DOI, URL, etc","quantity":"?"},{"dtype":"text","name":"session_id","doc":"Lab-specific ID for the session.COMMENT: Only 1 session_id per file, with all time aligned to experiment start time.","quantity":"?"},{"dtype":"text","name":"slices","doc":"Description of slices, including information about preparation thickness, orientation, temperature and bath solution","quantity":"?"},{"dtype":"text","name":"source_script","doc":"Script file used to create this NWB file.","quantity":"?","attributes":[{"name":"file_name","doc":"Name of script file","dtype":"text"}]},{"dtype":"text","name":"stimulus","doc":"Notes about stimuli, such as how and where presented. COMMENT: Can be from Methods.","quantity":"?"},{"dtype":"text","name":"surgery","doc":"Narrative description about surgery/surgeries, including date(s) and who performed surgery. COMMENT: Much can be copied from Methods.","quantity":"?"},{"dtype":"text","name":"virus","doc":"Information about virus(es) used in experiments, including virus ID, source, date made, injection location, volume, etc.","quantity":"?"}],"name":"general","doc":"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 (e.g., 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. 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."},{"groups":[{"name":"epochs","doc":"divisions in time marking experimental stages or sub-divisions of a single recording session","quantity":"?","neurodata_type_inc":"TimeIntervals"},{"name":"trials","doc":"repeated experimental events that have a logical grouping","quantity":"?","neurodata_type_inc":"TimeIntervals"},{"name":"invalid_times","doc":"time intervals that should be removed from analysis","quantity":"?","neurodata_type_inc":"TimeIntervals"},{"doc":"an optional additional table for describing other experimental time intervals","quantity":"*","neurodata_type_inc":"TimeIntervals"}],"name":"intervals","doc":"Experimental intervals, whether that be logically distinct sub-experiments having a particular scientific goal, trials (see trials subgroup) during an experiment, or epochs (see epochs subgroup) deriving from analysis of data.","quantity":"?"},{"name":"units","doc":"Data about units","quantity":"?","neurodata_type_inc":"Units"}],"datasets":[{"shape":[null],"dims":["num_modifications"],"dtype":"isodatetime","name":"file_create_date","doc":"A record of the date the file was created and of subsequent modifications. COMMENT: - The date is stored in UTC with local timezone offset as ISO 8601 extended formatted strings: 2018-09-28T14:43:54.123+02:00 - Dates stored in UTC end in \"Z\" with no timezone offset. - Date accuracy is up to milliseconds. - The file can be created after the experiment was run, so this may differ from the experiment start time. - Each modification to the nwb file adds a new entry to the array."},{"dtype":"text","name":"identifier","doc":"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."},{"dtype":"text","name":"session_description","doc":"One or two sentences describing the experiment and data in the file."},{"dtype":"isodatetime","name":"session_start_time","doc":"Date and time of the experiment/session start. COMMENT: - The date is stored in UTC with local timezone offset as ISO 8601 extended formatted string: 2018-09-28T14:43:54.123+02:00 - Dates stored in UTC end in \"Z\" with no timezone offset. - Date accuracy is up to milliseconds."},{"dtype":"isodatetime","name":"timestamps_reference_time","doc":"Date and time corresponding to time zero of all timestamps. COMMENT: - The date is stored in UTC with local timezone offset as ISO 8601 extended formatted string: 2018-09-28T14:43:54.123+02:00 - Dates stored in UTC end in \"Z\" with no timezone offset. - Date accuracy is up to milliseconds. - All times stored in the file use this time as reference (ie, time zero)."}],"name":"root","doc":"Top level of NWB file.","neurodata_type_inc":"NWBContainer","neurodata_type_def":"NWBFile","attributes":[{"name":"help","doc":"Value is 'an NWB:N file for storing cellular-based neurophysiology data'","dtype":"text","value":"an NWB:N file for storing cellular-based neurophysiology data"},{"name":"nwb_version","doc":"File version string. COMMENT: Eg, NWB-1.0.0. This will be the name of the format with trailing major, minor and patch numbers.","dtype":"text","value":"2.0.2"}]}]}-{"groups":[{"datasets":[{"shape":[[null],[null,null]],"dims":[["num_times"],["num_times","num_features"]],"dtype":"numeric","name":"data","doc":"Values of each feature at each time.","attributes":[{"name":"unit","doc":"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.","required":false,"dtype":"text","default_value":"see 'feature_units'"},{"name":"conversion","doc":"Scalar to multiply each element in data to convert it to the specified unit","required":false,"dtype":"float32","default_value":1.0},{"name":"resolution","doc":"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 -1.0","required":false,"dtype":"float32","default_value":0.0}]},{"shape":[null],"dims":["num_features"],"dtype":"text","name":"feature_units","doc":"Units of each feature.","quantity":"?"},{"shape":[null],"dims":["num_features"],"dtype":"text","name":"features","doc":"Description of the features represented in TimeSeries::data."}],"doc":"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.","neurodata_type_inc":"TimeSeries","neurodata_type_def":"AbstractFeatureSeries","attributes":[{"name":"help","doc":"Value is 'Features of an applied stimulus. This is useful when storing the raw stimulus is impractical'","dtype":"text","value":"Features of an applied stimulus. This is useful when storing the raw stimulus is impractical"},{"name":"comments","doc":"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.","required":false,"dtype":"text","default_value":"no comments"},{"name":"description","doc":"Description of TimeSeries","required":false,"dtype":"text","default_value":"no description"}]},{"datasets":[{"shape":[null],"dims":["num_times"],"dtype":"text","name":"data","doc":"Annotations made during an experiment.","attributes":[{"name":"resolution","doc":"Value is -1.0","dtype":"float","value":-1.0},{"name":"unit","doc":"Value is 'n/a'","dtype":"text","value":"n/a"},{"name":"conversion","doc":"Scalar to multiply each element in data to convert it to the specified unit","required":false,"dtype":"float32","default_value":1.0}]}],"doc":"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.","neurodata_type_inc":"TimeSeries","neurodata_type_def":"AnnotationSeries","attributes":[{"name":"help","doc":"Value is 'Time-stamped annotations about an experiment'","dtype":"text","value":"Time-stamped annotations about an experiment"},{"name":"comments","doc":"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.","required":false,"dtype":"text","default_value":"no comments"},{"name":"description","doc":"Description of TimeSeries","required":false,"dtype":"text","default_value":"no description"}]},{"datasets":[{"shape":[null],"dims":["num_times"],"dtype":"int8","name":"data","doc":">0 if interval started, <0 if interval ended.","attributes":[{"name":"resolution","doc":"Value is -1.0","dtype":"float","value":-1.0},{"name":"unit","doc":"Value is 'n/a'","dtype":"text","value":"n/a"},{"name":"conversion","doc":"Scalar to multiply each element in data to convert it to the specified unit","required":false,"dtype":"float32","default_value":1.0}]}],"doc":"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.","neurodata_type_inc":"TimeSeries","neurodata_type_def":"IntervalSeries","attributes":[{"name":"help","doc":"Value is 'Stores the start and stop times for events'","dtype":"text","value":"Stores the start and stop times for events"},{"name":"comments","doc":"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.","required":false,"dtype":"text","default_value":"no comments"},{"name":"description","doc":"Description of TimeSeries","required":false,"dtype":"text","default_value":"no description"}]},{"groups":[{"datasets":[{"dtype":"text","name":"band_name","doc":"the name of the band e.g. theta","neurodata_type_inc":"VectorData","attributes":[{"name":"description","doc":"value is 'the name of the band e.g. theta'","dtype":"text","value":"the name of the band e.g. theta"}]},{"shape":[null,2],"dims":["num_bands","low, high"],"dtype":"float","name":"band_limits","doc":"Low and high limit of each band in Hz. If it is a Gaussian filter, use 2 SD on either side of the center","neurodata_type_inc":"VectorData","attributes":[{"name":"description","doc":"value is 'Low and high limit of each band in Hz. If it is a Gaussian filter, use 2 SD on either side of the center'","dtype":"text","value":"Low and high limit of each band in Hz. If it is a Gaussian filter, use 2 SD on either side of the center"}]},{"shape":[null],"dims":["num_bands"],"dtype":"float","name":"band_mean","doc":"The mean Gaussian filters in Hz","neurodata_type_inc":"VectorData","attributes":[{"name":"description","doc":"The mean Gaussian filters in Hz","dtype":"text","value":"The mean Gaussian filters in Hz"}]},{"shape":[null],"dims":["num_bands"],"dtype":"float","name":"band_stdev","doc":"The standard devaition of Gaussian filters in Hz","neurodata_type_inc":"VectorData","attributes":[{"name":"description","doc":"The standard devaition of Gaussian filters in Hz","dtype":"text","value":"The standard devaition of Gaussian filters in Hz"}]}],"name":"bands","doc":"A table for describing the bands that this series was generated from. There should be one row in this table for each band","neurodata_type_inc":"DynamicTable"}],"datasets":[{"shape":[null,null,null],"dims":["num_times","num_channels","num_bands"],"dtype":"numeric","name":"data","doc":"The data goes here","attributes":[{"name":"conversion","doc":"Scalar to multiply each element in data to convert it to the specified unit","required":false,"dtype":"float32","default_value":1.0},{"name":"resolution","doc":"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 -1.0","required":false,"dtype":"float32","default_value":0.0},{"name":"unit","doc":"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.","dtype":"text"}]},{"dtype":"text","name":"metric","doc":"recommended: phase, amplitude, power"}],"links":[{"name":"source_timeseries","doc":"HDF5 link to TimesSeries that this data was calculated from. Metadata about electrodes and their position can be read from that ElectricalSeries so it is not necessary to store that information here","target_type":"TimeSeries","quantity":"?"}],"doc":"Holds spectral analysis of a timeseries. For instance of LFP or a speech signal","neurodata_type_inc":"TimeSeries","neurodata_type_def":"DecompositionSeries","attributes":[{"name":"comments","doc":"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.","required":false,"dtype":"text","default_value":"no comments"},{"name":"description","doc":"Description of TimeSeries","required":false,"dtype":"text","default_value":"no description"},{"name":"help","doc":"Value is 'General time series object'","dtype":"text","value":"General time series object"}]},{"datasets":[{"name":"spike_times_index","doc":"the index into the spike_times dataset","quantity":"?","neurodata_type_inc":"VectorIndex"},{"dtype":"double","name":"spike_times","doc":"the spike times for each unit","quantity":"?","neurodata_type_inc":"VectorData"},{"name":"obs_intervals_index","doc":"the index into the obs_intervals dataset","quantity":"?","neurodata_type_inc":"VectorIndex"},{"shape":[null,2],"dims":["num_intervals","start|end"],"dtype":"double","name":"obs_intervals","doc":"the observation intervals for each unit","quantity":"?","neurodata_type_inc":"VectorData"},{"name":"electrodes_index","doc":"the index into electrodes","quantity":"?","neurodata_type_inc":"VectorIndex"},{"name":"electrodes","doc":"the electrode that each spike unit came from","quantity":"?","neurodata_type_inc":"DynamicTableRegion"},{"dtype":{"target_type":"ElectrodeGroup","reftype":"object"},"name":"electrode_group","doc":"the electrode group that each spike unit came from","quantity":"?","neurodata_type_inc":"VectorData"},{"shape":[[null,null],[null,null,null]],"dims":[["num_units","num_samples"],["num_units","num_samples","num_electrodes"]],"dtype":"float","name":"waveform_mean","doc":"the spike waveform mean for each spike unit","quantity":"?","neurodata_type_inc":"VectorData"},{"shape":[[null,null],[null,null,null]],"dims":[["num_units","num_samples"],["num_units","num_samples","num_electrodes"]],"dtype":"float","name":"waveform_sd","doc":"the spike waveform standard deviation for each spike unit","quantity":"?","neurodata_type_inc":"VectorData"}],"doc":"Data about spiking units. Event times of observed units (e.g. cell, synapse, etc.) should be concatenated and stored in spike_times.","default_name":"Units","neurodata_type_inc":"DynamicTable","neurodata_type_def":"Units","attributes":[{"name":"help","doc":"Value is 'Data about spiking units'","dtype":"text","value":"Data about spiking units"},{"name":"colnames","doc":"The names of the columns in this table. This should be used to specifying an order to the columns","dtype":"ascii","shape":[null],"dims":["num_columns"]},{"name":"description","doc":"Description of what is in this dynamic table","dtype":"text"}]}]}{"groups":[{"datasets":[{"shape":[[null],[null,null]],"dims":[["num_times"],["num_times","num_features"]],"dtype":"numeric","name":"data","doc":"2-D array storing position or direction relative to some reference frame.","attributes":[{"name":"unit","doc":"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.","required":false,"dtype":"text","default_value":"meter"},{"name":"conversion","doc":"Scalar to multiply each element in data to convert it to the specified unit","required":false,"dtype":"float32","default_value":1.0},{"name":"resolution","doc":"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 -1.0","required":false,"dtype":"float32","default_value":0.0}]},{"dtype":"text","name":"reference_frame","doc":"Description defining what exactly 'straight-ahead' means.","quantity":"?"}],"doc":"Direction, e.g., of gaze or travel, or position. The TimeSeries::data field is a 2D array storing position or direction relative to some reference frame. Array structure: [num measurements] [num dimensions]. Each SpatialSeries has a text dataset reference_frame that indicates the zero-position, or the zero-axes for direction. For example, if representing gaze direction, 'straight-ahead' might be a specific pixel on the monitor, or some other point in space. For position data, the 0,0 point might be the top-left corner of an enclosure, as viewed from the tracking camera. The unit of data will indicate how to interpret SpatialSeries values.","neurodata_type_inc":"TimeSeries","neurodata_type_def":"SpatialSeries","attributes":[{"name":"help","doc":"Value is: Stores points in space over time. The data[] array structure is [num samples][num spatial dimensions]","dtype":"text","value":"Stores points in space over time. The data[] array structure is [num samples][num spatial dimensions]"},{"name":"comments","doc":"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.","required":false,"dtype":"text","default_value":"no comments"},{"name":"description","doc":"Description of TimeSeries","required":false,"dtype":"text","default_value":"no description"}]},{"groups":[{"doc":"IntervalSeries object containing start and stop times of epochs","quantity":"*","neurodata_type_inc":"IntervalSeries"}],"doc":"TimeSeries for storing behavioral epochs. The objective of this and the other two Behavioral interfaces (e.g. BehavioralEvents and BehavioralTimeSeries) is to provide generic hooks for software tools/scripts. This allows a tool/script to take the output one specific interface (e.g., UnitTimes) and plot that data relative to another data modality (e.g., behavioral events) without having to define all possible modalities in advance. Declaring one of these interfaces means that one or more TimeSeries of the specified type is published. These TimeSeries should reside in a group having the same name as the interface. For example, if a BehavioralTimeSeries interface is declared, the module will have one or more TimeSeries defined in the module sub-group 'BehavioralTimeSeries'. BehavioralEpochs should use IntervalSeries. BehavioralEvents is used for irregular events. BehavioralTimeSeries is for continuous data.","default_name":"BehavioralEpochs","neurodata_type_inc":"NWBDataInterface","neurodata_type_def":"BehavioralEpochs","attributes":[{"name":"help","doc":"Value is 'General container for storing behavioral epochs'","dtype":"text","value":"General container for storing behavioral epochs"}]},{"groups":[{"doc":"TimeSeries object containing irregular behavioral events","quantity":"*","neurodata_type_inc":"TimeSeries"}],"doc":"TimeSeries for storing behavioral events. See description of BehavioralEpochs for more details.","default_name":"BehavioralEvents","neurodata_type_inc":"NWBDataInterface","neurodata_type_def":"BehavioralEvents","attributes":[{"name":"help","doc":"Value is 'Position data, whether along the x, xy or xyz axis'","dtype":"text","value":"Position data, whether along the x, xy or xyz axis"}]},{"groups":[{"doc":"TimeSeries object containing continuous behavioral data","quantity":"*","neurodata_type_inc":"TimeSeries"}],"doc":"TimeSeries for storing Behavoioral time series data.See description of BehavioralEpochs for more details.","default_name":"BehavioralTimeSeries","neurodata_type_inc":"NWBDataInterface","neurodata_type_def":"BehavioralTimeSeries","attributes":[{"name":"help","doc":"Value is 'General container for storing continuously sampled behavioral data.'","dtype":"text","value":"General container for storing continuously sampled behavioral data."}]},{"groups":[{"doc":"TimeSeries object containing time series data on pupil size","quantity":"+","neurodata_type_inc":"TimeSeries"}],"doc":"Eye-tracking data, representing pupil size.","default_name":"PupilTracking","neurodata_type_inc":"NWBDataInterface","neurodata_type_def":"PupilTracking","attributes":[{"name":"help","doc":"Value is 'Eye-tracking data, representing pupil size'","dtype":"text","value":"Eye-tracking data, representing pupil size"}]},{"groups":[{"doc":"SpatialSeries object containing data measuring direction of gaze","quantity":"*","neurodata_type_inc":"SpatialSeries"}],"doc":"Eye-tracking data, representing direction of gaze.","default_name":"EyeTracking","neurodata_type_inc":"NWBDataInterface","neurodata_type_def":"EyeTracking","attributes":[{"name":"help","doc":"Value is 'Eye-tracking data, representing direction of gaze'","dtype":"text","value":"Eye-tracking data, representing direction of gaze"}]},{"groups":[{"doc":"SpatialSeries object containing direction of gaze travel","quantity":"*","neurodata_type_inc":"SpatialSeries"}],"doc":"With a CompassDirection interface, a module publishes a SpatialSeries object representing a floating point value for theta. The SpatialSeries::reference_frame field should indicate what direction corresponds to 0 and which is the direction of rotation (this should be clockwise). The si_unit for the SpatialSeries should be radians or degrees.","default_name":"CompassDirection","neurodata_type_inc":"NWBDataInterface","neurodata_type_def":"CompassDirection","attributes":[{"name":"help","doc":"Value is 'Direction as measured radially. Spatial series reference frame should indicate which direction corresponds to zero and what is the direction of positive rotation'","dtype":"text","value":"Direction as measured radially. Spatial series reference frame should indicate which direction corresponds to zero and what is the direction of positive rotation"}]},{"groups":[{"doc":"SpatialSeries object containing position data","quantity":"+","neurodata_type_inc":"SpatialSeries"}],"doc":"Position data, whether along the x, x/y or x/y/z axis.","default_name":"Position","neurodata_type_inc":"NWBDataInterface","neurodata_type_def":"Position","attributes":[{"name":"help","doc":"Value is 'Position data, whether along the x, xy or xyz axis'","dtype":"text","value":"Position data, whether along the x, xy or xyz axis"}]}]}S {"groups":[{"datasets":[{"shape":[null],"dims":["num_times"],"dtype":"numeric","name":"data","doc":"Applied power for optogenetic stimulus.","attributes":[{"name":"unit","doc":"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.","required":false,"dtype":"text","default_value":"watt"},{"name":"conversion","doc":"Scalar to multiply each element in data to convert it to the specified unit","required":false,"dtype":"float32","default_value":1.0},{"name":"resolution","doc":"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 -1.0","required":false,"dtype":"float32","default_value":0.0}]}],"links":[{"name":"site","doc":"link to OptogeneticStimulusSite group that describes the site to which this stimulus was applied","target_type":"OptogeneticStimulusSite"}],"doc":"Optogenetic stimulus. The data[] field is in unit of watts.","neurodata_type_inc":"TimeSeries","neurodata_type_def":"OptogeneticSeries","attributes":[{"name":"help","doc":"Value is 'Optogenetic stimulus'","dtype":"text","value":"Optogenetic stimulus"},{"name":"comments","doc":"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.","required":false,"dtype":"text","default_value":"no comments"},{"name":"description","doc":"Description of TimeSeries","required":false,"dtype":"text","default_value":"no description"}]},{"datasets":[{"dtype":"text","name":"description","doc":"Description of site"},{"dtype":"float","name":"excitation_lambda","doc":"Excitation wavelength in nm"},{"dtype":"text","name":"location","doc":"Location of stimulation site"}],"links":[{"name":"device","doc":"Device that generated the stimulus","target_type":"Device"}],"doc":"One of possibly many groups describing an optogenetic stimulation site. COMMENT: Name is arbitrary but should be meaningful. Name is referenced by OptogeneticSeries","quantity":"*","neurodata_type_inc":"NWBContainer","neurodata_type_def":"OptogeneticStimulusSite","attributes":[{"name":"help","doc":"Value is 'Metadata about an optogenetic stimulus site'","dtype":"text","value":"Metadata about an optogenetic stimulus site"}]}]}p3#]3#]3#]SNOD8hvxPO(XuHxw`PRS3#]3#]3#]GCOL5{"groups":[{"datasets":[{"shape":[[null],[null,null],[null,null,null]],"dims":[["num_times"],["num_times","num_channels"],["num_times","num_channels","num_samples"]],"dtype":"numeric","name":"data","doc":"Recorded voltage data.","attributes":[{"name":"unit","doc":"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.","required":false,"dtype":"text","default_value":"volt"},{"name":"conversion","doc":"Scalar to multiply each element in data to convert it to the specified unit","required":false,"dtype":"float32","default_value":1.0},{"name":"resolution","doc":"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 -1.0","required":false,"dtype":"float32","default_value":0.0}]},{"name":"electrodes","doc":"the electrodes that this series was generated from","neurodata_type_inc":"DynamicTableRegion"}],"doc":"Stores acquired voltage data from extracellular recordings. The data field of an ElectricalSeries is an int or float array storing data in Volts. TimeSeries::data array structure: :blue:`[num times] [num channels] (or [num_times] for single electrode).`","neurodata_type_inc":"TimeSeries","neurodata_type_def":"ElectricalSeries","attributes":[{"name":"help","doc":"Value is 'Stores acquired voltage data from extracellular recordings'","dtype":"text","value":"Stores acquired voltage data from extracellular recordings"},{"name":"comments","doc":"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.","required":false,"dtype":"text","default_value":"no comments"},{"name":"description","doc":"Description of TimeSeries","required":false,"dtype":"text","default_value":"no description"}]},{"datasets":[{"shape":[[null,null],[null,null,null]],"dims":[["num_events","num_samples"],["num_events","num_channels","num_samples"]],"dtype":"numeric","name":"data","doc":"Spike waveforms.","attributes":[{"name":"unit","doc":"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.","required":false,"dtype":"text","default_value":"volt"},{"name":"conversion","doc":"Scalar to multiply each element in data to convert it to the specified unit","required":false,"dtype":"float32","default_value":1.0},{"name":"resolution","doc":"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 -1.0","required":false,"dtype":"float32","default_value":0.0}]},{"shape":[null],"dims":["num_times"],"dtype":"float64","name":"timestamps","doc":"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. This is added here so that the timestamps is required for SpikeEventTimes.","attributes":[{"name":"interval","doc":"Value is '1'","dtype":"int32","value":1},{"name":"unit","doc":"Value is 'Seconds'","dtype":"text","value":"Seconds"}]}],"doc":"Stores 'snapshots' of spike events (i.e., threshold crossings) in data. This may also be raw data, as reported by ephys hardware. If so, the TimeSeries::description field should describing how events were detected. All SpikeEventSeries should reside in a module (under EventWaveform interface) even if the spikes were reported and stored by hardware. All events span the same recording channels and store snapshots of equal duration. TimeSeries::data array structure: [num events] [num channels] [num samples] (or [num events] [num samples] for single electrode).","neurodata_type_inc":"ElectricalSeries","neurodata_type_def":"SpikeEventSeries","attributes":[{"name":"help","doc":"Value is 'Snapshots of spike events from data.'","dtype":"text","value":"Snapshots of spike events from data."},{"name":"comments","doc":"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.","required":false,"dtype":"text","default_value":"no comments"},{"name":"description","doc":"Description of TimeSeries","required":false,"dtype":"text","default_value":"no description"}]},{"datasets":[{"dtype":"text","name":"waveform_filtering","doc":"Filtering applied to data before generating mean/sd"},{"shape":[null,null],"dims":["num_clusters","num_samples"],"dtype":"float32","name":"waveform_mean","doc":"The mean waveform for each cluster, using the same indices for each wave as cluster numbers in the associated Clustering module (i.e, cluster 3 is in array slot [3]). Waveforms corresponding to gaps in cluster sequence should be empty (e.g., zero- filled)"},{"shape":[null,null],"dims":["num_clusters","num_samples"],"dtype":"float32","name":"waveform_sd","doc":"Stdev of waveforms for each cluster, using the same indices as in mean"}],"links":[{"name":"clustering_interface","doc":"HDF5 link to Clustering interface that was the source of the clustered data","target_type":"Clustering"}],"doc":"DEPRECATED The mean waveform shape, including standard deviation, of the different clusters. Ideally, the waveform analysis should be performed on data that is only high-pass filtered. This is a separate module because it is expected to require updating. For example, IMEC probes may require different storage requirements to store/display mean waveforms, requiring a new interface or an extension of this one.","default_name":"ClusterWaveforms","neurodata_type_inc":"NWBDataInterface","neurodata_type_def":"ClusterWaveforms","attributes":[{"name":"help","doc":"Value is 'Mean waveform shape of clusters. Waveforms should be high-pass filtered (ie, not the same bandpass filter used waveform analysis and clustering)'","dtype":"text","value":"DEPRECATED Mean waveform shape of clusters. Waveforms should be high-pass filtered (ie, not the same bandpass filter used waveform analysis and clustering)"}]},{"datasets":[{"dtype":"text","name":"description","doc":"Description of clusters or clustering, (e.g. cluster 0 is noise, clusters curated using Klusters, etc)"},{"shape":[null],"dims":["num_events"],"dtype":"int32","name":"num","doc":"Cluster number of each event"},{"shape":[null],"dims":["num_clusters"],"dtype":"float32","name":"peak_over_rms","doc":"Maximum ratio of waveform peak to RMS on any channel in the cluster (provides a basic clustering metric)."},{"shape":[null],"dims":["num_events"],"dtype":"float64","name":"times","doc":"Times of clustered events, in seconds. This may be a link to times field in associated FeatureExtraction module."}],"doc":"DEPRECATED Clustered spike data, whether from automatic clustering tools (e.g., klustakwik) or as a result of manual sorting.","default_name":"Clustering","neurodata_type_inc":"NWBDataInterface","neurodata_type_def":"Clustering","attributes":[{"name":"help","doc":"Value is 'Clustered spike data, whether from automatic clustering tools (eg, klustakwik) or as a result of manual sorting'","dtype":"text","value":"DEPRECATED Clustered spike data, whether from automatic clustering tools (eg, klustakwik) or as a result of manual sorting"}]},{"datasets":[{"shape":[null],"dims":["num_features"],"dtype":"text","name":"description","doc":"Description of features (eg, ''PC1'') for each of the extracted features."},{"shape":[null,null,null],"dims":["num_events","num_channels","num_features"],"dtype":"float32","name":"features","doc":"Multi-dimensional array of features extracted from each event."},{"shape":[null],"dims":["num_events"],"dtype":"float64","name":"times","doc":"Times of events that features correspond to (can be a link)."},{"name":"electrodes","doc":"the electrodes that this series was generated from","neurodata_type_inc":"DynamicTableRegion"}],"doc":"Features, such as PC1 and PC2, that are extracted from signals stored in a SpikeEvent TimeSeries or other source.","default_name":"FeatureExtraction","neurodata_type_inc":"NWBDataInterface","neurodata_type_def":"FeatureExtraction","attributes":[{"name":"help","doc":"Value is 'Container for salient features of detected events'","dtype":"text","value":"Container for salient features of detected events"}]},{"datasets":[{"dtype":"text","name":"detection_method","doc":"Description of how events were detected, such as voltage threshold, or dV/dT threshold, as well as relevant values."},{"shape":[null],"dims":["num_events"],"dtype":"int32","name":"source_idx","doc":"Indices (zero-based) into source ElectricalSeries::data array corresponding to time of event. Module description should define what is meant by time of event (e.g., .25msec before action potential peak, zero-crossing time, etc). The index points to each event from the raw data"},{"shape":[null],"dims":["num_events"],"dtype":"float64","name":"times","doc":"Timestamps of events, in Seconds","attributes":[{"name":"unit","doc":"The string ''Seconds''","required":false,"dtype":"text","default_value":"Seconds"}]}],"links":[{"name":"source_electricalseries","doc":"HDF5 link to ElectricalSeries that this data was calculated from. Metadata about electrodes and their position can be read from that ElectricalSeries so it's not necessary to mandate that information be stored here","target_type":"ElectricalSeries"}],"doc":"Detected spike events from voltage trace(s).","default_name":"EventDetection","neurodata_type_inc":"NWBDataInterface","neurodata_type_def":"EventDetection","attributes":[{"name":"help","doc":"Value is 'Detected spike events from voltage trace(s)'","dtype":"text","value":"Detected spike events from voltage trace(s)"}]},{"groups":[{"doc":"SpikeEventSeries object containing detected spike event waveforms","quantity":"*","neurodata_type_inc":"SpikeEventSeries"}],"doc":"Represents either the waveforms of detected events, as extracted from a raw data trace in /acquisition, or the event waveforms that were stored during experiment acquisition.","default_name":"EventWaveform","neurodata_type_inc":"NWBDataInterface","neurodata_type_def":"EventWaveform","attributes":[{"name":"help","doc":"Value is 'Waveform of detected extracellularly recorded spike events'","dtype":"text","value":"Waveform of detected extracellularly recorded spike events"}]},{"groups":[{"doc":"ElectricalSeries object containing filtered electrophysiology data","quantity":"+","neurodata_type_inc":"ElectricalSeries"}],"doc":"Ephys data from one or more channels that has been subjected to filtering. Examples of filtered data include Theta and Gamma (LFP has its own interface). FilteredEphys modules publish an ElectricalSeries for each filtered channel or set of channels. The name of each ElectricalSeries is arbitrary but should be informative. The source of the filtered data, whether this is from analysis of another time series or as acquired by hardware, should be noted in each's TimeSeries::description field. There is no assumed 1::1 correspondence between filtered ephys signals and electrodes, as a single signal can apply to many nearby electrodes, and one electrode may have different filtered (e.g., theta and/or gamma) signals represented.","default_name":"FilteredEphys","neurodata_type_inc":"NWBDataInterface","neurodata_type_def":"FilteredEphys","attributes":[{"name":"help","doc":"Value is 'Ephys data from one or more channels that is subjected to filtering, such as for gamma or theta oscillations (LFP has its own interface). Filter properties should be noted in the ElectricalSeries'","dtype":"text","value":"Ephys data from one or more channels that is subjected to filtering, such as for gamma or theta oscillations (LFP has its own interface). Filter properties should be noted in the ElectricalSeries"}]},{"groups":[{"doc":"ElectricalSeries object containing LFP data for one or more channels","quantity":"+","neurodata_type_inc":"ElectricalSeries"}],"doc":"LFP data from one or more channels. The electrode map in each published ElectricalSeries will identify which channels are providing LFP data. Filter properties should be noted in the ElectricalSeries description or comments field.","default_name":"LFP","neurodata_type_inc":"NWBDataInterface","neurodata_type_def":"LFP","attributes":[{"name":"help","doc":"Value is 'LFP data from one or more channels. Filter properties should be noted in the ElectricalSeries'","dtype":"text","value":"LFP data from one or more channels. Filter properties should be noted in the ElectricalSeries"}]},{"links":[{"name":"device","doc":"the device that was used to record from this electrode group","target_type":"Device","quantity":"?"}],"doc":"One of possibly many groups, one for each electrode group.","neurodata_type_inc":"NWBContainer","neurodata_type_def":"ElectrodeGroup","attributes":[{"name":"help","doc":"Value is 'Metadata about a physical grouping of channels'","dtype":"text","value":"A physical grouping of channels"},{"name":"description","doc":"description of this electrode group","dtype":"text"},{"name":"location","doc":"description of location of this electrode group","dtype":"text"}]}]}#8{"groups":[{"datasets":[{"shape":[null],"dims":["num_times"],"dtype":"numeric","name":"data","doc":"Recorded voltage or current.","attributes":[{"name":"conversion","doc":"Scalar to multiply each element in data to convert it to the specified unit","required":false,"dtype":"float32","default_value":1.0},{"name":"resolution","doc":"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 -1.0","required":false,"dtype":"float32","default_value":0.0},{"name":"unit","doc":"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.","dtype":"text"}]},{"dtype":"float","name":"gain","doc":"Units: Volt/Amp (v-clamp) or Volt/Volt (c-clamp)","quantity":"?"}],"links":[{"name":"electrode","doc":"link to IntracellularElectrode group that describes th electrode that was used to apply or record this data","target_type":"IntracellularElectrode"}],"doc":"Stores stimulus or response current or voltage. Superclass definition for patch-clamp data (this class should not be instantiated directly).","neurodata_type_inc":"TimeSeries","neurodata_type_def":"PatchClampSeries","attributes":[{"name":"help","doc":"Value is 'Superclass definition for patch-clamp data'","dtype":"text","value":"Superclass definition for patch-clamp data"},{"name":"stimulus_description","doc":"the protocol/stimulus name for this patch-clamp dataset","dtype":"text"},{"name":"sweep_number","doc":"Sweep number, allows to group different PatchClampSeries together.","required":false,"dtype":"uint64"},{"name":"comments","doc":"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.","required":false,"dtype":"text","default_value":"no comments"},{"name":"description","doc":"Description of TimeSeries","required":false,"dtype":"text","default_value":"no description"}]},{"datasets":[{"dtype":"float32","name":"bias_current","doc":"Unit: Amp","quantity":"?"},{"dtype":"float32","name":"bridge_balance","doc":"Unit: Ohm","quantity":"?"},{"dtype":"float32","name":"capacitance_compensation","doc":"Unit: Farad","quantity":"?"}],"doc":"Stores voltage data recorded from intracellular current-clamp recordings. A corresponding CurrentClampStimulusSeries (stored separately as a stimulus) is used to store the current injected.","neurodata_type_inc":"PatchClampSeries","neurodata_type_def":"CurrentClampSeries","attributes":[{"name":"help","doc":"Value is 'Voltage recorded from cell during current-clamp recording'","dtype":"text","value":"Voltage recorded from cell during current-clamp recording"},{"name":"stimulus_description","doc":"the protocol/stimulus name for this patch-clamp dataset","dtype":"text"},{"name":"sweep_number","doc":"Sweep number, allows to group different PatchClampSeries together.","required":false,"dtype":"uint64"},{"name":"comments","doc":"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.","required":false,"dtype":"text","default_value":"no comments"},{"name":"description","doc":"Description of TimeSeries","required":false,"dtype":"text","default_value":"no description"}]},{"doc":"Stores recorded voltage data from intracellular recordings when all current and amplifier settings are off (i.e., CurrentClampSeries fields will be zero). There is no CurrentClampStimulusSeries associated with an IZero series because the amplifier is disconnected and no stimulus can reach the cell.","neurodata_type_inc":"CurrentClampSeries","neurodata_type_def":"IZeroClampSeries","attributes":[{"name":"help","doc":"Value is 'Voltage from intracellular recordings when all current and amplifier settings are off'","dtype":"text","value":"Voltage from intracellular recordings when all current and amplifier settings are off"},{"name":"stimulus_description","doc":"the protocol/stimulus name for this patch-clamp dataset","dtype":"text"},{"name":"sweep_number","doc":"Sweep number, allows to group different PatchClampSeries together.","required":false,"dtype":"uint64"},{"name":"comments","doc":"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.","required":false,"dtype":"text","default_value":"no comments"},{"name":"description","doc":"Description of TimeSeries","required":false,"dtype":"text","default_value":"no description"}]},{"doc":"Aliases to standard PatchClampSeries. Its functionality is to better tag PatchClampSeries for machine (and human) readability of the file.","neurodata_type_inc":"PatchClampSeries","neurodata_type_def":"CurrentClampStimulusSeries","attributes":[{"name":"help","doc":"Value is 'Stimulus current applied during current clamp recording'","dtype":"text","value":"Stimulus current applied during current clamp recording"},{"name":"stimulus_description","doc":"the protocol/stimulus name for this patch-clamp dataset","dtype":"text"},{"name":"sweep_number","doc":"Sweep number, allows to group different PatchClampSeries together.","required":false,"dtype":"uint64"},{"name":"comments","doc":"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.","required":false,"dtype":"text","default_value":"no comments"},{"name":"description","doc":"Description of TimeSeries","required":false,"dtype":"text","default_value":"no description"}]},{"datasets":[{"dtype":"float32","name":"capacitance_fast","doc":"Unit: Farad","quantity":"?","attributes":[{"name":"unit","doc":"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.","required":false,"dtype":"text","default_value":"Farad"}]},{"dtype":"float32","name":"capacitance_slow","doc":"Unit: Farad","quantity":"?","attributes":[{"name":"unit","doc":"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.","required":false,"dtype":"text","default_value":"Farad"}]},{"dtype":"float32","name":"resistance_comp_bandwidth","doc":"Unit: Hz","quantity":"?","attributes":[{"name":"unit","doc":"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.","required":false,"dtype":"text","default_value":"Hz"}]},{"dtype":"float32","name":"resistance_comp_correction","doc":"Unit: %","quantity":"?","attributes":[{"name":"unit","doc":"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.","required":false,"dtype":"text","default_value":"percent"}]},{"dtype":"float32","name":"resistance_comp_prediction","doc":"Unit: %","quantity":"?","attributes":[{"name":"unit","doc":"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.","required":false,"dtype":"text","default_value":"percent"}]},{"dtype":"float32","name":"whole_cell_capacitance_comp","doc":"Unit: Farad","quantity":"?","attributes":[{"name":"unit","doc":"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.","required":false,"dtype":"text","default_value":"Farad"}]},{"dtype":"float32","name":"whole_cell_series_resistance_comp","doc":"Unit: Ohm","quantity":"?","attributes":[{"name":"unit","doc":"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.","required":false,"dtype":"text","default_value":"Ohm"}]}],"doc":"Stores current data recorded from intracellular voltage-clamp recordings. A corresponding VoltageClampStimulusSeries (stored separately as a stimulus) is used to store the voltage injected.","neurodata_type_inc":"PatchClampSeries","neurodata_type_def":"VoltageClampSeries","attributes":[{"name":"help","doc":"Value is 'Current recorded from cell during voltage-clamp recording'","dtype":"text","value":"Current recorded from cell during voltage-clamp recording"},{"name":"stimulus_description","doc":"the protocol/stimulus name for this patch-clamp dataset","dtype":"text"},{"name":"sweep_number","doc":"Sweep number, allows to group different PatchClampSeries together.","required":false,"dtype":"uint64"},{"name":"comments","doc":"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.","required":false,"dtype":"text","default_value":"no comments"},{"name":"description","doc":"Description of TimeSeries","required":false,"dtype":"text","default_value":"no description"}]},{"doc":"Aliases to standard PatchClampSeries. Its functionality is to better tag PatchClampSeries for machine (and human) readability of the file.","neurodata_type_inc":"PatchClampSeries","neurodata_type_def":"VoltageClampStimulusSeries","attributes":[{"name":"help","doc":"Value is 'Stimulus voltage applied during voltage clamp recording'","dtype":"text","value":"Stimulus voltage applied during voltage clamp recording"},{"name":"stimulus_description","doc":"the protocol/stimulus name for this patch-clamp dataset","dtype":"text"},{"name":"sweep_number","doc":"Sweep number, allows to group different PatchClampSeries together.","required":false,"dtype":"uint64"},{"name":"comments","doc":"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.","required":false,"dtype":"text","default_value":"no comments"},{"name":"description","doc":"Description of TimeSeries","required":false,"dtype":"text","default_value":"no description"}]},{"datasets":[{"dtype":"text","name":"description","doc":"Recording description, description of electrode (e.g., whole-cell, sharp, etc)COMMENT: Free-form text (can be from Methods)"},{"dtype":"text","name":"filtering","doc":"Electrode specific filtering.","quantity":"?"},{"dtype":"text","name":"initial_access_resistance","doc":"Initial access resistance","quantity":"?"},{"dtype":"text","name":"location","doc":"Area, layer, comments on estimation, stereotaxis coordinates (if in vivo, etc)","quantity":"?"},{"dtype":"text","name":"resistance","doc":"Electrode resistance COMMENT: unit: Ohm","quantity":"?"},{"dtype":"text","name":"seal","doc":"Information about seal used for recording","quantity":"?"},{"dtype":"text","name":"slice","doc":"Information about slice used for recording","quantity":"?"}],"links":[{"name":"device","doc":"the device that was used to record from this electrode","target_type":"Device"}],"doc":"One of possibly many. COMMENT: Name should be informative.","neurodata_type_inc":"NWBContainer","neurodata_type_def":"IntracellularElectrode","attributes":[{"name":"help","doc":"Value is 'Metadata about an intracellular electrode'","dtype":"text","value":"Metadata about an intracellular electrode"}]},{"datasets":[{"dtype":"uint64","name":"sweep_number","doc":"The sweep number of the PatchClampSeries in that row.","neurodata_type_inc":"VectorData","attributes":[{"name":"description","doc":"value is 'The sweep number of the PatchClampSeries in that row'","dtype":"text","value":"The sweep number of the PatchClampSeries in that row"}]},{"dtype":{"target_type":"PatchClampSeries","reftype":"object"},"name":"series","doc":"The PatchClampSeries with the sweep number in that row","neurodata_type_inc":"VectorData","attributes":[{"name":"help","doc":"Value is 'The PatchClampSeries with the sweep number in that row'","dtype":"text","value":"The PatchClampSeries with the sweep number in that row"}]},{"name":"series_index","doc":"Index for series","neurodata_type_inc":"VectorIndex"}],"doc":"The table which groups different PatchClampSeries together.","neurodata_type_inc":"DynamicTable","neurodata_type_def":"SweepTable","attributes":[{"name":"help","doc":"Value is 'The table which groups different PatchClampSeries together'","dtype":"text","value":"The table which groups different PatchClampSeries together"},{"name":"colnames","doc":"The names of the columns in this table. This should be used to specifying an order to the columns","dtype":"ascii","shape":[null],"dims":["num_columns"]},{"name":"description","doc":"Description of what is in this dynamic table","dtype":"text"}]}]}]1{"groups":[{"datasets":[{"shape":[[2],[3]],"dims":["width|height","width|height|depth"],"dtype":"float32","name":"field_of_view","doc":"Width, height and depth of image, or imaged area (meters).","quantity":"?"}],"links":[{"name":"imaging_plane","doc":"link to ImagingPlane group from which this TimeSeries data was generated","target_type":"ImagingPlane"}],"doc":"A special case of optical imaging.","neurodata_type_inc":"ImageSeries","neurodata_type_def":"TwoPhotonSeries","attributes":[{"name":"help","doc":"Value is 'Image stack recorded from 2-photon microscope'","dtype":"text","value":"Image stack recorded from 2-photon microscope"},{"name":"pmt_gain","doc":"Photomultiplier gain","required":false,"dtype":"float32"},{"name":"scan_line_rate","doc":"Lines imaged per second. This is also stored in /general/optophysiology but is kept here as it is useful information for analysis, and so good to be stored w/ the actual data.","required":false,"dtype":"float32"},{"name":"comments","doc":"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.","required":false,"dtype":"text","default_value":"no comments"},{"name":"description","doc":"Description of TimeSeries","required":false,"dtype":"text","default_value":"no description"}]},{"datasets":[{"shape":[[null],[null,null]],"dims":[["num_times"],["num_times","num_ROIs"]],"dtype":"numeric","name":"data","doc":"Signals from ROIs","attributes":[{"name":"conversion","doc":"Scalar to multiply each element in data to convert it to the specified unit","required":false,"dtype":"float32","default_value":1.0},{"name":"resolution","doc":"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 -1.0","required":false,"dtype":"float32","default_value":0.0},{"name":"unit","doc":"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.","dtype":"text"}]},{"name":"rois","doc":"a dataset referencing into an ROITable containing information on the ROIs stored in this timeseries","neurodata_type_inc":"DynamicTableRegion"}],"doc":"ROI responses over an imaging plane. Each row in data[] should correspond to the signal from one ROI.","neurodata_type_inc":"TimeSeries","neurodata_type_def":"RoiResponseSeries","attributes":[{"name":"help","doc":"Value is 'ROI responses over an imaging plane. Each element on the second dimension of data[] should correspond to the signal from one ROI'","dtype":"text","value":"ROI responses over an imaging plane. Each element on the second dimension of data[] should correspond to the signal from one ROI"},{"name":"comments","doc":"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.","required":false,"dtype":"text","default_value":"no comments"},{"name":"description","doc":"Description of TimeSeries","required":false,"dtype":"text","default_value":"no description"}]},{"groups":[{"doc":"RoiResponseSeries object containing dF/F for a ROI","quantity":"+","neurodata_type_inc":"RoiResponseSeries"}],"doc":"dF/F information about a region of interest (ROI). Storage hierarchy of dF/F should be the same as for segmentation (ie, same names for ROIs and for image planes).","default_name":"DfOverF","neurodata_type_inc":"NWBDataInterface","neurodata_type_def":"DfOverF","attributes":[{"name":"help","doc":"Value is 'Df/f over time of one or more ROIs. TimeSeries names should correspond to imaging plane names'","dtype":"text","value":"Df/f over time of one or more ROIs. TimeSeries names should correspond to imaging plane names"}]},{"groups":[{"doc":"RoiResponseSeries object containing fluorescence data for a ROI","quantity":"+","neurodata_type_inc":"RoiResponseSeries"}],"doc":"Fluorescence information about a region of interest (ROI). Storage hierarchy of fluorescence should be the same as for segmentation (ie, same names for ROIs and for image planes).","default_name":"Fluorescence","neurodata_type_inc":"NWBDataInterface","neurodata_type_def":"Fluorescence","attributes":[{"name":"help","doc":"Value is 'Fluorescence over time of one or more ROIs. TimeSeries names should correspond to imaging plane names'","dtype":"text","value":"Fluorescence over time of one or more ROIs. TimeSeries names should correspond to imaging plane names"}]},{"groups":[{"groups":[{"groups":[{"doc":"One or more image stacks that the masks apply to (can be one-element stack)","quantity":"*","neurodata_type_inc":"ImageSeries"}],"name":"reference_images","doc":"Stores image stacks segmentation mask apply to."}],"datasets":[{"shape":[[null,null,null],[null,null,null,null]],"dims":[["num_roi","num_x","num_y"],["num_roi","num_x","num_y","num_z"]],"name":"image_mask","doc":"ROI masks for each ROI. Each image mask is the size of the original imaging plane (or volume) and members of the ROI are finite non-zero","quantity":"?","neurodata_type_inc":"VectorData"},{"name":"pixel_mask_index","doc":"index into pixel_mask","quantity":"?","neurodata_type_inc":"VectorIndex"},{"dtype":[{"doc":"the pixel x-coordinate","name":"x","dtype":"uint"},{"doc":"the pixel y-coordinate","name":"y","dtype":"uint"},{"doc":"the weight of the pixel","name":"weight","dtype":"float"}],"name":"pixel_mask","doc":"Pixel masks for each ROI: a list of indices and weights for the ROI. Pixel masks are concatenated and parsing of this dataset is maintained by the PlaneSegmentation","quantity":"?","neurodata_type_inc":"VectorData"},{"name":"voxel_mask_index","doc":"index into voxel_mask","quantity":"?","neurodata_type_inc":"VectorIndex"},{"dtype":[{"doc":"the voxel x-coordinate","name":"x","dtype":"uint"},{"doc":"the voxel y-coordinate","name":"y","dtype":"uint"},{"doc":"the voxel y-coordinate","name":"z","dtype":"uint"},{"doc":"the weight of the voxel","name":"weight","dtype":"float"}],"name":"voxel_mask","doc":"Voxel masks for each ROI: a list of indices and weights for the ROI. Voxel masks are concatenated and parsing of this dataset is maintained by the PlaneSegmentation","quantity":"?","neurodata_type_inc":"VectorData"},{"shape":[null],"dims":["num_rows"],"dtype":"int","name":"id","doc":"The unique identifier for the rows in this dynamic table","neurodata_type_inc":"ElementIdentifiers"},{"doc":"The vector columns in this dynamic table","quantity":"*","neurodata_type_inc":"VectorData"},{"doc":"The indices for the vector columns in this dynamic table","quantity":"*","neurodata_type_inc":"VectorIndex"}],"links":[{"name":"imaging_plane","doc":"link to ImagingPlane group from which this TimeSeries data was generated","target_type":"ImagingPlane"}],"doc":"results for image segmentation of a specific imaging plane","quantity":"+","neurodata_type_inc":"DynamicTable","neurodata_type_def":"PlaneSegmentation","attributes":[{"name":"help","doc":"Value is 'Results from segmentation of an imaging plane'","dtype":"text","value":"Results from segmentation of an imaging plane"},{"name":"colnames","doc":"The names of the columns in this table. This should be used to specifying an order to the columns","dtype":"ascii","shape":[null],"dims":["num_columns"]},{"name":"description","doc":"Description of what is in this dynamic table","dtype":"text"}]}],"doc":"Stores pixels in an image that represent different regions of interest (ROIs) or masks. All segmentation for a given imaging plane is stored together, with storage for multiple imaging planes (masks) supported. Each ROI is stored in its own subgroup, with the ROI group containing both a 2D mask and a list of pixels that make up this mask. Segments can also be used for masking neuropil. If segmentation is allowed to change with time, a new imaging plane (or module) is required and ROI names should remain consistent between them.","default_name":"ImageSegmentation","neurodata_type_inc":"NWBDataInterface","neurodata_type_def":"ImageSegmentation","attributes":[{"name":"help","doc":"Value is 'Stores groups of pixels that define regions of interest from one or more imaging planes'","dtype":"text","value":"Stores groups of pixels that define regions of interest from one or more imaging planes"}]},{"groups":[{"datasets":[{"dtype":"text","name":"description","doc":"Any notes or comments about the channel"},{"dtype":"float","name":"emission_lambda","doc":"Emission wavelength for channel in nm"}],"doc":"One of possibly many groups storing channel-specific data COMMENT: Name is arbitrary but should be meaningful","neurodata_type_inc":"NWBContainer","neurodata_type_def":"OpticalChannel","attributes":[{"name":"help","doc":"Value is 'Metadata about an optical channel used to record from an imaging plane'","dtype":"text","value":"Metadata about an optical channel used to record from an imaging plane"}]}],"datasets":[{"dtype":"text","name":"description","doc":"Description of image_plane_X","quantity":"?"},{"dtype":"float","name":"excitation_lambda","doc":"Excitation wavelength in nm"},{"dtype":"float","name":"imaging_rate","doc":"Rate images are acquired, in Hz."},{"dtype":"text","name":"indicator","doc":"Calcium indicator"},{"dtype":"text","name":"location","doc":"Location of image plane"},{"shape":[[null,null,3],[null,null,null,3]],"dims":[["height","width","x|y|z"],["height","width","depth","x|y|z"]],"dtype":"float32","name":"manifold","doc":"Physical position of each pixel. COMMENT: 'xyz' represents the position of the pixel relative to the defined coordinate space","quantity":"?","attributes":[{"name":"conversion","doc":"Multiplier to get from stored values to specified unit (e.g., 1e-3 for millimeters)","required":false,"dtype":"float","default_value":1.0},{"name":"unit","doc":"Base unit that coordinates are stored in (e.g., Meters)","required":false,"dtype":"text","default_value":"Meter"}]},{"dtype":"text","name":"reference_frame","doc":"Describes position and reference frame of manifold based on position of first element in manifold. For example, text description of anatomical location or vectors needed to rotate to common anatomical axis (eg, AP/DV/ML). COMMENT: This field is necessary to interpret manifold. If manifold is not present then this field is not required","quantity":"?"}],"links":[{"name":"device","doc":"the device that was used to record from this electrode","target_type":"Device"}],"doc":"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","quantity":"*","neurodata_type_inc":"NWBContainer","neurodata_type_def":"ImagingPlane","attributes":[{"name":"help","doc":"Value is 'Metadata about an imaging plane'","dtype":"text","value":"Metadata about an imaging plane"}]},{"groups":[{"groups":[{"name":"corrected","doc":"Image stack with frames shifted to the common coordinates.","neurodata_type_inc":"ImageSeries"},{"name":"xy_translation","doc":"Stores the x,y delta necessary to align each frame to the common coordinates, for example, to align each frame to a reference image.","neurodata_type_inc":"TimeSeries"}],"links":[{"name":"original","doc":"HDF5 Link to image series that is being registered.","target_type":"ImageSeries"}],"doc":"One of possibly many. Name should be informative.","quantity":"+","neurodata_type_inc":"NWBDataInterface","neurodata_type_def":"CorrectedImageStack","attributes":[{"name":"help","doc":"Value is 'Reuslts from motion correction of an image stack'","dtype":"text","value":"Reuslts from motion correction of an image stack"}]}],"doc":"An image stack where all frames are shifted (registered) to a common coordinate system, to account for movement and drift between frames. Note: each frame at each point in time is assumed to be 2-D (has only x & y dimensions).","default_name":"MotionCorrection","neurodata_type_inc":"NWBDataInterface","neurodata_type_def":"MotionCorrection","attributes":[{"name":"help","doc":"Value is 'Image stacks whose frames have been shifted (registered) to account for motion'","dtype":"text","value":"Image stacks whose frames have been shifted (registered) to account for motion"}]}]}{"groups":[{"datasets":[{"shape":[null,null],"dims":["num_rows","num_cols"],"dtype":"float32","name":"axis_1_phase_map","doc":"Phase response to stimulus on the first measured axis","attributes":[{"name":"dimension","doc":"Number of rows and columns in the image. NOTE: row, column representation is equivalent to height,width.","dtype":"int32","shape":[null],"dims":["row_col"]},{"name":"field_of_view","doc":"Size of viewing area, in meters","dtype":"float","shape":[null],"dims":["row|column"]},{"name":"unit","doc":"Unit that axis data is stored in (e.g., degrees)","dtype":"text"}]},{"shape":[null,null],"dims":["num_rows","num_cols"],"dtype":"float32","name":"axis_1_power_map","doc":"Power response on the first measured axis. Response is scaled so 0.0 is no power in the response and 1.0 is maximum relative power.","quantity":"?","attributes":[{"name":"dimension","doc":"Number of rows and columns in the image. NOTE: row, column representation is equivalent to height,width.","dtype":"int32","shape":[null],"dims":["row_col"]},{"name":"field_of_view","doc":"Size of viewing area, in meters","dtype":"float","shape":[null],"dims":["row_col"]},{"name":"unit","doc":"Unit that axis data is stored in (e.g., degrees)","dtype":"text"}]},{"shape":[null,null],"dims":["num_rows","num_cols"],"dtype":"float32","name":"axis_2_phase_map","doc":"Phase response to stimulus on the second measured axis","attributes":[{"name":"dimension","doc":"Number of rows and columns in the image. NOTE: row, column representation is equivalent to height,width.","dtype":"int32","shape":[null],"dims":["row_col"]},{"name":"field_of_view","doc":"Size of viewing area, in meters","dtype":"float","shape":[null],"dims":["row_col"]},{"name":"unit","doc":"Unit that axis data is stored in (e.g., degrees)","dtype":"text"}]},{"shape":[null,null],"dims":["num_rows","num_cols"],"dtype":"float32","name":"axis_2_power_map","doc":"Power response on the second measured axis. Response is scaled so 0.0 is no power in the response and 1.0 is maximum relative power.","quantity":"?","attributes":[{"name":"dimension","doc":"Number of rows and columns in the image. NOTE: row, column representation is equivalent to height,width.","dtype":"int32","shape":[null],"dims":["row_col"]},{"name":"field_of_view","doc":"Size of viewing area, in meters","dtype":"float","shape":[null],"dims":["row_col"]},{"name":"unit","doc":"Unit that axis data is stored in (e.g., degrees)","dtype":"text"}]},{"shape":[null],"dims":["2"],"dtype":"text","name":"axis_descriptions","doc":"Two-element array describing the contents of the two response axis fields. Description should be something like ['altitude', 'azimuth'] or '['radius', 'theta']"},{"shape":[null,null],"dims":["num_rows","num_cols"],"dtype":"uint16","name":"focal_depth_image","doc":"Gray-scale image taken with same settings/parameters (e.g., focal depth, wavelength) as data collection. Array format: [rows][columns]","attributes":[{"name":"bits_per_pixel","doc":"Number of bits used to represent each value. This is necessary to determine maximum (white) pixel value","dtype":"int32"},{"name":"dimension","doc":"Number of rows and columns in the image. NOTE: row, column representation is equivalent to height,width.","dtype":"int32","shape":[null],"dims":["row_col"]},{"name":"field_of_view","doc":"Size of viewing area, in meters","dtype":"float","shape":[null],"dims":["row_col"]},{"name":"focal_depth","doc":"Focal depth offset, in meters","dtype":"float"},{"name":"format","doc":"Format of image. Right now only 'raw' supported","dtype":"text"}]},{"shape":[null,null],"dims":["num_rows","num_cols"],"dtype":"float32","name":"sign_map","doc":"Sine of the angle between the direction of the gradient in axis_1 and axis_2","attributes":[{"name":"dimension","doc":"Number of rows and columns in the image. NOTE: row, column representation is equivalent to height,width.","dtype":"int32","shape":[null],"dims":["row_col"]},{"name":"field_of_view","doc":"Size of viewing area, in meters.","dtype":"float","shape":[null],"dims":["row_col"]}]},{"shape":[null,null],"dims":["num_rows","num_cols"],"dtype":"uint16","name":"vasculature_image","doc":"Gray-scale anatomical image of cortical surface. Array structure: [rows][columns]","attributes":[{"name":"bits_per_pixel","doc":"Number of bits used to represent each value. This is necessary to determine maximum (white) pixel value","dtype":"int32"},{"name":"dimension","doc":"Number of rows and columns in the image. NOTE: row, column representation is equivalent to height,width.","dtype":"int32","shape":[null],"dims":["row_col"]},{"name":"field_of_view","doc":"Size of viewing area, in meters","dtype":"float","shape":[null],"dims":["row_col"]},{"name":"format","doc":"Format of image. Right now only 'raw' supported","dtype":"text"}]}],"doc":"Intrinsic signal optical imaging or widefield imaging for measuring retinotopy. Stores orthogonal maps (e.g., altitude/azimuth; radius/theta) of responses to specific stimuli and a combined polarity map from which to identify visual areas.
Note: for data consistency, all images and arrays are stored in the format [row][column] and [row, col], which equates to [y][x]. Field of view and dimension arrays may appear backward (i.e., y before x).","default_name":"ImagingRetinotopy","neurodata_type_inc":"NWBDataInterface","neurodata_type_def":"ImagingRetinotopy","attributes":[{"name":"help","doc":"Value is 'Intrinsic signal optical imaging or Widefield imaging for measuring retinotopy'","dtype":"text","value":"Intrinsic signal optical imaging or Widefield imaging for measuring retinotopy"}]}]}U{"namespaces":[{"doc":"NWB namespace","schema":[{"source":"nwb.base"},{"source":"nwb.epoch"},{"source":"nwb.image"},{"source":"nwb.file"},{"source":"nwb.misc"},{"source":"nwb.behavior"},{"source":"nwb.ecephys"},{"source":"nwb.icephys"},{"source":"nwb.ogen"},{"source":"nwb.ophys"},{"source":"nwb.retinotopy"}],"name":"core","full_name":"NWB core","version":"2.0.2","author":["Andrew Tritt","Oliver Ruebel","Ryan Ly","Ben Dichter","Keith Godfrey","Jeff Teeters"],"contact":["ajtritt@lbl.gov","oruebel@lbl.gov","rly@lbl.gov","bdichter@lbl.gov","keithg@alleninstitute.org","jteeters@berkeley.edu"]}]}x$pynwb-1.2.1/tests/back_compat/__init__.py0000644000655200065520000000000013612200244021736 0ustar circlecicircleci00000000000000pynwb-1.2.1/tests/back_compat/1.1.2_nwbfile.nwb0000644000655200065520000044150013612200244022520 0ustar circlecicircleci00000000000000HDF  @C` TREEHP/HEAP`- 0 .speclocpHhTREEHEAPXPSNOD Hh(Pp PH0XxPp TREEHEAPX P 0 TREEHEAPXP P TREE(HEAPX(presentationtemplates0TREEHEAPXPSNODhpTREEHEAPXPXxTREEHEAPXP H nwb_version1:<C'^x GCOL 2020-01-21T17:58:27.445200-08:00ADDMEADDME 2020-01-21T17:58:27.444165-08:00 2020-01-21T17:58:27.444165-08:002.1.0coreNWBFile $a0e3c42c-ec68-4e58-8505-ab7baa4c0ca8 {"groups":[{"datasets":[{"shape":[null],"dtype":"int","name":"indices","doc":"column indices"},{"shape":[null],"dtype":"int","name":"indptr","doc":"index pointer"},{"shape":[null],"name":"data","doc":"values in the matrix"}],"doc":"a compressed sparse row matrix","data_type_def":"CSRMatrix","attributes":[{"name":"shape","doc":"the shape of this sparse matrix","dtype":"int","shape":[2]}]}]} H{"namespaces":[{"doc":"Common data structures provided by HDMF","schema":[{"source":"table"},{"source":"sparse"}],"name":"hdmf-common","full_name":"HDMF Common","version":"1.0.0","author":["Andrew Tritt","Oliver Ruebel","Ryan Ly","Ben Dichter"],"contact":["ajtritt@lbl.gov","oruebel@lbl.gov","rly@lbl.gov","bdichter@lbl.gov"]}]} G{"groups":[{"datasets":[{"dtype":"float","name":"start_time","doc":"Start time of epoch, in seconds.","neurodata_type_inc":"VectorData"},{"dtype":"float","name":"stop_time","doc":"Stop time of epoch, in seconds.","neurodata_type_inc":"VectorData"},{"dtype":"text","name":"tags","doc":"User-defined tags that identify or categorize events.","quantity":"?","neurodata_type_inc":"VectorData"},{"name":"tags_index","doc":"Index for tags.","quantity":"?","neurodata_type_inc":"VectorIndex"},{"dtype":[{"doc":"Start index into the TimeSeries 'data' and 'timestamp' datasets of the referenced TimeSeries. The first dimension of those arrays is always time.","name":"idx_start","dtype":"int32"},{"doc":"Number of data samples available in this time series, during this epoch.","name":"count","dtype":"int32"},{"doc":"the TimeSeries that this index applies to.","name":"timeseries","dtype":{"target_type":"TimeSeries","reftype":"object"}}],"name":"timeseries","doc":"An index into a TimeSeries object.","quantity":"?","neurodata_type_inc":"VectorData"},{"name":"timeseries_index","doc":"Index for timeseries.","quantity":"?","neurodata_type_inc":"VectorIndex"}],"doc":"A container for aggregating epoch data and the TimeSeries that each epoch applies to.","neurodata_type_inc":"DynamicTable","neurodata_type_def":"TimeIntervals","attributes":[{"name":"colnames","doc":"The names of the columns in this table. This should be used to specify an order to the columns.","dtype":"ascii","shape":[null],"dims":["num_columns"]},{"name":"description","doc":"Description of what is in this dynamic table.","dtype":"text"}]}]}h2C'^2C'^2C'^acquisitionanalysisprocessingstimulusgeneralfile_create_dateidentifiersession_descriptionsession_start_timetimestamps_reference_timespecificationsSNODh*(  0 x+,p:<8  02C'^ H namespace Hneurodata_type H object_id$ P  xF H hbG y("<,1w4PTBPT~ ,PTPTqPTTREE@HEAPX =hdmf-commoncore8=?TREE DHEAPX?1.0.0HSNODZZ\X==?ACTREE(WHEAPX(Ctablesparsenamespace0SNOD`AAC3C'^GCOL{"datasets":[{"doc":"An abstract data type for a dataset.","data_type_def":"Data"},{"doc":"Pointers that index data values.","data_type_inc":"Data","data_type_def":"Index","attributes":[{"name":"target","doc":"Target dataset that this index applies to.","dtype":{"target_type":"Data","reftype":"object"}}]},{"doc":"A 1-dimensional dataset. This can be indexed using a VectorIndex to encode a 2-dimensional ragged array in 1 dimension. The first vector is at VectorData[0:VectorIndex(0)+1]. The second vector is at VectorData[VectorIndex(0)+1:VectorIndex(1)+1]. And so on.","data_type_inc":"Data","data_type_def":"VectorData","attributes":[{"name":"description","doc":"Description of what these vectors represent.","dtype":"text"}]},{"doc":"An array of indices into the first dimension of the target VectorData. Can be used with VectorData to encode a 2-dimensional ragged array in 1 dimension.","data_type_inc":"Index","data_type_def":"VectorIndex","attributes":[{"name":"target","doc":"Reference to the target dataset that this index applies to.","dtype":{"target_type":"VectorData","reftype":"object"}}]},{"shape":[null],"dims":["num_elements"],"dtype":"int","doc":"A list of unique identifiers for values within a dataset, e.g. rows of a DynamicTable.","default_name":"element_id","data_type_inc":"Data","data_type_def":"ElementIdentifiers"},{"dtype":"int","doc":"A region/index into a DynamicTable.","data_type_inc":"VectorData","data_type_def":"DynamicTableRegion","attributes":[{"name":"table","doc":"Reference to the DynamicTable object that this region applies to.","dtype":{"target_type":"DynamicTable","reftype":"object"}},{"name":"description","doc":"Description of what this table region points to.","dtype":"text"}]}],"groups":[{"doc":"An abstract data type for a generic container storing collections of data and metadata. Base type for all data and metadata containers.","data_type_def":"Container"},{"datasets":[{"shape":[null],"dims":["num_rows"],"dtype":"int","name":"id","doc":"Array of unique identifiers for the rows of this dynamic table.","data_type_inc":"ElementIdentifiers"},{"doc":"Vector columns of this dynamic table.","quantity":"*","data_type_inc":"VectorData"},{"doc":"Indices for the vector columns of this dynamic table.","quantity":"*","data_type_inc":"VectorIndex"}],"doc":"A group containing multiple datasets that are aligned on the first dimension (Currently, this requirement if left up to APIs to check and enforce). Apart from a column that contains unique identifiers for each row there are no other required datasets. Users are free to add any number of VectorData objects here. Table functionality is already supported through compound types, which is analogous to storing an array-of-structs. DynamicTable can be thought of as a struct-of-arrays. This provides an alternative structure to choose from when optimizing storage for anticipated access patterns. Additionally, this type provides a way of creating a table without having to define a compound type up front. Although this convenience may be attractive, users should think carefully about how data will be accessed. DynamicTable is more appropriate for column-centric access, whereas a dataset with a compound type would be more appropriate for row-centric access. Finally, data size should also be taken into account. For small tables, performance loss may be an acceptable trade-off for the flexibility of a DynamicTable. For example, DynamicTable was originally developed for storing trial data and spike unit metadata. Both of these use cases are expected to produce relatively small tables, so the spatial locality of multiple datasets present in a DynamicTable is not expected to have a significant performance impact. Additionally, requirements of trial and unit metadata tables are sufficiently diverse that performance implications can be overlooked in favor of usability.","data_type_inc":"Container","data_type_def":"DynamicTable","attributes":[{"name":"colnames","doc":"The names of the columns in this table. This should be used to specify an order to the columns.","dtype":"ascii","shape":[null],"dims":["num_columns"]},{"name":"description","doc":"Description of what is in this dynamic table.","dtype":"text"}]}]}SNODYpXhE3C'^ 3C'^Z\TREE`HEAPX\2.1.0Hx]_TREEzOHEAP`8SNODP]x]_03D'^GCOL8{"datasets":[{"doc":"An abstract data type for a dataset.","neurodata_type_inc":"Data","neurodata_type_def":"NWBData"},{"shape":[[null,null],[null,null,3],[null,null,4]],"dims":[["num_x","num_y"],["num_x","num_y","(r, g, b)"],["num_x","num_y","(r, g, b, a)"]],"doc":"An abstract data type for an image. Shape can be 2-D (x, y), or 3-D where the third dimension can have three or four elements, e.g. (x, y, (r, g, b)) or (x, y, (r, g, b, a)).","neurodata_type_inc":"NWBData","neurodata_type_def":"Image","attributes":[{"name":"resolution","doc":"Pixel resolution of the image, in pixels per centimeter.","required":false,"dtype":"float"},{"name":"description","doc":"Description of the image.","required":false,"dtype":"text"}]}],"groups":[{"doc":"An abstract data type for a generic container storing collections of data and metadata. Base type for all data and metadata containers.","neurodata_type_inc":"Container","neurodata_type_def":"NWBContainer"},{"doc":"An abstract data type for a generic container storing collections of data, as opposed to metadata.","neurodata_type_inc":"NWBContainer","neurodata_type_def":"NWBDataInterface"},{"groups":[{"name":"sync","doc":"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. 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.","quantity":"?"}],"datasets":[{"shape":[[null],[null,null],[null,null,null],[null,null,null,null]],"dims":[["num_times"],["num_times","num_DIM2"],["num_times","num_DIM2","num_DIM3"],["num_times","num_DIM2","num_DIM3","num_DIM4"]],"name":"data","doc":"Data values. Data can be in 1-D, 2-D, 3-D, or 4-D. The first dimension should always represent time. This can also be used to store binary data (e.g., image frames). This can also be a link to data stored in an external file.","attributes":[{"name":"conversion","doc":"Scalar to multiply each element in data to convert it to the specified 'unit'. If the data are stored in acquisition system units or other units that require a conversion to be interpretable, multiply the data by 'conversion' to convert the data to the specified 'unit'. e.g. if the data acquisition system stores values in this object as signed 16-bit integers (int16 range -32,768 to 32,767) that correspond to a 5V range (-2.5V to 2.5V), and the data acquisition system gain is 8000X, then the 'conversion' multiplier to get from raw data acquisition values to recorded volts is 2.5/32768/8000 = 9.5367e-9.","required":false,"dtype":"float32","default_value":1.0},{"name":"resolution","doc":"Smallest meaningful difference between values in data, stored in the specified by unit, 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 -1.0.","required":false,"dtype":"float32","default_value":-1.0},{"name":"unit","doc":"Base unit of measurement for working with the data. Actual stored values are not necessarily stored in these units. To access the data in these units, multiply 'data' by 'conversion'.","dtype":"text"}]},{"dtype":"float64","name":"starting_time","doc":"Timestamp of the first sample in seconds. When timestamps are uniformly spaced, the timestamp of the first sample can be specified and all subsequent ones calculated from the sampling rate attribute.","quantity":"?","attributes":[{"name":"rate","doc":"Sampling rate, in Hz.","dtype":"float32"},{"name":"unit","doc":"Unit of measurement for time, which is fixed to 'seconds'.","dtype":"text","value":"seconds"}]},{"shape":[null],"dims":["num_times"],"dtype":"float64","name":"timestamps","doc":"Timestamps for samples stored in data, in seconds, relative to the common experiment master-clock stored in NWBFile.timestamps_reference_time.","quantity":"?","attributes":[{"name":"interval","doc":"Value is '1'","dtype":"int32","value":1},{"name":"unit","doc":"Unit of measurement for timestamps, which is fixed to 'seconds'.","dtype":"text","value":"seconds"}]},{"shape":[null],"dims":["num_times"],"dtype":"uint8","name":"control","doc":"Numerical labels that apply to each time point in data for the purpose of querying and slicing data by these values. If present, the length of this array should be the same size as the first dimension of data.","quantity":"?"},{"shape":[null],"dims":["num_control_values"],"dtype":"text","name":"control_description","doc":"Description of each control value. Must be present if control is present. If present, control_description[0] should describe time points where control == 0.","quantity":"?"}],"doc":"General purpose time series.","neurodata_type_inc":"NWBDataInterface","neurodata_type_def":"TimeSeries","attributes":[{"name":"description","doc":"Description of the time series.","required":false,"dtype":"text","default_value":"no description"},{"name":"comments","doc":"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.","required":false,"dtype":"text","default_value":"no comments"}]},{"groups":[{"doc":"Data objects stored in this collection.","quantity":"*","neurodata_type_inc":"NWBDataInterface"},{"doc":"Tables stored in this collection.","quantity":"*","neurodata_type_inc":"DynamicTable"}],"doc":"A collection of processed data.","neurodata_type_inc":"NWBContainer","neurodata_type_def":"ProcessingModule","attributes":[{"name":"description","doc":"Description of this collection of processed data.","dtype":"text"}]},{"datasets":[{"doc":"Images stored in this collection.","quantity":"+","neurodata_type_inc":"Image"}],"doc":"A collection of images.","default_name":"Images","neurodata_type_inc":"NWBDataInterface","neurodata_type_def":"Images","attributes":[{"name":"description","doc":"Description of this collection of images.","dtype":"text"}]}]}SNODRXaX(hPL{@3D'^P3D'^`3D'^p3D'^3D'^nwb.basenwb.epochnwb.imagenwb.filenwb.miscnwb.behaviornwb.ecephysnwb.icephysnwb.ogennwb.ophysnwb.retinotopynamespaceGCOLy({"datasets":[{"shape":[null,null],"dims":["y","x"],"doc":"A grayscale image.","neurodata_type_inc":"Image","neurodata_type_def":"GrayscaleImage","attributes":[{"name":"resolution","doc":"Pixel resolution of the image, in pixels per centimeter.","required":false,"dtype":"float"},{"name":"description","doc":"Description of the image.","required":false,"dtype":"text"}]},{"shape":[null,null,3],"dims":["y","x","R, G, B"],"doc":"A color image.","neurodata_type_inc":"Image","neurodata_type_def":"RGBImage","attributes":[{"name":"resolution","doc":"Pixel resolution of the image, in pixels per centimeter.","required":false,"dtype":"float"},{"name":"description","doc":"Description of the image.","required":false,"dtype":"text"}]},{"shape":[null,null,4],"dims":["y","x","R, G, B, A"],"doc":"A color image with transparency.","neurodata_type_inc":"Image","neurodata_type_def":"RGBAImage","attributes":[{"name":"resolution","doc":"Pixel resolution of the image, in pixels per centimeter.","required":false,"dtype":"float"},{"name":"description","doc":"Description of the image.","required":false,"dtype":"text"}]}],"groups":[{"datasets":[{"shape":[[null,null,null],[null,null,null,null]],"dims":[["frame","y","x"],["frame","z","y","x"]],"dtype":"numeric","name":"data","doc":"Binary data representing images across frames.","quantity":"?","attributes":[{"name":"conversion","doc":"Scalar to multiply each element in data to convert it to the specified 'unit'. If the data are stored in acquisition system units or other units that require a conversion to be interpretable, multiply the data by 'conversion' to convert the data to the specified 'unit'. e.g. if the data acquisition system stores values in this object as signed 16-bit integers (int16 range -32,768 to 32,767) that correspond to a 5V range (-2.5V to 2.5V), and the data acquisition system gain is 8000X, then the 'conversion' multiplier to get from raw data acquisition values to recorded volts is 2.5/32768/8000 = 9.5367e-9.","required":false,"dtype":"float32","default_value":1.0},{"name":"resolution","doc":"Smallest meaningful difference between values in data, stored in the specified by unit, 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 -1.0.","required":false,"dtype":"float32","default_value":-1.0},{"name":"unit","doc":"Base unit of measurement for working with the data. Actual stored values are not necessarily stored in these units. To access the data in these units, multiply 'data' by 'conversion'.","dtype":"text"}]},{"shape":[null],"dims":["rank"],"dtype":"int32","name":"dimension","doc":"Number of pixels on x, y, (and z) axes.","quantity":"?"},{"shape":[null],"dims":["num_files"],"dtype":"text","name":"external_file","doc":"Paths to one or more external file(s). The field is only present if format='external'. This is only relevant if the image series is stored in the file system as one or more image file(s). This field should NOT be used if the image is stored in another NWB file and that file is linked to this file.","quantity":"?","attributes":[{"name":"starting_frame","doc":"Each external image may contain one or more consecutive frames of the full ImageSeries. This attribute serves as an index to indicate which frames each file contains, to faciliate random access. The 'starting_frame' attribute, hence, contains a list of frame numbers within the full ImageSeries of the first frame of each file listed in the parent 'external_file' dataset. Zero-based indexing is used (hence, the first element will always be zero). For example, if the 'external_file' dataset has three paths to files and the first file has 5 frames, the second file has 10 frames, and the third file has 20 frames, then this attribute will have values [0, 5, 15]. If there is a single external file that holds all of the frames of the ImageSeries (and so there is a single element in the 'external_file' dataset), then this attribute should have value [0].","dtype":"int","shape":[null],"dims":["num_files"]}]},{"dtype":"text","name":"format","doc":"Format of image. If this is 'external', then the attribute 'external_file' contains the path information to the image files. If this is 'raw', then the raw (single-channel) binary data is stored in the 'data' dataset. If this attribute is not present, then the default format='raw' case is assumed.","quantity":"?","default_value":"raw"}],"doc":"General image data that is common between acquisition and stimulus time series. Sometimes the image data is stored in the file in a raw format while other times it will be stored as a series of external image files in the host file system. The data field will either be binary data, if the data is stored in the NWB file, or empty, if the data is stored in an external image stack. [frame][y][x] or [frame][z][y][x].","neurodata_type_inc":"TimeSeries","neurodata_type_def":"ImageSeries","attributes":[{"name":"description","doc":"Description of the time series.","required":false,"dtype":"text","default_value":"no description"},{"name":"comments","doc":"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.","required":false,"dtype":"text","default_value":"no comments"}]},{"links":[{"name":"masked_imageseries","doc":"Link to ImageSeries object that this image mask is applied to.","target_type":"ImageSeries"}],"doc":"An alpha mask that is applied to a presented visual stimulus. The 'data' array contains an array of mask values that are applied to the displayed image. Mask values are stored as RGBA. Mask can vary with time. The timestamps array indicates the starting time of a mask, and that mask pattern continues until it's explicitly changed.","neurodata_type_inc":"ImageSeries","neurodata_type_def":"ImageMaskSeries","attributes":[{"name":"description","doc":"Description of the time series.","required":false,"dtype":"text","default_value":"no description"},{"name":"comments","doc":"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.","required":false,"dtype":"text","default_value":"no comments"}]},{"datasets":[{"dtype":"float32","name":"distance","doc":"Distance from camera/monitor to target/eye.","quantity":"?"},{"shape":[[2],[3]],"dims":[["width, height"],["width, height, depth"]],"dtype":"float32","name":"field_of_view","doc":"Width, height and depth of image, or imaged area, in meters.","quantity":"?"},{"dtype":"text","name":"orientation","doc":"Description of image relative to some reference frame (e.g., which way is up). Must also specify frame of reference.","quantity":"?"}],"doc":"Image data that is presented or recorded. A stimulus template movie will be stored only as an image. When the image is presented as stimulus, additional data is required, such as field of view (e.g., how much of the visual field the image covers, or how what is the area of the target being imaged). If the OpticalSeries represents acquired imaging data, orientation is also important.","neurodata_type_inc":"ImageSeries","neurodata_type_def":"OpticalSeries","attributes":[{"name":"description","doc":"Description of the time series.","required":false,"dtype":"text","default_value":"no description"},{"name":"comments","doc":"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.","required":false,"dtype":"text","default_value":"no comments"}]},{"datasets":[{"shape":[null],"dims":["num_times"],"dtype":"int","name":"data","doc":"Index of the frame in the referenced ImageSeries.","attributes":[{"name":"conversion","doc":"Scalar to multiply each element in data to convert it to the specified 'unit'. If the data are stored in acquisition system units or other units that require a conversion to be interpretable, multiply the data by 'conversion' to convert the data to the specified 'unit'. e.g. if the data acquisition system stores values in this object as signed 16-bit integers (int16 range -32,768 to 32,767) that correspond to a 5V range (-2.5V to 2.5V), and the data acquisition system gain is 8000X, then the 'conversion' multiplier to get from raw data acquisition values to recorded volts is 2.5/32768/8000 = 9.5367e-9.","required":false,"dtype":"float32","default_value":1.0},{"name":"resolution","doc":"Smallest meaningful difference between values in data, stored in the specified by unit, 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 -1.0.","required":false,"dtype":"float32","default_value":-1.0},{"name":"unit","doc":"Base unit of measurement for working with the data. Actual stored values are not necessarily stored in these units. To access the data in these units, multiply 'data' by 'conversion'.","dtype":"text"}]}],"links":[{"name":"indexed_timeseries","doc":"Link to ImageSeries object containing images that are indexed.","target_type":"ImageSeries"}],"doc":"Stores indices to image frames stored in an ImageSeries. The purpose of the ImageIndexSeries 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 ImageSeries, and the timestamps array indicates when that image was displayed.","neurodata_type_inc":"TimeSeries","neurodata_type_def":"IndexSeries","attributes":[{"name":"description","doc":"Description of the time series.","required":false,"dtype":"text","default_value":"no description"},{"name":"comments","doc":"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.","required":false,"dtype":"text","default_value":"no comments"}]}]}"<{"groups":[{"groups":[{"groups":[{"doc":"Acquired, raw data.","quantity":"*","neurodata_type_inc":"NWBDataInterface"},{"doc":"Tabular data that is relevent to acquisition","quantity":"*","neurodata_type_inc":"DynamicTable"}],"name":"acquisition","doc":"Data streams recorded from the system, including ephys, ophys, tracking, etc. This group should be 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 NWB files. This will allow keeping bulky raw data out of the file while preserving the option of keeping some/all in the file. Acquired data includes tracking and experimental data streams (i.e., everything measured from the system). If bulky data is stored in the /acquisition group, the data can exist in a separate NWB file that is linked to by the file being used for processing and analysis."},{"groups":[{"doc":"Custom analysis results.","quantity":"*","neurodata_type_inc":"NWBContainer"},{"doc":"Tabular data that is relevent to data stored in analysis","quantity":"*","neurodata_type_inc":"DynamicTable"}],"name":"analysis","doc":"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. To facilitate sharing analysis data between labs, the contents here should be stored in standard types (e.g., neurodata_types) and appropriately documented. 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 could be shared with other labs."},{"groups":[{"doc":"Any one-off containers","quantity":"*","neurodata_type_inc":"NWBContainer"},{"doc":"Any one-off tables","quantity":"*","neurodata_type_inc":"DynamicTable"}],"datasets":[{"doc":"Any one-off datasets","quantity":"*","neurodata_type_inc":"NWBData","neurodata_type_def":"ScratchData","attributes":[{"name":"notes","doc":"Any notes the user has about the dataset being stored","dtype":"text"}]}],"name":"scratch","doc":"A place to store one-off analysis results. Data placed here is not intended for sharing. By placing data here, users acknowledge that there is no guarantee that their data meets any standard.","quantity":"?"},{"groups":[{"doc":"Intermediate analysis of acquired data.","quantity":"*","neurodata_type_inc":"ProcessingModule"}],"name":"processing","doc":"The home for ProcessingModules. 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. ProcessingModules 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. 'Processing' refers to intermediate analysis of the acquired data to make it more amenable to scientific analysis."},{"groups":[{"groups":[{"doc":"TimeSeries objects containing data of presented stimuli.","quantity":"*","neurodata_type_inc":"TimeSeries"}],"name":"presentation","doc":"Stimuli presented during the experiment."},{"groups":[{"doc":"TimeSeries objects containing template data of presented stimuli.","quantity":"*","neurodata_type_inc":"TimeSeries"}],"name":"templates","doc":"Template stimuli. Timestamps 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."}],"name":"stimulus","doc":"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). This group should be made 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. 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 linked to a remote library file."},{"groups":[{"doc":"Place-holder than can be extended so that lab-specific meta-data can be placed in /general.","quantity":"*","neurodata_type_inc":"NWBContainer","neurodata_type_def":"LabMetaData"},{"groups":[{"doc":"A data acquisition device, e.g. recording system.","quantity":"+","neurodata_type_inc":"NWBContainer","neurodata_type_def":"Device"}],"name":"devices","doc":"Description of hardware devices used during experiment, e.g., monitors, ADC boards, microscopes, etc.","quantity":"?"},{"datasets":[{"dtype":"text","name":"age","doc":"Age of subject. Can be supplied instead of 'date_of_birth'.","quantity":"?"},{"dtype":"isodatetime","name":"date_of_birth","doc":"Date of birth of subject. Can be supplied instead of 'age'.","quantity":"?"},{"dtype":"text","name":"description","doc":"Description of subject and where subject came from (e.g., breeder, if animal).","quantity":"?"},{"dtype":"text","name":"genotype","doc":"Genetic strain. If absent, assume Wild Type (WT).","quantity":"?"},{"dtype":"text","name":"sex","doc":"Gender of subject.","quantity":"?"},{"dtype":"text","name":"species","doc":"Species of subject.","quantity":"?"},{"dtype":"text","name":"subject_id","doc":"ID of animal/person used/participating in experiment (lab convention).","quantity":"?"},{"dtype":"text","name":"weight","doc":"Weight at time of experiment, at time of surgery and at other important times.","quantity":"?"}],"name":"subject","doc":"Information about the animal or person from which the data was measured.","quantity":"?","neurodata_type_inc":"NWBContainer","neurodata_type_def":"Subject"},{"groups":[{"doc":"Physical group of electrodes.","quantity":"*","neurodata_type_inc":"ElectrodeGroup"},{"datasets":[{"dtype":"float","name":"x","doc":"x coordinate of the channel location.","neurodata_type_inc":"VectorData"},{"dtype":"float","name":"y","doc":"y coordinate of the channel location.","neurodata_type_inc":"VectorData"},{"dtype":"float","name":"z","doc":"z coordinate of the channel location.","neurodata_type_inc":"VectorData"},{"dtype":"float","name":"imp","doc":"Impedance of the channel.","neurodata_type_inc":"VectorData"},{"dtype":"ascii","name":"location","doc":"Location of the electrode (channel). Specify the area, layer, comments on estimation of area/layer, stereotaxic coordinates if in vivo, etc. Use standard atlas names for anatomical regions when possible.","neurodata_type_inc":"VectorData"},{"dtype":"float","name":"filtering","doc":"Description of hardware filtering.","neurodata_type_inc":"VectorData"},{"dtype":{"target_type":"ElectrodeGroup","reftype":"object"},"name":"group","doc":"Reference to the ElectrodeGroup this electrode is a part of.","neurodata_type_inc":"VectorData"},{"dtype":"ascii","name":"group_name","doc":"Name of the ElectrodeGroup this electrode is a part of.","neurodata_type_inc":"VectorData"}],"name":"electrodes","doc":"A table of all electrodes (i.e. channels) used for recording.","quantity":"?","neurodata_type_inc":"DynamicTable"}],"name":"extracellular_ephys","doc":"Metadata related to extracellular electrophysiology.","quantity":"?"},{"groups":[{"doc":"An intracellular electrode.","quantity":"*","neurodata_type_inc":"IntracellularElectrode"},{"name":"sweep_table","doc":"The table which groups different PatchClampSeries together.","quantity":"?","neurodata_type_inc":"SweepTable"}],"datasets":[{"dtype":"text","name":"filtering","doc":"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.","quantity":"?"}],"name":"intracellular_ephys","doc":"Metadata related to intracellular electrophysiology.","quantity":"?"},{"groups":[{"doc":"An optogenetic stimulation site.","quantity":"*","neurodata_type_inc":"OptogeneticStimulusSite"}],"name":"optogenetics","doc":"Metadata describing optogenetic stimuluation.","quantity":"?"},{"groups":[{"doc":"An imaging plane.","quantity":"*","neurodata_type_inc":"ImagingPlane"}],"name":"optophysiology","doc":"Metadata related to optophysiology.","quantity":"?"}],"datasets":[{"dtype":"text","name":"data_collection","doc":"Notes about data collection and analysis.","quantity":"?"},{"dtype":"text","name":"experiment_description","doc":"General description of the experiment.","quantity":"?"},{"shape":[null],"dims":["num_experimenters"],"dtype":"text","name":"experimenter","doc":"Name of person(s) who performed the experiment. Can also specify roles of different people involved.","quantity":"?"},{"dtype":"text","name":"institution","doc":"Institution(s) where experiment was performed.","quantity":"?"},{"shape":[null],"dims":["num_keywords"],"dtype":"text","name":"keywords","doc":"Terms to search over.","quantity":"?"},{"dtype":"text","name":"lab","doc":"Laboratory where experiment was performed.","quantity":"?"},{"dtype":"text","name":"notes","doc":"Notes about the experiment.","quantity":"?"},{"dtype":"text","name":"pharmacology","doc":"Description of drugs used, including how and when they were administered. Anesthesia(s), painkiller(s), etc., plus dosage, concentration, etc.","quantity":"?"},{"dtype":"text","name":"protocol","doc":"Experimental protocol, if applicable. e.g., include IACUC protocol number.","quantity":"?"},{"shape":[null],"dims":["num_publications"],"dtype":"text","name":"related_publications","doc":"Publication information. PMID, DOI, URL, etc.","quantity":"?"},{"dtype":"text","name":"session_id","doc":"Lab-specific ID for the session.","quantity":"?"},{"dtype":"text","name":"slices","doc":"Description of slices, including information about preparation thickness, orientation, temperature, and bath solution.","quantity":"?"},{"dtype":"text","name":"source_script","doc":"Script file or link to public source code used to create this NWB file.","quantity":"?","attributes":[{"name":"file_name","doc":"Name of script file.","dtype":"text"}]},{"dtype":"text","name":"stimulus","doc":"Notes about stimuli, such as how and where they were presented.","quantity":"?"},{"dtype":"text","name":"surgery","doc":"Narrative description about surgery/surgeries, including date(s) and who performed surgery.","quantity":"?"},{"dtype":"text","name":"virus","doc":"Information about virus(es) used in experiments, including virus ID, source, date made, injection location, volume, etc.","quantity":"?"}],"name":"general","doc":"Experimental metadata, including protocol, notes and description of hardware device(s). The metadata stored in this section should be used to describe the experiment. Metadata necessary for interpreting the data is stored with the data. 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 (e.g., 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. 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."},{"groups":[{"name":"epochs","doc":"Divisions in time marking experimental stages or sub-divisions of a single recording session.","quantity":"?","neurodata_type_inc":"TimeIntervals"},{"name":"trials","doc":"Repeated experimental events that have a logical grouping.","quantity":"?","neurodata_type_inc":"TimeIntervals"},{"name":"invalid_times","doc":"Time intervals that should be removed from analysis.","quantity":"?","neurodata_type_inc":"TimeIntervals"},{"doc":"Optional additional table(s) for describing other experimental time intervals.","quantity":"*","neurodata_type_inc":"TimeIntervals"}],"name":"intervals","doc":"Experimental intervals, whether that be logically distinct sub-experiments having a particular scientific goal, trials (see trials subgroup) during an experiment, or epochs (see epochs subgroup) deriving from analysis of data.","quantity":"?"},{"name":"units","doc":"Data about sorted spike units.","quantity":"?","neurodata_type_inc":"Units"}],"datasets":[{"shape":[null],"dims":["num_modifications"],"dtype":"isodatetime","name":"file_create_date","doc":"A record of the date the file was created and of subsequent modifications. The date is stored in UTC with local timezone offset as ISO 8601 extended formatted strings: 2018-09-28T14:43:54.123+02:00. Dates stored in UTC end in \"Z\" with no timezone offset. Date accuracy is up to milliseconds. The file can be created after the experiment was run, so this may differ from the experiment start time. Each modification to the nwb file adds a new entry to the array."},{"dtype":"text","name":"identifier","doc":"A unique text identifier for the file. For example, 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."},{"dtype":"text","name":"session_description","doc":"A description of the experimental session and data in the file."},{"dtype":"isodatetime","name":"session_start_time","doc":"Date and time of the experiment/session start. The date is stored in UTC with local timezone offset as ISO 8601 extended formatted string: 2018-09-28T14:43:54.123+02:00. Dates stored in UTC end in \"Z\" with no timezone offset. Date accuracy is up to milliseconds."},{"dtype":"isodatetime","name":"timestamps_reference_time","doc":"Date and time corresponding to time zero of all timestamps. The date is stored in UTC with local timezone offset as ISO 8601 extended formatted string: 2018-09-28T14:43:54.123+02:00. Dates stored in UTC end in \"Z\" with no timezone offset. Date accuracy is up to milliseconds. All times stored in the file use this time as reference (i.e., time zero)."}],"name":"root","doc":"An NWB:N file storing cellular-based neurophysiology data from a single experimental session.","neurodata_type_inc":"NWBContainer","neurodata_type_def":"NWBFile","attributes":[{"name":"nwb_version","doc":"File version string. Use semantic versioning, e.g. 1.2.1. This will be the name of the format with trailing major, minor and patch numbers.","dtype":"text","value":"2.1.0"}]}]},1{"groups":[{"datasets":[{"shape":[[null],[null,null]],"dims":[["num_times"],["num_times","num_features"]],"dtype":"numeric","name":"data","doc":"Values of each feature at each time.","attributes":[{"name":"unit","doc":"Since there can be different units for different features, store the units in 'feature_units'. The default value for this attribute is \"see 'feature_units'\".","required":false,"dtype":"text","default_value":"see 'feature_units'"},{"name":"conversion","doc":"Scalar to multiply each element in data to convert it to the specified 'unit'. If the data are stored in acquisition system units or other units that require a conversion to be interpretable, multiply the data by 'conversion' to convert the data to the specified 'unit'. e.g. if the data acquisition system stores values in this object as signed 16-bit integers (int16 range -32,768 to 32,767) that correspond to a 5V range (-2.5V to 2.5V), and the data acquisition system gain is 8000X, then the 'conversion' multiplier to get from raw data acquisition values to recorded volts is 2.5/32768/8000 = 9.5367e-9.","required":false,"dtype":"float32","default_value":1.0},{"name":"resolution","doc":"Smallest meaningful difference between values in data, stored in the specified by unit, 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 -1.0.","required":false,"dtype":"float32","default_value":-1.0}]},{"shape":[null],"dims":["num_features"],"dtype":"text","name":"feature_units","doc":"Units of each feature.","quantity":"?"},{"shape":[null],"dims":["num_features"],"dtype":"text","name":"features","doc":"Description of the features represented in TimeSeries::data."}],"doc":"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. This is useful when storing the raw stimulus is impractical.","neurodata_type_inc":"TimeSeries","neurodata_type_def":"AbstractFeatureSeries","attributes":[{"name":"description","doc":"Description of the time series.","required":false,"dtype":"text","default_value":"no description"},{"name":"comments","doc":"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.","required":false,"dtype":"text","default_value":"no comments"}]},{"datasets":[{"shape":[null],"dims":["num_times"],"dtype":"text","name":"data","doc":"Annotations made during an experiment.","attributes":[{"name":"resolution","doc":"Smallest meaningful difference between values in data. Annotations have no units, so the value is fixed to -1.0.","dtype":"float","value":-1.0},{"name":"unit","doc":"Base unit of measurement for working with the data. Annotations have no units, so the value is fixed to 'n/a'.","dtype":"text","value":"n/a"},{"name":"conversion","doc":"Scalar to multiply each element in data to convert it to the specified 'unit'. If the data are stored in acquisition system units or other units that require a conversion to be interpretable, multiply the data by 'conversion' to convert the data to the specified 'unit'. e.g. if the data acquisition system stores values in this object as signed 16-bit integers (int16 range -32,768 to 32,767) that correspond to a 5V range (-2.5V to 2.5V), and the data acquisition system gain is 8000X, then the 'conversion' multiplier to get from raw data acquisition values to recorded volts is 2.5/32768/8000 = 9.5367e-9.","required":false,"dtype":"float32","default_value":1.0}]}],"doc":"Stores user annotations made during an experiment. The 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.","neurodata_type_inc":"TimeSeries","neurodata_type_def":"AnnotationSeries","attributes":[{"name":"description","doc":"Description of the time series.","required":false,"dtype":"text","default_value":"no description"},{"name":"comments","doc":"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.","required":false,"dtype":"text","default_value":"no comments"}]},{"datasets":[{"shape":[null],"dims":["num_times"],"dtype":"int8","name":"data","doc":"Use values >0 if interval started, <0 if interval ended.","attributes":[{"name":"resolution","doc":"Smallest meaningful difference between values in data. Annotations have no units, so the value is fixed to -1.0.","dtype":"float","value":-1.0},{"name":"unit","doc":"Base unit of measurement for working with the data. Annotations have no units, so the value is fixed to 'n/a'.","dtype":"text","value":"n/a"},{"name":"conversion","doc":"Scalar to multiply each element in data to convert it to the specified 'unit'. If the data are stored in acquisition system units or other units that require a conversion to be interpretable, multiply the data by 'conversion' to convert the data to the specified 'unit'. e.g. if the data acquisition system stores values in this object as signed 16-bit integers (int16 range -32,768 to 32,767) that correspond to a 5V range (-2.5V to 2.5V), and the data acquisition system gain is 8000X, then the 'conversion' multiplier to get from raw data acquisition values to recorded volts is 2.5/32768/8000 = 9.5367e-9.","required":false,"dtype":"float32","default_value":1.0}]}],"doc":"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.","neurodata_type_inc":"TimeSeries","neurodata_type_def":"IntervalSeries","attributes":[{"name":"description","doc":"Description of the time series.","required":false,"dtype":"text","default_value":"no description"},{"name":"comments","doc":"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.","required":false,"dtype":"text","default_value":"no comments"}]},{"groups":[{"datasets":[{"dtype":"text","name":"band_name","doc":"Name of the band, e.g. theta.","neurodata_type_inc":"VectorData"},{"shape":[null,2],"dims":["num_bands","low, high"],"dtype":"float","name":"band_limits","doc":"Low and high limit of each band in Hz. If it is a Gaussian filter, use 2 SD on either side of the center.","neurodata_type_inc":"VectorData"},{"shape":[null],"dims":["num_bands"],"dtype":"float","name":"band_mean","doc":"The mean Gaussian filters, in Hz.","neurodata_type_inc":"VectorData"},{"shape":[null],"dims":["num_bands"],"dtype":"float","name":"band_stdev","doc":"The standard deviation of Gaussian filters, in Hz.","neurodata_type_inc":"VectorData"}],"name":"bands","doc":"Table for describing the bands that this series was generated from. There should be one row in this table for each band.","neurodata_type_inc":"DynamicTable"}],"datasets":[{"shape":[null,null,null],"dims":["num_times","num_channels","num_bands"],"dtype":"numeric","name":"data","doc":"Data decomposed into frequency bands.","attributes":[{"name":"unit","doc":"Base unit of measurement for working with the data. Actual stored values are not necessarily stored in these units. To access the data in these units, multiply 'data' by 'conversion'.","required":false,"dtype":"text","default_value":"no unit"},{"name":"conversion","doc":"Scalar to multiply each element in data to convert it to the specified 'unit'. If the data are stored in acquisition system units or other units that require a conversion to be interpretable, multiply the data by 'conversion' to convert the data to the specified 'unit'. e.g. if the data acquisition system stores values in this object as signed 16-bit integers (int16 range -32,768 to 32,767) that correspond to a 5V range (-2.5V to 2.5V), and the data acquisition system gain is 8000X, then the 'conversion' multiplier to get from raw data acquisition values to recorded volts is 2.5/32768/8000 = 9.5367e-9.","required":false,"dtype":"float32","default_value":1.0},{"name":"resolution","doc":"Smallest meaningful difference between values in data, stored in the specified by unit, 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 -1.0.","required":false,"dtype":"float32","default_value":-1.0}]},{"dtype":"text","name":"metric","doc":"The metric used, e.g. phase, amplitude, power."}],"links":[{"name":"source_timeseries","doc":"Link to TimeSeries object that this data was calculated from. Metadata about electrodes and their position can be read from that ElectricalSeries so it is not necessary to store that information here.","target_type":"TimeSeries","quantity":"?"}],"doc":"Spectral analysis of a time series, e.g. of an LFP or a speech signal.","neurodata_type_inc":"TimeSeries","neurodata_type_def":"DecompositionSeries","attributes":[{"name":"description","doc":"Description of the time series.","required":false,"dtype":"text","default_value":"no description"},{"name":"comments","doc":"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.","required":false,"dtype":"text","default_value":"no comments"}]},{"datasets":[{"name":"spike_times_index","doc":"Index into the spike_times dataset.","quantity":"?","neurodata_type_inc":"VectorIndex"},{"dtype":"double","name":"spike_times","doc":"Spike times for each unit.","quantity":"?","neurodata_type_inc":"VectorData"},{"name":"obs_intervals_index","doc":"Index into the obs_intervals dataset.","quantity":"?","neurodata_type_inc":"VectorIndex"},{"shape":[null,2],"dims":["num_intervals","start|end"],"dtype":"double","name":"obs_intervals","doc":"Observation intervals for each unit.","quantity":"?","neurodata_type_inc":"VectorData"},{"name":"electrodes_index","doc":"Index into electrodes.","quantity":"?","neurodata_type_inc":"VectorIndex"},{"name":"electrodes","doc":"Electrode that each spike unit came from, specified using a DynamicTableRegion.","quantity":"?","neurodata_type_inc":"DynamicTableRegion"},{"dtype":{"target_type":"ElectrodeGroup","reftype":"object"},"name":"electrode_group","doc":"Electrode group that each spike unit came from.","quantity":"?","neurodata_type_inc":"VectorData"},{"shape":[[null,null],[null,null,null]],"dims":[["num_units","num_samples"],["num_units","num_samples","num_electrodes"]],"dtype":"float","name":"waveform_mean","doc":"Spike waveform mean for each spike unit.","quantity":"?","neurodata_type_inc":"VectorData"},{"shape":[[null,null],[null,null,null]],"dims":[["num_units","num_samples"],["num_units","num_samples","num_electrodes"]],"dtype":"float","name":"waveform_sd","doc":"Spike waveform standard deviation for each spike unit.","quantity":"?","neurodata_type_inc":"VectorData"}],"doc":"Data about spiking units. Event times of observed units (e.g. cell, synapse, etc.) should be concatenated and stored in spike_times.","default_name":"Units","neurodata_type_inc":"DynamicTable","neurodata_type_def":"Units","attributes":[{"name":"colnames","doc":"The names of the columns in this table. This should be used to specify an order to the columns.","dtype":"ascii","shape":[null],"dims":["num_columns"]},{"name":"description","doc":"Description of what is in this dynamic table.","dtype":"text"}]}]}{"groups":[{"datasets":[{"shape":[[null],[null,null]],"dims":[["num_times"],["num_times","num_features"]],"dtype":"numeric","name":"data","doc":"1-D or 2-D array storing position or direction relative to some reference frame.","attributes":[{"name":"unit","doc":"Base unit of measurement for working with the data. The default value is 'meters'. Actual stored values are not necessarily stored in these units. To access the data in these units, multiply 'data' by 'conversion'.","required":false,"dtype":"text","default_value":"meters"},{"name":"conversion","doc":"Scalar to multiply each element in data to convert it to the specified 'unit'. If the data are stored in acquisition system units or other units that require a conversion to be interpretable, multiply the data by 'conversion' to convert the data to the specified 'unit'. e.g. if the data acquisition system stores values in this object as signed 16-bit integers (int16 range -32,768 to 32,767) that correspond to a 5V range (-2.5V to 2.5V), and the data acquisition system gain is 8000X, then the 'conversion' multiplier to get from raw data acquisition values to recorded volts is 2.5/32768/8000 = 9.5367e-9.","required":false,"dtype":"float32","default_value":1.0},{"name":"resolution","doc":"Smallest meaningful difference between values in data, stored in the specified by unit, 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 -1.0.","required":false,"dtype":"float32","default_value":-1.0}]},{"dtype":"text","name":"reference_frame","doc":"Description defining what exactly 'straight-ahead' means.","quantity":"?"}],"doc":"Direction, e.g., of gaze or travel, or position. The TimeSeries::data field is a 2D array storing position or direction relative to some reference frame. Array structure: [num measurements] [num dimensions]. Each SpatialSeries has a text dataset reference_frame that indicates the zero-position, or the zero-axes for direction. For example, if representing gaze direction, 'straight-ahead' might be a specific pixel on the monitor, or some other point in space. For position data, the 0,0 point might be the top-left corner of an enclosure, as viewed from the tracking camera. The unit of data will indicate how to interpret SpatialSeries values.","neurodata_type_inc":"TimeSeries","neurodata_type_def":"SpatialSeries","attributes":[{"name":"description","doc":"Description of the time series.","required":false,"dtype":"text","default_value":"no description"},{"name":"comments","doc":"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.","required":false,"dtype":"text","default_value":"no comments"}]},{"groups":[{"doc":"IntervalSeries object containing start and stop times of epochs.","quantity":"*","neurodata_type_inc":"IntervalSeries"}],"doc":"TimeSeries for storing behavioral epochs. The objective of this and the other two Behavioral interfaces (e.g. BehavioralEvents and BehavioralTimeSeries) is to provide generic hooks for software tools/scripts. This allows a tool/script to take the output one specific interface (e.g., UnitTimes) and plot that data relative to another data modality (e.g., behavioral events) without having to define all possible modalities in advance. Declaring one of these interfaces means that one or more TimeSeries of the specified type is published. These TimeSeries should reside in a group having the same name as the interface. For example, if a BehavioralTimeSeries interface is declared, the module will have one or more TimeSeries defined in the module sub-group 'BehavioralTimeSeries'. BehavioralEpochs should use IntervalSeries. BehavioralEvents is used for irregular events. BehavioralTimeSeries is for continuous data.","default_name":"BehavioralEpochs","neurodata_type_inc":"NWBDataInterface","neurodata_type_def":"BehavioralEpochs"},{"groups":[{"doc":"TimeSeries object containing behavioral events.","quantity":"*","neurodata_type_inc":"TimeSeries"}],"doc":"TimeSeries for storing behavioral events. See description of BehavioralEpochs for more details.","default_name":"BehavioralEvents","neurodata_type_inc":"NWBDataInterface","neurodata_type_def":"BehavioralEvents"},{"groups":[{"doc":"TimeSeries object containing continuous behavioral data.","quantity":"*","neurodata_type_inc":"TimeSeries"}],"doc":"TimeSeries for storing Behavoioral time series data. See description of BehavioralEpochs for more details.","default_name":"BehavioralTimeSeries","neurodata_type_inc":"NWBDataInterface","neurodata_type_def":"BehavioralTimeSeries"},{"groups":[{"doc":"TimeSeries object containing time series data on pupil size.","quantity":"+","neurodata_type_inc":"TimeSeries"}],"doc":"Eye-tracking data, representing pupil size.","default_name":"PupilTracking","neurodata_type_inc":"NWBDataInterface","neurodata_type_def":"PupilTracking"},{"groups":[{"doc":"SpatialSeries object containing data measuring direction of gaze.","quantity":"*","neurodata_type_inc":"SpatialSeries"}],"doc":"Eye-tracking data, representing direction of gaze.","default_name":"EyeTracking","neurodata_type_inc":"NWBDataInterface","neurodata_type_def":"EyeTracking"},{"groups":[{"doc":"SpatialSeries object containing direction of gaze travel.","quantity":"*","neurodata_type_inc":"SpatialSeries"}],"doc":"With a CompassDirection interface, a module publishes a SpatialSeries object representing a floating point value for theta. The SpatialSeries::reference_frame field should indicate what direction corresponds to 0 and which is the direction of rotation (this should be clockwise). The si_unit for the SpatialSeries should be radians or degrees.","default_name":"CompassDirection","neurodata_type_inc":"NWBDataInterface","neurodata_type_def":"CompassDirection"},{"groups":[{"doc":"SpatialSeries object containing position data.","quantity":"+","neurodata_type_inc":"SpatialSeries"}],"doc":"Position data, whether along the x, x/y or x/y/z axis.","default_name":"Position","neurodata_type_inc":"NWBDataInterface","neurodata_type_def":"Position"}]}~ {"groups":[{"datasets":[{"shape":[null],"dims":["num_times"],"dtype":"numeric","name":"data","doc":"Applied power for optogenetic stimulus, in watts.","attributes":[{"name":"unit","doc":"Unit of measurement for data, which is fixed to 'watts'.","dtype":"text","value":"watts"},{"name":"conversion","doc":"Scalar to multiply each element in data to convert it to the specified 'unit'. If the data are stored in acquisition system units or other units that require a conversion to be interpretable, multiply the data by 'conversion' to convert the data to the specified 'unit'. e.g. if the data acquisition system stores values in this object as signed 16-bit integers (int16 range -32,768 to 32,767) that correspond to a 5V range (-2.5V to 2.5V), and the data acquisition system gain is 8000X, then the 'conversion' multiplier to get from raw data acquisition values to recorded volts is 2.5/32768/8000 = 9.5367e-9.","required":false,"dtype":"float32","default_value":1.0},{"name":"resolution","doc":"Smallest meaningful difference between values in data, stored in the specified by unit, 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 -1.0.","required":false,"dtype":"float32","default_value":-1.0}]}],"links":[{"name":"site","doc":"Link to OptogeneticStimulusSite object that describes the site to which this stimulus was applied.","target_type":"OptogeneticStimulusSite"}],"doc":"An optogenetic stimulus.","neurodata_type_inc":"TimeSeries","neurodata_type_def":"OptogeneticSeries","attributes":[{"name":"description","doc":"Description of the time series.","required":false,"dtype":"text","default_value":"no description"},{"name":"comments","doc":"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.","required":false,"dtype":"text","default_value":"no comments"}]},{"datasets":[{"dtype":"text","name":"description","doc":"Description of stimulation site."},{"dtype":"float","name":"excitation_lambda","doc":"Excitation wavelength, in nm."},{"dtype":"text","name":"location","doc":"Location of the stimulation site. Specify the area, layer, comments on estimation of area/layer, stereotaxic coordinates if in vivo, etc. Use standard atlas names for anatomical regions when possible."}],"links":[{"name":"device","doc":"Device that generated the stimulus.","target_type":"Device"}],"doc":"A site of optogenetic stimulation.","quantity":"*","neurodata_type_inc":"NWBContainer","neurodata_type_def":"OptogeneticStimulusSite"}]}`3D'^3D'^3D'^SNOD8~x`M(|HpNPQ3D'^3D'^3D'^GCOLw4{"groups":[{"datasets":[{"shape":[[null],[null,null],[null,null,null]],"dims":[["num_times"],["num_times","num_channels"],["num_times","num_channels","num_samples"]],"dtype":"numeric","name":"data","doc":"Recorded voltage data.","attributes":[{"name":"unit","doc":"Base unit of measurement for working with the data. This value is fixed to 'volts'. Actual stored values are not necessarily stored in these units. To access the data in these units, multiply 'data' by 'conversion' and 'channel_conversion' (if present).","dtype":"text","value":"volts"},{"name":"conversion","doc":"Scalar to multiply each element in data to convert it to the specified 'unit'. If the data are stored in acquisition system units or other units that require a conversion to be interpretable, multiply the data by 'conversion' to convert the data to the specified 'unit'. e.g. if the data acquisition system stores values in this object as signed 16-bit integers (int16 range -32,768 to 32,767) that correspond to a 5V range (-2.5V to 2.5V), and the data acquisition system gain is 8000X, then the 'conversion' multiplier to get from raw data acquisition values to recorded volts is 2.5/32768/8000 = 9.5367e-9.","required":false,"dtype":"float32","default_value":1.0},{"name":"resolution","doc":"Smallest meaningful difference between values in data, stored in the specified by unit, 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 -1.0.","required":false,"dtype":"float32","default_value":-1.0}]},{"name":"electrodes","doc":"DynamicTableRegion pointer to the electrodes that this time series was generated from.","neurodata_type_inc":"DynamicTableRegion"},{"shape":[null],"dims":["num_channels"],"dtype":"float","name":"channel_conversion","doc":"Channel-specific conversion factor. Multiply the data in the 'data' dataset by these values along the channel axis (as indicated by axis attribute) AND by the global conversion factor in the 'conversion' attribute of 'data' to get the data values in Volts, i.e, data in Volts = data * data.conversion * channel_conversion. This approach allows for both global and per-channel data conversion factors needed to support the storage of electrical recordings as native values generated by data acquisition systems. If this dataset is not present, then there is no channel-specific conversion factor, i.e. it is 1 for all channels.","quantity":"?","attributes":[{"name":"axis","doc":"The zero-indexed axis of the 'data' dataset that the channel-specific conversion factor corresponds to. This value is fixed to 1.","dtype":"int","value":1}]}],"doc":"A time series of acquired voltage data from extracellular recordings. The data field is an int or float array storing data in volts. The first dimension should always represent time. The second dimension, if present, should represent channels.","neurodata_type_inc":"TimeSeries","neurodata_type_def":"ElectricalSeries","attributes":[{"name":"description","doc":"Description of the time series.","required":false,"dtype":"text","default_value":"no description"},{"name":"comments","doc":"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.","required":false,"dtype":"text","default_value":"no comments"}]},{"datasets":[{"shape":[[null,null],[null,null,null]],"dims":[["num_events","num_samples"],["num_events","num_channels","num_samples"]],"dtype":"numeric","name":"data","doc":"Spike waveforms.","attributes":[{"name":"unit","doc":"Unit of measurement for waveforms, which is fixed to 'volts'.","dtype":"text","value":"volts"},{"name":"conversion","doc":"Scalar to multiply each element in data to convert it to the specified 'unit'. If the data are stored in acquisition system units or other units that require a conversion to be interpretable, multiply the data by 'conversion' to convert the data to the specified 'unit'. e.g. if the data acquisition system stores values in this object as signed 16-bit integers (int16 range -32,768 to 32,767) that correspond to a 5V range (-2.5V to 2.5V), and the data acquisition system gain is 8000X, then the 'conversion' multiplier to get from raw data acquisition values to recorded volts is 2.5/32768/8000 = 9.5367e-9.","required":false,"dtype":"float32","default_value":1.0},{"name":"resolution","doc":"Smallest meaningful difference between values in data, stored in the specified by unit, 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 -1.0.","required":false,"dtype":"float32","default_value":-1.0}]},{"shape":[null],"dims":["num_times"],"dtype":"float64","name":"timestamps","doc":"Timestamps for samples stored in data, in seconds, relative to the common experiment master-clock stored in NWBFile.timestamps_reference_time. Timestamps are required for the events. Unlike for TimeSeries, timestamps are required for SpikeEventSeries and are thus re-specified here.","attributes":[{"name":"interval","doc":"Value is '1'","dtype":"int32","value":1},{"name":"unit","doc":"Unit of measurement for timestamps, which is fixed to 'seconds'.","dtype":"text","value":"seconds"}]}],"doc":"Stores snapshots/snippets of recorded spike events (i.e., threshold crossings). This may also be raw data, as reported by ephys hardware. If so, the TimeSeries::description field should describe how events were detected. All SpikeEventSeries should reside in a module (under EventWaveform interface) even if the spikes were reported and stored by hardware. All events span the same recording channels and store snapshots of equal duration. TimeSeries::data array structure: [num events] [num channels] [num samples] (or [num events] [num samples] for single electrode).","neurodata_type_inc":"ElectricalSeries","neurodata_type_def":"SpikeEventSeries","attributes":[{"name":"description","doc":"Description of the time series.","required":false,"dtype":"text","default_value":"no description"},{"name":"comments","doc":"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.","required":false,"dtype":"text","default_value":"no comments"}]},{"datasets":[{"shape":[null],"dims":["num_features"],"dtype":"text","name":"description","doc":"Description of features (eg, ''PC1'') for each of the extracted features."},{"shape":[null,null,null],"dims":["num_events","num_channels","num_features"],"dtype":"float32","name":"features","doc":"Multi-dimensional array of features extracted from each event."},{"shape":[null],"dims":["num_events"],"dtype":"float64","name":"times","doc":"Times of events that features correspond to (can be a link)."},{"name":"electrodes","doc":"DynamicTableRegion pointer to the electrodes that this time series was generated from.","neurodata_type_inc":"DynamicTableRegion"}],"doc":"Features, such as PC1 and PC2, that are extracted from signals stored in a SpikeEventSeries or other source.","default_name":"FeatureExtraction","neurodata_type_inc":"NWBDataInterface","neurodata_type_def":"FeatureExtraction"},{"datasets":[{"dtype":"text","name":"detection_method","doc":"Description of how events were detected, such as voltage threshold, or dV/dT threshold, as well as relevant values."},{"shape":[null],"dims":["num_events"],"dtype":"int32","name":"source_idx","doc":"Indices (zero-based) into source ElectricalSeries::data array corresponding to time of event. ''description'' should define what is meant by time of event (e.g., .25 ms before action potential peak, zero-crossing time, etc). The index points to each event from the raw data."},{"shape":[null],"dims":["num_events"],"dtype":"float64","name":"times","doc":"Timestamps of events, in seconds.","attributes":[{"name":"unit","doc":"Unit of measurement for event times, which is fixed to 'seconds'.","dtype":"text","value":"seconds"}]}],"links":[{"name":"source_electricalseries","doc":"Link to the ElectricalSeries that this data was calculated from. Metadata about electrodes and their position can be read from that ElectricalSeries so it's not necessary to include that information here.","target_type":"ElectricalSeries"}],"doc":"Detected spike events from voltage trace(s).","default_name":"EventDetection","neurodata_type_inc":"NWBDataInterface","neurodata_type_def":"EventDetection"},{"groups":[{"doc":"SpikeEventSeries object(s) containing detected spike event waveforms.","quantity":"*","neurodata_type_inc":"SpikeEventSeries"}],"doc":"Represents either the waveforms of detected events, as extracted from a raw data trace in /acquisition, or the event waveforms that were stored during experiment acquisition.","default_name":"EventWaveform","neurodata_type_inc":"NWBDataInterface","neurodata_type_def":"EventWaveform"},{"groups":[{"doc":"ElectricalSeries object(s) containing filtered electrophysiology data.","quantity":"+","neurodata_type_inc":"ElectricalSeries"}],"doc":"Electrophysiology data from one or more channels that has been subjected to filtering. Examples of filtered data include Theta and Gamma (LFP has its own interface). FilteredEphys modules publish an ElectricalSeries for each filtered channel or set of channels. The name of each ElectricalSeries is arbitrary but should be informative. The source of the filtered data, whether this is from analysis of another time series or as acquired by hardware, should be noted in each's TimeSeries::description field. There is no assumed 1::1 correspondence between filtered ephys signals and electrodes, as a single signal can apply to many nearby electrodes, and one electrode may have different filtered (e.g., theta and/or gamma) signals represented. Filter properties should be noted in the ElectricalSeries.","default_name":"FilteredEphys","neurodata_type_inc":"NWBDataInterface","neurodata_type_def":"FilteredEphys"},{"groups":[{"doc":"ElectricalSeries object(s) containing LFP data for one or more channels.","quantity":"+","neurodata_type_inc":"ElectricalSeries"}],"doc":"LFP data from one or more channels. The electrode map in each published ElectricalSeries will identify which channels are providing LFP data. Filter properties should be noted in the ElectricalSeries description or comments field.","default_name":"LFP","neurodata_type_inc":"NWBDataInterface","neurodata_type_def":"LFP"},{"links":[{"name":"device","doc":"Link to the device that was used to record from this electrode group.","target_type":"Device"}],"doc":"A physical grouping of electrodes, e.g. a shank of an array.","neurodata_type_inc":"NWBContainer","neurodata_type_def":"ElectrodeGroup","attributes":[{"name":"description","doc":"Description of this electrode group.","dtype":"text"},{"name":"location","doc":"Location of electrode group. Specify the area, layer, comments on estimation of area/layer, stereotaxic coordinates if in vivo, etc. Use standard atlas names for anatomical regions when possible.","dtype":"text"}]},{"datasets":[{"dtype":"text","name":"waveform_filtering","doc":"Filtering applied to data before generating mean/sd"},{"shape":[null,null],"dims":["num_clusters","num_samples"],"dtype":"float32","name":"waveform_mean","doc":"The mean waveform for each cluster, using the same indices for each wave as cluster numbers in the associated Clustering module (i.e, cluster 3 is in array slot [3]). Waveforms corresponding to gaps in cluster sequence should be empty (e.g., zero- filled)"},{"shape":[null,null],"dims":["num_clusters","num_samples"],"dtype":"float32","name":"waveform_sd","doc":"Stdev of waveforms for each cluster, using the same indices as in mean"}],"links":[{"name":"clustering_interface","doc":"Link to Clustering interface that was the source of the clustered data","target_type":"Clustering"}],"doc":"DEPRECATED The mean waveform shape, including standard deviation, of the different clusters. Ideally, the waveform analysis should be performed on data that is only high-pass filtered. This is a separate module because it is expected to require updating. For example, IMEC probes may require different storage requirements to store/display mean waveforms, requiring a new interface or an extension of this one.","default_name":"ClusterWaveforms","neurodata_type_inc":"NWBDataInterface","neurodata_type_def":"ClusterWaveforms"},{"datasets":[{"dtype":"text","name":"description","doc":"Description of clusters or clustering, (e.g. cluster 0 is noise, clusters curated using Klusters, etc)"},{"shape":[null],"dims":["num_events"],"dtype":"int32","name":"num","doc":"Cluster number of each event"},{"shape":[null],"dims":["num_clusters"],"dtype":"float32","name":"peak_over_rms","doc":"Maximum ratio of waveform peak to RMS on any channel in the cluster (provides a basic clustering metric)."},{"shape":[null],"dims":["num_events"],"dtype":"float64","name":"times","doc":"Times of clustered events, in seconds. This may be a link to times field in associated FeatureExtraction module."}],"doc":"DEPRECATED Clustered spike data, whether from automatic clustering tools (e.g., klustakwik) or as a result of manual sorting.","default_name":"Clustering","neurodata_type_inc":"NWBDataInterface","neurodata_type_def":"Clustering"}]}B{"groups":[{"datasets":[{"shape":[null],"dims":["num_times"],"dtype":"numeric","name":"data","doc":"Recorded voltage or current.","attributes":[{"name":"unit","doc":"Base unit of measurement for working with the data. Actual stored values are not necessarily stored in these units. To access the data in these units, multiply 'data' by 'conversion'.","dtype":"text"},{"name":"conversion","doc":"Scalar to multiply each element in data to convert it to the specified 'unit'. If the data are stored in acquisition system units or other units that require a conversion to be interpretable, multiply the data by 'conversion' to convert the data to the specified 'unit'. e.g. if the data acquisition system stores values in this object as signed 16-bit integers (int16 range -32,768 to 32,767) that correspond to a 5V range (-2.5V to 2.5V), and the data acquisition system gain is 8000X, then the 'conversion' multiplier to get from raw data acquisition values to recorded volts is 2.5/32768/8000 = 9.5367e-9.","required":false,"dtype":"float32","default_value":1.0},{"name":"resolution","doc":"Smallest meaningful difference between values in data, stored in the specified by unit, 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 -1.0.","required":false,"dtype":"float32","default_value":-1.0}]},{"dtype":"float","name":"gain","doc":"Gain of the recording, in units Volt/Amp (v-clamp) or Volt/Volt (c-clamp).","quantity":"?"}],"links":[{"name":"electrode","doc":"Link to IntracellularElectrode object that describes the electrode that was used to apply or record this data.","target_type":"IntracellularElectrode"}],"doc":"An abstract base class for patch-clamp data - stimulus or response, current or voltage.","neurodata_type_inc":"TimeSeries","neurodata_type_def":"PatchClampSeries","attributes":[{"name":"stimulus_description","doc":"Protocol/stimulus name for this patch-clamp dataset.","dtype":"text"},{"name":"sweep_number","doc":"Sweep number, allows to group different PatchClampSeries together.","required":false,"dtype":"uint64"},{"name":"description","doc":"Description of the time series.","required":false,"dtype":"text","default_value":"no description"},{"name":"comments","doc":"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.","required":false,"dtype":"text","default_value":"no comments"}]},{"datasets":[{"name":"data","doc":"Recorded voltage.","attributes":[{"name":"unit","doc":"Base unit of measurement for working with the data. which is fixed to 'volts'. Actual stored values are not necessarily stored in these units. To access the data in these units, multiply 'data' by 'conversion'.","dtype":"text","value":"volts"},{"name":"conversion","doc":"Scalar to multiply each element in data to convert it to the specified 'unit'. If the data are stored in acquisition system units or other units that require a conversion to be interpretable, multiply the data by 'conversion' to convert the data to the specified 'unit'. e.g. if the data acquisition system stores values in this object as signed 16-bit integers (int16 range -32,768 to 32,767) that correspond to a 5V range (-2.5V to 2.5V), and the data acquisition system gain is 8000X, then the 'conversion' multiplier to get from raw data acquisition values to recorded volts is 2.5/32768/8000 = 9.5367e-9.","required":false,"dtype":"float32","default_value":1.0},{"name":"resolution","doc":"Smallest meaningful difference between values in data, stored in the specified by unit, 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 -1.0.","required":false,"dtype":"float32","default_value":-1.0}]},{"dtype":"float32","name":"bias_current","doc":"Bias current, in amps.","quantity":"?"},{"dtype":"float32","name":"bridge_balance","doc":"Bridge balance, in ohms.","quantity":"?"},{"dtype":"float32","name":"capacitance_compensation","doc":"Capacitance compensation, in farads.","quantity":"?"}],"doc":"Voltage data from an intracellular current-clamp recording. A corresponding CurrentClampStimulusSeries (stored separately as a stimulus) is used to store the current injected.","neurodata_type_inc":"PatchClampSeries","neurodata_type_def":"CurrentClampSeries","attributes":[{"name":"stimulus_description","doc":"Protocol/stimulus name for this patch-clamp dataset.","dtype":"text"},{"name":"sweep_number","doc":"Sweep number, allows to group different PatchClampSeries together.","required":false,"dtype":"uint64"},{"name":"description","doc":"Description of the time series.","required":false,"dtype":"text","default_value":"no description"},{"name":"comments","doc":"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.","required":false,"dtype":"text","default_value":"no comments"}]},{"datasets":[{"dtype":"float32","name":"bias_current","doc":"Bias current, in amps, fixed to 0.0."},{"dtype":"float32","name":"bridge_balance","doc":"Bridge balance, in ohms, fixed to 0.0."},{"dtype":"float32","name":"capacitance_compensation","doc":"Capacitance compensation, in farads, fixed to 0.0."}],"doc":"Voltage data from an intracellular recording when all current and amplifier settings are off (i.e., CurrentClampSeries fields will be zero). There is no CurrentClampStimulusSeries associated with an IZero series because the amplifier is disconnected and no stimulus can reach the cell.","neurodata_type_inc":"CurrentClampSeries","neurodata_type_def":"IZeroClampSeries","attributes":[{"name":"stimulus_description","doc":"Protocol/stimulus name for this patch-clamp dataset.","dtype":"text"},{"name":"sweep_number","doc":"Sweep number, allows to group different PatchClampSeries together.","required":false,"dtype":"uint64"},{"name":"description","doc":"Description of the time series.","required":false,"dtype":"text","default_value":"no description"},{"name":"comments","doc":"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.","required":false,"dtype":"text","default_value":"no comments"}]},{"datasets":[{"name":"data","doc":"Stimulus current applied.","attributes":[{"name":"unit","doc":"Base unit of measurement for working with the data. which is fixed to 'amperes'. Actual stored values are not necessarily stored in these units. To access the data in these units, multiply 'data' by 'conversion'.","dtype":"text","value":"amperes"},{"name":"conversion","doc":"Scalar to multiply each element in data to convert it to the specified 'unit'. If the data are stored in acquisition system units or other units that require a conversion to be interpretable, multiply the data by 'conversion' to convert the data to the specified 'unit'. e.g. if the data acquisition system stores values in this object as signed 16-bit integers (int16 range -32,768 to 32,767) that correspond to a 5V range (-2.5V to 2.5V), and the data acquisition system gain is 8000X, then the 'conversion' multiplier to get from raw data acquisition values to recorded volts is 2.5/32768/8000 = 9.5367e-9.","required":false,"dtype":"float32","default_value":1.0},{"name":"resolution","doc":"Smallest meaningful difference between values in data, stored in the specified by unit, 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 -1.0.","required":false,"dtype":"float32","default_value":-1.0}]}],"doc":"Stimulus current applied during current clamp recording.","neurodata_type_inc":"PatchClampSeries","neurodata_type_def":"CurrentClampStimulusSeries","attributes":[{"name":"stimulus_description","doc":"Protocol/stimulus name for this patch-clamp dataset.","dtype":"text"},{"name":"sweep_number","doc":"Sweep number, allows to group different PatchClampSeries together.","required":false,"dtype":"uint64"},{"name":"description","doc":"Description of the time series.","required":false,"dtype":"text","default_value":"no description"},{"name":"comments","doc":"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.","required":false,"dtype":"text","default_value":"no comments"}]},{"datasets":[{"name":"data","doc":"Recorded current.","attributes":[{"name":"unit","doc":"Base unit of measurement for working with the data. which is fixed to 'amperes'. Actual stored values are not necessarily stored in these units. To access the data in these units, multiply 'data' by 'conversion'.","dtype":"text","value":"amperes"},{"name":"conversion","doc":"Scalar to multiply each element in data to convert it to the specified 'unit'. If the data are stored in acquisition system units or other units that require a conversion to be interpretable, multiply the data by 'conversion' to convert the data to the specified 'unit'. e.g. if the data acquisition system stores values in this object as signed 16-bit integers (int16 range -32,768 to 32,767) that correspond to a 5V range (-2.5V to 2.5V), and the data acquisition system gain is 8000X, then the 'conversion' multiplier to get from raw data acquisition values to recorded volts is 2.5/32768/8000 = 9.5367e-9.","required":false,"dtype":"float32","default_value":1.0},{"name":"resolution","doc":"Smallest meaningful difference between values in data, stored in the specified by unit, 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 -1.0.","required":false,"dtype":"float32","default_value":-1.0}]},{"dtype":"float32","name":"capacitance_fast","doc":"Fast capacitance, in farads.","quantity":"?","attributes":[{"name":"unit","doc":"Unit of measurement for capacitance_fast, which is fixed to 'farads'.","dtype":"text","value":"farads"}]},{"dtype":"float32","name":"capacitance_slow","doc":"Slow capacitance, in farads.","quantity":"?","attributes":[{"name":"unit","doc":"Unit of measurement for capacitance_fast, which is fixed to 'farads'.","dtype":"text","value":"farads"}]},{"dtype":"float32","name":"resistance_comp_bandwidth","doc":"Resistance compensation bandwidth, in hertz.","quantity":"?","attributes":[{"name":"unit","doc":"Unit of measurement for resistance_comp_bandwidth, which is fixed to 'hertz'.","dtype":"text","value":"hertz"}]},{"dtype":"float32","name":"resistance_comp_correction","doc":"Resistance compensation correction, in percent.","quantity":"?","attributes":[{"name":"unit","doc":"Unit of measurement for resistance_comp_correction, which is fixed to 'percent'.","dtype":"text","value":"percent"}]},{"dtype":"float32","name":"resistance_comp_prediction","doc":"Resistance compensation prediction, in percent.","quantity":"?","attributes":[{"name":"unit","doc":"Unit of measurement for resistance_comp_prediction, which is fixed to 'percent'.","dtype":"text","value":"percent"}]},{"dtype":"float32","name":"whole_cell_capacitance_comp","doc":"Whole cell capacitance compensation, in farads.","quantity":"?","attributes":[{"name":"unit","doc":"Unit of measurement for whole_cell_capacitance_comp, which is fixed to 'farads'.","dtype":"text","value":"farads"}]},{"dtype":"float32","name":"whole_cell_series_resistance_comp","doc":"Whole cell series resistance compensation, in ohms.","quantity":"?","attributes":[{"name":"unit","doc":"Unit of measurement for whole_cell_series_resistance_comp, which is fixed to 'ohms'.","dtype":"text","value":"ohms"}]}],"doc":"Current data from an intracellular voltage-clamp recording. A corresponding VoltageClampStimulusSeries (stored separately as a stimulus) is used to store the voltage injected.","neurodata_type_inc":"PatchClampSeries","neurodata_type_def":"VoltageClampSeries","attributes":[{"name":"stimulus_description","doc":"Protocol/stimulus name for this patch-clamp dataset.","dtype":"text"},{"name":"sweep_number","doc":"Sweep number, allows to group different PatchClampSeries together.","required":false,"dtype":"uint64"},{"name":"description","doc":"Description of the time series.","required":false,"dtype":"text","default_value":"no description"},{"name":"comments","doc":"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.","required":false,"dtype":"text","default_value":"no comments"}]},{"datasets":[{"name":"data","doc":"Stimulus voltage applied.","attributes":[{"name":"unit","doc":"Base unit of measurement for working with the data. which is fixed to 'volts'. Actual stored values are not necessarily stored in these units. To access the data in these units, multiply 'data' by 'conversion'.","dtype":"text","value":"volts"},{"name":"conversion","doc":"Scalar to multiply each element in data to convert it to the specified 'unit'. If the data are stored in acquisition system units or other units that require a conversion to be interpretable, multiply the data by 'conversion' to convert the data to the specified 'unit'. e.g. if the data acquisition system stores values in this object as signed 16-bit integers (int16 range -32,768 to 32,767) that correspond to a 5V range (-2.5V to 2.5V), and the data acquisition system gain is 8000X, then the 'conversion' multiplier to get from raw data acquisition values to recorded volts is 2.5/32768/8000 = 9.5367e-9.","required":false,"dtype":"float32","default_value":1.0},{"name":"resolution","doc":"Smallest meaningful difference between values in data, stored in the specified by unit, 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 -1.0.","required":false,"dtype":"float32","default_value":-1.0}]}],"doc":"Stimulus voltage applied during a voltage clamp recording.","neurodata_type_inc":"PatchClampSeries","neurodata_type_def":"VoltageClampStimulusSeries","attributes":[{"name":"stimulus_description","doc":"Protocol/stimulus name for this patch-clamp dataset.","dtype":"text"},{"name":"sweep_number","doc":"Sweep number, allows to group different PatchClampSeries together.","required":false,"dtype":"uint64"},{"name":"description","doc":"Description of the time series.","required":false,"dtype":"text","default_value":"no description"},{"name":"comments","doc":"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.","required":false,"dtype":"text","default_value":"no comments"}]},{"datasets":[{"dtype":"text","name":"description","doc":"Description of electrode (e.g., whole-cell, sharp, etc.)."},{"dtype":"text","name":"filtering","doc":"Electrode specific filtering.","quantity":"?"},{"dtype":"text","name":"initial_access_resistance","doc":"Initial access resistance.","quantity":"?"},{"dtype":"text","name":"location","doc":"Location of the electrode. Specify the area, layer, comments on estimation of area/layer, stereotaxic coordinates if in vivo, etc. Use standard atlas names for anatomical regions when possible.","quantity":"?"},{"dtype":"text","name":"resistance","doc":"Electrode resistance, in ohms.","quantity":"?"},{"dtype":"text","name":"seal","doc":"Information about seal used for recording.","quantity":"?"},{"dtype":"text","name":"slice","doc":"Information about slice used for recording.","quantity":"?"}],"links":[{"name":"device","doc":"Device that was used to record from this electrode.","target_type":"Device"}],"doc":"An intracellular electrode and its metadata.","neurodata_type_inc":"NWBContainer","neurodata_type_def":"IntracellularElectrode"},{"datasets":[{"dtype":"uint64","name":"sweep_number","doc":"Sweep number of the PatchClampSeries in that row.","neurodata_type_inc":"VectorData"},{"dtype":{"target_type":"PatchClampSeries","reftype":"object"},"name":"series","doc":"The PatchClampSeries with the sweep number in that row.","neurodata_type_inc":"VectorData"},{"name":"series_index","doc":"Index for series.","neurodata_type_inc":"VectorIndex"}],"doc":"The table which groups different PatchClampSeries together.","neurodata_type_inc":"DynamicTable","neurodata_type_def":"SweepTable","attributes":[{"name":"colnames","doc":"The names of the columns in this table. This should be used to specify an order to the columns.","dtype":"ascii","shape":[null],"dims":["num_columns"]},{"name":"description","doc":"Description of what is in this dynamic table.","dtype":"text"}]}]},{"groups":[{"datasets":[{"shape":[[2],[3]],"dims":["width|height","width|height|depth"],"dtype":"float32","name":"field_of_view","doc":"Width, height and depth of image, or imaged area, in meters.","quantity":"?"}],"links":[{"name":"imaging_plane","doc":"Link to ImagingPlane object from which this TimeSeries data was generated.","target_type":"ImagingPlane"}],"doc":"Image stack recorded over time from 2-photon microscope.","neurodata_type_inc":"ImageSeries","neurodata_type_def":"TwoPhotonSeries","attributes":[{"name":"pmt_gain","doc":"Photomultiplier gain.","required":false,"dtype":"float32"},{"name":"scan_line_rate","doc":"Lines imaged per second. This is also stored in /general/optophysiology but is kept here as it is useful information for analysis, and so good to be stored w/ the actual data.","required":false,"dtype":"float32"},{"name":"description","doc":"Description of the time series.","required":false,"dtype":"text","default_value":"no description"},{"name":"comments","doc":"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.","required":false,"dtype":"text","default_value":"no comments"}]},{"datasets":[{"shape":[[null],[null,null]],"dims":[["num_times"],["num_times","num_ROIs"]],"dtype":"numeric","name":"data","doc":"Signals from ROIs.","attributes":[{"name":"conversion","doc":"Scalar to multiply each element in data to convert it to the specified 'unit'. If the data are stored in acquisition system units or other units that require a conversion to be interpretable, multiply the data by 'conversion' to convert the data to the specified 'unit'. e.g. if the data acquisition system stores values in this object as signed 16-bit integers (int16 range -32,768 to 32,767) that correspond to a 5V range (-2.5V to 2.5V), and the data acquisition system gain is 8000X, then the 'conversion' multiplier to get from raw data acquisition values to recorded volts is 2.5/32768/8000 = 9.5367e-9.","required":false,"dtype":"float32","default_value":1.0},{"name":"resolution","doc":"Smallest meaningful difference between values in data, stored in the specified by unit, 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 -1.0.","required":false,"dtype":"float32","default_value":-1.0},{"name":"unit","doc":"Base unit of measurement for working with the data. Actual stored values are not necessarily stored in these units. To access the data in these units, multiply 'data' by 'conversion'.","dtype":"text"}]},{"name":"rois","doc":"DynamicTableRegion referencing into an ROITable containing information on the ROIs stored in this timeseries.","neurodata_type_inc":"DynamicTableRegion"}],"doc":"ROI responses over an imaging plane. Each row in data should correspond to the signal from one ROI. Each element on the second dimension of data should correspond to the signal from one ROI.","neurodata_type_inc":"TimeSeries","neurodata_type_def":"RoiResponseSeries","attributes":[{"name":"description","doc":"Description of the time series.","required":false,"dtype":"text","default_value":"no description"},{"name":"comments","doc":"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.","required":false,"dtype":"text","default_value":"no comments"}]},{"groups":[{"doc":"RoiResponseSeries object(s) containing dF/F for a ROI.","quantity":"+","neurodata_type_inc":"RoiResponseSeries"}],"doc":"dF/F information about a region of interest (ROI). Storage hierarchy of dF/F should be the same as for segmentation (i.e., same names for ROIs and for image planes).","default_name":"DfOverF","neurodata_type_inc":"NWBDataInterface","neurodata_type_def":"DfOverF"},{"groups":[{"doc":"RoiResponseSeries object(s) containing fluorescence data for a ROI.","quantity":"+","neurodata_type_inc":"RoiResponseSeries"}],"doc":"Fluorescence information about a region of interest (ROI). Storage hierarchy of fluorescence should be the same as for segmentation (ie, same names for ROIs and for image planes).","default_name":"Fluorescence","neurodata_type_inc":"NWBDataInterface","neurodata_type_def":"Fluorescence"},{"groups":[{"groups":[{"groups":[{"doc":"One or more image stacks that the masks apply to (can be one-element stack).","quantity":"*","neurodata_type_inc":"ImageSeries"}],"name":"reference_images","doc":"Image stacks that the segmentation masks apply to."}],"datasets":[{"shape":[[null,null,null],[null,null,null,null]],"dims":[["num_roi","num_x","num_y"],["num_roi","num_x","num_y","num_z"]],"name":"image_mask","doc":"ROI masks for each ROI. Each image mask is the size of the original imaging plane (or volume) and members of the ROI are finite non-zero.","quantity":"?","neurodata_type_inc":"VectorData"},{"name":"pixel_mask_index","doc":"Index into pixel_mask.","quantity":"?","neurodata_type_inc":"VectorIndex"},{"dtype":[{"doc":"Pixel x-coordinate.","name":"x","dtype":"uint"},{"doc":"Pixel y-coordinate.","name":"y","dtype":"uint"},{"doc":"Weight of the pixel.","name":"weight","dtype":"float"}],"name":"pixel_mask","doc":"Pixel masks for each ROI: a list of indices and weights for the ROI. Pixel masks are concatenated and parsing of this dataset is maintained by the PlaneSegmentation","quantity":"?","neurodata_type_inc":"VectorData"},{"name":"voxel_mask_index","doc":"Index into voxel_mask.","quantity":"?","neurodata_type_inc":"VectorIndex"},{"dtype":[{"doc":"Voxel x-coordinate.","name":"x","dtype":"uint"},{"doc":"Voxel y-coordinate.","name":"y","dtype":"uint"},{"doc":"Voxel z-coordinate.","name":"z","dtype":"uint"},{"doc":"Weight of the voxel.","name":"weight","dtype":"float"}],"name":"voxel_mask","doc":"Voxel masks for each ROI: a list of indices and weights for the ROI. Voxel masks are concatenated and parsing of this dataset is maintained by the PlaneSegmentation","quantity":"?","neurodata_type_inc":"VectorData"},{"shape":[null],"dims":["num_rows"],"dtype":"int","name":"id","doc":"Array of unique identifiers for the rows of this dynamic table.","neurodata_type_inc":"ElementIdentifiers"},{"doc":"Vector columns of this dynamic table.","quantity":"*","neurodata_type_inc":"VectorData"},{"doc":"Indices for the vector columns of this dynamic table.","quantity":"*","neurodata_type_inc":"VectorIndex"}],"links":[{"name":"imaging_plane","doc":"Link to ImagingPlane object from which this data was generated.","target_type":"ImagingPlane"}],"doc":"Results from image segmentation of a specific imaging plane.","quantity":"+","neurodata_type_inc":"DynamicTable","neurodata_type_def":"PlaneSegmentation","attributes":[{"name":"colnames","doc":"The names of the columns in this table. This should be used to specify an order to the columns.","dtype":"ascii","shape":[null],"dims":["num_columns"]},{"name":"description","doc":"Description of what is in this dynamic table.","dtype":"text"}]}],"doc":"Stores pixels in an image that represent different regions of interest (ROIs) or masks. All segmentation for a given imaging plane is stored together, with storage for multiple imaging planes (masks) supported. Each ROI is stored in its own subgroup, with the ROI group containing both a 2D mask and a list of pixels that make up this mask. Segments can also be used for masking neuropil. If segmentation is allowed to change with time, a new imaging plane (or module) is required and ROI names should remain consistent between them.","default_name":"ImageSegmentation","neurodata_type_inc":"NWBDataInterface","neurodata_type_def":"ImageSegmentation"},{"groups":[{"datasets":[{"dtype":"text","name":"description","doc":"Description or other notes about the channel."},{"dtype":"float","name":"emission_lambda","doc":"Emission wavelength for channel, in nm."}],"doc":"An optical channel used to record from an imaging plane.","neurodata_type_inc":"NWBContainer","neurodata_type_def":"OpticalChannel"}],"datasets":[{"dtype":"text","name":"description","doc":"Description of the imaging plane.","quantity":"?"},{"dtype":"float","name":"excitation_lambda","doc":"Excitation wavelength, in nm."},{"dtype":"float","name":"imaging_rate","doc":"Rate that images are acquired, in Hz."},{"dtype":"text","name":"indicator","doc":"Calcium indicator."},{"dtype":"text","name":"location","doc":"Location of the imaging plane. Specify the area, layer, comments on estimation of area/layer, stereotaxic coordinates if in vivo, etc. Use standard atlas names for anatomical regions when possible."},{"shape":[[null,null,3],[null,null,null,3]],"dims":[["height","width","x|y|z"],["height","width","depth","x|y|z"]],"dtype":"float32","name":"manifold","doc":"Physical position of each pixel. 'xyz' represents the position of the pixel relative to the defined coordinate space.","quantity":"?","attributes":[{"name":"conversion","doc":"Scalar to multiply each element in data to convert it to the specified 'unit'. If the data are stored in acquisition system units or other units that require a conversion to be interpretable, multiply the data by 'conversion' to convert the data to the specified 'unit'. e.g. if the data acquisition system stores values in this object as pixels from x = -500 to 499, y = -500 to 499 that correspond to a 2 m x 2 m range, then the 'conversion' multiplier to get from raw data acquisition pixel units to meters is 2/1000.","required":false,"dtype":"float","default_value":1.0},{"name":"unit","doc":"Base unit of measurement for working with the data. The default value is 'meters'.","required":false,"dtype":"text","default_value":"meters"}]},{"dtype":"text","name":"reference_frame","doc":"Describes position and reference frame of manifold based on position of first element in manifold. For example, text description of anatomical location or vectors needed to rotate to common anatomical axis (eg, AP/DV/ML). This field is necessary to interpret manifold. If manifold is not present then this field is not required.","quantity":"?"}],"links":[{"name":"device","doc":"Link to the Device object that was used to record from this electrode.","target_type":"Device"}],"doc":"An imaging plane and its metadata.","quantity":"*","neurodata_type_inc":"NWBContainer","neurodata_type_def":"ImagingPlane"},{"groups":[{"groups":[{"name":"corrected","doc":"Image stack with frames shifted to the common coordinates.","neurodata_type_inc":"ImageSeries"},{"name":"xy_translation","doc":"Stores the x,y delta necessary to align each frame to the common coordinates, for example, to align each frame to a reference image.","neurodata_type_inc":"TimeSeries"}],"links":[{"name":"original","doc":"Link to ImageSeries object that is being registered.","target_type":"ImageSeries"}],"doc":"Reuslts from motion correction of an image stack.","quantity":"+","neurodata_type_inc":"NWBDataInterface","neurodata_type_def":"CorrectedImageStack"}],"doc":"An image stack where all frames are shifted (registered) to a common coordinate system, to account for movement and drift between frames. Note: each frame at each point in time is assumed to be 2-D (has only x & y dimensions).","default_name":"MotionCorrection","neurodata_type_inc":"NWBDataInterface","neurodata_type_def":"MotionCorrection"}]}{"groups":[{"datasets":[{"shape":[null,null],"dims":["num_rows","num_cols"],"dtype":"float32","name":"axis_1_phase_map","doc":"Phase response to stimulus on the first measured axis.","attributes":[{"name":"dimension","doc":"Number of rows and columns in the image. NOTE: row, column representation is equivalent to height,width.","dtype":"int32","shape":[null],"dims":["row_col"]},{"name":"field_of_view","doc":"Size of viewing area, in meters.","dtype":"float","shape":[null],"dims":["row|column"]},{"name":"unit","doc":"Unit that axis data is stored in (e.g., degrees).","dtype":"text"}]},{"shape":[null,null],"dims":["num_rows","num_cols"],"dtype":"float32","name":"axis_1_power_map","doc":"Power response on the first measured axis. Response is scaled so 0.0 is no power in the response and 1.0 is maximum relative power.","quantity":"?","attributes":[{"name":"dimension","doc":"Number of rows and columns in the image. NOTE: row, column representation is equivalent to height,width.","dtype":"int32","shape":[null],"dims":["row_col"]},{"name":"field_of_view","doc":"Size of viewing area, in meters.","dtype":"float","shape":[null],"dims":["row_col"]},{"name":"unit","doc":"Unit that axis data is stored in (e.g., degrees).","dtype":"text"}]},{"shape":[null,null],"dims":["num_rows","num_cols"],"dtype":"float32","name":"axis_2_phase_map","doc":"Phase response to stimulus on the second measured axis.","attributes":[{"name":"dimension","doc":"Number of rows and columns in the image. NOTE: row, column representation is equivalent to height,width.","dtype":"int32","shape":[null],"dims":["row_col"]},{"name":"field_of_view","doc":"Size of viewing area, in meters.","dtype":"float","shape":[null],"dims":["row_col"]},{"name":"unit","doc":"Unit that axis data is stored in (e.g., degrees).","dtype":"text"}]},{"shape":[null,null],"dims":["num_rows","num_cols"],"dtype":"float32","name":"axis_2_power_map","doc":"Power response on the second measured axis. Response is scaled so 0.0 is no power in the response and 1.0 is maximum relative power.","quantity":"?","attributes":[{"name":"dimension","doc":"Number of rows and columns in the image. NOTE: row, column representation is equivalent to height,width.","dtype":"int32","shape":[null],"dims":["row_col"]},{"name":"field_of_view","doc":"Size of viewing area, in meters.","dtype":"float","shape":[null],"dims":["row_col"]},{"name":"unit","doc":"Unit that axis data is stored in (e.g., degrees).","dtype":"text"}]},{"shape":[2],"dims":["names"],"dtype":"text","name":"axis_descriptions","doc":"Two-element array describing the contents of the two response axis fields. Description should be something like ['altitude', 'azimuth'] or '['radius', 'theta']."},{"shape":[null,null],"dims":["num_rows","num_cols"],"dtype":"uint16","name":"focal_depth_image","doc":"Gray-scale image taken with same settings/parameters (e.g., focal depth, wavelength) as data collection. Array format: [rows][columns].","attributes":[{"name":"bits_per_pixel","doc":"Number of bits used to represent each value. This is necessary to determine maximum (white) pixel value.","dtype":"int32"},{"name":"dimension","doc":"Number of rows and columns in the image. NOTE: row, column representation is equivalent to height,width.","dtype":"int32","shape":[null],"dims":["row_col"]},{"name":"field_of_view","doc":"Size of viewing area, in meters.","dtype":"float","shape":[null],"dims":["row_col"]},{"name":"focal_depth","doc":"Focal depth offset, in meters.","dtype":"float"},{"name":"format","doc":"Format of image. Right now only 'raw' is supported.","dtype":"text"}]},{"shape":[null,null],"dims":["num_rows","num_cols"],"dtype":"float32","name":"sign_map","doc":"Sine of the angle between the direction of the gradient in axis_1 and axis_2.","attributes":[{"name":"dimension","doc":"Number of rows and columns in the image. NOTE: row, column representation is equivalent to height,width.","dtype":"int32","shape":[null],"dims":["row_col"]},{"name":"field_of_view","doc":"Size of viewing area, in meters.","dtype":"float","shape":[null],"dims":["row_col"]}]},{"shape":[null,null],"dims":["num_rows","num_cols"],"dtype":"uint16","name":"vasculature_image","doc":"Gray-scale anatomical image of cortical surface. Array structure: [rows][columns]","attributes":[{"name":"bits_per_pixel","doc":"Number of bits used to represent each value. This is necessary to determine maximum (white) pixel value","dtype":"int32"},{"name":"dimension","doc":"Number of rows and columns in the image. NOTE: row, column representation is equivalent to height,width.","dtype":"int32","shape":[null],"dims":["row_col"]},{"name":"field_of_view","doc":"Size of viewing area, in meters.","dtype":"float","shape":[null],"dims":["row_col"]},{"name":"format","doc":"Format of image. Right now only 'raw' is supported.","dtype":"text"}]}],"doc":"Intrinsic signal optical imaging or widefield imaging for measuring retinotopy. Stores orthogonal maps (e.g., altitude/azimuth; radius/theta) of responses to specific stimuli and a combined polarity map from which to identify visual areas. Note: for data consistency, all images and arrays are stored in the format [row][column] and [row, col], which equates to [y][x]. Field of view and dimension arrays may appear backward (i.e., y before x).","default_name":"ImagingRetinotopy","neurodata_type_inc":"NWBDataInterface","neurodata_type_def":"ImagingRetinotopy"}]}q{"namespaces":[{"doc":"NWB namespace","schema":[{"namespace":"hdmf-common"},{"source":"nwb.base"},{"source":"nwb.epoch"},{"source":"nwb.image"},{"source":"nwb.file"},{"source":"nwb.misc"},{"source":"nwb.behavior"},{"source":"nwb.ecephys"},{"source":"nwb.icephys"},{"source":"nwb.ogen"},{"source":"nwb.ophys"},{"source":"nwb.retinotopy"}],"name":"core","full_name":"NWB core","version":"2.1.0","author":["Andrew Tritt","Oliver Ruebel","Ryan Ly","Ben Dichter","Keith Godfrey","Jeff Teeters"],"contact":["ajtritt@lbl.gov","oruebel@lbl.gov","rly@lbl.gov","bdichter@lbl.gov","keithg@alleninstitute.org","jteeters@berkeley.edu"]}]}2pynwb-1.2.1/tests/back_compat/1.0.2_nwbfile.nwb0000644000655200065520000003140013612200244022511 0ustar circlecicircleci00000000000000HDF  3` TREEHP/HEAP`-HhTREEHEAPXPSNOD Hh(Pp PH0XxPp TREEHEAPX P 0 TREEHEAPXP P TREE(HEAPX(presentationtemplates0TREEHEAPXPSNODhpTREEHEAPXPXxTREEHEAPXP @help=1"]x GCOL 2019-11-27T17:28:27.611843-08:00ADDMEADDME 2019-11-27T17:28:27.610392-08:00 2019-11-27T17:28:27.610392-08:00=an NWB:N file for storing cellular-based neurophysiology data2.0bcore NWBFile2"]2"]2"]acquisitionanalysisprocessingstimulusgeneralfile_create_dateidentifiersession_descriptionsession_start_timetimestamps_reference_timeSNODh*(  0 x+,8  02"] H nwb_version H namespace Hneurodata_type   pynwb-1.2.1/tests/back_compat/1.0.2_str_experimenter.nwb0000644000655200065520000003642013612200244024471 0ustar circlecicircleci00000000000000HDF  =` TREEH:HEAP`H0HhTREEHEAPXPSNOD Hh(Pp P,H0XxPp TREEHEAPX P 0 TREEHEAPXP P TREE(HEAPX(presentationtemplates0TREEHEAPXPSNODhpTREEHEAPXPXxTREE*HEAPXexperimenter@ @help=<"]GCOLone experimenter 2019-11-27T17:28:27.944667-08:00ADDMEADDME 2019-11-27T17:28:27.943534-08:00 2019-11-27T17:28:27.943534-08:00=an NWB:N file for storing cellular-based neurophysiology data2.0b core NWBFilexSNOD2"]x2"]2"]2"]acquisitionanalysisprocessingstimulusgeneralfile_create_dateidentifiersession_descriptionsession_start_timetimestamps_reference_time3"]   SNODh-(  0 x(.8/8  1 H nwb_version H namespace Hneurodata_type pynwb-1.2.1/tests/back_compat/1.0.3_nwbfile.nwb0000644000655200065520000043022013612200244022515 0ustar circlecicircleci00000000000000HDF  0` TREEHP/HEAP`- 0 .speclocpHhTREEHEAPXPSNOD Hh(Pp PH0XxPp TREEHEAPX P 0 TREEHEAPXP P TREE(HEAPX(presentationtemplates0TREEHEAPXPSNODhpTREEHEAPXPXxTREEHEAPXP @help=1:<#]x GCOL 2019-11-27T17:32:04.543292-08:00ADDMEADDME 2019-11-27T17:32:04.542259-08:00 2019-11-27T17:32:04.542259-08:00=an NWB:N file for storing cellular-based neurophysiology data2.0.2core NWBFile  {"groups":[{"datasets":[{"dtype":"float","name":"start_time","doc":"Start time of epoch, in seconds","neurodata_type_inc":"VectorData","attributes":[{"name":"description","doc":"value is 'start time of the epoch, in seconds'","dtype":"text","value":"start time of the epoch, in seconds"}]},{"dtype":"float","name":"stop_time","doc":"Stop time of epoch, in seconds","neurodata_type_inc":"VectorData","attributes":[{"name":"description","doc":"value is 'stop time of the epoch, in seconds'","dtype":"text","value":"stop time of the epoch, in seconds"}]},{"dtype":"text","name":"tags","doc":"User-defined tags that identify events. Tags are to help identify or categorize events.","quantity":"?","neurodata_type_inc":"VectorData","attributes":[{"name":"description","doc":"value is 'user-defined tags'","dtype":"text","value":"user-defined tags"}]},{"name":"tags_index","doc":"Index for tags","quantity":"?","neurodata_type_inc":"VectorIndex"},{"dtype":[{"doc":"Start index into the TimeSeries data[] field. COMMENT: This can be used to calculate location in TimeSeries timestamp[] field","name":"idx_start","dtype":"int32"},{"doc":"Number of data samples available in this time series, during this epoch.","name":"count","dtype":"int32"},{"doc":"the TimeSeries that this index applies to","name":"timeseries","dtype":{"target_type":"TimeSeries","reftype":"object"}}],"name":"timeseries","doc":"An index into a TimeSeries object","quantity":"?","neurodata_type_inc":"VectorData","attributes":[{"name":"help","doc":"Value is 'Data on how an epoch applies to a time series'","dtype":"text","value":"Data on how an epoch applies to a time series"}]},{"name":"timeseries_index","doc":"Index for timeseries","quantity":"?","neurodata_type_inc":"VectorIndex"}],"doc":"A container for aggregating epoch data and the TimeSeries that each epoch applies to","neurodata_type_inc":"DynamicTable","neurodata_type_def":"TimeIntervals","attributes":[{"name":"help","doc":"Value is 'A general epoch object'","dtype":"text","value":"A general epoch object"},{"name":"colnames","doc":"The names of the columns in this table. This should be used to specifying an order to the columns","dtype":"ascii","shape":[null],"dims":["num_columns"]},{"name":"description","doc":"Description of what is in this dynamic table","dtype":"text"}]}]}2#]2#]2#]acquisitionanalysisprocessingstimulusgeneralfile_create_dateidentifiersession_descriptionsession_start_timetimestamps_reference_timespecificationsSNODh*(  0 x+,p:<8  02#] H nwb_version H namespace Hneurodata_type P  *xF  &xBx-xx5S#8SS x]1SSUSTREE@HEAPX=coreH=?TREE DHEAPX?2.0.2HSNODX==?ACTREEp OHEAP`HwSNOD`AAC3#]GCOL8**{"datasets":[{"doc":"An abstract data type for a dataset","neurodata_type_def":"NWBData","attributes":[{"name":"help","doc":"Short description of what this type of Interface contains.","dtype":"text"}]},{"doc":"Pointers that index data values","neurodata_type_inc":"NWBData","neurodata_type_def":"Index","attributes":[{"name":"help","doc":"a help string","dtype":"text","value":"indexes into a list of values for a list of elements"},{"name":"target","doc":"the target dataset that this index applies to","dtype":{"target_type":"NWBData","reftype":"object"}}]},{"doc":"Data values indexed by pointer","neurodata_type_inc":"NWBData","neurodata_type_def":"VectorData","attributes":[{"name":"help","doc":"a help string","dtype":"text","value":"Values for a list of elements"},{"name":"description","doc":"A short description of what these vectors are","dtype":"text"}]},{"doc":"Pointers that index data values","neurodata_type_inc":"Index","neurodata_type_def":"VectorIndex","attributes":[{"name":"target","doc":"the target dataset that this index applies to","dtype":{"target_type":"VectorData","reftype":"object"}},{"name":"help","doc":"a help string","dtype":"text","value":"indexes into a list of values for a list of elements"}]},{"shape":[null],"dims":["num_elements"],"dtype":"int","doc":"a unique identifier for each element","default_name":"element_id","neurodata_type_inc":"NWBData","neurodata_type_def":"ElementIdentifiers","attributes":[{"name":"help","doc":"a help string","dtype":"text","value":"unique identifiers for a list of elements"}]},{"dtype":"int","doc":"a region/index into a DynamicTable","neurodata_type_inc":"VectorData","neurodata_type_def":"DynamicTableRegion","attributes":[{"name":"help","doc":"value is 'a subset (i.e. slice or region) of a DynamicTable'","dtype":"text","value":"a subset (i.e. slice or region) of a DynamicTable"},{"name":"table","doc":"a reference to the DynamicTable this region applies to","dtype":{"target_type":"DynamicTable","reftype":"object"}},{"name":"description","doc":"Description of what this table region points to","dtype":"text"}]},{"shape":[[null,null],[null,null,3],[null,null,4]],"dims":[["num_x","num_y"],["num_x","num_y","(r, g, b)"],["num_x","num_y","(r, g, b, a)"]],"doc":"Image base type.","neurodata_type_inc":"NWBData","neurodata_type_def":"Image","attributes":[{"name":"help","doc":"base image (use GrayscaleImage, RGBImage, RGBAImage, etc.)","dtype":"text"},{"name":"resolution","doc":"pixels / cm","required":false,"dtype":"float"},{"name":"description","doc":"description of image","required":false,"dtype":"text"}]}],"groups":[{"doc":"An abstract data type for a generic container storing collections of data and metadata. Base type for all data and metadata containers.","neurodata_type_def":"NWBContainer","attributes":[{"name":"help","doc":"Short description of what this type of NWBContainer contains.","dtype":"text"}]},{"doc":"An abstract data type for a generic container storing collections of data, as opposed to metadata.","neurodata_type_inc":"NWBContainer","neurodata_type_def":"NWBDataInterface","attributes":[{"name":"help","doc":"Short description of what this type of NWBContainer contains.","dtype":"text"}]},{"groups":[{"name":"sync","doc":"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.","quantity":"?"}],"datasets":[{"shape":[null],"dims":["num_times"],"dtype":"uint8","name":"control","doc":"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[].","quantity":"?"},{"shape":[null],"dims":["num_control_values"],"dtype":"text","name":"control_description","doc":"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.","quantity":"?"},{"shape":[[null],[null,null],[null,null,null],[null,null,null,null]],"dims":[["num_times"],["num_times","num_DIM2"],["num_times","num_DIM2","num_DIM3"],["num_times","num_DIM2","num_DIM3","num_DIM4"]],"name":"data","doc":"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":[{"name":"conversion","doc":"Scalar to multiply each element in data to convert it to the specified unit","required":false,"dtype":"float32","default_value":1.0},{"name":"resolution","doc":"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 -1.0","required":false,"dtype":"float32","default_value":0.0},{"name":"unit","doc":"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.","dtype":"text"}]},{"dtype":"float64","name":"starting_time","doc":"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.","quantity":"?","attributes":[{"name":"rate","doc":"Sampling rate, in Hz COMMENT: Rate information is stored in Hz","dtype":"float32"},{"name":"unit","doc":"Value is 'Seconds'","dtype":"text","value":"Seconds"}]},{"shape":[null],"dims":["num_times"],"dtype":"float64","name":"timestamps","doc":"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.","quantity":"?","attributes":[{"name":"interval","doc":"Value is '1'","dtype":"int32","value":1},{"name":"unit","doc":"Value is 'Seconds'","dtype":"text","value":"Seconds"}]}],"doc":"General purpose time series.","neurodata_type_inc":"NWBDataInterface","neurodata_type_def":"TimeSeries","attributes":[{"name":"comments","doc":"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.","required":false,"dtype":"text","default_value":"no comments"},{"name":"description","doc":"Description of TimeSeries","required":false,"dtype":"text","default_value":"no description"},{"name":"help","doc":"Value is 'General time series object'","dtype":"text","value":"General time series object"}]},{"groups":[{"doc":"Interface objects containing data output from processing steps","quantity":"*","neurodata_type_inc":"NWBDataInterface"}],"doc":"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.","neurodata_type_inc":"NWBContainer","neurodata_type_def":"ProcessingModule","attributes":[{"name":"description","doc":"Description of Module","dtype":"text"},{"name":"help","doc":"Value is 'A collection of analysis outputs from processing of data'","dtype":"text","value":"A collection of analysis outputs from processing of data"}]},{"datasets":[{"doc":"Images stored in this NWBDataInterface","quantity":"+","neurodata_type_inc":"Image"}],"doc":"A NWBDataInterface for storing images that have some relationship","default_name":"Images","neurodata_type_inc":"NWBDataInterface","neurodata_type_def":"Images","attributes":[{"name":"description","doc":"Description of images in this container","dtype":"text"},{"name":"help","doc":"Value is 'A collection of images that have some meaningful relationship'","dtype":"text","value":"A collection of images that have some meaningful relationship"}]},{"datasets":[{"shape":[null],"dims":["num_rows"],"dtype":"int","name":"id","doc":"The unique identifier for the rows in this dynamic table","neurodata_type_inc":"ElementIdentifiers"},{"doc":"The vector columns in this dynamic table","quantity":"*","neurodata_type_inc":"VectorData"},{"doc":"The indices for the vector columns in this dynamic table","quantity":"*","neurodata_type_inc":"VectorIndex"}],"doc":"A group containing multiple datasets that are aligned on the first dimension (Currently, this requirement if left up to APIs to check and enforce). Apart from a column that contains unique identifiers for each row there are no other required datasets. Users are free to add any number of VectorData objects here. Table functionality is already supported through compound types, which is analogous to storing an array-of-structs. DynamicTable can be thought of as a struct-of-arrays. This provides an alternative structure to choose from when optimizing storage for anticipated access patterns. Additionally, this type provides a way of creating a table without having to define a compound type up front. Although this convenience may be attractive, users should think carefully about how data will be accessed. DynamicTable is more appropriate for column-centric access, whereas a dataset with a compound type would be more appropriate for row-centric access. Finally, data size should also be taken into account. For small tables, performance loss may be an acceptable trade-off for the flexibility of a DynamicTable. For example, DynamicTable was originally developed for storing trial data and spike unit metadata. Both of these use cases are expected to produce relatively small tables, so the spatial locality of multiple datasets present in a DynamicTable is not expected to have a significant performance impact. Additionally, requirements of trial and unit metadata tables are sufficiently diverse that performance implications can be overlooked in favor of usability.","neurodata_type_inc":"NWBDataInterface","neurodata_type_def":"DynamicTable","attributes":[{"name":"help","doc":"Value is 'A column-centric table'","dtype":"text","value":"A column-centric table"},{"name":"colnames","doc":"The names of the columns in this table. This should be used to specifying an order to the columns","dtype":"ascii","shape":[null],"dims":["num_columns"]},{"name":"description","doc":"Description of what is in this dynamic table","dtype":"text"}]}]}SNODRhEX8vhKq3#] 3#]03#]@3#]P3#]nwb.basenwb.epochnwb.imagenwb.filenwb.miscnwb.behaviornwb.ecephysnwb.icephysnwb.ogennwb.ophysnwb.retinotopynamespaceGCOL@&{"datasets":[{"shape":[null,null],"dims":["y","x"],"doc":"Grayscale image","neurodata_type_inc":"Image","neurodata_type_def":"GrayscaleImage","attributes":[{"name":"help","doc":"base image (use GrayscaleImage, RGBImage, RGBAImage, etc.)","dtype":"text"},{"name":"resolution","doc":"pixels / cm","required":false,"dtype":"float"},{"name":"description","doc":"description of image","required":false,"dtype":"text"}]},{"shape":[null,null,3],"dims":["y","x","R,G,B"],"doc":"Color image","neurodata_type_inc":"Image","neurodata_type_def":"RGBImage","attributes":[{"name":"help","doc":"base image (use GrayscaleImage, RGBImage, RGBAImage, etc.)","dtype":"text"},{"name":"resolution","doc":"pixels / cm","required":false,"dtype":"float"},{"name":"description","doc":"description of image","required":false,"dtype":"text"}]},{"shape":[null,null,4],"dims":["y","x","R,G,B,A"],"doc":"Color image with transparency","neurodata_type_inc":"Image","neurodata_type_def":"RGBAImage","attributes":[{"name":"help","doc":"base image (use GrayscaleImage, RGBImage, RGBAImage, etc.)","dtype":"text"},{"name":"resolution","doc":"pixels / cm","required":false,"dtype":"float"},{"name":"description","doc":"description of image","required":false,"dtype":"text"}]}],"groups":[{"datasets":[{"shape":[[null,null,null],[null,null,null,null]],"dims":[["frame","y","x"],["frame","z","y","x"]],"dtype":"numeric","name":"data","doc":"Either binary data containing image or empty.","quantity":"?","attributes":[{"name":"conversion","doc":"Scalar to multiply each element in data to convert it to the specified unit","required":false,"dtype":"float32","default_value":1.0},{"name":"resolution","doc":"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 -1.0","required":false,"dtype":"float32","default_value":0.0},{"name":"unit","doc":"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.","dtype":"text"}]},{"shape":[null],"dims":["rank"],"dtype":"int32","name":"dimension","doc":"Number of pixels on x, y, (and z) axes.","quantity":"?"},{"shape":[null],"dims":["num_files"],"dtype":"text","name":"external_file","doc":"Path or URL to one or more external file(s). Field only present if format=external. NOTE: this is only relevant if the image is stored in the file system as one or more image file(s). This field should NOT be used if the image is stored in another HDF5 file and that file is HDF5 linked to this file.","quantity":"?","attributes":[{"name":"starting_frame","doc":"Each entry is the frame number (within the full ImageSeries) of the first frame in the corresponding external_file entry. This serves as an index to what frames each file contains, allowing random access.Zero-based indexing is used. (The first element will always be zero).","dtype":"int","shape":[null],"dims":["num_files"]}]},{"dtype":"text","name":"format","doc":"Format of image. If this is 'external' then the field external_file contains the path or URL information to that file. For tiff, png, jpg, etc, the binary representation of the image is stored in data. If the format is raw then the fields bit_per_pixel and dimension are used. For raw images, only a single channel is stored (eg, red).","quantity":"?"}],"doc":"General image data that is common between acquisition and stimulus time series. Sometimes the image data is stored in the HDF5 file in a raw format while other times it will be stored as an external image file in the host file system. The data field will either be binary data or empty. TimeSeries::data array structure: [frame] [y][x] or [frame][z][y][x].","neurodata_type_inc":"TimeSeries","neurodata_type_def":"ImageSeries","attributes":[{"name":"help","doc":"Value is 'Storage object for time-series 2-D image data'","dtype":"text","value":"Storage object for time-series 2-D image data"},{"name":"comments","doc":"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.","required":false,"dtype":"text","default_value":"no comments"},{"name":"description","doc":"Description of TimeSeries","required":false,"dtype":"text","default_value":"no description"}]},{"links":[{"name":"masked_imageseries","doc":"Link to ImageSeries that mask is applied to.","target_type":"ImageSeries"}],"doc":"An alpha mask that is applied to a presented visual stimulus. The data[] array contains an array of mask values that are applied to the displayed image. Mask values are stored as RGBA. Mask can vary with time. The timestamps array indicates the starting time of a mask, and that mask pattern continues until it's explicitly changed.","neurodata_type_inc":"ImageSeries","neurodata_type_def":"ImageMaskSeries","attributes":[{"name":"help","doc":"Value is 'An alpha mask that is applied to a presented visual stimulus'","dtype":"text","value":"An alpha mask that is applied to a presented visual stimulus"},{"name":"comments","doc":"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.","required":false,"dtype":"text","default_value":"no comments"},{"name":"description","doc":"Description of TimeSeries","required":false,"dtype":"text","default_value":"no description"}]},{"datasets":[{"dtype":"float32","name":"distance","doc":"Distance from camera/monitor to target/eye.","quantity":"?"},{"shape":[[2],[3]],"dims":[["width|height"],["width|height|depth"]],"dtype":"float32","name":"field_of_view","doc":"Width, height and depth of image, or imaged area (meters).","quantity":"?"},{"dtype":"text","name":"orientation","doc":"Description of image relative to some reference frame (e.g., which way is up). Must also specify frame of reference.","quantity":"?"}],"doc":"Image data that is presented or recorded. A stimulus template movie will be stored only as an image. When the image is presented as stimulus, additional data is required, such as field of view (eg, how much of the visual field the image covers, or how what is the area of the target being imaged). If the OpticalSeries represents acquired imaging data, orientation is also important.","neurodata_type_inc":"ImageSeries","neurodata_type_def":"OpticalSeries","attributes":[{"name":"help","doc":"Value is 'Time-series image stack for optical recording or stimulus'","dtype":"text","value":"Time-series image stack for optical recording or stimulus"},{"name":"comments","doc":"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.","required":false,"dtype":"text","default_value":"no comments"},{"name":"description","doc":"Description of TimeSeries","required":false,"dtype":"text","default_value":"no description"}]},{"datasets":[{"shape":[null],"dims":["num_times"],"dtype":"int","name":"data","doc":"Index of the frame in the referenced ImageSeries.","attributes":[{"name":"conversion","doc":"Scalar to multiply each element in data to convert it to the specified unit","required":false,"dtype":"float32","default_value":1.0},{"name":"resolution","doc":"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 -1.0","required":false,"dtype":"float32","default_value":0.0},{"name":"unit","doc":"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.","dtype":"text"}]}],"links":[{"name":"indexed_timeseries","doc":"HDF5 link to TimeSeries containing images that are indexed.","target_type":"ImageSeries"}],"doc":"Stores indices to image frames stored in an ImageSeries. The purpose of the ImageIndexSeries 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 ImageSeries, and the timestamps array indicates when that image was displayed.","neurodata_type_inc":"TimeSeries","neurodata_type_def":"IndexSeries","attributes":[{"name":"help","doc":"Value is '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'","dtype":"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"},{"name":"comments","doc":"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.","required":false,"dtype":"text","default_value":"no comments"},{"name":"description","doc":"Description of TimeSeries","required":false,"dtype":"text","default_value":"no description"}]}]}B{"groups":[{"groups":[{"groups":[{"doc":"Any objects representing acquired data","quantity":"*","neurodata_type_inc":"NWBDataInterface"}],"name":"acquisition","doc":"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."},{"groups":[{"doc":"Custom analysis results","quantity":"*","neurodata_type_inc":"NWBContainer"}],"name":"analysis","doc":"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 could be shared with other labs."},{"groups":[{"doc":"Intermediate analysis of acquired data","quantity":"*","neurodata_type_inc":"ProcessingModule"}],"name":"processing","doc":"The home for ProcessingModules. 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."},{"groups":[{"groups":[{"doc":"TimeSeries objects containing data of presented stimuli","quantity":"*","neurodata_type_inc":"TimeSeries"}],"name":"presentation","doc":"Stimuli presented during the experiment."},{"groups":[{"doc":"TimeSeries objects containing template data of presented stimuli","quantity":"*","neurodata_type_inc":"TimeSeries"}],"name":"templates","doc":"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."}],"name":"stimulus","doc":"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."},{"groups":[{"doc":"place-holder than can be extended so that lab-specific meta-data can be placed in /general","quantity":"*","neurodata_type_inc":"NWBContainer","neurodata_type_def":"LabMetaData","attributes":[{"name":"help","doc":"Short description of what this type of NWBContainer contains.","dtype":"text"}]},{"groups":[{"doc":"One of possibly many. Information about device and device description.","quantity":"+","neurodata_type_inc":"NWBContainer","neurodata_type_def":"Device","attributes":[{"name":"help","doc":"Value is 'A recording device e.g. amplifier'.","dtype":"text","value":"A recording device e.g. amplifier"}]}],"name":"devices","doc":"Description of hardware devices used during experiment. COMMENT: Eg, monitors, ADC boards, microscopes, etc","quantity":"?"},{"datasets":[{"dtype":"text","name":"age","doc":"Age of subject","quantity":"?"},{"dtype":"isodatetime","name":"date_of_birth","doc":"can be supplied instead of age","quantity":"?"},{"dtype":"text","name":"description","doc":"Description of subject and where subject came from (e.g., breeder, if animal).","quantity":"?"},{"dtype":"text","name":"genotype","doc":"Genetic strain COMMENT: If absent, assume Wild Type (WT)","quantity":"?"},{"dtype":"text","name":"sex","doc":"Gender of subject","quantity":"?"},{"dtype":"text","name":"species","doc":"Species of subject","quantity":"?"},{"dtype":"text","name":"subject_id","doc":"ID of animal/person used/participating in experiment (lab convention)","quantity":"?"},{"dtype":"text","name":"weight","doc":"Weight at time of experiment, at time of surgery and at other important times","quantity":"?"}],"name":"subject","doc":"Information about the animal or person from which the data was measured.","quantity":"?","neurodata_type_inc":"NWBContainer","neurodata_type_def":"Subject","attributes":[{"name":"help","doc":"Value is 'Information about the subject'","dtype":"text","value":"Information about the subject"}]},{"groups":[{"doc":"One of possibly many groups, one for each electrode group.","quantity":"*","neurodata_type_inc":"ElectrodeGroup"},{"datasets":[{"dtype":"float","name":"x","doc":"the x coordinate of the channel location","neurodata_type_inc":"VectorData","attributes":[{"name":"description","doc":"value is 'the x coordinate of the channel location'","dtype":"text","value":"the x coordinate of the channel location"}]},{"dtype":"float","name":"y","doc":"the y coordinate of the channel location","neurodata_type_inc":"VectorData","attributes":[{"name":"description","doc":"value is 'the y coordinate of the channel location'","dtype":"text","value":"the y coordinate of the channel location"}]},{"dtype":"float","name":"z","doc":"the z coordinate of the channel location","neurodata_type_inc":"VectorData","attributes":[{"name":"description","doc":"value is 'the z coordinate of the channel location'","dtype":"text","value":"the z coordinate of the channel location"}]},{"dtype":"float","name":"imp","doc":"the impedance of the channel","neurodata_type_inc":"VectorData","attributes":[{"name":"description","doc":"value is 'the impedance of the channel'","dtype":"text","value":"the impedance of the channel"}]},{"dtype":"ascii","name":"location","doc":"the location of channel within the subject e.g. brain region","neurodata_type_inc":"VectorData","attributes":[{"name":"description","doc":"value is 'the location of channel within the subject e.g. brain region'","dtype":"text","value":"the location of channel within the subject e.g. brain region"}]},{"dtype":"float","name":"filtering","doc":"description of hardware filtering","neurodata_type_inc":"VectorData","attributes":[{"name":"description","doc":"value is 'description of hardware filtering'","dtype":"text","value":"description of hardware filtering"}]},{"dtype":{"target_type":"ElectrodeGroup","reftype":"object"},"name":"group","doc":"a reference to the ElectrodeGroup this electrode is a part of","neurodata_type_inc":"VectorData","attributes":[{"name":"description","doc":"value is 'a reference to the ElectrodeGroup this electrode is a part of'","dtype":"text","value":"a reference to the ElectrodeGroup this electrode is a part of"}]},{"dtype":"ascii","name":"group_name","doc":"name of the ElectrodeGroup this electrode is a part of","neurodata_type_inc":"VectorData","attributes":[{"name":"description","doc":"value is 'the name of the ElectrodeGroup this electrode is a part of'","dtype":"text","value":"the name of the ElectrodeGroup this electrode is a part of"}]}],"name":"electrodes","doc":"A table of all electrodes (i.e. channels) used for recording.","quantity":"?","neurodata_type_inc":"DynamicTable"}],"name":"extracellular_ephys","doc":"Metadata related to extracellular electrophysiology.","quantity":"?"},{"groups":[{"doc":"One of possibly many. COMMENT: Name should be informative.","quantity":"*","neurodata_type_inc":"IntracellularElectrode"},{"name":"sweep_table","doc":"The table which groups different PatchClampSeries together.","quantity":"?","neurodata_type_inc":"SweepTable"}],"datasets":[{"dtype":"text","name":"filtering","doc":"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.","quantity":"?"}],"name":"intracellular_ephys","doc":"Metadata related to intracellular electrophysiology","quantity":"?"},{"groups":[{"doc":"One of possibly many groups describing an optogenetic stimulation site. COMMENT: Name is arbitrary but should be meaningful. Name is referenced by OptogeneticSeries.","quantity":"*","neurodata_type_inc":"OptogeneticStimulusSite"}],"name":"optogenetics","doc":"Metadata describing optogenetic stimuluation","quantity":"?"},{"groups":[{"doc":"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.","quantity":"*","neurodata_type_inc":"ImagingPlane"}],"name":"optophysiology","doc":"Metadata related to optophysiology.","quantity":"?"}],"datasets":[{"dtype":"text","name":"data_collection","doc":"Notes about data collection and analysis.COMMENT: Can be from Methods","quantity":"?"},{"dtype":"text","name":"experiment_description","doc":"General description of the experiment.COMMENT: Can be from Methods","quantity":"?"},{"dtype":"text","name":"experimenter","doc":"Name of person who performed the experiment.COMMENT: More than one person OK. Can specify roles of different people involved.","quantity":"?"},{"dtype":"text","name":"institution","doc":"Institution(s) where experiment was performed","quantity":"?"},{"shape":[null],"dims":["num_keywords"],"dtype":"text","name":"keywords","doc":"Terms to search over","quantity":"?"},{"dtype":"text","name":"lab","doc":"Lab where experiment was performed","quantity":"?"},{"dtype":"text","name":"notes","doc":"Notes about the experiment. COMMENT: Things particular to this experiment","quantity":"?"},{"dtype":"text","name":"pharmacology","doc":"Description of drugs used, including how and when they were administered. COMMENT: Anesthesia(s), painkiller(s), etc., plus dosage, concentration, etc.","quantity":"?"},{"dtype":"text","name":"protocol","doc":"Experimental protocol, if applicable. COMMENT: E.g., include IACUC protocol.","quantity":"?"},{"dtype":"text","name":"related_publications","doc":"Publication information. COMMENT: PMID, DOI, URL, etc. If multiple, concatenate together and describe which is which. such as PMID, DOI, URL, etc","quantity":"?"},{"dtype":"text","name":"session_id","doc":"Lab-specific ID for the session.COMMENT: Only 1 session_id per file, with all time aligned to experiment start time.","quantity":"?"},{"dtype":"text","name":"slices","doc":"Description of slices, including information about preparation thickness, orientation, temperature and bath solution","quantity":"?"},{"dtype":"text","name":"source_script","doc":"Script file used to create this NWB file.","quantity":"?","attributes":[{"name":"file_name","doc":"Name of script file","dtype":"text"}]},{"dtype":"text","name":"stimulus","doc":"Notes about stimuli, such as how and where presented. COMMENT: Can be from Methods.","quantity":"?"},{"dtype":"text","name":"surgery","doc":"Narrative description about surgery/surgeries, including date(s) and who performed surgery. COMMENT: Much can be copied from Methods.","quantity":"?"},{"dtype":"text","name":"virus","doc":"Information about virus(es) used in experiments, including virus ID, source, date made, injection location, volume, etc.","quantity":"?"}],"name":"general","doc":"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 (e.g., 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. 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."},{"groups":[{"name":"epochs","doc":"divisions in time marking experimental stages or sub-divisions of a single recording session","quantity":"?","neurodata_type_inc":"TimeIntervals"},{"name":"trials","doc":"repeated experimental events that have a logical grouping","quantity":"?","neurodata_type_inc":"TimeIntervals"},{"name":"invalid_times","doc":"time intervals that should be removed from analysis","quantity":"?","neurodata_type_inc":"TimeIntervals"},{"doc":"an optional additional table for describing other experimental time intervals","quantity":"*","neurodata_type_inc":"TimeIntervals"}],"name":"intervals","doc":"Experimental intervals, whether that be logically distinct sub-experiments having a particular scientific goal, trials (see trials subgroup) during an experiment, or epochs (see epochs subgroup) deriving from analysis of data.","quantity":"?"},{"name":"units","doc":"Data about units","quantity":"?","neurodata_type_inc":"Units"}],"datasets":[{"shape":[null],"dims":["num_modifications"],"dtype":"isodatetime","name":"file_create_date","doc":"A record of the date the file was created and of subsequent modifications. COMMENT: - The date is stored in UTC with local timezone offset as ISO 8601 extended formatted strings: 2018-09-28T14:43:54.123+02:00 - Dates stored in UTC end in \"Z\" with no timezone offset. - Date accuracy is up to milliseconds. - The file can be created after the experiment was run, so this may differ from the experiment start time. - Each modification to the nwb file adds a new entry to the array."},{"dtype":"text","name":"identifier","doc":"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."},{"dtype":"text","name":"session_description","doc":"One or two sentences describing the experiment and data in the file."},{"dtype":"isodatetime","name":"session_start_time","doc":"Date and time of the experiment/session start. COMMENT: - The date is stored in UTC with local timezone offset as ISO 8601 extended formatted string: 2018-09-28T14:43:54.123+02:00 - Dates stored in UTC end in \"Z\" with no timezone offset. - Date accuracy is up to milliseconds."},{"dtype":"isodatetime","name":"timestamps_reference_time","doc":"Date and time corresponding to time zero of all timestamps. COMMENT: - The date is stored in UTC with local timezone offset as ISO 8601 extended formatted string: 2018-09-28T14:43:54.123+02:00 - Dates stored in UTC end in \"Z\" with no timezone offset. - Date accuracy is up to milliseconds. - All times stored in the file use this time as reference (ie, time zero)."}],"name":"root","doc":"Top level of NWB file.","neurodata_type_inc":"NWBContainer","neurodata_type_def":"NWBFile","attributes":[{"name":"help","doc":"Value is 'an NWB:N file for storing cellular-based neurophysiology data'","dtype":"text","value":"an NWB:N file for storing cellular-based neurophysiology data"},{"name":"nwb_version","doc":"File version string. COMMENT: Eg, NWB-1.0.0. This will be the name of the format with trailing major, minor and patch numbers.","dtype":"text","value":"2.0.2"}]}]}-{"groups":[{"datasets":[{"shape":[[null],[null,null]],"dims":[["num_times"],["num_times","num_features"]],"dtype":"numeric","name":"data","doc":"Values of each feature at each time.","attributes":[{"name":"unit","doc":"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.","required":false,"dtype":"text","default_value":"see 'feature_units'"},{"name":"conversion","doc":"Scalar to multiply each element in data to convert it to the specified unit","required":false,"dtype":"float32","default_value":1.0},{"name":"resolution","doc":"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 -1.0","required":false,"dtype":"float32","default_value":0.0}]},{"shape":[null],"dims":["num_features"],"dtype":"text","name":"feature_units","doc":"Units of each feature.","quantity":"?"},{"shape":[null],"dims":["num_features"],"dtype":"text","name":"features","doc":"Description of the features represented in TimeSeries::data."}],"doc":"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.","neurodata_type_inc":"TimeSeries","neurodata_type_def":"AbstractFeatureSeries","attributes":[{"name":"help","doc":"Value is 'Features of an applied stimulus. This is useful when storing the raw stimulus is impractical'","dtype":"text","value":"Features of an applied stimulus. This is useful when storing the raw stimulus is impractical"},{"name":"comments","doc":"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.","required":false,"dtype":"text","default_value":"no comments"},{"name":"description","doc":"Description of TimeSeries","required":false,"dtype":"text","default_value":"no description"}]},{"datasets":[{"shape":[null],"dims":["num_times"],"dtype":"text","name":"data","doc":"Annotations made during an experiment.","attributes":[{"name":"resolution","doc":"Value is -1.0","dtype":"float","value":-1.0},{"name":"unit","doc":"Value is 'n/a'","dtype":"text","value":"n/a"},{"name":"conversion","doc":"Scalar to multiply each element in data to convert it to the specified unit","required":false,"dtype":"float32","default_value":1.0}]}],"doc":"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.","neurodata_type_inc":"TimeSeries","neurodata_type_def":"AnnotationSeries","attributes":[{"name":"help","doc":"Value is 'Time-stamped annotations about an experiment'","dtype":"text","value":"Time-stamped annotations about an experiment"},{"name":"comments","doc":"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.","required":false,"dtype":"text","default_value":"no comments"},{"name":"description","doc":"Description of TimeSeries","required":false,"dtype":"text","default_value":"no description"}]},{"datasets":[{"shape":[null],"dims":["num_times"],"dtype":"int8","name":"data","doc":">0 if interval started, <0 if interval ended.","attributes":[{"name":"resolution","doc":"Value is -1.0","dtype":"float","value":-1.0},{"name":"unit","doc":"Value is 'n/a'","dtype":"text","value":"n/a"},{"name":"conversion","doc":"Scalar to multiply each element in data to convert it to the specified unit","required":false,"dtype":"float32","default_value":1.0}]}],"doc":"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.","neurodata_type_inc":"TimeSeries","neurodata_type_def":"IntervalSeries","attributes":[{"name":"help","doc":"Value is 'Stores the start and stop times for events'","dtype":"text","value":"Stores the start and stop times for events"},{"name":"comments","doc":"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.","required":false,"dtype":"text","default_value":"no comments"},{"name":"description","doc":"Description of TimeSeries","required":false,"dtype":"text","default_value":"no description"}]},{"groups":[{"datasets":[{"dtype":"text","name":"band_name","doc":"the name of the band e.g. theta","neurodata_type_inc":"VectorData","attributes":[{"name":"description","doc":"value is 'the name of the band e.g. theta'","dtype":"text","value":"the name of the band e.g. theta"}]},{"shape":[null,2],"dims":["num_bands","low, high"],"dtype":"float","name":"band_limits","doc":"Low and high limit of each band in Hz. If it is a Gaussian filter, use 2 SD on either side of the center","neurodata_type_inc":"VectorData","attributes":[{"name":"description","doc":"value is 'Low and high limit of each band in Hz. If it is a Gaussian filter, use 2 SD on either side of the center'","dtype":"text","value":"Low and high limit of each band in Hz. If it is a Gaussian filter, use 2 SD on either side of the center"}]},{"shape":[null],"dims":["num_bands"],"dtype":"float","name":"band_mean","doc":"The mean Gaussian filters in Hz","neurodata_type_inc":"VectorData","attributes":[{"name":"description","doc":"The mean Gaussian filters in Hz","dtype":"text","value":"The mean Gaussian filters in Hz"}]},{"shape":[null],"dims":["num_bands"],"dtype":"float","name":"band_stdev","doc":"The standard devaition of Gaussian filters in Hz","neurodata_type_inc":"VectorData","attributes":[{"name":"description","doc":"The standard devaition of Gaussian filters in Hz","dtype":"text","value":"The standard devaition of Gaussian filters in Hz"}]}],"name":"bands","doc":"A table for describing the bands that this series was generated from. There should be one row in this table for each band","neurodata_type_inc":"DynamicTable"}],"datasets":[{"shape":[null,null,null],"dims":["num_times","num_channels","num_bands"],"dtype":"numeric","name":"data","doc":"The data goes here","attributes":[{"name":"conversion","doc":"Scalar to multiply each element in data to convert it to the specified unit","required":false,"dtype":"float32","default_value":1.0},{"name":"resolution","doc":"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 -1.0","required":false,"dtype":"float32","default_value":0.0},{"name":"unit","doc":"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.","dtype":"text"}]},{"dtype":"text","name":"metric","doc":"recommended: phase, amplitude, power"}],"links":[{"name":"source_timeseries","doc":"HDF5 link to TimesSeries that this data was calculated from. Metadata about electrodes and their position can be read from that ElectricalSeries so it is not necessary to store that information here","target_type":"TimeSeries","quantity":"?"}],"doc":"Holds spectral analysis of a timeseries. For instance of LFP or a speech signal","neurodata_type_inc":"TimeSeries","neurodata_type_def":"DecompositionSeries","attributes":[{"name":"comments","doc":"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.","required":false,"dtype":"text","default_value":"no comments"},{"name":"description","doc":"Description of TimeSeries","required":false,"dtype":"text","default_value":"no description"},{"name":"help","doc":"Value is 'General time series object'","dtype":"text","value":"General time series object"}]},{"datasets":[{"name":"spike_times_index","doc":"the index into the spike_times dataset","quantity":"?","neurodata_type_inc":"VectorIndex"},{"dtype":"double","name":"spike_times","doc":"the spike times for each unit","quantity":"?","neurodata_type_inc":"VectorData"},{"name":"obs_intervals_index","doc":"the index into the obs_intervals dataset","quantity":"?","neurodata_type_inc":"VectorIndex"},{"shape":[null,2],"dims":["num_intervals","start|end"],"dtype":"double","name":"obs_intervals","doc":"the observation intervals for each unit","quantity":"?","neurodata_type_inc":"VectorData"},{"name":"electrodes_index","doc":"the index into electrodes","quantity":"?","neurodata_type_inc":"VectorIndex"},{"name":"electrodes","doc":"the electrode that each spike unit came from","quantity":"?","neurodata_type_inc":"DynamicTableRegion"},{"dtype":{"target_type":"ElectrodeGroup","reftype":"object"},"name":"electrode_group","doc":"the electrode group that each spike unit came from","quantity":"?","neurodata_type_inc":"VectorData"},{"shape":[[null,null],[null,null,null]],"dims":[["num_units","num_samples"],["num_units","num_samples","num_electrodes"]],"dtype":"float","name":"waveform_mean","doc":"the spike waveform mean for each spike unit","quantity":"?","neurodata_type_inc":"VectorData"},{"shape":[[null,null],[null,null,null]],"dims":[["num_units","num_samples"],["num_units","num_samples","num_electrodes"]],"dtype":"float","name":"waveform_sd","doc":"the spike waveform standard deviation for each spike unit","quantity":"?","neurodata_type_inc":"VectorData"}],"doc":"Data about spiking units. Event times of observed units (e.g. cell, synapse, etc.) should be concatenated and stored in spike_times.","default_name":"Units","neurodata_type_inc":"DynamicTable","neurodata_type_def":"Units","attributes":[{"name":"help","doc":"Value is 'Data about spiking units'","dtype":"text","value":"Data about spiking units"},{"name":"colnames","doc":"The names of the columns in this table. This should be used to specifying an order to the columns","dtype":"ascii","shape":[null],"dims":["num_columns"]},{"name":"description","doc":"Description of what is in this dynamic table","dtype":"text"}]}]}{"groups":[{"datasets":[{"shape":[[null],[null,null]],"dims":[["num_times"],["num_times","num_features"]],"dtype":"numeric","name":"data","doc":"2-D array storing position or direction relative to some reference frame.","attributes":[{"name":"unit","doc":"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.","required":false,"dtype":"text","default_value":"meter"},{"name":"conversion","doc":"Scalar to multiply each element in data to convert it to the specified unit","required":false,"dtype":"float32","default_value":1.0},{"name":"resolution","doc":"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 -1.0","required":false,"dtype":"float32","default_value":0.0}]},{"dtype":"text","name":"reference_frame","doc":"Description defining what exactly 'straight-ahead' means.","quantity":"?"}],"doc":"Direction, e.g., of gaze or travel, or position. The TimeSeries::data field is a 2D array storing position or direction relative to some reference frame. Array structure: [num measurements] [num dimensions]. Each SpatialSeries has a text dataset reference_frame that indicates the zero-position, or the zero-axes for direction. For example, if representing gaze direction, 'straight-ahead' might be a specific pixel on the monitor, or some other point in space. For position data, the 0,0 point might be the top-left corner of an enclosure, as viewed from the tracking camera. The unit of data will indicate how to interpret SpatialSeries values.","neurodata_type_inc":"TimeSeries","neurodata_type_def":"SpatialSeries","attributes":[{"name":"help","doc":"Value is: Stores points in space over time. The data[] array structure is [num samples][num spatial dimensions]","dtype":"text","value":"Stores points in space over time. The data[] array structure is [num samples][num spatial dimensions]"},{"name":"comments","doc":"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.","required":false,"dtype":"text","default_value":"no comments"},{"name":"description","doc":"Description of TimeSeries","required":false,"dtype":"text","default_value":"no description"}]},{"groups":[{"doc":"IntervalSeries object containing start and stop times of epochs","quantity":"*","neurodata_type_inc":"IntervalSeries"}],"doc":"TimeSeries for storing behavioral epochs. The objective of this and the other two Behavioral interfaces (e.g. BehavioralEvents and BehavioralTimeSeries) is to provide generic hooks for software tools/scripts. This allows a tool/script to take the output one specific interface (e.g., UnitTimes) and plot that data relative to another data modality (e.g., behavioral events) without having to define all possible modalities in advance. Declaring one of these interfaces means that one or more TimeSeries of the specified type is published. These TimeSeries should reside in a group having the same name as the interface. For example, if a BehavioralTimeSeries interface is declared, the module will have one or more TimeSeries defined in the module sub-group 'BehavioralTimeSeries'. BehavioralEpochs should use IntervalSeries. BehavioralEvents is used for irregular events. BehavioralTimeSeries is for continuous data.","default_name":"BehavioralEpochs","neurodata_type_inc":"NWBDataInterface","neurodata_type_def":"BehavioralEpochs","attributes":[{"name":"help","doc":"Value is 'General container for storing behavioral epochs'","dtype":"text","value":"General container for storing behavioral epochs"}]},{"groups":[{"doc":"TimeSeries object containing irregular behavioral events","quantity":"*","neurodata_type_inc":"TimeSeries"}],"doc":"TimeSeries for storing behavioral events. See description of BehavioralEpochs for more details.","default_name":"BehavioralEvents","neurodata_type_inc":"NWBDataInterface","neurodata_type_def":"BehavioralEvents","attributes":[{"name":"help","doc":"Value is 'Position data, whether along the x, xy or xyz axis'","dtype":"text","value":"Position data, whether along the x, xy or xyz axis"}]},{"groups":[{"doc":"TimeSeries object containing continuous behavioral data","quantity":"*","neurodata_type_inc":"TimeSeries"}],"doc":"TimeSeries for storing Behavoioral time series data.See description of BehavioralEpochs for more details.","default_name":"BehavioralTimeSeries","neurodata_type_inc":"NWBDataInterface","neurodata_type_def":"BehavioralTimeSeries","attributes":[{"name":"help","doc":"Value is 'General container for storing continuously sampled behavioral data.'","dtype":"text","value":"General container for storing continuously sampled behavioral data."}]},{"groups":[{"doc":"TimeSeries object containing time series data on pupil size","quantity":"+","neurodata_type_inc":"TimeSeries"}],"doc":"Eye-tracking data, representing pupil size.","default_name":"PupilTracking","neurodata_type_inc":"NWBDataInterface","neurodata_type_def":"PupilTracking","attributes":[{"name":"help","doc":"Value is 'Eye-tracking data, representing pupil size'","dtype":"text","value":"Eye-tracking data, representing pupil size"}]},{"groups":[{"doc":"SpatialSeries object containing data measuring direction of gaze","quantity":"*","neurodata_type_inc":"SpatialSeries"}],"doc":"Eye-tracking data, representing direction of gaze.","default_name":"EyeTracking","neurodata_type_inc":"NWBDataInterface","neurodata_type_def":"EyeTracking","attributes":[{"name":"help","doc":"Value is 'Eye-tracking data, representing direction of gaze'","dtype":"text","value":"Eye-tracking data, representing direction of gaze"}]},{"groups":[{"doc":"SpatialSeries object containing direction of gaze travel","quantity":"*","neurodata_type_inc":"SpatialSeries"}],"doc":"With a CompassDirection interface, a module publishes a SpatialSeries object representing a floating point value for theta. The SpatialSeries::reference_frame field should indicate what direction corresponds to 0 and which is the direction of rotation (this should be clockwise). The si_unit for the SpatialSeries should be radians or degrees.","default_name":"CompassDirection","neurodata_type_inc":"NWBDataInterface","neurodata_type_def":"CompassDirection","attributes":[{"name":"help","doc":"Value is 'Direction as measured radially. Spatial series reference frame should indicate which direction corresponds to zero and what is the direction of positive rotation'","dtype":"text","value":"Direction as measured radially. Spatial series reference frame should indicate which direction corresponds to zero and what is the direction of positive rotation"}]},{"groups":[{"doc":"SpatialSeries object containing position data","quantity":"+","neurodata_type_inc":"SpatialSeries"}],"doc":"Position data, whether along the x, x/y or x/y/z axis.","default_name":"Position","neurodata_type_inc":"NWBDataInterface","neurodata_type_def":"Position","attributes":[{"name":"help","doc":"Value is 'Position data, whether along the x, xy or xyz axis'","dtype":"text","value":"Position data, whether along the x, xy or xyz axis"}]}]}S {"groups":[{"datasets":[{"shape":[null],"dims":["num_times"],"dtype":"numeric","name":"data","doc":"Applied power for optogenetic stimulus.","attributes":[{"name":"unit","doc":"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.","required":false,"dtype":"text","default_value":"watt"},{"name":"conversion","doc":"Scalar to multiply each element in data to convert it to the specified unit","required":false,"dtype":"float32","default_value":1.0},{"name":"resolution","doc":"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 -1.0","required":false,"dtype":"float32","default_value":0.0}]}],"links":[{"name":"site","doc":"link to OptogeneticStimulusSite group that describes the site to which this stimulus was applied","target_type":"OptogeneticStimulusSite"}],"doc":"Optogenetic stimulus. The data[] field is in unit of watts.","neurodata_type_inc":"TimeSeries","neurodata_type_def":"OptogeneticSeries","attributes":[{"name":"help","doc":"Value is 'Optogenetic stimulus'","dtype":"text","value":"Optogenetic stimulus"},{"name":"comments","doc":"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.","required":false,"dtype":"text","default_value":"no comments"},{"name":"description","doc":"Description of TimeSeries","required":false,"dtype":"text","default_value":"no description"}]},{"datasets":[{"dtype":"text","name":"description","doc":"Description of site"},{"dtype":"float","name":"excitation_lambda","doc":"Excitation wavelength in nm"},{"dtype":"text","name":"location","doc":"Location of stimulation site"}],"links":[{"name":"device","doc":"Device that generated the stimulus","target_type":"Device"}],"doc":"One of possibly many groups describing an optogenetic stimulation site. COMMENT: Name is arbitrary but should be meaningful. Name is referenced by OptogeneticSeries","quantity":"*","neurodata_type_inc":"NWBContainer","neurodata_type_def":"OptogeneticStimulusSite","attributes":[{"name":"help","doc":"Value is 'Metadata about an optogenetic stimulus site'","dtype":"text","value":"Metadata about an optogenetic stimulus site"}]}]}`3#]p3#]3#]SNOD8txM(sH(uNhPxQ3#]3#]3#]GCOL5{"groups":[{"datasets":[{"shape":[[null],[null,null],[null,null,null]],"dims":[["num_times"],["num_times","num_channels"],["num_times","num_channels","num_samples"]],"dtype":"numeric","name":"data","doc":"Recorded voltage data.","attributes":[{"name":"unit","doc":"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.","required":false,"dtype":"text","default_value":"volt"},{"name":"conversion","doc":"Scalar to multiply each element in data to convert it to the specified unit","required":false,"dtype":"float32","default_value":1.0},{"name":"resolution","doc":"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 -1.0","required":false,"dtype":"float32","default_value":0.0}]},{"name":"electrodes","doc":"the electrodes that this series was generated from","neurodata_type_inc":"DynamicTableRegion"}],"doc":"Stores acquired voltage data from extracellular recordings. The data field of an ElectricalSeries is an int or float array storing data in Volts. TimeSeries::data array structure: :blue:`[num times] [num channels] (or [num_times] for single electrode).`","neurodata_type_inc":"TimeSeries","neurodata_type_def":"ElectricalSeries","attributes":[{"name":"help","doc":"Value is 'Stores acquired voltage data from extracellular recordings'","dtype":"text","value":"Stores acquired voltage data from extracellular recordings"},{"name":"comments","doc":"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.","required":false,"dtype":"text","default_value":"no comments"},{"name":"description","doc":"Description of TimeSeries","required":false,"dtype":"text","default_value":"no description"}]},{"datasets":[{"shape":[[null,null],[null,null,null]],"dims":[["num_events","num_samples"],["num_events","num_channels","num_samples"]],"dtype":"numeric","name":"data","doc":"Spike waveforms.","attributes":[{"name":"unit","doc":"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.","required":false,"dtype":"text","default_value":"volt"},{"name":"conversion","doc":"Scalar to multiply each element in data to convert it to the specified unit","required":false,"dtype":"float32","default_value":1.0},{"name":"resolution","doc":"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 -1.0","required":false,"dtype":"float32","default_value":0.0}]},{"shape":[null],"dims":["num_times"],"dtype":"float64","name":"timestamps","doc":"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. This is added here so that the timestamps is required for SpikeEventTimes.","attributes":[{"name":"interval","doc":"Value is '1'","dtype":"int32","value":1},{"name":"unit","doc":"Value is 'Seconds'","dtype":"text","value":"Seconds"}]}],"doc":"Stores 'snapshots' of spike events (i.e., threshold crossings) in data. This may also be raw data, as reported by ephys hardware. If so, the TimeSeries::description field should describing how events were detected. All SpikeEventSeries should reside in a module (under EventWaveform interface) even if the spikes were reported and stored by hardware. All events span the same recording channels and store snapshots of equal duration. TimeSeries::data array structure: [num events] [num channels] [num samples] (or [num events] [num samples] for single electrode).","neurodata_type_inc":"ElectricalSeries","neurodata_type_def":"SpikeEventSeries","attributes":[{"name":"help","doc":"Value is 'Snapshots of spike events from data.'","dtype":"text","value":"Snapshots of spike events from data."},{"name":"comments","doc":"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.","required":false,"dtype":"text","default_value":"no comments"},{"name":"description","doc":"Description of TimeSeries","required":false,"dtype":"text","default_value":"no description"}]},{"datasets":[{"dtype":"text","name":"waveform_filtering","doc":"Filtering applied to data before generating mean/sd"},{"shape":[null,null],"dims":["num_clusters","num_samples"],"dtype":"float32","name":"waveform_mean","doc":"The mean waveform for each cluster, using the same indices for each wave as cluster numbers in the associated Clustering module (i.e, cluster 3 is in array slot [3]). Waveforms corresponding to gaps in cluster sequence should be empty (e.g., zero- filled)"},{"shape":[null,null],"dims":["num_clusters","num_samples"],"dtype":"float32","name":"waveform_sd","doc":"Stdev of waveforms for each cluster, using the same indices as in mean"}],"links":[{"name":"clustering_interface","doc":"HDF5 link to Clustering interface that was the source of the clustered data","target_type":"Clustering"}],"doc":"DEPRECATED The mean waveform shape, including standard deviation, of the different clusters. Ideally, the waveform analysis should be performed on data that is only high-pass filtered. This is a separate module because it is expected to require updating. For example, IMEC probes may require different storage requirements to store/display mean waveforms, requiring a new interface or an extension of this one.","default_name":"ClusterWaveforms","neurodata_type_inc":"NWBDataInterface","neurodata_type_def":"ClusterWaveforms","attributes":[{"name":"help","doc":"Value is 'Mean waveform shape of clusters. Waveforms should be high-pass filtered (ie, not the same bandpass filter used waveform analysis and clustering)'","dtype":"text","value":"DEPRECATED Mean waveform shape of clusters. Waveforms should be high-pass filtered (ie, not the same bandpass filter used waveform analysis and clustering)"}]},{"datasets":[{"dtype":"text","name":"description","doc":"Description of clusters or clustering, (e.g. cluster 0 is noise, clusters curated using Klusters, etc)"},{"shape":[null],"dims":["num_events"],"dtype":"int32","name":"num","doc":"Cluster number of each event"},{"shape":[null],"dims":["num_clusters"],"dtype":"float32","name":"peak_over_rms","doc":"Maximum ratio of waveform peak to RMS on any channel in the cluster (provides a basic clustering metric)."},{"shape":[null],"dims":["num_events"],"dtype":"float64","name":"times","doc":"Times of clustered events, in seconds. This may be a link to times field in associated FeatureExtraction module."}],"doc":"DEPRECATED Clustered spike data, whether from automatic clustering tools (e.g., klustakwik) or as a result of manual sorting.","default_name":"Clustering","neurodata_type_inc":"NWBDataInterface","neurodata_type_def":"Clustering","attributes":[{"name":"help","doc":"Value is 'Clustered spike data, whether from automatic clustering tools (eg, klustakwik) or as a result of manual sorting'","dtype":"text","value":"DEPRECATED Clustered spike data, whether from automatic clustering tools (eg, klustakwik) or as a result of manual sorting"}]},{"datasets":[{"shape":[null],"dims":["num_features"],"dtype":"text","name":"description","doc":"Description of features (eg, ''PC1'') for each of the extracted features."},{"shape":[null,null,null],"dims":["num_events","num_channels","num_features"],"dtype":"float32","name":"features","doc":"Multi-dimensional array of features extracted from each event."},{"shape":[null],"dims":["num_events"],"dtype":"float64","name":"times","doc":"Times of events that features correspond to (can be a link)."},{"name":"electrodes","doc":"the electrodes that this series was generated from","neurodata_type_inc":"DynamicTableRegion"}],"doc":"Features, such as PC1 and PC2, that are extracted from signals stored in a SpikeEvent TimeSeries or other source.","default_name":"FeatureExtraction","neurodata_type_inc":"NWBDataInterface","neurodata_type_def":"FeatureExtraction","attributes":[{"name":"help","doc":"Value is 'Container for salient features of detected events'","dtype":"text","value":"Container for salient features of detected events"}]},{"datasets":[{"dtype":"text","name":"detection_method","doc":"Description of how events were detected, such as voltage threshold, or dV/dT threshold, as well as relevant values."},{"shape":[null],"dims":["num_events"],"dtype":"int32","name":"source_idx","doc":"Indices (zero-based) into source ElectricalSeries::data array corresponding to time of event. Module description should define what is meant by time of event (e.g., .25msec before action potential peak, zero-crossing time, etc). The index points to each event from the raw data"},{"shape":[null],"dims":["num_events"],"dtype":"float64","name":"times","doc":"Timestamps of events, in Seconds","attributes":[{"name":"unit","doc":"The string ''Seconds''","required":false,"dtype":"text","default_value":"Seconds"}]}],"links":[{"name":"source_electricalseries","doc":"HDF5 link to ElectricalSeries that this data was calculated from. Metadata about electrodes and their position can be read from that ElectricalSeries so it's not necessary to mandate that information be stored here","target_type":"ElectricalSeries"}],"doc":"Detected spike events from voltage trace(s).","default_name":"EventDetection","neurodata_type_inc":"NWBDataInterface","neurodata_type_def":"EventDetection","attributes":[{"name":"help","doc":"Value is 'Detected spike events from voltage trace(s)'","dtype":"text","value":"Detected spike events from voltage trace(s)"}]},{"groups":[{"doc":"SpikeEventSeries object containing detected spike event waveforms","quantity":"*","neurodata_type_inc":"SpikeEventSeries"}],"doc":"Represents either the waveforms of detected events, as extracted from a raw data trace in /acquisition, or the event waveforms that were stored during experiment acquisition.","default_name":"EventWaveform","neurodata_type_inc":"NWBDataInterface","neurodata_type_def":"EventWaveform","attributes":[{"name":"help","doc":"Value is 'Waveform of detected extracellularly recorded spike events'","dtype":"text","value":"Waveform of detected extracellularly recorded spike events"}]},{"groups":[{"doc":"ElectricalSeries object containing filtered electrophysiology data","quantity":"+","neurodata_type_inc":"ElectricalSeries"}],"doc":"Ephys data from one or more channels that has been subjected to filtering. Examples of filtered data include Theta and Gamma (LFP has its own interface). FilteredEphys modules publish an ElectricalSeries for each filtered channel or set of channels. The name of each ElectricalSeries is arbitrary but should be informative. The source of the filtered data, whether this is from analysis of another time series or as acquired by hardware, should be noted in each's TimeSeries::description field. There is no assumed 1::1 correspondence between filtered ephys signals and electrodes, as a single signal can apply to many nearby electrodes, and one electrode may have different filtered (e.g., theta and/or gamma) signals represented.","default_name":"FilteredEphys","neurodata_type_inc":"NWBDataInterface","neurodata_type_def":"FilteredEphys","attributes":[{"name":"help","doc":"Value is 'Ephys data from one or more channels that is subjected to filtering, such as for gamma or theta oscillations (LFP has its own interface). Filter properties should be noted in the ElectricalSeries'","dtype":"text","value":"Ephys data from one or more channels that is subjected to filtering, such as for gamma or theta oscillations (LFP has its own interface). Filter properties should be noted in the ElectricalSeries"}]},{"groups":[{"doc":"ElectricalSeries object containing LFP data for one or more channels","quantity":"+","neurodata_type_inc":"ElectricalSeries"}],"doc":"LFP data from one or more channels. The electrode map in each published ElectricalSeries will identify which channels are providing LFP data. Filter properties should be noted in the ElectricalSeries description or comments field.","default_name":"LFP","neurodata_type_inc":"NWBDataInterface","neurodata_type_def":"LFP","attributes":[{"name":"help","doc":"Value is 'LFP data from one or more channels. Filter properties should be noted in the ElectricalSeries'","dtype":"text","value":"LFP data from one or more channels. Filter properties should be noted in the ElectricalSeries"}]},{"links":[{"name":"device","doc":"the device that was used to record from this electrode group","target_type":"Device","quantity":"?"}],"doc":"One of possibly many groups, one for each electrode group.","neurodata_type_inc":"NWBContainer","neurodata_type_def":"ElectrodeGroup","attributes":[{"name":"help","doc":"Value is 'Metadata about a physical grouping of channels'","dtype":"text","value":"A physical grouping of channels"},{"name":"description","doc":"description of this electrode group","dtype":"text"},{"name":"location","doc":"description of location of this electrode group","dtype":"text"}]}]}#8{"groups":[{"datasets":[{"shape":[null],"dims":["num_times"],"dtype":"numeric","name":"data","doc":"Recorded voltage or current.","attributes":[{"name":"conversion","doc":"Scalar to multiply each element in data to convert it to the specified unit","required":false,"dtype":"float32","default_value":1.0},{"name":"resolution","doc":"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 -1.0","required":false,"dtype":"float32","default_value":0.0},{"name":"unit","doc":"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.","dtype":"text"}]},{"dtype":"float","name":"gain","doc":"Units: Volt/Amp (v-clamp) or Volt/Volt (c-clamp)","quantity":"?"}],"links":[{"name":"electrode","doc":"link to IntracellularElectrode group that describes th electrode that was used to apply or record this data","target_type":"IntracellularElectrode"}],"doc":"Stores stimulus or response current or voltage. Superclass definition for patch-clamp data (this class should not be instantiated directly).","neurodata_type_inc":"TimeSeries","neurodata_type_def":"PatchClampSeries","attributes":[{"name":"help","doc":"Value is 'Superclass definition for patch-clamp data'","dtype":"text","value":"Superclass definition for patch-clamp data"},{"name":"stimulus_description","doc":"the protocol/stimulus name for this patch-clamp dataset","dtype":"text"},{"name":"sweep_number","doc":"Sweep number, allows to group different PatchClampSeries together.","required":false,"dtype":"uint64"},{"name":"comments","doc":"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.","required":false,"dtype":"text","default_value":"no comments"},{"name":"description","doc":"Description of TimeSeries","required":false,"dtype":"text","default_value":"no description"}]},{"datasets":[{"dtype":"float32","name":"bias_current","doc":"Unit: Amp","quantity":"?"},{"dtype":"float32","name":"bridge_balance","doc":"Unit: Ohm","quantity":"?"},{"dtype":"float32","name":"capacitance_compensation","doc":"Unit: Farad","quantity":"?"}],"doc":"Stores voltage data recorded from intracellular current-clamp recordings. A corresponding CurrentClampStimulusSeries (stored separately as a stimulus) is used to store the current injected.","neurodata_type_inc":"PatchClampSeries","neurodata_type_def":"CurrentClampSeries","attributes":[{"name":"help","doc":"Value is 'Voltage recorded from cell during current-clamp recording'","dtype":"text","value":"Voltage recorded from cell during current-clamp recording"},{"name":"stimulus_description","doc":"the protocol/stimulus name for this patch-clamp dataset","dtype":"text"},{"name":"sweep_number","doc":"Sweep number, allows to group different PatchClampSeries together.","required":false,"dtype":"uint64"},{"name":"comments","doc":"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.","required":false,"dtype":"text","default_value":"no comments"},{"name":"description","doc":"Description of TimeSeries","required":false,"dtype":"text","default_value":"no description"}]},{"doc":"Stores recorded voltage data from intracellular recordings when all current and amplifier settings are off (i.e., CurrentClampSeries fields will be zero). There is no CurrentClampStimulusSeries associated with an IZero series because the amplifier is disconnected and no stimulus can reach the cell.","neurodata_type_inc":"CurrentClampSeries","neurodata_type_def":"IZeroClampSeries","attributes":[{"name":"help","doc":"Value is 'Voltage from intracellular recordings when all current and amplifier settings are off'","dtype":"text","value":"Voltage from intracellular recordings when all current and amplifier settings are off"},{"name":"stimulus_description","doc":"the protocol/stimulus name for this patch-clamp dataset","dtype":"text"},{"name":"sweep_number","doc":"Sweep number, allows to group different PatchClampSeries together.","required":false,"dtype":"uint64"},{"name":"comments","doc":"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.","required":false,"dtype":"text","default_value":"no comments"},{"name":"description","doc":"Description of TimeSeries","required":false,"dtype":"text","default_value":"no description"}]},{"doc":"Aliases to standard PatchClampSeries. Its functionality is to better tag PatchClampSeries for machine (and human) readability of the file.","neurodata_type_inc":"PatchClampSeries","neurodata_type_def":"CurrentClampStimulusSeries","attributes":[{"name":"help","doc":"Value is 'Stimulus current applied during current clamp recording'","dtype":"text","value":"Stimulus current applied during current clamp recording"},{"name":"stimulus_description","doc":"the protocol/stimulus name for this patch-clamp dataset","dtype":"text"},{"name":"sweep_number","doc":"Sweep number, allows to group different PatchClampSeries together.","required":false,"dtype":"uint64"},{"name":"comments","doc":"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.","required":false,"dtype":"text","default_value":"no comments"},{"name":"description","doc":"Description of TimeSeries","required":false,"dtype":"text","default_value":"no description"}]},{"datasets":[{"dtype":"float32","name":"capacitance_fast","doc":"Unit: Farad","quantity":"?","attributes":[{"name":"unit","doc":"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.","required":false,"dtype":"text","default_value":"Farad"}]},{"dtype":"float32","name":"capacitance_slow","doc":"Unit: Farad","quantity":"?","attributes":[{"name":"unit","doc":"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.","required":false,"dtype":"text","default_value":"Farad"}]},{"dtype":"float32","name":"resistance_comp_bandwidth","doc":"Unit: Hz","quantity":"?","attributes":[{"name":"unit","doc":"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.","required":false,"dtype":"text","default_value":"Hz"}]},{"dtype":"float32","name":"resistance_comp_correction","doc":"Unit: %","quantity":"?","attributes":[{"name":"unit","doc":"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.","required":false,"dtype":"text","default_value":"percent"}]},{"dtype":"float32","name":"resistance_comp_prediction","doc":"Unit: %","quantity":"?","attributes":[{"name":"unit","doc":"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.","required":false,"dtype":"text","default_value":"percent"}]},{"dtype":"float32","name":"whole_cell_capacitance_comp","doc":"Unit: Farad","quantity":"?","attributes":[{"name":"unit","doc":"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.","required":false,"dtype":"text","default_value":"Farad"}]},{"dtype":"float32","name":"whole_cell_series_resistance_comp","doc":"Unit: Ohm","quantity":"?","attributes":[{"name":"unit","doc":"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.","required":false,"dtype":"text","default_value":"Ohm"}]}],"doc":"Stores current data recorded from intracellular voltage-clamp recordings. A corresponding VoltageClampStimulusSeries (stored separately as a stimulus) is used to store the voltage injected.","neurodata_type_inc":"PatchClampSeries","neurodata_type_def":"VoltageClampSeries","attributes":[{"name":"help","doc":"Value is 'Current recorded from cell during voltage-clamp recording'","dtype":"text","value":"Current recorded from cell during voltage-clamp recording"},{"name":"stimulus_description","doc":"the protocol/stimulus name for this patch-clamp dataset","dtype":"text"},{"name":"sweep_number","doc":"Sweep number, allows to group different PatchClampSeries together.","required":false,"dtype":"uint64"},{"name":"comments","doc":"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.","required":false,"dtype":"text","default_value":"no comments"},{"name":"description","doc":"Description of TimeSeries","required":false,"dtype":"text","default_value":"no description"}]},{"doc":"Aliases to standard PatchClampSeries. Its functionality is to better tag PatchClampSeries for machine (and human) readability of the file.","neurodata_type_inc":"PatchClampSeries","neurodata_type_def":"VoltageClampStimulusSeries","attributes":[{"name":"help","doc":"Value is 'Stimulus voltage applied during voltage clamp recording'","dtype":"text","value":"Stimulus voltage applied during voltage clamp recording"},{"name":"stimulus_description","doc":"the protocol/stimulus name for this patch-clamp dataset","dtype":"text"},{"name":"sweep_number","doc":"Sweep number, allows to group different PatchClampSeries together.","required":false,"dtype":"uint64"},{"name":"comments","doc":"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.","required":false,"dtype":"text","default_value":"no comments"},{"name":"description","doc":"Description of TimeSeries","required":false,"dtype":"text","default_value":"no description"}]},{"datasets":[{"dtype":"text","name":"description","doc":"Recording description, description of electrode (e.g., whole-cell, sharp, etc)COMMENT: Free-form text (can be from Methods)"},{"dtype":"text","name":"filtering","doc":"Electrode specific filtering.","quantity":"?"},{"dtype":"text","name":"initial_access_resistance","doc":"Initial access resistance","quantity":"?"},{"dtype":"text","name":"location","doc":"Area, layer, comments on estimation, stereotaxis coordinates (if in vivo, etc)","quantity":"?"},{"dtype":"text","name":"resistance","doc":"Electrode resistance COMMENT: unit: Ohm","quantity":"?"},{"dtype":"text","name":"seal","doc":"Information about seal used for recording","quantity":"?"},{"dtype":"text","name":"slice","doc":"Information about slice used for recording","quantity":"?"}],"links":[{"name":"device","doc":"the device that was used to record from this electrode","target_type":"Device"}],"doc":"One of possibly many. COMMENT: Name should be informative.","neurodata_type_inc":"NWBContainer","neurodata_type_def":"IntracellularElectrode","attributes":[{"name":"help","doc":"Value is 'Metadata about an intracellular electrode'","dtype":"text","value":"Metadata about an intracellular electrode"}]},{"datasets":[{"dtype":"uint64","name":"sweep_number","doc":"The sweep number of the PatchClampSeries in that row.","neurodata_type_inc":"VectorData","attributes":[{"name":"description","doc":"value is 'The sweep number of the PatchClampSeries in that row'","dtype":"text","value":"The sweep number of the PatchClampSeries in that row"}]},{"dtype":{"target_type":"PatchClampSeries","reftype":"object"},"name":"series","doc":"The PatchClampSeries with the sweep number in that row","neurodata_type_inc":"VectorData","attributes":[{"name":"help","doc":"Value is 'The PatchClampSeries with the sweep number in that row'","dtype":"text","value":"The PatchClampSeries with the sweep number in that row"}]},{"name":"series_index","doc":"Index for series","neurodata_type_inc":"VectorIndex"}],"doc":"The table which groups different PatchClampSeries together.","neurodata_type_inc":"DynamicTable","neurodata_type_def":"SweepTable","attributes":[{"name":"help","doc":"Value is 'The table which groups different PatchClampSeries together'","dtype":"text","value":"The table which groups different PatchClampSeries together"},{"name":"colnames","doc":"The names of the columns in this table. This should be used to specifying an order to the columns","dtype":"ascii","shape":[null],"dims":["num_columns"]},{"name":"description","doc":"Description of what is in this dynamic table","dtype":"text"}]}]}]1{"groups":[{"datasets":[{"shape":[[2],[3]],"dims":["width|height","width|height|depth"],"dtype":"float32","name":"field_of_view","doc":"Width, height and depth of image, or imaged area (meters).","quantity":"?"}],"links":[{"name":"imaging_plane","doc":"link to ImagingPlane group from which this TimeSeries data was generated","target_type":"ImagingPlane"}],"doc":"A special case of optical imaging.","neurodata_type_inc":"ImageSeries","neurodata_type_def":"TwoPhotonSeries","attributes":[{"name":"help","doc":"Value is 'Image stack recorded from 2-photon microscope'","dtype":"text","value":"Image stack recorded from 2-photon microscope"},{"name":"pmt_gain","doc":"Photomultiplier gain","required":false,"dtype":"float32"},{"name":"scan_line_rate","doc":"Lines imaged per second. This is also stored in /general/optophysiology but is kept here as it is useful information for analysis, and so good to be stored w/ the actual data.","required":false,"dtype":"float32"},{"name":"comments","doc":"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.","required":false,"dtype":"text","default_value":"no comments"},{"name":"description","doc":"Description of TimeSeries","required":false,"dtype":"text","default_value":"no description"}]},{"datasets":[{"shape":[[null],[null,null]],"dims":[["num_times"],["num_times","num_ROIs"]],"dtype":"numeric","name":"data","doc":"Signals from ROIs","attributes":[{"name":"conversion","doc":"Scalar to multiply each element in data to convert it to the specified unit","required":false,"dtype":"float32","default_value":1.0},{"name":"resolution","doc":"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 -1.0","required":false,"dtype":"float32","default_value":0.0},{"name":"unit","doc":"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.","dtype":"text"}]},{"name":"rois","doc":"a dataset referencing into an ROITable containing information on the ROIs stored in this timeseries","neurodata_type_inc":"DynamicTableRegion"}],"doc":"ROI responses over an imaging plane. Each row in data[] should correspond to the signal from one ROI.","neurodata_type_inc":"TimeSeries","neurodata_type_def":"RoiResponseSeries","attributes":[{"name":"help","doc":"Value is 'ROI responses over an imaging plane. Each element on the second dimension of data[] should correspond to the signal from one ROI'","dtype":"text","value":"ROI responses over an imaging plane. Each element on the second dimension of data[] should correspond to the signal from one ROI"},{"name":"comments","doc":"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.","required":false,"dtype":"text","default_value":"no comments"},{"name":"description","doc":"Description of TimeSeries","required":false,"dtype":"text","default_value":"no description"}]},{"groups":[{"doc":"RoiResponseSeries object containing dF/F for a ROI","quantity":"+","neurodata_type_inc":"RoiResponseSeries"}],"doc":"dF/F information about a region of interest (ROI). Storage hierarchy of dF/F should be the same as for segmentation (ie, same names for ROIs and for image planes).","default_name":"DfOverF","neurodata_type_inc":"NWBDataInterface","neurodata_type_def":"DfOverF","attributes":[{"name":"help","doc":"Value is 'Df/f over time of one or more ROIs. TimeSeries names should correspond to imaging plane names'","dtype":"text","value":"Df/f over time of one or more ROIs. TimeSeries names should correspond to imaging plane names"}]},{"groups":[{"doc":"RoiResponseSeries object containing fluorescence data for a ROI","quantity":"+","neurodata_type_inc":"RoiResponseSeries"}],"doc":"Fluorescence information about a region of interest (ROI). Storage hierarchy of fluorescence should be the same as for segmentation (ie, same names for ROIs and for image planes).","default_name":"Fluorescence","neurodata_type_inc":"NWBDataInterface","neurodata_type_def":"Fluorescence","attributes":[{"name":"help","doc":"Value is 'Fluorescence over time of one or more ROIs. TimeSeries names should correspond to imaging plane names'","dtype":"text","value":"Fluorescence over time of one or more ROIs. TimeSeries names should correspond to imaging plane names"}]},{"groups":[{"groups":[{"groups":[{"doc":"One or more image stacks that the masks apply to (can be one-element stack)","quantity":"*","neurodata_type_inc":"ImageSeries"}],"name":"reference_images","doc":"Stores image stacks segmentation mask apply to."}],"datasets":[{"shape":[[null,null,null],[null,null,null,null]],"dims":[["num_roi","num_x","num_y"],["num_roi","num_x","num_y","num_z"]],"name":"image_mask","doc":"ROI masks for each ROI. Each image mask is the size of the original imaging plane (or volume) and members of the ROI are finite non-zero","quantity":"?","neurodata_type_inc":"VectorData"},{"name":"pixel_mask_index","doc":"index into pixel_mask","quantity":"?","neurodata_type_inc":"VectorIndex"},{"dtype":[{"doc":"the pixel x-coordinate","name":"x","dtype":"uint"},{"doc":"the pixel y-coordinate","name":"y","dtype":"uint"},{"doc":"the weight of the pixel","name":"weight","dtype":"float"}],"name":"pixel_mask","doc":"Pixel masks for each ROI: a list of indices and weights for the ROI. Pixel masks are concatenated and parsing of this dataset is maintained by the PlaneSegmentation","quantity":"?","neurodata_type_inc":"VectorData"},{"name":"voxel_mask_index","doc":"index into voxel_mask","quantity":"?","neurodata_type_inc":"VectorIndex"},{"dtype":[{"doc":"the voxel x-coordinate","name":"x","dtype":"uint"},{"doc":"the voxel y-coordinate","name":"y","dtype":"uint"},{"doc":"the voxel y-coordinate","name":"z","dtype":"uint"},{"doc":"the weight of the voxel","name":"weight","dtype":"float"}],"name":"voxel_mask","doc":"Voxel masks for each ROI: a list of indices and weights for the ROI. Voxel masks are concatenated and parsing of this dataset is maintained by the PlaneSegmentation","quantity":"?","neurodata_type_inc":"VectorData"},{"shape":[null],"dims":["num_rows"],"dtype":"int","name":"id","doc":"The unique identifier for the rows in this dynamic table","neurodata_type_inc":"ElementIdentifiers"},{"doc":"The vector columns in this dynamic table","quantity":"*","neurodata_type_inc":"VectorData"},{"doc":"The indices for the vector columns in this dynamic table","quantity":"*","neurodata_type_inc":"VectorIndex"}],"links":[{"name":"imaging_plane","doc":"link to ImagingPlane group from which this TimeSeries data was generated","target_type":"ImagingPlane"}],"doc":"results for image segmentation of a specific imaging plane","quantity":"+","neurodata_type_inc":"DynamicTable","neurodata_type_def":"PlaneSegmentation","attributes":[{"name":"help","doc":"Value is 'Results from segmentation of an imaging plane'","dtype":"text","value":"Results from segmentation of an imaging plane"},{"name":"colnames","doc":"The names of the columns in this table. This should be used to specifying an order to the columns","dtype":"ascii","shape":[null],"dims":["num_columns"]},{"name":"description","doc":"Description of what is in this dynamic table","dtype":"text"}]}],"doc":"Stores pixels in an image that represent different regions of interest (ROIs) or masks. All segmentation for a given imaging plane is stored together, with storage for multiple imaging planes (masks) supported. Each ROI is stored in its own subgroup, with the ROI group containing both a 2D mask and a list of pixels that make up this mask. Segments can also be used for masking neuropil. If segmentation is allowed to change with time, a new imaging plane (or module) is required and ROI names should remain consistent between them.","default_name":"ImageSegmentation","neurodata_type_inc":"NWBDataInterface","neurodata_type_def":"ImageSegmentation","attributes":[{"name":"help","doc":"Value is 'Stores groups of pixels that define regions of interest from one or more imaging planes'","dtype":"text","value":"Stores groups of pixels that define regions of interest from one or more imaging planes"}]},{"groups":[{"datasets":[{"dtype":"text","name":"description","doc":"Any notes or comments about the channel"},{"dtype":"float","name":"emission_lambda","doc":"Emission wavelength for channel in nm"}],"doc":"One of possibly many groups storing channel-specific data COMMENT: Name is arbitrary but should be meaningful","neurodata_type_inc":"NWBContainer","neurodata_type_def":"OpticalChannel","attributes":[{"name":"help","doc":"Value is 'Metadata about an optical channel used to record from an imaging plane'","dtype":"text","value":"Metadata about an optical channel used to record from an imaging plane"}]}],"datasets":[{"dtype":"text","name":"description","doc":"Description of image_plane_X","quantity":"?"},{"dtype":"float","name":"excitation_lambda","doc":"Excitation wavelength in nm"},{"dtype":"float","name":"imaging_rate","doc":"Rate images are acquired, in Hz."},{"dtype":"text","name":"indicator","doc":"Calcium indicator"},{"dtype":"text","name":"location","doc":"Location of image plane"},{"shape":[[null,null,3],[null,null,null,3]],"dims":[["height","width","x|y|z"],["height","width","depth","x|y|z"]],"dtype":"float32","name":"manifold","doc":"Physical position of each pixel. COMMENT: 'xyz' represents the position of the pixel relative to the defined coordinate space","quantity":"?","attributes":[{"name":"conversion","doc":"Multiplier to get from stored values to specified unit (e.g., 1e-3 for millimeters)","required":false,"dtype":"float","default_value":1.0},{"name":"unit","doc":"Base unit that coordinates are stored in (e.g., Meters)","required":false,"dtype":"text","default_value":"Meter"}]},{"dtype":"text","name":"reference_frame","doc":"Describes position and reference frame of manifold based on position of first element in manifold. For example, text description of anatomical location or vectors needed to rotate to common anatomical axis (eg, AP/DV/ML). COMMENT: This field is necessary to interpret manifold. If manifold is not present then this field is not required","quantity":"?"}],"links":[{"name":"device","doc":"the device that was used to record from this electrode","target_type":"Device"}],"doc":"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","quantity":"*","neurodata_type_inc":"NWBContainer","neurodata_type_def":"ImagingPlane","attributes":[{"name":"help","doc":"Value is 'Metadata about an imaging plane'","dtype":"text","value":"Metadata about an imaging plane"}]},{"groups":[{"groups":[{"name":"corrected","doc":"Image stack with frames shifted to the common coordinates.","neurodata_type_inc":"ImageSeries"},{"name":"xy_translation","doc":"Stores the x,y delta necessary to align each frame to the common coordinates, for example, to align each frame to a reference image.","neurodata_type_inc":"TimeSeries"}],"links":[{"name":"original","doc":"HDF5 Link to image series that is being registered.","target_type":"ImageSeries"}],"doc":"One of possibly many. Name should be informative.","quantity":"+","neurodata_type_inc":"NWBDataInterface","neurodata_type_def":"CorrectedImageStack","attributes":[{"name":"help","doc":"Value is 'Reuslts from motion correction of an image stack'","dtype":"text","value":"Reuslts from motion correction of an image stack"}]}],"doc":"An image stack where all frames are shifted (registered) to a common coordinate system, to account for movement and drift between frames. Note: each frame at each point in time is assumed to be 2-D (has only x & y dimensions).","default_name":"MotionCorrection","neurodata_type_inc":"NWBDataInterface","neurodata_type_def":"MotionCorrection","attributes":[{"name":"help","doc":"Value is 'Image stacks whose frames have been shifted (registered) to account for motion'","dtype":"text","value":"Image stacks whose frames have been shifted (registered) to account for motion"}]}]}{"groups":[{"datasets":[{"shape":[null,null],"dims":["num_rows","num_cols"],"dtype":"float32","name":"axis_1_phase_map","doc":"Phase response to stimulus on the first measured axis","attributes":[{"name":"dimension","doc":"Number of rows and columns in the image. NOTE: row, column representation is equivalent to height,width.","dtype":"int32","shape":[null],"dims":["row_col"]},{"name":"field_of_view","doc":"Size of viewing area, in meters","dtype":"float","shape":[null],"dims":["row|column"]},{"name":"unit","doc":"Unit that axis data is stored in (e.g., degrees)","dtype":"text"}]},{"shape":[null,null],"dims":["num_rows","num_cols"],"dtype":"float32","name":"axis_1_power_map","doc":"Power response on the first measured axis. Response is scaled so 0.0 is no power in the response and 1.0 is maximum relative power.","quantity":"?","attributes":[{"name":"dimension","doc":"Number of rows and columns in the image. NOTE: row, column representation is equivalent to height,width.","dtype":"int32","shape":[null],"dims":["row_col"]},{"name":"field_of_view","doc":"Size of viewing area, in meters","dtype":"float","shape":[null],"dims":["row_col"]},{"name":"unit","doc":"Unit that axis data is stored in (e.g., degrees)","dtype":"text"}]},{"shape":[null,null],"dims":["num_rows","num_cols"],"dtype":"float32","name":"axis_2_phase_map","doc":"Phase response to stimulus on the second measured axis","attributes":[{"name":"dimension","doc":"Number of rows and columns in the image. NOTE: row, column representation is equivalent to height,width.","dtype":"int32","shape":[null],"dims":["row_col"]},{"name":"field_of_view","doc":"Size of viewing area, in meters","dtype":"float","shape":[null],"dims":["row_col"]},{"name":"unit","doc":"Unit that axis data is stored in (e.g., degrees)","dtype":"text"}]},{"shape":[null,null],"dims":["num_rows","num_cols"],"dtype":"float32","name":"axis_2_power_map","doc":"Power response on the second measured axis. Response is scaled so 0.0 is no power in the response and 1.0 is maximum relative power.","quantity":"?","attributes":[{"name":"dimension","doc":"Number of rows and columns in the image. NOTE: row, column representation is equivalent to height,width.","dtype":"int32","shape":[null],"dims":["row_col"]},{"name":"field_of_view","doc":"Size of viewing area, in meters","dtype":"float","shape":[null],"dims":["row_col"]},{"name":"unit","doc":"Unit that axis data is stored in (e.g., degrees)","dtype":"text"}]},{"shape":[null],"dims":["2"],"dtype":"text","name":"axis_descriptions","doc":"Two-element array describing the contents of the two response axis fields. Description should be something like ['altitude', 'azimuth'] or '['radius', 'theta']"},{"shape":[null,null],"dims":["num_rows","num_cols"],"dtype":"uint16","name":"focal_depth_image","doc":"Gray-scale image taken with same settings/parameters (e.g., focal depth, wavelength) as data collection. Array format: [rows][columns]","attributes":[{"name":"bits_per_pixel","doc":"Number of bits used to represent each value. This is necessary to determine maximum (white) pixel value","dtype":"int32"},{"name":"dimension","doc":"Number of rows and columns in the image. NOTE: row, column representation is equivalent to height,width.","dtype":"int32","shape":[null],"dims":["row_col"]},{"name":"field_of_view","doc":"Size of viewing area, in meters","dtype":"float","shape":[null],"dims":["row_col"]},{"name":"focal_depth","doc":"Focal depth offset, in meters","dtype":"float"},{"name":"format","doc":"Format of image. Right now only 'raw' supported","dtype":"text"}]},{"shape":[null,null],"dims":["num_rows","num_cols"],"dtype":"float32","name":"sign_map","doc":"Sine of the angle between the direction of the gradient in axis_1 and axis_2","attributes":[{"name":"dimension","doc":"Number of rows and columns in the image. NOTE: row, column representation is equivalent to height,width.","dtype":"int32","shape":[null],"dims":["row_col"]},{"name":"field_of_view","doc":"Size of viewing area, in meters.","dtype":"float","shape":[null],"dims":["row_col"]}]},{"shape":[null,null],"dims":["num_rows","num_cols"],"dtype":"uint16","name":"vasculature_image","doc":"Gray-scale anatomical image of cortical surface. Array structure: [rows][columns]","attributes":[{"name":"bits_per_pixel","doc":"Number of bits used to represent each value. This is necessary to determine maximum (white) pixel value","dtype":"int32"},{"name":"dimension","doc":"Number of rows and columns in the image. NOTE: row, column representation is equivalent to height,width.","dtype":"int32","shape":[null],"dims":["row_col"]},{"name":"field_of_view","doc":"Size of viewing area, in meters","dtype":"float","shape":[null],"dims":["row_col"]},{"name":"format","doc":"Format of image. Right now only 'raw' supported","dtype":"text"}]}],"doc":"Intrinsic signal optical imaging or widefield imaging for measuring retinotopy. Stores orthogonal maps (e.g., altitude/azimuth; radius/theta) of responses to specific stimuli and a combined polarity map from which to identify visual areas.
Note: for data consistency, all images and arrays are stored in the format [row][column] and [row, col], which equates to [y][x]. Field of view and dimension arrays may appear backward (i.e., y before x).","default_name":"ImagingRetinotopy","neurodata_type_inc":"NWBDataInterface","neurodata_type_def":"ImagingRetinotopy","attributes":[{"name":"help","doc":"Value is 'Intrinsic signal optical imaging or Widefield imaging for measuring retinotopy'","dtype":"text","value":"Intrinsic signal optical imaging or Widefield imaging for measuring retinotopy"}]}]}U{"namespaces":[{"doc":"NWB namespace","schema":[{"source":"nwb.base"},{"source":"nwb.epoch"},{"source":"nwb.image"},{"source":"nwb.file"},{"source":"nwb.misc"},{"source":"nwb.behavior"},{"source":"nwb.ecephys"},{"source":"nwb.icephys"},{"source":"nwb.ogen"},{"source":"nwb.ophys"},{"source":"nwb.retinotopy"}],"name":"core","full_name":"NWB core","version":"2.0.2","author":["Andrew Tritt","Oliver Ruebel","Ryan Ly","Ben Dichter","Keith Godfrey","Jeff Teeters"],"contact":["ajtritt@lbl.gov","oruebel@lbl.gov","rly@lbl.gov","bdichter@lbl.gov","keithg@alleninstitute.org","jteeters@berkeley.edu"]}]}x$pynwb-1.2.1/tests/back_compat/1.1.2_str_experimenter.nwb0000644000655200065520000044262013612200244024475 0ustar circlecicircleci00000000000000HDF  E` TREEH1HEAP`H0 0 .speclocpHhTREEHEAPXPSNOD Hh(Pp P,H0XxPp TREEHEAPX P 0 TREEHEAPXP P TREE(HEAPX(presentationtemplates0TREEHEAPXPSNODhpTREEHEAPXPXxTREEHEAPXexperimenter@ H nwb_version<=0?E'^xSNODGCOLone experimenter 2020-01-21T17:58:29.172657-08:00ADDMEADDME 2020-01-21T17:58:29.171660-08:00 2020-01-21T17:58:29.171660-08:002.1.0core NWBFile $62787364-9064-441d-a0ac-d7d735042f82 {"groups":[{"datasets":[{"shape":[null],"dtype":"int","name":"indices","doc":"column indices"},{"shape":[null],"dtype":"int","name":"indptr","doc":"index pointer"},{"shape":[null],"name":"data","doc":"values in the matrix"}],"doc":"a compressed sparse row matrix","data_type_def":"CSRMatrix","attributes":[{"name":"shape","doc":"the shape of this sparse matrix","dtype":"int","shape":[2]}]}]} H{"namespaces":[{"doc":"Common data structures provided by HDMF","schema":[{"source":"table"},{"source":"sparse"}],"name":"hdmf-common","full_name":"HDMF Common","version":"1.0.0","author":["Andrew Tritt","Oliver Ruebel","Ryan Ly","Ben Dichter"],"contact":["ajtritt@lbl.gov","oruebel@lbl.gov","rly@lbl.gov","bdichter@lbl.gov"]}]} G{"groups":[{"datasets":[{"dtype":"float","name":"start_time","doc":"Start time of epoch, in seconds.","neurodata_type_inc":"VectorData"},{"dtype":"float","name":"stop_time","doc":"Stop time of epoch, in seconds.","neurodata_type_inc":"VectorData"},{"dtype":"text","name":"tags","doc":"User-defined tags that identify or categorize events.","quantity":"?","neurodata_type_inc":"VectorData"},{"name":"tags_index","doc":"Index for tags.","quantity":"?","neurodata_type_inc":"VectorIndex"},{"dtype":[{"doc":"Start index into the TimeSeries 'data' and 'timestamp' datasets of the referenced TimeSeries. The first dimension of those arrays is always time.","name":"idx_start","dtype":"int32"},{"doc":"Number of data samples available in this time series, during this epoch.","name":"count","dtype":"int32"},{"doc":"the TimeSeries that this index applies to.","name":"timeseries","dtype":{"target_type":"TimeSeries","reftype":"object"}}],"name":"timeseries","doc":"An index into a TimeSeries object.","quantity":"?","neurodata_type_inc":"VectorData"},{"name":"timeseries_index","doc":"Index for timeseries.","quantity":"?","neurodata_type_inc":"VectorIndex"}],"doc":"A container for aggregating epoch data and the TimeSeries that each epoch applies to.","neurodata_type_inc":"DynamicTable","neurodata_type_def":"TimeIntervals","attributes":[{"name":"colnames","doc":"The names of the columns in this table. This should be used to specify an order to the columns.","dtype":"ascii","shape":[null],"dims":["num_columns"]},{"name":"description","doc":"Description of what is in this dynamic table.","dtype":"text"}]}]}H4E'^x4E'^(4E'^84E'^acquisitionanalysisprocessingstimulusgeneralfile_create_dateidentifiersession_descriptionsession_start_timetimestamps_reference_timespecificationsSNODh-(  0 x(.8/p=0?8  2H4E'^   H H dG y("<,1w4VBV~ ,VVqV H namespace Hneurodata_type H object_id$ PTREEhBHEAPX P?hdmf-commoncore8?ATREEpFHEAPXB1.0.0HSNOD\](_??ACETREExYHEAPX(Ftablesparsenamespace0SNODCCEX4E'^GCOL{"datasets":[{"doc":"An abstract data type for a dataset.","data_type_def":"Data"},{"doc":"Pointers that index data values.","data_type_inc":"Data","data_type_def":"Index","attributes":[{"name":"target","doc":"Target dataset that this index applies to.","dtype":{"target_type":"Data","reftype":"object"}}]},{"doc":"A 1-dimensional dataset. This can be indexed using a VectorIndex to encode a 2-dimensional ragged array in 1 dimension. The first vector is at VectorData[0:VectorIndex(0)+1]. The second vector is at VectorData[VectorIndex(0)+1:VectorIndex(1)+1]. And so on.","data_type_inc":"Data","data_type_def":"VectorData","attributes":[{"name":"description","doc":"Description of what these vectors represent.","dtype":"text"}]},{"doc":"An array of indices into the first dimension of the target VectorData. Can be used with VectorData to encode a 2-dimensional ragged array in 1 dimension.","data_type_inc":"Index","data_type_def":"VectorIndex","attributes":[{"name":"target","doc":"Reference to the target dataset that this index applies to.","dtype":{"target_type":"VectorData","reftype":"object"}}]},{"shape":[null],"dims":["num_elements"],"dtype":"int","doc":"A list of unique identifiers for values within a dataset, e.g. rows of a DynamicTable.","default_name":"element_id","data_type_inc":"Data","data_type_def":"ElementIdentifiers"},{"dtype":"int","doc":"A region/index into a DynamicTable.","data_type_inc":"VectorData","data_type_def":"DynamicTableRegion","attributes":[{"name":"table","doc":"Reference to the DynamicTable object that this region applies to.","dtype":{"target_type":"DynamicTable","reftype":"object"}},{"name":"description","doc":"Description of what this table region points to.","dtype":"text"}]}],"groups":[{"doc":"An abstract data type for a generic container storing collections of data and metadata. Base type for all data and metadata containers.","data_type_def":"Container"},{"datasets":[{"shape":[null],"dims":["num_rows"],"dtype":"int","name":"id","doc":"Array of unique identifiers for the rows of this dynamic table.","data_type_inc":"ElementIdentifiers"},{"doc":"Vector columns of this dynamic table.","quantity":"*","data_type_inc":"VectorData"},{"doc":"Indices for the vector columns of this dynamic table.","quantity":"*","data_type_inc":"VectorIndex"}],"doc":"A group containing multiple datasets that are aligned on the first dimension (Currently, this requirement if left up to APIs to check and enforce). Apart from a column that contains unique identifiers for each row there are no other required datasets. Users are free to add any number of VectorData objects here. Table functionality is already supported through compound types, which is analogous to storing an array-of-structs. DynamicTable can be thought of as a struct-of-arrays. This provides an alternative structure to choose from when optimizing storage for anticipated access patterns. Additionally, this type provides a way of creating a table without having to define a compound type up front. Although this convenience may be attractive, users should think carefully about how data will be accessed. DynamicTable is more appropriate for column-centric access, whereas a dataset with a compound type would be more appropriate for row-centric access. Finally, data size should also be taken into account. For small tables, performance loss may be an acceptable trade-off for the flexibility of a DynamicTable. For example, DynamicTable was originally developed for storing trial data and spike unit metadata. Both of these use cases are expected to produce relatively small tables, so the spatial locality of multiple datasets present in a DynamicTable is not expected to have a significant performance impact. Additionally, requirements of trial and unit metadata tables are sufficiently diverse that performance implications can be overlooked in favor of usability.","data_type_inc":"Container","data_type_def":"DynamicTable","attributes":[{"name":"colnames","doc":"The names of the columns in this table. This should be used to specify an order to the columns.","dtype":"ascii","shape":[null],"dims":["num_columns"]},{"name":"description","doc":"Description of what is in this dynamic table.","dtype":"text"}]}]}SNOD[ZGh4E'^x4E'^](_TREE`bHEAPXH_2.1.0H_aTREE|QHEAP`SNOD__a4F'^GCOL8{"datasets":[{"doc":"An abstract data type for a dataset.","neurodata_type_inc":"Data","neurodata_type_def":"NWBData"},{"shape":[[null,null],[null,null,3],[null,null,4]],"dims":[["num_x","num_y"],["num_x","num_y","(r, g, b)"],["num_x","num_y","(r, g, b, a)"]],"doc":"An abstract data type for an image. Shape can be 2-D (x, y), or 3-D where the third dimension can have three or four elements, e.g. (x, y, (r, g, b)) or (x, y, (r, g, b, a)).","neurodata_type_inc":"NWBData","neurodata_type_def":"Image","attributes":[{"name":"resolution","doc":"Pixel resolution of the image, in pixels per centimeter.","required":false,"dtype":"float"},{"name":"description","doc":"Description of the image.","required":false,"dtype":"text"}]}],"groups":[{"doc":"An abstract data type for a generic container storing collections of data and metadata. Base type for all data and metadata containers.","neurodata_type_inc":"Container","neurodata_type_def":"NWBContainer"},{"doc":"An abstract data type for a generic container storing collections of data, as opposed to metadata.","neurodata_type_inc":"NWBContainer","neurodata_type_def":"NWBDataInterface"},{"groups":[{"name":"sync","doc":"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. 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.","quantity":"?"}],"datasets":[{"shape":[[null],[null,null],[null,null,null],[null,null,null,null]],"dims":[["num_times"],["num_times","num_DIM2"],["num_times","num_DIM2","num_DIM3"],["num_times","num_DIM2","num_DIM3","num_DIM4"]],"name":"data","doc":"Data values. Data can be in 1-D, 2-D, 3-D, or 4-D. The first dimension should always represent time. This can also be used to store binary data (e.g., image frames). This can also be a link to data stored in an external file.","attributes":[{"name":"conversion","doc":"Scalar to multiply each element in data to convert it to the specified 'unit'. If the data are stored in acquisition system units or other units that require a conversion to be interpretable, multiply the data by 'conversion' to convert the data to the specified 'unit'. e.g. if the data acquisition system stores values in this object as signed 16-bit integers (int16 range -32,768 to 32,767) that correspond to a 5V range (-2.5V to 2.5V), and the data acquisition system gain is 8000X, then the 'conversion' multiplier to get from raw data acquisition values to recorded volts is 2.5/32768/8000 = 9.5367e-9.","required":false,"dtype":"float32","default_value":1.0},{"name":"resolution","doc":"Smallest meaningful difference between values in data, stored in the specified by unit, 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 -1.0.","required":false,"dtype":"float32","default_value":-1.0},{"name":"unit","doc":"Base unit of measurement for working with the data. Actual stored values are not necessarily stored in these units. To access the data in these units, multiply 'data' by 'conversion'.","dtype":"text"}]},{"dtype":"float64","name":"starting_time","doc":"Timestamp of the first sample in seconds. When timestamps are uniformly spaced, the timestamp of the first sample can be specified and all subsequent ones calculated from the sampling rate attribute.","quantity":"?","attributes":[{"name":"rate","doc":"Sampling rate, in Hz.","dtype":"float32"},{"name":"unit","doc":"Unit of measurement for time, which is fixed to 'seconds'.","dtype":"text","value":"seconds"}]},{"shape":[null],"dims":["num_times"],"dtype":"float64","name":"timestamps","doc":"Timestamps for samples stored in data, in seconds, relative to the common experiment master-clock stored in NWBFile.timestamps_reference_time.","quantity":"?","attributes":[{"name":"interval","doc":"Value is '1'","dtype":"int32","value":1},{"name":"unit","doc":"Unit of measurement for timestamps, which is fixed to 'seconds'.","dtype":"text","value":"seconds"}]},{"shape":[null],"dims":["num_times"],"dtype":"uint8","name":"control","doc":"Numerical labels that apply to each time point in data for the purpose of querying and slicing data by these values. If present, the length of this array should be the same size as the first dimension of data.","quantity":"?"},{"shape":[null],"dims":["num_control_values"],"dtype":"text","name":"control_description","doc":"Description of each control value. Must be present if control is present. If present, control_description[0] should describe time points where control == 0.","quantity":"?"}],"doc":"General purpose time series.","neurodata_type_inc":"NWBDataInterface","neurodata_type_def":"TimeSeries","attributes":[{"name":"description","doc":"Description of the time series.","required":false,"dtype":"text","default_value":"no description"},{"name":"comments","doc":"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.","required":false,"dtype":"text","default_value":"no comments"}]},{"groups":[{"doc":"Data objects stored in this collection.","quantity":"*","neurodata_type_inc":"NWBDataInterface"},{"doc":"Tables stored in this collection.","quantity":"*","neurodata_type_inc":"DynamicTable"}],"doc":"A collection of processed data.","neurodata_type_inc":"NWBContainer","neurodata_type_def":"ProcessingModule","attributes":[{"name":"description","doc":"Description of this collection of processed data.","dtype":"text"}]},{"datasets":[{"doc":"Images stored in this collection.","quantity":"+","neurodata_type_inc":"Image"}],"doc":"A collection of images.","default_name":"Images","neurodata_type_inc":"NWBDataInterface","neurodata_type_def":"Images","attributes":[{"name":"description","doc":"Description of this collection of images.","dtype":"text"}]}]}SNOD8UcXxhN8~4F'^4F'^4F'^4F'^4F'^nwb.basenwb.epochnwb.imagenwb.filenwb.miscnwb.behaviornwb.ecephysnwb.icephysnwb.ogennwb.ophysnwb.retinotopynamespaceGCOLy({"datasets":[{"shape":[null,null],"dims":["y","x"],"doc":"A grayscale image.","neurodata_type_inc":"Image","neurodata_type_def":"GrayscaleImage","attributes":[{"name":"resolution","doc":"Pixel resolution of the image, in pixels per centimeter.","required":false,"dtype":"float"},{"name":"description","doc":"Description of the image.","required":false,"dtype":"text"}]},{"shape":[null,null,3],"dims":["y","x","R, G, B"],"doc":"A color image.","neurodata_type_inc":"Image","neurodata_type_def":"RGBImage","attributes":[{"name":"resolution","doc":"Pixel resolution of the image, in pixels per centimeter.","required":false,"dtype":"float"},{"name":"description","doc":"Description of the image.","required":false,"dtype":"text"}]},{"shape":[null,null,4],"dims":["y","x","R, G, B, A"],"doc":"A color image with transparency.","neurodata_type_inc":"Image","neurodata_type_def":"RGBAImage","attributes":[{"name":"resolution","doc":"Pixel resolution of the image, in pixels per centimeter.","required":false,"dtype":"float"},{"name":"description","doc":"Description of the image.","required":false,"dtype":"text"}]}],"groups":[{"datasets":[{"shape":[[null,null,null],[null,null,null,null]],"dims":[["frame","y","x"],["frame","z","y","x"]],"dtype":"numeric","name":"data","doc":"Binary data representing images across frames.","quantity":"?","attributes":[{"name":"conversion","doc":"Scalar to multiply each element in data to convert it to the specified 'unit'. If the data are stored in acquisition system units or other units that require a conversion to be interpretable, multiply the data by 'conversion' to convert the data to the specified 'unit'. e.g. if the data acquisition system stores values in this object as signed 16-bit integers (int16 range -32,768 to 32,767) that correspond to a 5V range (-2.5V to 2.5V), and the data acquisition system gain is 8000X, then the 'conversion' multiplier to get from raw data acquisition values to recorded volts is 2.5/32768/8000 = 9.5367e-9.","required":false,"dtype":"float32","default_value":1.0},{"name":"resolution","doc":"Smallest meaningful difference between values in data, stored in the specified by unit, 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 -1.0.","required":false,"dtype":"float32","default_value":-1.0},{"name":"unit","doc":"Base unit of measurement for working with the data. Actual stored values are not necessarily stored in these units. To access the data in these units, multiply 'data' by 'conversion'.","dtype":"text"}]},{"shape":[null],"dims":["rank"],"dtype":"int32","name":"dimension","doc":"Number of pixels on x, y, (and z) axes.","quantity":"?"},{"shape":[null],"dims":["num_files"],"dtype":"text","name":"external_file","doc":"Paths to one or more external file(s). The field is only present if format='external'. This is only relevant if the image series is stored in the file system as one or more image file(s). This field should NOT be used if the image is stored in another NWB file and that file is linked to this file.","quantity":"?","attributes":[{"name":"starting_frame","doc":"Each external image may contain one or more consecutive frames of the full ImageSeries. This attribute serves as an index to indicate which frames each file contains, to faciliate random access. The 'starting_frame' attribute, hence, contains a list of frame numbers within the full ImageSeries of the first frame of each file listed in the parent 'external_file' dataset. Zero-based indexing is used (hence, the first element will always be zero). For example, if the 'external_file' dataset has three paths to files and the first file has 5 frames, the second file has 10 frames, and the third file has 20 frames, then this attribute will have values [0, 5, 15]. If there is a single external file that holds all of the frames of the ImageSeries (and so there is a single element in the 'external_file' dataset), then this attribute should have value [0].","dtype":"int","shape":[null],"dims":["num_files"]}]},{"dtype":"text","name":"format","doc":"Format of image. If this is 'external', then the attribute 'external_file' contains the path information to the image files. If this is 'raw', then the raw (single-channel) binary data is stored in the 'data' dataset. If this attribute is not present, then the default format='raw' case is assumed.","quantity":"?","default_value":"raw"}],"doc":"General image data that is common between acquisition and stimulus time series. Sometimes the image data is stored in the file in a raw format while other times it will be stored as a series of external image files in the host file system. The data field will either be binary data, if the data is stored in the NWB file, or empty, if the data is stored in an external image stack. [frame][y][x] or [frame][z][y][x].","neurodata_type_inc":"TimeSeries","neurodata_type_def":"ImageSeries","attributes":[{"name":"description","doc":"Description of the time series.","required":false,"dtype":"text","default_value":"no description"},{"name":"comments","doc":"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.","required":false,"dtype":"text","default_value":"no comments"}]},{"links":[{"name":"masked_imageseries","doc":"Link to ImageSeries object that this image mask is applied to.","target_type":"ImageSeries"}],"doc":"An alpha mask that is applied to a presented visual stimulus. The 'data' array contains an array of mask values that are applied to the displayed image. Mask values are stored as RGBA. Mask can vary with time. The timestamps array indicates the starting time of a mask, and that mask pattern continues until it's explicitly changed.","neurodata_type_inc":"ImageSeries","neurodata_type_def":"ImageMaskSeries","attributes":[{"name":"description","doc":"Description of the time series.","required":false,"dtype":"text","default_value":"no description"},{"name":"comments","doc":"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.","required":false,"dtype":"text","default_value":"no comments"}]},{"datasets":[{"dtype":"float32","name":"distance","doc":"Distance from camera/monitor to target/eye.","quantity":"?"},{"shape":[[2],[3]],"dims":[["width, height"],["width, height, depth"]],"dtype":"float32","name":"field_of_view","doc":"Width, height and depth of image, or imaged area, in meters.","quantity":"?"},{"dtype":"text","name":"orientation","doc":"Description of image relative to some reference frame (e.g., which way is up). Must also specify frame of reference.","quantity":"?"}],"doc":"Image data that is presented or recorded. A stimulus template movie will be stored only as an image. When the image is presented as stimulus, additional data is required, such as field of view (e.g., how much of the visual field the image covers, or how what is the area of the target being imaged). If the OpticalSeries represents acquired imaging data, orientation is also important.","neurodata_type_inc":"ImageSeries","neurodata_type_def":"OpticalSeries","attributes":[{"name":"description","doc":"Description of the time series.","required":false,"dtype":"text","default_value":"no description"},{"name":"comments","doc":"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.","required":false,"dtype":"text","default_value":"no comments"}]},{"datasets":[{"shape":[null],"dims":["num_times"],"dtype":"int","name":"data","doc":"Index of the frame in the referenced ImageSeries.","attributes":[{"name":"conversion","doc":"Scalar to multiply each element in data to convert it to the specified 'unit'. If the data are stored in acquisition system units or other units that require a conversion to be interpretable, multiply the data by 'conversion' to convert the data to the specified 'unit'. e.g. if the data acquisition system stores values in this object as signed 16-bit integers (int16 range -32,768 to 32,767) that correspond to a 5V range (-2.5V to 2.5V), and the data acquisition system gain is 8000X, then the 'conversion' multiplier to get from raw data acquisition values to recorded volts is 2.5/32768/8000 = 9.5367e-9.","required":false,"dtype":"float32","default_value":1.0},{"name":"resolution","doc":"Smallest meaningful difference between values in data, stored in the specified by unit, 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 -1.0.","required":false,"dtype":"float32","default_value":-1.0},{"name":"unit","doc":"Base unit of measurement for working with the data. Actual stored values are not necessarily stored in these units. To access the data in these units, multiply 'data' by 'conversion'.","dtype":"text"}]}],"links":[{"name":"indexed_timeseries","doc":"Link to ImageSeries object containing images that are indexed.","target_type":"ImageSeries"}],"doc":"Stores indices to image frames stored in an ImageSeries. The purpose of the ImageIndexSeries 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 ImageSeries, and the timestamps array indicates when that image was displayed.","neurodata_type_inc":"TimeSeries","neurodata_type_def":"IndexSeries","attributes":[{"name":"description","doc":"Description of the time series.","required":false,"dtype":"text","default_value":"no description"},{"name":"comments","doc":"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.","required":false,"dtype":"text","default_value":"no comments"}]}]}"<{"groups":[{"groups":[{"groups":[{"doc":"Acquired, raw data.","quantity":"*","neurodata_type_inc":"NWBDataInterface"},{"doc":"Tabular data that is relevent to acquisition","quantity":"*","neurodata_type_inc":"DynamicTable"}],"name":"acquisition","doc":"Data streams recorded from the system, including ephys, ophys, tracking, etc. This group should be 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 NWB files. This will allow keeping bulky raw data out of the file while preserving the option of keeping some/all in the file. Acquired data includes tracking and experimental data streams (i.e., everything measured from the system). If bulky data is stored in the /acquisition group, the data can exist in a separate NWB file that is linked to by the file being used for processing and analysis."},{"groups":[{"doc":"Custom analysis results.","quantity":"*","neurodata_type_inc":"NWBContainer"},{"doc":"Tabular data that is relevent to data stored in analysis","quantity":"*","neurodata_type_inc":"DynamicTable"}],"name":"analysis","doc":"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. To facilitate sharing analysis data between labs, the contents here should be stored in standard types (e.g., neurodata_types) and appropriately documented. 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 could be shared with other labs."},{"groups":[{"doc":"Any one-off containers","quantity":"*","neurodata_type_inc":"NWBContainer"},{"doc":"Any one-off tables","quantity":"*","neurodata_type_inc":"DynamicTable"}],"datasets":[{"doc":"Any one-off datasets","quantity":"*","neurodata_type_inc":"NWBData","neurodata_type_def":"ScratchData","attributes":[{"name":"notes","doc":"Any notes the user has about the dataset being stored","dtype":"text"}]}],"name":"scratch","doc":"A place to store one-off analysis results. Data placed here is not intended for sharing. By placing data here, users acknowledge that there is no guarantee that their data meets any standard.","quantity":"?"},{"groups":[{"doc":"Intermediate analysis of acquired data.","quantity":"*","neurodata_type_inc":"ProcessingModule"}],"name":"processing","doc":"The home for ProcessingModules. 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. ProcessingModules 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. 'Processing' refers to intermediate analysis of the acquired data to make it more amenable to scientific analysis."},{"groups":[{"groups":[{"doc":"TimeSeries objects containing data of presented stimuli.","quantity":"*","neurodata_type_inc":"TimeSeries"}],"name":"presentation","doc":"Stimuli presented during the experiment."},{"groups":[{"doc":"TimeSeries objects containing template data of presented stimuli.","quantity":"*","neurodata_type_inc":"TimeSeries"}],"name":"templates","doc":"Template stimuli. Timestamps 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."}],"name":"stimulus","doc":"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). This group should be made 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. 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 linked to a remote library file."},{"groups":[{"doc":"Place-holder than can be extended so that lab-specific meta-data can be placed in /general.","quantity":"*","neurodata_type_inc":"NWBContainer","neurodata_type_def":"LabMetaData"},{"groups":[{"doc":"A data acquisition device, e.g. recording system.","quantity":"+","neurodata_type_inc":"NWBContainer","neurodata_type_def":"Device"}],"name":"devices","doc":"Description of hardware devices used during experiment, e.g., monitors, ADC boards, microscopes, etc.","quantity":"?"},{"datasets":[{"dtype":"text","name":"age","doc":"Age of subject. Can be supplied instead of 'date_of_birth'.","quantity":"?"},{"dtype":"isodatetime","name":"date_of_birth","doc":"Date of birth of subject. Can be supplied instead of 'age'.","quantity":"?"},{"dtype":"text","name":"description","doc":"Description of subject and where subject came from (e.g., breeder, if animal).","quantity":"?"},{"dtype":"text","name":"genotype","doc":"Genetic strain. If absent, assume Wild Type (WT).","quantity":"?"},{"dtype":"text","name":"sex","doc":"Gender of subject.","quantity":"?"},{"dtype":"text","name":"species","doc":"Species of subject.","quantity":"?"},{"dtype":"text","name":"subject_id","doc":"ID of animal/person used/participating in experiment (lab convention).","quantity":"?"},{"dtype":"text","name":"weight","doc":"Weight at time of experiment, at time of surgery and at other important times.","quantity":"?"}],"name":"subject","doc":"Information about the animal or person from which the data was measured.","quantity":"?","neurodata_type_inc":"NWBContainer","neurodata_type_def":"Subject"},{"groups":[{"doc":"Physical group of electrodes.","quantity":"*","neurodata_type_inc":"ElectrodeGroup"},{"datasets":[{"dtype":"float","name":"x","doc":"x coordinate of the channel location.","neurodata_type_inc":"VectorData"},{"dtype":"float","name":"y","doc":"y coordinate of the channel location.","neurodata_type_inc":"VectorData"},{"dtype":"float","name":"z","doc":"z coordinate of the channel location.","neurodata_type_inc":"VectorData"},{"dtype":"float","name":"imp","doc":"Impedance of the channel.","neurodata_type_inc":"VectorData"},{"dtype":"ascii","name":"location","doc":"Location of the electrode (channel). Specify the area, layer, comments on estimation of area/layer, stereotaxic coordinates if in vivo, etc. Use standard atlas names for anatomical regions when possible.","neurodata_type_inc":"VectorData"},{"dtype":"float","name":"filtering","doc":"Description of hardware filtering.","neurodata_type_inc":"VectorData"},{"dtype":{"target_type":"ElectrodeGroup","reftype":"object"},"name":"group","doc":"Reference to the ElectrodeGroup this electrode is a part of.","neurodata_type_inc":"VectorData"},{"dtype":"ascii","name":"group_name","doc":"Name of the ElectrodeGroup this electrode is a part of.","neurodata_type_inc":"VectorData"}],"name":"electrodes","doc":"A table of all electrodes (i.e. channels) used for recording.","quantity":"?","neurodata_type_inc":"DynamicTable"}],"name":"extracellular_ephys","doc":"Metadata related to extracellular electrophysiology.","quantity":"?"},{"groups":[{"doc":"An intracellular electrode.","quantity":"*","neurodata_type_inc":"IntracellularElectrode"},{"name":"sweep_table","doc":"The table which groups different PatchClampSeries together.","quantity":"?","neurodata_type_inc":"SweepTable"}],"datasets":[{"dtype":"text","name":"filtering","doc":"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.","quantity":"?"}],"name":"intracellular_ephys","doc":"Metadata related to intracellular electrophysiology.","quantity":"?"},{"groups":[{"doc":"An optogenetic stimulation site.","quantity":"*","neurodata_type_inc":"OptogeneticStimulusSite"}],"name":"optogenetics","doc":"Metadata describing optogenetic stimuluation.","quantity":"?"},{"groups":[{"doc":"An imaging plane.","quantity":"*","neurodata_type_inc":"ImagingPlane"}],"name":"optophysiology","doc":"Metadata related to optophysiology.","quantity":"?"}],"datasets":[{"dtype":"text","name":"data_collection","doc":"Notes about data collection and analysis.","quantity":"?"},{"dtype":"text","name":"experiment_description","doc":"General description of the experiment.","quantity":"?"},{"shape":[null],"dims":["num_experimenters"],"dtype":"text","name":"experimenter","doc":"Name of person(s) who performed the experiment. Can also specify roles of different people involved.","quantity":"?"},{"dtype":"text","name":"institution","doc":"Institution(s) where experiment was performed.","quantity":"?"},{"shape":[null],"dims":["num_keywords"],"dtype":"text","name":"keywords","doc":"Terms to search over.","quantity":"?"},{"dtype":"text","name":"lab","doc":"Laboratory where experiment was performed.","quantity":"?"},{"dtype":"text","name":"notes","doc":"Notes about the experiment.","quantity":"?"},{"dtype":"text","name":"pharmacology","doc":"Description of drugs used, including how and when they were administered. Anesthesia(s), painkiller(s), etc., plus dosage, concentration, etc.","quantity":"?"},{"dtype":"text","name":"protocol","doc":"Experimental protocol, if applicable. e.g., include IACUC protocol number.","quantity":"?"},{"shape":[null],"dims":["num_publications"],"dtype":"text","name":"related_publications","doc":"Publication information. PMID, DOI, URL, etc.","quantity":"?"},{"dtype":"text","name":"session_id","doc":"Lab-specific ID for the session.","quantity":"?"},{"dtype":"text","name":"slices","doc":"Description of slices, including information about preparation thickness, orientation, temperature, and bath solution.","quantity":"?"},{"dtype":"text","name":"source_script","doc":"Script file or link to public source code used to create this NWB file.","quantity":"?","attributes":[{"name":"file_name","doc":"Name of script file.","dtype":"text"}]},{"dtype":"text","name":"stimulus","doc":"Notes about stimuli, such as how and where they were presented.","quantity":"?"},{"dtype":"text","name":"surgery","doc":"Narrative description about surgery/surgeries, including date(s) and who performed surgery.","quantity":"?"},{"dtype":"text","name":"virus","doc":"Information about virus(es) used in experiments, including virus ID, source, date made, injection location, volume, etc.","quantity":"?"}],"name":"general","doc":"Experimental metadata, including protocol, notes and description of hardware device(s). The metadata stored in this section should be used to describe the experiment. Metadata necessary for interpreting the data is stored with the data. 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 (e.g., 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. 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."},{"groups":[{"name":"epochs","doc":"Divisions in time marking experimental stages or sub-divisions of a single recording session.","quantity":"?","neurodata_type_inc":"TimeIntervals"},{"name":"trials","doc":"Repeated experimental events that have a logical grouping.","quantity":"?","neurodata_type_inc":"TimeIntervals"},{"name":"invalid_times","doc":"Time intervals that should be removed from analysis.","quantity":"?","neurodata_type_inc":"TimeIntervals"},{"doc":"Optional additional table(s) for describing other experimental time intervals.","quantity":"*","neurodata_type_inc":"TimeIntervals"}],"name":"intervals","doc":"Experimental intervals, whether that be logically distinct sub-experiments having a particular scientific goal, trials (see trials subgroup) during an experiment, or epochs (see epochs subgroup) deriving from analysis of data.","quantity":"?"},{"name":"units","doc":"Data about sorted spike units.","quantity":"?","neurodata_type_inc":"Units"}],"datasets":[{"shape":[null],"dims":["num_modifications"],"dtype":"isodatetime","name":"file_create_date","doc":"A record of the date the file was created and of subsequent modifications. The date is stored in UTC with local timezone offset as ISO 8601 extended formatted strings: 2018-09-28T14:43:54.123+02:00. Dates stored in UTC end in \"Z\" with no timezone offset. Date accuracy is up to milliseconds. The file can be created after the experiment was run, so this may differ from the experiment start time. Each modification to the nwb file adds a new entry to the array."},{"dtype":"text","name":"identifier","doc":"A unique text identifier for the file. For example, 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."},{"dtype":"text","name":"session_description","doc":"A description of the experimental session and data in the file."},{"dtype":"isodatetime","name":"session_start_time","doc":"Date and time of the experiment/session start. The date is stored in UTC with local timezone offset as ISO 8601 extended formatted string: 2018-09-28T14:43:54.123+02:00. Dates stored in UTC end in \"Z\" with no timezone offset. Date accuracy is up to milliseconds."},{"dtype":"isodatetime","name":"timestamps_reference_time","doc":"Date and time corresponding to time zero of all timestamps. The date is stored in UTC with local timezone offset as ISO 8601 extended formatted string: 2018-09-28T14:43:54.123+02:00. Dates stored in UTC end in \"Z\" with no timezone offset. Date accuracy is up to milliseconds. All times stored in the file use this time as reference (i.e., time zero)."}],"name":"root","doc":"An NWB:N file storing cellular-based neurophysiology data from a single experimental session.","neurodata_type_inc":"NWBContainer","neurodata_type_def":"NWBFile","attributes":[{"name":"nwb_version","doc":"File version string. Use semantic versioning, e.g. 1.2.1. This will be the name of the format with trailing major, minor and patch numbers.","dtype":"text","value":"2.1.0"}]}]},1{"groups":[{"datasets":[{"shape":[[null],[null,null]],"dims":[["num_times"],["num_times","num_features"]],"dtype":"numeric","name":"data","doc":"Values of each feature at each time.","attributes":[{"name":"unit","doc":"Since there can be different units for different features, store the units in 'feature_units'. The default value for this attribute is \"see 'feature_units'\".","required":false,"dtype":"text","default_value":"see 'feature_units'"},{"name":"conversion","doc":"Scalar to multiply each element in data to convert it to the specified 'unit'. If the data are stored in acquisition system units or other units that require a conversion to be interpretable, multiply the data by 'conversion' to convert the data to the specified 'unit'. e.g. if the data acquisition system stores values in this object as signed 16-bit integers (int16 range -32,768 to 32,767) that correspond to a 5V range (-2.5V to 2.5V), and the data acquisition system gain is 8000X, then the 'conversion' multiplier to get from raw data acquisition values to recorded volts is 2.5/32768/8000 = 9.5367e-9.","required":false,"dtype":"float32","default_value":1.0},{"name":"resolution","doc":"Smallest meaningful difference between values in data, stored in the specified by unit, 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 -1.0.","required":false,"dtype":"float32","default_value":-1.0}]},{"shape":[null],"dims":["num_features"],"dtype":"text","name":"feature_units","doc":"Units of each feature.","quantity":"?"},{"shape":[null],"dims":["num_features"],"dtype":"text","name":"features","doc":"Description of the features represented in TimeSeries::data."}],"doc":"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. This is useful when storing the raw stimulus is impractical.","neurodata_type_inc":"TimeSeries","neurodata_type_def":"AbstractFeatureSeries","attributes":[{"name":"description","doc":"Description of the time series.","required":false,"dtype":"text","default_value":"no description"},{"name":"comments","doc":"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.","required":false,"dtype":"text","default_value":"no comments"}]},{"datasets":[{"shape":[null],"dims":["num_times"],"dtype":"text","name":"data","doc":"Annotations made during an experiment.","attributes":[{"name":"resolution","doc":"Smallest meaningful difference between values in data. Annotations have no units, so the value is fixed to -1.0.","dtype":"float","value":-1.0},{"name":"unit","doc":"Base unit of measurement for working with the data. Annotations have no units, so the value is fixed to 'n/a'.","dtype":"text","value":"n/a"},{"name":"conversion","doc":"Scalar to multiply each element in data to convert it to the specified 'unit'. If the data are stored in acquisition system units or other units that require a conversion to be interpretable, multiply the data by 'conversion' to convert the data to the specified 'unit'. e.g. if the data acquisition system stores values in this object as signed 16-bit integers (int16 range -32,768 to 32,767) that correspond to a 5V range (-2.5V to 2.5V), and the data acquisition system gain is 8000X, then the 'conversion' multiplier to get from raw data acquisition values to recorded volts is 2.5/32768/8000 = 9.5367e-9.","required":false,"dtype":"float32","default_value":1.0}]}],"doc":"Stores user annotations made during an experiment. The 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.","neurodata_type_inc":"TimeSeries","neurodata_type_def":"AnnotationSeries","attributes":[{"name":"description","doc":"Description of the time series.","required":false,"dtype":"text","default_value":"no description"},{"name":"comments","doc":"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.","required":false,"dtype":"text","default_value":"no comments"}]},{"datasets":[{"shape":[null],"dims":["num_times"],"dtype":"int8","name":"data","doc":"Use values >0 if interval started, <0 if interval ended.","attributes":[{"name":"resolution","doc":"Smallest meaningful difference between values in data. Annotations have no units, so the value is fixed to -1.0.","dtype":"float","value":-1.0},{"name":"unit","doc":"Base unit of measurement for working with the data. Annotations have no units, so the value is fixed to 'n/a'.","dtype":"text","value":"n/a"},{"name":"conversion","doc":"Scalar to multiply each element in data to convert it to the specified 'unit'. If the data are stored in acquisition system units or other units that require a conversion to be interpretable, multiply the data by 'conversion' to convert the data to the specified 'unit'. e.g. if the data acquisition system stores values in this object as signed 16-bit integers (int16 range -32,768 to 32,767) that correspond to a 5V range (-2.5V to 2.5V), and the data acquisition system gain is 8000X, then the 'conversion' multiplier to get from raw data acquisition values to recorded volts is 2.5/32768/8000 = 9.5367e-9.","required":false,"dtype":"float32","default_value":1.0}]}],"doc":"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.","neurodata_type_inc":"TimeSeries","neurodata_type_def":"IntervalSeries","attributes":[{"name":"description","doc":"Description of the time series.","required":false,"dtype":"text","default_value":"no description"},{"name":"comments","doc":"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.","required":false,"dtype":"text","default_value":"no comments"}]},{"groups":[{"datasets":[{"dtype":"text","name":"band_name","doc":"Name of the band, e.g. theta.","neurodata_type_inc":"VectorData"},{"shape":[null,2],"dims":["num_bands","low, high"],"dtype":"float","name":"band_limits","doc":"Low and high limit of each band in Hz. If it is a Gaussian filter, use 2 SD on either side of the center.","neurodata_type_inc":"VectorData"},{"shape":[null],"dims":["num_bands"],"dtype":"float","name":"band_mean","doc":"The mean Gaussian filters, in Hz.","neurodata_type_inc":"VectorData"},{"shape":[null],"dims":["num_bands"],"dtype":"float","name":"band_stdev","doc":"The standard deviation of Gaussian filters, in Hz.","neurodata_type_inc":"VectorData"}],"name":"bands","doc":"Table for describing the bands that this series was generated from. There should be one row in this table for each band.","neurodata_type_inc":"DynamicTable"}],"datasets":[{"shape":[null,null,null],"dims":["num_times","num_channels","num_bands"],"dtype":"numeric","name":"data","doc":"Data decomposed into frequency bands.","attributes":[{"name":"unit","doc":"Base unit of measurement for working with the data. Actual stored values are not necessarily stored in these units. To access the data in these units, multiply 'data' by 'conversion'.","required":false,"dtype":"text","default_value":"no unit"},{"name":"conversion","doc":"Scalar to multiply each element in data to convert it to the specified 'unit'. If the data are stored in acquisition system units or other units that require a conversion to be interpretable, multiply the data by 'conversion' to convert the data to the specified 'unit'. e.g. if the data acquisition system stores values in this object as signed 16-bit integers (int16 range -32,768 to 32,767) that correspond to a 5V range (-2.5V to 2.5V), and the data acquisition system gain is 8000X, then the 'conversion' multiplier to get from raw data acquisition values to recorded volts is 2.5/32768/8000 = 9.5367e-9.","required":false,"dtype":"float32","default_value":1.0},{"name":"resolution","doc":"Smallest meaningful difference between values in data, stored in the specified by unit, 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 -1.0.","required":false,"dtype":"float32","default_value":-1.0}]},{"dtype":"text","name":"metric","doc":"The metric used, e.g. phase, amplitude, power."}],"links":[{"name":"source_timeseries","doc":"Link to TimeSeries object that this data was calculated from. Metadata about electrodes and their position can be read from that ElectricalSeries so it is not necessary to store that information here.","target_type":"TimeSeries","quantity":"?"}],"doc":"Spectral analysis of a time series, e.g. of an LFP or a speech signal.","neurodata_type_inc":"TimeSeries","neurodata_type_def":"DecompositionSeries","attributes":[{"name":"description","doc":"Description of the time series.","required":false,"dtype":"text","default_value":"no description"},{"name":"comments","doc":"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.","required":false,"dtype":"text","default_value":"no comments"}]},{"datasets":[{"name":"spike_times_index","doc":"Index into the spike_times dataset.","quantity":"?","neurodata_type_inc":"VectorIndex"},{"dtype":"double","name":"spike_times","doc":"Spike times for each unit.","quantity":"?","neurodata_type_inc":"VectorData"},{"name":"obs_intervals_index","doc":"Index into the obs_intervals dataset.","quantity":"?","neurodata_type_inc":"VectorIndex"},{"shape":[null,2],"dims":["num_intervals","start|end"],"dtype":"double","name":"obs_intervals","doc":"Observation intervals for each unit.","quantity":"?","neurodata_type_inc":"VectorData"},{"name":"electrodes_index","doc":"Index into electrodes.","quantity":"?","neurodata_type_inc":"VectorIndex"},{"name":"electrodes","doc":"Electrode that each spike unit came from, specified using a DynamicTableRegion.","quantity":"?","neurodata_type_inc":"DynamicTableRegion"},{"dtype":{"target_type":"ElectrodeGroup","reftype":"object"},"name":"electrode_group","doc":"Electrode group that each spike unit came from.","quantity":"?","neurodata_type_inc":"VectorData"},{"shape":[[null,null],[null,null,null]],"dims":[["num_units","num_samples"],["num_units","num_samples","num_electrodes"]],"dtype":"float","name":"waveform_mean","doc":"Spike waveform mean for each spike unit.","quantity":"?","neurodata_type_inc":"VectorData"},{"shape":[[null,null],[null,null,null]],"dims":[["num_units","num_samples"],["num_units","num_samples","num_electrodes"]],"dtype":"float","name":"waveform_sd","doc":"Spike waveform standard deviation for each spike unit.","quantity":"?","neurodata_type_inc":"VectorData"}],"doc":"Data about spiking units. Event times of observed units (e.g. cell, synapse, etc.) should be concatenated and stored in spike_times.","default_name":"Units","neurodata_type_inc":"DynamicTable","neurodata_type_def":"Units","attributes":[{"name":"colnames","doc":"The names of the columns in this table. This should be used to specify an order to the columns.","dtype":"ascii","shape":[null],"dims":["num_columns"]},{"name":"description","doc":"Description of what is in this dynamic table.","dtype":"text"}]}]}{"groups":[{"datasets":[{"shape":[[null],[null,null]],"dims":[["num_times"],["num_times","num_features"]],"dtype":"numeric","name":"data","doc":"1-D or 2-D array storing position or direction relative to some reference frame.","attributes":[{"name":"unit","doc":"Base unit of measurement for working with the data. The default value is 'meters'. Actual stored values are not necessarily stored in these units. To access the data in these units, multiply 'data' by 'conversion'.","required":false,"dtype":"text","default_value":"meters"},{"name":"conversion","doc":"Scalar to multiply each element in data to convert it to the specified 'unit'. If the data are stored in acquisition system units or other units that require a conversion to be interpretable, multiply the data by 'conversion' to convert the data to the specified 'unit'. e.g. if the data acquisition system stores values in this object as signed 16-bit integers (int16 range -32,768 to 32,767) that correspond to a 5V range (-2.5V to 2.5V), and the data acquisition system gain is 8000X, then the 'conversion' multiplier to get from raw data acquisition values to recorded volts is 2.5/32768/8000 = 9.5367e-9.","required":false,"dtype":"float32","default_value":1.0},{"name":"resolution","doc":"Smallest meaningful difference between values in data, stored in the specified by unit, 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 -1.0.","required":false,"dtype":"float32","default_value":-1.0}]},{"dtype":"text","name":"reference_frame","doc":"Description defining what exactly 'straight-ahead' means.","quantity":"?"}],"doc":"Direction, e.g., of gaze or travel, or position. The TimeSeries::data field is a 2D array storing position or direction relative to some reference frame. Array structure: [num measurements] [num dimensions]. Each SpatialSeries has a text dataset reference_frame that indicates the zero-position, or the zero-axes for direction. For example, if representing gaze direction, 'straight-ahead' might be a specific pixel on the monitor, or some other point in space. For position data, the 0,0 point might be the top-left corner of an enclosure, as viewed from the tracking camera. The unit of data will indicate how to interpret SpatialSeries values.","neurodata_type_inc":"TimeSeries","neurodata_type_def":"SpatialSeries","attributes":[{"name":"description","doc":"Description of the time series.","required":false,"dtype":"text","default_value":"no description"},{"name":"comments","doc":"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.","required":false,"dtype":"text","default_value":"no comments"}]},{"groups":[{"doc":"IntervalSeries object containing start and stop times of epochs.","quantity":"*","neurodata_type_inc":"IntervalSeries"}],"doc":"TimeSeries for storing behavioral epochs. The objective of this and the other two Behavioral interfaces (e.g. BehavioralEvents and BehavioralTimeSeries) is to provide generic hooks for software tools/scripts. This allows a tool/script to take the output one specific interface (e.g., UnitTimes) and plot that data relative to another data modality (e.g., behavioral events) without having to define all possible modalities in advance. Declaring one of these interfaces means that one or more TimeSeries of the specified type is published. These TimeSeries should reside in a group having the same name as the interface. For example, if a BehavioralTimeSeries interface is declared, the module will have one or more TimeSeries defined in the module sub-group 'BehavioralTimeSeries'. BehavioralEpochs should use IntervalSeries. BehavioralEvents is used for irregular events. BehavioralTimeSeries is for continuous data.","default_name":"BehavioralEpochs","neurodata_type_inc":"NWBDataInterface","neurodata_type_def":"BehavioralEpochs"},{"groups":[{"doc":"TimeSeries object containing behavioral events.","quantity":"*","neurodata_type_inc":"TimeSeries"}],"doc":"TimeSeries for storing behavioral events. See description of BehavioralEpochs for more details.","default_name":"BehavioralEvents","neurodata_type_inc":"NWBDataInterface","neurodata_type_def":"BehavioralEvents"},{"groups":[{"doc":"TimeSeries object containing continuous behavioral data.","quantity":"*","neurodata_type_inc":"TimeSeries"}],"doc":"TimeSeries for storing Behavoioral time series data. See description of BehavioralEpochs for more details.","default_name":"BehavioralTimeSeries","neurodata_type_inc":"NWBDataInterface","neurodata_type_def":"BehavioralTimeSeries"},{"groups":[{"doc":"TimeSeries object containing time series data on pupil size.","quantity":"+","neurodata_type_inc":"TimeSeries"}],"doc":"Eye-tracking data, representing pupil size.","default_name":"PupilTracking","neurodata_type_inc":"NWBDataInterface","neurodata_type_def":"PupilTracking"},{"groups":[{"doc":"SpatialSeries object containing data measuring direction of gaze.","quantity":"*","neurodata_type_inc":"SpatialSeries"}],"doc":"Eye-tracking data, representing direction of gaze.","default_name":"EyeTracking","neurodata_type_inc":"NWBDataInterface","neurodata_type_def":"EyeTracking"},{"groups":[{"doc":"SpatialSeries object containing direction of gaze travel.","quantity":"*","neurodata_type_inc":"SpatialSeries"}],"doc":"With a CompassDirection interface, a module publishes a SpatialSeries object representing a floating point value for theta. The SpatialSeries::reference_frame field should indicate what direction corresponds to 0 and which is the direction of rotation (this should be clockwise). The si_unit for the SpatialSeries should be radians or degrees.","default_name":"CompassDirection","neurodata_type_inc":"NWBDataInterface","neurodata_type_def":"CompassDirection"},{"groups":[{"doc":"SpatialSeries object containing position data.","quantity":"+","neurodata_type_inc":"SpatialSeries"}],"doc":"Position data, whether along the x, x/y or x/y/z axis.","default_name":"Position","neurodata_type_inc":"NWBDataInterface","neurodata_type_def":"Position"}]}~ {"groups":[{"datasets":[{"shape":[null],"dims":["num_times"],"dtype":"numeric","name":"data","doc":"Applied power for optogenetic stimulus, in watts.","attributes":[{"name":"unit","doc":"Unit of measurement for data, which is fixed to 'watts'.","dtype":"text","value":"watts"},{"name":"conversion","doc":"Scalar to multiply each element in data to convert it to the specified 'unit'. If the data are stored in acquisition system units or other units that require a conversion to be interpretable, multiply the data by 'conversion' to convert the data to the specified 'unit'. e.g. if the data acquisition system stores values in this object as signed 16-bit integers (int16 range -32,768 to 32,767) that correspond to a 5V range (-2.5V to 2.5V), and the data acquisition system gain is 8000X, then the 'conversion' multiplier to get from raw data acquisition values to recorded volts is 2.5/32768/8000 = 9.5367e-9.","required":false,"dtype":"float32","default_value":1.0},{"name":"resolution","doc":"Smallest meaningful difference between values in data, stored in the specified by unit, 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 -1.0.","required":false,"dtype":"float32","default_value":-1.0}]}],"links":[{"name":"site","doc":"Link to OptogeneticStimulusSite object that describes the site to which this stimulus was applied.","target_type":"OptogeneticStimulusSite"}],"doc":"An optogenetic stimulus.","neurodata_type_inc":"TimeSeries","neurodata_type_def":"OptogeneticSeries","attributes":[{"name":"description","doc":"Description of the time series.","required":false,"dtype":"text","default_value":"no description"},{"name":"comments","doc":"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.","required":false,"dtype":"text","default_value":"no comments"}]},{"datasets":[{"dtype":"text","name":"description","doc":"Description of stimulation site."},{"dtype":"float","name":"excitation_lambda","doc":"Excitation wavelength, in nm."},{"dtype":"text","name":"location","doc":"Location of the stimulation site. Specify the area, layer, comments on estimation of area/layer, stereotaxic coordinates if in vivo, etc. Use standard atlas names for anatomical regions when possible."}],"links":[{"name":"device","doc":"Device that generated the stimulus.","target_type":"Device"}],"doc":"A site of optogenetic stimulation.","quantity":"*","neurodata_type_inc":"NWBContainer","neurodata_type_def":"OptogeneticStimulusSite"}]}`4F'^4F'^5F'^SNOD8XxO(HHhPS(T5F'^(5F'^85F'^GCOLw4{"groups":[{"datasets":[{"shape":[[null],[null,null],[null,null,null]],"dims":[["num_times"],["num_times","num_channels"],["num_times","num_channels","num_samples"]],"dtype":"numeric","name":"data","doc":"Recorded voltage data.","attributes":[{"name":"unit","doc":"Base unit of measurement for working with the data. This value is fixed to 'volts'. Actual stored values are not necessarily stored in these units. To access the data in these units, multiply 'data' by 'conversion' and 'channel_conversion' (if present).","dtype":"text","value":"volts"},{"name":"conversion","doc":"Scalar to multiply each element in data to convert it to the specified 'unit'. If the data are stored in acquisition system units or other units that require a conversion to be interpretable, multiply the data by 'conversion' to convert the data to the specified 'unit'. e.g. if the data acquisition system stores values in this object as signed 16-bit integers (int16 range -32,768 to 32,767) that correspond to a 5V range (-2.5V to 2.5V), and the data acquisition system gain is 8000X, then the 'conversion' multiplier to get from raw data acquisition values to recorded volts is 2.5/32768/8000 = 9.5367e-9.","required":false,"dtype":"float32","default_value":1.0},{"name":"resolution","doc":"Smallest meaningful difference between values in data, stored in the specified by unit, 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 -1.0.","required":false,"dtype":"float32","default_value":-1.0}]},{"name":"electrodes","doc":"DynamicTableRegion pointer to the electrodes that this time series was generated from.","neurodata_type_inc":"DynamicTableRegion"},{"shape":[null],"dims":["num_channels"],"dtype":"float","name":"channel_conversion","doc":"Channel-specific conversion factor. Multiply the data in the 'data' dataset by these values along the channel axis (as indicated by axis attribute) AND by the global conversion factor in the 'conversion' attribute of 'data' to get the data values in Volts, i.e, data in Volts = data * data.conversion * channel_conversion. This approach allows for both global and per-channel data conversion factors needed to support the storage of electrical recordings as native values generated by data acquisition systems. If this dataset is not present, then there is no channel-specific conversion factor, i.e. it is 1 for all channels.","quantity":"?","attributes":[{"name":"axis","doc":"The zero-indexed axis of the 'data' dataset that the channel-specific conversion factor corresponds to. This value is fixed to 1.","dtype":"int","value":1}]}],"doc":"A time series of acquired voltage data from extracellular recordings. The data field is an int or float array storing data in volts. The first dimension should always represent time. The second dimension, if present, should represent channels.","neurodata_type_inc":"TimeSeries","neurodata_type_def":"ElectricalSeries","attributes":[{"name":"description","doc":"Description of the time series.","required":false,"dtype":"text","default_value":"no description"},{"name":"comments","doc":"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.","required":false,"dtype":"text","default_value":"no comments"}]},{"datasets":[{"shape":[[null,null],[null,null,null]],"dims":[["num_events","num_samples"],["num_events","num_channels","num_samples"]],"dtype":"numeric","name":"data","doc":"Spike waveforms.","attributes":[{"name":"unit","doc":"Unit of measurement for waveforms, which is fixed to 'volts'.","dtype":"text","value":"volts"},{"name":"conversion","doc":"Scalar to multiply each element in data to convert it to the specified 'unit'. If the data are stored in acquisition system units or other units that require a conversion to be interpretable, multiply the data by 'conversion' to convert the data to the specified 'unit'. e.g. if the data acquisition system stores values in this object as signed 16-bit integers (int16 range -32,768 to 32,767) that correspond to a 5V range (-2.5V to 2.5V), and the data acquisition system gain is 8000X, then the 'conversion' multiplier to get from raw data acquisition values to recorded volts is 2.5/32768/8000 = 9.5367e-9.","required":false,"dtype":"float32","default_value":1.0},{"name":"resolution","doc":"Smallest meaningful difference between values in data, stored in the specified by unit, 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 -1.0.","required":false,"dtype":"float32","default_value":-1.0}]},{"shape":[null],"dims":["num_times"],"dtype":"float64","name":"timestamps","doc":"Timestamps for samples stored in data, in seconds, relative to the common experiment master-clock stored in NWBFile.timestamps_reference_time. Timestamps are required for the events. Unlike for TimeSeries, timestamps are required for SpikeEventSeries and are thus re-specified here.","attributes":[{"name":"interval","doc":"Value is '1'","dtype":"int32","value":1},{"name":"unit","doc":"Unit of measurement for timestamps, which is fixed to 'seconds'.","dtype":"text","value":"seconds"}]}],"doc":"Stores snapshots/snippets of recorded spike events (i.e., threshold crossings). This may also be raw data, as reported by ephys hardware. If so, the TimeSeries::description field should describe how events were detected. All SpikeEventSeries should reside in a module (under EventWaveform interface) even if the spikes were reported and stored by hardware. All events span the same recording channels and store snapshots of equal duration. TimeSeries::data array structure: [num events] [num channels] [num samples] (or [num events] [num samples] for single electrode).","neurodata_type_inc":"ElectricalSeries","neurodata_type_def":"SpikeEventSeries","attributes":[{"name":"description","doc":"Description of the time series.","required":false,"dtype":"text","default_value":"no description"},{"name":"comments","doc":"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.","required":false,"dtype":"text","default_value":"no comments"}]},{"datasets":[{"shape":[null],"dims":["num_features"],"dtype":"text","name":"description","doc":"Description of features (eg, ''PC1'') for each of the extracted features."},{"shape":[null,null,null],"dims":["num_events","num_channels","num_features"],"dtype":"float32","name":"features","doc":"Multi-dimensional array of features extracted from each event."},{"shape":[null],"dims":["num_events"],"dtype":"float64","name":"times","doc":"Times of events that features correspond to (can be a link)."},{"name":"electrodes","doc":"DynamicTableRegion pointer to the electrodes that this time series was generated from.","neurodata_type_inc":"DynamicTableRegion"}],"doc":"Features, such as PC1 and PC2, that are extracted from signals stored in a SpikeEventSeries or other source.","default_name":"FeatureExtraction","neurodata_type_inc":"NWBDataInterface","neurodata_type_def":"FeatureExtraction"},{"datasets":[{"dtype":"text","name":"detection_method","doc":"Description of how events were detected, such as voltage threshold, or dV/dT threshold, as well as relevant values."},{"shape":[null],"dims":["num_events"],"dtype":"int32","name":"source_idx","doc":"Indices (zero-based) into source ElectricalSeries::data array corresponding to time of event. ''description'' should define what is meant by time of event (e.g., .25 ms before action potential peak, zero-crossing time, etc). The index points to each event from the raw data."},{"shape":[null],"dims":["num_events"],"dtype":"float64","name":"times","doc":"Timestamps of events, in seconds.","attributes":[{"name":"unit","doc":"Unit of measurement for event times, which is fixed to 'seconds'.","dtype":"text","value":"seconds"}]}],"links":[{"name":"source_electricalseries","doc":"Link to the ElectricalSeries that this data was calculated from. Metadata about electrodes and their position can be read from that ElectricalSeries so it's not necessary to include that information here.","target_type":"ElectricalSeries"}],"doc":"Detected spike events from voltage trace(s).","default_name":"EventDetection","neurodata_type_inc":"NWBDataInterface","neurodata_type_def":"EventDetection"},{"groups":[{"doc":"SpikeEventSeries object(s) containing detected spike event waveforms.","quantity":"*","neurodata_type_inc":"SpikeEventSeries"}],"doc":"Represents either the waveforms of detected events, as extracted from a raw data trace in /acquisition, or the event waveforms that were stored during experiment acquisition.","default_name":"EventWaveform","neurodata_type_inc":"NWBDataInterface","neurodata_type_def":"EventWaveform"},{"groups":[{"doc":"ElectricalSeries object(s) containing filtered electrophysiology data.","quantity":"+","neurodata_type_inc":"ElectricalSeries"}],"doc":"Electrophysiology data from one or more channels that has been subjected to filtering. Examples of filtered data include Theta and Gamma (LFP has its own interface). FilteredEphys modules publish an ElectricalSeries for each filtered channel or set of channels. The name of each ElectricalSeries is arbitrary but should be informative. The source of the filtered data, whether this is from analysis of another time series or as acquired by hardware, should be noted in each's TimeSeries::description field. There is no assumed 1::1 correspondence between filtered ephys signals and electrodes, as a single signal can apply to many nearby electrodes, and one electrode may have different filtered (e.g., theta and/or gamma) signals represented. Filter properties should be noted in the ElectricalSeries.","default_name":"FilteredEphys","neurodata_type_inc":"NWBDataInterface","neurodata_type_def":"FilteredEphys"},{"groups":[{"doc":"ElectricalSeries object(s) containing LFP data for one or more channels.","quantity":"+","neurodata_type_inc":"ElectricalSeries"}],"doc":"LFP data from one or more channels. The electrode map in each published ElectricalSeries will identify which channels are providing LFP data. Filter properties should be noted in the ElectricalSeries description or comments field.","default_name":"LFP","neurodata_type_inc":"NWBDataInterface","neurodata_type_def":"LFP"},{"links":[{"name":"device","doc":"Link to the device that was used to record from this electrode group.","target_type":"Device"}],"doc":"A physical grouping of electrodes, e.g. a shank of an array.","neurodata_type_inc":"NWBContainer","neurodata_type_def":"ElectrodeGroup","attributes":[{"name":"description","doc":"Description of this electrode group.","dtype":"text"},{"name":"location","doc":"Location of electrode group. Specify the area, layer, comments on estimation of area/layer, stereotaxic coordinates if in vivo, etc. Use standard atlas names for anatomical regions when possible.","dtype":"text"}]},{"datasets":[{"dtype":"text","name":"waveform_filtering","doc":"Filtering applied to data before generating mean/sd"},{"shape":[null,null],"dims":["num_clusters","num_samples"],"dtype":"float32","name":"waveform_mean","doc":"The mean waveform for each cluster, using the same indices for each wave as cluster numbers in the associated Clustering module (i.e, cluster 3 is in array slot [3]). Waveforms corresponding to gaps in cluster sequence should be empty (e.g., zero- filled)"},{"shape":[null,null],"dims":["num_clusters","num_samples"],"dtype":"float32","name":"waveform_sd","doc":"Stdev of waveforms for each cluster, using the same indices as in mean"}],"links":[{"name":"clustering_interface","doc":"Link to Clustering interface that was the source of the clustered data","target_type":"Clustering"}],"doc":"DEPRECATED The mean waveform shape, including standard deviation, of the different clusters. Ideally, the waveform analysis should be performed on data that is only high-pass filtered. This is a separate module because it is expected to require updating. For example, IMEC probes may require different storage requirements to store/display mean waveforms, requiring a new interface or an extension of this one.","default_name":"ClusterWaveforms","neurodata_type_inc":"NWBDataInterface","neurodata_type_def":"ClusterWaveforms"},{"datasets":[{"dtype":"text","name":"description","doc":"Description of clusters or clustering, (e.g. cluster 0 is noise, clusters curated using Klusters, etc)"},{"shape":[null],"dims":["num_events"],"dtype":"int32","name":"num","doc":"Cluster number of each event"},{"shape":[null],"dims":["num_clusters"],"dtype":"float32","name":"peak_over_rms","doc":"Maximum ratio of waveform peak to RMS on any channel in the cluster (provides a basic clustering metric)."},{"shape":[null],"dims":["num_events"],"dtype":"float64","name":"times","doc":"Times of clustered events, in seconds. This may be a link to times field in associated FeatureExtraction module."}],"doc":"DEPRECATED Clustered spike data, whether from automatic clustering tools (e.g., klustakwik) or as a result of manual sorting.","default_name":"Clustering","neurodata_type_inc":"NWBDataInterface","neurodata_type_def":"Clustering"}]}B{"groups":[{"datasets":[{"shape":[null],"dims":["num_times"],"dtype":"numeric","name":"data","doc":"Recorded voltage or current.","attributes":[{"name":"unit","doc":"Base unit of measurement for working with the data. Actual stored values are not necessarily stored in these units. To access the data in these units, multiply 'data' by 'conversion'.","dtype":"text"},{"name":"conversion","doc":"Scalar to multiply each element in data to convert it to the specified 'unit'. If the data are stored in acquisition system units or other units that require a conversion to be interpretable, multiply the data by 'conversion' to convert the data to the specified 'unit'. e.g. if the data acquisition system stores values in this object as signed 16-bit integers (int16 range -32,768 to 32,767) that correspond to a 5V range (-2.5V to 2.5V), and the data acquisition system gain is 8000X, then the 'conversion' multiplier to get from raw data acquisition values to recorded volts is 2.5/32768/8000 = 9.5367e-9.","required":false,"dtype":"float32","default_value":1.0},{"name":"resolution","doc":"Smallest meaningful difference between values in data, stored in the specified by unit, 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 -1.0.","required":false,"dtype":"float32","default_value":-1.0}]},{"dtype":"float","name":"gain","doc":"Gain of the recording, in units Volt/Amp (v-clamp) or Volt/Volt (c-clamp).","quantity":"?"}],"links":[{"name":"electrode","doc":"Link to IntracellularElectrode object that describes the electrode that was used to apply or record this data.","target_type":"IntracellularElectrode"}],"doc":"An abstract base class for patch-clamp data - stimulus or response, current or voltage.","neurodata_type_inc":"TimeSeries","neurodata_type_def":"PatchClampSeries","attributes":[{"name":"stimulus_description","doc":"Protocol/stimulus name for this patch-clamp dataset.","dtype":"text"},{"name":"sweep_number","doc":"Sweep number, allows to group different PatchClampSeries together.","required":false,"dtype":"uint64"},{"name":"description","doc":"Description of the time series.","required":false,"dtype":"text","default_value":"no description"},{"name":"comments","doc":"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.","required":false,"dtype":"text","default_value":"no comments"}]},{"datasets":[{"name":"data","doc":"Recorded voltage.","attributes":[{"name":"unit","doc":"Base unit of measurement for working with the data. which is fixed to 'volts'. Actual stored values are not necessarily stored in these units. To access the data in these units, multiply 'data' by 'conversion'.","dtype":"text","value":"volts"},{"name":"conversion","doc":"Scalar to multiply each element in data to convert it to the specified 'unit'. If the data are stored in acquisition system units or other units that require a conversion to be interpretable, multiply the data by 'conversion' to convert the data to the specified 'unit'. e.g. if the data acquisition system stores values in this object as signed 16-bit integers (int16 range -32,768 to 32,767) that correspond to a 5V range (-2.5V to 2.5V), and the data acquisition system gain is 8000X, then the 'conversion' multiplier to get from raw data acquisition values to recorded volts is 2.5/32768/8000 = 9.5367e-9.","required":false,"dtype":"float32","default_value":1.0},{"name":"resolution","doc":"Smallest meaningful difference between values in data, stored in the specified by unit, 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 -1.0.","required":false,"dtype":"float32","default_value":-1.0}]},{"dtype":"float32","name":"bias_current","doc":"Bias current, in amps.","quantity":"?"},{"dtype":"float32","name":"bridge_balance","doc":"Bridge balance, in ohms.","quantity":"?"},{"dtype":"float32","name":"capacitance_compensation","doc":"Capacitance compensation, in farads.","quantity":"?"}],"doc":"Voltage data from an intracellular current-clamp recording. A corresponding CurrentClampStimulusSeries (stored separately as a stimulus) is used to store the current injected.","neurodata_type_inc":"PatchClampSeries","neurodata_type_def":"CurrentClampSeries","attributes":[{"name":"stimulus_description","doc":"Protocol/stimulus name for this patch-clamp dataset.","dtype":"text"},{"name":"sweep_number","doc":"Sweep number, allows to group different PatchClampSeries together.","required":false,"dtype":"uint64"},{"name":"description","doc":"Description of the time series.","required":false,"dtype":"text","default_value":"no description"},{"name":"comments","doc":"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.","required":false,"dtype":"text","default_value":"no comments"}]},{"datasets":[{"dtype":"float32","name":"bias_current","doc":"Bias current, in amps, fixed to 0.0."},{"dtype":"float32","name":"bridge_balance","doc":"Bridge balance, in ohms, fixed to 0.0."},{"dtype":"float32","name":"capacitance_compensation","doc":"Capacitance compensation, in farads, fixed to 0.0."}],"doc":"Voltage data from an intracellular recording when all current and amplifier settings are off (i.e., CurrentClampSeries fields will be zero). There is no CurrentClampStimulusSeries associated with an IZero series because the amplifier is disconnected and no stimulus can reach the cell.","neurodata_type_inc":"CurrentClampSeries","neurodata_type_def":"IZeroClampSeries","attributes":[{"name":"stimulus_description","doc":"Protocol/stimulus name for this patch-clamp dataset.","dtype":"text"},{"name":"sweep_number","doc":"Sweep number, allows to group different PatchClampSeries together.","required":false,"dtype":"uint64"},{"name":"description","doc":"Description of the time series.","required":false,"dtype":"text","default_value":"no description"},{"name":"comments","doc":"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.","required":false,"dtype":"text","default_value":"no comments"}]},{"datasets":[{"name":"data","doc":"Stimulus current applied.","attributes":[{"name":"unit","doc":"Base unit of measurement for working with the data. which is fixed to 'amperes'. Actual stored values are not necessarily stored in these units. To access the data in these units, multiply 'data' by 'conversion'.","dtype":"text","value":"amperes"},{"name":"conversion","doc":"Scalar to multiply each element in data to convert it to the specified 'unit'. If the data are stored in acquisition system units or other units that require a conversion to be interpretable, multiply the data by 'conversion' to convert the data to the specified 'unit'. e.g. if the data acquisition system stores values in this object as signed 16-bit integers (int16 range -32,768 to 32,767) that correspond to a 5V range (-2.5V to 2.5V), and the data acquisition system gain is 8000X, then the 'conversion' multiplier to get from raw data acquisition values to recorded volts is 2.5/32768/8000 = 9.5367e-9.","required":false,"dtype":"float32","default_value":1.0},{"name":"resolution","doc":"Smallest meaningful difference between values in data, stored in the specified by unit, 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 -1.0.","required":false,"dtype":"float32","default_value":-1.0}]}],"doc":"Stimulus current applied during current clamp recording.","neurodata_type_inc":"PatchClampSeries","neurodata_type_def":"CurrentClampStimulusSeries","attributes":[{"name":"stimulus_description","doc":"Protocol/stimulus name for this patch-clamp dataset.","dtype":"text"},{"name":"sweep_number","doc":"Sweep number, allows to group different PatchClampSeries together.","required":false,"dtype":"uint64"},{"name":"description","doc":"Description of the time series.","required":false,"dtype":"text","default_value":"no description"},{"name":"comments","doc":"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.","required":false,"dtype":"text","default_value":"no comments"}]},{"datasets":[{"name":"data","doc":"Recorded current.","attributes":[{"name":"unit","doc":"Base unit of measurement for working with the data. which is fixed to 'amperes'. Actual stored values are not necessarily stored in these units. To access the data in these units, multiply 'data' by 'conversion'.","dtype":"text","value":"amperes"},{"name":"conversion","doc":"Scalar to multiply each element in data to convert it to the specified 'unit'. If the data are stored in acquisition system units or other units that require a conversion to be interpretable, multiply the data by 'conversion' to convert the data to the specified 'unit'. e.g. if the data acquisition system stores values in this object as signed 16-bit integers (int16 range -32,768 to 32,767) that correspond to a 5V range (-2.5V to 2.5V), and the data acquisition system gain is 8000X, then the 'conversion' multiplier to get from raw data acquisition values to recorded volts is 2.5/32768/8000 = 9.5367e-9.","required":false,"dtype":"float32","default_value":1.0},{"name":"resolution","doc":"Smallest meaningful difference between values in data, stored in the specified by unit, 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 -1.0.","required":false,"dtype":"float32","default_value":-1.0}]},{"dtype":"float32","name":"capacitance_fast","doc":"Fast capacitance, in farads.","quantity":"?","attributes":[{"name":"unit","doc":"Unit of measurement for capacitance_fast, which is fixed to 'farads'.","dtype":"text","value":"farads"}]},{"dtype":"float32","name":"capacitance_slow","doc":"Slow capacitance, in farads.","quantity":"?","attributes":[{"name":"unit","doc":"Unit of measurement for capacitance_fast, which is fixed to 'farads'.","dtype":"text","value":"farads"}]},{"dtype":"float32","name":"resistance_comp_bandwidth","doc":"Resistance compensation bandwidth, in hertz.","quantity":"?","attributes":[{"name":"unit","doc":"Unit of measurement for resistance_comp_bandwidth, which is fixed to 'hertz'.","dtype":"text","value":"hertz"}]},{"dtype":"float32","name":"resistance_comp_correction","doc":"Resistance compensation correction, in percent.","quantity":"?","attributes":[{"name":"unit","doc":"Unit of measurement for resistance_comp_correction, which is fixed to 'percent'.","dtype":"text","value":"percent"}]},{"dtype":"float32","name":"resistance_comp_prediction","doc":"Resistance compensation prediction, in percent.","quantity":"?","attributes":[{"name":"unit","doc":"Unit of measurement for resistance_comp_prediction, which is fixed to 'percent'.","dtype":"text","value":"percent"}]},{"dtype":"float32","name":"whole_cell_capacitance_comp","doc":"Whole cell capacitance compensation, in farads.","quantity":"?","attributes":[{"name":"unit","doc":"Unit of measurement for whole_cell_capacitance_comp, which is fixed to 'farads'.","dtype":"text","value":"farads"}]},{"dtype":"float32","name":"whole_cell_series_resistance_comp","doc":"Whole cell series resistance compensation, in ohms.","quantity":"?","attributes":[{"name":"unit","doc":"Unit of measurement for whole_cell_series_resistance_comp, which is fixed to 'ohms'.","dtype":"text","value":"ohms"}]}],"doc":"Current data from an intracellular voltage-clamp recording. A corresponding VoltageClampStimulusSeries (stored separately as a stimulus) is used to store the voltage injected.","neurodata_type_inc":"PatchClampSeries","neurodata_type_def":"VoltageClampSeries","attributes":[{"name":"stimulus_description","doc":"Protocol/stimulus name for this patch-clamp dataset.","dtype":"text"},{"name":"sweep_number","doc":"Sweep number, allows to group different PatchClampSeries together.","required":false,"dtype":"uint64"},{"name":"description","doc":"Description of the time series.","required":false,"dtype":"text","default_value":"no description"},{"name":"comments","doc":"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.","required":false,"dtype":"text","default_value":"no comments"}]},{"datasets":[{"name":"data","doc":"Stimulus voltage applied.","attributes":[{"name":"unit","doc":"Base unit of measurement for working with the data. which is fixed to 'volts'. Actual stored values are not necessarily stored in these units. To access the data in these units, multiply 'data' by 'conversion'.","dtype":"text","value":"volts"},{"name":"conversion","doc":"Scalar to multiply each element in data to convert it to the specified 'unit'. If the data are stored in acquisition system units or other units that require a conversion to be interpretable, multiply the data by 'conversion' to convert the data to the specified 'unit'. e.g. if the data acquisition system stores values in this object as signed 16-bit integers (int16 range -32,768 to 32,767) that correspond to a 5V range (-2.5V to 2.5V), and the data acquisition system gain is 8000X, then the 'conversion' multiplier to get from raw data acquisition values to recorded volts is 2.5/32768/8000 = 9.5367e-9.","required":false,"dtype":"float32","default_value":1.0},{"name":"resolution","doc":"Smallest meaningful difference between values in data, stored in the specified by unit, 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 -1.0.","required":false,"dtype":"float32","default_value":-1.0}]}],"doc":"Stimulus voltage applied during a voltage clamp recording.","neurodata_type_inc":"PatchClampSeries","neurodata_type_def":"VoltageClampStimulusSeries","attributes":[{"name":"stimulus_description","doc":"Protocol/stimulus name for this patch-clamp dataset.","dtype":"text"},{"name":"sweep_number","doc":"Sweep number, allows to group different PatchClampSeries together.","required":false,"dtype":"uint64"},{"name":"description","doc":"Description of the time series.","required":false,"dtype":"text","default_value":"no description"},{"name":"comments","doc":"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.","required":false,"dtype":"text","default_value":"no comments"}]},{"datasets":[{"dtype":"text","name":"description","doc":"Description of electrode (e.g., whole-cell, sharp, etc.)."},{"dtype":"text","name":"filtering","doc":"Electrode specific filtering.","quantity":"?"},{"dtype":"text","name":"initial_access_resistance","doc":"Initial access resistance.","quantity":"?"},{"dtype":"text","name":"location","doc":"Location of the electrode. Specify the area, layer, comments on estimation of area/layer, stereotaxic coordinates if in vivo, etc. Use standard atlas names for anatomical regions when possible.","quantity":"?"},{"dtype":"text","name":"resistance","doc":"Electrode resistance, in ohms.","quantity":"?"},{"dtype":"text","name":"seal","doc":"Information about seal used for recording.","quantity":"?"},{"dtype":"text","name":"slice","doc":"Information about slice used for recording.","quantity":"?"}],"links":[{"name":"device","doc":"Device that was used to record from this electrode.","target_type":"Device"}],"doc":"An intracellular electrode and its metadata.","neurodata_type_inc":"NWBContainer","neurodata_type_def":"IntracellularElectrode"},{"datasets":[{"dtype":"uint64","name":"sweep_number","doc":"Sweep number of the PatchClampSeries in that row.","neurodata_type_inc":"VectorData"},{"dtype":{"target_type":"PatchClampSeries","reftype":"object"},"name":"series","doc":"The PatchClampSeries with the sweep number in that row.","neurodata_type_inc":"VectorData"},{"name":"series_index","doc":"Index for series.","neurodata_type_inc":"VectorIndex"}],"doc":"The table which groups different PatchClampSeries together.","neurodata_type_inc":"DynamicTable","neurodata_type_def":"SweepTable","attributes":[{"name":"colnames","doc":"The names of the columns in this table. This should be used to specify an order to the columns.","dtype":"ascii","shape":[null],"dims":["num_columns"]},{"name":"description","doc":"Description of what is in this dynamic table.","dtype":"text"}]}]},{"groups":[{"datasets":[{"shape":[[2],[3]],"dims":["width|height","width|height|depth"],"dtype":"float32","name":"field_of_view","doc":"Width, height and depth of image, or imaged area, in meters.","quantity":"?"}],"links":[{"name":"imaging_plane","doc":"Link to ImagingPlane object from which this TimeSeries data was generated.","target_type":"ImagingPlane"}],"doc":"Image stack recorded over time from 2-photon microscope.","neurodata_type_inc":"ImageSeries","neurodata_type_def":"TwoPhotonSeries","attributes":[{"name":"pmt_gain","doc":"Photomultiplier gain.","required":false,"dtype":"float32"},{"name":"scan_line_rate","doc":"Lines imaged per second. This is also stored in /general/optophysiology but is kept here as it is useful information for analysis, and so good to be stored w/ the actual data.","required":false,"dtype":"float32"},{"name":"description","doc":"Description of the time series.","required":false,"dtype":"text","default_value":"no description"},{"name":"comments","doc":"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.","required":false,"dtype":"text","default_value":"no comments"}]},{"datasets":[{"shape":[[null],[null,null]],"dims":[["num_times"],["num_times","num_ROIs"]],"dtype":"numeric","name":"data","doc":"Signals from ROIs.","attributes":[{"name":"conversion","doc":"Scalar to multiply each element in data to convert it to the specified 'unit'. If the data are stored in acquisition system units or other units that require a conversion to be interpretable, multiply the data by 'conversion' to convert the data to the specified 'unit'. e.g. if the data acquisition system stores values in this object as signed 16-bit integers (int16 range -32,768 to 32,767) that correspond to a 5V range (-2.5V to 2.5V), and the data acquisition system gain is 8000X, then the 'conversion' multiplier to get from raw data acquisition values to recorded volts is 2.5/32768/8000 = 9.5367e-9.","required":false,"dtype":"float32","default_value":1.0},{"name":"resolution","doc":"Smallest meaningful difference between values in data, stored in the specified by unit, 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 -1.0.","required":false,"dtype":"float32","default_value":-1.0},{"name":"unit","doc":"Base unit of measurement for working with the data. Actual stored values are not necessarily stored in these units. To access the data in these units, multiply 'data' by 'conversion'.","dtype":"text"}]},{"name":"rois","doc":"DynamicTableRegion referencing into an ROITable containing information on the ROIs stored in this timeseries.","neurodata_type_inc":"DynamicTableRegion"}],"doc":"ROI responses over an imaging plane. Each row in data should correspond to the signal from one ROI. Each element on the second dimension of data should correspond to the signal from one ROI.","neurodata_type_inc":"TimeSeries","neurodata_type_def":"RoiResponseSeries","attributes":[{"name":"description","doc":"Description of the time series.","required":false,"dtype":"text","default_value":"no description"},{"name":"comments","doc":"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.","required":false,"dtype":"text","default_value":"no comments"}]},{"groups":[{"doc":"RoiResponseSeries object(s) containing dF/F for a ROI.","quantity":"+","neurodata_type_inc":"RoiResponseSeries"}],"doc":"dF/F information about a region of interest (ROI). Storage hierarchy of dF/F should be the same as for segmentation (i.e., same names for ROIs and for image planes).","default_name":"DfOverF","neurodata_type_inc":"NWBDataInterface","neurodata_type_def":"DfOverF"},{"groups":[{"doc":"RoiResponseSeries object(s) containing fluorescence data for a ROI.","quantity":"+","neurodata_type_inc":"RoiResponseSeries"}],"doc":"Fluorescence information about a region of interest (ROI). Storage hierarchy of fluorescence should be the same as for segmentation (ie, same names for ROIs and for image planes).","default_name":"Fluorescence","neurodata_type_inc":"NWBDataInterface","neurodata_type_def":"Fluorescence"},{"groups":[{"groups":[{"groups":[{"doc":"One or more image stacks that the masks apply to (can be one-element stack).","quantity":"*","neurodata_type_inc":"ImageSeries"}],"name":"reference_images","doc":"Image stacks that the segmentation masks apply to."}],"datasets":[{"shape":[[null,null,null],[null,null,null,null]],"dims":[["num_roi","num_x","num_y"],["num_roi","num_x","num_y","num_z"]],"name":"image_mask","doc":"ROI masks for each ROI. Each image mask is the size of the original imaging plane (or volume) and members of the ROI are finite non-zero.","quantity":"?","neurodata_type_inc":"VectorData"},{"name":"pixel_mask_index","doc":"Index into pixel_mask.","quantity":"?","neurodata_type_inc":"VectorIndex"},{"dtype":[{"doc":"Pixel x-coordinate.","name":"x","dtype":"uint"},{"doc":"Pixel y-coordinate.","name":"y","dtype":"uint"},{"doc":"Weight of the pixel.","name":"weight","dtype":"float"}],"name":"pixel_mask","doc":"Pixel masks for each ROI: a list of indices and weights for the ROI. Pixel masks are concatenated and parsing of this dataset is maintained by the PlaneSegmentation","quantity":"?","neurodata_type_inc":"VectorData"},{"name":"voxel_mask_index","doc":"Index into voxel_mask.","quantity":"?","neurodata_type_inc":"VectorIndex"},{"dtype":[{"doc":"Voxel x-coordinate.","name":"x","dtype":"uint"},{"doc":"Voxel y-coordinate.","name":"y","dtype":"uint"},{"doc":"Voxel z-coordinate.","name":"z","dtype":"uint"},{"doc":"Weight of the voxel.","name":"weight","dtype":"float"}],"name":"voxel_mask","doc":"Voxel masks for each ROI: a list of indices and weights for the ROI. Voxel masks are concatenated and parsing of this dataset is maintained by the PlaneSegmentation","quantity":"?","neurodata_type_inc":"VectorData"},{"shape":[null],"dims":["num_rows"],"dtype":"int","name":"id","doc":"Array of unique identifiers for the rows of this dynamic table.","neurodata_type_inc":"ElementIdentifiers"},{"doc":"Vector columns of this dynamic table.","quantity":"*","neurodata_type_inc":"VectorData"},{"doc":"Indices for the vector columns of this dynamic table.","quantity":"*","neurodata_type_inc":"VectorIndex"}],"links":[{"name":"imaging_plane","doc":"Link to ImagingPlane object from which this data was generated.","target_type":"ImagingPlane"}],"doc":"Results from image segmentation of a specific imaging plane.","quantity":"+","neurodata_type_inc":"DynamicTable","neurodata_type_def":"PlaneSegmentation","attributes":[{"name":"colnames","doc":"The names of the columns in this table. This should be used to specify an order to the columns.","dtype":"ascii","shape":[null],"dims":["num_columns"]},{"name":"description","doc":"Description of what is in this dynamic table.","dtype":"text"}]}],"doc":"Stores pixels in an image that represent different regions of interest (ROIs) or masks. All segmentation for a given imaging plane is stored together, with storage for multiple imaging planes (masks) supported. Each ROI is stored in its own subgroup, with the ROI group containing both a 2D mask and a list of pixels that make up this mask. Segments can also be used for masking neuropil. If segmentation is allowed to change with time, a new imaging plane (or module) is required and ROI names should remain consistent between them.","default_name":"ImageSegmentation","neurodata_type_inc":"NWBDataInterface","neurodata_type_def":"ImageSegmentation"},{"groups":[{"datasets":[{"dtype":"text","name":"description","doc":"Description or other notes about the channel."},{"dtype":"float","name":"emission_lambda","doc":"Emission wavelength for channel, in nm."}],"doc":"An optical channel used to record from an imaging plane.","neurodata_type_inc":"NWBContainer","neurodata_type_def":"OpticalChannel"}],"datasets":[{"dtype":"text","name":"description","doc":"Description of the imaging plane.","quantity":"?"},{"dtype":"float","name":"excitation_lambda","doc":"Excitation wavelength, in nm."},{"dtype":"float","name":"imaging_rate","doc":"Rate that images are acquired, in Hz."},{"dtype":"text","name":"indicator","doc":"Calcium indicator."},{"dtype":"text","name":"location","doc":"Location of the imaging plane. Specify the area, layer, comments on estimation of area/layer, stereotaxic coordinates if in vivo, etc. Use standard atlas names for anatomical regions when possible."},{"shape":[[null,null,3],[null,null,null,3]],"dims":[["height","width","x|y|z"],["height","width","depth","x|y|z"]],"dtype":"float32","name":"manifold","doc":"Physical position of each pixel. 'xyz' represents the position of the pixel relative to the defined coordinate space.","quantity":"?","attributes":[{"name":"conversion","doc":"Scalar to multiply each element in data to convert it to the specified 'unit'. If the data are stored in acquisition system units or other units that require a conversion to be interpretable, multiply the data by 'conversion' to convert the data to the specified 'unit'. e.g. if the data acquisition system stores values in this object as pixels from x = -500 to 499, y = -500 to 499 that correspond to a 2 m x 2 m range, then the 'conversion' multiplier to get from raw data acquisition pixel units to meters is 2/1000.","required":false,"dtype":"float","default_value":1.0},{"name":"unit","doc":"Base unit of measurement for working with the data. The default value is 'meters'.","required":false,"dtype":"text","default_value":"meters"}]},{"dtype":"text","name":"reference_frame","doc":"Describes position and reference frame of manifold based on position of first element in manifold. For example, text description of anatomical location or vectors needed to rotate to common anatomical axis (eg, AP/DV/ML). This field is necessary to interpret manifold. If manifold is not present then this field is not required.","quantity":"?"}],"links":[{"name":"device","doc":"Link to the Device object that was used to record from this electrode.","target_type":"Device"}],"doc":"An imaging plane and its metadata.","quantity":"*","neurodata_type_inc":"NWBContainer","neurodata_type_def":"ImagingPlane"},{"groups":[{"groups":[{"name":"corrected","doc":"Image stack with frames shifted to the common coordinates.","neurodata_type_inc":"ImageSeries"},{"name":"xy_translation","doc":"Stores the x,y delta necessary to align each frame to the common coordinates, for example, to align each frame to a reference image.","neurodata_type_inc":"TimeSeries"}],"links":[{"name":"original","doc":"Link to ImageSeries object that is being registered.","target_type":"ImageSeries"}],"doc":"Reuslts from motion correction of an image stack.","quantity":"+","neurodata_type_inc":"NWBDataInterface","neurodata_type_def":"CorrectedImageStack"}],"doc":"An image stack where all frames are shifted (registered) to a common coordinate system, to account for movement and drift between frames. Note: each frame at each point in time is assumed to be 2-D (has only x & y dimensions).","default_name":"MotionCorrection","neurodata_type_inc":"NWBDataInterface","neurodata_type_def":"MotionCorrection"}]}{"groups":[{"datasets":[{"shape":[null,null],"dims":["num_rows","num_cols"],"dtype":"float32","name":"axis_1_phase_map","doc":"Phase response to stimulus on the first measured axis.","attributes":[{"name":"dimension","doc":"Number of rows and columns in the image. NOTE: row, column representation is equivalent to height,width.","dtype":"int32","shape":[null],"dims":["row_col"]},{"name":"field_of_view","doc":"Size of viewing area, in meters.","dtype":"float","shape":[null],"dims":["row|column"]},{"name":"unit","doc":"Unit that axis data is stored in (e.g., degrees).","dtype":"text"}]},{"shape":[null,null],"dims":["num_rows","num_cols"],"dtype":"float32","name":"axis_1_power_map","doc":"Power response on the first measured axis. Response is scaled so 0.0 is no power in the response and 1.0 is maximum relative power.","quantity":"?","attributes":[{"name":"dimension","doc":"Number of rows and columns in the image. NOTE: row, column representation is equivalent to height,width.","dtype":"int32","shape":[null],"dims":["row_col"]},{"name":"field_of_view","doc":"Size of viewing area, in meters.","dtype":"float","shape":[null],"dims":["row_col"]},{"name":"unit","doc":"Unit that axis data is stored in (e.g., degrees).","dtype":"text"}]},{"shape":[null,null],"dims":["num_rows","num_cols"],"dtype":"float32","name":"axis_2_phase_map","doc":"Phase response to stimulus on the second measured axis.","attributes":[{"name":"dimension","doc":"Number of rows and columns in the image. NOTE: row, column representation is equivalent to height,width.","dtype":"int32","shape":[null],"dims":["row_col"]},{"name":"field_of_view","doc":"Size of viewing area, in meters.","dtype":"float","shape":[null],"dims":["row_col"]},{"name":"unit","doc":"Unit that axis data is stored in (e.g., degrees).","dtype":"text"}]},{"shape":[null,null],"dims":["num_rows","num_cols"],"dtype":"float32","name":"axis_2_power_map","doc":"Power response on the second measured axis. Response is scaled so 0.0 is no power in the response and 1.0 is maximum relative power.","quantity":"?","attributes":[{"name":"dimension","doc":"Number of rows and columns in the image. NOTE: row, column representation is equivalent to height,width.","dtype":"int32","shape":[null],"dims":["row_col"]},{"name":"field_of_view","doc":"Size of viewing area, in meters.","dtype":"float","shape":[null],"dims":["row_col"]},{"name":"unit","doc":"Unit that axis data is stored in (e.g., degrees).","dtype":"text"}]},{"shape":[2],"dims":["names"],"dtype":"text","name":"axis_descriptions","doc":"Two-element array describing the contents of the two response axis fields. Description should be something like ['altitude', 'azimuth'] or '['radius', 'theta']."},{"shape":[null,null],"dims":["num_rows","num_cols"],"dtype":"uint16","name":"focal_depth_image","doc":"Gray-scale image taken with same settings/parameters (e.g., focal depth, wavelength) as data collection. Array format: [rows][columns].","attributes":[{"name":"bits_per_pixel","doc":"Number of bits used to represent each value. This is necessary to determine maximum (white) pixel value.","dtype":"int32"},{"name":"dimension","doc":"Number of rows and columns in the image. NOTE: row, column representation is equivalent to height,width.","dtype":"int32","shape":[null],"dims":["row_col"]},{"name":"field_of_view","doc":"Size of viewing area, in meters.","dtype":"float","shape":[null],"dims":["row_col"]},{"name":"focal_depth","doc":"Focal depth offset, in meters.","dtype":"float"},{"name":"format","doc":"Format of image. Right now only 'raw' is supported.","dtype":"text"}]},{"shape":[null,null],"dims":["num_rows","num_cols"],"dtype":"float32","name":"sign_map","doc":"Sine of the angle between the direction of the gradient in axis_1 and axis_2.","attributes":[{"name":"dimension","doc":"Number of rows and columns in the image. NOTE: row, column representation is equivalent to height,width.","dtype":"int32","shape":[null],"dims":["row_col"]},{"name":"field_of_view","doc":"Size of viewing area, in meters.","dtype":"float","shape":[null],"dims":["row_col"]}]},{"shape":[null,null],"dims":["num_rows","num_cols"],"dtype":"uint16","name":"vasculature_image","doc":"Gray-scale anatomical image of cortical surface. Array structure: [rows][columns]","attributes":[{"name":"bits_per_pixel","doc":"Number of bits used to represent each value. This is necessary to determine maximum (white) pixel value","dtype":"int32"},{"name":"dimension","doc":"Number of rows and columns in the image. NOTE: row, column representation is equivalent to height,width.","dtype":"int32","shape":[null],"dims":["row_col"]},{"name":"field_of_view","doc":"Size of viewing area, in meters.","dtype":"float","shape":[null],"dims":["row_col"]},{"name":"format","doc":"Format of image. Right now only 'raw' is supported.","dtype":"text"}]}],"doc":"Intrinsic signal optical imaging or widefield imaging for measuring retinotopy. Stores orthogonal maps (e.g., altitude/azimuth; radius/theta) of responses to specific stimuli and a combined polarity map from which to identify visual areas. Note: for data consistency, all images and arrays are stored in the format [row][column] and [row, col], which equates to [y][x]. Field of view and dimension arrays may appear backward (i.e., y before x).","default_name":"ImagingRetinotopy","neurodata_type_inc":"NWBDataInterface","neurodata_type_def":"ImagingRetinotopy"}]}q{"namespaces":[{"doc":"NWB namespace","schema":[{"namespace":"hdmf-common"},{"source":"nwb.base"},{"source":"nwb.epoch"},{"source":"nwb.image"},{"source":"nwb.file"},{"source":"nwb.misc"},{"source":"nwb.behavior"},{"source":"nwb.ecephys"},{"source":"nwb.icephys"},{"source":"nwb.ogen"},{"source":"nwb.ophys"},{"source":"nwb.retinotopy"}],"name":"core","full_name":"NWB core","version":"2.1.0","author":["Andrew Tritt","Oliver Ruebel","Ryan Ly","Ben Dichter","Keith Godfrey","Jeff Teeters"],"contact":["ajtritt@lbl.gov","oruebel@lbl.gov","rly@lbl.gov","bdichter@lbl.gov","keithg@alleninstitute.org","jteeters@berkeley.edu"]}]}2pynwb-1.2.1/tests/back_compat/1.1.0_nwbfile.nwb0000644000655200065520000042626013612200244022524 0ustar circlecicircleci00000000000000HDF  ,` TREEHP/HEAP`- 0 .speclocpHhTREEHEAPXPSNOD Hh(Pp PH0XxPp TREEHEAPX P 0 TREEHEAPXP P TREE(HEAPX(presentationtemplates0TREEHEAPXPSNODhpTREEHEAPXPXxTREEHEAPXP H nwb_version1:<#]x GCOL 2019-11-27T17:32:32.461235-08:00ADDMEADDME 2019-11-27T17:32:32.460239-08:00 2019-11-27T17:32:32.460239-08:002.1.0coreNWBFile $35ee1e61-e948-479d-9a14-8ed8cbedd9f5 G{"groups":[{"datasets":[{"dtype":"float","name":"start_time","doc":"Start time of epoch, in seconds.","neurodata_type_inc":"VectorData"},{"dtype":"float","name":"stop_time","doc":"Stop time of epoch, in seconds.","neurodata_type_inc":"VectorData"},{"dtype":"text","name":"tags","doc":"User-defined tags that identify or categorize events.","quantity":"?","neurodata_type_inc":"VectorData"},{"name":"tags_index","doc":"Index for tags.","quantity":"?","neurodata_type_inc":"VectorIndex"},{"dtype":[{"doc":"Start index into the TimeSeries 'data' and 'timestamp' datasets of the referenced TimeSeries. The first dimension of those arrays is always time.","name":"idx_start","dtype":"int32"},{"doc":"Number of data samples available in this time series, during this epoch.","name":"count","dtype":"int32"},{"doc":"the TimeSeries that this index applies to.","name":"timeseries","dtype":{"target_type":"TimeSeries","reftype":"object"}}],"name":"timeseries","doc":"An index into a TimeSeries object.","quantity":"?","neurodata_type_inc":"VectorData"},{"name":"timeseries_index","doc":"Index for timeseries.","quantity":"?","neurodata_type_inc":"VectorIndex"}],"doc":"A container for aggregating epoch data and the TimeSeries that each epoch applies to.","neurodata_type_inc":"DynamicTable","neurodata_type_def":"TimeIntervals","attributes":[{"name":"colnames","doc":"The names of the columns in this table. This should be used to specify an order to the columns.","dtype":"ascii","shape":[null],"dims":["num_columns"]},{"name":"description","doc":"Description of what is in this dynamic table.","dtype":"text"}]}]}X2#]2#]2#]acquisitionanalysisprocessingstimulusgeneralfile_create_dateidentifiersession_descriptionsession_start_timetimestamps_reference_timespecificationsSNODh*(  0 x+,p:<8  02#] H namespace Hneurodata_type H object_id$ P  S'xFG y(u:u,1uu0@EB@E~ u,@E@EU@ETREE@HEAPX=coreH=?TREE DHEAPX?2.1.0HSNODX==?ACTREEmp@HEAP`tSNOD`AAC3#]GCOLx'S'{"datasets":[{"doc":"An abstract data type for a dataset.","neurodata_type_def":"NWBData"},{"doc":"Pointers that index data values.","neurodata_type_inc":"NWBData","neurodata_type_def":"Index","attributes":[{"name":"target","doc":"Target dataset that this index applies to.","dtype":{"target_type":"NWBData","reftype":"object"}}]},{"doc":"A 1-dimensional dataset. This can be indexed using a VectorIndex to encode a 2-dimensional ragged array in 1 dimension. The first vector is at VectorData[0:VectorIndex(0)+1]. The second vector is at VectorData[VectorIndex(0)+1:VectorIndex(1)+1]. And so on.","neurodata_type_inc":"NWBData","neurodata_type_def":"VectorData","attributes":[{"name":"description","doc":"Description of what these vectors represent.","dtype":"text"}]},{"doc":"An array of indices into the first dimension of the target VectorData. Can be used with VectorData to encode a 2-dimensional ragged array in 1 dimension.","neurodata_type_inc":"Index","neurodata_type_def":"VectorIndex","attributes":[{"name":"target","doc":"Reference to the target dataset that this index applies to.","dtype":{"target_type":"VectorData","reftype":"object"}}]},{"shape":[null],"dims":["num_elements"],"dtype":"int","doc":"A list of unique identifiers for values within a dataset, e.g. rows of a DynamicTable.","default_name":"element_id","neurodata_type_inc":"NWBData","neurodata_type_def":"ElementIdentifiers"},{"dtype":"int","doc":"A region/index into a DynamicTable.","neurodata_type_inc":"VectorData","neurodata_type_def":"DynamicTableRegion","attributes":[{"name":"table","doc":"Reference to the DynamicTable object that this region applies to.","dtype":{"target_type":"DynamicTable","reftype":"object"}},{"name":"description","doc":"Description of what this table region points to.","dtype":"text"}]},{"shape":[[null,null],[null,null,3],[null,null,4]],"dims":[["num_x","num_y"],["num_x","num_y","(r, g, b)"],["num_x","num_y","(r, g, b, a)"]],"doc":"An abstract data type for an image. Shape can be 2-D (x, y), or 3-D where the third dimension can have three or four elements, e.g. (x, y, (r, g, b)) or (x, y, (r, g, b, a)).","neurodata_type_inc":"NWBData","neurodata_type_def":"Image","attributes":[{"name":"resolution","doc":"Pixel resolution of the image, in pixels per centimeter.","required":false,"dtype":"float"},{"name":"description","doc":"Description of the image.","required":false,"dtype":"text"}]}],"groups":[{"doc":"An abstract data type for a generic container storing collections of data and metadata. Base type for all data and metadata containers.","neurodata_type_def":"NWBContainer"},{"doc":"An abstract data type for a generic container storing collections of data, as opposed to metadata.","neurodata_type_inc":"NWBContainer","neurodata_type_def":"NWBDataInterface"},{"groups":[{"name":"sync","doc":"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. 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.","quantity":"?"}],"datasets":[{"shape":[[null],[null,null],[null,null,null],[null,null,null,null]],"dims":[["num_times"],["num_times","num_DIM2"],["num_times","num_DIM2","num_DIM3"],["num_times","num_DIM2","num_DIM3","num_DIM4"]],"name":"data","doc":"Data values. Data can be in 1-D, 2-D, 3-D, or 4-D. The first dimension should always represent time. This can also be used to store binary data (e.g., image frames). This can also be a link to data stored in an external file.","attributes":[{"name":"conversion","doc":"Scalar to multiply each element in data to convert it to the specified 'unit'. If the data are stored in acquisition system units or other units that require a conversion to be interpretable, multiply the data by 'conversion' to convert the data to the specified 'unit'. e.g. if the data acquisition system stores values in this object as signed 16-bit integers (int16 range -32,768 to 32,767) that correspond to a 5V range (-2.5V to 2.5V), and the data acquisition system gain is 8000X, then the 'conversion' multiplier to get from raw data acquisition values to recorded volts is 2.5/32768/8000 = 9.5367e-9.","required":false,"dtype":"float32","default_value":1.0},{"name":"resolution","doc":"Smallest meaningful difference between values in data, stored in the specified by unit, 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 -1.0.","required":false,"dtype":"float32","default_value":-1.0},{"name":"unit","doc":"Base unit of measurement for working with the data. Actual stored values are not necessarily stored in these units. To access the data in these units, multiply 'data' by 'conversion'.","dtype":"text"}]},{"dtype":"float64","name":"starting_time","doc":"Timestamp of the first sample in seconds. When timestamps are uniformly spaced, the timestamp of the first sample can be specified and all subsequent ones calculated from the sampling rate attribute.","quantity":"?","attributes":[{"name":"rate","doc":"Sampling rate, in Hz.","dtype":"float32"},{"name":"unit","doc":"Unit of measurement for time, which is fixed to 'seconds'.","dtype":"text","value":"seconds"}]},{"shape":[null],"dims":["num_times"],"dtype":"float64","name":"timestamps","doc":"Timestamps for samples stored in data, in seconds, relative to the common experiment master-clock stored in NWBFile.timestamps_reference_time.","quantity":"?","attributes":[{"name":"interval","doc":"Value is '1'","dtype":"int32","value":1},{"name":"unit","doc":"Unit of measurement for timestamps, which is fixed to 'seconds'.","dtype":"text","value":"seconds"}]},{"shape":[null],"dims":["num_times"],"dtype":"uint8","name":"control","doc":"Numerical labels that apply to each time point in data for the purpose of querying and slicing data by these values. If present, the length of this array should be the same size as the first dimension of data.","quantity":"?"},{"shape":[null],"dims":["num_control_values"],"dtype":"text","name":"control_description","doc":"Description of each control value. Must be present if control is present. If present, control_description[0] should describe time points where control == 0.","quantity":"?"}],"doc":"General purpose time series.","neurodata_type_inc":"NWBDataInterface","neurodata_type_def":"TimeSeries","attributes":[{"name":"description","doc":"Description of the time series.","required":false,"dtype":"text","default_value":"no description"},{"name":"comments","doc":"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.","required":false,"dtype":"text","default_value":"no comments"}]},{"groups":[{"doc":"Data objects stored in this collection.","quantity":"*","neurodata_type_inc":"NWBDataInterface"}],"doc":"A collection of processed data.","neurodata_type_inc":"NWBContainer","neurodata_type_def":"ProcessingModule","attributes":[{"name":"description","doc":"Description of this collection of processed data.","dtype":"text"}]},{"datasets":[{"doc":"Images stored in this collection.","quantity":"+","neurodata_type_inc":"Image"}],"doc":"A collection of images.","default_name":"Images","neurodata_type_inc":"NWBDataInterface","neurodata_type_def":"Images","attributes":[{"name":"description","doc":"Description of this collection of images.","dtype":"text"}]},{"datasets":[{"shape":[null],"dims":["num_rows"],"dtype":"int","name":"id","doc":"Array of unique identifiers for the rows of this dynamic table.","neurodata_type_inc":"ElementIdentifiers"},{"doc":"Vector columns of this dynamic table.","quantity":"*","neurodata_type_inc":"VectorData"},{"doc":"Indices for the vector columns of this dynamic table.","quantity":"*","neurodata_type_inc":"VectorIndex"}],"doc":"A group containing multiple datasets that are aligned on the first dimension (Currently, this requirement if left up to APIs to check and enforce). Apart from a column that contains unique identifiers for each row there are no other required datasets. Users are free to add any number of VectorData objects here. Table functionality is already supported through compound types, which is analogous to storing an array-of-structs. DynamicTable can be thought of as a struct-of-arrays. This provides an alternative structure to choose from when optimizing storage for anticipated access patterns. Additionally, this type provides a way of creating a table without having to define a compound type up front. Although this convenience may be attractive, users should think carefully about how data will be accessed. DynamicTable is more appropriate for column-centric access, whereas a dataset with a compound type would be more appropriate for row-centric access. Finally, data size should also be taken into account. For small tables, performance loss may be an acceptable trade-off for the flexibility of a DynamicTable. For example, DynamicTable was originally developed for storing trial data and spike unit metadata. Both of these use cases are expected to produce relatively small tables, so the spatial locality of multiple datasets present in a DynamicTable is not expected to have a significant performance impact. Additionally, requirements of trial and unit metadata tables are sufficiently diverse that performance implications can be overlooked in favor of usability.","neurodata_type_inc":"NWBDataInterface","neurodata_type_def":"DynamicTable","attributes":[{"name":"colnames","doc":"The names of the columns in this table. This should be used to specify an order to the columns.","dtype":"ascii","shape":[null],"dims":["num_columns"]},{"name":"description","doc":"Description of what is in this dynamic table.","dtype":"text"}]}]}SNODChEXxsh@=8o3#] 3#]03#]@3#]P3#]nwb.basenwb.epochnwb.imagenwb.filenwb.miscnwb.behaviornwb.ecephysnwb.icephysnwb.ogennwb.ophysnwb.retinotopynamespaceGCOLPy({"datasets":[{"shape":[null,null],"dims":["y","x"],"doc":"A grayscale image.","neurodata_type_inc":"Image","neurodata_type_def":"GrayscaleImage","attributes":[{"name":"resolution","doc":"Pixel resolution of the image, in pixels per centimeter.","required":false,"dtype":"float"},{"name":"description","doc":"Description of the image.","required":false,"dtype":"text"}]},{"shape":[null,null,3],"dims":["y","x","R, G, B"],"doc":"A color image.","neurodata_type_inc":"Image","neurodata_type_def":"RGBImage","attributes":[{"name":"resolution","doc":"Pixel resolution of the image, in pixels per centimeter.","required":false,"dtype":"float"},{"name":"description","doc":"Description of the image.","required":false,"dtype":"text"}]},{"shape":[null,null,4],"dims":["y","x","R, G, B, A"],"doc":"A color image with transparency.","neurodata_type_inc":"Image","neurodata_type_def":"RGBAImage","attributes":[{"name":"resolution","doc":"Pixel resolution of the image, in pixels per centimeter.","required":false,"dtype":"float"},{"name":"description","doc":"Description of the image.","required":false,"dtype":"text"}]}],"groups":[{"datasets":[{"shape":[[null,null,null],[null,null,null,null]],"dims":[["frame","y","x"],["frame","z","y","x"]],"dtype":"numeric","name":"data","doc":"Binary data representing images across frames.","quantity":"?","attributes":[{"name":"conversion","doc":"Scalar to multiply each element in data to convert it to the specified 'unit'. If the data are stored in acquisition system units or other units that require a conversion to be interpretable, multiply the data by 'conversion' to convert the data to the specified 'unit'. e.g. if the data acquisition system stores values in this object as signed 16-bit integers (int16 range -32,768 to 32,767) that correspond to a 5V range (-2.5V to 2.5V), and the data acquisition system gain is 8000X, then the 'conversion' multiplier to get from raw data acquisition values to recorded volts is 2.5/32768/8000 = 9.5367e-9.","required":false,"dtype":"float32","default_value":1.0},{"name":"resolution","doc":"Smallest meaningful difference between values in data, stored in the specified by unit, 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 -1.0.","required":false,"dtype":"float32","default_value":-1.0},{"name":"unit","doc":"Base unit of measurement for working with the data. Actual stored values are not necessarily stored in these units. To access the data in these units, multiply 'data' by 'conversion'.","dtype":"text"}]},{"shape":[null],"dims":["rank"],"dtype":"int32","name":"dimension","doc":"Number of pixels on x, y, (and z) axes.","quantity":"?"},{"shape":[null],"dims":["num_files"],"dtype":"text","name":"external_file","doc":"Paths to one or more external file(s). The field is only present if format='external'. This is only relevant if the image series is stored in the file system as one or more image file(s). This field should NOT be used if the image is stored in another NWB file and that file is linked to this file.","quantity":"?","attributes":[{"name":"starting_frame","doc":"Each external image may contain one or more consecutive frames of the full ImageSeries. This attribute serves as an index to indicate which frames each file contains, to faciliate random access. The 'starting_frame' attribute, hence, contains a list of frame numbers within the full ImageSeries of the first frame of each file listed in the parent 'external_file' dataset. Zero-based indexing is used (hence, the first element will always be zero). For example, if the 'external_file' dataset has three paths to files and the first file has 5 frames, the second file has 10 frames, and the third file has 20 frames, then this attribute will have values [0, 5, 15]. If there is a single external file that holds all of the frames of the ImageSeries (and so there is a single element in the 'external_file' dataset), then this attribute should have value [0].","dtype":"int","shape":[null],"dims":["num_files"]}]},{"dtype":"text","name":"format","doc":"Format of image. If this is 'external', then the attribute 'external_file' contains the path information to the image files. If this is 'raw', then the raw (single-channel) binary data is stored in the 'data' dataset. If this attribute is not present, then the default format='raw' case is assumed.","quantity":"?","default_value":"raw"}],"doc":"General image data that is common between acquisition and stimulus time series. Sometimes the image data is stored in the file in a raw format while other times it will be stored as a series of external image files in the host file system. The data field will either be binary data, if the data is stored in the NWB file, or empty, if the data is stored in an external image stack. [frame][y][x] or [frame][z][y][x].","neurodata_type_inc":"TimeSeries","neurodata_type_def":"ImageSeries","attributes":[{"name":"description","doc":"Description of the time series.","required":false,"dtype":"text","default_value":"no description"},{"name":"comments","doc":"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.","required":false,"dtype":"text","default_value":"no comments"}]},{"links":[{"name":"masked_imageseries","doc":"Link to ImageSeries object that this image mask is applied to.","target_type":"ImageSeries"}],"doc":"An alpha mask that is applied to a presented visual stimulus. The 'data' array contains an array of mask values that are applied to the displayed image. Mask values are stored as RGBA. Mask can vary with time. The timestamps array indicates the starting time of a mask, and that mask pattern continues until it's explicitly changed.","neurodata_type_inc":"ImageSeries","neurodata_type_def":"ImageMaskSeries","attributes":[{"name":"description","doc":"Description of the time series.","required":false,"dtype":"text","default_value":"no description"},{"name":"comments","doc":"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.","required":false,"dtype":"text","default_value":"no comments"}]},{"datasets":[{"dtype":"float32","name":"distance","doc":"Distance from camera/monitor to target/eye.","quantity":"?"},{"shape":[[2],[3]],"dims":[["width, height"],["width, height, depth"]],"dtype":"float32","name":"field_of_view","doc":"Width, height and depth of image, or imaged area, in meters.","quantity":"?"},{"dtype":"text","name":"orientation","doc":"Description of image relative to some reference frame (e.g., which way is up). Must also specify frame of reference.","quantity":"?"}],"doc":"Image data that is presented or recorded. A stimulus template movie will be stored only as an image. When the image is presented as stimulus, additional data is required, such as field of view (e.g., how much of the visual field the image covers, or how what is the area of the target being imaged). If the OpticalSeries represents acquired imaging data, orientation is also important.","neurodata_type_inc":"ImageSeries","neurodata_type_def":"OpticalSeries","attributes":[{"name":"description","doc":"Description of the time series.","required":false,"dtype":"text","default_value":"no description"},{"name":"comments","doc":"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.","required":false,"dtype":"text","default_value":"no comments"}]},{"datasets":[{"shape":[null],"dims":["num_times"],"dtype":"int","name":"data","doc":"Index of the frame in the referenced ImageSeries.","attributes":[{"name":"conversion","doc":"Scalar to multiply each element in data to convert it to the specified 'unit'. If the data are stored in acquisition system units or other units that require a conversion to be interpretable, multiply the data by 'conversion' to convert the data to the specified 'unit'. e.g. if the data acquisition system stores values in this object as signed 16-bit integers (int16 range -32,768 to 32,767) that correspond to a 5V range (-2.5V to 2.5V), and the data acquisition system gain is 8000X, then the 'conversion' multiplier to get from raw data acquisition values to recorded volts is 2.5/32768/8000 = 9.5367e-9.","required":false,"dtype":"float32","default_value":1.0},{"name":"resolution","doc":"Smallest meaningful difference between values in data, stored in the specified by unit, 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 -1.0.","required":false,"dtype":"float32","default_value":-1.0},{"name":"unit","doc":"Base unit of measurement for working with the data. Actual stored values are not necessarily stored in these units. To access the data in these units, multiply 'data' by 'conversion'.","dtype":"text"}]}],"links":[{"name":"indexed_timeseries","doc":"Link to ImageSeries object containing images that are indexed.","target_type":"ImageSeries"}],"doc":"Stores indices to image frames stored in an ImageSeries. The purpose of the ImageIndexSeries 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 ImageSeries, and the timestamps array indicates when that image was displayed.","neurodata_type_inc":"TimeSeries","neurodata_type_def":"IndexSeries","attributes":[{"name":"description","doc":"Description of the time series.","required":false,"dtype":"text","default_value":"no description"},{"name":"comments","doc":"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.","required":false,"dtype":"text","default_value":"no comments"}]}]}:{"groups":[{"groups":[{"groups":[{"doc":"Acquired, raw data.","quantity":"*","neurodata_type_inc":"NWBDataInterface"}],"name":"acquisition","doc":"Data streams recorded from the system, including ephys, ophys, tracking, etc. This group should be 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 NWB files. This will allow keeping bulky raw data out of the file while preserving the option of keeping some/all in the file. Acquired data includes tracking and experimental data streams (i.e., everything measured from the system). If bulky data is stored in the /acquisition group, the data can exist in a separate NWB file that is linked to by the file being used for processing and analysis."},{"groups":[{"doc":"Custom analysis results.","quantity":"*","neurodata_type_inc":"NWBContainer"}],"name":"analysis","doc":"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. To facilitate sharing analysis data between labs, the contents here should be stored in standard types (e.g., neurodata_types) and appropriately documented. 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 could be shared with other labs."},{"groups":[{"doc":"Any one-off containers","quantity":"*","neurodata_type_inc":"NWBContainer"}],"datasets":[{"doc":"Any one-off datasets","quantity":"*","neurodata_type_inc":"NWBData","neurodata_type_def":"ScratchData","attributes":[{"name":"notes","doc":"Any notes the user has about the dataset being stored","dtype":"text"}]}],"name":"scratch","doc":"A place to store one-off analysis results. Data placed here is not intended for sharing. By placing data here, users acknowledge that there is no guarantee that their data meets any standard.","quantity":"?"},{"groups":[{"doc":"Intermediate analysis of acquired data.","quantity":"*","neurodata_type_inc":"ProcessingModule"}],"name":"processing","doc":"The home for ProcessingModules. 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. ProcessingModules 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. 'Processing' refers to intermediate analysis of the acquired data to make it more amenable to scientific analysis."},{"groups":[{"groups":[{"doc":"TimeSeries objects containing data of presented stimuli.","quantity":"*","neurodata_type_inc":"TimeSeries"}],"name":"presentation","doc":"Stimuli presented during the experiment."},{"groups":[{"doc":"TimeSeries objects containing template data of presented stimuli.","quantity":"*","neurodata_type_inc":"TimeSeries"}],"name":"templates","doc":"Template stimuli. Timestamps 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."}],"name":"stimulus","doc":"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). This group should be made 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. 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 linked to a remote library file."},{"groups":[{"doc":"Place-holder than can be extended so that lab-specific meta-data can be placed in /general.","quantity":"*","neurodata_type_inc":"NWBContainer","neurodata_type_def":"LabMetaData"},{"groups":[{"doc":"A data acquisition device, e.g. recording system.","quantity":"+","neurodata_type_inc":"NWBContainer","neurodata_type_def":"Device"}],"name":"devices","doc":"Description of hardware devices used during experiment, e.g., monitors, ADC boards, microscopes, etc.","quantity":"?"},{"datasets":[{"dtype":"text","name":"age","doc":"Age of subject. Can be supplied instead of 'date_of_birth'.","quantity":"?"},{"dtype":"isodatetime","name":"date_of_birth","doc":"Date of birth of subject. Can be supplied instead of 'age'.","quantity":"?"},{"dtype":"text","name":"description","doc":"Description of subject and where subject came from (e.g., breeder, if animal).","quantity":"?"},{"dtype":"text","name":"genotype","doc":"Genetic strain. If absent, assume Wild Type (WT).","quantity":"?"},{"dtype":"text","name":"sex","doc":"Gender of subject.","quantity":"?"},{"dtype":"text","name":"species","doc":"Species of subject.","quantity":"?"},{"dtype":"text","name":"subject_id","doc":"ID of animal/person used/participating in experiment (lab convention).","quantity":"?"},{"dtype":"text","name":"weight","doc":"Weight at time of experiment, at time of surgery and at other important times.","quantity":"?"}],"name":"subject","doc":"Information about the animal or person from which the data was measured.","quantity":"?","neurodata_type_inc":"NWBContainer","neurodata_type_def":"Subject"},{"groups":[{"doc":"Physical group of electrodes.","quantity":"*","neurodata_type_inc":"ElectrodeGroup"},{"datasets":[{"dtype":"float","name":"x","doc":"x coordinate of the channel location.","neurodata_type_inc":"VectorData"},{"dtype":"float","name":"y","doc":"y coordinate of the channel location.","neurodata_type_inc":"VectorData"},{"dtype":"float","name":"z","doc":"z coordinate of the channel location.","neurodata_type_inc":"VectorData"},{"dtype":"float","name":"imp","doc":"Impedance of the channel.","neurodata_type_inc":"VectorData"},{"dtype":"ascii","name":"location","doc":"Location of the electrode (channel). Specify the area, layer, comments on estimation of area/layer, stereotaxic coordinates if in vivo, etc. Use standard atlas names for anatomical regions when possible.","neurodata_type_inc":"VectorData"},{"dtype":"float","name":"filtering","doc":"Description of hardware filtering.","neurodata_type_inc":"VectorData"},{"dtype":{"target_type":"ElectrodeGroup","reftype":"object"},"name":"group","doc":"Reference to the ElectrodeGroup this electrode is a part of.","neurodata_type_inc":"VectorData"},{"dtype":"ascii","name":"group_name","doc":"Name of the ElectrodeGroup this electrode is a part of.","neurodata_type_inc":"VectorData"}],"name":"electrodes","doc":"A table of all electrodes (i.e. channels) used for recording.","quantity":"?","neurodata_type_inc":"DynamicTable"}],"name":"extracellular_ephys","doc":"Metadata related to extracellular electrophysiology.","quantity":"?"},{"groups":[{"doc":"An intracellular electrode.","quantity":"*","neurodata_type_inc":"IntracellularElectrode"},{"name":"sweep_table","doc":"The table which groups different PatchClampSeries together.","quantity":"?","neurodata_type_inc":"SweepTable"}],"datasets":[{"dtype":"text","name":"filtering","doc":"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.","quantity":"?"}],"name":"intracellular_ephys","doc":"Metadata related to intracellular electrophysiology.","quantity":"?"},{"groups":[{"doc":"An optogenetic stimulation site.","quantity":"*","neurodata_type_inc":"OptogeneticStimulusSite"}],"name":"optogenetics","doc":"Metadata describing optogenetic stimuluation.","quantity":"?"},{"groups":[{"doc":"An imaging plane.","quantity":"*","neurodata_type_inc":"ImagingPlane"}],"name":"optophysiology","doc":"Metadata related to optophysiology.","quantity":"?"}],"datasets":[{"dtype":"text","name":"data_collection","doc":"Notes about data collection and analysis.","quantity":"?"},{"dtype":"text","name":"experiment_description","doc":"General description of the experiment.","quantity":"?"},{"shape":[null],"dims":["num_experimenters"],"dtype":"text","name":"experimenter","doc":"Name of person(s) who performed the experiment. Can also specify roles of different people involved.","quantity":"?"},{"dtype":"text","name":"institution","doc":"Institution(s) where experiment was performed.","quantity":"?"},{"shape":[null],"dims":["num_keywords"],"dtype":"text","name":"keywords","doc":"Terms to search over.","quantity":"?"},{"dtype":"text","name":"lab","doc":"Laboratory where experiment was performed.","quantity":"?"},{"dtype":"text","name":"notes","doc":"Notes about the experiment.","quantity":"?"},{"dtype":"text","name":"pharmacology","doc":"Description of drugs used, including how and when they were administered. Anesthesia(s), painkiller(s), etc., plus dosage, concentration, etc.","quantity":"?"},{"dtype":"text","name":"protocol","doc":"Experimental protocol, if applicable. e.g., include IACUC protocol number.","quantity":"?"},{"shape":[null],"dims":["num_publications"],"dtype":"text","name":"related_publications","doc":"Publication information. PMID, DOI, URL, etc.","quantity":"?"},{"dtype":"text","name":"session_id","doc":"Lab-specific ID for the session.","quantity":"?"},{"dtype":"text","name":"slices","doc":"Description of slices, including information about preparation thickness, orientation, temperature, and bath solution.","quantity":"?"},{"dtype":"text","name":"source_script","doc":"Script file or link to public source code used to create this NWB file.","quantity":"?","attributes":[{"name":"file_name","doc":"Name of script file.","dtype":"text"}]},{"dtype":"text","name":"stimulus","doc":"Notes about stimuli, such as how and where they were presented.","quantity":"?"},{"dtype":"text","name":"surgery","doc":"Narrative description about surgery/surgeries, including date(s) and who performed surgery.","quantity":"?"},{"dtype":"text","name":"virus","doc":"Information about virus(es) used in experiments, including virus ID, source, date made, injection location, volume, etc.","quantity":"?"}],"name":"general","doc":"Experimental metadata, including protocol, notes and description of hardware device(s). The metadata stored in this section should be used to describe the experiment. Metadata necessary for interpreting the data is stored with the data. 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 (e.g., 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. 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."},{"groups":[{"name":"epochs","doc":"Divisions in time marking experimental stages or sub-divisions of a single recording session.","quantity":"?","neurodata_type_inc":"TimeIntervals"},{"name":"trials","doc":"Repeated experimental events that have a logical grouping.","quantity":"?","neurodata_type_inc":"TimeIntervals"},{"name":"invalid_times","doc":"Time intervals that should be removed from analysis.","quantity":"?","neurodata_type_inc":"TimeIntervals"},{"doc":"Optional additional table(s) for describing other experimental time intervals.","quantity":"*","neurodata_type_inc":"TimeIntervals"}],"name":"intervals","doc":"Experimental intervals, whether that be logically distinct sub-experiments having a particular scientific goal, trials (see trials subgroup) during an experiment, or epochs (see epochs subgroup) deriving from analysis of data.","quantity":"?"},{"name":"units","doc":"Data about sorted spike units.","quantity":"?","neurodata_type_inc":"Units"}],"datasets":[{"shape":[null],"dims":["num_modifications"],"dtype":"isodatetime","name":"file_create_date","doc":"A record of the date the file was created and of subsequent modifications. The date is stored in UTC with local timezone offset as ISO 8601 extended formatted strings: 2018-09-28T14:43:54.123+02:00. Dates stored in UTC end in \"Z\" with no timezone offset. Date accuracy is up to milliseconds. The file can be created after the experiment was run, so this may differ from the experiment start time. Each modification to the nwb file adds a new entry to the array."},{"dtype":"text","name":"identifier","doc":"A unique text identifier for the file. For example, 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."},{"dtype":"text","name":"session_description","doc":"A description of the experimental session and data in the file."},{"dtype":"isodatetime","name":"session_start_time","doc":"Date and time of the experiment/session start. The date is stored in UTC with local timezone offset as ISO 8601 extended formatted string: 2018-09-28T14:43:54.123+02:00. Dates stored in UTC end in \"Z\" with no timezone offset. Date accuracy is up to milliseconds."},{"dtype":"isodatetime","name":"timestamps_reference_time","doc":"Date and time corresponding to time zero of all timestamps. The date is stored in UTC with local timezone offset as ISO 8601 extended formatted string: 2018-09-28T14:43:54.123+02:00. Dates stored in UTC end in \"Z\" with no timezone offset. Date accuracy is up to milliseconds. All times stored in the file use this time as reference (i.e., time zero)."}],"name":"root","doc":"An NWB:N file storing cellular-based neurophysiology data from a single experimental session.","neurodata_type_inc":"NWBContainer","neurodata_type_def":"NWBFile","attributes":[{"name":"nwb_version","doc":"File version string. Use semantic versioning, e.g. 1.2.1. This will be the name of the format with trailing major, minor and patch numbers.","dtype":"text","value":"2.1.0"}]}]},1{"groups":[{"datasets":[{"shape":[[null],[null,null]],"dims":[["num_times"],["num_times","num_features"]],"dtype":"numeric","name":"data","doc":"Values of each feature at each time.","attributes":[{"name":"unit","doc":"Since there can be different units for different features, store the units in 'feature_units'. The default value for this attribute is \"see 'feature_units'\".","required":false,"dtype":"text","default_value":"see 'feature_units'"},{"name":"conversion","doc":"Scalar to multiply each element in data to convert it to the specified 'unit'. If the data are stored in acquisition system units or other units that require a conversion to be interpretable, multiply the data by 'conversion' to convert the data to the specified 'unit'. e.g. if the data acquisition system stores values in this object as signed 16-bit integers (int16 range -32,768 to 32,767) that correspond to a 5V range (-2.5V to 2.5V), and the data acquisition system gain is 8000X, then the 'conversion' multiplier to get from raw data acquisition values to recorded volts is 2.5/32768/8000 = 9.5367e-9.","required":false,"dtype":"float32","default_value":1.0},{"name":"resolution","doc":"Smallest meaningful difference between values in data, stored in the specified by unit, 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 -1.0.","required":false,"dtype":"float32","default_value":-1.0}]},{"shape":[null],"dims":["num_features"],"dtype":"text","name":"feature_units","doc":"Units of each feature.","quantity":"?"},{"shape":[null],"dims":["num_features"],"dtype":"text","name":"features","doc":"Description of the features represented in TimeSeries::data."}],"doc":"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. This is useful when storing the raw stimulus is impractical.","neurodata_type_inc":"TimeSeries","neurodata_type_def":"AbstractFeatureSeries","attributes":[{"name":"description","doc":"Description of the time series.","required":false,"dtype":"text","default_value":"no description"},{"name":"comments","doc":"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.","required":false,"dtype":"text","default_value":"no comments"}]},{"datasets":[{"shape":[null],"dims":["num_times"],"dtype":"text","name":"data","doc":"Annotations made during an experiment.","attributes":[{"name":"resolution","doc":"Smallest meaningful difference between values in data. Annotations have no units, so the value is fixed to -1.0.","dtype":"float","value":-1.0},{"name":"unit","doc":"Base unit of measurement for working with the data. Annotations have no units, so the value is fixed to 'n/a'.","dtype":"text","value":"n/a"},{"name":"conversion","doc":"Scalar to multiply each element in data to convert it to the specified 'unit'. If the data are stored in acquisition system units or other units that require a conversion to be interpretable, multiply the data by 'conversion' to convert the data to the specified 'unit'. e.g. if the data acquisition system stores values in this object as signed 16-bit integers (int16 range -32,768 to 32,767) that correspond to a 5V range (-2.5V to 2.5V), and the data acquisition system gain is 8000X, then the 'conversion' multiplier to get from raw data acquisition values to recorded volts is 2.5/32768/8000 = 9.5367e-9.","required":false,"dtype":"float32","default_value":1.0}]}],"doc":"Stores user annotations made during an experiment. The 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.","neurodata_type_inc":"TimeSeries","neurodata_type_def":"AnnotationSeries","attributes":[{"name":"description","doc":"Description of the time series.","required":false,"dtype":"text","default_value":"no description"},{"name":"comments","doc":"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.","required":false,"dtype":"text","default_value":"no comments"}]},{"datasets":[{"shape":[null],"dims":["num_times"],"dtype":"int8","name":"data","doc":"Use values >0 if interval started, <0 if interval ended.","attributes":[{"name":"resolution","doc":"Smallest meaningful difference between values in data. Annotations have no units, so the value is fixed to -1.0.","dtype":"float","value":-1.0},{"name":"unit","doc":"Base unit of measurement for working with the data. Annotations have no units, so the value is fixed to 'n/a'.","dtype":"text","value":"n/a"},{"name":"conversion","doc":"Scalar to multiply each element in data to convert it to the specified 'unit'. If the data are stored in acquisition system units or other units that require a conversion to be interpretable, multiply the data by 'conversion' to convert the data to the specified 'unit'. e.g. if the data acquisition system stores values in this object as signed 16-bit integers (int16 range -32,768 to 32,767) that correspond to a 5V range (-2.5V to 2.5V), and the data acquisition system gain is 8000X, then the 'conversion' multiplier to get from raw data acquisition values to recorded volts is 2.5/32768/8000 = 9.5367e-9.","required":false,"dtype":"float32","default_value":1.0}]}],"doc":"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.","neurodata_type_inc":"TimeSeries","neurodata_type_def":"IntervalSeries","attributes":[{"name":"description","doc":"Description of the time series.","required":false,"dtype":"text","default_value":"no description"},{"name":"comments","doc":"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.","required":false,"dtype":"text","default_value":"no comments"}]},{"groups":[{"datasets":[{"dtype":"text","name":"band_name","doc":"Name of the band, e.g. theta.","neurodata_type_inc":"VectorData"},{"shape":[null,2],"dims":["num_bands","low, high"],"dtype":"float","name":"band_limits","doc":"Low and high limit of each band in Hz. If it is a Gaussian filter, use 2 SD on either side of the center.","neurodata_type_inc":"VectorData"},{"shape":[null],"dims":["num_bands"],"dtype":"float","name":"band_mean","doc":"The mean Gaussian filters, in Hz.","neurodata_type_inc":"VectorData"},{"shape":[null],"dims":["num_bands"],"dtype":"float","name":"band_stdev","doc":"The standard deviation of Gaussian filters, in Hz.","neurodata_type_inc":"VectorData"}],"name":"bands","doc":"Table for describing the bands that this series was generated from. There should be one row in this table for each band.","neurodata_type_inc":"DynamicTable"}],"datasets":[{"shape":[null,null,null],"dims":["num_times","num_channels","num_bands"],"dtype":"numeric","name":"data","doc":"Data decomposed into frequency bands.","attributes":[{"name":"unit","doc":"Base unit of measurement for working with the data. Actual stored values are not necessarily stored in these units. To access the data in these units, multiply 'data' by 'conversion'.","required":false,"dtype":"text","default_value":"no unit"},{"name":"conversion","doc":"Scalar to multiply each element in data to convert it to the specified 'unit'. If the data are stored in acquisition system units or other units that require a conversion to be interpretable, multiply the data by 'conversion' to convert the data to the specified 'unit'. e.g. if the data acquisition system stores values in this object as signed 16-bit integers (int16 range -32,768 to 32,767) that correspond to a 5V range (-2.5V to 2.5V), and the data acquisition system gain is 8000X, then the 'conversion' multiplier to get from raw data acquisition values to recorded volts is 2.5/32768/8000 = 9.5367e-9.","required":false,"dtype":"float32","default_value":1.0},{"name":"resolution","doc":"Smallest meaningful difference between values in data, stored in the specified by unit, 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 -1.0.","required":false,"dtype":"float32","default_value":-1.0}]},{"dtype":"text","name":"metric","doc":"The metric used, e.g. phase, amplitude, power."}],"links":[{"name":"source_timeseries","doc":"Link to TimeSeries object that this data was calculated from. Metadata about electrodes and their position can be read from that ElectricalSeries so it is not necessary to store that information here.","target_type":"TimeSeries","quantity":"?"}],"doc":"Spectral analysis of a time series, e.g. of an LFP or a speech signal.","neurodata_type_inc":"TimeSeries","neurodata_type_def":"DecompositionSeries","attributes":[{"name":"description","doc":"Description of the time series.","required":false,"dtype":"text","default_value":"no description"},{"name":"comments","doc":"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.","required":false,"dtype":"text","default_value":"no comments"}]},{"datasets":[{"name":"spike_times_index","doc":"Index into the spike_times dataset.","quantity":"?","neurodata_type_inc":"VectorIndex"},{"dtype":"double","name":"spike_times","doc":"Spike times for each unit.","quantity":"?","neurodata_type_inc":"VectorData"},{"name":"obs_intervals_index","doc":"Index into the obs_intervals dataset.","quantity":"?","neurodata_type_inc":"VectorIndex"},{"shape":[null,2],"dims":["num_intervals","start|end"],"dtype":"double","name":"obs_intervals","doc":"Observation intervals for each unit.","quantity":"?","neurodata_type_inc":"VectorData"},{"name":"electrodes_index","doc":"Index into electrodes.","quantity":"?","neurodata_type_inc":"VectorIndex"},{"name":"electrodes","doc":"Electrode that each spike unit came from, specified using a DynamicTableRegion.","quantity":"?","neurodata_type_inc":"DynamicTableRegion"},{"dtype":{"target_type":"ElectrodeGroup","reftype":"object"},"name":"electrode_group","doc":"Electrode group that each spike unit came from.","quantity":"?","neurodata_type_inc":"VectorData"},{"shape":[[null,null],[null,null,null]],"dims":[["num_units","num_samples"],["num_units","num_samples","num_electrodes"]],"dtype":"float","name":"waveform_mean","doc":"Spike waveform mean for each spike unit.","quantity":"?","neurodata_type_inc":"VectorData"},{"shape":[[null,null],[null,null,null]],"dims":[["num_units","num_samples"],["num_units","num_samples","num_electrodes"]],"dtype":"float","name":"waveform_sd","doc":"Spike waveform standard deviation for each spike unit.","quantity":"?","neurodata_type_inc":"VectorData"}],"doc":"Data about spiking units. Event times of observed units (e.g. cell, synapse, etc.) should be concatenated and stored in spike_times.","default_name":"Units","neurodata_type_inc":"DynamicTable","neurodata_type_def":"Units","attributes":[{"name":"colnames","doc":"The names of the columns in this table. This should be used to specify an order to the columns.","dtype":"ascii","shape":[null],"dims":["num_columns"]},{"name":"description","doc":"Description of what is in this dynamic table.","dtype":"text"}]}]}{"groups":[{"datasets":[{"shape":[[null],[null,null]],"dims":[["num_times"],["num_times","num_features"]],"dtype":"numeric","name":"data","doc":"1-D or 2-D array storing position or direction relative to some reference frame.","attributes":[{"name":"unit","doc":"Base unit of measurement for working with the data. The default value is 'meters'. Actual stored values are not necessarily stored in these units. To access the data in these units, multiply 'data' by 'conversion'.","required":false,"dtype":"text","default_value":"meters"},{"name":"conversion","doc":"Scalar to multiply each element in data to convert it to the specified 'unit'. If the data are stored in acquisition system units or other units that require a conversion to be interpretable, multiply the data by 'conversion' to convert the data to the specified 'unit'. e.g. if the data acquisition system stores values in this object as signed 16-bit integers (int16 range -32,768 to 32,767) that correspond to a 5V range (-2.5V to 2.5V), and the data acquisition system gain is 8000X, then the 'conversion' multiplier to get from raw data acquisition values to recorded volts is 2.5/32768/8000 = 9.5367e-9.","required":false,"dtype":"float32","default_value":1.0},{"name":"resolution","doc":"Smallest meaningful difference between values in data, stored in the specified by unit, 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 -1.0.","required":false,"dtype":"float32","default_value":-1.0}]},{"dtype":"text","name":"reference_frame","doc":"Description defining what exactly 'straight-ahead' means.","quantity":"?"}],"doc":"Direction, e.g., of gaze or travel, or position. The TimeSeries::data field is a 2D array storing position or direction relative to some reference frame. Array structure: [num measurements] [num dimensions]. Each SpatialSeries has a text dataset reference_frame that indicates the zero-position, or the zero-axes for direction. For example, if representing gaze direction, 'straight-ahead' might be a specific pixel on the monitor, or some other point in space. For position data, the 0,0 point might be the top-left corner of an enclosure, as viewed from the tracking camera. The unit of data will indicate how to interpret SpatialSeries values.","neurodata_type_inc":"TimeSeries","neurodata_type_def":"SpatialSeries","attributes":[{"name":"description","doc":"Description of the time series.","required":false,"dtype":"text","default_value":"no description"},{"name":"comments","doc":"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.","required":false,"dtype":"text","default_value":"no comments"}]},{"groups":[{"doc":"IntervalSeries object containing start and stop times of epochs.","quantity":"*","neurodata_type_inc":"IntervalSeries"}],"doc":"TimeSeries for storing behavioral epochs. The objective of this and the other two Behavioral interfaces (e.g. BehavioralEvents and BehavioralTimeSeries) is to provide generic hooks for software tools/scripts. This allows a tool/script to take the output one specific interface (e.g., UnitTimes) and plot that data relative to another data modality (e.g., behavioral events) without having to define all possible modalities in advance. Declaring one of these interfaces means that one or more TimeSeries of the specified type is published. These TimeSeries should reside in a group having the same name as the interface. For example, if a BehavioralTimeSeries interface is declared, the module will have one or more TimeSeries defined in the module sub-group 'BehavioralTimeSeries'. BehavioralEpochs should use IntervalSeries. BehavioralEvents is used for irregular events. BehavioralTimeSeries is for continuous data.","default_name":"BehavioralEpochs","neurodata_type_inc":"NWBDataInterface","neurodata_type_def":"BehavioralEpochs"},{"groups":[{"doc":"TimeSeries object containing behavioral events.","quantity":"*","neurodata_type_inc":"TimeSeries"}],"doc":"TimeSeries for storing behavioral events. See description of BehavioralEpochs for more details.","default_name":"BehavioralEvents","neurodata_type_inc":"NWBDataInterface","neurodata_type_def":"BehavioralEvents"},{"groups":[{"doc":"TimeSeries object containing continuous behavioral data.","quantity":"*","neurodata_type_inc":"TimeSeries"}],"doc":"TimeSeries for storing Behavoioral time series data. See description of BehavioralEpochs for more details.","default_name":"BehavioralTimeSeries","neurodata_type_inc":"NWBDataInterface","neurodata_type_def":"BehavioralTimeSeries"},{"groups":[{"doc":"TimeSeries object containing time series data on pupil size.","quantity":"+","neurodata_type_inc":"TimeSeries"}],"doc":"Eye-tracking data, representing pupil size.","default_name":"PupilTracking","neurodata_type_inc":"NWBDataInterface","neurodata_type_def":"PupilTracking"},{"groups":[{"doc":"SpatialSeries object containing data measuring direction of gaze.","quantity":"*","neurodata_type_inc":"SpatialSeries"}],"doc":"Eye-tracking data, representing direction of gaze.","default_name":"EyeTracking","neurodata_type_inc":"NWBDataInterface","neurodata_type_def":"EyeTracking"},{"groups":[{"doc":"SpatialSeries object containing direction of gaze travel.","quantity":"*","neurodata_type_inc":"SpatialSeries"}],"doc":"With a CompassDirection interface, a module publishes a SpatialSeries object representing a floating point value for theta. The SpatialSeries::reference_frame field should indicate what direction corresponds to 0 and which is the direction of rotation (this should be clockwise). The si_unit for the SpatialSeries should be radians or degrees.","default_name":"CompassDirection","neurodata_type_inc":"NWBDataInterface","neurodata_type_def":"CompassDirection"},{"groups":[{"doc":"SpatialSeries object containing position data.","quantity":"+","neurodata_type_inc":"SpatialSeries"}],"doc":"Position data, whether along the x, x/y or x/y/z axis.","default_name":"Position","neurodata_type_inc":"NWBDataInterface","neurodata_type_def":"Position"}]}~ {"groups":[{"datasets":[{"shape":[null],"dims":["num_times"],"dtype":"numeric","name":"data","doc":"Applied power for optogenetic stimulus, in watts.","attributes":[{"name":"unit","doc":"Unit of measurement for data, which is fixed to 'watts'.","dtype":"text","value":"watts"},{"name":"conversion","doc":"Scalar to multiply each element in data to convert it to the specified 'unit'. If the data are stored in acquisition system units or other units that require a conversion to be interpretable, multiply the data by 'conversion' to convert the data to the specified 'unit'. e.g. if the data acquisition system stores values in this object as signed 16-bit integers (int16 range -32,768 to 32,767) that correspond to a 5V range (-2.5V to 2.5V), and the data acquisition system gain is 8000X, then the 'conversion' multiplier to get from raw data acquisition values to recorded volts is 2.5/32768/8000 = 9.5367e-9.","required":false,"dtype":"float32","default_value":1.0},{"name":"resolution","doc":"Smallest meaningful difference between values in data, stored in the specified by unit, 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 -1.0.","required":false,"dtype":"float32","default_value":-1.0}]}],"links":[{"name":"site","doc":"Link to OptogeneticStimulusSite object that describes the site to which this stimulus was applied.","target_type":"OptogeneticStimulusSite"}],"doc":"An optogenetic stimulus.","neurodata_type_inc":"TimeSeries","neurodata_type_def":"OptogeneticSeries","attributes":[{"name":"description","doc":"Description of the time series.","required":false,"dtype":"text","default_value":"no description"},{"name":"comments","doc":"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.","required":false,"dtype":"text","default_value":"no comments"}]},{"datasets":[{"dtype":"text","name":"description","doc":"Description of stimulation site."},{"dtype":"float","name":"excitation_lambda","doc":"Excitation wavelength, in nm."},{"dtype":"text","name":"location","doc":"Location of the stimulation site. Specify the area, layer, comments on estimation of area/layer, stereotaxic coordinates if in vivo, etc. Use standard atlas names for anatomical regions when possible."}],"links":[{"name":"device","doc":"Device that generated the stimulus.","target_type":"Device"}],"doc":"A site of optogenetic stimulation.","quantity":"*","neurodata_type_inc":"NWBContainer","neurodata_type_def":"OptogeneticStimulusSite"}]}0`3#]p3#]3#]SNOD8XqxP>(HpHhr`?AB3#]3#]3#]GCOLp0{"groups":[{"datasets":[{"shape":[[null],[null,null],[null,null,null]],"dims":[["num_times"],["num_times","num_channels"],["num_times","num_channels","num_samples"]],"dtype":"numeric","name":"data","doc":"Recorded voltage data.","attributes":[{"name":"unit","doc":"Base unit of measurement for working with the data. This value is fixed to 'volts'. Actual stored values are not necessarily stored in these units. To access the data in these units, multiply 'data' by 'conversion'.","dtype":"text","value":"volts"},{"name":"conversion","doc":"Scalar to multiply each element in data to convert it to the specified 'unit'. If the data are stored in acquisition system units or other units that require a conversion to be interpretable, multiply the data by 'conversion' to convert the data to the specified 'unit'. e.g. if the data acquisition system stores values in this object as signed 16-bit integers (int16 range -32,768 to 32,767) that correspond to a 5V range (-2.5V to 2.5V), and the data acquisition system gain is 8000X, then the 'conversion' multiplier to get from raw data acquisition values to recorded volts is 2.5/32768/8000 = 9.5367e-9.","required":false,"dtype":"float32","default_value":1.0},{"name":"resolution","doc":"Smallest meaningful difference between values in data, stored in the specified by unit, 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 -1.0.","required":false,"dtype":"float32","default_value":-1.0}]},{"name":"electrodes","doc":"DynamicTableRegion pointer to the electrodes that this time series was generated from.","neurodata_type_inc":"DynamicTableRegion"}],"doc":"A time series of acquired voltage data from extracellular recordings. The data field is an int or float array storing data in volts. The first dimension should always represent time. The second dimension, if present, should represent channels.","neurodata_type_inc":"TimeSeries","neurodata_type_def":"ElectricalSeries","attributes":[{"name":"description","doc":"Description of the time series.","required":false,"dtype":"text","default_value":"no description"},{"name":"comments","doc":"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.","required":false,"dtype":"text","default_value":"no comments"}]},{"datasets":[{"shape":[[null,null],[null,null,null]],"dims":[["num_events","num_samples"],["num_events","num_channels","num_samples"]],"dtype":"numeric","name":"data","doc":"Spike waveforms.","attributes":[{"name":"unit","doc":"Unit of measurement for waveforms, which is fixed to 'volts'.","dtype":"text","value":"volts"},{"name":"conversion","doc":"Scalar to multiply each element in data to convert it to the specified 'unit'. If the data are stored in acquisition system units or other units that require a conversion to be interpretable, multiply the data by 'conversion' to convert the data to the specified 'unit'. e.g. if the data acquisition system stores values in this object as signed 16-bit integers (int16 range -32,768 to 32,767) that correspond to a 5V range (-2.5V to 2.5V), and the data acquisition system gain is 8000X, then the 'conversion' multiplier to get from raw data acquisition values to recorded volts is 2.5/32768/8000 = 9.5367e-9.","required":false,"dtype":"float32","default_value":1.0},{"name":"resolution","doc":"Smallest meaningful difference between values in data, stored in the specified by unit, 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 -1.0.","required":false,"dtype":"float32","default_value":-1.0}]},{"shape":[null],"dims":["num_times"],"dtype":"float64","name":"timestamps","doc":"Timestamps for samples stored in data, in seconds, relative to the common experiment master-clock stored in NWBFile.timestamps_reference_time. Timestamps are required for the events. Unlike for TimeSeries, timestamps are required for SpikeEventSeries and are thus re-specified here.","attributes":[{"name":"interval","doc":"Value is '1'","dtype":"int32","value":1},{"name":"unit","doc":"Unit of measurement for timestamps, which is fixed to 'seconds'.","dtype":"text","value":"seconds"}]}],"doc":"Stores snapshots/snippets of recorded spike events (i.e., threshold crossings). This may also be raw data, as reported by ephys hardware. If so, the TimeSeries::description field should describe how events were detected. All SpikeEventSeries should reside in a module (under EventWaveform interface) even if the spikes were reported and stored by hardware. All events span the same recording channels and store snapshots of equal duration. TimeSeries::data array structure: [num events] [num channels] [num samples] (or [num events] [num samples] for single electrode).","neurodata_type_inc":"ElectricalSeries","neurodata_type_def":"SpikeEventSeries","attributes":[{"name":"description","doc":"Description of the time series.","required":false,"dtype":"text","default_value":"no description"},{"name":"comments","doc":"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.","required":false,"dtype":"text","default_value":"no comments"}]},{"datasets":[{"shape":[null],"dims":["num_features"],"dtype":"text","name":"description","doc":"Description of features (eg, ''PC1'') for each of the extracted features."},{"shape":[null,null,null],"dims":["num_events","num_channels","num_features"],"dtype":"float32","name":"features","doc":"Multi-dimensional array of features extracted from each event."},{"shape":[null],"dims":["num_events"],"dtype":"float64","name":"times","doc":"Times of events that features correspond to (can be a link)."},{"name":"electrodes","doc":"DynamicTableRegion pointer to the electrodes that this time series was generated from.","neurodata_type_inc":"DynamicTableRegion"}],"doc":"Features, such as PC1 and PC2, that are extracted from signals stored in a SpikeEventSeries or other source.","default_name":"FeatureExtraction","neurodata_type_inc":"NWBDataInterface","neurodata_type_def":"FeatureExtraction"},{"datasets":[{"dtype":"text","name":"detection_method","doc":"Description of how events were detected, such as voltage threshold, or dV/dT threshold, as well as relevant values."},{"shape":[null],"dims":["num_events"],"dtype":"int32","name":"source_idx","doc":"Indices (zero-based) into source ElectricalSeries::data array corresponding to time of event. ''description'' should define what is meant by time of event (e.g., .25 ms before action potential peak, zero-crossing time, etc). The index points to each event from the raw data."},{"shape":[null],"dims":["num_events"],"dtype":"float64","name":"times","doc":"Timestamps of events, in seconds.","attributes":[{"name":"unit","doc":"Unit of measurement for event times, which is fixed to 'seconds'.","dtype":"text","value":"seconds"}]}],"links":[{"name":"source_electricalseries","doc":"Link to the ElectricalSeries that this data was calculated from. Metadata about electrodes and their position can be read from that ElectricalSeries so it's not necessary to include that information here.","target_type":"ElectricalSeries"}],"doc":"Detected spike events from voltage trace(s).","default_name":"EventDetection","neurodata_type_inc":"NWBDataInterface","neurodata_type_def":"EventDetection"},{"groups":[{"doc":"SpikeEventSeries object(s) containing detected spike event waveforms.","quantity":"*","neurodata_type_inc":"SpikeEventSeries"}],"doc":"Represents either the waveforms of detected events, as extracted from a raw data trace in /acquisition, or the event waveforms that were stored during experiment acquisition.","default_name":"EventWaveform","neurodata_type_inc":"NWBDataInterface","neurodata_type_def":"EventWaveform"},{"groups":[{"doc":"ElectricalSeries object(s) containing filtered electrophysiology data.","quantity":"+","neurodata_type_inc":"ElectricalSeries"}],"doc":"Electrophysiology data from one or more channels that has been subjected to filtering. Examples of filtered data include Theta and Gamma (LFP has its own interface). FilteredEphys modules publish an ElectricalSeries for each filtered channel or set of channels. The name of each ElectricalSeries is arbitrary but should be informative. The source of the filtered data, whether this is from analysis of another time series or as acquired by hardware, should be noted in each's TimeSeries::description field. There is no assumed 1::1 correspondence between filtered ephys signals and electrodes, as a single signal can apply to many nearby electrodes, and one electrode may have different filtered (e.g., theta and/or gamma) signals represented. Filter properties should be noted in the ElectricalSeries.","default_name":"FilteredEphys","neurodata_type_inc":"NWBDataInterface","neurodata_type_def":"FilteredEphys"},{"groups":[{"doc":"ElectricalSeries object(s) containing LFP data for one or more channels.","quantity":"+","neurodata_type_inc":"ElectricalSeries"}],"doc":"LFP data from one or more channels. The electrode map in each published ElectricalSeries will identify which channels are providing LFP data. Filter properties should be noted in the ElectricalSeries description or comments field.","default_name":"LFP","neurodata_type_inc":"NWBDataInterface","neurodata_type_def":"LFP"},{"links":[{"name":"device","doc":"Link to the device that was used to record from this electrode group.","target_type":"Device"}],"doc":"A physical grouping of electrodes, e.g. a shank of an array.","neurodata_type_inc":"NWBContainer","neurodata_type_def":"ElectrodeGroup","attributes":[{"name":"description","doc":"Description of this electrode group.","dtype":"text"},{"name":"location","doc":"Location of electrode group. Specify the area, layer, comments on estimation of area/layer, stereotaxic coordinates if in vivo, etc. Use standard atlas names for anatomical regions when possible.","dtype":"text"}]},{"datasets":[{"dtype":"text","name":"waveform_filtering","doc":"Filtering applied to data before generating mean/sd"},{"shape":[null,null],"dims":["num_clusters","num_samples"],"dtype":"float32","name":"waveform_mean","doc":"The mean waveform for each cluster, using the same indices for each wave as cluster numbers in the associated Clustering module (i.e, cluster 3 is in array slot [3]). Waveforms corresponding to gaps in cluster sequence should be empty (e.g., zero- filled)"},{"shape":[null,null],"dims":["num_clusters","num_samples"],"dtype":"float32","name":"waveform_sd","doc":"Stdev of waveforms for each cluster, using the same indices as in mean"}],"links":[{"name":"clustering_interface","doc":"Link to Clustering interface that was the source of the clustered data","target_type":"Clustering"}],"doc":"DEPRECATED The mean waveform shape, including standard deviation, of the different clusters. Ideally, the waveform analysis should be performed on data that is only high-pass filtered. This is a separate module because it is expected to require updating. For example, IMEC probes may require different storage requirements to store/display mean waveforms, requiring a new interface or an extension of this one.","default_name":"ClusterWaveforms","neurodata_type_inc":"NWBDataInterface","neurodata_type_def":"ClusterWaveforms"},{"datasets":[{"dtype":"text","name":"description","doc":"Description of clusters or clustering, (e.g. cluster 0 is noise, clusters curated using Klusters, etc)"},{"shape":[null],"dims":["num_events"],"dtype":"int32","name":"num","doc":"Cluster number of each event"},{"shape":[null],"dims":["num_clusters"],"dtype":"float32","name":"peak_over_rms","doc":"Maximum ratio of waveform peak to RMS on any channel in the cluster (provides a basic clustering metric)."},{"shape":[null],"dims":["num_events"],"dtype":"float64","name":"times","doc":"Times of clustered events, in seconds. This may be a link to times field in associated FeatureExtraction module."}],"doc":"DEPRECATED Clustered spike data, whether from automatic clustering tools (e.g., klustakwik) or as a result of manual sorting.","default_name":"Clustering","neurodata_type_inc":"NWBDataInterface","neurodata_type_def":"Clustering"}]}B{"groups":[{"datasets":[{"shape":[null],"dims":["num_times"],"dtype":"numeric","name":"data","doc":"Recorded voltage or current.","attributes":[{"name":"unit","doc":"Base unit of measurement for working with the data. Actual stored values are not necessarily stored in these units. To access the data in these units, multiply 'data' by 'conversion'.","dtype":"text"},{"name":"conversion","doc":"Scalar to multiply each element in data to convert it to the specified 'unit'. If the data are stored in acquisition system units or other units that require a conversion to be interpretable, multiply the data by 'conversion' to convert the data to the specified 'unit'. e.g. if the data acquisition system stores values in this object as signed 16-bit integers (int16 range -32,768 to 32,767) that correspond to a 5V range (-2.5V to 2.5V), and the data acquisition system gain is 8000X, then the 'conversion' multiplier to get from raw data acquisition values to recorded volts is 2.5/32768/8000 = 9.5367e-9.","required":false,"dtype":"float32","default_value":1.0},{"name":"resolution","doc":"Smallest meaningful difference between values in data, stored in the specified by unit, 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 -1.0.","required":false,"dtype":"float32","default_value":-1.0}]},{"dtype":"float","name":"gain","doc":"Gain of the recording, in units Volt/Amp (v-clamp) or Volt/Volt (c-clamp).","quantity":"?"}],"links":[{"name":"electrode","doc":"Link to IntracellularElectrode object that describes the electrode that was used to apply or record this data.","target_type":"IntracellularElectrode"}],"doc":"An abstract base class for patch-clamp data - stimulus or response, current or voltage.","neurodata_type_inc":"TimeSeries","neurodata_type_def":"PatchClampSeries","attributes":[{"name":"stimulus_description","doc":"Protocol/stimulus name for this patch-clamp dataset.","dtype":"text"},{"name":"sweep_number","doc":"Sweep number, allows to group different PatchClampSeries together.","required":false,"dtype":"uint64"},{"name":"description","doc":"Description of the time series.","required":false,"dtype":"text","default_value":"no description"},{"name":"comments","doc":"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.","required":false,"dtype":"text","default_value":"no comments"}]},{"datasets":[{"name":"data","doc":"Recorded voltage.","attributes":[{"name":"unit","doc":"Base unit of measurement for working with the data. which is fixed to 'volts'. Actual stored values are not necessarily stored in these units. To access the data in these units, multiply 'data' by 'conversion'.","dtype":"text","value":"volts"},{"name":"conversion","doc":"Scalar to multiply each element in data to convert it to the specified 'unit'. If the data are stored in acquisition system units or other units that require a conversion to be interpretable, multiply the data by 'conversion' to convert the data to the specified 'unit'. e.g. if the data acquisition system stores values in this object as signed 16-bit integers (int16 range -32,768 to 32,767) that correspond to a 5V range (-2.5V to 2.5V), and the data acquisition system gain is 8000X, then the 'conversion' multiplier to get from raw data acquisition values to recorded volts is 2.5/32768/8000 = 9.5367e-9.","required":false,"dtype":"float32","default_value":1.0},{"name":"resolution","doc":"Smallest meaningful difference between values in data, stored in the specified by unit, 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 -1.0.","required":false,"dtype":"float32","default_value":-1.0}]},{"dtype":"float32","name":"bias_current","doc":"Bias current, in amps.","quantity":"?"},{"dtype":"float32","name":"bridge_balance","doc":"Bridge balance, in ohms.","quantity":"?"},{"dtype":"float32","name":"capacitance_compensation","doc":"Capacitance compensation, in farads.","quantity":"?"}],"doc":"Voltage data from an intracellular current-clamp recording. A corresponding CurrentClampStimulusSeries (stored separately as a stimulus) is used to store the current injected.","neurodata_type_inc":"PatchClampSeries","neurodata_type_def":"CurrentClampSeries","attributes":[{"name":"stimulus_description","doc":"Protocol/stimulus name for this patch-clamp dataset.","dtype":"text"},{"name":"sweep_number","doc":"Sweep number, allows to group different PatchClampSeries together.","required":false,"dtype":"uint64"},{"name":"description","doc":"Description of the time series.","required":false,"dtype":"text","default_value":"no description"},{"name":"comments","doc":"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.","required":false,"dtype":"text","default_value":"no comments"}]},{"datasets":[{"dtype":"float32","name":"bias_current","doc":"Bias current, in amps, fixed to 0.0."},{"dtype":"float32","name":"bridge_balance","doc":"Bridge balance, in ohms, fixed to 0.0."},{"dtype":"float32","name":"capacitance_compensation","doc":"Capacitance compensation, in farads, fixed to 0.0."}],"doc":"Voltage data from an intracellular recording when all current and amplifier settings are off (i.e., CurrentClampSeries fields will be zero). There is no CurrentClampStimulusSeries associated with an IZero series because the amplifier is disconnected and no stimulus can reach the cell.","neurodata_type_inc":"CurrentClampSeries","neurodata_type_def":"IZeroClampSeries","attributes":[{"name":"stimulus_description","doc":"Protocol/stimulus name for this patch-clamp dataset.","dtype":"text"},{"name":"sweep_number","doc":"Sweep number, allows to group different PatchClampSeries together.","required":false,"dtype":"uint64"},{"name":"description","doc":"Description of the time series.","required":false,"dtype":"text","default_value":"no description"},{"name":"comments","doc":"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.","required":false,"dtype":"text","default_value":"no comments"}]},{"datasets":[{"name":"data","doc":"Stimulus current applied.","attributes":[{"name":"unit","doc":"Base unit of measurement for working with the data. which is fixed to 'amperes'. Actual stored values are not necessarily stored in these units. To access the data in these units, multiply 'data' by 'conversion'.","dtype":"text","value":"amperes"},{"name":"conversion","doc":"Scalar to multiply each element in data to convert it to the specified 'unit'. If the data are stored in acquisition system units or other units that require a conversion to be interpretable, multiply the data by 'conversion' to convert the data to the specified 'unit'. e.g. if the data acquisition system stores values in this object as signed 16-bit integers (int16 range -32,768 to 32,767) that correspond to a 5V range (-2.5V to 2.5V), and the data acquisition system gain is 8000X, then the 'conversion' multiplier to get from raw data acquisition values to recorded volts is 2.5/32768/8000 = 9.5367e-9.","required":false,"dtype":"float32","default_value":1.0},{"name":"resolution","doc":"Smallest meaningful difference between values in data, stored in the specified by unit, 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 -1.0.","required":false,"dtype":"float32","default_value":-1.0}]}],"doc":"Stimulus current applied during current clamp recording.","neurodata_type_inc":"PatchClampSeries","neurodata_type_def":"CurrentClampStimulusSeries","attributes":[{"name":"stimulus_description","doc":"Protocol/stimulus name for this patch-clamp dataset.","dtype":"text"},{"name":"sweep_number","doc":"Sweep number, allows to group different PatchClampSeries together.","required":false,"dtype":"uint64"},{"name":"description","doc":"Description of the time series.","required":false,"dtype":"text","default_value":"no description"},{"name":"comments","doc":"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.","required":false,"dtype":"text","default_value":"no comments"}]},{"datasets":[{"name":"data","doc":"Recorded current.","attributes":[{"name":"unit","doc":"Base unit of measurement for working with the data. which is fixed to 'amperes'. Actual stored values are not necessarily stored in these units. To access the data in these units, multiply 'data' by 'conversion'.","dtype":"text","value":"amperes"},{"name":"conversion","doc":"Scalar to multiply each element in data to convert it to the specified 'unit'. If the data are stored in acquisition system units or other units that require a conversion to be interpretable, multiply the data by 'conversion' to convert the data to the specified 'unit'. e.g. if the data acquisition system stores values in this object as signed 16-bit integers (int16 range -32,768 to 32,767) that correspond to a 5V range (-2.5V to 2.5V), and the data acquisition system gain is 8000X, then the 'conversion' multiplier to get from raw data acquisition values to recorded volts is 2.5/32768/8000 = 9.5367e-9.","required":false,"dtype":"float32","default_value":1.0},{"name":"resolution","doc":"Smallest meaningful difference between values in data, stored in the specified by unit, 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 -1.0.","required":false,"dtype":"float32","default_value":-1.0}]},{"dtype":"float32","name":"capacitance_fast","doc":"Fast capacitance, in farads.","quantity":"?","attributes":[{"name":"unit","doc":"Unit of measurement for capacitance_fast, which is fixed to 'farads'.","dtype":"text","value":"farads"}]},{"dtype":"float32","name":"capacitance_slow","doc":"Slow capacitance, in farads.","quantity":"?","attributes":[{"name":"unit","doc":"Unit of measurement for capacitance_fast, which is fixed to 'farads'.","dtype":"text","value":"farads"}]},{"dtype":"float32","name":"resistance_comp_bandwidth","doc":"Resistance compensation bandwidth, in hertz.","quantity":"?","attributes":[{"name":"unit","doc":"Unit of measurement for resistance_comp_bandwidth, which is fixed to 'hertz'.","dtype":"text","value":"hertz"}]},{"dtype":"float32","name":"resistance_comp_correction","doc":"Resistance compensation correction, in percent.","quantity":"?","attributes":[{"name":"unit","doc":"Unit of measurement for resistance_comp_correction, which is fixed to 'percent'.","dtype":"text","value":"percent"}]},{"dtype":"float32","name":"resistance_comp_prediction","doc":"Resistance compensation prediction, in percent.","quantity":"?","attributes":[{"name":"unit","doc":"Unit of measurement for resistance_comp_prediction, which is fixed to 'percent'.","dtype":"text","value":"percent"}]},{"dtype":"float32","name":"whole_cell_capacitance_comp","doc":"Whole cell capacitance compensation, in farads.","quantity":"?","attributes":[{"name":"unit","doc":"Unit of measurement for whole_cell_capacitance_comp, which is fixed to 'farads'.","dtype":"text","value":"farads"}]},{"dtype":"float32","name":"whole_cell_series_resistance_comp","doc":"Whole cell series resistance compensation, in ohms.","quantity":"?","attributes":[{"name":"unit","doc":"Unit of measurement for whole_cell_series_resistance_comp, which is fixed to 'ohms'.","dtype":"text","value":"ohms"}]}],"doc":"Current data from an intracellular voltage-clamp recording. A corresponding VoltageClampStimulusSeries (stored separately as a stimulus) is used to store the voltage injected.","neurodata_type_inc":"PatchClampSeries","neurodata_type_def":"VoltageClampSeries","attributes":[{"name":"stimulus_description","doc":"Protocol/stimulus name for this patch-clamp dataset.","dtype":"text"},{"name":"sweep_number","doc":"Sweep number, allows to group different PatchClampSeries together.","required":false,"dtype":"uint64"},{"name":"description","doc":"Description of the time series.","required":false,"dtype":"text","default_value":"no description"},{"name":"comments","doc":"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.","required":false,"dtype":"text","default_value":"no comments"}]},{"datasets":[{"name":"data","doc":"Stimulus voltage applied.","attributes":[{"name":"unit","doc":"Base unit of measurement for working with the data. which is fixed to 'volts'. Actual stored values are not necessarily stored in these units. To access the data in these units, multiply 'data' by 'conversion'.","dtype":"text","value":"volts"},{"name":"conversion","doc":"Scalar to multiply each element in data to convert it to the specified 'unit'. If the data are stored in acquisition system units or other units that require a conversion to be interpretable, multiply the data by 'conversion' to convert the data to the specified 'unit'. e.g. if the data acquisition system stores values in this object as signed 16-bit integers (int16 range -32,768 to 32,767) that correspond to a 5V range (-2.5V to 2.5V), and the data acquisition system gain is 8000X, then the 'conversion' multiplier to get from raw data acquisition values to recorded volts is 2.5/32768/8000 = 9.5367e-9.","required":false,"dtype":"float32","default_value":1.0},{"name":"resolution","doc":"Smallest meaningful difference between values in data, stored in the specified by unit, 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 -1.0.","required":false,"dtype":"float32","default_value":-1.0}]}],"doc":"Stimulus voltage applied during a voltage clamp recording.","neurodata_type_inc":"PatchClampSeries","neurodata_type_def":"VoltageClampStimulusSeries","attributes":[{"name":"stimulus_description","doc":"Protocol/stimulus name for this patch-clamp dataset.","dtype":"text"},{"name":"sweep_number","doc":"Sweep number, allows to group different PatchClampSeries together.","required":false,"dtype":"uint64"},{"name":"description","doc":"Description of the time series.","required":false,"dtype":"text","default_value":"no description"},{"name":"comments","doc":"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.","required":false,"dtype":"text","default_value":"no comments"}]},{"datasets":[{"dtype":"text","name":"description","doc":"Description of electrode (e.g., whole-cell, sharp, etc.)."},{"dtype":"text","name":"filtering","doc":"Electrode specific filtering.","quantity":"?"},{"dtype":"text","name":"initial_access_resistance","doc":"Initial access resistance.","quantity":"?"},{"dtype":"text","name":"location","doc":"Location of the electrode. Specify the area, layer, comments on estimation of area/layer, stereotaxic coordinates if in vivo, etc. Use standard atlas names for anatomical regions when possible.","quantity":"?"},{"dtype":"text","name":"resistance","doc":"Electrode resistance, in ohms.","quantity":"?"},{"dtype":"text","name":"seal","doc":"Information about seal used for recording.","quantity":"?"},{"dtype":"text","name":"slice","doc":"Information about slice used for recording.","quantity":"?"}],"links":[{"name":"device","doc":"Device that was used to record from this electrode.","target_type":"Device"}],"doc":"An intracellular electrode and its metadata.","neurodata_type_inc":"NWBContainer","neurodata_type_def":"IntracellularElectrode"},{"datasets":[{"dtype":"uint64","name":"sweep_number","doc":"Sweep number of the PatchClampSeries in that row.","neurodata_type_inc":"VectorData"},{"dtype":{"target_type":"PatchClampSeries","reftype":"object"},"name":"series","doc":"The PatchClampSeries with the sweep number in that row.","neurodata_type_inc":"VectorData"},{"name":"series_index","doc":"Index for series.","neurodata_type_inc":"VectorIndex"}],"doc":"The table which groups different PatchClampSeries together.","neurodata_type_inc":"DynamicTable","neurodata_type_def":"SweepTable","attributes":[{"name":"colnames","doc":"The names of the columns in this table. This should be used to specify an order to the columns.","dtype":"ascii","shape":[null],"dims":["num_columns"]},{"name":"description","doc":"Description of what is in this dynamic table.","dtype":"text"}]}]},{"groups":[{"datasets":[{"shape":[[2],[3]],"dims":["width|height","width|height|depth"],"dtype":"float32","name":"field_of_view","doc":"Width, height and depth of image, or imaged area, in meters.","quantity":"?"}],"links":[{"name":"imaging_plane","doc":"Link to ImagingPlane object from which this TimeSeries data was generated.","target_type":"ImagingPlane"}],"doc":"Image stack recorded over time from 2-photon microscope.","neurodata_type_inc":"ImageSeries","neurodata_type_def":"TwoPhotonSeries","attributes":[{"name":"pmt_gain","doc":"Photomultiplier gain.","required":false,"dtype":"float32"},{"name":"scan_line_rate","doc":"Lines imaged per second. This is also stored in /general/optophysiology but is kept here as it is useful information for analysis, and so good to be stored w/ the actual data.","required":false,"dtype":"float32"},{"name":"description","doc":"Description of the time series.","required":false,"dtype":"text","default_value":"no description"},{"name":"comments","doc":"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.","required":false,"dtype":"text","default_value":"no comments"}]},{"datasets":[{"shape":[[null],[null,null]],"dims":[["num_times"],["num_times","num_ROIs"]],"dtype":"numeric","name":"data","doc":"Signals from ROIs.","attributes":[{"name":"conversion","doc":"Scalar to multiply each element in data to convert it to the specified 'unit'. If the data are stored in acquisition system units or other units that require a conversion to be interpretable, multiply the data by 'conversion' to convert the data to the specified 'unit'. e.g. if the data acquisition system stores values in this object as signed 16-bit integers (int16 range -32,768 to 32,767) that correspond to a 5V range (-2.5V to 2.5V), and the data acquisition system gain is 8000X, then the 'conversion' multiplier to get from raw data acquisition values to recorded volts is 2.5/32768/8000 = 9.5367e-9.","required":false,"dtype":"float32","default_value":1.0},{"name":"resolution","doc":"Smallest meaningful difference between values in data, stored in the specified by unit, 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 -1.0.","required":false,"dtype":"float32","default_value":-1.0},{"name":"unit","doc":"Base unit of measurement for working with the data. Actual stored values are not necessarily stored in these units. To access the data in these units, multiply 'data' by 'conversion'.","dtype":"text"}]},{"name":"rois","doc":"DynamicTableRegion referencing into an ROITable containing information on the ROIs stored in this timeseries.","neurodata_type_inc":"DynamicTableRegion"}],"doc":"ROI responses over an imaging plane. Each row in data should correspond to the signal from one ROI. Each element on the second dimension of data should correspond to the signal from one ROI.","neurodata_type_inc":"TimeSeries","neurodata_type_def":"RoiResponseSeries","attributes":[{"name":"description","doc":"Description of the time series.","required":false,"dtype":"text","default_value":"no description"},{"name":"comments","doc":"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.","required":false,"dtype":"text","default_value":"no comments"}]},{"groups":[{"doc":"RoiResponseSeries object(s) containing dF/F for a ROI.","quantity":"+","neurodata_type_inc":"RoiResponseSeries"}],"doc":"dF/F information about a region of interest (ROI). Storage hierarchy of dF/F should be the same as for segmentation (i.e., same names for ROIs and for image planes).","default_name":"DfOverF","neurodata_type_inc":"NWBDataInterface","neurodata_type_def":"DfOverF"},{"groups":[{"doc":"RoiResponseSeries object(s) containing fluorescence data for a ROI.","quantity":"+","neurodata_type_inc":"RoiResponseSeries"}],"doc":"Fluorescence information about a region of interest (ROI). Storage hierarchy of fluorescence should be the same as for segmentation (ie, same names for ROIs and for image planes).","default_name":"Fluorescence","neurodata_type_inc":"NWBDataInterface","neurodata_type_def":"Fluorescence"},{"groups":[{"groups":[{"groups":[{"doc":"One or more image stacks that the masks apply to (can be one-element stack).","quantity":"*","neurodata_type_inc":"ImageSeries"}],"name":"reference_images","doc":"Image stacks that the segmentation masks apply to."}],"datasets":[{"shape":[[null,null,null],[null,null,null,null]],"dims":[["num_roi","num_x","num_y"],["num_roi","num_x","num_y","num_z"]],"name":"image_mask","doc":"ROI masks for each ROI. Each image mask is the size of the original imaging plane (or volume) and members of the ROI are finite non-zero.","quantity":"?","neurodata_type_inc":"VectorData"},{"name":"pixel_mask_index","doc":"Index into pixel_mask.","quantity":"?","neurodata_type_inc":"VectorIndex"},{"dtype":[{"doc":"Pixel x-coordinate.","name":"x","dtype":"uint"},{"doc":"Pixel y-coordinate.","name":"y","dtype":"uint"},{"doc":"Weight of the pixel.","name":"weight","dtype":"float"}],"name":"pixel_mask","doc":"Pixel masks for each ROI: a list of indices and weights for the ROI. Pixel masks are concatenated and parsing of this dataset is maintained by the PlaneSegmentation","quantity":"?","neurodata_type_inc":"VectorData"},{"name":"voxel_mask_index","doc":"Index into voxel_mask.","quantity":"?","neurodata_type_inc":"VectorIndex"},{"dtype":[{"doc":"Voxel x-coordinate.","name":"x","dtype":"uint"},{"doc":"Voxel y-coordinate.","name":"y","dtype":"uint"},{"doc":"Voxel z-coordinate.","name":"z","dtype":"uint"},{"doc":"Weight of the voxel.","name":"weight","dtype":"float"}],"name":"voxel_mask","doc":"Voxel masks for each ROI: a list of indices and weights for the ROI. Voxel masks are concatenated and parsing of this dataset is maintained by the PlaneSegmentation","quantity":"?","neurodata_type_inc":"VectorData"},{"shape":[null],"dims":["num_rows"],"dtype":"int","name":"id","doc":"Array of unique identifiers for the rows of this dynamic table.","neurodata_type_inc":"ElementIdentifiers"},{"doc":"Vector columns of this dynamic table.","quantity":"*","neurodata_type_inc":"VectorData"},{"doc":"Indices for the vector columns of this dynamic table.","quantity":"*","neurodata_type_inc":"VectorIndex"}],"links":[{"name":"imaging_plane","doc":"Link to ImagingPlane object from which this data was generated.","target_type":"ImagingPlane"}],"doc":"Results from image segmentation of a specific imaging plane.","quantity":"+","neurodata_type_inc":"DynamicTable","neurodata_type_def":"PlaneSegmentation","attributes":[{"name":"colnames","doc":"The names of the columns in this table. This should be used to specify an order to the columns.","dtype":"ascii","shape":[null],"dims":["num_columns"]},{"name":"description","doc":"Description of what is in this dynamic table.","dtype":"text"}]}],"doc":"Stores pixels in an image that represent different regions of interest (ROIs) or masks. All segmentation for a given imaging plane is stored together, with storage for multiple imaging planes (masks) supported. Each ROI is stored in its own subgroup, with the ROI group containing both a 2D mask and a list of pixels that make up this mask. Segments can also be used for masking neuropil. If segmentation is allowed to change with time, a new imaging plane (or module) is required and ROI names should remain consistent between them.","default_name":"ImageSegmentation","neurodata_type_inc":"NWBDataInterface","neurodata_type_def":"ImageSegmentation"},{"groups":[{"datasets":[{"dtype":"text","name":"description","doc":"Description or other notes about the channel."},{"dtype":"float","name":"emission_lambda","doc":"Emission wavelength for channel, in nm."}],"doc":"An optical channel used to record from an imaging plane.","neurodata_type_inc":"NWBContainer","neurodata_type_def":"OpticalChannel"}],"datasets":[{"dtype":"text","name":"description","doc":"Description of the imaging plane.","quantity":"?"},{"dtype":"float","name":"excitation_lambda","doc":"Excitation wavelength, in nm."},{"dtype":"float","name":"imaging_rate","doc":"Rate that images are acquired, in Hz."},{"dtype":"text","name":"indicator","doc":"Calcium indicator."},{"dtype":"text","name":"location","doc":"Location of the imaging plane. Specify the area, layer, comments on estimation of area/layer, stereotaxic coordinates if in vivo, etc. Use standard atlas names for anatomical regions when possible."},{"shape":[[null,null,3],[null,null,null,3]],"dims":[["height","width","x|y|z"],["height","width","depth","x|y|z"]],"dtype":"float32","name":"manifold","doc":"Physical position of each pixel. 'xyz' represents the position of the pixel relative to the defined coordinate space.","quantity":"?","attributes":[{"name":"conversion","doc":"Scalar to multiply each element in data to convert it to the specified 'unit'. If the data are stored in acquisition system units or other units that require a conversion to be interpretable, multiply the data by 'conversion' to convert the data to the specified 'unit'. e.g. if the data acquisition system stores values in this object as pixels from x = -500 to 499, y = -500 to 499 that correspond to a 2 m x 2 m range, then the 'conversion' multiplier to get from raw data acquisition pixel units to meters is 2/1000.","required":false,"dtype":"float","default_value":1.0},{"name":"unit","doc":"Base unit of measurement for working with the data. The default value is 'meters'.","required":false,"dtype":"text","default_value":"meters"}]},{"dtype":"text","name":"reference_frame","doc":"Describes position and reference frame of manifold based on position of first element in manifold. For example, text description of anatomical location or vectors needed to rotate to common anatomical axis (eg, AP/DV/ML). This field is necessary to interpret manifold. If manifold is not present then this field is not required.","quantity":"?"}],"links":[{"name":"device","doc":"Link to the Device object that was used to record from this electrode.","target_type":"Device"}],"doc":"An imaging plane and its metadata.","quantity":"*","neurodata_type_inc":"NWBContainer","neurodata_type_def":"ImagingPlane"},{"groups":[{"groups":[{"name":"corrected","doc":"Image stack with frames shifted to the common coordinates.","neurodata_type_inc":"ImageSeries"},{"name":"xy_translation","doc":"Stores the x,y delta necessary to align each frame to the common coordinates, for example, to align each frame to a reference image.","neurodata_type_inc":"TimeSeries"}],"links":[{"name":"original","doc":"Link to ImageSeries object that is being registered.","target_type":"ImageSeries"}],"doc":"Reuslts from motion correction of an image stack.","quantity":"+","neurodata_type_inc":"NWBDataInterface","neurodata_type_def":"CorrectedImageStack"}],"doc":"An image stack where all frames are shifted (registered) to a common coordinate system, to account for movement and drift between frames. Note: each frame at each point in time is assumed to be 2-D (has only x & y dimensions).","default_name":"MotionCorrection","neurodata_type_inc":"NWBDataInterface","neurodata_type_def":"MotionCorrection"}]}{"groups":[{"datasets":[{"shape":[null,null],"dims":["num_rows","num_cols"],"dtype":"float32","name":"axis_1_phase_map","doc":"Phase response to stimulus on the first measured axis.","attributes":[{"name":"dimension","doc":"Number of rows and columns in the image. NOTE: row, column representation is equivalent to height,width.","dtype":"int32","shape":[null],"dims":["row_col"]},{"name":"field_of_view","doc":"Size of viewing area, in meters.","dtype":"float","shape":[null],"dims":["row|column"]},{"name":"unit","doc":"Unit that axis data is stored in (e.g., degrees).","dtype":"text"}]},{"shape":[null,null],"dims":["num_rows","num_cols"],"dtype":"float32","name":"axis_1_power_map","doc":"Power response on the first measured axis. Response is scaled so 0.0 is no power in the response and 1.0 is maximum relative power.","quantity":"?","attributes":[{"name":"dimension","doc":"Number of rows and columns in the image. NOTE: row, column representation is equivalent to height,width.","dtype":"int32","shape":[null],"dims":["row_col"]},{"name":"field_of_view","doc":"Size of viewing area, in meters.","dtype":"float","shape":[null],"dims":["row_col"]},{"name":"unit","doc":"Unit that axis data is stored in (e.g., degrees).","dtype":"text"}]},{"shape":[null,null],"dims":["num_rows","num_cols"],"dtype":"float32","name":"axis_2_phase_map","doc":"Phase response to stimulus on the second measured axis.","attributes":[{"name":"dimension","doc":"Number of rows and columns in the image. NOTE: row, column representation is equivalent to height,width.","dtype":"int32","shape":[null],"dims":["row_col"]},{"name":"field_of_view","doc":"Size of viewing area, in meters.","dtype":"float","shape":[null],"dims":["row_col"]},{"name":"unit","doc":"Unit that axis data is stored in (e.g., degrees).","dtype":"text"}]},{"shape":[null,null],"dims":["num_rows","num_cols"],"dtype":"float32","name":"axis_2_power_map","doc":"Power response on the second measured axis. Response is scaled so 0.0 is no power in the response and 1.0 is maximum relative power.","quantity":"?","attributes":[{"name":"dimension","doc":"Number of rows and columns in the image. NOTE: row, column representation is equivalent to height,width.","dtype":"int32","shape":[null],"dims":["row_col"]},{"name":"field_of_view","doc":"Size of viewing area, in meters.","dtype":"float","shape":[null],"dims":["row_col"]},{"name":"unit","doc":"Unit that axis data is stored in (e.g., degrees).","dtype":"text"}]},{"shape":[2],"dims":["names"],"dtype":"text","name":"axis_descriptions","doc":"Two-element array describing the contents of the two response axis fields. Description should be something like ['altitude', 'azimuth'] or '['radius', 'theta']."},{"shape":[null,null],"dims":["num_rows","num_cols"],"dtype":"uint16","name":"focal_depth_image","doc":"Gray-scale image taken with same settings/parameters (e.g., focal depth, wavelength) as data collection. Array format: [rows][columns].","attributes":[{"name":"bits_per_pixel","doc":"Number of bits used to represent each value. This is necessary to determine maximum (white) pixel value.","dtype":"int32"},{"name":"dimension","doc":"Number of rows and columns in the image. NOTE: row, column representation is equivalent to height,width.","dtype":"int32","shape":[null],"dims":["row_col"]},{"name":"field_of_view","doc":"Size of viewing area, in meters.","dtype":"float","shape":[null],"dims":["row_col"]},{"name":"focal_depth","doc":"Focal depth offset, in meters.","dtype":"float"},{"name":"format","doc":"Format of image. Right now only 'raw' is supported.","dtype":"text"}]},{"shape":[null,null],"dims":["num_rows","num_cols"],"dtype":"float32","name":"sign_map","doc":"Sine of the angle between the direction of the gradient in axis_1 and axis_2.","attributes":[{"name":"dimension","doc":"Number of rows and columns in the image. NOTE: row, column representation is equivalent to height,width.","dtype":"int32","shape":[null],"dims":["row_col"]},{"name":"field_of_view","doc":"Size of viewing area, in meters.","dtype":"float","shape":[null],"dims":["row_col"]}]},{"shape":[null,null],"dims":["num_rows","num_cols"],"dtype":"uint16","name":"vasculature_image","doc":"Gray-scale anatomical image of cortical surface. Array structure: [rows][columns]","attributes":[{"name":"bits_per_pixel","doc":"Number of bits used to represent each value. This is necessary to determine maximum (white) pixel value","dtype":"int32"},{"name":"dimension","doc":"Number of rows and columns in the image. NOTE: row, column representation is equivalent to height,width.","dtype":"int32","shape":[null],"dims":["row_col"]},{"name":"field_of_view","doc":"Size of viewing area, in meters.","dtype":"float","shape":[null],"dims":["row_col"]},{"name":"format","doc":"Format of image. Right now only 'raw' is supported.","dtype":"text"}]}],"doc":"Intrinsic signal optical imaging or widefield imaging for measuring retinotopy. Stores orthogonal maps (e.g., altitude/azimuth; radius/theta) of responses to specific stimuli and a combined polarity map from which to identify visual areas. Note: for data consistency, all images and arrays are stored in the format [row][column] and [row, col], which equates to [y][x]. Field of view and dimension arrays may appear backward (i.e., y before x).","default_name":"ImagingRetinotopy","neurodata_type_inc":"NWBDataInterface","neurodata_type_def":"ImagingRetinotopy"}]}U{"namespaces":[{"doc":"NWB namespace","schema":[{"source":"nwb.base"},{"source":"nwb.epoch"},{"source":"nwb.image"},{"source":"nwb.file"},{"source":"nwb.misc"},{"source":"nwb.behavior"},{"source":"nwb.ecephys"},{"source":"nwb.icephys"},{"source":"nwb.ogen"},{"source":"nwb.ophys"},{"source":"nwb.retinotopy"}],"name":"core","full_name":"NWB core","version":"2.1.0","author":["Andrew Tritt","Oliver Ruebel","Ryan Ly","Ben Dichter","Keith Godfrey","Jeff Teeters"],"contact":["ajtritt@lbl.gov","oruebel@lbl.gov","rly@lbl.gov","bdichter@lbl.gov","keithg@alleninstitute.org","jteeters@berkeley.edu"]}]}P/pynwb-1.2.1/tests/coloredtestrunner.py0000644000655200065520000004367513612200244021546 0ustar circlecicircleci00000000000000# -*- coding: utf-8 -*- """ A ColoredTestRunner for use with the Python unit testing framework. It generates a tabular report to show the result at a glance, with COLORS. coloredtestrunner.py was modified from code written by Vinícius Dantas and posted as a gist: https://gist.github.com/viniciusd/73e6eccd39dea5e714b1464e3c47e067 and demonstrated here: https://stackoverflow.com/questions/17162682/display-python-unittest-results-in-nice-tabular-form/31665827#31665827 The code linked above is based on HTMLTestRunner written by Wai Yip Tung. The BSD-3-Clause license covering HTMLTestRunner is below. ------------------------------------------------------------------------ Copyright (c) 2004-2007, Wai Yip Tung All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name Wai Yip Tung nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. """ import datetime try: from StringIO import StringIO except ImportError: from io import StringIO import sys import re import unittest import textwrap # ------------------------------------------------------------------------ # The redirectors below are used to capture output during testing. Output # sent to sys.stdout and sys.stderr are automatically captured. However # in some cases sys.stdout is already cached before HTMLTestRunner is # invoked (e.g. calling logging.basicConfig). In order to capture those # output, use the redirectors for the cached stream. # # e.g. # >>> logging.basicConfig(stream=HTMLTestRunner.stdout_redirector) # >>> class OutputRedirector(object): """ Wrapper to redirect stdout or stderr """ def __init__(self, fp): self.fp = fp def write(self, s): self.fp.write(s) def writelines(self, lines): self.fp.writelines(lines) def flush(self): self.fp.flush() class Table(object): def __init__(self, padding='', allow_newlines=False): self.__columnSize__ = [] self.__rows__ = [] self.__titles__ = None self.padding = padding self.allow_newlines = allow_newlines def __len__(self, x): return len(re.sub(r"\033\[[0-9];[0-9];[0-9]{1,2}m", "", x)) def addRow(self, row): rows = [[''] for l in range(len(row))] maxrows = 0 for i, x in enumerate(row): for j, y in enumerate(x.split("\n")): if len(y) == 0 and not self.allow_newlines: continue try: self.__columnSize__[i] = max(self.__columnSize__[i], self.__len__(y)) except IndexError: self.__columnSize__.append(self.__len__(y)) rows[i].append(y) maxrows = max(j, maxrows) for i in range(len(rows)): rows[i] += (maxrows-len(rows[i])+2)*[''] for i in range(maxrows + 1): self.__rows__.append([rows[j][i+1] for j in range(len(row))]) def addTitles(self, titles): for i, x in enumerate(titles): try: self.__columnSize__[i] = max(self.__columnSize__[i], self.__len__(x)) except IndexError: self.__columnSize__.append(self.__len__(x)) self.__titles__ = titles def __repr__(self): hline = self.padding+"+" for x in self.__columnSize__: hline += (x+2)*'-'+'+' rows = [] if self.__titles__ is None: title = "" else: if len(self.__titles__) < len(self.__columnSize__): self.__titles__ += ((len(self.__columnSize__)-len(self.__titles__))*['']) for i, x in enumerate(self.__titles__): self.__titles__[i] = x.center(self.__columnSize__[i]) title = self.padding+"| "+" | ".join(self.__titles__)+" |\n"+hline+"\n" for x in self.__rows__: if len(x) < len(self.__columnSize__): x += ((len(self.__columnSize__)-len(x))*['']) for i, c in enumerate(x): x[i] = c.ljust(self.__columnSize__[i])+(len(c)-self.__len__(c)-3)*' ' rows.append(self.padding+"| "+" | ".join(x)+" |") return hline+"\n"+title+"\n".join(rows)+"\n"+hline+"\n" class bcolors(object): FORMAT = { 'Regular': '0', 'Bold': '1', 'Underline': '4', 'High Intensity': '0', # +60 on color 'BoldHighIntensity': '1', # +60 on color } START = "\033[" COLOR = { 'black': "0;30m", 'red': "0;31m", 'green': "0;32m", 'yellow': "0;33m", 'blue': "0;34m", 'purple': "0;35m", 'cyan': "0;36m", 'white': "0;37m", 'end': "0m", } def __getattr__(self, name): def handlerFunction(*args, **kwargs): return self.START+self.FORMAT['Regular']+";"+self.COLOR[name.lower()] return handlerFunction(name=name) # ---------------------------------------------------------------------- # Template class Template_mixin(object): bc = bcolors() STATUS = { 0: bc.GREEN+'pass'+bc.END, 1: bc.PURPLE+'fail'+bc.END, 2: bc.RED+'error'+bc.END, } # ------------------------------------------------------------------------ # Report REPORT_TEST_WITH_OUTPUT_TMPL = r""" %(desc)s %(status)s %(script)s """ # variables: (tid, Class, style, desc, status) REPORT_TEST_NO_OUTPUT_TMPL = r""" %(desc)s %(status)s """ # variables: (tid, Class, style, desc, status) REPORT_TEST_OUTPUT_TMPL = r""" %(output)s """ # variables: (id, output) class ColoredTestResult(unittest.TextTestResult): stdout_redirector = OutputRedirector(sys.stdout) stderr_redirector = OutputRedirector(sys.stderr) def __init__(self, stream, descriptions, verbosity=1): super(ColoredTestResult, self).__init__(stream, descriptions, verbosity) self.stdout0 = None self.stderr0 = None self.success_count = 0 self.failure_count = 0 self.error_count = 0 self.skip_count = 0 self.verbosity = verbosity # deny TextTestResult showAll functionality self.showAll = False # result is a list of result in 4 tuple # ( # result code (0: success; 1: fail; 2: error), # TestCase object, # Test output (byte string), # stack trace, # ) self.result = [] def startTest(self, test): super(ColoredTestResult, self).startTest(test) # just one buffer for both stdout and stderr self.outputBuffer = StringIO() self.stdout_redirector.fp = self.outputBuffer self.stderr_redirector.fp = self.outputBuffer self.stdout0 = sys.stdout self.stderr0 = sys.stderr sys.stdout = self.stdout_redirector sys.stderr = self.stderr_redirector def complete_output(self): """ Disconnect output redirection and return buffer. Safe to call multiple times. """ if self.stdout0: sys.stdout = self.stdout0 sys.stderr = self.stderr0 self.stdout0 = None self.stderr0 = None return self.outputBuffer.getvalue() def stopTest(self, test): # Usually one of addSuccess, addError or addFailure would have been called. # But there are some path in unittest that would bypass this. # We must disconnect stdout in stopTest(), which is guaranteed to be called. self.complete_output() def addSuccess(self, test): self.success_count += 1 super(ColoredTestResult, self).addSuccess(test) output = self.complete_output() self.result.append((0, test, output, '')) sys.stdout.write('.') sys.stdout.flush() if not hasattr(self, 'successes'): self.successes = [test] else: self.successes.append(test) def addError(self, test, err): self.error_count += 1 super(ColoredTestResult, self).addError(test, err) output = self.complete_output() _, _exc_str = self.errors[-1] self.result.append((2, test, output, _exc_str)) sys.stdout.write('E') sys.stdout.flush() def addFailure(self, test, err): self.failure_count += 1 super(ColoredTestResult, self).addFailure(test, err) output = self.complete_output() _, _exc_str = self.failures[-1] self.result.append((1, test, output, _exc_str)) sys.stdout.write('F') sys.stdout.flush() def addSubTest(self, test, subtest, err): if err is not None: if issubclass(err[0], test.failureException): self.addFailure(subtest, err) else: self.addError(subtest, err) def addSkip(self, test, reason): self.skip_count += 1 super(ColoredTestResult, self).addSkip(test, reason) self.complete_output() sys.stdout.write('s') sys.stdout.flush() def get_all_cases_run(self): '''Return a list of each test case which failed or succeeded ''' cases = [] if hasattr(self, 'successes'): cases.extend(self.successes) cases.extend([failure[0] for failure in self.failures]) return cases class ColoredTestRunner(Template_mixin): def __init__(self, stream=sys.stdout, verbosity=1, title=None, description=None): self.stream = stream self.verbosity = verbosity if title is None: self.title = '' else: self.title = title if description is None: self.description = '' else: self.description = description self.startTime = datetime.datetime.now() self.bc = bcolors() self.desc_width = 40 self.output_width = 60 def run(self, test): "Run the given test case or test suite." result = ColoredTestResult(stream=self.stream, descriptions=True, verbosity=self.verbosity) test(result) self.stopTime = datetime.datetime.now() self.generateReport(test, result) return result def sortResult(self, result_list): # unittest does not seems to run in any particular order. # Here at least we want to group them together by class. rmap = {} classes = [] for n, test, output, error in result_list: testClass = test.__class__ if testClass not in rmap: rmap[testClass] = [] classes.append(testClass) rmap[testClass].append((n, test, output, error)) r = [(testClass, rmap[testClass]) for testClass in classes] return r def getReportAttributes(self, result): """ Return report attributes as a list of (name, value). Override this to add custom attributes. """ startTime = str(self.startTime)[:19] duration = str(self.stopTime - self.startTime) status = [] padding = 4 * ' ' if result.success_count: status.append(padding + self.bc.GREEN + 'Pass:' + self.bc.END + ' %s\n' % result.success_count) if result.failure_count: status.append(padding + self.bc.PURPLE + 'Failure:' + self.bc.END + ' %s\n' % result.failure_count) if result.error_count: status.append(padding + self.bc.RED + 'Error:' + self.bc.END + ' %s\n' % result.error_count) if status: status = '\n'+''.join(status) else: status = 'none' return [ ('Start Time', startTime), ('Duration', duration), ('Status', status), ] def generateReport(self, test, result): report_attrs = self.getReportAttributes(result) heading = self._generate_heading(report_attrs) report = self._generate_report(result) output = "\n" + self.title.rjust(30) + "\n" + heading + report try: self.stream.write(output.encode('utf8')) except TypeError: self.stream.write(output) def _generate_heading(self, report_attrs): a_lines = [] for name, value in report_attrs: line = self.bc.CYAN + name + ": " + self.bc.END + value + "\n" a_lines.append(line) heading = ''.join(a_lines) + self.bc.CYAN + "Description:" + self.bc.END + self.description + "\n" return heading def _generate_report(self, result): sortedResult = self.sortResult(result.result) padding = 4 * ' ' table = Table(padding=padding, allow_newlines=True) table.addTitles(["Test group/Test case", "Count", "Pass", "Fail", "Error"]) tests = '' for cid, (testClass, classResults) in enumerate(sortedResult): # Iterate over the test cases classTable = Table(padding=2*padding) classTable.addTitles(["Test name", "Output", "Status"]) # subtotal for a class np = nf = ne = 0 for n, test, output, error in classResults: if n == 0: np += 1 elif n == 1: nf += 1 else: ne += 1 # format class description if testClass.__module__ == "__main__": name = testClass.__name__ else: name = "%s.%s" % (testClass.__module__, testClass.__name__) tests += padding + name + "\n" doc = testClass.__doc__ and testClass.__doc__.split("\n")[0] or "" if doc: doc = self._indent(self._wrap_text(doc, width=self.output_width - 4), 4) desc = doc and ('%s:\n%s' % (name, doc)) or name table.addRow([self._wrap_text(desc, width=self.desc_width), str(np + nf + ne), str(np), str(nf), str(ne)]) for tid, (n, test, output, error) in enumerate(classResults): # Iterate over the unit tests classTable.addRow(self._generate_report_test(cid, tid, n, test, output, error)) tests += str(classTable) for tid, (n, test, output, error) in enumerate(classResults): # Iterate over the unit tests if error: tests += self._indent(self.bc.RED + "ERROR in test %s:" % test + self.bc.END, 2) tests += "\n" + self._indent(error, 2) + "\n" table.addRow([self.desc_width * '-', '----', '----', '----', '----']) table.addRow(["Total", str(result.success_count + result.failure_count + result.error_count), str(result.success_count), str(result.failure_count), str(result.error_count)]) report = self.bc.CYAN + "Summary: " + self.bc.END + "\n" + str(table) + tests return report def _generate_report_test(self, cid, tid, n, test, output, error): name = test.id().split('.')[-1] doc = test.shortDescription() or "" if doc: doc = self._indent(self._wrap_text(doc, width=self.output_width - 4), 4) desc = doc and ('%s:\n%s' % (name, doc)) or name # o and e should be byte string because they are collected from stdout and stderr? if isinstance(output, str): # TODO: some problem with 'string_escape': it escape \n and mess up formating # uo = unicode(o.encode('string_escape')) try: uo = output.decode('latin-1') except AttributeError: uo = output else: uo = output if isinstance(error, str): # TODO: some problem with 'string_escape': it escape \n and mess up formating # ue = unicode(e.encode('string_escape')) try: ue = error.decode('latin-1') except AttributeError: ue = error else: ue = error # just print the last line of any error if "\n" in ue: ue = ue.splitlines()[-1] script = self.REPORT_TEST_OUTPUT_TMPL % dict( output=self._wrap_text(uo, width=self.output_width) + self._wrap_text(ue, width=self.output_width), ) row = [desc, script, self.STATUS[n]] return row @staticmethod def _wrap_text(text, width): """Wrap text to a given width but preserve line breaks """ # https://stackoverflow.com/a/26538082 return '\n'.join(['\n'.join(textwrap.wrap(line, width, break_long_words=False, replace_whitespace=False)) for line in text.splitlines() if line.strip() != '']) @staticmethod def _indent(text, amount): """Indent text by a particular number of spaces on each line """ try: return textwrap.indent(text, amount * ' ') except AttributeError: # undefined function (indent wasn't added until Python 3.3) return ''.join((amount * ' ') + line for line in text.splitlines(True)) pynwb-1.2.1/tests/integration/0000755000655200065520000000000013612200376017725 5ustar circlecicircleci00000000000000pynwb-1.2.1/tests/integration/__init__.py0000644000655200065520000000000013612200244022016 0ustar circlecicircleci00000000000000pynwb-1.2.1/tests/integration/hdf5/0000755000655200065520000000000013612200376020553 5ustar circlecicircleci00000000000000pynwb-1.2.1/tests/integration/hdf5/test_device.py0000644000655200065520000000104213612200244023412 0ustar circlecicircleci00000000000000from pynwb.device import Device from pynwb.testing import NWBH5IOMixin, TestCase class TestDeviceIO(NWBH5IOMixin, TestCase): def setUpContainer(self): """ Return the test Device to read/write """ return Device(name='device_name') def addContainer(self, nwbfile): """ Add the test Device to the given NWBFile """ nwbfile.add_device(self.container) def getContainer(self, nwbfile): """ Return the test Device from the given NWBFile """ return nwbfile.get_device(self.container.name) pynwb-1.2.1/tests/integration/hdf5/test_ecephys.py0000644000655200065520000002223013612200244023615 0ustar circlecicircleci00000000000000from hdmf.common import DynamicTableRegion from pynwb.ecephys import ElectrodeGroup, ElectricalSeries, FilteredEphys, LFP, Clustering, ClusterWaveforms,\ SpikeEventSeries, EventWaveform, EventDetection, FeatureExtraction from pynwb.device import Device from pynwb.file import ElectrodeTable as get_electrode_table from pynwb.testing import NWBH5IOMixin, AcquisitionH5IOMixin, TestCase class TestElectrodeGroupIO(NWBH5IOMixin, TestCase): def setUpContainer(self): """ Return the test ElectrodeGroup to read/write """ self.dev1 = Device('dev1') eg = ElectrodeGroup('elec1', 'a test ElectrodeGroup', 'a nonexistent place', self.dev1) return eg def addContainer(self, nwbfile): """ Add the test ElectrodeGroup to the given NWBFile """ nwbfile.add_device(self.dev1) nwbfile.add_electrode_group(self.container) def getContainer(self, nwbfile): """ Return the test ElectrodeGroup from the given NWBFile """ return nwbfile.get_electrode_group(self.container.name) class TestElectricalSeriesIO(AcquisitionH5IOMixin, TestCase): @staticmethod def make_electrode_table(self): """ Make an electrode table, electrode group, and device """ self.table = get_electrode_table() self.dev1 = Device('dev1') self.group = ElectrodeGroup('tetrode1', 'tetrode description', 'tetrode location', self.dev1) for i in range(4): self.table.add_row(x=i, y=2.0, z=3.0, imp=-1.0, location='CA1', filtering='none', group=self.group, group_name='tetrode1') def setUpContainer(self): """ Return the test ElectricalSeries to read/write """ self.make_electrode_table(self) region = DynamicTableRegion('electrodes', [0, 2], 'the first and third electrodes', self.table) data = list(zip(range(10), range(10, 20))) timestamps = list(map(lambda x: x/10, range(10))) es = ElectricalSeries('test_eS', data, region, channel_conversion=[4., .4], timestamps=timestamps) return es def addContainer(self, nwbfile): """ Add the test ElectricalSeries and related objects to the given NWBFile """ nwbfile.add_device(self.dev1) nwbfile.add_electrode_group(self.group) nwbfile.set_electrode_table(self.table) nwbfile.add_acquisition(self.container) def test_eg_ref(self): """ Test that the electrode DynamicTableRegion references of the read ElectricalSeries have a group that correctly resolves to ElectrodeGroup instances. """ read = self.roundtripContainer() row1 = read.electrodes[0] row2 = read.electrodes[1] self.assertIsInstance(row1.iloc[0]['group'], ElectrodeGroup) self.assertIsInstance(row2.iloc[0]['group'], ElectrodeGroup) class MultiElectricalSeriesIOMixin(AcquisitionH5IOMixin): """ Mixin class for methods to run a roundtrip test writing an NWB file with multiple ElectricalSeries. The abstract method setUpContainer needs to be implemented by classes that include this mixin. def setUpContainer(self): # return a test Container to read/write """ def setUpTwoElectricalSeries(self): """ Return two test ElectricalSeries to read/write """ TestElectricalSeriesIO.make_electrode_table(self) region1 = DynamicTableRegion('electrodes', [0, 2], 'the first and third electrodes', self.table) region2 = DynamicTableRegion('electrodes', [1, 3], 'the second and fourth electrodes', self.table) data1 = list(zip(range(10), range(10, 20))) data2 = list(zip(reversed(range(10)), reversed(range(10, 20)))) timestamps = list(map(lambda x: x/10, range(10))) es1 = ElectricalSeries('test_eS1', data1, region1, timestamps=timestamps) es2 = ElectricalSeries('test_eS2', data2, region2, channel_conversion=[4., .4], timestamps=timestamps) return es1, es2 def addContainer(self, nwbfile): """ Add the test ElectricalSeries and related objects to the given NWBFile """ nwbfile.add_device(self.dev1) nwbfile.add_electrode_group(self.group) nwbfile.set_electrode_table(self.table) nwbfile.add_acquisition(self.container) class TestLFPIO(MultiElectricalSeriesIOMixin, TestCase): def setUpContainer(self): """ Return a test LFP to read/write """ es = self.setUpTwoElectricalSeries() lfp = LFP(es) return lfp class TestFilteredEphysIO(MultiElectricalSeriesIOMixin, TestCase): def setUpContainer(self): """ Return a test FilteredEphys to read/write """ es = self.setUpTwoElectricalSeries() fe = FilteredEphys(es) return fe class TestClusteringIO(AcquisitionH5IOMixin, TestCase): def setUpContainer(self): """ Return a test Clustering to read/write """ with self.assertWarnsWith(DeprecationWarning, 'use pynwb.misc.Units or NWBFile.units instead'): return Clustering("A fake Clustering interface", [0, 1, 2, 0, 1, 2], [100., 101., 102.], [float(i) for i in range(10, 61, 10)]) def roundtripContainer(self, cache_spec=False): # catch the DeprecationWarning raised when reading the Clustering object from file with self.assertWarnsWith(DeprecationWarning, 'use pynwb.misc.Units or NWBFile.units instead'): return super().roundtripContainer(cache_spec) class EventWaveformConstructor(AcquisitionH5IOMixin, TestCase): def setUpContainer(self): """ Return a test EventWaveform to read/write """ TestElectricalSeriesIO.make_electrode_table(self) region = DynamicTableRegion('electrodes', [0, 2], 'the first and third electrodes', self.table) sES = SpikeEventSeries('test_sES', ((1, 1, 1), (2, 2, 2)), list(range(2)), region) ew = EventWaveform(sES) return ew def addContainer(self, nwbfile): """ Add the test EventWaveform and related objects to the given NWBFile """ nwbfile.add_device(self.dev1) nwbfile.add_electrode_group(self.group) nwbfile.set_electrode_table(self.table) nwbfile.add_acquisition(self.container) class ClusterWaveformsConstructor(AcquisitionH5IOMixin, TestCase): def setUpContainer(self): """ Return a test ClusterWaveforms to read/write """ times = [1.3, 2.3] num = [3, 4] peak_over_rms = [5.3, 6.3] with self.assertWarnsWith(DeprecationWarning, 'use pynwb.misc.Units or NWBFile.units instead'): self.clustering = Clustering('description', num, peak_over_rms, times) means = [[7.3, 7.3]] stdevs = [[8.3, 8.3]] with self.assertWarnsWith(DeprecationWarning, 'use pynwb.misc.Units or NWBFile.units instead'): cw = ClusterWaveforms(self.clustering, 'filtering', means, stdevs) return cw def addContainer(self, nwbfile): """ Add the test ClusterWaveforms and related objects to the given NWBFile """ nwbfile.add_acquisition(self.clustering) nwbfile.add_acquisition(self.container) def roundtripContainer(self, cache_spec=False): # catch the DeprecationWarning raised when reading the Clustering object from file with self.assertWarnsWith(DeprecationWarning, 'use pynwb.misc.Units or NWBFile.units instead'): return super().roundtripContainer(cache_spec) class FeatureExtractionConstructor(AcquisitionH5IOMixin, TestCase): def setUpContainer(self): """ Return a test FeatureExtraction to read/write """ event_times = [1.9, 3.5] TestElectricalSeriesIO.make_electrode_table(self) region = DynamicTableRegion('electrodes', [0, 2], 'the first and third electrodes', self.table) description = ['desc1', 'desc2', 'desc3'] features = [[[0., 1., 2.], [3., 4., 5.]], [[6., 7., 8.], [9., 10., 11.]]] fe = FeatureExtraction(region, description, event_times, features) return fe def addContainer(self, nwbfile): """ Add the test FeatureExtraction and related objects to the given NWBFile """ nwbfile.add_device(self.dev1) nwbfile.add_electrode_group(self.group) nwbfile.set_electrode_table(self.table) nwbfile.add_acquisition(self.container) class EventDetectionConstructor(AcquisitionH5IOMixin, TestCase): def setUpContainer(self): """ Return a test EventDetection to read/write """ TestElectricalSeriesIO.make_electrode_table(self) region = DynamicTableRegion('electrodes', [0, 2], 'the first and third electrodes', self.table) data = list(range(10)) ts = [0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0] self.eS = ElectricalSeries('test_eS', data, region, timestamps=ts) eD = EventDetection('detection_method', self.eS, (1, 2, 3), (0.1, 0.2, 0.3)) return eD def addContainer(self, nwbfile): """ Add the test EventDetection and related objects to the given NWBFile """ nwbfile.add_device(self.dev1) nwbfile.add_electrode_group(self.group) nwbfile.set_electrode_table(self.table) nwbfile.add_acquisition(self.eS) nwbfile.add_acquisition(self.container) pynwb-1.2.1/tests/integration/hdf5/test_icephys.py0000644000655200065520000002545113612200244023631 0ustar circlecicircleci00000000000000from pynwb import NWBFile from pynwb.icephys import (IntracellularElectrode, PatchClampSeries, CurrentClampStimulusSeries, SweepTable, VoltageClampStimulusSeries, CurrentClampSeries, VoltageClampSeries, IZeroClampSeries) from pynwb.device import Device from pynwb.testing import NWBH5IOMixin, AcquisitionH5IOMixin, TestCase class TestIntracellularElectrode(NWBH5IOMixin, TestCase): def setUpContainer(self): """ Return the test IntracellularElectrode to read/write """ self.device = Device(name='device_name') elec = IntracellularElectrode(name="elec0", slice='tissue slice', resistance='something measured in ohms', seal='sealing method', description='a fake electrode object', location='Springfield Elementary School', filtering='a meaningless free-form text field', initial_access_resistance='I guess this changes', device=self.device) return elec def addContainer(self, nwbfile): """ Add the test IntracellularElectrode and Device to the given NWBFile """ nwbfile.add_ic_electrode(self.container) nwbfile.add_device(self.device) def getContainer(self, nwbfile): """ Return the test IntracellularElectrode from the given NWBFile """ return nwbfile.get_ic_electrode(self.container.name) class TestPatchClampSeries(AcquisitionH5IOMixin, TestCase): def setUpElectrode(self): """ Set up the test IntracellularElectrode """ self.device = Device(name='device_name') self.elec = IntracellularElectrode(name="elec0", slice='tissue slice', resistance='something measured in ohms', seal='sealing method', description='a fake electrode object', location='Springfield Elementary School', filtering='a meaningless free-form text field', initial_access_resistance='I guess this changes', device=self.device) def setUpContainer(self): """ Return the test PatchClampSeries to read/write """ self.setUpElectrode() return PatchClampSeries(name="pcs", data=[1, 2, 3, 4, 5], unit='A', starting_time=123.6, rate=10e3, electrode=self.elec, gain=0.126, stimulus_description="gotcha ya!", sweep_number=4711) def addContainer(self, nwbfile): """ Add the test PatchClampSeries as an acquisition and IntracellularElectrode and Device to the given NWBFile """ nwbfile.add_ic_electrode(self.elec) nwbfile.add_device(self.device) super().addContainer(nwbfile) class TestCurrentClampStimulusSeries(TestPatchClampSeries): def setUpContainer(self): """ Return the test CurrentClampStimulusSeries to read/write """ self.setUpElectrode() return CurrentClampStimulusSeries(name="ccss", data=[1, 2, 3, 4, 5], starting_time=123.6, rate=10e3, electrode=self.elec, gain=0.126) class TestVoltageClampStimulusSeries(TestPatchClampSeries): def setUpContainer(self): """ Return the test VoltageClampStimulusSeries to read/write """ self.setUpElectrode() return VoltageClampStimulusSeries(name="vcss", data=[1, 2, 3, 4, 5], starting_time=123.6, rate=10e3, electrode=self.elec, gain=0.126) class TestCurrentClampSeries(TestPatchClampSeries): def setUpContainer(self): """ Return the test CurrentClampSeries to read/write """ self.setUpElectrode() return CurrentClampSeries(name="ccs", data=[1, 2, 3, 4, 5], starting_time=123.6, rate=10e3, electrode=self.elec, gain=0.126, bias_current=1.2, bridge_balance=2.3, capacitance_compensation=3.45) class TestVoltageClampSeries(TestPatchClampSeries): def setUpContainer(self): """ Return the test VoltageClampSeries to read/write """ self.setUpElectrode() return VoltageClampSeries(name="vcs", data=[1, 2, 3, 4, 5], starting_time=123.6, rate=10e3, electrode=self.elec, gain=0.126, capacitance_fast=1.2, capacitance_slow=2.3, resistance_comp_bandwidth=3.45, resistance_comp_correction=4.5, resistance_comp_prediction=5.678, whole_cell_capacitance_comp=6.789, whole_cell_series_resistance_comp=0.7) class TestIZeroClampSeries(TestPatchClampSeries): def setUpContainer(self): """ Return the test IZeroClampSeries to read/write """ self.setUpElectrode() return IZeroClampSeries(name="izcs", data=[1, 2, 3, 4, 5], starting_time=123.6, rate=10e3, electrode=self.elec, gain=0.126) class TestSweepTableRoundTripEasy(NWBH5IOMixin, TestCase): def setUpContainer(self): """ Return the test SweepTable to read/write """ self.device = Device(name='device_name') self.elec = IntracellularElectrode(name="elec0", slice='tissue slice', resistance='something measured in ohms', seal='sealing method', description='a fake electrode object', location='Springfield Elementary School', filtering='a meaningless free-form text field', initial_access_resistance='I guess this changes', device=self.device) self.pcs = PatchClampSeries(name="pcs", data=[1, 2, 3, 4, 5], unit='A', starting_time=123.6, rate=10e3, electrode=self.elec, gain=0.126, stimulus_description="gotcha ya!", sweep_number=4711) return SweepTable(name='sweep_table') def addContainer(self, nwbfile): """ Add the test SweepTable, PatchClampSeries, IntracellularElectrode, and Device to the given NWBFile """ nwbfile.sweep_table = self.container nwbfile.add_device(self.device) nwbfile.add_ic_electrode(self.elec) nwbfile.add_acquisition(self.pcs) def getContainer(self, nwbfile): """ Return the test SweepTable from the given NWBFile """ return nwbfile.sweep_table def test_container(self): """ Test properties of the SweepTable read from file """ description = 'a file to test writing and reading a %s' % self.container_type identifier = 'TEST_%s' % self.container_type nwbfile = NWBFile(description, identifier, self.start_time, file_create_date=self.create_date) self.addContainer(nwbfile) sweep_table = self.getContainer(nwbfile) self.assertEqual(len(sweep_table['series'].data), 1) self.assertEqual(sweep_table.id[0], 0) self.assertEqual(sweep_table['sweep_number'].data[0], 4711) class TestSweepTableRoundTripComplicated(NWBH5IOMixin, TestCase): def setUpContainer(self): """ Return the test SweepTable to read/write """ self.device = Device(name='device_name') self.elec = IntracellularElectrode(name="elec0", slice='tissue slice', resistance='something measured in ohms', seal='sealing method', description='a fake electrode object', location='Springfield Elementary School', filtering='a meaningless free-form text field', initial_access_resistance='I guess this changes', device=self.device) self.pcs1 = PatchClampSeries(name="pcs1", data=[1, 2, 3, 4, 5], unit='A', starting_time=123.6, rate=10e3, electrode=self.elec, gain=0.126, stimulus_description="gotcha ya!", sweep_number=4711) self.pcs2a = PatchClampSeries(name="pcs2a", data=[1, 2, 3, 4, 5], unit='A', starting_time=123.6, rate=10e3, electrode=self.elec, gain=0.126, stimulus_description="gotcha ya!", sweep_number=4712) self.pcs2b = PatchClampSeries(name="pcs2b", data=[1, 2, 3, 4, 5], unit='A', starting_time=123.6, rate=10e3, electrode=self.elec, gain=0.126, stimulus_description="gotcha ya!", sweep_number=4712) return SweepTable(name='sweep_table') def addContainer(self, nwbfile): """ Add the test SweepTable, PatchClampSeries, IntracellularElectrode, and Device to the given NWBFile """ nwbfile.sweep_table = self.container nwbfile.add_device(self.device) nwbfile.add_ic_electrode(self.elec) nwbfile.add_acquisition(self.pcs1) nwbfile.add_stimulus_template(self.pcs2a) nwbfile.add_stimulus(self.pcs2b) def getContainer(self, nwbfile): """ Return the test SweepTable from the given NWBFile """ return nwbfile.sweep_table def test_container(self): """ Test properties of the SweepTable read from file """ description = 'a file to test writing and reading a %s' % self.container_type identifier = 'TEST_%s' % self.container_type nwbfile = NWBFile(description, identifier, self.start_time, file_create_date=self.create_date) self.addContainer(nwbfile) sweep_table = self.getContainer(nwbfile) self.assertEqual(len(sweep_table['series'].data), 3) self.assertEqual(sweep_table['sweep_number'].data[0], 4711) self.assertEqual(sweep_table['sweep_number'].data[1], 4712) self.assertEqual(sweep_table['sweep_number'].data[2], 4712) series = sweep_table.get_series(4711) self.assertEqual(len(series), 1) names = [elem.name for elem in series] self.assertEqual(names, ["pcs1"]) sweep_numbers = [elem.sweep_number for elem in series] self.assertEqual(sweep_numbers, [4711]) series = sweep_table.get_series(4712) self.assertEqual(len(series), 2) names = [elem.name for elem in series] self.assertEqual(names, ["pcs2a", "pcs2b"]) sweep_numbers = [elem.sweep_number for elem in series] self.assertEqual(sweep_numbers, [4712, 4712]) pynwb-1.2.1/tests/integration/hdf5/__init__.py0000644000655200065520000000000013612200244022644 0ustar circlecicircleci00000000000000pynwb-1.2.1/tests/integration/hdf5/test_modular_storage.py0000644000655200065520000001476313612200244025360 0ustar circlecicircleci00000000000000import os import gc from datetime import datetime from dateutil.tz import tzutc import numpy as np from hdmf.backends.hdf5 import HDF5IO from hdmf.backends.hdf5.h5_utils import H5DataIO from pynwb import get_manager, NWBFile, NWBHDF5IO, TimeSeries, validate as pynwb_validate from pynwb.testing import remove_test_file, TestCase class TestTimeSeriesModular(TestCase): def setUp(self): self.start_time = datetime(1971, 1, 1, 12, tzinfo=tzutc()) self.data = np.arange(2000).reshape((2, 1000)) self.timestamps = np.linspace(0, 1, 1000) self.container = TimeSeries( name='data_ts', unit='V', data=self.data, timestamps=self.timestamps ) self.data_filename = os.path.join(os.getcwd(), 'test_time_series_modular_data.nwb') self.link_filename = os.path.join(os.getcwd(), 'test_time_series_modular_link.nwb') self.read_container = None self.link_read_io = None self.data_read_io = None def tearDown(self): if self.read_container: self.read_container.data.file.close() self.read_container.timestamps.file.close() if self.link_read_io: self.link_read_io.close() if self.data_read_io: self.data_read_io.close() # necessary to remove all references to the file and garbage # collect on windows in order to be able to truncate/overwrite # the file later. see pynwb GH issue #975 if os.name == 'nt': gc.collect() remove_test_file(self.link_filename) remove_test_file(self.data_filename) def roundtripContainer(self): # create and write data file data_file = NWBFile( session_description='a test file', identifier='data_file', session_start_time=self.start_time ) data_file.add_acquisition(self.container) with HDF5IO(self.data_filename, 'w', manager=get_manager()) as data_write_io: data_write_io.write(data_file) # read data file with HDF5IO(self.data_filename, 'r', manager=get_manager()) as self.data_read_io: data_file_obt = self.data_read_io.read() # write "link file" with timeseries.data that is an external link to the timeseries in "data file" # also link timeseries.timestamps.data to the timeseries.timestamps in "data file" with HDF5IO(self.link_filename, 'w', manager=get_manager()) as link_write_io: link_file = NWBFile( session_description='a test file', identifier='link_file', session_start_time=self.start_time ) self.link_container = TimeSeries( name='test_mod_ts', unit='V', data=data_file_obt.get_acquisition('data_ts'), # test direct link timestamps=H5DataIO( data=data_file_obt.get_acquisition('data_ts').timestamps, link_data=True # test with setting link data ) ) link_file.add_acquisition(self.link_container) link_write_io.write(link_file) # note that self.link_container contains a link to a dataset that is now closed # read the link file self.link_read_io = HDF5IO(self.link_filename, 'r', manager=get_manager()) self.read_nwbfile = self.link_read_io.read() return self.getContainer(self.read_nwbfile) def test_roundtrip(self): self.read_container = self.roundtripContainer() # make sure we get a completely new object self.assertIsNotNone(str(self.container)) # added as a test to make sure printing works self.assertIsNotNone(str(self.link_container)) self.assertIsNotNone(str(self.read_container)) self.assertFalse(self.link_container.timestamps.valid) self.assertTrue(self.read_container.timestamps.id.valid) self.assertNotEqual(id(self.link_container), id(self.read_container)) self.assertIs(self.read_nwbfile.objects[self.link_container.object_id], self.read_container) self.assertContainerEqual(self.read_container, self.container, ignore_name=True, ignore_hdmf_attrs=True) self.assertEqual(self.read_container.object_id, self.link_container.object_id) self.validate() def test_link_root(self): # create and write data file data_file = NWBFile( session_description='a test file', identifier='data_file', session_start_time=self.start_time ) data_file.add_acquisition(self.container) with HDF5IO(self.data_filename, 'w', manager=get_manager()) as data_write_io: data_write_io.write(data_file) # read data file manager = get_manager() with HDF5IO(self.data_filename, 'r', manager=manager) as data_read_io: data_file_obt = data_read_io.read() link_file = NWBFile( session_description='a test file', identifier='link_file', session_start_time=self.start_time ) link_container = data_file_obt.acquisition[self.container.name] link_file.add_acquisition(link_container) self.assertIs(link_container.parent, data_file_obt) with HDF5IO(self.link_filename, 'w', manager=manager) as link_write_io: link_write_io.write(link_file) # read the link file, check container sources with HDF5IO(self.link_filename, 'r+', manager=get_manager()) as link_file_reader: read_nwbfile = link_file_reader.read() self.assertNotEqual(read_nwbfile.acquisition[self.container.name].container_source, read_nwbfile.container_source) self.assertEqual(read_nwbfile.acquisition[self.container.name].container_source, self.data_filename) self.assertEqual(read_nwbfile.container_source, self.link_filename) def validate(self): filenames = [self.data_filename, self.link_filename] for fn in filenames: if os.path.exists(fn): with NWBHDF5IO(fn, mode='r') as io: errors = pynwb_validate(io) if errors: for err in errors: raise Exception(err) def getContainer(self, nwbfile): return nwbfile.get_acquisition('test_mod_ts') pynwb-1.2.1/tests/integration/hdf5/test_nwbfile.py0000644000655200065520000005267113612200244023617 0ustar circlecicircleci00000000000000from datetime import datetime from dateutil.tz import tzlocal, tzutc import pandas as pd import numpy as np from hdmf.backends.hdf5 import HDF5IO from hdmf.common import DynamicTable from pynwb import NWBFile, TimeSeries, NWBHDF5IO, get_manager from pynwb.file import Subject from pynwb.epoch import TimeIntervals from pynwb.ecephys import ElectricalSeries from pynwb.testing import NWBH5IOMixin, TestCase, remove_test_file class TestNWBFileHDF5IO(TestCase): """ Test reading/writing an NWBFile using HDF5IO """ def setUp(self): """ Set up an NWBFile object with an acquisition TimeSeries, analysis TimeSeries, and a processing module """ self.start_time = datetime(1970, 1, 1, 12, tzinfo=tzutc()) self.ref_time = datetime(1979, 1, 1, 0, tzinfo=tzutc()) self.create_date = datetime(2017, 4, 15, 12, tzinfo=tzlocal()) self.manager = get_manager() self.filename = 'test_nwbfileio.h5' self.nwbfile = NWBFile('a test NWB File', 'TEST123', self.start_time, timestamps_reference_time=self.ref_time, file_create_date=self.create_date, experimenter='test experimenter', stimulus_notes='test stimulus notes', data_collection='test data collection notes', experiment_description='test experiment description', institution='nomad', lab='nolab', notes='nonotes', pharmacology='nopharmacology', protocol='noprotocol', related_publications='nopubs', session_id='007', slices='noslices', source_script='nosources', surgery='nosurgery', virus='novirus', source_script_file_name='nofilename') self.ts = TimeSeries('test_timeseries', list(range(100, 200, 10)), 'SIunit', timestamps=list(range(10)), resolution=0.1) self.nwbfile.add_acquisition(self.ts) self.ts2 = TimeSeries('test_timeseries2', list(range(200, 300, 10)), 'SIunit', timestamps=list(range(10)), resolution=0.1) self.nwbfile.add_analysis(self.ts2) self.mod = self.nwbfile.create_processing_module('test_module', 'a test module') self.ts3 = TimeSeries('test_timeseries2', list(range(100, 200, 10)), 'SIunit', timestamps=list(range(10)), resolution=0.1) self.mod.add(self.ts3) def tearDown(self): """ Delete the created test file """ remove_test_file(self.filename) def test_children(self): """ Test that the TimeSeries and processing module are children of their respective parents """ self.assertIn(self.ts, self.nwbfile.children) self.assertIn(self.ts2, self.nwbfile.children) self.assertIn(self.mod, self.nwbfile.children) self.assertIn(self.ts3, self.mod.children) def test_write(self): """ Test writing the NWBFile using HDF5IO """ hdf5io = HDF5IO(self.filename, manager=self.manager, mode='a') hdf5io.write(self.nwbfile) hdf5io.close() # TODO add some asserts def test_read(self): """ Test reading the NWBFile using HDF5IO """ hdf5io = HDF5IO(self.filename, manager=self.manager, mode='w') hdf5io.write(self.nwbfile) hdf5io.close() hdf5io = HDF5IO(self.filename, manager=self.manager, mode='r') container = hdf5io.read() self.assertIsInstance(container, NWBFile) self.assertEqual(len(container.acquisition), 1) self.assertEqual(len(container.analysis), 1) for v in container.acquisition.values(): self.assertIsInstance(v, TimeSeries) self.assertContainerEqual(container, self.nwbfile) hdf5io.close() class TestNWBFileIO(NWBH5IOMixin, TestCase): """ Test writing an NWBFile to disk and reading back the file """ # this uses methods tearDown, test_roundtrip, and validate from NWBH5IOMixin. the rest are overridden def setUp(self): super().setUp() self.start_time = datetime(1970, 1, 1, 12, tzinfo=tzutc()) self.ref_time = datetime(1979, 1, 1, 0, tzinfo=tzutc()) self.create_dates = [datetime(2017, 5, 1, 12, tzinfo=tzlocal()), datetime(2017, 5, 2, 13, 0, 0, 1, tzinfo=tzutc()), datetime(2017, 5, 2, 14, tzinfo=tzutc())] def setUpContainer(self): """ Return a placeholder NWBFile """ return NWBFile('placeholder', 'placeholder', datetime(1970, 1, 1, 12, tzinfo=tzutc())) def build_nwbfile(self): """ Create an NWB file """ self.container = NWBFile('a test session description for a test NWBFile', 'FILE123', self.start_time, file_create_date=self.create_dates, timestamps_reference_time=self.ref_time, experimenter='A test experimenter', lab='a test lab', institution='a test institution', experiment_description='a test experiment description', session_id='test1', notes='my notes', pharmacology='drugs', protocol='protocol', related_publications='my pubs', slices='my slices', surgery='surgery', virus='a virus', source_script='noscript', source_script_file_name='nofilename', stimulus_notes='test stimulus notes', data_collection='test data collection notes', keywords=('these', 'are', 'keywords')) def roundtripContainer(self, cache_spec=False): """ Build and write an NWBFile to disk, read the file, and return the NWBFile """ self.build_nwbfile() self.writer = NWBHDF5IO(self.filename, mode='w') self.writer.write(self.container, cache_spec=cache_spec) self.writer.close() self.reader = NWBHDF5IO(self.filename, mode='r') self.read_nwbfile = self.reader.read() return self.read_nwbfile def addContainer(self, nwbfile): """ No-op. roundtripContainer is overridden and no longer uses addContainer """ pass def getContainer(self, nwbfile): """ Get the NWBFile object from the given NWBFile """ return nwbfile class TestExperimentersConstructorRoundtrip(TestNWBFileIO): """ Test that a list of multiple experimenters in a constructor is written to and read from file """ def build_nwbfile(self): description = 'test nwbfile experimenter' identifier = 'TEST_experimenter' self.nwbfile = NWBFile(description, identifier, self.start_time, experimenter=('experimenter1', 'experimenter2')) class TestExperimentersSetterRoundtrip(TestNWBFileIO): """ Test that a list of multiple experimenters in a setter is written to and read from file """ def build_nwbfile(self): description = 'test nwbfile experimenter' identifier = 'TEST_experimenter' self.nwbfile = NWBFile(description, identifier, self.start_time) self.nwbfile.experimenter = ('experimenter1', 'experimenter2') class TestPublicationsConstructorRoundtrip(TestNWBFileIO): """ Test that a list of multiple publications in a constructor is written to and read from file """ def build_nwbfile(self): description = 'test nwbfile publications' identifier = 'TEST_publications' self.nwbfile = NWBFile(description, identifier, self.start_time, related_publications=('pub1', 'pub2')) class TestPublicationsSetterRoundtrip(TestNWBFileIO): """ Test that a list of multiple publications in a setter is written to and read from file """ def build_nwbfile(self): description = 'test nwbfile publications' identifier = 'TEST_publications' self.nwbfile = NWBFile(description, identifier, self.start_time) self.nwbfile.related_publications = ('pub1', 'pub2') class TestSubjectIO(NWBH5IOMixin, TestCase): def setUpContainer(self): """ Return the test Subject """ return Subject(age='12 mo', description='An unfortunate rat', genotype='WT', sex='M', species='Rattus norvegicus', subject_id='RAT123', weight='2 lbs', date_of_birth=datetime(1970, 1, 1, 12, tzinfo=tzutc())) def addContainer(self, nwbfile): """ Add the test Subject to the given NWBFile """ nwbfile.subject = self.container def getContainer(self, nwbfile): """ Return the test Subject from the given NWBFile """ return nwbfile.subject class TestEmptySubjectIO(TestSubjectIO): def setUpContainer(self): return Subject() class TestEpochsIO(NWBH5IOMixin, TestCase): def setUpContainer(self): """ Return placeholder epochs object. Tested epochs are added directly to the NWBFile in addContainer """ return TimeIntervals('epochs') def addContainer(self, nwbfile): """ Add the test epochs to the given NWBFile """ nwbfile.add_epoch_column( name='temperature', description='average temperture (c) during epoch' ) nwbfile.add_epoch( start_time=5.3, stop_time=6.1, timeseries=[], tags='ambient', temperature=26.4, ) # reset the thing self.container = nwbfile.epochs def getContainer(self, nwbfile): """ Return the test epochs from the given NWBFile """ return nwbfile.epochs class TestEpochsIODf(TestEpochsIO): def addContainer(self, nwbfile): """ Add the test epochs with TimeSeries objects to the given NWBFile """ tsa, tsb = [ TimeSeries(name='a', data=np.arange(11), unit='flubs', timestamps=np.linspace(0, 1, 11)), TimeSeries(name='b', data=np.arange(13), unit='flubs', timestamps=np.linspace(0.1, 5, 13)), ] nwbfile.add_acquisition(tsa) nwbfile.add_acquisition(tsb) nwbfile.epochs = TimeIntervals.from_dataframe( pd.DataFrame({ 'foo': [1, 2, 3, 4], 'bar': ['fish', 'fowl', 'dog', 'cat'], 'start_time': [0.2, 0.25, 0.30, 0.35], 'stop_time': [0.25, 0.30, 0.40, 0.45], 'timeseries': [[(2, 1, tsa)], [(3, 1, tsa)], [(3, 1, tsa)], [(4, 1, tsa)]], 'tags': [[''], [''], ['fizz', 'buzz'], ['qaz']] }), 'epochs', columns=[ {'name': 'foo', 'description': 'a column of integers'}, {'name': 'bar', 'description': 'a column of strings'}, ] ) # reset the thing self.container = nwbfile.epochs def test_df_comparison(self): """ Test that the epochs read from file converted to a data frame are the same as the data frame converted from the original epochs and the timeseries columns within them are the same """ self.read_container = self.roundtripContainer() df_obt = self.read_container.to_dataframe() tsa = self.read_nwbfile.get_acquisition('a') df_exp = pd.DataFrame({ 'foo': [1, 2, 3, 4], 'bar': ['fish', 'fowl', 'dog', 'cat'], 'start_time': [0.2, 0.25, 0.30, 0.35], 'stop_time': [0.25, 0.30, 0.40, 0.45], 'timeseries': [[(2, 1, tsa)], [(3, 1, tsa)], [(3, 1, tsa)], [(4, 1, tsa)]], 'tags': [[''], [''], ['fizz', 'buzz'], ['qaz']] }, index=pd.Index(np.arange(4), name='id') ) # pop the timeseries column out because ts_obt has rows of lists of tuples and ts_exp has rows of lists of lists ts_obt = df_obt.pop('timeseries') ts_exp = df_exp.pop('timeseries') pd.testing.assert_frame_equal(df_exp, df_obt, check_like=True, check_dtype=False) # check the timeseries columns match for ex, obt in zip(ts_exp, ts_obt): self.assertEqual(ex[0][0], obt[0][0]) self.assertEqual(ex[0][1], obt[0][1]) self.assertContainerEqual(ex[0][2], obt[0][2]) def test_df_comparison_no_ts(self): """ Test that the epochs read from file converted to a data frame are the same as the data frame converted from the original epochs without a timeseries column """ self.read_container = self.roundtripContainer() df_exp = pd.DataFrame({ 'foo': [1, 2, 3, 4], 'bar': ['fish', 'fowl', 'dog', 'cat'], 'start_time': [0.2, 0.25, 0.30, 0.35], 'stop_time': [0.25, 0.30, 0.40, 0.45], 'tags': [[''], [''], ['fizz', 'buzz'], ['qaz']] }, index=pd.Index(np.arange(4), name='id') ) df_obt = self.read_container.to_dataframe(exclude=set(['timeseries', 'timeseries_index'])) pd.testing.assert_frame_equal(df_exp, df_obt, check_like=True, check_dtype=False) class TestTrials(NWBH5IOMixin, TestCase): def setUpContainer(self): """ Return placeholder Table for trials. Tested trials are added directly to the NWBFile in addContainer """ return DynamicTable('trials', 'a placeholder table') # this will get ignored def addContainer(self, nwbfile): """ Add trials and trial columns to the given NWBFile """ nwbfile.add_trial_column('foo', 'an int column') nwbfile.add_trial_column('bar', 'a float column') nwbfile.add_trial_column('baz', 'a string column') nwbfile.add_trial_column('qux', 'a boolean column') nwbfile.add_trial(start_time=0., stop_time=1., foo=27, bar=28.0, baz="29", qux=True) nwbfile.add_trial(start_time=2., stop_time=3., foo=37, bar=38.0, baz="39", qux=False) self.container = nwbfile.trials # override self.container which has the placeholder def getContainer(self, nwbfile): """ Return the test trials table from the given NWBFile """ return nwbfile.trials class TestInvalidTimes(NWBH5IOMixin, TestCase): def setUpContainer(self): """ Return placeholder Table for trials. Tested invalid times are added directly to the NWBFile in addContainer """ return DynamicTable('invalid times', 'a placeholder table') def addContainer(self, nwbfile): """ Add invalid times and invalid times columns to the given NWBFile """ nwbfile.add_invalid_times_column('foo', 'an int column') nwbfile.add_invalid_times_column('bar', 'a float column') nwbfile.add_invalid_times_column('baz', 'a string column') nwbfile.add_invalid_times_column('qux', 'a boolean column') nwbfile.add_invalid_time_interval(start_time=0., stop_time=1., foo=27, bar=28.0, baz="29", qux=True) nwbfile.add_invalid_time_interval(start_time=2., stop_time=3., foo=37, bar=38.0, baz="39", qux=False) self.container = nwbfile.invalid_times # override self.container which has the placeholder def getContainer(self, nwbfile): """ Return the test invalid times table from the given NWBFile """ return nwbfile.invalid_times class TestUnits(NWBH5IOMixin, TestCase): def setUpContainer(self): """ Return placeholder table for Units. Tested units are added directly to the NWBFile in addContainer """ return DynamicTable('units', 'a placeholder table') def addContainer(self, nwbfile): """ Add units and unit columns to the given NWBFile """ nwbfile.add_unit_column('foo', 'an int column') nwbfile.add_unit_column('my_bool', 'a bool column') nwbfile.add_unit(foo=27, my_bool=True) nwbfile.add_unit(foo=37, my_bool=False) self.container = nwbfile.units # override self.container which has the placeholder def getContainer(self, nwbfile): """ Return the test units table from the given NWBFile """ return nwbfile.units class TestDynamicTableFromDataframeIO(NWBH5IOMixin, TestCase): def setUpContainer(self): return DynamicTable.from_dataframe(pd.DataFrame({ 'a': [[1, 2, 3], [1, 2, 3], [1, 2, 3]], 'b': ['4', '5', '6'] }), 'test_table') def addContainer(self, nwbfile): test_mod = nwbfile.create_processing_module('test', 'desc') test_mod.add(self.container) def getContainer(self, nwbfile): dyn_tab = nwbfile.processing['test'].data_interfaces['test_table'] return dyn_tab def test_to_dataframe(self): dyn_tab = self.roundtripContainer() dyn_tab.to_dataframe() # also test 2D column round-trip class TestElectrodes(NWBH5IOMixin, TestCase): def setUpContainer(self): """ Return placeholder table for electrodes. Tested electrodes are added directly to the NWBFile in addContainer """ return DynamicTable('electrodes', 'a placeholder table') def addContainer(self, nwbfile): """ Add electrodes and related objects to the given NWBFile """ self.dev1 = nwbfile.create_device('dev1') self.group = nwbfile.create_electrode_group('tetrode1', 'tetrode description', 'tetrode location', self.dev1) nwbfile.add_electrode(id=1, x=1.0, y=2.0, z=3.0, imp=-1.0, location='CA1', filtering='none', group=self.group, group_name='tetrode1') nwbfile.add_electrode(id=2, x=1.0, y=2.0, z=3.0, imp=-2.0, location='CA1', filtering='none', group=self.group, group_name='tetrode1') nwbfile.add_electrode(id=3, x=1.0, y=2.0, z=3.0, imp=-3.0, location='CA1', filtering='none', group=self.group, group_name='tetrode1') nwbfile.add_electrode(id=4, x=1.0, y=2.0, z=3.0, imp=-4.0, location='CA1', filtering='none', group=self.group, group_name='tetrode1') self.container = nwbfile.electrodes # override self.container which has the placeholder def getContainer(self, nwbfile): """ Return the test electrodes table from the given NWBFile """ return nwbfile.electrodes def test_roundtrip(self): super().test_roundtrip() # When comparing the pandas dataframes for the row we drop the 'group' column since the # ElectrodeGroup object after reading will naturally have a different address pd.testing.assert_frame_equal(self.read_container[0].drop('group', axis=1), self.container[0].drop('group', axis=1)) class TestElectrodesRegion(NWBH5IOMixin, TestCase): def setUpContainer(self): """ Return placeholder table for electrodes. Tested electrodes are added directly to the NWBFile in addContainer """ return DynamicTable('electrodes', 'a placeholder table') def addContainer(self, nwbfile): """ Add electrode table region and related objects to the given NWBFile """ self.dev1 = nwbfile.create_device('dev1') self.group = nwbfile.create_electrode_group('tetrode1', 'tetrode description', 'tetrode location', self.dev1) nwbfile.add_electrode(id=1, x=1.0, y=2.0, z=3.0, imp=-1.0, location='CA1', filtering='none', group=self.group, group_name='tetrode1') nwbfile.add_electrode(id=2, x=1.0, y=2.0, z=3.0, imp=-2.0, location='CA1', filtering='none', group=self.group, group_name='tetrode1') nwbfile.add_electrode(id=3, x=1.0, y=2.0, z=3.0, imp=-3.0, location='CA1', filtering='none', group=self.group, group_name='tetrode1') nwbfile.add_electrode(id=4, x=1.0, y=2.0, z=3.0, imp=-4.0, location='CA1', filtering='none', group=self.group, group_name='tetrode1') region = nwbfile.create_electrode_table_region( region=tuple([1, 2, 3]), name='electrodes', description='desc' ) nwbfile.add_acquisition(ElectricalSeries( name='test_data', data=np.arange(10), timestamps=np.arange(10), electrodes=region )) self.container = region # override self.container which has the placeholder def getContainer(self, nwbfile): """ Return the test electrodes table from the given NWBFile """ self.table = nwbfile.electrodes return nwbfile.get_acquisition('test_data').electrodes def test_roundtrip(self): super().test_roundtrip() for ii, item in enumerate(self.read_container): pd.testing.assert_frame_equal(self.table[ii+1], item) pynwb-1.2.1/tests/integration/hdf5/test_scratch.py0000644000655200065520000001123613612200244023610 0ustar circlecicircleci00000000000000import pandas as pd import numpy as np from numpy.testing import assert_array_equal from pynwb import NWBFile, NWBHDF5IO, TimeSeries from pynwb.core import ScratchData from pynwb.testing import NWBH5IOMixin, TestCase class TestScratchDataIO(NWBH5IOMixin, TestCase): def setUpContainer(self): """ Return the test ScratchData to read/write """ return ScratchData('foo', [1, 2, 3, 4], notes='test scratch') def addContainer(self, nwbfile): """ Add the test ScratchData to the given NWBFile """ nwbfile.add_scratch(self.container) def getContainer(self, nwbfile): """ Return the test ScratchData from the given NWBFile """ return nwbfile.get_scratch('foo', convert=False) def roundtrip_scratch(self, data, case, **kwargs): self.filename = 'test_scratch_%s.nwb' % case description = 'a file to test writing and reading a scratch data of type %s' % case identifier = 'TEST_scratch_%s' % case nwbfile = NWBFile(description, identifier, self.start_time, file_create_date=self.create_date) nwbfile.add_scratch(data, name='foo', notes='test scratch', **kwargs) self.writer = NWBHDF5IO(self.filename, mode='w') self.writer.write(nwbfile) self.writer.close() self.reader = NWBHDF5IO(self.filename, mode='r') self.read_nwbfile = self.reader.read() return self.read_nwbfile.get_scratch('foo') def test_scratch_convert_list(self): data = [1, 2, 3, 4] ret = self.roundtrip_scratch(data, 'list') assert_array_equal(data, ret) self.validate() def test_scratch_convert_ndarray(self): data = np.array([1, 2, 3, 4]) ret = self.roundtrip_scratch(data, 'ndarray') assert_array_equal(data, ret) self.validate() def test_scratch_convert_DataFrame(self): data = pd.DataFrame(data={'col1': [1, 2, 3, 4], 'col2': ['a', 'b', 'c', 'd']}) warn_msg = 'Notes argument is ignored when adding a pandas DataFrame to scratch' with self.assertWarnsWith(UserWarning, warn_msg): ret = self.roundtrip_scratch(data, 'DataFrame') assert_array_equal(data.values, ret.values) assert_array_equal(data.index.values, ret.index.values) self.validate() def test_scratch_convert_DataFrame_table_desc(self): """Test round trip convert of DataFrame with a table description""" data = pd.DataFrame(data={'col1': [1, 2, 3, 4], 'col2': ['a', 'b', 'c', 'd']}) case = 'dataframe_desc' self.filename = 'test_scratch_%s.nwb' % case description = 'a file to test writing and reading a scratch data of type %s' % case identifier = 'TEST_scratch_%s' % case nwbfile = NWBFile(description, identifier, self.start_time, file_create_date=self.create_date) nwbfile.add_scratch(data, name='foo', table_description='my_table') self.writer = NWBHDF5IO(self.filename, mode='w') self.writer.write(nwbfile) self.writer.close() self.reader = NWBHDF5IO(self.filename, mode='r') self.read_nwbfile = self.reader.read() ret = self.read_nwbfile.get_scratch('foo', convert=False) ret_df = ret.to_dataframe() self.assertEqual(ret.description, 'my_table') assert_array_equal(data.values, ret_df.values) assert_array_equal(data.index.values, ret_df.index.values) self.validate() def _test_scratch_container(self, validate=True, **kwargs): data = TimeSeries('test_ts', [1, 2, 3, 4, 5], unit='unit', timestamps=[1.1, 1.2, 1.3, 1.4, 1.5]) nwbfile = NWBFile('test', 'test', self.start_time, file_create_date=self.create_date) nwbfile.add_scratch(data, **kwargs) self.writer = NWBHDF5IO(self.filename, mode='w') self.writer.write(nwbfile) self.writer.close() self.reader = NWBHDF5IO(self.filename, mode='r') self.read_nwbfile = self.reader.read() ret = self.read_nwbfile.get_scratch('test_ts') self.assertContainerEqual(data, ret) if validate: self.validate() def test_scratch_container(self): self._test_scratch_container(validate=True) def test_scratch_container_with_name(self): warn_msg = 'Name argument is ignored when adding an NWBContainer to scratch' with self.assertWarnsWith(UserWarning, warn_msg): self._test_scratch_container(validate=False, name='foo') def test_scratch_container_with_notes(self): warn_msg = 'Notes argument is ignored when adding an NWBContainer to scratch' with self.assertWarnsWith(UserWarning, warn_msg): self._test_scratch_container(validate=False, notes='test scratch') pynwb-1.2.1/tests/integration/hdf5/test_ophys.py0000644000655200065520000002075413612200244023330 0ustar circlecicircleci00000000000000from copy import deepcopy from abc import ABCMeta from pynwb.ophys import ( ImagingPlane, OpticalChannel, PlaneSegmentation, ImageSegmentation, TwoPhotonSeries, RoiResponseSeries ) from pynwb.image import ImageSeries from pynwb.device import Device from pynwb.testing import NWBH5IOMixin, AcquisitionH5IOMixin, TestCase class TestImagingPlaneIO(NWBH5IOMixin, TestCase): def setUpContainer(self): """ Return the test ImagingPlane to read/write """ self.device = Device(name='dev1') self.optical_channel = OpticalChannel('optchan1', 'a fake OpticalChannel', 500.) return ImagingPlane('imgpln1', self.optical_channel, 'a fake ImagingPlane', self.device, 600., 300., 'GFP', 'somewhere in the brain', reference_frame='unknonwn') def addContainer(self, nwbfile): """ Add the test ImagingPlane and Device to the given NWBFile """ nwbfile.add_device(self.device) nwbfile.add_imaging_plane(self.container) def getContainer(self, nwbfile): """ Return the test ImagingPlane from the given NWBFile """ return nwbfile.get_imaging_plane(self.container.name) class TestTwoPhotonSeriesIO(AcquisitionH5IOMixin, TestCase): def make_imaging_plane(self): """ Make an ImagingPlane and related objects """ self.device = Device(name='dev1') self.optical_channel = OpticalChannel('optchan1', 'a fake OpticalChannel', 500.) self.imaging_plane = ImagingPlane('imgpln1', self.optical_channel, 'a fake ImagingPlane', self.device, 600., 300., 'GFP', 'somewhere in the brain', reference_frame='unknown') def setUpContainer(self): """ Return the test TwoPhotonSeries to read/write """ self.make_imaging_plane() data = [[[1., 1.] * 2] * 2] timestamps = list(map(lambda x: x/10, range(10))) fov = [2.0, 2.0, 5.0] ret = TwoPhotonSeries('test_2ps', self.imaging_plane, data, 'image_unit', 'raw', fov, 1.7, 3.4, timestamps=timestamps, dimension=[2]) return ret def addContainer(self, nwbfile): """ Add the test TwoPhotonSeries as an acquisition and add Device and ImagingPlane to the given NWBFile """ nwbfile.add_device(self.device) nwbfile.add_imaging_plane(self.imaging_plane) nwbfile.add_acquisition(self.container) class TestPlaneSegmentationIO(NWBH5IOMixin, TestCase): @staticmethod def buildPlaneSegmentation(self): """ Return an PlaneSegmentation and set related objects """ w, h = 5, 5 img_mask = [[[1.0 for x in range(w)] for y in range(h)], [[2.0 for x in range(w)] for y in range(h)]] pix_mask = [(1, 2, 1.0), (3, 4, 1.0), (5, 6, 1.0), (7, 8, 2.0), (9, 10, 2.)] ts = [0.0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9] self.image_series = ImageSeries(name='test_iS', dimension=[2], external_file=['images.tiff'], starting_frame=[1, 2, 3], format='tiff', timestamps=ts) self.device = Device(name='dev1') self.optical_channel = OpticalChannel('test_optical_channel', 'optical channel description', 500.) self.imaging_plane = ImagingPlane('imgpln1', self.optical_channel, 'a fake ImagingPlane', self.device, 600., 200., 'GFP', 'somewhere in the brain', (((1., 2., 3.), (4., 5., 6.)),), 2., 'a unit', reference_frame='unknown') self.img_mask = deepcopy(img_mask) self.pix_mask = deepcopy(pix_mask) self.pxmsk_index = [3, 5] pS = PlaneSegmentation('plane segmentation description', self.imaging_plane, 'test_plane_seg_name', self.image_series) pS.add_roi(pixel_mask=pix_mask[0:3], image_mask=img_mask[0]) pS.add_roi(pixel_mask=pix_mask[3:5], image_mask=img_mask[1]) return pS def setUpContainer(self): """ Return the test PlaneSegmentation to read/write """ return self.buildPlaneSegmentation(self) def addContainer(self, nwbfile): """ Add an ImageSegmentation in processing with a PlaneSegmentation and add Device and ImagingPlane to the given NWBFile """ nwbfile.add_device(self.device) nwbfile.add_imaging_plane(self.imaging_plane) img_seg = ImageSegmentation() img_seg.add_plane_segmentation(self.container) self.mod = nwbfile.create_processing_module('plane_seg_test_module', 'a plain module for testing') self.mod.add(img_seg) def getContainer(self, nwbfile): """ Return the test PlaneSegmentation from the given NWBFile """ mod = nwbfile.get_processing_module(self.mod.name) img_seg = mod.get('ImageSegmentation') return img_seg.get_plane_segmentation(self.container.name) class MaskIO(TestPlaneSegmentationIO, metaclass=ABCMeta): def buildPlaneSegmentationNoRois(self): """ Return an PlaneSegmentation and set related objects """ ts = [0.0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9] self.image_series = ImageSeries(name='test_iS', dimension=[2], external_file=['images.tiff'], starting_frame=[1, 2, 3], format='tiff', timestamps=ts) self.device = Device(name='dev1') self.optical_channel = OpticalChannel('test_optical_channel', 'optical channel description', 500.) self.imaging_plane = ImagingPlane('test_imaging_plane', self.optical_channel, 'imaging plane description', self.device, 600., 300., 'GFP', 'somewhere in the brain', (((1., 2., 3.), (4., 5., 6.)),), 4.0, 'manifold unit', 'A frame to refer to') return PlaneSegmentation('description', self.imaging_plane, 'test_plane_seg_name', self.image_series) class TestPixelMaskIO(MaskIO): def setUpContainer(self): """ Return the test PlaneSegmentation with pixel mask ROIs to read/write """ pix_mask = [(1, 2, 1.0), (3, 4, 1.0), (5, 6, 1.0), (7, 8, 2.0), (9, 10, 2.)] pS = self.buildPlaneSegmentationNoRois() pS.add_roi(pixel_mask=pix_mask[0:3]) pS.add_roi(pixel_mask=pix_mask[3:5]) return pS class TestImageMaskIO(MaskIO): def setUpContainer(self): """ Return the test PlaneSegmentation with voxel mask ROIs to read/write """ w, h = 5, 5 img_mask = [[[1.0 for x in range(w)] for y in range(h)], [[2.0 for x in range(w)] for y in range(h)]] pS = self.buildPlaneSegmentationNoRois() pS.add_roi(image_mask=img_mask[0]) pS.add_roi(image_mask=img_mask[1]) return pS class TestRoiResponseSeriesIO(AcquisitionH5IOMixin, TestCase): def setUpContainer(self): """ Return the test RoiResponseSeries to read/write """ self.plane_segmentation = TestPlaneSegmentationIO.buildPlaneSegmentation(self) self.rt_region = self.plane_segmentation.create_roi_table_region('the first of two ROIs', region=[0]) data = [0., 1., 2., 3., 4., 5., 6., 7., 8., 9.] timestamps = [0.0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9] return RoiResponseSeries('test_roi_response_series', data, self.rt_region, unit='lumens', timestamps=timestamps) def addContainer(self, nwbfile): """ Add the test RoiResponseSeries as an acquisition and add Device, ImagingPlane, ImageSegmentation, and PlaneSegmentation to the given NWBFile """ nwbfile.add_device(self.device) nwbfile.add_imaging_plane(self.imaging_plane) img_seg = ImageSegmentation() img_seg.add_plane_segmentation(self.plane_segmentation) mod = nwbfile.create_processing_module('plane_seg_test_module', 'a plain module for testing') mod.add(img_seg) super().addContainer(nwbfile) pynwb-1.2.1/tests/integration/hdf5/test_ogen.py0000644000655200065520000000310613612200244023106 0ustar circlecicircleci00000000000000from pynwb.ogen import OptogeneticSeries, OptogeneticStimulusSite from pynwb.device import Device from pynwb.testing import NWBH5IOMixin, AcquisitionH5IOMixin, TestCase class TestOptogeneticStimulusSiteIO(NWBH5IOMixin, TestCase): def setUpContainer(self): """ Return the test OptogeneticStimulusSite to read/write """ self.device = Device(name='dev1') return OptogeneticStimulusSite('stim_site', self.device, 'my stim site', 300., 'in the brain') def addContainer(self, nwbfile): """ Add the test OptogeneticStimulusSite and Device to the given NWBFile """ nwbfile.add_device(self.device) nwbfile.add_ogen_site(self.container) def getContainer(self, nwbfile): """ Return the test OptogeneticStimulusSite from the given NWBFile """ return nwbfile.get_ogen_site(self.container.name) class TestOptogeneticSeriesIO(AcquisitionH5IOMixin, TestCase): def setUpContainer(self): """ Return the test OptogeneticSeries to read/write """ self.device = Device(name='dev1') self.ogen_stim_site = OptogeneticStimulusSite('stim_site', self.device, 'my stim site', 300., 'in the brain') return OptogeneticSeries('stim_series', [1., 2., 3.], self.ogen_stim_site, rate=100.) def addContainer(self, nwbfile): """ Add the test OptogeneticSeries as an acquisition and add Device and OptogeneticStimulusSite to the given NWBFile """ nwbfile.add_device(self.device) nwbfile.add_ogen_site(self.ogen_stim_site) nwbfile.add_acquisition(self.container) pynwb-1.2.1/tests/integration/hdf5/test_base.py0000644000655200065520000000262113612200244023071 0ustar circlecicircleci00000000000000import numpy as np from datetime import datetime from dateutil.tz import tzlocal from pynwb import TimeSeries, NWBFile, NWBHDF5IO from pynwb.testing import AcquisitionH5IOMixin, TestCase class TestTimeSeriesIO(AcquisitionH5IOMixin, TestCase): def setUpContainer(self): """ Return the test TimeSeries to read/write """ return TimeSeries('test_timeseries', list(range(100, 200, 10)), 'SIunit', timestamps=list(range(10)), resolution=0.1) class TestTimeSeriesLinking(TestCase): def test_timestamps_linking(self): ''' Test that timestamps get linked to in TimeSeries ''' tsa = TimeSeries(name='a', data=np.linspace(0, 1, 1000), timestamps=np.arange(1000), unit='m') tsb = TimeSeries(name='b', data=np.linspace(0, 1, 1000), timestamps=tsa, unit='m') nwbfile = NWBFile(identifier='foo', session_start_time=datetime(2017, 5, 1, 12, 0, 0, tzinfo=tzlocal()), session_description='bar') nwbfile.add_acquisition(tsa) nwbfile.add_acquisition(tsb) filename = 'test_timestamps_linking.nwb' with NWBHDF5IO(filename, 'w') as io: io.write(nwbfile) with NWBHDF5IO(filename, 'r') as io: nwbfile = io.read() tsa = nwbfile.acquisition['a'] tsb = nwbfile.acquisition['b'] self.assertIs(tsa.timestamps, tsb.timestamps) pynwb-1.2.1/tests/integration/hdf5/test_misc.py0000644000655200065520000001151113612200244023110 0ustar circlecicircleci00000000000000import numpy as np from hdmf.common import DynamicTable, VectorData from pynwb import TimeSeries from pynwb.misc import Units, DecompositionSeries from pynwb.testing import NWBH5IOMixin, AcquisitionH5IOMixin, TestCase class TestUnitsIO(AcquisitionH5IOMixin, TestCase): """ Test adding Units into acquisition and accessing Units after read """ def setUpContainer(self): """ Return the test Units to read/write """ ut = Units(name='UnitsTest', description='a simple table for testing Units') ut.add_unit(spike_times=[0, 1, 2], obs_intervals=[[0, 1], [2, 3]]) ut.add_unit(spike_times=[3, 4, 5], obs_intervals=[[2, 5], [6, 7]]) return ut def test_get_spike_times(self): """ Test whether the Units spike times read from file are what was written """ ut = self.roundtripContainer() received = ut.get_unit_spike_times(0) self.assertTrue(np.array_equal(received, [0, 1, 2])) received = ut.get_unit_spike_times(1) self.assertTrue(np.array_equal(received, [3, 4, 5])) self.assertTrue(np.array_equal(ut['spike_times'][:], [[0, 1, 2], [3, 4, 5]])) def test_get_obs_intervals(self): """ Test whether the Units observation intervals read from file are what was written """ ut = self.roundtripContainer() received = ut.get_unit_obs_intervals(0) self.assertTrue(np.array_equal(received, [[0, 1], [2, 3]])) received = ut.get_unit_obs_intervals(1) self.assertTrue(np.array_equal(received, [[2, 5], [6, 7]])) self.assertTrue(np.array_equal(ut['obs_intervals'][:], [[[0, 1], [2, 3]], [[2, 5], [6, 7]]])) class TestUnitsFileIO(NWBH5IOMixin, TestCase): def setUpContainer(self): """ Return placeholder Units object. Tested units are added directly to the NWBFile in addContainer """ return Units('placeholder') # this will get ignored def addContainer(self, nwbfile): """ Add units to the given NWBFile """ device = nwbfile.create_device(name='trodes_rig123') electrode_name = 'tetrode1' description = "an example tetrode" location = "somewhere in the hippocampus" electrode_group = nwbfile.create_electrode_group(electrode_name, description=description, location=location, device=device) for idx in [1, 2, 3, 4]: nwbfile.add_electrode(id=idx, x=1.0, y=2.0, z=3.0, imp=float(-idx), location='CA1', filtering='none', group=electrode_group) nwbfile.add_unit(id=1, electrodes=[1], electrode_group=electrode_group) nwbfile.add_unit(id=2, electrodes=[1], electrode_group=electrode_group) self.container = nwbfile.units # override self.container which has the placeholder def getContainer(self, nwbfile): """ Return the test Units from the given NWBFile """ return nwbfile.units def test_to_dataframe(self): units = self.roundtripContainer() units.to_dataframe() class TestDecompositionSeriesIO(NWBH5IOMixin, TestCase): def setUpContainer(self): """ Return the test DecompositionSeries to read/write """ self.timeseries = TimeSeries(name='dummy timeseries', description='desc', data=np.ones((3, 3)), unit='flibs', timestamps=np.ones((3,))) bands = DynamicTable(name='bands', description='band info for LFPSpectralAnalysis', columns=[ VectorData(name='band_name', description='name of bands', data=['alpha', 'beta', 'gamma']), VectorData(name='band_limits', description='low and high cutoffs in Hz', data=np.ones((3, 2))) ]) spec_anal = DecompositionSeries(name='LFPSpectralAnalysis', description='my description', data=np.ones((3, 3, 3)), timestamps=np.ones((3,)), source_timeseries=self.timeseries, metric='amplitude', bands=bands) return spec_anal def addContainer(self, nwbfile): """ Add the test DecompositionSeries to the given NWBFile in a processing module """ nwbfile.add_acquisition(self.timeseries) prcs_mod = nwbfile.create_processing_module('test_mod', 'test_mod') prcs_mod.add(self.container) def getContainer(self, nwbfile): """ Return the test DecompositionSeries from the given NWBFile """ return nwbfile.processing['test_mod']['LFPSpectralAnalysis'] pynwb-1.2.1/tests/integration/hdf5/test_image.py0000644000655200065520000000212113612200244023234 0ustar circlecicircleci00000000000000import numpy as np from pynwb.image import OpticalSeries from pynwb.testing import NWBH5IOMixin, TestCase class TestOpticalSeriesIO(NWBH5IOMixin, TestCase): def setUpContainer(self): """ Return a test OpticalSeries to read/write """ self.optical_series = OpticalSeries(name='OpticalSeries', distance=8., field_of_view=(4., 5.), orientation='upper left', data=np.ones((10, 3, 3)), unit='m', format='raw', timestamps=np.arange(10)) return self.optical_series def addContainer(self, nwbfile): """ Add the test OpticalSeries to the given NWBFile """ nwbfile.add_stimulus(self.optical_series) def getContainer(self, nwbfile): """ Return the test OpticalSeries from the given NWBFile """ return nwbfile.stimulus['OpticalSeries'] pynwb-1.2.1/tests/integration/test_io.py0000644000655200065520000004465213612200244021752 0ustar circlecicircleci00000000000000from datetime import datetime from dateutil.tz import tzlocal, tzutc import numpy as np from h5py import File from pynwb import NWBFile, TimeSeries, get_manager, NWBHDF5IO, validate from hdmf.backends.io import UnsupportedOperation from hdmf.backends.hdf5 import HDF5IO, H5DataIO from hdmf.data_utils import DataChunkIterator from hdmf.build import GroupBuilder, DatasetBuilder from hdmf.spec import NamespaceCatalog from pynwb.spec import NWBGroupSpec, NWBDatasetSpec, NWBNamespace from pynwb.ecephys import ElectricalSeries, LFP from pynwb.testing import remove_test_file, TestCase class TestHDF5Writer(TestCase): _required_tests = ('test_nwbio', 'test_write_clobber', 'test_write_cache_spec', 'test_write_no_cache_spec') @property def required_tests(self): return self._required_tests def setUp(self): self.manager = get_manager() self.path = "test_pynwb_io_hdf5.nwb" self.start_time = datetime(1970, 1, 1, 12, tzinfo=tzutc()) self.create_date = datetime(2017, 4, 15, 12, tzinfo=tzlocal()) self.container = NWBFile('a test NWB File', 'TEST123', self.start_time, file_create_date=self.create_date) ts = TimeSeries('test_timeseries', list(range(100, 200, 10)), 'SIunit', timestamps=list(range(10)), resolution=0.1) self.container.add_acquisition(ts) ts_builder = GroupBuilder('test_timeseries', attributes={'neurodata_type': 'TimeSeries'}, datasets={'data': DatasetBuilder('data', list(range(100, 200, 10)), attributes={'unit': 'SIunit', 'conversion': 1.0, 'resolution': 0.1}), 'timestamps': DatasetBuilder('timestamps', list(range(10)), attributes={'unit': 'seconds', 'interval': 1})}) self.builder = GroupBuilder( 'root', groups={'acquisition': GroupBuilder('acquisition', groups={'test_timeseries': ts_builder}), 'analysis': GroupBuilder('analysis'), 'general': GroupBuilder('general'), 'processing': GroupBuilder('processing'), 'stimulus': GroupBuilder( 'stimulus', groups={'presentation': GroupBuilder('presentation'), 'templates': GroupBuilder('templates')})}, datasets={'file_create_date': DatasetBuilder('file_create_date', [self.create_date.isoformat()]), 'identifier': DatasetBuilder('identifier', 'TEST123'), 'session_description': DatasetBuilder('session_description', 'a test NWB File'), 'nwb_version': DatasetBuilder('nwb_version', '1.0.6'), 'session_start_time': DatasetBuilder('session_start_time', self.start_time.isoformat())}, attributes={'neurodata_type': 'NWBFile'}) def tearDown(self): remove_test_file(self.path) def test_nwbio(self): with HDF5IO(self.path, manager=self.manager, mode='a') as io: io.write(self.container) with File(self.path, 'r') as f: self.assertIn('acquisition', f) self.assertIn('analysis', f) self.assertIn('general', f) self.assertIn('processing', f) self.assertIn('file_create_date', f) self.assertIn('identifier', f) self.assertIn('session_description', f) self.assertIn('session_start_time', f) acq = f.get('acquisition') self.assertIn('test_timeseries', acq) def test_write_clobber(self): with HDF5IO(self.path, manager=self.manager, mode='a') as io: io.write(self.container) with self.assertRaisesWith(UnsupportedOperation, "Unable to open file %s in 'w-' mode. File already exists." % self.path): with HDF5IO(self.path, manager=self.manager, mode='w-') as io: pass def test_write_cache_spec(self): ''' Round-trip test for writing spec and reading it back in ''' with HDF5IO(self.path, manager=self.manager, mode="a") as io: io.write(self.container) with File(self.path, 'r') as f: self.assertIn('specifications', f) ns_catalog = NamespaceCatalog(NWBGroupSpec, NWBDatasetSpec, NWBNamespace) HDF5IO.load_namespaces(ns_catalog, self.path) original_ns = self.manager.namespace_catalog.get_namespace('core') cached_ns = ns_catalog.get_namespace('core') self.maxDiff = None for key in ('author', 'contact', 'doc', 'full_name', 'name'): with self.subTest(namespace_field=key): self.assertEqual(original_ns[key], cached_ns[key]) for dt in original_ns.get_registered_types(): with self.subTest(neurodata_type=dt): original_spec = original_ns.get_spec(dt) cached_spec = cached_ns.get_spec(dt) with self.subTest(test='data_type spec read back in'): self.assertIsNotNone(cached_spec) with self.subTest(test='cached spec preserved original spec'): self.assertDictEqual(original_spec, cached_spec) def test_write_no_cache_spec(self): ''' Round-trip test for not writing spec ''' with HDF5IO(self.path, manager=self.manager, mode="a") as io: io.write(self.container, cache_spec=False) with File(self.path, 'r') as f: self.assertNotIn('specifications', f) class TestHDF5WriterWithInjectedFile(TestCase): _required_tests = ('test_nwbio', 'test_write_clobber', 'test_write_cache_spec') @property def required_tests(self): return self._required_tests def setUp(self): self.manager = get_manager() self.path = "test_pynwb_io_hdf5_injected.nwb" self.start_time = datetime(1970, 1, 1, 12, tzinfo=tzutc()) self.create_date = datetime(2017, 4, 15, 12, tzinfo=tzlocal()) self.container = NWBFile('a test NWB File', 'TEST123', self.start_time, file_create_date=self.create_date) ts = TimeSeries('test_timeseries', list(range(100, 200, 10)), 'SIunit', timestamps=list(range(10)), resolution=0.1) self.container.add_acquisition(ts) ts_builder = GroupBuilder('test_timeseries', attributes={'neurodata_type': 'TimeSeries'}, datasets={'data': DatasetBuilder('data', list(range(100, 200, 10)), attributes={'unit': 'SIunit', 'conversion': 1.0, 'resolution': 0.1}), 'timestamps': DatasetBuilder('timestamps', list(range(10)), attributes={'unit': 'seconds', 'interval': 1})}) self.builder = GroupBuilder( 'root', groups={'acquisition': GroupBuilder('acquisition', groups={'test_timeseries': ts_builder}), 'analysis': GroupBuilder('analysis'), 'general': GroupBuilder('general'), 'processing': GroupBuilder('processing'), 'stimulus': GroupBuilder( 'stimulus', groups={'presentation': GroupBuilder('presentation'), 'templates': GroupBuilder('templates')})}, datasets={'file_create_date': DatasetBuilder('file_create_date', [self.create_date.isoformat()]), 'identifier': DatasetBuilder('identifier', 'TEST123'), 'session_description': DatasetBuilder('session_description', 'a test NWB File'), 'nwb_version': DatasetBuilder('nwb_version', '1.0.6'), 'session_start_time': DatasetBuilder('session_start_time', self.start_time.isoformat())}, attributes={'neurodata_type': 'NWBFile'}) def tearDown(self): remove_test_file(self.path) def test_nwbio(self): with File(self.path, 'w') as fil: with HDF5IO(self.path, manager=self.manager, file=fil, mode='a') as io: io.write(self.container) with File(self.path, 'r') as f: self.assertIn('acquisition', f) self.assertIn('analysis', f) self.assertIn('general', f) self.assertIn('processing', f) self.assertIn('file_create_date', f) self.assertIn('identifier', f) self.assertIn('session_description', f) self.assertIn('session_start_time', f) acq = f.get('acquisition') self.assertIn('test_timeseries', acq) def test_write_clobber(self): with File(self.path, 'w') as fil: with HDF5IO(self.path, manager=self.manager, file=fil, mode='a') as io: io.write(self.container) with self.assertRaisesWith(UnsupportedOperation, "Unable to open file %s in 'w-' mode. File already exists." % self.path): with HDF5IO(self.path, manager=self.manager, mode='w-') as io: pass def test_write_cache_spec(self): ''' Round-trip test for writing spec and reading it back in ''' with File(self.path, 'w') as fil: with HDF5IO(self.path, manager=self.manager, file=fil, mode='a') as io: io.write(self.container) with File(self.path, 'r') as f: self.assertIn('specifications', f) ns_catalog = NamespaceCatalog(NWBGroupSpec, NWBDatasetSpec, NWBNamespace) HDF5IO.load_namespaces(ns_catalog, self.path) original_ns = self.manager.namespace_catalog.get_namespace('core') cached_ns = ns_catalog.get_namespace('core') self.maxDiff = None for key in ('author', 'contact', 'doc', 'full_name', 'name'): with self.subTest(namespace_field=key): self.assertEqual(original_ns[key], cached_ns[key]) for dt in original_ns.get_registered_types(): with self.subTest(neurodata_type=dt): original_spec = original_ns.get_spec(dt) cached_spec = cached_ns.get_spec(dt) with self.subTest(test='data_type spec read back in'): self.assertIsNotNone(cached_spec) with self.subTest(test='cached spec preserved original spec'): self.assertDictEqual(original_spec, cached_spec) class TestAppend(TestCase): def setUp(self): self.nwbfile = NWBFile(session_description='hi', identifier='hi', session_start_time=datetime(1970, 1, 1, 12, tzinfo=tzutc())) self.path = "test_append.nwb" def tearDown(self): remove_test_file(self.path) def test_append(self): proc_mod = self.nwbfile.create_processing_module(name='test_proc_mod', description='') proc_inter = LFP(name='test_proc_dset') proc_mod.add(proc_inter) device = self.nwbfile.create_device(name='test_device') e_group = self.nwbfile.create_electrode_group( name='test_electrode_group', description='', location='', device=device ) self.nwbfile.add_electrode(x=0.0, y=0.0, z=0.0, imp=np.nan, location='', filtering='', group=e_group) electrodes = self.nwbfile.create_electrode_table_region(region=[0], description='') e_series = ElectricalSeries( name='test_es', electrodes=electrodes, data=np.ones(shape=(100,)), rate=10000.0, ) proc_inter.add_electrical_series(e_series) with NWBHDF5IO(self.path, mode='w') as io: io.write(self.nwbfile, cache_spec=False) with NWBHDF5IO(self.path, mode='a') as io: nwb = io.read() link_electrodes = nwb.processing['test_proc_mod']['LFP'].electrical_series['test_es'].electrodes ts2 = ElectricalSeries(name='timeseries2', data=[4., 5., 6.], rate=1.0, electrodes=link_electrodes) nwb.add_acquisition(ts2) io.write(nwb) # also attempt to write same spec again self.assertIs(nwb.processing['test_proc_mod']['LFP'].electrical_series['test_es'].electrodes, nwb.acquisition['timeseries2'].electrodes) with NWBHDF5IO(self.path, mode='r') as io: nwb = io.read() np.testing.assert_equal(nwb.acquisition['timeseries2'].data[:], ts2.data) self.assertIs(nwb.processing['test_proc_mod']['LFP'].electrical_series['test_es'].electrodes, nwb.acquisition['timeseries2'].electrodes) errors = validate(io) for e in errors: print('ERROR', e) class TestH5DataIO(TestCase): """ Test that H5DataIO functions correctly on round trip with the HDF5IO backend """ def setUp(self): self.nwbfile = NWBFile('a', 'b', datetime(1970, 1, 1, 12, tzinfo=tzutc())) self.path = "test_pynwb_io_hdf5_h5dataIO.h5" def tearDown(self): remove_test_file(self.path) def test_gzip_timestamps(self): ts = TimeSeries('ts_name', [1, 2, 3], 'A', timestamps=H5DataIO(np.array([1., 2., 3.]), compression='gzip')) self.nwbfile.add_acquisition(ts) with NWBHDF5IO(self.path, 'w') as io: io.write(self.nwbfile, cache_spec=False) # confirm that the dataset was indeed compressed with File(self.path, 'r') as f: self.assertEqual(f['/acquisition/ts_name/timestamps'].compression, 'gzip') def test_write_dataset_custom_compress(self): a = H5DataIO(np.arange(30).reshape(5, 2, 3), compression='gzip', compression_opts=5, shuffle=True, fletcher32=True) ts = TimeSeries('ts_name', a, 'A', timestamps=np.arange(5)) self.nwbfile.add_acquisition(ts) with NWBHDF5IO(self.path, 'w') as io: io.write(self.nwbfile, cache_spec=False) with File(self.path, 'r') as f: dset = f['/acquisition/ts_name/data'] self.assertTrue(np.all(dset[:] == a.data)) self.assertEqual(dset.compression, 'gzip') self.assertEqual(dset.compression_opts, 5) self.assertEqual(dset.shuffle, True) self.assertEqual(dset.fletcher32, True) def test_write_dataset_custom_chunks(self): a = H5DataIO(np.arange(30).reshape(5, 2, 3), chunks=(1, 1, 3)) ts = TimeSeries('ts_name', a, 'A', timestamps=np.arange(5)) self.nwbfile.add_acquisition(ts) with NWBHDF5IO(self.path, 'w') as io: io.write(self.nwbfile, cache_spec=False) with File(self.path, 'r') as f: dset = f['/acquisition/ts_name/data'] self.assertTrue(np.all(dset[:] == a.data)) self.assertEqual(dset.chunks, (1, 1, 3)) def test_write_dataset_custom_fillvalue(self): a = H5DataIO(np.arange(20).reshape(5, 4), fillvalue=-1) ts = TimeSeries('ts_name', a, 'A', timestamps=np.arange(5)) self.nwbfile.add_acquisition(ts) with NWBHDF5IO(self.path, 'w') as io: io.write(self.nwbfile, cache_spec=False) with File(self.path, 'r') as f: dset = f['/acquisition/ts_name/data'] self.assertTrue(np.all(dset[:] == a.data)) self.assertEqual(dset.fillvalue, -1) def test_write_dataset_datachunkiterator_data_and_time(self): a = np.arange(30).reshape(5, 2, 3) aiter = iter(a) daiter = DataChunkIterator.from_iterable(aiter, buffer_size=2) tstamps = np.arange(5) tsiter = DataChunkIterator.from_iterable(tstamps) ts = TimeSeries('ts_name', daiter, 'A', timestamps=tsiter) self.nwbfile.add_acquisition(ts) with NWBHDF5IO(self.path, 'w') as io: io.write(self.nwbfile, cache_spec=False) with File(self.path, 'r') as f: dset = f['/acquisition/ts_name/data'] self.assertListEqual(dset[:].tolist(), a.tolist()) def test_write_dataset_datachunkiterator_data_only(self): a = np.arange(30).reshape(5, 2, 3) aiter = iter(a) daiter = DataChunkIterator.from_iterable(aiter, buffer_size=2) tstamps = np.arange(5) ts = TimeSeries('ts_name', daiter, 'A', timestamps=tstamps) self.nwbfile.add_acquisition(ts) with NWBHDF5IO(self.path, 'w') as io: io.write(self.nwbfile, cache_spec=False) with File(self.path, 'r') as f: dset = f['/acquisition/ts_name/data'] self.assertListEqual(dset[:].tolist(), a.tolist()) def test_write_dataset_datachunkiterator_with_compression(self): a = np.arange(30).reshape(5, 2, 3) aiter = iter(a) daiter = DataChunkIterator.from_iterable(aiter, buffer_size=2) wrapped_daiter = H5DataIO(data=daiter, compression='gzip', compression_opts=5, shuffle=True, fletcher32=True) ts = TimeSeries('ts_name', wrapped_daiter, 'A', timestamps=np.arange(5)) self.nwbfile.add_acquisition(ts) with NWBHDF5IO(self.path, 'w') as io: io.write(self.nwbfile, cache_spec=False) with File(self.path, 'r') as f: dset = f['/acquisition/ts_name/data'] self.assertEqual(dset.shape, a.shape) self.assertListEqual(dset[:].tolist(), a.tolist()) self.assertEqual(dset.compression, 'gzip') self.assertEqual(dset.compression_opts, 5) self.assertEqual(dset.shuffle, True) self.assertEqual(dset.fletcher32, True) pynwb-1.2.1/license.txt0000644000655200065520000000455013612200244016421 0ustar circlecicircleci00000000000000“pynwb” Copyright (c) 2017-2020, The Regents of the University of California, through Lawrence Berkeley National Laboratory (subject to receipt of any required approvals from the U.S. Dept. of Energy). All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: (1) Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. (2) Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. (3) Neither the name of the University of California, Lawrence Berkeley National Laboratory, U.S. Dept. of Energy nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. You are under no obligation whatsoever to provide any bug fixes, patches, or upgrades to the features, functionality or performance of the source code ("Enhancements") to anyone; however, if you choose to make your Enhancements available either publicly, or directly to Lawrence Berkeley National Laboratory, without imposing a separate written license agreement for such Enhancements, then you hereby grant the following license: a non-exclusive, royalty-free perpetual license to install, use, modify, prepare derivative works, incorporate into other computer software, distribute, and sublicense such enhancements or derivative works thereof, in binary and source code form.