Developer Guidelines: Adding a new simulation method#
If you have an open-source room acoustic simulation method you would like to add to the CHORAS back-end, you have come to the right place! (Also, if you are reading this in preparation for the CHORAS Developer Workshop, you have found the right document :))
Before changing code#
1. Create a new Branch#
Use the format sim/<your_method_name> for your branch name in simulation-backend submodule so that your changes stay organized and isolated from the main codebase
Use SSH for Git (optional)#
If you want to authenticate via ssh (instead of the default https), change the repository URL by running this command in the backend root directory:
git remote set-url origin git@github.com:choras-org/simulation-backend.git
Including your simulation method#
1. Create a new Folder#
Add a new folder named <method_name>_method inside the simulation-backend submodule. This will contain everything related to your simulation method.
2. Add an interface File#
Inside your new folder, create a file named <your_method_name>Interface.py (see MyNewMethodInterface.py for reference).
This file defines the interface between CHORAS and your simulation method. It must include:
A main interface function, e.g.
<your_method_name>_method(), which:Accepts the path to a
.jsoninput file as its argument.Interprets the file data for your method.
Reports progress and results back to CHORAS (e.g., % complete, output data).
A
main()function that calls the above interface function for testing or standalone runs.
3. Define Dependencies#
Add a requirements.txt file inside your method’s folder. Include your method’s dependencies with explicit version numbers.
Prefer libraries that are installable via pip
If your package is hosted in a git repository, you can install it using:
git+https://gitprovider.com/user/project.git@{version}
Refer to the Python Packaging Authority guide for more options. Note that providing a specific version number is important to ensure reproducibility (and stability) of the results and CHORAS as a platform. If your method is not yet installable via pip, please refer to packaging guidelines provided by the Python Packaging Authority.
4. Create a Docker File#
Add a Dockerfile in your folder (see the MyNewMethod folder for reference).
This file should define the environment setup required to build your simulation method’s Docker image. Guidelines of creating dockerfile is as follows:
Specify the python version is being used by your method. Preferably make it with the stable versions
Set the working directory as
/appInstall system dependencies for mesh generation and scientific computing. You can use the following lines to do this step:
RUN apt-get update && apt-get install -y
git
build-essential
gmsh
&& rm -rf /var/lib/apt/lists/*
Copy
requirements.txtfirst and install with Docker layer cachingInclude all files your method needs (interface, example input, shared geometry/helpers)
Define
CMDcommand to run the main interface file.
5. Provide an example Input File#
Add an example file named exampleInput_<Method>.json inside the folder. This file will be used as a reference for the dynamic file being created by the backend itself when simulation is to be executed.
This JSON file demonstrates how CHORAS interacts with your method.
You can follow the example at exampleInput_MyNewMethod.json.
The .json file has the following structure:
{
"absorption_coefficients": {
"floor": "0.6, 0.69, 0.71, 0.7, 0.63",
"wall1": "0.6, 0.69, 0.71, 0.7, 0.63",
"ceiling": "0.6, 0.69, 0.71, 0.7, 0.63",
"wall2": "0.6, 0.69, 0.71, 0.7, 0.63",
"wall3": "0.6, 0.69, 0.71, 0.7, 0.63",
"wall4": "0.6, 0.69, 0.71, 0.7, 0.63"
},
"msh_path": "MeasurementRoom.msh",
"geo_path": "MeasurementRoom.geo",
"simulationSettings": {
"mnm_1": 0.5,
"mnm_2": 50.0
},
"results": [
{
"percentage": 100,
"sourceX": 2,
"sourceY": 2,
"sourceZ": 1.5,
"resultType": "MyNewMethod",
"frequencies": [
125,
250,
500,
1000,
2000
],
"responses": [
{
"x": 1,
"y": 1,
"z": 1.5,
"parameters": {
"edt": [],
"t20": [],
"t30": [],
"c80": [],
"d50": [],
"ts": [],
"spl_t0_freq": []
},
"receiverResults": []
}
]
}
]
}
7. Add example settings#
Add a JSON file describing your method’s adjustable parameters in example_settings/.
Follow the format of mynewmethod_setting.json.
This file would have the following structure:
At the top level there would be an object with the two fields:
type: Specified as"SimulationSettings"options: Array of objects for settings options
Each object in that array describes one configurable parameter and uses the following fields:
name: Human‑readable label shown in the UI, e.g."MyNewMethod parameter 1"id: Internal identifier used in backend/frontend logic, e.g."mnm_1". This must be unique per method.type: Data type of the parameter value, e.g."flkoat"(other types can be added if the system supports them, such as"int","bool","string").display: How this parameter is rendered in the UI, e.g."text"for a text/number input field (could be other widgets if supported, such as sliders, dropdowns, etc.).min: Minimum allowed value for numeric types. Used for validation and UI constraints.max: Maximum allowed value for numeric types. Also used for validation and UI constraints.default: Default value if the user does not provide one. Can benullif you want to force the user or backend to set it explicitly.step: Increment used in the UI for numeric inputs (e.g. how much the value changes when the user uses arrow keys or a slider).endAdornment(optional): Optional string shown next to the field in the UI, often for units (e.g."dB","m","s"). Empty string if not needed.
Updating Method Configuration File in simulation-backend submodule#
Finally, update the root file method-config.json in the simulation-backend directory.
This file lists all available simulation methods, so CHORAS can recognize yours.
simulationType: The short name of the simulation acting as an identifiercontainerImage: Name for the container image to be madeenvVars: Dictionary of specific environment variables (if required) for Docker containerslabel: Name of the methodentryFile: Python entry point to start executionsetting: Setting file name so that it can be loaded in frontend and backendrepositoryURL: Link to the original repository of the simulation methoddocumentationURL: Link to the documentation of the simulation method
Testing the Integration of New Method with CHORAS#
Go to root CHORAS.
1. Docker Image Configuration#
Open the docker-compose.yml and add your method under services:
services:
# ... existing services ...
mynew-method: # ← Your method name (kept as service name)
platform: linux/amd64 # ← Keep unchanged
build:
context: ./simulation-backend # ← Keep unchanged
dockerfile: new_method/Dockerfile # ← Path to your Dockerfile
image: mynew_image:latest # ← EXACTLY match methods-config.json
profiles:
- sim_method # ← Keep unchanged
2. Update the Bash Script#
In the root directory, go to the CHORAS_BUILD.sh file and add the following commands based on your method before compose up:
# Export new method image for backend executor
echo "📦 Exporting MyNewMethod image..."
docker save -o backend/app/services/executors/mynew_image.tar mynew_image:latest
echo "✅ Docker image exported: mynew_image.tar"
Replace:
mynew_image.tar&mynew_image:latestwith your actual image name.
After this, delete the DB volume and container, and run the CHORAS_BUILD.sh bash command again.
Debugging the Simulation Method Execution#
If a simulation fails (you see a “Simulation Failed” alert at the top of the screen), you can inspect the underlying container logs.
Open
backend/app/services/executors/local_executor.py.Locate the line that removes the container after execution (for example, a call that stops or removes the container when it finishes).
try: client = docker.from_env() container = client.containers.run( image=image, environment=env, # JSON_PATH is the container path, valid in child too volumes={ host_uploads_dir: { "bind": container_uploads_dir, # same path in child container "mode": "rw", } }, detach=True, working_dir=self.work_dir, name=container_name, # remove = True, # ← Comment This one ) return container except Exception as e: logger.error(f"Failed to start Docker container: {e}") raise
Temporarily comment out that line so the container is not removed automatically.
Rebuild the image and container. With the container kept alive after the simulation ends, you can open your container runtime (e.g., Docker) and inspect the container logs to see detailed error messages and tracebacks for the simulation method execution.
Next steps#
If you have not yet run CHORAS fully (including frontend) please go to the Installing CHORAS page for instructions on how to install CHORAS locally.
If you have previously installed CHORAS and want to test whether you can control your simulation backend using the CHORAS frontend, please continue to Coupling your method to CHORAS.