Tools for Organizing and Displaying Reports

register_check(importance: Importance, neurodata_type: object, nwb_schema_version_lt: str | None = None, nwb_schema_version_gt: str | None = None) Callable

Wrap a check function with this decorator to add it to the check registry and automatically parse some output.

Parameters:
  • importance (Importance) –

    Importance has three levels:
    CRITICAL
    • potentially incorrect data

    BEST_PRACTICE_VIOLATION
    • very suboptimal data representation

    BEST_PRACTICE_SUGGESTION
    • improvable data representation

  • neurodata_type – The most generic HDMF/PyNWB class the check function applies to. Should generally match the type annotation of the check. If this check is intended to apply to any general NWBFile object, set neurodata_type to None.

  • nwb_schema_version_lt (str, optional) – Only run this check on NWB files with schema version less than this value. Useful for checks that only apply to older schema versions.

  • nwb_schema_version_gt (str, optional) – Only run this check on NWB files with schema version greater than this value. Useful for checks that only apply to newer schema versions.

class Importance(*values)

Bases: Enum

A definition of the valid importance levels for a given check function.

class Severity(*values)

Bases: Enum

A definition of the valid severity levels for the output from a given check function.

Strictly for internal development that improves report organization; users should never directly see these values.

class InspectorMessage(message: str, importance: Importance = Importance.BEST_PRACTICE_SUGGESTION, severity: Severity = Severity.LOW, check_function_name: str | None = None, object_type: str | None = None, object_name: str | None = None, location: str | None = None, file_path: str | None = None)

Bases: object

The primary output to be returned by every check function.

Parameters:
  • message (str) – A message that informs the user of the violation.

  • severity (Severity, optional) – If a check of non-CRITICAL importance has some basis of comparison, such as magnitude of affected data, then the developer of the check may set the severity as Severity.HIGH or Severity.LOW by calling from nwbinspector.register_checks import Severity. A good example is comparing if h5py.Dataset compression has been enabled on smaller vs. larger objects (see nwbinspector/checks/nwb_containers.py for details).

    The user will never directly see this severity, but it will prioritize the order in which check results are presented by the NWBInspector.

  • importance (Importance) – The Importance level specified by the decorator of the check function.

  • check_function_name (str) – The name of the check function the decorator was applied to.

  • object_type (str) – The specific class of the instantiated object being inspected.

  • object_name (str) – The name of the instantiated object being inspected.

  • location (str) – The location relative to the root of the NWBFile where the inspected object may be found.

  • file_path (str) – The path of the NWBFile this message pertains to Relative to the path called from inspect_nwb, inspect_all, or the path specified at the command line.

__repr__()

Representation for InspectorMessage objects according to black format.

validate_config(config: dict) None

Validate an instance of configuration against the official schema.

load_config(filepath_or_keyword: str | Path) dict

Load a config dictionary either via keyword search of the internal configs, or an explicit filepath.

Currently supported keywords are:
  • ‘dandi’

    For all DANDI archive related practices, including validation and upload.

configure_checks(checks: list | None = None, config: dict | None = None, ignore: list[str] | None = None, select: list[str] | None = None, importance_threshold: Importance = Importance.BEST_PRACTICE_SUGGESTION) list

Filter a list of check functions (the entire base registry by default) according to the configuration.

Parameters:
  • checks (list of check functions, optional) – If None, defaults to all registered checks.

  • config (dict) – Dictionary valid against our JSON configuration schema. Can specify a mapping of importance levels and list of check functions whose importance you wish to change. Typically loaded via json.load from a valid .json file

  • ignore (list, optional) – Names of functions to skip.

  • select (list, optional) – If loading all registered checks, this can be shorthand for selecting only a handful of them.

  • importance_threshold (string, optional) – Ignores all tests with an post-configuration assigned importance below this threshold. Importance has three levels:

    CRITICAL
    • potentially incorrect data

    BEST_PRACTICE_VIOLATION
    • very suboptimal data representation

    BEST_PRACTICE_SUGGESTION
    • improvable data representation

    The default is the lowest level, BEST_PRACTICE_SUGGESTION.

class InspectorOutputJSONEncoder(*, skipkeys=False, ensure_ascii=True, check_circular=True, allow_nan=True, sort_keys=False, indent=None, separators=None, default=None)

