> For the complete documentation index, see [llms.txt](https://calctree.gitbook.io/docs/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://calctree.gitbook.io/docs/integrations/graphql-api/examples/bulk-calculations-with-python.md).

# Bulk calculations with Python

## Bulk calculations with Python

Run one CalcTree calculation many times with different inputs — ideal for parametric studies, design tables, or batch checks. The simplest approach uses `simpleCalculate`, which takes inputs **by variable name**, so you don't need to look up statement IDs.

### Approach 1 — `simpleCalculate` (recommended)

Pass a dict of input variable names → values for each run. No statement-ID mapping required.

```python
import requests

URL = "https://graph.calctree.com/graphql"
HEADERS = {"Content-Type": "application/json", "x-api-key": apiKey}

QUERY = """
query SimpleCalculate($workspaceId: ID!, $calculationId: ID!, $scope: [ScopeNamedValueInput!]!) {
  simpleCalculate(workspaceId: $workspaceId, calculationId: $calculationId, scope: $scope) {
    revisionId
    scope { name value type }
  }
}
"""

def run(workspace_id, calculation_id, inputs):
    scope = [{"name": k, "value": v} for k, v in inputs.items()]
    r = requests.post(URL, headers=HEADERS, json={
        "query": QUERY,
        "variables": {"workspaceId": workspace_id, "calculationId": calculation_id, "scope": scope},
    })
    return r.json()["data"]["simpleCalculate"]["scope"]

# A parametric sweep over a beam span, keeping the load fixed
runs = [
    {"w": "10 kN/m", "span": "6 m"},
    {"w": "10 kN/m", "span": "8 m"},
    {"w": "10 kN/m", "span": "10 m"},
]

for inputs in runs:
    scope = run("your-workspace-id", "your-calculation-id", inputs)
    M = next(s for s in scope if s["name"] == "M")
    print(inputs, "->", M["value"])
```

{% hint style="warning" %}
**Pass united values as strings.** If a variable has units, send `"10 kN/m"`, not the bare number `10`. A bare number makes the variable dimensionless and silently changes downstream units. Dimensionless variables can be passed as plain numbers.
{% endhint %}

`value` is JSON-encoded; unit values use the mathjs `Unit` shape (`{"mathjs":"Unit","value":45,"unit":"kN m"}`). Parse it to extract the numeric `value`/`unit`.

### Approach 2 — `Calculate` (by statement ID)

If you need to override **formulas** (not just input values), use `Calculate`. First call `GetCalculation` to fetch each `statementId`, then submit `StatementInput` objects (`{ statementId, formula }`). This is more verbose but lets you rewrite the formula text, not only substitute values.

### Neither of these saves changes

`simpleCalculate` and `calculate` are **evaluate-only** — they never modify the stored calculation. To persist results or build calculations programmatically, use `createOrUpdateCalculation`.
