Configuration

General overview of the possible individual configuration of a simulation using the configuration attribute of the bptk constructor
Keywords

configuration, bptk, bptk-py, python, business simulation

Configuration

This document explains the configuration settings of a bptk object.

The code on this page is shown rather than run: it configures logging, file monitors and where scenarios are read from, none of which has an effect you could see on a documentation page — and some of which needs a token or a directory that only exists on your own machine. The one section that is live is the last one, on graphical settings.

General

The bptk constructor accepts two arguments:

  • loglevel — adjusts the global logging level, so it also applies to other bptk instances in the same process.
  • configuration — a dictionary, and the subject of the rest of this page.

Configure Logfire

Logging to Logfire is enabled globally through the configuration argument. It needs the observability extra:

pip install "BPTK-Py[observability]"

Register with Logfire, obtain a write token, and keep it out of your code — an .env file beside your notebook is the usual place. Reading it needs python-dotenv, which BPTK does not depend on; install it alongside:

pip install python-dotenv
# .env
LOGFIRE_TOKEN=pylf_v1_eu_your_write_token_here

Then read it and hand it to the constructor:

import os
from dotenv import load_dotenv
from logfire import ConsoleOptions
from BPTK_Py import bptk

load_dotenv()

bptk_instance = bptk(
    loglevel="INFO",
    configuration={
        "logfire_config": {
            "environment": "development",
            "token": os.getenv("LOGFIRE_TOKEN"),
            "console": ConsoleOptions(show_project_link=False),
        }
    },
)

Once Logfire is configured, every message written to bptk_py.log (the default logfile name) is also sent to Logfire. Inside "logfire_config" you can pass both the essentials — "environment" and "token" — and any of the optional settings that control Logfire’s behaviour and its appearance in the console. The full list is in the Logfire configuration reference.

Logfire can also be configured directly, without going through a bptk instance:

import BPTK_Py.logger.logger as logmod
from logfire import ConsoleOptions

logmod.configure_logfire(
    token=os.getenv("LOGFIRE_TOKEN"),
    console=ConsoleOptions(show_project_link=False),
)

Without the observability extra installed, this raises ImportError naming the extra.

Configure Additional Logging Settings

Two further keys control where log messages go. Both are applied globally.

  • "log_modes" — list of strings, any of "print" and "logfile". Default: ["logfile"].
  • "log_file" — string, the name of the logfile. Default: "bptk_py.log".
bptk_instance = bptk(
    loglevel="WARN",
    configuration={
        "log_modes": ["print", "logfile"],
        "log_file": "test_bptk.log",
    },
)

With this setting, log messages are written both to test_bptk.log and to the console.

Configure Scenario and Model Monitor

For each bptk instance you can decide whether changes to scenario files and model files are detected and applied automatically.

  • "set_scenario_monitor" — boolean. When True, a FileMonitor thread runs for each scenario JSON file and reloads the scenarios in it when the file changes on disk. Default: True.
  • "set_model_monitor" — boolean. When True, a ModelMonitor thread runs for the associated model file and updates every scenario that depends on it when the file changes. Default: True.

To switch both off:

bptk_instance = bptk(
    loglevel="WARN",
    configuration={
        "set_scenario_monitor": False,
        "set_model_monitor": False,
    },
)

Neither monitor runs in a browser: they need threads that never return, which the browser platform does not provide.

Configure the path to scenario storage

A bptk instance finds its scenarios through the "scenario_storage" key, which defaults to "scenarios/" — a folder named scenarios relative to any directory on sys.path.

The folders beside this page are laid out like this, and you can open the files:

concepts/
├── configuration/
│   └── subfolder1/
│       └── scenarios/
│           └── scenario2.json
└── folder2/
    └── scenarios/
        └── scenario3.json

To load scenario2.json, which sits one level below this page:

bptk_instance = bptk(
    loglevel="INFO",
    configuration={"scenario_storage": "subfolder1/scenarios/"},
)

To load scenario3.json, which sits in a sibling of this page’s folder, use a relative path pointing one level up:

bptk_instance = bptk(
    loglevel="INFO",
    configuration={"scenario_storage": "../folder2/scenarios/"},
)

Note that the parent of the "scenario_storage" path is added to sys.path. The instance therefore also resolves the "model" path inside the scenario JSON relative to that parent.

Configure graphic settings

Plotting reads its defaults from the same configuration dictionary, so you can set the look of every plot an instance produces in one place instead of per call. This section is live — the model below is built in the page, so both plots really run.

With no graphic settings at all, an instance plots like this:

One configuration for every plot

The plot settings live in one place that every plot method reads — plot_scenarios, plot_lookup, Element.plot and the agent data collector alike. Passing configuration to the constructor writes into it, so the settings apply to every plot in the process, not only to the plots of the instance you configured:

BPTK_Py.bptk(
    configuration={
        "kind": "bar",              # bars instead of lines
        "stacked": False,           # side by side rather than on top of each other
        "colors": ["Red", "Blue", "Green"],
        "alpha": 0.98,              # almost opaque
        "matplotlib_rc_settings": {
            "xtick.labelsize": 10,
            "ytick.labelsize": 12,
            "legend.fontsize": 14,
        },
    }
)

That is deliberate — you configure the look of your plots once — but it is worth knowing before you build a second instance and wonder why it draws in the first instance’s style. BPTK_Py.plotting_config.reset() gets back to the defaults.

Charts you draw yourself are not affected. The settings are applied around our own drawing calls, never written into matplotlib’s global rcParams, so a figure you build with plt.subplots() keeps matplotlib’s own defaults.

Styling a single plot

Where one chart should differ, hand the settings to that call instead. They are laid over the central configuration for this one draw and leave it as it is, so the plot above keeps its own look. Change a value and press play: