Annotations#

Background#

The LinkML model provides a fixed set of metamodel slots which can be applied to any schema element.

Examples of these are:

  • description - a human readable description of the element

  • comments - a human readable comment about the element

  • aliases - a set of alternative names for the element

  • deprecated - a boolean flag indicating that the element is deprecated

  • seeAlso - a set of URIs that provide additional information about the element

If you attempt to assign a slot that is not in the metamodel, you will get an error. For example, if you wanted to add a review slot to the Person class like this:

classes:
  Person:
    description: A person, living or dead
    review: A very useful class that is well defined
    attributes:
      id: ...

This will result in an error, because review is not a metamodel slot.

This conformance to a single metamodel can be useful for ensuring consistency and interoperability among LinkML schemas. However, it can be too constraining in some cases. To get around this, the LinkML metamodel has a generic annotations slot that can be used to assign arbitrary tags and values to any schema element.

Adding your own annotations#

In the above case, we can add the review annotation to the Person class like this:

classes:
  Person:
    annotations:
      review: A very useful class that is well defined
      ...

Note that in the underlying metamodel, the range of annotations is an Annotation class, which has two slots: tag and value. This is usually written in compact form as tag: value, as in the above.

Note also that prior to LinkML 1.6, the range of the annotation value was string, but in 1.6 and higher, the range can be any object.

Annotation validation#

By default, all annotation tags and values are valid. Feel free to add whatever annotations you like to any schema element - classes, enums, permissible values, slots, even schemas themselves.

However, if you want to restrict the set of valid annotations, you can do this starting from LinkMK 1.6, where you can treat annotation tags as if they were slots in your own metamodel extension.

This is done by adding an instantiates slot-value assignment onto any schema element. The range of the instantiates slot is a uriorcurie that references a class that serves as a metamodel extension class.

For example, given our example schema fragment, we can add an instantiates slot to the Person class, stating that this class is an instance of the Reviewable metamodel extension class:

classes:
  Person:
    instantiates: 
      - mymetamodel:Reviewable
    annotations:
      review: A very useful class that is well defined
      ...

This metaclass extension can live in the same schema, or in a different schema. This is why they are referenced by uriorcurie rather than a local name.

The Reviewable class might be defined as follows:

id: https://example.org/mymetamodel/
name: mymetamodel
...
classes:
  Reviewable:
    class_uri: mymetamodel:Reviewable
    attributes:
      review:
        description: an expert review of a schema element
        range: string

This can be thought of as a schema element mixin class - the class defines the extra slots that can be attached to schema elements via annotations.

Other schema elements can also instantiate the Reviewable class:

classes:
  Person:
    instantiates: 
      - mymetamodel:Reviewable
    annotations:
      review: A very useful class that is well defined
      ...
    attributes:
      name:
        description: the name of a person
        instantiates: mymetamodel:Reviewable
        annotations:
          review: A very useful attribute that is well defined
          ...

Note that here the attributes section of the Person definition is the attributes that an instance of Person may have. The annotations section pertains to the class Person, not instances.

Validation of annotations#

If a schema element does not instantiate a metamodel extension class, then any annotation tag is valid. (this is already the case for all pre 1.6 schemas, since the instantiates slot is not defined in previous versions of the metamodel).

If a schema element does instantiate a metamodel extension class, then the set of valid annotation tags should conform to the slots defined in the metamodel extension class, as if the annotation tags were first-class slots, and instantiates value was a mixin.

However, this is not yet supported in the current LinkML validator, so using instantiates indicates your intent, but does not yet enforce validation.

Other uses of instantiates#

The instantiates slot can also be used constrain rather than extend.

For example, to define a strict metamodel element that must have a description:

id: https://example.org/mymetamodel/
name: mymetamodel
...
classes:
  StrictElement:
    class_uri: mymetamodel:StrictClassDefinition
    slot_usage:
      description:
        required: true

Any schema element that instantiates StrictElement must have a description:

classes:
  Person:
    instantiates: 
      - mymetamodel:StrictElement
    description: A person, living or dead   ## must be provided