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
3 changes: 3 additions & 0 deletions fairscape_models/__init__.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
from fairscape_models.activity import Activity
from fairscape_models.digital_object import DigitalObject
from fairscape_models.annotation import Annotation
from fairscape_models.biochem_entity import BioChemEntity
from fairscape_models.computation import Computation
from fairscape_models.dataset import Dataset
from fairscape_models.software import Software
from fairscape_models.mlmodel import MLModel
from fairscape_models.fairscape_base import IdentifierValue, IdentifierPropertyValue
from fairscape_models.medical_condition import MedicalCondition
from fairscape_models.schema import Schema
Expand Down
16 changes: 16 additions & 0 deletions fairscape_models/activity.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
from pydantic import BaseModel, Field, ConfigDict
from typing import Optional, List

from fairscape_models.fairscape_base import IdentifierValue

class Activity(BaseModel):
"""Base class for Activity types (Computation, Annotation, Experiment)"""
guid: str = Field(alias="@id")
name: str
metadataType: Optional[str] = Field(default=None, alias="@type")
description: str = Field(min_length=10)
associatedPublication: Optional[str] = Field(default=None)
generated: Optional[List[IdentifierValue]] = Field(default=[])
isPartOf: Optional[List[IdentifierValue]] = Field(default=[])

model_config = ConfigDict(extra="allow")
13 changes: 3 additions & 10 deletions fairscape_models/annotation.py
Original file line number Diff line number Diff line change
@@ -1,19 +1,12 @@
from pydantic import BaseModel, Field, ConfigDict
from pydantic import Field, ConfigDict
from typing import Optional, List

from fairscape_models.fairscape_base import IdentifierValue, ANNOTATION_TYPE
from fairscape_models.activity import Activity

class Annotation(BaseModel):
guid: str = Field(alias="@id")
name: str
class Annotation(Activity):
metadataType: Optional[str] = Field(default="https://w3id.org/EVI#Annotation", alias="@type")
additionalType: Optional[str] = Field(default=ANNOTATION_TYPE)
createdBy: str
description: str = Field(min_length=10)
dateCreated: str
associatedPublication: Optional[str] = Field(default=None)
usedDataset: Optional[List[IdentifierValue]] = Field(default=[])
generated: Optional[List[IdentifierValue]] = Field(default=[])
isPartOf: Optional[List[IdentifierValue]] = Field(default=[])

model_config = ConfigDict(extra="allow")
15 changes: 4 additions & 11 deletions fairscape_models/computation.py
Original file line number Diff line number Diff line change
@@ -1,23 +1,16 @@
from pydantic import BaseModel, Field, ConfigDict
from pydantic import Field, ConfigDict
from typing import Optional, List, Union

from fairscape_models.fairscape_base import IdentifierValue, COMPUTATION_TYPE
from fairscape_models.activity import Activity

class Computation(BaseModel):
guid: str = Field(alias="@id")
name: str
metadataType: Optional[str] = Field(default="https://w3id.org/EVI#Computation",alias="@type")
class Computation(Activity):
metadataType: Optional[str] = Field(default="https://w3id.org/EVI#Computation", alias="@type")
additionalType: Optional[str] = Field(default=COMPUTATION_TYPE)
runBy: str
description: str = Field(min_length=10)
dateCreated: str
associatedPublication: Optional[str] = Field(default=None)
additionalDocumentation: Optional[str] = Field(default=None)
command: Optional[Union[List[str], str]] = Field(default=None)
usedSoftware: Optional[List[IdentifierValue]] = Field(default=[])
usedMLModel: Optional[List[IdentifierValue]] = Field(default=[])
usedDataset: Optional[List[IdentifierValue]] = Field(default=[])
generated: Optional[List[IdentifierValue]] = Field(default=[])
isPartOf: Optional[List[IdentifierValue]] = Field(default=[])

model_config = ConfigDict(extra="allow")
23 changes: 6 additions & 17 deletions fairscape_models/dataset.py
Original file line number Diff line number Diff line change
@@ -1,30 +1,19 @@
from pydantic import BaseModel, Field, ConfigDict, AliasChoices, field_validator
from pydantic import Field, ConfigDict, AliasChoices
from typing import Optional, List, Union

