Check Functions

NWBFile Metadata

Check functions that examine general NWBFile metadata.

check_session_start_time_old_date(nwbfile: NWBFile) InspectorMessage | None

Check if the session_start_time was set to an appropriate value.

Best Practice: Global Date and Time Reference

check_session_start_time_future_date(nwbfile: NWBFile) InspectorMessage | None

Check if the session_start_time was set to an appropriate value.

Best Practice: Global Date and Time Reference

check_experimenter_exists(nwbfile: NWBFile) InspectorMessage | None

Check if an experimenter has been added for the session.

Best Practice: Experimenter

check_experimenter_form(nwbfile: NWBFile) Iterable[InspectorMessage] | None

Check the text form of each experimenter to see if it matches the DANDI regex pattern.

Best Practice: Experimenter

check_experiment_description(nwbfile: NWBFile) InspectorMessage | None

Check if a description has been added for the session.

Best Practice: Experiment Description

check_institution(nwbfile: NWBFile) InspectorMessage | None

Check if a description has been added for the session.

Best Practice: Institution

check_keywords(nwbfile: NWBFile) InspectorMessage | None

Check if keywords have been added for the session.

Best Practice: Keywords

check_subject_exists(nwbfile: NWBFile) InspectorMessage | None

Check if subject exists.

Best Practice: Subject

check_doi_publications(nwbfile: NWBFile) Iterable[InspectorMessage] | None

Check if related_publications has been properly added as ‘doi: ###’ or an external ‘doi’ link.

Best Practice: Link to DOI Publications

check_publication_list_format(nwbfile: NWBFile) Iterable[InspectorMessage] | None

Check if related_publications entries contain comma-separated values that should be separate list entries.

Best Practice: Link to DOI Publications

check_subject_age(subject: Subject) InspectorMessage | None

Check if the Subject age is in ISO 8601 or our extension of it for ranges.

Best Practice: Subject Age

check_subject_proper_age_range(subject: Subject) InspectorMessage | None

Check if the Subject age, if specified as duration range (e.g., ‘P1D/P3D’), has properly increasing bounds.

Best Practice: Subject Age

check_subject_age_reference(subject: Subject) InspectorMessage | None

Check if the Subject age reference, when specified, is one of the supported options.

Best Practice: Subject Age

check_subject_id_exists(subject: Subject) InspectorMessage | None

Check if subject_id is defined.

Best Practice: Subject ID

check_subject_weight(subject: Subject) InspectorMessage | None

Check if subject weight follows the form ‘[numeric] [unit]’, e.g. ‘2.3 kg’.

The weight should include a numeric value followed by a space and a unit string. Without a unit, the weight is ambiguous.

Best Practice: Subject Weight

_check_subject_sex_defaults(sex: str) InspectorMessage | None

Check if the subject sex has been specified properly for the C. elegans species.

_check_subject_sex_c_elegans(sex: str) InspectorMessage | None

Check if the subject sex has been specified properly for the C. elegans species.

check_subject_sex(subject: Subject) InspectorMessage | None

Check if the subject sex has been specified and ensure that it has has the correct form depending on the species.

Best Practice: Subject Sex

check_subject_species_exists(subject: Subject) InspectorMessage | None

Check if the subject species has been specified.

Best Practice: Subject Species

check_subject_species_form(subject: Subject) InspectorMessage | None

Check if the subject species follows latin binomial form or is a link to an NCBI taxonomy in the form of a Term IRI.

The Term IRI can be found at the https://ontobee.org/ database.

Best Practice: Subject Species

check_processing_module_name(processing_module: ProcessingModule) InspectorMessage | None

Check if the name of a processing module is of a valid modality.

Best Practice: Processing Module Names

check_session_id_no_slashes(nwbfile: NWBFile) InspectorMessage | None

Check if session_id contains slash characters, which can cause problems when constructing paths in DANDI.

Best Practice: Session ID

check_subject_id_no_slashes(subject: Subject) InspectorMessage | None

Check if subject_id contains slash characters, which can cause problems when constructing paths in DANDI.

Best Practice: Subject ID

check_file_extension(nwbfile: NWBFile) InspectorMessage | None

Check if the file extension contains “.nwb”. If a backend storage type is specified, check that it matches the backend storage type.

NWB files should use appropriate extensions based on their backend: - .nwb (minimum recommendation), .nwb.h5 (HDF5), or .nwb.zarr (Zarr)

Best Practice: File Extensions

General

