Basic use of entities#
Load an entity#
A test entity:
description: A bare-bones entity for testing.
dimensions:
N: Number of elements.
identity: http://onto-ns.com/s7/0.1.0/MolecularSpecies
properties:
atom:
description: An atom.
shape:
- N
type: string
electrons:
description: Number of electrons.
shape:
- N
type: int
mass:
description: Atomic mass.
shape:
- N
type: float
unit: amu
radius:
description: Atomic radius.
shape:
- N
type: float
unit: Å
Load the entity as a SOFT7Entity
class.
from s7.pydantic_models.soft7_entity import SOFT7Entity
entity = SOFT7Entity(**RAW_TEST_ENTITY)
print(entity)
identity=AnyHttpUrl('http://onto-ns.com/s7/0.1.0/MolecularSpecies') description='A bare-bones entity for testing.' dimensions={'N': 'Number of elements.'} properties={'atom': SOFT7EntityProperty(type='string', description='An atom.', shape=['N'], unit=None), 'electrons': SOFT7EntityProperty(type='int', description='Number of electrons.', shape=['N'], unit=None), 'mass': SOFT7EntityProperty(type='float', description='Atomic mass.', shape=['N'], unit='amu'), 'radius': SOFT7EntityProperty(type='float', description='Atomic radius.', shape=['N'], unit='Å')}
Generate a Python class from the entity#
Generate a custom Python class based on the entity. It will be possible to create instances of this class, based on the properties and dimensions of the entity.
from s7.factories import create_entity
MolecularSpecies = create_entity(entity)
print(f"Class: {MolecularSpecies}")
print(MolecularSpecies.__doc__)
print("JSON Schema:")
print(MolecularSpecies.model_json_schema())
Class: <class 's7.factories.generated_classes.MolecularSpeciesEntity'>
MolecularSpecies
A bare-bones entity for testing.
SOFT7 Entity Metadata:
Identity: http://onto-ns.com/s7/0.1.0/MolecularSpecies
Namespace: http://onto-ns.com/s7
Version: 0.1.0
Name: MolecularSpecies
Dimensions:
N (int): Number of elements.
Attributes:
atom (list[str]): An atom.
electrons (list[int]): Number of electrons.
mass (list[float]): Atomic mass.
radius (list[float]): Atomic radius.
JSON Schema:
{'$defs': {'MolecularSpeciesEntityDimensions': {'additionalProperties': False, 'description': 'MolecularSpeciesDimensions\n\nDimensions for the MolecularSpecies SOFT7 data source.\n\nSOFT7 Entity: http://onto-ns.com/s7/0.1.0/MolecularSpecies\n\nAttributes:\n N (int): Number of elements.', 'properties': {'N': {'anyOf': [{'type': 'integer'}, {'type': 'null'}], 'default': None, 'description': 'Number of elements.', 'title': 'N'}}, 'title': 'MolecularSpeciesEntityDimensions', 'type': 'object'}, 'MolecularSpeciesEntityProperties': {'additionalProperties': False, 'description': 'MolecularSpeciesProperties\n\nProperties for the MolecularSpecies SOFT7 data source.\n\nSOFT7 Entity: http://onto-ns.com/s7/0.1.0/MolecularSpecies\n\nAttributes:\n atom (list[str]): An atom.\n electrons (list[int]): Number of electrons.\n mass (list[float]): Atomic mass.\n radius (list[float]): Atomic radius.', 'properties': {'atom': {'anyOf': [{'items': {'type': 'string'}, 'type': 'array'}, {'type': 'null'}], 'default': None, 'description': 'An atom.', 'title': 'atom', 'x-soft7-shape': ['N']}, 'electrons': {'anyOf': [{'items': {'type': 'integer'}, 'type': 'array'}, {'type': 'null'}], 'default': None, 'description': 'Number of electrons.', 'title': 'electrons', 'x-soft7-shape': ['N']}, 'mass': {'anyOf': [{'items': {'type': 'number'}, 'type': 'array'}, {'type': 'null'}], 'default': None, 'description': 'Atomic mass.', 'title': 'mass', 'x-soft7-shape': ['N'], 'x-soft7-unit': 'amu'}, 'radius': {'anyOf': [{'items': {'type': 'number'}, 'type': 'array'}, {'type': 'null'}], 'default': None, 'description': 'Atomic radius.', 'title': 'radius', 'x-soft7-shape': ['N'], 'x-soft7-unit': 'Å'}}, 'title': 'MolecularSpeciesEntityProperties', 'type': 'object'}}, 'additionalProperties': False, 'description': 'MolecularSpecies\n\nA bare-bones entity for testing.\n\nSOFT7 Entity Metadata:\n Identity: http://onto-ns.com/s7/0.1.0/MolecularSpecies\n\n Namespace: http://onto-ns.com/s7\n Version: 0.1.0\n Name: MolecularSpecies\n\nDimensions:\n N (int): Number of elements.\n\nAttributes:\n atom (list[str]): An atom.\n electrons (list[int]): Number of electrons.\n mass (list[float]): Atomic mass.\n radius (list[float]): Atomic radius.', 'properties': {'dimensions': {'$ref': '#/$defs/MolecularSpeciesEntityDimensions', 'description': 'The MolecularSpecies SOFT7 entity dimensions.'}, 'properties': {'$ref': '#/$defs/MolecularSpeciesEntityProperties', 'description': 'The MolecularSpecies SOFT7 entity properties.'}}, 'required': ['dimensions', 'properties'], 'title': 'MolecularSpeciesEntity', 'type': 'object'}
The entity is still accessible under the entity
class attribute:
print(MolecularSpecies.entity)
identity=AnyHttpUrl('http://onto-ns.com/s7/0.1.0/MolecularSpecies') description='A bare-bones entity for testing.' dimensions={'N': 'Number of elements.'} properties={'atom': SOFT7EntityProperty(type='string', description='An atom.', shape=['N'], unit=None), 'electrons': SOFT7EntityProperty(type='int', description='Number of electrons.', shape=['N'], unit=None), 'mass': SOFT7EntityProperty(type='float', description='Atomic mass.', shape=['N'], unit='amu'), 'radius': SOFT7EntityProperty(type='float', description='Atomic radius.', shape=['N'], unit='Å')}
When generating a new class, it can be imported from the s7.factories.generated_classes
module:
from s7.factories import generated_classes
# Here we are printing all the classes that were generated by the factory.
# More specifically, we are printing all the classes that are in the generated_classes
# module.
print([_ for _ in generated_classes.__dict__.values() if isinstance(_, type)])
[<class 's7.factories.generated_classes.MolecularSpeciesEntityDimensions'>, <class 's7.factories.generated_classes.MolecularSpeciesEntityProperties'>, <class 's7.factories.generated_classes.MolecularSpeciesEntity'>]
Note that along with the generated class (here MolecularSpeciesEntity
), two more classes are generated to represent the entity’s properties (here MolecularSpeciesEntityProperties
) and dimensions (here MolecularSpeciesEntityDimensions
).
One can even import the named entity classes directly from the s7.factories.generated_classes
module:
from s7.factories.generated_classes import MolecularSpeciesEntity
print(MolecularSpeciesEntity)
print(
"The imported 'MolecularSpeciesEntity' class is exactly the same as the previously "
f"generated 'MolecularSpecies' class: {MolecularSpeciesEntity == MolecularSpecies}"
)
print(MolecularSpeciesEntity.__doc__)
print(MolecularSpeciesEntity.entity)
<class 's7.factories.generated_classes.MolecularSpeciesEntity'>
The imported 'MolecularSpeciesEntity' class is exactly the same as the previously generated 'MolecularSpecies' class: True
MolecularSpecies
A bare-bones entity for testing.
SOFT7 Entity Metadata:
Identity: http://onto-ns.com/s7/0.1.0/MolecularSpecies
Namespace: http://onto-ns.com/s7
Version: 0.1.0
Name: MolecularSpecies
Dimensions:
N (int): Number of elements.
Attributes:
atom (list[str]): An atom.
electrons (list[int]): Number of electrons.
mass (list[float]): Atomic mass.
radius (list[float]): Atomic radius.
identity=AnyHttpUrl('http://onto-ns.com/s7/0.1.0/MolecularSpecies') description='A bare-bones entity for testing.' dimensions={'N': 'Number of elements.'} properties={'atom': SOFT7EntityProperty(type='string', description='An atom.', shape=['N'], unit=None), 'electrons': SOFT7EntityProperty(type='int', description='Number of electrons.', shape=['N'], unit=None), 'mass': SOFT7EntityProperty(type='float', description='Atomic mass.', shape=['N'], unit='amu'), 'radius': SOFT7EntityProperty(type='float', description='Atomic radius.', shape=['N'], unit='Å')}
Create an instance of the custom class#
Load test data that has been pre-formatted to match the data structure of an entity, i.e., it has been written as a dictionary/object with the top keys dimensions
and properties
.
TEST_ENTITY_DATA_PATH = STATIC_TEST_DIR / "soft_datasource_entity_test_data.yaml"
RAW_TEST_ENTITY_DATA: dict[str, Any] = yaml.safe_load(TEST_ENTITY_DATA_PATH.read_text())
print(yaml.safe_dump(RAW_TEST_ENTITY_DATA))
dimensions:
N: 3
properties:
atom:
- H
- He
- Li
electrons:
- 1
- 2
- 3
mass:
- 1.008
- 4.0026
- 6.94
radius:
- 0.37
- 0.32
- 1.45
entity_data = MolecularSpecies(**RAW_TEST_ENTITY_DATA)
print(entity_data)
dimensions=MolecularSpeciesEntityDimensions(N=3) properties=MolecularSpeciesEntityProperties(atom=['H', 'He', 'Li'], electrons=[1, 2, 3], mass=[1.008, 4.0026, 6.94], radius=[0.37, 0.32, 1.45])
While the entity is still accessible under the entity
class attribute for the instance, when serialized to JSON or a dictionary utilizing the standard serialization methods for a pydantic model, only dimensions
and properties
are included:
print("Python dictionary:")
print(entity_data.model_dump())
print("JSON:")
print_json(entity_data.model_dump_json())
Python dictionary:
{'dimensions': {'N': 3}, 'properties': {'atom': ['H', 'He', 'Li'], 'electrons': [1, 2, 3], 'mass': [1.008, 4.0026, 6.94], 'radius': [0.37, 0.32, 1.45]}}
JSON:
{"dimensions":{"N":3},"properties":{"atom":["H","He","Li"],"electrons":[1,2,3],"mass":[1.008,4.0026,6.94],"radius":[0.37,0.32,1.45]}}