# Workflow Tables ## Standard Tables An ActivitySim table definition is written as a Python function with a `workflow.table` decorator: ```python import pandas as pd from activitysim.core import workflow @workflow.table def households(state: workflow.State) -> pd.DataFrame: df = pd.DataFrame(...) # do something to set up table here return df ``` Similar to a typical Python class method, the first argument to a workflow table function is always a reference to a [`State`](core-workflow-api.md) object named `state`. Unlike a typical Python class method, this is rigorously enforced -- if you decorate a function as a `workflow.table` and the first argument is not named `state` a `TypeError` will be raised. For most tables, the initialization of the table will be defined by values in the {py:class}`Settings `, and there will be no other function arguments. If table initialization does require access to other tables (e.g. the *vehicles* table needs access to the *households* table to be initialized) then other tables can be provided as matching-named arguments, in the same way as [`workflow.step`](core-workflow-steps) functions. The `workflow.table` function should return a `pandas.DataFrame` or `xarray.Dataset` representation of the table. When this function is called automatically by the processes that orchestrate execution, this object will be stored in the state's context as the name of the table. ## Temporary Tables In addition to the main `workflow.table` decorator, there is also a similar `workflow.temp_table` decorator for temporary tables. ```python import pandas as pd from activitysim.core import workflow @workflow.temp_table def households_merged( state: workflow.State, households: pd.DataFrame, land_use: pd.DataFrame, accessibility: pd.DataFrame, ) -> pd.DataFrame: df = pd.DataFrame(...) # do something to set up table here return df ``` There are two main differences between regular tables and temporary tables: 1. Temporary tables are never checkpointed. The supposition for temporary tables is that they are generally large, and easy to re-create on the fly, so storing them to disk is wasteful. Most temporary tables in ActivitySim are simply merges of other existing tables, although that is not formally a requirement of a temporary tables. 2. Temporary tables are dropped when any predicate argument is changed in the same `State`. The *predicates* are all the named arguments of the `workflow.temp_table` wrapped function after the `state`. If another ActivitySim instruction triggers an update to *any* of these predicate arguments, the temporary table is dropped from the state's context. It can (presumably) be recreated easily from the (now different) predicate values if/when needed for later steps. (core-workflow-cached-objects)= ## Other Cached Objects Other arbitrary Python objects can also be generated by functions that are handled by the same automatic system as tables, using the `workflow.cached_object` decorator. ```python from activitysim.core import workflow @workflow.cached_object def name_of_object( state: workflow.State, other_thing: bool = False, ): obj = [1,2,3] if other_thing else [7,8,9] # or any python object return obj ``` Similar to temporary tables, these objects are not stored in checkpoint files. Unlike temporary tables, they are not formally predicated on their arguments, so for example in the `cached_object` above, a change in the value of `other_thing` will cause `name_of_object` to be regenerated if it already exists in the state's context. ## API ```{eval-rst} .. currentmodule:: activitysim.core.workflow .. autosummary:: :toctree: _generated :template: autosummary/class_decorator.rst :recursive: table temp_table cached_object ```