Bases: JSONEncoder

Custom JSONEncoder for the NWBInspector.

Constructor for JSONEncoder, with sensible defaults.

If skipkeys is false, then it is a TypeError to attempt encoding of keys that are not str, int, float, bool or None. If skipkeys is True, such items are simply skipped.

If ensure_ascii is true, the output is guaranteed to be str objects with all incoming non-ASCII and non-printable characters escaped. If ensure_ascii is false, the output can contain non-ASCII and non-printable characters.

If check_circular is true, then lists, dicts, and custom encoded objects will be checked for circular references during encoding to prevent an infinite recursion (which would cause an RecursionError). Otherwise, no such check takes place.

If allow_nan is true, then NaN, Infinity, and -Infinity will be encoded as such. This behavior is not JSON specification compliant, but is consistent with most JavaScript based encoders and decoders. Otherwise, it will be a ValueError to encode such floats.

If sort_keys is true, then the output of dictionaries will be sorted by key; this is useful for regression tests to ensure that JSON serializations can be compared on a day-to-day basis.

If indent is a non-negative integer, then JSON array elements and object members will be pretty-printed with that indent level. An indent level of 0 will only insert newlines. None is the most compact representation.

If specified, separators should be an (item_separator, key_separator) tuple. The default is (’, ‘, ‘: ‘) if indent is None and (‘,’, ‘: ‘) otherwise. To get the most compact JSON representation, you should specify (‘,’, ‘:’) to eliminate whitespace.

If specified, default is a function that gets called for objects that can’t otherwise be serialized. It should return a JSON encodable version of the object or raise a TypeError.

default(o: object) Any

Implement this method in a subclass such that it returns a serializable object for o, or calls the base implementation (to raise a TypeError).

For example, to support arbitrary iterators, you could implement default like this:

def default(self, o):
    try:
        iterable = iter(o)
    except TypeError:
        pass
    else:
        return list(iterable)
    # Let the base class default method raise the TypeError
    return super().default(o)
inspect_dandiset(*, dandiset_id: str, dandiset_version: str | Literal['draft'] | None = None, config: str | Path | dict | Literal['dandi'] | None = None, checks: list | None = None, ignore: list[str] | None = None, select: list[str] | None = None, importance_threshold: str | Importance = Importance.BEST_PRACTICE_SUGGESTION, skip_validate: bool = False, show_progress_bar: bool = True, client: dandi.dandiapi.DandiAPIClient | None = None) Iterable[InspectorMessage | None]

Inspect a Dandiset for common issues.

Parameters:
  • dandiset_id (six-digit string, “draft”, or None) – The six-digit ID of the Dandiset to inspect.

  • dandiset_version (string) – The specific published version of the Dandiset to inspect. If None, the latest version is used. If there are no published versions, then ‘draft’ is used instead.

  • config (file path, dictionary, or “dandi”, default: “dandi”) – If a file path, loads the dictionary configuration from the file. If a dictionary, it must be valid against the configuration schema. If “dandi”, uses the requirements for DANDI validation.

  • checks (list, optional) – list of checks to run

  • ignore (list, optional) – Names of functions to skip.

  • select (list, optional) – Names of functions to pick out of available checks.

  • importance_threshold (string or Importance, optional) – Ignores tests with an assigned importance below this threshold. Importance has three levels:

    CRITICAL
    • potentially incorrect data

    BEST_PRACTICE_VIOLATION
    • very suboptimal data representation

    BEST_PRACTICE_SUGGESTION
    • improvable data representation

    The default is the lowest level, BEST_PRACTICE_SUGGESTION.

  • skip_validate (bool, default: False) – Skip the PyNWB validation step. This may be desired for older NWBFiles (< schema version v2.10).

  • show_progress_bar (bool, optional) – Whether to display a progress bar while scanning the assets on the Dandiset.

  • client (dandi.dandiapi.DandiAPIClient) – The client object can be passed to avoid re-instantiation over an iteration.

inspect_dandi_file_path(*, dandi_file_path: str, dandiset_id: str, dandiset_version: str | Literal['draft'] | None = None, config: str | Path | dict | Literal['dandi'] | None = 'dandi', checks: list | None = None, ignore: list[str] | None = None, select: list[str] | None = None, importance_threshold: str | Importance = Importance.BEST_PRACTICE_SUGGESTION, skip_validate: bool = False, client: dandi.dandiapi.DandiAPIClient | None = None) Iterable[InspectorMessage | None]