from fairscape_models.fairscape_base import IdentifierValue, DATASET_TYPE
from fairscape_models.digital_object import DigitalObject

class Dataset(BaseModel):
guid: str = Field(alias="@id")
name: str
metadataType: Optional[str] = Field(default="https://w3id.org/EVI#Dataset",alias="@type")
class Dataset(DigitalObject):
metadataType: Optional[str] = Field(default="https://w3id.org/EVI#Dataset", alias="@type")
additionalType: Optional[str] = Field(default=DATASET_TYPE)
author: Union[str, List[str]]
datePublished: str = Field(...)
version: str = Field(default="0.1.0")
description: str = Field(min_length=10)
keywords: List[str] = Field(...)
associatedPublication: Optional[Union[str,List[str]]] = Field(default=None)
additionalDocumentation: Optional[str] = Field(default=None)
fileFormat: str = Field(alias="format")
dataSchema: Optional[IdentifierValue] = Field(
validation_alias=AliasChoices('evi:Schema', 'EVI:Schema', 'schema','evi:schema'),
validation_alias=AliasChoices('evi:Schema', 'EVI:Schema', 'schema', 'evi:schema'),
serialization_alias='evi:Schema',
default=None
)
generatedBy: Optional[Union[IdentifierValue, List[IdentifierValue]]] = Field(default=[])
derivedFrom: Optional[List[IdentifierValue]] = Field(default=[])
usedByComputation: Optional[List[IdentifierValue]] = Field(default=[])
contentUrl: Optional[Union[str, List[str]]] = Field(default=None)
isPartOf: Optional[List[IdentifierValue]] = Field(default=[])

model_config = ConfigDict(extra="allow")
derivedFrom: Optional[List[IdentifierValue]] = Field(default=[])
20 changes: 20 additions & 0 deletions fairscape_models/digital_object.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
from pydantic import BaseModel, Field, ConfigDict
from typing import Optional, List, Union

from fairscape_models.fairscape_base import IdentifierValue

class DigitalObject(BaseModel):
"""Base class for DigitalObject types (Dataset, Software, MLModel)"""
guid: str = Field(alias="@id")
name: str
metadataType: Optional[str] = Field(default=None, alias="@type")
author: Union[str, List[str]]
description: str = Field(min_length=10)
version: str = Field(default="0.1.0")
associatedPublication: Optional[Union[str, List[str]]] = Field(default=None)
additionalDocumentation: Optional[str] = Field(default=None)
contentUrl: Optional[Union[str, List[str]]] = Field(default=None)
isPartOf: Optional[List[IdentifierValue]] = Field(default=[])
usedByComputation: Optional[List[IdentifierValue]] = Field(default=[])

model_config = ConfigDict(extra="allow")
26 changes: 10 additions & 16 deletions fairscape_models/experiment.py
Original file line number Diff line number Diff line change
@@ -1,21 +1,15 @@
from pydantic import BaseModel, Field, ConfigDict
from typing import Optional, List, Union
from pydantic import Field, ConfigDict
from typing import Optional, List
from fairscape_models.fairscape_base import IdentifierValue
from fairscape_models.activity import Activity