Check functions that examine any general neurodata_type with the available attributes.

check_name_slashes(neurodata_object: object) InspectorMessage | None

Check if there has been added for the session.

Best Practice: Do Not Use Slashes or Colons in Names

check_name_colons(neurodata_object: object) InspectorMessage | None

Check if an object name contains a colon.

Best Practice: Do Not Use Slashes or Colons in Names

check_description(neurodata_object: object) InspectorMessage | None

Check if the description is a not missing or a placeholder.

Best Practice: Empty Strings

NWB Containers

Check functions that can apply to any object inside an NWBContainer.

check_large_dataset_compression(nwb_container: NWBContainer, gb_lower_bound: float = 20.0) InspectorMessage | None

If the data in the Container object is a ‘large’ h5py.Dataset, check if it has compression enabled.

Will only return an inspector warning if the size of the h5py.Dataset is larger than the gb_lower_bound (default of 20 GB).

Best Practice: Compress Data

check_small_dataset_compression(nwb_container: NWBContainer, gb_severity_threshold: float = 10.0, mb_lower_bound: float = 50.0, gb_upper_bound: float = 20.0) InspectorMessage | None

If the data in the Container object is a h5py.Dataset, check if it has compression enabled.

Will only return an inspector warning if the size of the h5py.Dataset is larger than mb_lower_bound (default 50 MB) and smaller than gb_upper_bound (default of 20 GB).

Best Practice: Compress Data

check_empty_string_for_optional_attribute(nwb_container: NWBContainer) Iterable[InspectorMessage] | None

Check if any NWBContainer has optional fields that are written as an empty string.

These values should just be omitted instead.

Parameters:

Time Series

Check functions that can apply to any descendant of TimeSeries.

check_regular_timestamps(time_series: TimeSeries, time_tolerance_decimals: int = 9, gb_severity_threshold: float = 1.0) InspectorMessage | None

If the TimeSeries uses timestamps, check if they are regular (i.e., they have a constant rate).

Best Practice: Timestamps vs. Start & Rate

check_data_orientation(time_series: TimeSeries) InspectorMessage | None

If the TimeSeries has data, check if the longest axis (almost always time) is also the zero-axis.

Best Practice: Data Orientation

check_timestamps_match_first_dimension(time_series: TimeSeries) InspectorMessage | None

If the TimeSeries has timestamps, check if their length is the same as the zero-axis of data.

Best Practice: Data Orientation

check_timestamps_ascending(time_series: TimeSeries, nelems: int | None = 200) InspectorMessage | None

Check that the values in the timestamps array are strictly increasing.

Best Practice: Breaks in Continuity

check_timestamps_without_nans(time_series: TimeSeries, nelems: int | None = 200) InspectorMessage | None

Check if there are NaN values in the timestamps array.

Best Practice: Timestamps without NaNs

check_timestamp_of_the_first_sample_is_not_negative(time_series: TimeSeries) InspectorMessage | None

Check that the timestamp of the first sample is not negative.

Best Practice: Avoid Negative Timestamps

check_missing_unit(time_series: TimeSeries) InspectorMessage | None

Check if the TimeSeries.unit field is empty.

Best Practice: Units of Measurement

check_resolution(time_series: TimeSeries) InspectorMessage | None

Check the resolution value of a TimeSeries for proper format (-1.0 or NaN for unknown).

Best Practice: Unknown Resolution

check_time_series_duration(time_series: TimeSeries, duration_threshold: float = 31557600.0) InspectorMessage | None

Check if the TimeSeries duration is longer than the specified threshold.

The default threshold is 1 year (31,557,600 seconds = 365.25 days). Duration is calculated from either timestamps or starting_time + rate + data length.

Best Practice: Units of Measurement

check_time_series_data_is_not_empty(time_series: TimeSeries) InspectorMessage | None

Check if a TimeSeries has empty data.

Empty datasets are often the result of incomplete data entry or errors during conversion.

ImageSeries with external_file set intentionally have empty data and are skipped.

Best Practice: Empty Data

check_rate_not_below_threshold(time_series: TimeSeries, low_rate_threshold: float = 0.01) InspectorMessage | None

Check if the sampling rate is suspiciously low (below threshold, default 0.01 Hz).

A very low rate likely indicates the period (time between samples) was provided instead of the frequency. The default threshold of 0.01 Hz corresponds to a period of 100 seconds.

Best Practice: Units of Measurement

Tables

Check functions that can apply to any descendant of DynamicTable.