Inspect a Dandifile for common issues.

Parameters:
  • dandi_file_path (string) – The path to the Dandifile as seen on the archive; e.g., ‘sub-123_ses-456+ecephys.nwb’.

  • dandiset_id (six-digit string, “draft”, or None) – The six-digit ID of the Dandiset.

  • dandiset_version (string) – The specific published version of the Dandiset to inspect. If None, the latest version is used. If there are no published versions, then ‘draft’ is used instead.

  • config (file path, dictionary, “dandi”, or None, default: “dandi”) – If a file path, loads the dictionary configuration from the file. If a dictionary, it must be valid against the configuration schema. If “dandi”, uses the requirements for DANDI validation.

  • checks (list, optional) – list of checks to run

  • ignore (list, optional) – Names of functions to skip.

  • select (list, optional) – Names of functions to pick out of available checks.

  • importance_threshold (string or Importance, optional) – Ignores tests with an assigned importance below this threshold. Importance has three levels:

    CRITICAL
    • potentially incorrect data

    BEST_PRACTICE_VIOLATION
    • very suboptimal data representation

    BEST_PRACTICE_SUGGESTION
    • improvable data representation

    The default is the lowest level, BEST_PRACTICE_SUGGESTION.

  • skip_validate (bool, default: False) – Skip the PyNWB validation step. This may be desired for older NWBFiles (< schema version v2.10).

  • client (dandi.dandiapi.DandiAPIClient) – The client object can be passed to avoid re-instantiation over an iteration.

inspect_url(*, url: str, config: str | Path | dict | Literal['dandi'] | None = 'dandi', checks: list | None = None, ignore: list[str] | None = None, select: list[str] | None = None, importance_threshold: str | Importance = Importance.BEST_PRACTICE_SUGGESTION, skip_validate: bool = False) Iterable[InspectorMessage | None]

Inspect an explicit S3 URL.

Parameters:
  • url (string) – A URL referring to the cloud location of an NWB file. Commonly used with DANDI, where the URL has a form similar to: https://dandiarchive.s3.amazonaws.com/blobs/636/57e/63657e32-ad33-4625-b664-31699b5bf664

    Note: this must be the https URL, not the ‘s3://’ form.

  • config (file path, dictionary, “dandi”, or None, default: “dandi”) – If a file path, loads the dictionary configuration from the file. If a dictionary, it must be valid against the configuration schema. If “dandi”, uses the requirements for DANDI validation.

  • checks (list, optional) – list of checks to run

  • ignore (list, optional) – Names of functions to skip.

  • select (list, optional) – Names of functions to pick out of available checks.

  • importance_threshold (string or Importance, optional) – Ignores tests with an assigned importance below this threshold. Importance has three levels:

    CRITICAL
    • potentially incorrect data

    BEST_PRACTICE_VIOLATION
    • very suboptimal data representation

    BEST_PRACTICE_SUGGESTION
    • improvable data representation

    The default is the lowest level, BEST_PRACTICE_SUGGESTION.

  • skip_validate (bool, default: False) – Whether to skip the PyNWB validation step.

inspect_all(path: PathType, config: dict | None = None, ignore: list[str] | None = None, select: list[str] | None = None, importance_threshold: str | Importance = Importance.BEST_PRACTICE_SUGGESTION, n_jobs: int = 1, skip_validate: bool = False, progress_bar: bool = True, progress_bar_class: Type[tqdm] = <class 'tqdm.std.tqdm'>, progress_bar_options: dict | None = None, stream: bool = False, version_id: str | None = None, modules: list[str] | None = None) Iterable[InspectorMessage | None]

Inspect a local NWBFile or folder of NWBFiles and return suggestions for improvements according to best practices.

