Schema language¶
The NOMAD Metainfo is the schema language used to define all data in NOMAD. This page is the authoritative reference for the language itself: the attributes you can put on a definition, the quantity types you can declare, and the conventions definitions should follow.
For task-oriented instructions, see How-to guides > Work with schemas. For the concepts behind the language, see Explanation > Data structure.
Quantity types¶
The type of a quantity determines what values it accepts, how they are validated and converted,
and how they are serialized. Type names are case insensitive.
| YAML spelling | Python spelling | Runtime type | Serialized form | Notes |
|---|---|---|---|---|
string, str |
str |
str |
JSON string | |
boolean, bool |
bool |
bool |
JSON boolean | |
int |
int |
32-bit integer | JSON number | Bare int is 32-bit. Use np.int64 for wider values. |
float |
float |
64-bit float | JSON number | |
complex |
complex |
complex |
{"re": ..., "im": ...} |
|
np.int8, np.int16, np.int32, np.int64 |
same | NumPy integer | JSON number or nested array | |
np.float16, np.float32, np.float64 |
same | NumPy float | JSON number or nested array | |
np.complex128 |
same | NumPy complex | {"re": ..., "im": ...} |
|
Datetime |
Datetime |
datetime.datetime (UTC) |
ISO 8601 string | |
{type_kind: Enum, type_data: [...]} |
MEnum('a', 'b') |
str |
JSON string | Use type_data to list the allowed values. |
JSON |
JSON |
dict |
JSON object | Arbitrary nested JSON. |
Bytes |
Bytes |
bytes |
base64 string | The Python bytes type itself is not accepted; use the name. |
URL |
URL |
str |
JSON string | |
File |
File |
str |
JSON string | A path relative to the upload. |
Capitalized |
Capitalized |
str |
JSON string | Capitalizes the first letter on assignment. |
Any |
Any |
any | as-is | No validation. |
User |
User |
NOMAD user | user id string | |
Author |
Author |
Author |
JSON object | |
*<section name>* |
MySection |
section instance or MProxy |
reference URL | See Work with schemas > Link data with references. |
{type_kind: quantity_reference, type_data: <Section>/<quantity>} |
MySection.my_quantity |
the target quantity's value | reference URL ending in the quantity name | Assign the section that holds the quantity, not the value. |
What you can write in type¶
Types are resolved by nomad.metainfo.data_type.normalize_type(), which accepts:
- Strings —
'string','boolean','json','datetime','url','file','any','capitalized','bytes','user','author', or any builtin name such as'int'and'float'. - NumPy names — any
np.<dtype>ornumpy.<dtype>string, e.g.'np.float64'. - Python types —
str,bool,int,float,complex,datetime.datetime. Note that the Pythonbytestype is not accepted, only the string'bytes'. - NumPy types —
np.int16,np.float32,np.complex128,np.bool_, andnp.dtype(...)instances. - Section definitions — a section class or its
m_def, making a section reference. - Quantity definitions —
MySection.my_quantity, making a quantity reference. - Dictionaries — the
{'type_kind': ..., 'type_data': ...}form produced when a definition is serialized. This is howMEnumand custom types round-trip, and also how references are spelled:{'type_kind': 'reference'}for a section and{'type_kind': 'quantity_reference'}for a quantity. The dictionary is the only way to write a quantity reference outside Python, because a bare string is always resolved as a section reference.
To add a type that is not in this list, see How-to guides > Develop the core software > Add a new type.
Shapes¶
The shape of a quantity is a list of dimensions. An empty list (or no shape) is a scalar, one
dimension is a vector, two a matrix, and so on. Each dimension may be:
- an integer, for a fixed size — a 3x3 matrix is
[3, 3]; - the string
'*', for an arbitrary size — a list is['*']; - the name of a sibling quantity with an integer type, e.g.
['number_of_atoms', 3].
Note
shape works the same way for every quantity type, including reference types. For a reference
type it describes the dimensionality of the references, not of the referenced data.
Value coercion¶
Values are converted to the declared type and unit on assignment, using NumPy and Pint. Assigning a Pint quantity extracts the magnitude and converts it to the declared unit.
The rule for array quantities is:
- if the
typeis a NumPy type, such asnp.int32, the value becomes a NumPy array; - if the
typeis a Python type, such asfloatorint, the value becomes a (nested) Python list.
Units are given as strings parsed by Pint — simple units or expressions, e.g. m, meter, mm,
m/s, m/s**2. Uploaded schemas may use any unit; the built-in NOMAD schema uses SI units only.
See Work with schemas > Work with units.
Reference forms¶
A reference quantity is serialized as a URL. An inter-entry reference has two parts,
<entry>#<path>: a path or URL denoting the target entry, and a path within that entry's subsection
hierarchy. The path usually ends at a section; for a quantity reference it ends at the target
quantity's name. The host and path parts correspond to the
NOMAD API.
| Example reference | Meaning |
|---|---|
#/data/processes/0 |
A section within the same archive. |
#/data/instruments/0/name |
A quantity within the same archive, i.e. a quantity reference. |
/run/0/calculation/1 |
A section within the same archive (legacy form). |
Instrument |
A section definition in the same archive. Targets section definitions only. |
nomad.datamodel.metainfo.workflow |
A section definition written in Python as part of the NOMAD code. Targets section definitions only. |
../upload/raw/data.archive.yaml#/data |
A section in a different .archive.yaml file of the same upload. |
../upload/archive/mainfile/data.archive.yaml#/data |
A section in a processed archive, given by the entry mainfile. |
../upload/archive/zxhS43h2kqHsVDqMboiP9cULrS_v#/data |
A section in a processed archive, given by entry id. |
../uploads/zxhS43h2kqHsVDqMboiP9cULrS_v/raw/data.archive.yaml#/data |
A section in an entry of a different upload. |
/entries/{entry_id}/archive#/data/processes/0 |
A section in a different entry on the same NOMAD installation. |
/uploads/{upload_id}/archive/{entry_id}#/data/processes/0 |
The same, addressed by upload. |
https://mylab.eu/oasis/api/v1/uploads/{upload_id}/raw/data.archive.yaml#/data |
A section in a different NOMAD installation. |
Writing type: Instrument or section: Instrument in a schema is itself a reference — a convenience
form standing in for the otherwise cryptic #/definitions/sections/0. This is also what m_def is
for: whenever the section definition cannot be worked out from the subsection that contains it,
m_def names it explicitly.
Naming conventions¶
- Section definitions use
UpperCamelCase, e.g.MySection,PvdEvaporation. - Quantities and subsections use
lower_snake_case, e.g.chamber_pressure,data_file. - Prefer subsections over inheritance when adding specific quantities to a general section. For example, the
workflowsection contains ageometry_optimizationsubsection for the quantities that only apply to geometry optimizations.
These conventions apply equally to YAML and Python schemas. In Python they are not optional: a definition takes its name from the Python class or attribute name, so it must be a valid identifier.
Where definitions live¶
The nomad-lab package defines the Metainfo in three modules:
nomad.metainfo— the schema language itself, including its self-referencing schema. This is the package rendered below.nomad.datamodel— the root sectionEntryArchiveand themetadatasection holding administrative metadata.nomad.datamodel.metainfo— the central, method-specific (but not parser-specific) definitions that are shared across parsers.
Serialization options¶
m_to_dict() converts a section instance to a plain dictionary. The options you are most likely to
need:
| Option | Effect |
|---|---|
with_meta |
Include m_def, and m_parent_index/m_parent_sub_section where applicable. |
with_def_id |
Include the definition id of each definition. |
include_defaults |
Include quantities that still hold their default value. |
include_derived |
Include derived quantities. |
resolve_references |
Replace references with what they point to — the target section, or the target value for a quantity reference — instead of reference URLs. |
categories |
Only include definitions in the given categories. |
include, exclude |
Filter properties by a predicate. |
transform |
Apply a function to every serialized value. |
m_from_dict() performs the inverse, reconstructing a section tree from a dictionary and validating
it against the schema. It is the mechanism behind the archive REST API.
Definition reference¶
The following is generated from the nomad.metainfo package, which defines the schema language in
terms of itself. Section, Quantity and SubSection are the definitions you use to write a
schema; Definition holds the attributes they all share.
Note
The more attribute is not listed below. It collects any additional keyword arguments passed to
a definition, so that schemas can carry custom metadata. Category is retained for backwards
compatibility but is deprecated — use annotations instead.
Definition¶
description: :class:Definition is the common base class for all metainfo definitions. All metainfo definitions (sections, quantities, subsections, packages, ...) share
some common properties.
properties:
| name | type | |
|---|---|---|
| name | str |
Each definition has a name. Names have to be valid Python identifier. They can contain letters, numbers and _, but must not start with a number. This also qualifies them as identifier in most storage formats, databases, makes them URL safe, etc.Names must be unique within the :class: Package or :class:Section that this definition is part of.By convention, we use capitalized CamelCase identifier to refer to sections definitions (i.e. section definitions are represented by Python classes), lower case snake_case identifier for variables that hold sections, and for properties (i.e. fields in a Python class) we typically use lower case snake_case identifier. Subsections are often prefixed with section_ to clearly separate subsections from quantities.Generally, you do not have to set this attribute manually, it will be derived from Python identifiers automatically. |
| label | str |
Each definition can have an optional label. Label are like names, but do not have to adhere to the Python identifier syntax. |
| description | str |
The description can be an arbitrary human-readable text that explains what a definition is about. For section definitions you do not have to set this manually as it will be derived from the classes doc string. Quantity and subsection descriptions can also be taken from the containing section class' doc-string Attributes: section. |
| links | str |
Each definition can be accompanied by a list of URLs. These should point to resources that further explain the definition. shape= ['0..*'] |
| categories | Category |
All metainfo definitions can be put into one or more categories. Categories allow to organize the definitions themselves. It is different from sections, which organize the data (e.g. quantity values) and not the definitions of data (e.g. quantities definitions). See :ref:metainfo-categories for more details.shape= ['0..*'], default=[] |
| deprecated | str |
If set this definition is marked deprecated. The value should be a string that describes how to replace the deprecated definition. |
| aliases | str |
A list of alternative names. For quantities and subsections these can be used to access the respective property with a different name from its containing section. Package aliases will be considered when resolving Python references, e.g. in m_def.shape= ['0..*'], default=[] |
| variable | bool |
A boolean that indicates this property has variable parts in its name. If this is set to true, all capital letters in the name can be replaced with arbitrary strings. However, variable names work similar to aliases and can be considered on-demand aliases. Other aliases and the defined name will work as well. Thus, variable names are only resolved at runtime by the Python interface and are not directly serialized. However, the variable name is set in a meta attribute m_source_name automatically for properties (but not attributes). Variable names are only implemented for Quantity, SubSection, Attribute.default= False |
| more | nomad.metainfo.data_type.JSON |
A dictionary that contains additional definition properties that are not part of the metainfo. Those can be passed as additional kwargs to definition constructors. The values must be JSON serializable. default= Complex object, default value not displayed. |
| all_attributes | nomad.metainfo.data_type.Any |
A virtual convenient property that provides all attributes as a dictionary from attribute name to attribute. This includes meta attributes (starting with m_) that are defined for all properties of the same kind (sub_section or quantity). |
| attributes | Attribute |
The attributes that can further qualify property values. sub-section, repeats |
Attribute¶
description: Attributes can be used to qualify all properties (subsections and quantities) with simple primitive values.
inherits from: Definition
properties:
| name | type | |
|---|---|---|
| type | nomad.metainfo.metainfo.QuantityType |
The type of the attribute. Needs to be a primitive type that is a subclass of Datatype. |
| shape | nomad.metainfo.data_type.Dimension |
The shape of the attribute. Need to be a list, similar to the shape of a quantity. shape= ['0..*'], default=[] |
Property¶
description: A common base-class for section properties: subsections and quantities.
inherits from: Definition
Section¶
description: Instances of the class :class:Section are created by writing Python classes that extend :class:MSection like this:
.. code-block:: python
class SectionName(BaseSection):
''' Section description '''
m_def = Section(**section_attributes)
quantity_name = Quantity(**quantity_attributes)
sub_section_name = SubSection(**sub_section_attributes)
We call such classes section classes. They are not the section definition, but just
representation of it in Python syntax. The section definition (in instance of :class:Section)
will be created for each of these classes and stored in the m_def property. See
:ref:metainfo-reflection for more details.
Most of the attributes for a :class:Section instance will be set automatically from
the section class:
inherits from: Definition
properties:
| name | type | |
|---|---|---|
| base_sections | Section |
shape=['0..*'], default=[] |
| extending_sections | Section |
shape=['0..*'], default=[] |
| extends_base_section | bool |
default=False |
| inheriting_sections | Section |
shape=['0..*'], default=[] |
| constraints | str |
shape=['0..*'], default=[] |
| event_handlers | nomad.metainfo.data_type.Callable |
Event handler are functions that get called when the section data is changed. There are two types of events: set and add_sub_section. The handler type is determined by the handler (i.e. function) name: on_set and on_add_sub_section. The handler arguments correspond to MSection.m_set (section, quantity_def, value) and MSection.m_add_sub_section (section, sub_section_def, sub_section). Handler are called after the respective action was performed. This quantity is automatically populated with handler from the section classes methods. If there is a method on_set or on_add_sub_section, it will be added as handler.shape= ['0..*'], default=[] |
| inherited_sections | nomad.metainfo.data_type.Any |
A helper attribute that gives direct and indirect base sections and extending sections including this section. These are all sections that this sections gets its properties from. |
| all_base_sections | nomad.metainfo.data_type.Any |
A helper attribute that gives direct and indirect base sections. |
| all_inheriting_sections | nomad.metainfo.data_type.Any |
A helper attribute that gives direct and indirect inheriting sections. |
| all_properties | nomad.metainfo.data_type.Any |
A helper attribute that gives all properties (subsection and quantity) definitions including inherited properties and properties from extending sections as a dictionary with names and definitions. |
| all_quantities | nomad.metainfo.data_type.Any |
A helper attribute that gives all quantity definition including inherited ones and ones from extending sections as a dictionary that maps names (strings) to :class:Quantity. |
| all_sub_sections | nomad.metainfo.data_type.Any |
A helper attribute that gives all subsection definition including inherited ones and ones from extending sections as a dictionary that maps names (strings) to :class:SubSection. |
| all_sub_sections_by_section | nomad.metainfo.data_type.Any |
A helper attribute that gives all subsection definition including inherited ones and ones from extending sections as a dictionary that maps section classes (i.e. Python class objects) to lists of :class:SubSection. |
| all_aliases | nomad.metainfo.data_type.Any |
A helper attribute that gives all aliases for all properties including inherited properties and properties form extending sections as a dictionary with aliases and the definitions. |
| all_inner_section_definitions | nomad.metainfo.data_type.Any |
A helper attribute that gives all inner_section_definitions including their aliases by name. |
| has_variable_names | nomad.metainfo.data_type.Any |
|
| path | nomad.metainfo.data_type.Any |
Shortest path from a root section to this section. This is not the path in the metainfo schema (m_path) but an archive path in potential data. |
| quantities | Quantity |
sub-section, repeats |
| sub_sections | SubSection |
sub-section, repeats |
| inner_section_definitions | Section |
sub-section, repeats |
Package¶
description: Packages organize metainfo definitions alongside Python modules Each Python module with metainfo Definition (explicitly or implicitly) has a member
m_package with an instance of this class. Definitions (categories, sections) in
Python modules are automatically added to the module's :class:Package.
Packages are not nested and rather have the fully qualified Python module name as
name.
This allows to inspect all definitions in a Python module and automatically puts
module name and docstring as :class:Package name and description.
Besides the regular :class:Definition attributes, packages can have the following
attributes:
inherits from: Definition
properties:
| name | type | |
|---|---|---|
| all_definitions | nomad.metainfo.data_type.Any |
A helper attribute that provides all section and category definitions by name and aliases. |
| dependencies | nomad.metainfo.data_type.Any |
All packages that provide definitions needed by this package. Being 'needed' includes categories, base sections, and referenced definitions. |
| section_definitions | Section |
All section definitions in this package as :class:Section objects.sub-section, repeats |
| category_definitions | Category |
All category definitions in this package as :class:Category objects.sub-section, repeats |
normalization without further documentation
Category¶
description: Categories allow to organize metainfo definitions (not metainfo data like sections do) Each definition, including categories themselves, can belong to a set of categories.
Categories therefore form a hierarchy of concepts that definitions can belong to, i.e.
they form a is a relationship.
inherits from: Definition
Quantity¶
description: To define quantities, instantiate :class:Quantity as a class attribute values in a section classes. The name of a quantity is automatically taken from its section class
attribute. You can provide all other attributes to the constructor with keyword arguments
See :ref:metainfo-sections to learn about section classes.
In Python terms, Quantity is a descriptor. Descriptors define how to get and
set attributes in a Python object. This allows us to use sections like regular
Python objects and quantity like regular Python attributes.
Each quantity must define a basic data type and a shape. The values of a quantity must fulfil the given type. The default shape is a single value. Quantities can also have physical units. Units are applied to all values.
inherits from: Property
properties:
| name | type | |
|---|---|---|
| type | nomad.metainfo.metainfo.QuantityType |
|
| shape | nomad.metainfo.data_type.Dimension |
shape=['0..*'], default=[] |
| unit | nomad.metainfo.data_type.Unit |
|
| dimensionality | str |
|
| default | nomad.metainfo.data_type.Any |
|
| derived | nomad.metainfo.data_type.Callable |
A Python callable that takes the containing section as input and outputs the value for this quantity. This quantity cannot be set directly, its value is only derived by the given callable. The callable is executed when this quantity is get. Derived quantities are always virtual. |
| cached | bool |
A bool indicating that derived values should be cached unless the underlying section has changed. default= False |
| virtual | bool |
A boolean that determines if this quantity is virtual. Virtual quantities can be got/set like regular quantities, but their values are not (de-)serialized, hence never permanently stored. default= False |
| is_scalar | bool |
|
| use_full_storage | bool |
A derived boolean that indicates if this quantity should be stored in full storage mode. It will be set to True if flexible_unit is True, or variable is True, or it has attributes. |
| flexible_unit | bool |
A boolean to indicate if this quantity may have a unit that is not the default unit. In this case, the quantity will be stored in full storage mode as a MQuantity.default= False |
SubSection¶
description: Like quantities, subsections are defined in a section class as attributes of this class. Unlike quantities, each subsection definition becomes a property of
the corresponding section definition (parent). A subsection definition references
another section definition as the subsection (child). As a consequence, parent
section instances can contain child section instances as subsections.
Contrary to the old NOMAD metainfo, we distinguish between subsection the section
and subsection the property. This allows to use on child section definition as
subsection of many parent section definitions.
inherits from: Property
properties:
| name | type | |
|---|---|---|
| sub_section | Section |
A :class:Section or Python class object for a section class. This will be the child section definition. The defining section the child section definition. |
| repeats | bool |
A boolean that determines whether this subsection can appear multiple times in the parent section. default= False |
| key_quantity | str |