Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 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."
Comment thread
spco marked this conversation as resolved.
Outdated
),
)
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