Parameters:
  • path (PathType) – File path to an NWBFile, folder path to iterate over recursively and scan all NWBFiles present, or a six-digit identifier of the DANDISet.

  • config (dict, optional) – If a dictionary, it must be valid against our JSON configuration schema. Can specify a mapping of importance levels and list of check functions whose importance you wish to change. Typically loaded via json.load from a valid .json file

  • ignore (list of strings, optional) – Names of functions to skip.

  • select (list of strings, optional) – Names of functions to pick out of available checks.

  • importance_threshold (string or Importance, optional) – Ignores tests with an assigned importance below this threshold. Importance has three levels:

    CRITICAL
    • potentially incorrect data

    BEST_PRACTICE_VIOLATION
    • very suboptimal data representation

    BEST_PRACTICE_SUGGESTION
    • improvable data representation

    The default is the lowest level, BEST_PRACTICE_SUGGESTION.

  • n_jobs (int) – Number of jobs to use in parallel. Set to -1 to use all available resources. This may also be a negative integer x from -2 to -(number_of_cpus - 1) which acts like negative slicing by using all available CPUs minus x. Set to 1 (also the default) to disable.

  • skip_validate (bool, optional) – Skip the PyNWB validation step. The default is False, which is recommended.

  • progress_bar (bool, optional) – Display a progress bar while scanning NWBFiles. Defaults to True.

  • progress_bar_class (type of tqdm.tqdm, optional) – The specific child class of tqdm.tqdm to use to make progress bars. Defaults to tqdm.tqdm, the most generic parent.

  • progress_bar_options (dict, optional) – Dictionary of keyword arguments to pass directly to the progress_bar_class.

  • modules (list of strings, optional) – List of external module names to load; examples would be namespace extensions. These modules may also contain their own custom checks for their extensions.

inspect_nwbfile(nwbfile_path: str | Path, driver: str | None = None, skip_validate: bool = False, max_retries: int | None = None, checks: list | None = None, config: dict | None = None, ignore: list[str] | None = None, select: list[str] | None = None, importance_threshold: str | Importance = Importance.BEST_PRACTICE_SUGGESTION) Iterable[InspectorMessage | None]

Open an NWB file, inspect the contents, and return suggestions for improvements according to best practices.

Parameters:
  • nwbfile_path (FilePathType) – Path to the NWB file on disk or on S3.

  • skip_validate (bool) – Skip the PyNWB validation step. The default is False, which is recommended.

  • checks (list, optional) – List of checks to run.

  • config (dict) – Dictionary valid against our JSON configuration schema. Can specify a mapping of importance levels and list of check functions whose importance you wish to change. Typically loaded via json.load from a valid .json file.

  • ignore (list, optional) – Names of functions to skip.

  • select (list, optional) – Names of functions to pick out of available checks.

  • importance_threshold (string or Importance, optional) – Ignores tests with an assigned importance below this threshold. Importance has three levels:

    CRITICAL
    • potentially incorrect data

    BEST_PRACTICE_VIOLATION
    • very suboptimal data representation

    BEST_PRACTICE_SUGGESTION
    • improvable data representation

    The default is the lowest level, BEST_PRACTICE_SUGGESTION.

inspect_nwbfile_object(nwbfile_object: NWBFile, checks: list | None = None, config: dict | None = None, ignore: list[str] | None = None, select: list[str] | None = None, importance_threshold: str | Importance = Importance.BEST_PRACTICE_SUGGESTION) Iterable[InspectorMessage | None]

Inspect an in-memory NWBFile object and return suggestions for improvements according to best practices.

Parameters:
  • nwbfile_object (NWBFile) – An in-memory NWBFile object.

  • checks (list, optional) – list of checks to run

  • config (dict, optional) – Dictionary valid against our JSON configuration schema. Can specify a mapping of importance levels and list of check functions whose importance you wish to change. Typically loaded via json.load from a valid .json file

  • ignore (list, optional) – Names of functions to skip.

  • select (list, optional) – Names of functions to pick out of available checks.

  • importance_threshold (string or Importance, optional) – Ignores tests with an assigned importance below this threshold. Importance has three levels:

    CRITICAL
    • potentially incorrect data

    BEST_PRACTICE_VIOLATION
    • very suboptimal data representation

    BEST_PRACTICE_SUGGESTION
    • improvable data representation

    The default is the lowest level, BEST_PRACTICE_SUGGESTION.

run_checks(nwbfile: NWBFile, checks: list, progress_bar_class: Type[tqdm] | None = None, progress_bar_options: dict | None = None, nwb_schema_version: Version | None = None) Iterable[InspectorMessage | None]

