Persisting and Visualizing Data¶
Note
This section is intended for node-developers.
Simstack persists data using a MongoDB database, which is exposed via the fast-api server to a web-frontend. Each user has a dedicated database on a MongoDB server which is configured in the configuration file (Create simstack.toml).
To facilitate access to the database in the python workflows, Simstack II uses the odmantic package to provide an object-oriented access to the data via odmantic Models. Odmantic Models are drived from pydantic (V2) classes and developers of nodes (Workflows) can define their own classes deriving from Model.
To customize the appearance of the models in the UI, the model definition
should be decorated by @simstack_model
(simstack.core.simstack_model.simstack_model())
which provides ui-related functionality discussed below
(Model Appearance in the GUI)
Model Definitions¶
For detailed information on odmantic models, consult the odmantic documentation.
A basic model definition look like:
from typing import Optional, List
from odmantic import Model, EmbeddedModel, Field
@simstack_model
class OtherModel(Model):
observations: List[float]
max: float
@simstack_model
class SmallData(EmbeddedModel)
number: int
@simstack_model
class ComplexData(Model)
counter: int = Field(default=1)
limit: Optional[int] = None
other_model: OtherModel = Reference() # this defines a reference to the
# other table in the db
# loading ComplexData will load
# the other model too
small_data: SmallData # directly stored in the complex_data table
Important
The node developer does not have explicitly save models to the db, the @node decorator will take care of this.
There is no Model inheritance, which is a real pain.
ODMantic Issue #484: https://github.com/art049/odmantic/issues/484
Note
Even though its formally allowed do not use Dict[str,Any] in models, because the UI behavior is unpredictable (see below). Dict[str,known_type] is ok.
Standard Models
simstack.models.base_types provides basic models:
IntData
StrData
FloatData
BooleanData
And simstack.models.array_storage:
ArrayStorage
ArrayList
And the list mixins for creating custom list models (see List Mixins):
GenericListMixin
ObjectListMixin
And for file management (see File Management):
FileStack
FileList
FileListModel
And the parallel execution utilities (see MassRunner and FireAndForgetRunner):
MassRunner
FireAndForgetRunner
simstack.models.array_storage.ArrayStorage is an example of a class which
packs its content by serializing and deserializing it. This is the
recommended procedure for all content which MongoDB cannot natively store. To
interact with such classes, the developer has to provide access functions and
a member function custom_model_dump which the fast-api server to convert
the content of the class into a dict which can be visualized in the GUI.
Model Appearance in the GUI¶
The simstack.models.models.ModelTable table in the database stores
for each class a json-schema (derived from the pydantic json-schema) and a
ui_scheme which is created by
simstack.core.model_table.make_model_table().
The UI used a package react-json-forms (rjsf) to interpret these schema to provide input and output representations of the model. When queried the routes of the fast-api server provide (get) or store (post) dicts that are compatible with the json-schema. 8
Class Methods
Function Name |
Purpose |
default |
json_schema |
json schema for rjsf |
pydantic-schema |
ui_schema |
ui_schema dict for rjsf |
hide id |
ui_make_title |
title for the model in ui |
class name |
from_dict |
create model instance from dict |
odmantic func |
from_model |
copy constructor |
odmantic default |
Instance Functions
Function Name |
Purpose |
default |
custom_model_dump |
convert model to dict |
model_dump |
Advanced Tools¶
Conditional Schema
schema['properties']['test'] = {
"type": "object",
"oneOf": [
{
"properties": {
"lorem": {
"type": "string"
}
},
"required": [
"lorem"
]
},
{
"properties": {
"ipsum": {
"type": "string"
}
},
"required": [
"ipsum"
]
}