Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add in vitro support #431

Merged
merged 7 commits into from
Feb 2, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,12 @@

* Use cached extension namespaces when calling pynwb validate instead of just the core namespace. [#425](https://github.com/NeurodataWithoutBorders/nwbinspector/pull/425)

### Improvements

* Added automatic suppression of certain subject related checks when inspecting files using the "dandi" configuration that have a `subject_id` that starts with the keyphrase "protein"; _e.g._, "proteinCaMPARI3" to indicate the _in vitro_ subject of the experiment is a purified CaMPARI3 protein.



# v0.4.30

### Fixes
Expand Down
2 changes: 2 additions & 0 deletions docs/best_practices/nwbfile_metadata.rst
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,8 @@ A ``subject_id`` is required for upload to the :dandi-archive:`DANDI archive <>`
not intended for DANDI upload, if the :ref:`nwb-schema:sec-Subject` is specified at all it should be given a
``subject_id`` for reference.

In the special case of *in vitro* studies where the 'subject' of scientific interest was not a tissue sample obtained from a living subject but was instead a purified protein, this will be annotated by prepending the keyphrase "protein" to the subject ID; *e.g*, "proteinCaMPARI3". In the case where the *in vitro* experiment is performed on an extracted or cultured biological sample, the other subject attributes (such as age and sex) should be specified as their values at the time the sample was collected.

Check function: :py:meth:`~nwbinspector.checks.nwbfile_metadata.check_subject_id_exists`


Expand Down
36 changes: 35 additions & 1 deletion src/nwbinspector/nwbinspector.py
Original file line number Diff line number Diff line change
Expand Up @@ -604,6 +604,38 @@ def inspect_nwbfile(
)


# TODO: deprecate once subject types and dandi schemas have been extended
def _intercept_in_vitro_protein(nwbfile_object: pynwb.NWBFile, checks: Optional[list] = None) -> List[callable]:
"""
If the special 'protein' subject_id is specified, return a truncated list of checks to run.

This is a temporary method for allowing upload of certain in vitro data to DANDI and
is expected to replaced in future versions.
"""
subject_related_check_names = [
"check_subject_exists",
"check_subject_id_exists",
"check_subject_sex",
"check_subject_species_exists",
"check_subject_species_form",
"check_subject_age",
"check_subject_proper_age_range",
]
subject_related_dandi_requirements = [
check.importance == Importance.CRITICAL for check in checks if check.__name__ in subject_related_check_names
]

subject = getattr(nwbfile_object, "subject", None)
if (
any(subject_related_dandi_requirements)
and subject is not None
and getattr(subject, "subject_id", "").startswith("protein")
):
non_subject_checks = [check for check in checks if check.__name__ not in subject_related_check_names]
return non_subject_checks
return checks


def inspect_nwbfile_object(
nwbfile_object: pynwb.NWBFile,
checks: Optional[list] = None,
Expand Down Expand Up @@ -651,7 +683,9 @@ def inspect_nwbfile_object(
checks=checks, config=config, ignore=ignore, select=select, importance_threshold=importance_threshold
)

for inspector_message in run_checks(nwbfile=nwbfile_object, checks=checks):
subject_dependent_checks = _intercept_in_vitro_protein(nwbfile_object=nwbfile_object, checks=checks)

for inspector_message in run_checks(nwbfile=nwbfile_object, checks=subject_dependent_checks):
yield inspector_message


Expand Down
19 changes: 16 additions & 3 deletions tests/test_inspector.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import os
import pytest
from shutil import rmtree
from tempfile import mkdtemp
from pathlib import Path
Expand All @@ -8,7 +7,7 @@

import numpy as np
from pynwb import NWBFile, NWBHDF5IO, TimeSeries
from pynwb.file import TimeIntervals
from pynwb.file import TimeIntervals, Subject
from pynwb.behavior import SpatialSeries, Position
from hdmf.common import DynamicTable
from natsort import natsorted
Expand All @@ -22,7 +21,7 @@
check_subject_exists,
load_config,
)
from nwbinspector import inspect_all, inspect_nwbfile, available_checks
from nwbinspector import inspect_all, inspect_nwbfile, inspect_nwbfile_object, available_checks
from nwbinspector.register_checks import Severity, InspectorMessage, register_check
from nwbinspector.tools import make_minimal_nwbfile
from nwbinspector.utils import FilePathType
Expand Down Expand Up @@ -727,3 +726,17 @@ def test_check_unique_identifiers_fail(self):
file_path=str(self.tempdir),
)
]


def test_dandi_config_in_vitro_injection():
"""Test that a subject_id starting with 'protein' excludes meaningless CRITICAL-elevated subject checks."""
nwbfile = make_minimal_nwbfile()
nwbfile.subject = Subject(
subject_id="proteinCaMPARI3", description="A detailed description about the in vitro setup."
)
config = load_config(filepath_or_keyword="dandi")
importance_threshold = "CRITICAL"
messages = list(
inspect_nwbfile_object(nwbfile_object=nwbfile, config=config, importance_threshold=importance_threshold)
)
assert messages == []
Loading