Stage Variables#

The stage is an UPSTAGE feature to allow thread-safe “global” variables accessible by any Actor or Task.

To add variables to the stage, within the EnvironmentContext manager use the add_stage_variable() function.

Once you set a stage variable, it cannot be changed. This is intentional, as the stage is meant to be static. Anything that changes should go through SimPy or UPSTAGE tasks, states, or processes.

class Person(UP.Actor):

    def do_thinking(self):
        number = self.stage.my_variable
        print(f"'{self}'' is thinking about {number}")


class Think(UP.Task):
    def task(self, *, actor: Person):
        number = self.stage.my_variable
        print(f"Think Task is thinking about {number}")
        actor.do_thinking()
        yield UP.Event()


with UP.EnvironmentContext(initial_time=0.0) as env:
    UP.add_stage_variable("my_variable", 3.14)
    p = Person(name="Arthur")
    Think().run(actor=p)
    env.run()

>>> Think Task is thinking about 3.14
>>> 'Person: Arthur' is thinking about 3.14

Expected Stage Variables#

Some variables are expected to exist on the stage for some features. These are found in the StageProtocol protocol, and are listed below:

  • “altitude_units”: A string of “ft”, “m”, or other distance unit. See unit_convert() for a list.

  • “distance_units”: A string of distance units

  • “stage_model”: A model to use for Geodetic calculations. See Geography for more.

  • “intersection_model”: A model to use for motion manager. See Geography and Motion Manager for more.

  • “time_unit”: Units of time. See unit_convert() for a list.

If they are not set and you use a feature that needs them, you’ll get a warning about not being able to find a stage variable.

Accessing Stage through UpstageBase#

The UpstageBase class can be inherited to provide access to self.env and self.stage in any object, not just actors and tasks. The following snippets shows how you might use it for pure SimPy capabilities.

class ManagerCode(UP.UpstageBase):
    def run(self):
        def _proc():
            process_time = self.stage.process_time
            yield self.env.timeout(process_time)

        self.env.process(_proc())