check_dynamic_table_region_data_validity(dynamic_table_region: DynamicTableRegion, nelems: int | None = 200) InspectorMessage | None

Check if a DynamicTableRegion is valid.

Best Practice: Table Region Data

check_empty_table(table: DynamicTable) InspectorMessage | None

Check if a DynamicTable is empty.

Best Practice: Empty Tables

check_time_intervals_start_time_not_constant(time_intervals: TimeIntervals, nelems: int | None = 200) InspectorMessage | None

Check if all start_time values are identical.

Best Practice: Timing Columns

Parameters:
  • time_intervals (TimeIntervals)

  • nelems (int, optional) – Only check the first {nelems} elements. This is useful in case there columns are very long so you don’t need to load the entire array into memory. Use None to load the entire arrays.

check_time_interval_time_columns(time_intervals: TimeIntervals, nelems: int | None = 200) InspectorMessage | None

Check that start_time values are in non-decreasing order.

Despite the function name suggesting multiple time columns, this only checks start_time. It was originally written to check all columns ending in _time, but was narrowed in PR #382 (see issue #375) because other time columns are not required to be ascending across rows. For example, a SleepStates table may contain overlapping state annotations where multiple states (e.g. WAKEtheta, QWake, WAKEnontheta) start at the same time with different stop times, making stop_time non-ascending by design.

Best Practice: Timing Columns

Parameters:
  • time_intervals (TimeIntervals)

  • nelems (int, optional) – Only check the first {nelems} elements. This is useful in case there columns are very long so you don’t need to load the entire array into memory. Use None to load the entire arrays.

check_time_intervals_stop_after_start(time_intervals: TimeIntervals, nelems: int | None = 200) InspectorMessage | None

Check that all stop times on a TimeInterval object occur after their corresponding start times.

Best Practice: Timing Columns

Parameters:
  • time_intervals (TimeIntervals)

  • nelems (int, optional) – Only check the first {nelems} elements. This is useful in case there columns are very long so you don’t need to load the entire array into memory. Use None to load the entire arrays.

check_column_binary_capability(table: DynamicTable, nelems: int | None = 200) Iterable[InspectorMessage] | None

Check each column of a table to see if the data could be set as a boolean dtype.

Parameters:
  • table (DynamicTable)

  • nelems (int, optional) – Only check the first {nelems} elements. This is useful in case there columns are very long so you don’t need to load the entire array into memory. Use None to load the entire arrays.

Best Practice: Boolean Columns

check_single_row(table: DynamicTable, exclude_types: tuple | None = None, exclude_names: tuple[str] | None = None) InspectorMessage | None

Check if DynamicTable has only a single row; may be better represented by another data type.

Skips the Units table since it is OK to have only a single spiking unit. Skips the Electrode table since it is OK to have only a single electrode.

Best Practice: Tables With Only a Single Row

check_table_values_for_dict(table: DynamicTable, nelems: int | None = 200) Iterable[InspectorMessage] | None

Check if any values in a row or column of a table contain a string casting of a Python dictionary.

Best Practice: Table Values

check_col_not_nan(table: DynamicTable, nelems: int | None = 200) Iterable[InspectorMessage] | None

Check if all the values in a single column of a table are NaN.

Best Practice: Tables With an Entire Column as NaN

check_ids_unique(table: DynamicTable, nelems: int | None = 200) InspectorMessage | None

Ensure that the values of the id attribute of a DynamicTable are unique.

Best Practice: Unique ids

Parameters:
  • table (DynamicTable)

  • nelems (int, optional) – Only inspect the first {nelems} elements

check_table_time_columns_are_not_negative(table: DynamicTable) Iterable[InspectorMessage] | None

Check that time columns are not negative.

Best Practice: Global Date and Time Reference

Parameters:

table (DynamicTable)

check_time_intervals_duration(time_intervals: TimeIntervals, duration_threshold: float = 31557600.0) InspectorMessage | None

Check if the duration spanned by time columns in a TimeIntervals table exceeds a threshold.

This check examines start_time, stop_time, and any other columns ending in _time.

Best Practice: Timing Columns

Parameters:
  • time_intervals (TimeIntervals) – The table to check

  • duration_threshold (float, optional) – Maximum expected duration in seconds. Default is 1 year (365.25 days).

Behavior

Checks for types belonging to the pynwb.behavior module.

check_spatial_series_dims(spatial_series: SpatialSeries) InspectorMessage | None

Check if a SpatialSeries has the correct dimensions.

