Configurations in Hyrax#

Hyrax uses configuration files to make it easier to track all of the parameters used for a given process. Hyrax attempts to provide a set of reasonable configuration values for all of the operations a user will perform, with exceptions.

When you create a Hyrax instance, the built in defaults will be used automatically.

[1]:
from hyrax import Hyrax

h = Hyrax()

Once a Hyrax instance is created, the configuration is available as the h.config dictionary. We can view any particular value by using the keys of the dictionary. For instance, if we wanted to know what the default filename will be for the trained model weights file, we can use the following:

[2]:
h.config["train"]["weights_filename"]
[2]:
'example_model.pth'

If you’re interested, the complete Hyrax default configuration file can be seen here: https://hyrax.readthedocs.io/en/latest/hyrax_default_config.html

A small portion of the default config can be seen below.

[3]:
import json

print(json.dumps(h.config["general"], indent=2))
{
  "dev_mode": false,
  "log_destination": "stderr",
  "log_level": "info",
  "data_dir": "/home/docs/checkouts/readthedocs.org/user_builds/hyrax/checkouts/latest/docs/notebooks/data",
  "results_dir": "./results"
}

Updating config values#

While it is possible to set the values in the dictionaries directly, using h.set_config() will rerun the Hyrax configuration resolution algorithm to ensure that any secondary configuration updates are incorporated.

[4]:
print(f"Default number of epochs: {h.config['train']['epochs']}")
h.set_config("train.epochs", 5)
print(f"Updated number of epochs: {h.config['train']['epochs']}")
Default number of epochs: 10
Updated number of epochs: 5

Warning

Use caution with ``None`` When setting config values, it is generally a good idea to avoid using None. It is preferable to use False or an empty string, "" when using .toml.

Using over_write flag#

By default, new configs are merged into existing ones, and any unspecified fields are left unchanged.

[5]:
base_config = {"a": 1, "b": {"x": 100, "y": 200}}

h.set_config("base_config", base_config)
print(f"Base config: {h.config['base_config']}")

new_config = {"b": {"x": 2}}
h.set_config("base_config", new_config)
print(f"Merged config: {h.config['base_config']}")
[2026-05-21 21:21:00,695 hyrax.config_utils:WARNING] Runtime config contains key or section 'base_config' which has no default defined. All configuration keys and sections must be defined in /home/docs/checkouts/readthedocs.org/user_builds/hyrax/envs/latest/lib/python3.12/site-packages/hyrax/hyrax_default_config.toml
Base config: {'a': 1, 'b': {'x': 100, 'y': 200}}
Merged config: {'a': 1, 'b': {'x': 2, 'y': 200}}

With the optional flag (over_write=True), the entire matching top-level section is fully overwritten by the new value.

[6]:
h.set_config("base_config", new_config, over_write=True)
print(f"Overwritten config: {h.config['base_config']}")
Overwritten config: {'b': {'x': 2}}

This is useful when you want to completely replace a config section instead of partially updating it, especially for complex nested settings where old fields should not be preserved.

See the documentation for more information: set_config

User configuration files#

It is not always convenient to manually modify configurations each time Hyrax runs. Configurations can be overridden with a custom .toml file provided to Hyrax during instantiation.

In this example, we’ll name our file user_config.toml (any file name is fine), and set the log level and weights filename like so:

[general]
log_level = "error"

[train]
weights_filename = "model_weights.pth"

Note

User configuration files don’t need to be a complete copy of the default configuration file. Hyrax will start with the defaults and override the specific keys with values from the user’s configuration file.

[7]:
import json

h = Hyrax(config_file="./user_config.toml")

print("Only the log level has been changed in the 'general' section:")
print(json.dumps(h.config["general"], indent=2))

print("Additionally, the trained weights file name is now:")
print(h.config["train"]["weights_filename"])
[2026-05-21 21:21:00,769 hyrax.config_migrations.migration_utils:WARNING] All migrations complete. Your configuration file is now up to date with the latest schema. The runtime config saved in the output directory will reflect the new schema, and your original config file will remain unchanged on disk.
Only the log level has been changed in the 'general' section:
{
  "dev_mode": false,
  "log_destination": "stderr",
  "log_level": "error",
  "data_dir": "/home/docs/checkouts/readthedocs.org/user_builds/hyrax/checkouts/latest/docs/notebooks/data",
  "results_dir": "./results"
}
Additionally, the trained weights file name is now:
model_weights.pth

Config immutability#

To support reproducibility, once a Hyrax action starts, the configuration is locked. There are very few exceptions to this rule, and Hyrax clearly logs when the config does change. This ensures that when the config state is saved, it accurately represents the settings used by Hyrax.

The state of the configuration will always be saved alongside the output of a Hyrax action in a time stamped directory like YYYYmmdd-HHMMSS-train-RAND.

This is another way that Hyrax supports low-code experimentation with machine learning.