class Experiment(BaseModel):
guid: str = Field(alias="@id")
name: str
class Experiment(Activity):
metadataType: Optional[str] = Field(default="https://w3id.org/EVI#Experiment", alias="@type")
experimentType: str
experimentType: str
runBy: str
description: str = Field(min_length=10)
datePerformed: str
associatedPublication: Optional[str] = Field(default=None)
protocol: Optional[str] = Field(default=None)
usedInstrument: Optional[List[IdentifierValue]] = Field(default=[])
usedSample: Optional[List[IdentifierValue]] = Field(default=[])
datePerformed: str
protocol: Optional[str] = Field(default=None)
usedInstrument: Optional[List[IdentifierValue]] = Field(default=[])
usedSample: Optional[List[IdentifierValue]] = Field(default=[])
usedTreatment: Optional[List[IdentifierValue]] = Field(default=[])
usedStain: Optional[List[IdentifierValue]] = Field(default=[])
generated: Optional[List[IdentifierValue]] = Field(default=[])
isPartOf: Optional[List[IdentifierValue]] = Field(default=[])
model_config = ConfigDict(extra="allow")
usedStain: Optional[List[IdentifierValue]] = Field(default=[])
2 changes: 2 additions & 0 deletions fairscape_models/fairscape_base.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
DATASET_TYPE = "Dataset"
DATASET_CONTAINER_TYPE = "DatasetContainer"
SOFTWARE_TYPE = "Software"
MLMODEL_TYPE = "MLModel"
COMPUTATION_TYPE = "Computation"
ANNOTATION_TYPE = "Annotation"
ROCRATE_TYPE = "ROCrate"
Expand Down Expand Up @@ -58,6 +59,7 @@
class ClassType(str, Enum):
DATASET = 'Dataset'
SOFTWARE = 'Software'
MLMODEL = 'MLModel'
COMPUTATION = 'Computation'
ANNOTATION = 'Annotation'
SCHEMA = 'Schema'
Expand Down
14 changes: 14 additions & 0 deletions fairscape_models/mlmodel.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
from pydantic import Field, ConfigDict
from typing import Optional, List, Union

from fairscape_models.fairscape_base import IdentifierValue, MLMODEL_TYPE
from fairscape_models.digital_object import DigitalObject

class MLModel(DigitalObject):
metadataType: Optional[str] = Field(default="https://w3id.org/EVI#MLModel", alias="@type")
additionalType: Optional[str] = Field(default=MLMODEL_TYPE)
dateModified: Optional[str] = Field(default=None)
fileFormat: str = Field(alias="format")
modelTask: Optional[str] = Field(default=None)
modelArchitecture: Optional[str] = Field(default=None)
trainedOn: Optional[List[IdentifierValue]] = Field(default=[])
93 changes: 86 additions & 7 deletions fairscape_models/rocrate.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,11 @@
from fairscape_models.biochem_entity import BioChemEntity
from fairscape_models.medical_condition import MedicalCondition
from fairscape_models.computation import Computation
from fairscape_models.annotation import Annotation
from fairscape_models.experiment import Experiment
from fairscape_models.dataset import Dataset
from fairscape_models.software import Software
from fairscape_models.mlmodel import MLModel
from fairscape_models.patient import Patient

class GenericMetadataElem(BaseModel):
Expand Down Expand Up @@ -127,7 +130,10 @@ class ROCrateV1_2(BaseModel):
metadataGraph: List[Union[
Dataset,
Software,
MLModel,
Computation,
Annotation,
Experiment,
ROCrateMetadataElem,
ROCrateMetadataFileElem,
Schema,
Expand All @@ -146,7 +152,10 @@ def validate_metadata_graph(cls, values: Dict[str, Any]) -> Dict[str, Any]:
type_map = {
"Dataset": Dataset,
"Software": Software,
"MLModel": MLModel,
"Computation": Computation,
"Annotation": Annotation,
"Experiment": Experiment,
"CreativeWork": ROCrateMetadataFileElem,
"Schema": Schema,
"BioChemEntity": BioChemEntity,
Expand Down Expand Up @@ -206,8 +215,6 @@ def cleanIdentifierList(identifier_list):
"""Helper to clean a list of identifiers"""
if identifier_list is None:
return
if not isinstance(identifier_list, list):
return
for item in identifier_list:
if hasattr(item, 'guid') and isinstance(item.guid, str) and "ark:" in item.guid:
cleanGUID(item)
Expand Down Expand Up @@ -241,6 +248,11 @@ def cleanIdentifierUnion(identifier_union):
if isinstance(elem, Software):
cleanIdentifierList(elem.usedByComputation)

if isinstance(elem, MLModel):
cleanIdentifierList(elem.usedByComputation)

cleanIdentifierList(elem.trainedOn)

if isinstance(elem, Computation):

cleanIdentifierList(elem.usedDataset)
Expand All @@ -249,6 +261,26 @@ def cleanIdentifierUnion(identifier_union):

cleanIdentifierList(elem.usedSoftware)

cleanIdentifierList(elem.usedMLModel)

if isinstance(elem, Annotation):

cleanIdentifierList(elem.usedDataset)

cleanIdentifierList(elem.generated)

if isinstance(elem, Experiment):

cleanIdentifierList(elem.usedInstrument)

cleanIdentifierList(elem.usedSample)

cleanIdentifierList(elem.usedTreatment)

cleanIdentifierList(elem.usedStain)

cleanIdentifierList(elem.generated)

def getCrateMetadata(self)-> ROCrateMetadataElem:
""" Filter the Metadata Graph for the Metadata Element Describing the Toplevel ROCrate

Expand Down Expand Up @@ -316,7 +348,49 @@ def getComputations(self) -> List[Computation]:
:rtype List[fairscape_mds.models.rocrate.Computation]
"""
filterResults = list(filter(
lambda x: isinstance(x, Computation),
lambda x: isinstance(x, Computation),
self.metadataGraph
))

return filterResults

def getAnnotations(self) -> List[Annotation]:
""" Filter the Metadata Graph for Annotation Elements

:param self
:return: All Annotation metadata records within the ROCrate
:rtype List[fairscape_mds.models.rocrate.Annotation]
"""
filterResults = list(filter(
lambda x: isinstance(x, Annotation),
self.metadataGraph
))

return filterResults

def getExperiments(self) -> List[Experiment]:
""" Filter the Metadata Graph for Experiment Elements

:param self
:return: All Experiment metadata records within the ROCrate
:rtype List[fairscape_mds.models.rocrate.Experiment]
"""
filterResults = list(filter(
lambda x: isinstance(x, Experiment),
self.metadataGraph
))

return filterResults

def getMLModels(self) -> List[MLModel]:
""" Filter the Metadata Graph for MLModel Elements

:param self
:return: All MLModel metadata records within the ROCrate
:rtype List[fairscape_mds.models.rocrate.MLModel]
"""
filterResults = list(filter(
lambda x: isinstance(x, MLModel),
self.metadataGraph
))

Expand Down Expand Up @@ -354,13 +428,18 @@ def getMedicalConditions(self) -> List[MedicalCondition]:


def getEVIElements(self) -> List[Union[
Computation,
Dataset,
Software,
Computation,
Annotation,
Experiment,
Dataset,
Software,
MLModel,
Schema,
BioChemEntity,
MedicalCondition
]]:
""" Query the metadata graph for elements which require minting identifiers
"""
return self.getDatasets() + self.getSoftware() + self.getComputations() + self.getSchemas()
return (self.getDatasets() + self.getSoftware() + self.getMLModels() +
self.getComputations() + self.getAnnotations() + self.getExperiments() +
self.getSchemas())
19 changes: 4 additions & 15 deletions fairscape_models/software.py
Original file line number Diff line number Diff line change
@@ -1,22 +1,11 @@
from pydantic import BaseModel, Field, ConfigDict
from typing import Optional, List, Union
from pydantic import Field, ConfigDict
from typing import Optional, List

from fairscape_models.fairscape_base import IdentifierValue, SOFTWARE_TYPE
from fairscape_models.digital_object import DigitalObject

class Software(BaseModel):
guid: str = Field(alias="@id")
name: str
class Software(DigitalObject):
metadataType: Optional[str] = Field(default="https://w3id.org/EVI#Software", alias="@type")
additionalType: Optional[str] = Field(default=SOFTWARE_TYPE)
author: str = Field(min_length=4)
dateModified: Optional[str]
version: str = Field(default="0.1.0")
description: str = Field(min_length=10)
associatedPublication: Optional[str] = Field(default=None)
additionalDocumentation: Optional[str] = Field(default=None)
fileFormat: str = Field(title="fileFormat", alias="format")
usedByComputation: Optional[List[IdentifierValue]] = Field(default=[])
contentUrl: Optional[str] = Field(default=None)
isPartOf: Optional[List[IdentifierValue]] = Field(default=[])

model_config = ConfigDict(extra="allow")
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"

[project]
name = "fairscape-models"
version = "1.0.15"
version = "1.0.19"
description = "Fairscape pydantic models"
readme = "README.md"
authors = [
Expand Down
Loading