Introduction

The code in this tutorial can also be found in the introduction ipython notebook.

Create an empty document

Working with odML 2 always starts the creation of an empty Document.

import datetime as dt
from odml2 import Document, SB, Value

doc = Document()

Basic document properties

Each odML 2 document has a set of basic attributes which provide additional information. Some of those are read-only and automatically set to a certain value. The attribute location for example is set when a document is loaded or saved, it is always none for newly created documents. Other attributes are writable and meant to be defined by the user.

The following listing shows how those attributes can be accessed:

# automatically filled properties
print("doc.is_writable: %s" % doc.is_writable)
print("doc.is_attached: %s" % doc.is_attached)
print("doc.location: %s" % doc.location)

# user defined properties
doc.author = "John Doe"
doc.version = 3
doc.date = dt.datetime.now()

print("doc.author: %s" % doc.author)
print("doc.version: %s" % doc.version)
print("doc.date: %s" % doc.date)

odML value objects

In odML 2 all values of non section properties are represented as Value objects. In most places where Value objects are expected as an argument one can also use a plain literal or variable of the respective type. But if one wants to define with values additional information such as unit or uncertainty it is useful to know how to use them.

The following codes shows how values can be created:

v = Value(10)
print(v)
print(repr(v))

v = Value(200, unit="µm", uncertainty=0.002)
print(repr(v))

v = Value.from_obj("42 +-0.002 mV")
print(repr(v))

Value objects are immutable. If one needs a modified instance of a certain value the copy() method can used.

v = v.copy(unit="V")

Value objects can further be hashed (and therefore be used as keys in dicts) and support all kinds of comparison operations.

Add a section as document root

To populate an odML 2 document with metadata one has to create a root Section which represents the entry point to the metadata. Section instances are usually not created directly. Instead the section builder class SB can be used. It provides a much more convenient and less verbose way to create sections and even entire metadata structures.

doc.root = SB("RecordingSession", label="session 2")
doc.root

Add properties to a section

A Section is basically a dict or map of properties. There are two different kinds of properties: value properties point to a single Value, whereas section properties point to one or many child Section objects.

The following example shows how both kinds of properties can be added to a parent section:

sec = doc.root

sec["recording_date"] = dt.date.today()
sec["time_delay"] = Value(10, unit="ms", uncertainty=0.001)
sec["experimenter"] = SB(
        "Person",
        first_name="John",
        last_name="Doe"
)

Access section properties

Although a section can be seen as a dict with values being either lists of sections or single Value objects, the Section class acts a bit differently in order to make some common uses-cases a bit easier.

sec["recording_date"]

If a value property is accessed via square brackets, the section does actually not return the Value object, but instead the values value. In the above example the returned value would be the a date.

sec.get("recording_date")

In contrast to the square brackets operator the get() method returns always the Value object (if it’s a value property).

sec["experimenter"]

If a section property is accessed via square brackets the returned object is either a list of sections or a single section (in cases where the property points to a list of sections with only one entry).

sec.get("experimenter")

The get() method returns always a list of sections when it is used to access a section property.

Generally accessing properties via square brackets is more convenient, especially if the type of a property is already known. Access via get() in contrast is more reliable and should be used when unknown documents are processed.

Save the odML document

doc.save("intro.yml")

with open("intro.yml") as f:
    print(f.read())
date: 2016-02-17 11:59:15.587085
document_version: 3
format_version: 2
author: John Doe
namespaces: null
definitions: null
metadata:
  type: RecordingSession
  uuid: 941350b3-a4e9-42d1-ad76-85def35120b0
  label: session 2
  recording_date: 2016-02-17
  experimenter:
    type: Person
    uuid: f1473908-6a84-420a-9c25-d288a44715ef
    first_name: John
    last_name: Doe

Load a document

new_doc = Document()
new_doc.load("intro.yml")

Navigation