Skip to content

Commit

Permalink
Merge branch 'staging' of github.com:HumanCellAtlas/metadata-schema i…
Browse files Browse the repository at this point in the history
…nto ac-tissue-dissociation-Issue1592
  • Loading branch information
arschat committed Jan 6, 2025
2 parents 34ddf39 + 293e535 commit 8a9b62c
Show file tree
Hide file tree
Showing 9 changed files with 109 additions and 47 deletions.
8 changes: 8 additions & 0 deletions changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,14 @@ and (starting with v4.0.0) this project adheres to [Semantic Versioning](http://

## [Released](https://github.com/HumanCellAtlas/metadata-schema/)

### [type/biomaterial/donor_organism.json - v17.1.0] - 2024-12-11
### Added
Added non-required gender identity field.

### [module/ontology/gender_identity_ontology.json - v1.0.0] - 2024-12-11
### Added
Added ontology module for gender identity.

### [module/biomaterial/medical_history.json - v7.0.0] - 2024-11-06
### Changed
Changed medication field type Fix#1589
Expand Down
11 changes: 11 additions & 0 deletions docs/jsonBrowser/module.md
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,17 @@ text | The name of a process type being used. | string | yes | | Process type |
ontology | An ontology term identifier in the form prefix:accession. | string | no | | Process type ontology ID | | EFO:0009128; EFO:0009121
ontology_label | The preferred label for the ontology term referred to in the ontology field. This may differ from the user-supplied value in the text field. | string | no | | Process type ontology label | | enzymatic dissociation; blood draw

## Gender identity ontology<a name='Gender identity ontology'></a>
_A term that may be associated with a gender-related ontology term._

Location: module/ontology/gender_identity_ontology.json

Property name | Description | Type | Required? | Object reference? | User friendly name | Allowed values | Example
--- | --- | --- | --- | --- | --- | --- | ---
text | The gender identity of the human donor at the time of the experiment. | string | yes | | Gender identity | | Female Gender; Agender; Non-Binary Gender
ontology | An ontology term identifier in the form prefix:accession. | string | no | | Gender identity ontology ID | | NCIT:C46110; NCIT:C205469; NCIT:C160941
ontology_label | The preferred label for the ontology term referred to in the ontology field. This may differ from the user-supplied value in the text field. | string | no | | Gender identity ontology label | | Female Gender; Agender; Non-Binary Gender

## Sequencing ontology<a name='Sequencing ontology'></a>
_A term that may be associated with a process-related ontology term._

Expand Down
4 changes: 4 additions & 0 deletions docs/jsonBrowser/required_fields.md
Original file line number Diff line number Diff line change
Expand Up @@ -264,6 +264,10 @@ text | The name of a library construction approach being used. | string | | Lib
Property name | Description | Type | Object reference? | User friendly name | Allowed values | Example
--- | --- | --- | --- | --- | --- | ---
text | The name of a process type being used. | string | | Process type | | enzymatic dissociation; blood draw
### Gender identity ontology<a name='Gender identity ontology'></a>
Property name | Description | Type | Object reference? | User friendly name | Allowed values | Example
--- | --- | --- | --- | --- | --- | ---
text | The gender identity of the human donor at the time of the experiment. | string | | Gender identity | | Female Gender; Agender; Non-Binary Gender
### Sequencing ontology<a name='Sequencing ontology'></a>
Property name | Description | Type | Object reference? | User friendly name | Allowed values | Example
--- | --- | --- | --- | --- | --- | ---
Expand Down
1 change: 1 addition & 0 deletions docs/jsonBrowser/type.md
Original file line number Diff line number Diff line change
Expand Up @@ -447,6 +447,7 @@ height | Height of organism in Height unit. | string | no | | Height | | 160;
height_unit | The unit in which Height is expressed. | object | no | [See module length_unit_ontology](module.md#length-unit-ontology) | Height unit | |
weight | Weight of organism in Weight unit. | string | no | | Weight | | 60; 40-60
weight_unit | The unit in which Weight is expressed. | object | no | [See module mass_unit_ontology](module.md#mass-unit-ontology) | Weight unit | |
gender_identity | The donor's personal sense of their own gender at the time of the experiment. | object | no | [See module gender_identity_ontology](module.md#gender-identity-ontology) | Gender identity | |

## Organoid
_Information about an organoid biomaterial._
Expand Down
49 changes: 49 additions & 0 deletions json_schema/module/ontology/gender_identity_ontology.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
{
"$schema": "http://json-schema.org/draft-07/schema#",
"description": "A term that may be associated with a gender-related ontology term.",
"additionalProperties": false,
"required": [
"text"
],
"title": "Gender identity ontology",
"name": "gender_identity_ontology",
"type": "object",
"properties": {
"describedBy" : {
"description": "The URL reference to the schema.",
"pattern" : "^(http|https)://schema.(.*?)humancellatlas.org/module/ontology/(([0-9]{1,}.[0-9]{1,}.[0-9]{1,})|([a-zA-Z]*?))/gender_identity_ontology",
"type": "string"
},
"schema_version": {
"description": "Version number in major.minor.patch format.",
"type": "string",
"pattern": "^[0-9]{1,}.[0-9]{1,}.[0-9]{1,}$",
"example": "4.6.1"
},
"text": {
"description": "The gender identity of the human donor at the time of the experiment.",
"type": "string",
"user_friendly": "Gender identity",
"example": "Female Gender; Agender; Non-Binary Gender"
},
"ontology": {
"description": "An ontology term identifier in the form prefix:accession.",
"type": "string",
"graph_restriction": {
"ontologies" : ["obo:ncit"],
"classes": ["NCIT:C17357"],
"relations": ["rdfs:subClassOf"],
"direct": false,
"include_self": false
},
"user_friendly": "Gender identity ontology ID",
"example": "NCIT:C46110; NCIT:C205469; NCIT:C160941"
},
"ontology_label": {
"description": "The preferred label for the ontology term referred to in the ontology field. This may differ from the user-supplied value in the text field.",
"type": "string",
"user_friendly": "Gender identity ontology label",
"example": "Female Gender; Agender; Non-Binary Gender"
}
}
}
6 changes: 6 additions & 0 deletions json_schema/type/biomaterial/donor_organism.json
Original file line number Diff line number Diff line change
Expand Up @@ -199,6 +199,12 @@
"type": "object",
"$ref": "module/ontology/mass_unit_ontology.json",
"user_friendly": "Weight unit"
},
"gender_identity": {
"description": "The donor's personal sense of their own gender at the time of the experiment.",
"type": "object",
"$ref": "module/ontology/gender_identity_ontology.json",
"user_friendly": "Gender identity"
}
}
}
5 changes: 3 additions & 2 deletions json_schema/versions.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"last_update_date": "2024-11-06T17:01:14Z",
"last_update_date": "2024-12-11T09:29:09Z",
"version_numbers": {
"core": {
"biomaterial": {
Expand Down Expand Up @@ -45,6 +45,7 @@
"ethnicity_ontology": "5.3.9",
"file_content_ontology": "2.0.0",
"file_format_ontology": "1.0.0",
"gender_identity_ontology": "1.0.0",
"instrument_ontology": "5.3.6",
"length_unit_ontology": "5.3.5",
"library_amplification_ontology": "1.2.5",
Expand Down Expand Up @@ -94,7 +95,7 @@
"biomaterial": {
"cell_line": "16.0.0",
"cell_suspension": "14.0.0",
"donor_organism": "17.0.0",
"donor_organism": "17.1.0",
"imaged_specimen": "3.5.0",
"organoid": "11.5.0",
"specimen_from_organism": "10.9.0"
Expand Down
4 changes: 2 additions & 2 deletions src/human_readable_json.py
Original file line number Diff line number Diff line change
Expand Up @@ -118,9 +118,9 @@ def generateMarkdown(self, schemas, entity_type):
# print(schema["title"] + "\t "+ property + "\t"+ link)

if "enum" in schema["properties"][property]:
enum_values = ", ".join(schema["properties"][property]["enum"])
enum_values = ", ".join(str(enum) for enum in schema["properties"][property]["enum"])
elif "enum" in schema["properties"][property].get("items", ""):
enum_values = ", ".join(schema["properties"][property]["items"]["enum"])
enum_values = ", ".join(str(enum) for enum in schema["properties"][property]["items"]["enum"])
else:
enum_values = ""
file.write(property + " | "+
Expand Down
68 changes: 25 additions & 43 deletions src/schema_linter.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
import re
import json
import sys
import argparse
from urllib.request import urlopen
from urllib.error import HTTPError

Expand All @@ -16,7 +15,7 @@

required_schema_fields = ['$schema', 'description', 'additionalProperties', 'title', 'name', 'type', 'properties']

allowed_schema_fields = ['$schema', 'description', 'additionalProperties', 'required', 'title', 'name', 'type', 'properties', 'definitions', 'dependencies', 'if', 'then', 'else', 'minProperties']
allowed_schema_fields = ['$schema', 'description', 'additionalProperties', 'required', 'title', 'name', 'type', 'properties', 'definitions', 'dependencies', 'if', 'then', 'else', 'allOf', 'minProperties']

# Properties

Expand All @@ -38,24 +37,6 @@

graph_restriction_attributes = ['ontologies', 'classes', 'relations', 'direct', 'include_self']

# Accepted environments and conversion for OLS API url

ENVIRONMENTS = ['develop', 'integration', 'staging', 'master']

OLS_ENVIRONMENT = {
"develop": "dev",
"integration": "integration",
"staging": "staging",
"master": "staging"
}

def argument_parser():
# Create the parser, define arguments and return it
parser = argparse.ArgumentParser()
parser.add_argument('--environment', '-e', type=str, dest='environment', help='environment the OLS API feeds on',
default='staging', action='store', choices=ENVIRONMENTS)
return parser


class SchemaLinter:
def __init__(self):
Expand Down Expand Up @@ -163,26 +144,30 @@ def lintSchema(self, path, ols_api):
errors.append(schema_filename + ".json: Keyword `type` missing from property `" + property + "`.")

else:
# type attribute must be set to one of the valid JSON types
if properties[property]['type'] not in ["string", "number", "boolean", "array", "object", "integer"]:
errors.append(schema_filename + ".json: Type `" + properties[property]['type'] + "` is not a valid JSON type.")

# Property of type array must contain the attribute items
if properties[property]['type'] == "array" and 'items' not in properties[property].keys():
errors.append(schema_filename + ".json: Property `" + property + "` is type array but doesn't contain items.")

# Property of type array must contains the attribute items
# items must have either type or $ref attribute
if properties[property]['type'] == "array" and 'items' in properties[property].keys() and '$ref' not in properties[property]['items'].keys() and 'type' not in properties[property]['items'].keys():
errors.append(schema_filename + ".json: Property `" + property + "` is type array but items attribute doesn't contain type or $ref attribute.")

# Property of type object must contains the attribute $ref
if properties[property]['type'] == "object" and '$ref' not in properties[property].keys():
errors.append(schema_filename + ".json: Property `" + property + "` is type object but doesn't contain $ref.")
# change property to list to test all values of array
properties[property]['type'] = properties[property]['type'] if isinstance(properties[property]['type'], list) else [properties[property]['type']]

for property_type in properties[property]['type']:
# type attribute must be set to one of the valid JSON types
if property_type not in ["string", "number", "boolean", "array", "object", "integer", "null"]:
errors.append(schema_filename + ".json: Type `" + property_type + "` is not a valid JSON type.")

# Property of type array must contain the attribute items
if property_type == "array" and 'items' not in properties[property].keys():
errors.append(schema_filename + ".json: Property `" + property + "` is type array but doesn't contain items.")

# Property of type array must contains the attribute items
# items must have either type or $ref attribute
if property_type == "array" and 'items' in properties[property].keys() and '$ref' not in properties[property]['items'].keys() and 'type' not in properties[property]['items'].keys():
errors.append(schema_filename + ".json: Property `" + property + "` is type array but items attribute doesn't contain type or $ref attribute.")

# Property of type object must contains the attribute $ref
if property_type == "object" and '$ref' not in properties[property].keys():
errors.append(schema_filename + ".json: Property `" + property + "` is type object but doesn't contain $ref.")

# format must be a valid JSON format
if 'format' in properties[property].keys() and properties[property]['format'] not in ["date", "date-time", "email"]:
errors.append(schema_filename + ".json: Format `" + properties[property]['format'] + "` is not a valid JSON format).")
if 'format' in properties[property].keys() and properties[property]['format'] not in ["date", "date-time", "email", "uri"]:
errors.append(schema_filename + ".json: Format `" + properties[property]['format'] + "` is not a valid JSON format.")

# description should be a sentence - start with capital letter and end with full stop
if 'description' in properties[property].keys() and not re.match('^[A-Z][^?!]*[.]$', properties[property]['description']):
Expand Down Expand Up @@ -329,11 +314,8 @@ def get_json_from_file(self, filename, warn = False):


if __name__ == "__main__":
# Define the environment, transforming 'develop' and 'master' to their respective OLS valid environment to
# define the proper OLS API URL.
arguments = argument_parser().parse_args(sys.argv[1:])
environment = OLS_ENVIRONMENT[arguments.environment]
ols_api = 'https://ontology.{}.archive.data.humancellatlas.org/api'.format(environment)
# As of November 2024, we are now using the OLS4 for ontology checkup
ols_api = 'https://www.ebi.ac.uk/ols/api'

schema_path = '../json_schema' if cwd == 'src' else 'json_schema'
jsons = [os.path.join(dirpath, f)
Expand Down

0 comments on commit 8a9b62c

Please sign in to comment.