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:
nwb_container (NWBContainer)
Best Practice (Empty Strings)
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, aSleepStatestable may contain overlapping state annotations where multiple states (e.g. WAKEtheta, QWake, WAKEnontheta) start at the same time with different stop times, makingstop_timenon-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
resolutionfield 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
resolutionfield 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_roi_response_series_link_to_plane_segmentation(roi_response_series: RoiResponseSeries) InspectorMessage | None
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