Best Practice: SpatialSeries Dimensionality

check_compass_direction_unit(compass_direction: CompassDirection) Iterable[InspectorMessage] | None

Check that SpatialSeries objects within CompassDirection objects have units ‘degrees’ or ‘radians’.

Best Practice: SpatialSeries Units

check_spatial_series_radians_magnitude(spatial_series: SpatialSeries, nelems: int = 200) InspectorMessage | None

Check that SpatialSeries with units radians have data values between -2*pi and 2*pi.

Best Practice: SpatialSeries Data Values

check_spatial_series_degrees_magnitude(spatial_series: SpatialSeries, nelems: int = 200) InspectorMessage | None

Check that SpatialSeries with units of degrees have data values between -360 and 360.

Best Practice: SpatialSeries Data Values

check_spatial_series_unit(spatial_series: SpatialSeries) InspectorMessage | None

Check that SpatialSeries.unit is a recognized spatial unit.

Best Practice: SpatialSeries General Units

Intracellular Electrophysiology (icephys)

Checks specific to intracellular electrophysiology neurodata types.

check_intracellular_electrode_cell_id_exists(intracellular_electrode: IntracellularElectrode) InspectorMessage | None

Check if the IntracellularElectrode contains a cell_id.

Best Practice: TODO

check_sweeptable_deprecated(sweep_table: SweepTable) InspectorMessage | None

Check if the deprecated SweepTable is used in an NWB file with schema version >= 2.4.0.

Best Practice: SweepTable was deprecated in NWB 2.4.0 in favor of IntracellularRecordingsTable.

check_intracellular_electrode_location_allen_ccf(intracellular_electrode: IntracellularElectrode) InspectorMessage | None

Check that the IntracellularElectrode location is a term in the Allen Mouse Brain CCF ontology.

Only applies when the subject species is mouse.

Best Practice: Location

Extracellular Electrophysiology (ecephys)

Check functions specific to extracellular electrophysiology neurodata types.

check_units_table_has_spikes(units_table: Units) InspectorMessage | None

Check if the Units table is missing a spike_times column.

Best Practice: Units Table

check_negative_spike_times(units_table: Units) InspectorMessage | None

Check if the Units table contains negative spike times.

Best Practice: Negative Spike Times

check_units_resolution_is_set(units_table: Units) InspectorMessage | None

Check that the Units table has resolution set to a meaningful positive float.

Best Practice: Units Resolution

check_units_resolution_is_valid(units_table: Units) InspectorMessage | None

Check that the Units table resolution is not suspiciously large.

A resolution greater than 0.01 seconds (sampling rate below 100 Hz) likely indicates that the sampling rate was entered instead of the resolution (1/sampling_rate).

Best Practice: Units Resolution

check_spike_times_not_in_samples(units_table: Units, nelems: int | None = 200) InspectorMessage | None

Check if spike times appear to be sample indices rather than seconds.

Spike times stored as sample indices are integer-valued. Real spike times in seconds have fractional parts at any common electrophysiology sampling rate. If the resolution field on the Units table is set to >= 1.0 second, the check is skipped. This serves as an escape hatch for the unlikely case where spike time resolution is truly 1 second or lower; users must explicitly set this field to suppress the check.

Best Practice: Spike Times in Seconds

check_electrical_series_dims(electrical_series: ElectricalSeries) InspectorMessage | None

Use the length of the linked electrode region to check the data orientation.

Best Practice: Data Orientation

check_electrical_series_reference_electrodes_table(electrical_series: ElectricalSeries) InspectorMessage | None

Check that the ‘electrodes’ of an ElectricalSeries references the ElectrodesTable.

Best Practice: TODO

check_spike_times_not_in_unobserved_interval(units_table: Units, nunits: int = 4) InspectorMessage | None

Check if a Units table has spike times that occur outside of observed intervals.

Best Practice: Observation Intervals

check_spike_times_without_nans(units_table: Units) InspectorMessage | None

Check if the Units table contains NaN values in spike times.

Best Practice: No NaN Spike Times

check_ascending_spike_times(units_table: Units, nelems: int | None = 200) InspectorMessage | None

Check that spike times are strictly ascending for each unit.

Descending spike times always indicate a data error (trial-concatenated times, spike sorting bug, or conversion error). Equal consecutive spike times violate the neural refractory period for single-unit data. If the resolution field on the Units table is set, equal consecutive spike times are allowed because they may reflect hardware timing precision limits.

Best Practice Ascending Spike Times

