How to express computed properties in linkml and get the result when instantiating?

47 Views Asked by At

I created a linkml model named PersonModel:

id: PersonModel
    name: Person Model
    prefixes:
      - prefix: person
        uri: http://example.org/person/
    default_prefix: person
    types:
      - name: Person
        description: A person entity
        slots:
          - name: name
            range: string
          - name: weight
            range: decimal
          - name: height
            range: decimal
          - name: BMI
            range: decimal
            formula: "weight / (height * height)"

There is now an instance object file as bobInstance.yaml:

id: bob
type: Person
name: Bob
weight: 67
height: 1.7

Is my expression of BMI in PersonModel correct? Now how to use python to validate the compliance of bobInstance and calculate the value of bob.BMI? Someone told me to use BMI = eval(BMI_formula),But I haven't gotten the correct result. How should I write this python file?

1

There are 1 best solutions below

0
Chris Mungall On

Here is a modified version of your schema:

id: https://stackoverflow.com/questions/77122653/how-to-validate-data-files-with-linkml-model
name: how-to-validate-data-files-with-linkml-model
prefixes:
  linkml: https://w3id.org/linkml/
  ex: https://example.org/
default_prefix: ex
imports:
  - linkml:types
classes:
  Person:
    attributes:
      name:
        required: true
    
      weight:
        range: float
    
      height:
        range: float
    
      bmi:
        range: float
        equals_expression: "weight / (height * height)"

Note the correct slot is equals_expression

I also modified decimal to float for simplicity

Assuming you have converted the above to dataclasses using the Python generator, into a path datamodel/person.yaml you can then do the following:

from datamodel.person import Person
bob = Person(name="Bob", weight=67, height= 1.7)

from linkml_runtime.utils.schemaview import SchemaView
sv = SchemaView("datamodel/person.yaml")

from linkml_runtime.utils.inference_utils import infer_all_slot_values
from linkml_runtime.utils.inference_utils import Config

infer_all_slot_values(bob, schemaview=sv, config=Config(use_expressions=True))
print(bob)

You will get:

Person(name='Bob', weight=67.0, height=1.7, bmi=23.18339100346021)

Note that by default, the inference methods won't use expressions, you need to pass in a config option with Config(use_expressions=True)

See: