Registry of Updaters, Dividers, and Serializers¶
You should interpret words and phrases that appear fully capitalized in this document as described in RFC 2119. Here is a brief summary of the RFC:
“MUST” indicates absolute requirements. Vivarium may not work correctly if you don’t follow these.
“SHOULD” indicates strong suggestions. You might have a valid reason for deviating from them, but be careful that you understand the ramifications.
“MAY” indicates truly optional features that you can include or exclude as you wish.
Updaters¶
Each updater is defined as a function whose name begins with
update_
. Vivarium uses these functions to apply updates to
variables. Updater names are registered in
updater_registry
, which maps these names to updater functions.
Updater API¶
An updater function SHOULD have a name that begins with update_
. The
function MUST accept exactly three positional arguments: the first MUST
be the current value of the variable (i.e. before applying the update),
the second MUST be the value associated with the variable in the update,
and the third MUST be either a dictionary of states from the simulation
hierarchy or None if no port_mapping
key was specified in the
updater definition. The function SHOULD not accept any other parameters.
The function MUST return the updated value of the variable only.
Dividers¶
Each divider is defined by a function that follows the API we
describe below. Vivarium uses these dividers to generate daughter cell
states from the mother cell’s state. Divider names are registered in
divider_registry
, which maps these names to divider functions.
Divider API¶
Each divider function SHOULD have a name prefixed with divide_
. The
function MUST accept a single positional argument, the value of the
variable in the mother cell. It SHOULD accept no other arguments. The
function MUST return either:
A
list
with two elements: the values of the variables in each of the daughter cells.None
, in which case division will be skipped for that variable.
Note
Dividers MAY not be deterministic and MAY not be symmetric. For example, a divider splitting an odd, integer-valued value may randomly decide which daughter cell receives the remainder.
Serializers¶
Each serializer is defined as a class that follows the API we
describe below. Vivarium uses these serializers to convert emitted data
into a BSON-compatible format for database storage. Serializer names are
registered in serializer_registry
, which maps these names to
serializer subclasses. For maximum performance, register serializers
using a key equal to the string representation of its designated type
(e.g. str(Serializer.python_type)
).
Serializer API¶
Serializers MUST define the following:
The
python_type
class attributes that determines what types are handled by the serializerThe
vivarium.core.registry.Serializer.serialize()
method which is called on all objects of typepython_type
Avoid defining custom serializers for built-in or Numpy types as these are
automatically handled by orjson
, the package used to serialize data.
Note
All dictionary keys MUST be Python strings for orjson
to work.
Numpy strings (np.str_
) are not allowed.
If it is necessary to redefine the how objects are serialized by orjson,
assign custom serializers to the stores containing objects of the affected
type(s) using the _serializer
ports schema key. This can also be used
to serialize objects of the same Python type differently. To ensure that
objects serialized this way are deserialized correctly, you SHOULD consider
implementing the following as well:
vivarium.core.registry.Serializer.can_deserialize()
to determine whether to calldeserialize
on datavivarium.core.registry.Serializer.deserialize()
to deserialize data
If it is necessary to deserialize objects of the same BSON type differently, the corresponding serializer(s) MUST implement these 2 methods.
-
class
vivarium.core.registry.
Registry
[source]¶ Bases:
object
A Registry holds a collection of functions or objects.
-
register
(key, item, alternate_keys=())[source]¶ Add an item to the registry.
- Parameters
key – Item key.
item – The item to add.
alternate_keys –
Additional keys under which to register the item. These keys will not be included in the list returned by
Registry.list()
.This may be useful if you want to be able to look up an item in the registry under multiple keys.
-
-
class
vivarium.core.registry.
Serializer
[source]¶ Bases:
object
Base serializer class.
Serializers work together to convert Python objects, which may be collections of many different kinds of objects, into BSON-compatible representations. Those representations can then be deserialized to recover the original object.
Serialization of Python’s built-in datatypes and most Numpy types is handled directly by the
orjson.dumps()
method.The serialization routines in Serializers are compiled into a fallback function that is called on objects not handled by
orjson
.If one wishes to modify how built-in/Numpy objects are serialized, the relevant stores can be assigned a custom serializer using the
_serializer
key. Thevivarium.core.registry.Serializer.serialize()
method of that serializer will be called on the values in these stores before they are passed toorjson
.During deserialization, the
can_deserialize
method of each Serializer is used to determine whether to call thedeserialize
method.- Parameters
name – Name of the serializer. Defaults to the class name.
-
can_deserialize
(data)[source]¶ This tells
vivarium.core.serialize.deserialize_value()
whether to calldeserialize
on data.
-
deserialize
(data)[source]¶ This allows for data of the same BSON type to be deserialized differently (see regex matching of strings in
vivarium.core.serialize.UnitsSerializer.deserialize()
for an example).
-
python_type
: Any = None¶ Type matching is NOT exact (subclasses included)
-
vivarium.core.registry.
assert_no_divide
(state)[source]¶ Assert that the variable is never divided
- Raises
AssertionError – If the variable is divided
-
vivarium.core.registry.
divide_null
(state)[source]¶ Divider that causes the variable to be skipped during division.
- Returns
None
so that no divided values are provided to the daughter cells. This is useful for process objects, which are handled separately during division.
-
vivarium.core.registry.
divide_set
(state)[source]¶ Set Divider
- Returns
A list
[state, state]
. No copying is performed.
-
vivarium.core.registry.
divide_set_value
(state, config)[source]¶ Set Value Divider :param ‘state’: value
- Returns
A list
[value, value]
. No copying is performed.
-
vivarium.core.registry.
divide_split
(state)[source]¶ Split Divider
- Parameters
state – Must be an
int
, afloat
, or astr
of valueInfinity
.- Returns
A list, each of whose elements contains half of
state
. Ifstate
is anint
, the remainder is placed at random in one of the two elements. Ifstate
is infinite, the return value is[state, state]
(no copying is done).- Raises
Exception – if
state
is of an unrecognized type.
-
vivarium.core.registry.
divide_split_dict
(state)[source]¶ Split-Dictionary Divider
- Returns
A list of two dictionaries. The first dictionary stores the first half of the key-value pairs in
state
, and the second dictionary stores the rest of the key-value pairs.Note
Since dictionaries are unordered, you should avoid making any assumptions about which keys will be sent to which daughter cell.
-
vivarium.core.registry.
divider_registry
= <vivarium.core.registry.Registry object>¶ Map divider names to divider functions
-
vivarium.core.registry.
emitter_registry
= <vivarium.core.registry.Registry object>¶ Map serializer names to Emitter classes
-
vivarium.core.registry.
process_registry
= <vivarium.core.registry.Registry object>¶ Maps process names to process classes
-
vivarium.core.registry.
serializer_registry
= <vivarium.core.registry.Registry object>¶ Map serializer names to serializer classes
-
vivarium.core.registry.
update_accumulate
(current_value, new_value)[source]¶ Accumulate Updater
- Returns
The sum of
current_value
andnew_value
.
-
vivarium.core.registry.
update_dictionary
(current, update)[source]¶ Dictionary Updater Updater that translates _add and _delete -style updates into operations on a dictionary.
Expects current to be a dictionary, with no restriction on the types of objects stored within it, and no defaults values.
-
vivarium.core.registry.
update_merge
(current_value, new_value)[source]¶ Merge Updater
- Returns
The merger of
current_value
andnew_value
. For any shared keys, the value innew_value
is used.- Return type
-
vivarium.core.registry.
update_nonnegative_accumulate
(current_value, new_value)[source]¶ Non-negative Accumulate Updater
- Returns
The sum of
current_value
andnew_value
if positive, 0 if negative.
-
vivarium.core.registry.
update_null
(current_value, new_value)[source]¶ Null Updater
- Returns
The value provided in
current_value
.