An OERecord is a data container that holds a variety of strongly-typed, named values, plus associated metadata. It is used to pass data between cubes in Orion workfloes, and is the main mechanism by which data is communicated to and from Orion. OERecords also provide a general way to create and store structured data within the OpenEye ecosystem.

The most straightforward use of an OERecord is for storage and retrieval of simple values. The following example illustrates how to use a record to store and retrieve integer, string, and floating point values.

record = OERecord()
int_field = OEField("My Integer Field", Types.Int)
string_field = OEField("My String Field", Types.String)
float_field = OEField("My Float Field", Types.Float)

record.set_value(int_field, 12345)
record.set_value(string_field, "Hello World!")
record.set_value(float_field, 67.89)

value = record.get_value(string_field)
print(value)  # "Hello World!"

print(record.get_value(int_field))  # 12345
print(record.get_value(float_field))  # 67.89

OERecord has methods that allow you to interrogate the record for the presence of fields and values.

print(record.has_value(int_field))  # True

# The value is cleared, but the field still exists
print(record.has_value(int_field))  # False
print(record.has_field(int_field))  # True
print(record.get_value(int_field))  # None

# Remove the field
print(record.has_field(int_field))  # False
print(record.get_value(int_field))  # None

Other types of data can be stored on OERecords, including molecules and even other OERecords.

record2 = OERecord()
mol_field = OEField("Molecule", Types.Chem.Mol)
mol = OEMol()
OESmilesToMol(mol, "c1cc[nH]c1CC2COCNC2")
record2.set_value(mol_field, mol)
print(record2.get_value(mol_field).NumAtoms())  # 12

# Now let's store another record on this one
record_field = OEField("Check this out", Types.Record)
record2.set_value(record_field, record)

OERecords can be written to files and read from files using the OEWriteRecord and OEReadRecord functions.

# Save our record to a file
ofs = oeofstream("MyRecord.oedb")
OEWriteRecord(ofs, record2)

ifs = oeifstream("MyRecord.oedb")
new_record = OEReadRecord(ifs)
child_record = new_record.get_value(record_field)
print(child_record.has_field(float_field))  # True
print(child_record.get_value(float_field))  # 67.89

Metadata on fields

In addition to holding various types of data, OERecord can also hold various pieces of metadata about its fields. The metadata is stored onto field objects using the OEFieldMeta class and constants from the OEMetadata class.

There are two types of metadata: options which are simple flags, and attributes which are key/value pairs with user-supplied values.

In the following example, two pieces of metadata, one option and one attribute, are put on a field to describe the contents of that field.

rec = OERecord()

# Write a SMILES string onto a record, and provide a hint, using
# metadata, that this string is in SMILES notation.
meta = OEFieldMeta()
meta.set_attribute(Meta.Display.Values.Priority, 1)
smiles_field = OEField("SMILES string", Types.String, meta)
rec.set_value(smiles_field, "c1ccccc1CCOC")

meta_from_record = rec.get_field_meta("SMILES string")
print(meta_from_record.has_option(Meta.Hints.Chem.SMILES))  # True
print(meta_from_record.get_attribute(Meta.Display.Values.Priority))  # 1

Metadata can also be used to designate relationships between fields on a record. The following example shows how to attach error values to a field using metadata.

value_field = OEField("value", Types.Float)
err_meta = OEFieldMeta()
# Add an "Errors For" relationship, referencing the value_field
err_meta.add_relation(Meta.Relations.ErrorsFor, value_field)
err_field = OEField("error", Types.Float, err_meta)
rec.set_value(value_field, 46.5)
rec.set_value(err_field, 0.34)