Table Definitions#
The traveler.examples.mtc_mini.tables package contains table definitions
for the MTC Mini example, including classes for households and tours, among
others. These tables are implemented as subclasses of JaxTable and define
the schema for each data table in the model.
from traveler.trees import JaxTable
from traveler.typing import TypeMaker
t = TypeMaker("household")
class Households(JaxTable):
"""
A class representing households in the ActivityJAX framework.
"""
household_id: t.Int32 # (3)
"""Unique identifier for the household.""" # (1)
home_zone_id: t.Int32
"""Identifier for the home zone of the household."""
income_in_thousands: t.Float32
hhsize: t.Int8 # (2)
non_family: t.Bool
_household_idx_: t.Int32
Docstrings can be added to each field to describe its purpose and any relevant details.
The data type for
hhsizeis set toInt8, which is a small integer type suitable for household sizes. The validation tool can be set to safely coerce integer values to this type if the underlying data can be represented accurately.Type annotations are used to define the data types of each field in the
Householdsclass. Thet.Int32type is used for 32-bit integers,t.Float32for 32-bit floating-point numbers, andt.Boolfor boolean values. TheTypeMakerutility is used to create type aliases for various numeric types, and also ensures that data arrays added to the table have appropriate dimensions (e.g. match the number of rows in the table, or are a scalar value that can be broadcast to the rows).
from traveler.trees import JaxTable
from traveler.typing import TypeMaker
t = TypeMaker("tour")
time_periods = ["EA", "AM", "MD", "PM", "EV"]
class Tours(JaxTable):
"""
A class representing households in the ActivityJAX framework.
"""
tour_id: t.Int32
person_id: t.Int32
household_id: t.Int32
otaz: t.Int32
dtaz: t.Int32
out_period: t.Categorical(categories=time_periods) # (3)
"""Skims time period for the outbound (first) half of the tour."""
in_period: t.Categorical(categories=time_periods)
"""Skims time period for the inbound (second, return) half of the tour."""
_household_idx_: t.Int32
_person_idx_: t.Int32
@lazy # (1)
def sov_available(self, store: AbstractStore) -> t.Bool:
"""Whether the SOV mode is available for this tour."""
odt_skims = skims_data(store, self.otaz, self.dtaz, self.out_period)
dot_skims = skims_data(store, self.dtaz, self.otaz, self.in_period)
return (odt_skims("SOV_TIME") > 0) & (dot_skims("SOV_TIME") > 0)
is_joint: Endog("tour_preprocessor", t.Bool) # (2)
"""Whether this is a joint tour."""
The
lazydecorator is used to define a lazy-loaded property that computes a new table column only when demanded. This allows for efficient computation and avoids unnecessary calculations. The computed column is cached in the table, so it is only computed once per table row, and can be used in subsequent computations without recomputing it.The
Endogannotation is used to define an endogenous variable that is computed by some step that is part of the model. Data validation will expect that the endogenous variable does not need to exist unless that step has been run, but if that step has been run, the variable will be validated for shape and dtype.The
Categoricaltype is used to define a categorical variable with nominal or ordinal categories. This is useful for representing discrete choices or categories in the data, such as time periods in this case. Data validation will ensure that the categories in the data match the defined categories, and will raise an error if they do not match.