Best Practice: Ascending Spike Times

check_electrical_series_unscaled_data(electrical_series: ElectricalSeries) InspectorMessage | None

Check if an ElectricalSeries has integer data with default conversion and offset values.

If the data type is an integer (int16, uint16, etc.) and both conversion and offset are set to their default values (1.0 and 0.0 respectively), this is likely a mistake because the raw integer values are probably not in Volts.

However, if channel_conversion is set with non-default values (not all 1.0), then the conversion factors are properly specified and no warning is needed.

Best Practice: Data Type and Conversion

check_units_table_duration(units_table: Units, duration_threshold: float = 31557600.0) InspectorMessage | None

Check if the duration of spike times in a Units table exceeds a threshold.

This check helps identify potential issues where spike times may have been stored in the wrong units (e.g., milliseconds instead of seconds) or have other data quality issues that result in an unrealistically long recording duration.

Best Practice Duration

Parameters:
  • units_table (Units) – The Units table to check.

  • duration_threshold (float, optional) – The duration threshold in seconds. If the duration exceeds this value, an InspectorMessage is returned. Default is 1 year (31557600 seconds).

Returns:

An InspectorMessage if the duration exceeds the threshold, None otherwise.

Return type:

Optional[InspectorMessage]

Best Practice: Duration

check_electrodes_location_allen_ccf(nwbfile: NWBFile) Iterable[InspectorMessage] | None

Check that electrode locations are terms in the Allen Mouse Brain CCF ontology.

Only applies when the subject species is mouse.

Best Practice: Ontologies

Optical Electrophysiology (ophys)

Check functions specific to optical electrophysiology neurodata types.

check_roi_response_series_dims(roi_response_series: RoiResponseSeries) InspectorMessage | None

Check the dimensions of an ROI series to ensure the time axis is the correct dimension.

Best Practice: Data Orientation

Check that each ROI response series links to a plane segmentation.

Best Practice: TODO

check_emission_lambda_in_nm(optical_channel: OpticalChannel) InspectorMessage | None

Check that emission lambda is in feasible range for unit nanometers.

Best Practice: Units of Measurement

check_excitation_lambda_in_nm(imaging_plane: ImagingPlane) InspectorMessage | None

Check that emission lambda is in feasible range for unit nanometers.

Best Practice: Units of Measurement

check_plane_segmentation_image_mask_shape_against_ref_images(plane_segmentation: PlaneSegmentation) Iterable[InspectorMessage] | None

Check that image masks and reference images have the same shape.

Best Practice: Image Shape Consistency

check_imaging_plane_location_allen_ccf(imaging_plane: ImagingPlane) InspectorMessage | None

Check that the ImagingPlane location is a term in the Allen Mouse Brain CCF ontology.

Only applies when the subject species is mouse.

Best Practice: Location

Optogenetics (ogen)

check_optogenetic_stimulus_site_has_optogenetic_series(ogen_site: OptogeneticStimulusSite) InspectorMessage | None

Check if an optogenetic stimulus site has an optogenetic series linked to it.

Best Practice: OptogeneticSeries

ImageSeries

Check functions specific to ImageSeries.

check_image_series_external_file_valid(image_series: ImageSeries) Iterable[InspectorMessage] | None

Check if the external_file specified by an ImageSeries actually exists.

Best Practice: Use external mode for videos of animals

check_image_series_external_file_relative(image_series: ImageSeries) Iterable[InspectorMessage] | None

Check if the external_file specified by an ImageSeries, if it exists, is relative.

Best Practice: Use external mode for videos of animals

check_image_series_data_size(image_series: ImageSeries, gb_lower_bound: float = 20.0) InspectorMessage | None

Check if an ImageSeries stored is larger than gb_lower_bound and suggests external file.

Best Practice: Use external mode for videos of animals

check_image_series_starting_frame_without_external_file(image_series: ImageSeries) InspectorMessage | None

Check if starting_frame is set when external_file is not used.

The starting_frame attribute is only relevant when using external files. If there is no external file, there should be no starting_frame.

Best Practice: Starting frame only with external file

Images

Checks specific to the Images neurodata type.

check_order_of_images_unique(images: Images) InspectorMessage | None

Check that all the values in the order_of_images field of an Images object are unique.

Best Practice: Storing the order of images in an Images object

check_order_of_images_len(images: Images) InspectorMessage | None

Check that all the values in the order_of_images field of an Images object are unique.

Best Practice: Storing the order of images in an Images object