Skip to content
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: 5 additions & 1 deletion available.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,11 @@
"1.0",
"1.1",
"1.2",
"2.0"
"2.0",
"2.1"
],
"CRUK": [
"1.0.0"
],
"SchemaOrg": [
"BioSchema",
Expand Down
109 changes: 109 additions & 0 deletions hdr_schemata/examples/CRUK/1.0.0/example.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
{
"identifier": "a7ddefbd-31d9-4703-a738-256e4689f76a",
"version": "1.0.0",
"revisions": [
{
"version": "1.0.0",
"url": "https://example.org/datasets/a7ddefbd-31d9-4703-a738-256e4689f76a"
}
],
"issued": "2020-08-05T14:35:59Z",
"modified": "2021-01-28T14:15:46Z",
"summary": {
"title": "CRUK DataHub Example Dataset",
"abstract": "Example CRUK dataset record extending HDRUK 4.0.0 with CRUK-specific fields.",
"dataCustodian": {
"identifier": "hdr-uk",
"name": "HEALTH DATA RESEARCH UK",
"contactPoint": "susheel.varma@hdruk.ac.uk"
},
"populationSize": 575,
"keywords": [
"Cancer",
"CRUK",
"Example"
],
"doiName": "10.1093/ije/dyx196",
"contactPoint": "susheel.varma@hdruk.ac.uk"
},
"accessibility": {
"formatAndStandards": {
"language": [
"en"
],
"vocabularyEncodingScheme": [
"OTHER"
],
"format": [
"CSV",
"JSON"
],
"conformsTo": [
"OTHER"
]
},
"usage": {
"dataUseLimitation": [
"General research use"
],
"resourceCreator": "HDR UK Science Team",
"dataUseRequirements": [
"Return to database or resource"
]
},
"access": {
"dataController": "HDR UK",
"jurisdiction": [
"GB-ENG"
],
"dataProcessor": "HDR UK",
"accessService": "https://github.com/HDRUK/papers",
"accessRights": "https://raw.githubusercontent.com/HDRUK/papers/master/LICENSE",
"accessRequestCost": "Free",
"deliveryLeadTime": "Other"
}
},
"observations": [
{
"observedNode": "Findings",
"measuredValue": 575,
"disambiguatingDescription": "Example observation count",
"observationDate": "2020-11-27",
"measuredProperty": "Count"
}
],
"datasetFilters": [
{
"id": "1",
"label": "Breast",
"category": "Cancer",
"primaryGroup": "cancer-type",
"description": "Breast cancer"
}
],
"icons": [
"icon-a",
"icon-b"
],
"erd": null,
"projectGrants": [
{
"pid": "CRUK-PROJ-001",
"projectGrantName": "CRUK Example Grant Title",
"leadResearcher": "Dr Smith",
"leadResearchInstitute": "Sussex University",
"grantNumber": "ABC123",
"projectGrantStartDate": "2020-01-01",
"projectGrantEndDate": "2024-12-31",
"projectGrantScope": "Longitudinal genomic data including somatic mutations"
}
],
"otherDataTypes": [
{
"title": "Mammograms",
"description": "2D images of both normal and malignant breasts",
"format": "image/jpeg"
}
]
}

3,422 changes: 3,422 additions & 0 deletions hdr_schemata/models/CRUK/1.0.0/schema.json

Large diffs are not rendered by default.

2 changes: 2 additions & 0 deletions hdr_schemata/models/CRUK/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
from .v1_0_0 import Cruk100

4 changes: 4 additions & 0 deletions hdr_schemata/models/CRUK/create_json_schema.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
import v1_0_0

v1_0_0.Cruk100.save_schema()

226 changes: 226 additions & 0 deletions hdr_schemata/models/CRUK/v1_0_0/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,226 @@
import json
from typing import List, Literal, Optional

from pydantic import BaseModel, Field, constr

from hdr_schemata.definitions.HDRUK import (
Format,
OneHundredFiftyCharacters,
ShortDescription,
Url,
)
from hdr_schemata.models.HDRUK.v4_0_0 import Hdruk400
from hdr_schemata.models.HDRUK.v3_0_0.DataTable import DataTable as BaseDataTable
from hdr_schemata.models.HDRUK.v3_0_0.StructuralMetadata import (
StructuralMetadata as BaseStructuralMetadata,
)
from hdr_schemata.models.HDRUK.v4_0_0.Summary import Summary as BaseSummary


class DatasetFilter(BaseModel):
class Config:
extra = "forbid"

id: constr(pattern=r"(\d+_){0,5}\d+") = Field(..., title="Id")
label: constr(min_length=0, max_length=150) = Field(..., title="Label")
category: constr(min_length=0, max_length=150) = Field(..., title="Category")
primaryGroup: Literal["cancer-type", "data-type", "access-type"] = Field(
..., title="Primary group"
)
description: constr(min_length=0, max_length=150) = Field(..., title="Description")


class DataTable(BaseDataTable):
Comment thread
spco marked this conversation as resolved.
size: Optional[int] = Field(
None,
title="Table size",
description="Number of Complete Entries.",
json_schema_extra={
"guidance": (
"Provides a measure of the completeness of the data set. A row which includes n/a against "
"columns that are not relevant or not applicable should still be counted as complete."
)
},
)


class StructuralMetadata(BaseStructuralMetadata):
class Config:
extra = "forbid"

# Override `tables` so CRUK's schema uses CRUK `DataTable` (adds `size`).
tables: Optional[List[DataTable]] = Field(
None,
description="Tables in the dataset",
title="Tables",
)


class Summary(BaseSummary):
class Config:
extra = "forbid"

# Optional-by-absence (not nullable). If provided, must be a 150-char string.
leadResearcher: OneHundredFiftyCharacters = Field(
default=None,
title="Lead Researcher",
description="Lead for the dataset. This need not be the same as the lead for the underlying grant",
examples=["Professor Karen Blogs", "Dr A Dataset"],
)
leadResearchInstitute: OneHundredFiftyCharacters = Field(
default=None,
title="Lead Research Institute",
description="",
examples=["Sussex University"],
)


class OtherDataType(BaseModel):
class Config:
extra = "forbid"

title: OneHundredFiftyCharacters = Field(
...,
title="Title",
json_schema_extra={"guidance": "Short descriptive titles"},
examples=["Mammograms", "Patient recordings"],
)
description: ShortDescription = Field(
...,
title="Data description",
json_schema_extra={"guidance": "A description of the data type."},
examples=[
"2D images of both normal and malignant breasts",
"audio-tapes of oncology consultations",
],
)
format: Format = Field(
...,
title="Format",
description="Format drawn from https://www.iana.org/assignments/media-types/media-types.xhtml.",
json_schema_extra={
"guidance": (
"https://www.iana.org/assignments/media-types/media-types.xhtml lists the commonly used "
"formats for different media (such as video/image/audio) etc. If your format is not "
"included in the list set out there, please indicate other and specify in the description."
)
},
)


class ProjectGrant(BaseModel):
pid: Optional[OneHundredFiftyCharacters] = Field(
None,
title="Persistent identifier of the study",
)
projectGrantName: OneHundredFiftyCharacters = Field(
...,
title="Project Grant Title",
description=(
"The Project Grant Title should be unique to the CRUK datahub. "
"(Add your institute or name if necessary to disambiguate)."
),
)
leadResearcher: OneHundredFiftyCharacters = Field(
...,
title="Lead Researcher",
examples=["Dr Smith"],
)
leadResearchInstitute: OneHundredFiftyCharacters = Field(
...,
title="Lead Research Institute",
examples=["Sussex University"],
)
grantNumber: str = Field(
...,
title="Grant number(s)",
description="List of CRUK and any other grant numbers.",
examples=["ABC123"],
json_schema_extra={"guidance": "Normally specified on the grant acceptance letter"},
)
projectGrantStartDate: str = Field(
...,
title="Project Start Date",
description="Starting date of projectGrant grant.",
json_schema_extra={
"guidance": (
"Date on which the dataset projectGrant starts. This is normally set out in the grant "
"contract and will be different from the start of any data collection"
)
},
)
projectGrantEndDate: Optional[str] = Field(
...,
title="Project End Date",
description="Current end date of project grant.",
json_schema_extra={
"guidance": (
"Date on which the dataset project is currently projected to finish. This is normally set "
"out in the grant contract and will be different from the end of any data collection"
)
},
)
projectGrantScope: Optional[constr(min_length=5, max_length=500)] = Field(
None,
title="Project Scope",
description="data and biospecimens expected to result from the grant.",
examples=["Longitudinal genomic data including somatic mutations"],
json_schema_extra={
"guidance": (
"Short paragraph setting out the types of data / biospecimens likely to result from the "
"grant and the cancers covered"
)
},
)


class Cruk100(Hdruk400):
class Config:
extra = "forbid"

# Override HDRUK 4.0.0 summary for CRUK-specific lead fields.
summary: Summary = Field(
...,
description="Summary of metadata describing key pieces of information.",
)

# Override structural metadata so DataTable includes `size`.
structuralMetadata: Optional[StructuralMetadata] = Field(
None,
description="Descriptions of all tables and data elements that can be included in the dataset.",
title="Structural metadata",
)

datasetFilters: Optional[List[DatasetFilter]] = Field(
None,
title="Dataset Filters",
)
icons: Optional[List[str]] = Field(
None,
title="Icons",
description="Calculated categorization icons added during export.",
)
erd: Optional[Url] = Field(
None,
title="Entity Relationship Diagram",
description="Visual representation of data table relationships.",
json_schema_extra={
"guidance": (
"Please upload an image file (max 5MB) showing the relationship between the different tables"
)
},
)
projectGrants: Optional[List[ProjectGrant]] = Field(
None,
title="Associated Project Grants",
)
otherDataTypes: Optional[List[OtherDataType]] = Field(
None,
title="Other data types",
)

@classmethod
def save_schema(cls, location: str = "./1.0.0/schema.json") -> None:
with open(location, "w") as f:
json.dump(cls.model_json_schema(), f, indent=6)

Loading
Loading