Run checks on an open NWBFile object.

Parameters:
  • nwbfile (pynwb.NWBFile) – The in-memory pynwb.NWBFile object to run the checks on.

  • checks (list of check functions) – The list of check functions that will be run on the in-memory pynwb.NWBFile object.

  • progress_bar_class (type of tqdm.tqdm, optional) – The specific child class of tqdm.tqdm to use to make progress bars. Defaults to not displaying progress per set of checks over an individual file.

  • progress_bar_options (dict, optional) – Dictionary of keyword arguments to pass directly to the progress_bar_class.

  • nwb_schema_version (packaging.version.Version, optional) – The NWB schema version of the file being inspected. If not provided, will be read from nwbfile.read_io.nwb_version if available. This arg is mostly used for tests. Usually it is best to leave as None.

Yields:

results (a generator of InspectorMessage objects) – A generator that returns a message on each iteration, if any are triggered by downstream conditions. Otherwise, has length zero (if cast as list), or raises StopIteration (if explicitly calling next).

format_messages(messages: list[InspectorMessage | None], levels: list[str] | None = None, reverse: list[bool] | None = None, detailed: bool = False, nfiles_detected: int | None = None) list[str]

Print InspectorMessages in order specified by the organization structure.

print_to_console(formatted_messages: list[str]) None

Print report file contents to console.

save_report(report_file_path: str | Path, formatted_messages: list[str], overwrite: bool = False) None

Write the list of organized check results to a nicely formatted text file.

class MessageFormatter(messages: list[InspectorMessage | None], levels: list[str], reverse: list[bool] | None = None, detailed: bool = False, formatter_options: FormatterOptions | None = None, nfiles_detected: int | None = None)

Bases: object

For full customization of all format parameters, use this class instead of the ‘format_messages’ function.

_add_subsection(organized_messages: dict, levels: list[str], level_counter: list[int]) None

Recursive helper for display_messages.

format_messages() list[str]

Deploy recursive addition of sections, terminating with message display.

class FormatterOptions(indent_size: int = 2, indent: str | None = None, section_headers: tuple[str, ...] = ('=', '-', '~'))

Bases: object

Class structure for defining all free attributes for the design of a report format.

Class that defines all the format parameters used by the generic MessageFormatter.

Parameters:
  • indent_size (int, optional) – Defines the spacing between numerical sectioning and section name or message. Defaults to 2 spaces.

  • indent (str, optional) – Defines the specific indentation to inject between numerical sectioning and section name or message. Overrides indent_size. Defaults to “ “ * indent_size.

  • section_headers (tuple of strings) – List of characters that will be injected under the display of each new section of the report. If levels is longer than this list, the last item will be repeated over the remaining levels. If levels is shorter than this list, only the first len(levels) of items will be used. Defaults to the .rst style for three subsections: [“=”, “-”, “~”]

organize_messages(messages: list[InspectorMessage | None], levels: list[str], reverse: list[bool] | None = None) dict

General function for organizing list of InspectorMessages.

Returns a nested dictionary organized according to the order of the ‘levels’ argument.

Parameters:
  • messages (list of InspectorMessages)

  • levels (list of strings) – Each string in this list must correspond onto an attribute of the InspectorMessage class, excluding the ‘message’ text and ‘object_name’ (this will be coupled to the ‘object_type’).

  • reverse (list of bool, optional) – If provided, this should be a list of booleans that correspond to the ‘levels’ argument. If True, the values will be sorted in reverse order.

Internally used tools specifically for rendering more human-readable output from collected check results.

_sort_unique_values(unique_values: list, reverse: bool = False) list

Technically, the ‘set’ method applies basic sorting to the unique contents, but natsort is more general.

organize_messages(messages: list[InspectorMessage | None], levels: list[str], reverse: list[bool] | None = None) dict

General function for organizing list of InspectorMessages.

Returns a nested dictionary organized according to the order of the ‘levels’ argument.

Parameters:
  • messages (list of InspectorMessages)

  • levels (list of strings) – Each string in this list must correspond onto an attribute of the InspectorMessage class, excluding the ‘message’ text and ‘object_name’ (this will be coupled to the ‘object_type’).

  • reverse (list of bool, optional) – If provided, this should be a list of booleans that correspond to the ‘levels’ argument. If True, the values will be sorted in reverse order.

