Skip to content

Commit

Permalink
yaml-validation
Browse files Browse the repository at this point in the history
  • Loading branch information
zoldello committed Jul 31, 2023
1 parent fb5e330 commit b93eb6d
Show file tree
Hide file tree
Showing 22 changed files with 3,436 additions and 92 deletions.
18 changes: 18 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,21 @@
Converts data from SpikeGadgets to the NWB Data Format

This will supersede [rec_to_nwb](https://github.com/LorenFrankLab/rec_to_nwb) once it is operational.

## Notes

### Unit Test

Unit test are quick-running test to ensure that no code is broken as new code is added. It is recommended you run them frequently and before and after adding new code. To run the unit test, run -

```bash
pytest src/spikegadgets_to_nwb/tests/unit_tests/
```

### Integration Test

Integration test are to ensure the system works. Functionality and third-party libraries are tested together and noting is mocked. They are best ran prior to pushing a commit as they can be slow. To run the test, run -

```bash
pytest src/spikegadgets_to_nwb/tests/integration_tests/
```
31 changes: 16 additions & 15 deletions environment.yml
Original file line number Diff line number Diff line change
@@ -1,18 +1,19 @@
name: spikegadgets_to_nwb
channels:
- defaults
- conda-forge
- franklab
- defaults
- conda-forge
- franklab
dependencies:
- numpy
- scipy
- pandas
- pynwb
- ipython
- black
- pytest
- pytest-cov
- pip
- pyyaml
- pip:
- ndx-franklab-novela
- numpy
- scipy
- pandas
- pynwb
- ipython
- black
- pytest
- pytest-cov
- pip
- pyyaml
- jsonschema
- pip:
- ndx-franklab-novela
19 changes: 19 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -50,3 +50,22 @@ exclude = [".git_archival.txt"]
[tool.hatch.build.targets.wheel]
packages = ["src/spikegadgets_to_nwb"]
exclude = ["src/spikegadgets_to_nwb/data/test_data"]

[tool.black]
exclude = '''
(
/(
\.eggs # exclude a few common directories in the
| \.git # root of the project
| \.hg
| \.mypy_cache
| \.tox
| \.venv
| _build
| buck-out
| build
| dist
)/
)
'''
6 changes: 6 additions & 0 deletions src/spikegadgets_to_nwb/convert_yaml.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import yaml
from xml.etree import ElementTree
from spikegadgets_to_nwb import metadata_validation

from pynwb import NWBFile, TimeSeries
from pynwb.file import Subject, ProcessingModule
Expand Down Expand Up @@ -39,6 +40,11 @@ def load_metadata(
"""
with open(metadata_path, "r") as stream:
metadata = yaml.safe_load(stream)

is_metadata_valid, metadata_errors = metadata_validation.validate(metadata)
if not is_metadata_valid:
raise ValueError("".join(metadata_errors))

probe_metadata = []
for path in probe_metadata_paths:
with open(path, "r") as stream:
Expand Down
74 changes: 74 additions & 0 deletions src/spikegadgets_to_nwb/metadata_validation.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
import jsonschema
import os
import yaml
import copy
import datetime


def _get_nwb_json_schema_path() -> str:
"""Get the NWB JSON Schema file path
Returns
-------
str
NWB Schema file Path
"""
current_path = os.path.dirname(os.path.abspath(__file__))
json_schema_file = "/./nwb_schema.json"
return f"{current_path}{os.path.normpath(json_schema_file)}"


def _get_json_schema() -> str:
"""Get JSON Schema
Returns
-------
str
JSON Schema content
"""
json_schema = None
json_schema_path = _get_nwb_json_schema_path()
with open(json_schema_path, "r") as stream:
json_schema = yaml.safe_load(stream)
return json_schema


def validate(metadata: dict) -> tuple:
"""Validates metadata
Parameters
----------
metadata : dict
metadata documenting the particulars of a session
Returns
-------
tuple
information of the validity of the metadata data and any errors
"""
assert metadata is not None # metadata cannot be null
assert isinstance(metadata, dict) # cannot proceed if metadata is not a dictionary

# date_of_birth is set to a datetime by the YAML-to-dict converter.
# This code converts date_of_birth to string
metadata_content = copy.deepcopy(metadata) or {}
if (
metadata_content["subject"]
and metadata_content["subject"]["date_of_birth"]
and type(metadata_content["subject"]["date_of_birth"]) is datetime.datetime
):
metadata_content["subject"]["date_of_birth"] = (
metadata_content["subject"]["date_of_birth"].utcnow().isoformat()
)

schema = _get_json_schema()
validator = jsonschema.Draft202012Validator(schema)
metadata_validation_errors = validator.iter_errors(metadata_content)
errors = []

for metadata_validation_error in metadata_validation_errors:
errors.append(metadata_validation_error.message)

is_valid = len(errors) == 0

return is_valid, errors
Loading

0 comments on commit b93eb6d

Please sign in to comment.