Internally used tools specifically for rendering more human-readable output from collected check results.

class InspectorOutputJSONEncoder(*, skipkeys=False, ensure_ascii=True, check_circular=True, allow_nan=True, sort_keys=False, indent=None, separators=None, default=None)

Bases: JSONEncoder

Custom JSONEncoder for the NWBInspector.

Constructor for JSONEncoder, with sensible defaults.

If skipkeys is false, then it is a TypeError to attempt encoding of keys that are not str, int, float, bool or None. If skipkeys is True, such items are simply skipped.

If ensure_ascii is true, the output is guaranteed to be str objects with all incoming non-ASCII and non-printable characters escaped. If ensure_ascii is false, the output can contain non-ASCII and non-printable characters.

If check_circular is true, then lists, dicts, and custom encoded objects will be checked for circular references during encoding to prevent an infinite recursion (which would cause an RecursionError). Otherwise, no such check takes place.

If allow_nan is true, then NaN, Infinity, and -Infinity will be encoded as such. This behavior is not JSON specification compliant, but is consistent with most JavaScript based encoders and decoders. Otherwise, it will be a ValueError to encode such floats.

If sort_keys is true, then the output of dictionaries will be sorted by key; this is useful for regression tests to ensure that JSON serializations can be compared on a day-to-day basis.

If indent is a non-negative integer, then JSON array elements and object members will be pretty-printed with that indent level. An indent level of 0 will only insert newlines. None is the most compact representation.

If specified, separators should be an (item_separator, key_separator) tuple. The default is (’, ‘, ‘: ‘) if indent is None and (‘,’, ‘: ‘) otherwise. To get the most compact JSON representation, you should specify (‘,’, ‘:’) to eliminate whitespace.

If specified, default is a function that gets called for objects that can’t otherwise be serialized. It should return a JSON encodable version of the object or raise a TypeError.

default(o: object) Any

Implement this method in a subclass such that it returns a serializable object for o, or calls the base implementation (to raise a TypeError).

For example, to support arbitrary iterators, you could implement default like this:

def default(self, o):
    try:
        iterable = iter(o)
    except TypeError:
        pass
    else:
        return list(iterable)
    # Let the base class default method raise the TypeError
    return super().default(o)
_get_report_header() dict[str, str]

Grab basic information from system at time of report generation.

class FormatterOptions(indent_size: int = 2, indent: str | None = None, section_headers: tuple[str, ...] = ('=', '-', '~'))

Bases: object

Class structure for defining all free attributes for the design of a report format.

Class that defines all the format parameters used by the generic MessageFormatter.

Parameters:
  • indent_size (int, optional) – Defines the spacing between numerical sectioning and section name or message. Defaults to 2 spaces.

  • indent (str, optional) – Defines the specific indentation to inject between numerical sectioning and section name or message. Overrides indent_size. Defaults to “ “ * indent_size.

  • section_headers (tuple of strings) – List of characters that will be injected under the display of each new section of the report. If levels is longer than this list, the last item will be repeated over the remaining levels. If levels is shorter than this list, only the first len(levels) of items will be used. Defaults to the .rst style for three subsections: [“=”, “-”, “~”]

class MessageFormatter(messages: list[InspectorMessage | None], levels: list[str], reverse: list[bool] | None = None, detailed: bool = False, formatter_options: FormatterOptions | None = None, nfiles_detected: int | None = None)

Bases: object

For full customization of all format parameters, use this class instead of the ‘format_messages’ function.

_add_subsection(organized_messages: dict, levels: list[str], level_counter: list[int]) None

Recursive helper for display_messages.

format_messages() list[str]

Deploy recursive addition of sections, terminating with message display.

format_messages(messages: list[InspectorMessage | None], levels: list[str] | None = None, reverse: list[bool] | None = None, detailed: bool = False, nfiles_detected: int | None = None) list[str]

Print InspectorMessages in order specified by the organization structure.

print_to_console(formatted_messages: list[str]) None

Print report file contents to console.

save_report(report_file_path: str | Path, formatted_messages: list[str], overwrite: bool = False) None

Write the list of organized check results to a nicely formatted text file.