# Results
Every engine returns the same kind of result: the same tables, the same
statistics, a recipe you can run next, and a record of how it was made.
[Outputs](../reference/outputs.md) lists every key and file; this page
explains what they mean.
## What comes back
```mermaid
flowchart LR
RUN{{run}} --> T["Tables
refined parameters · unit cell
reflections · fit profile"]
RUN --> S["Statistics
Rwp · Rexp · GoF · χ²"]
RUN --> O["Output recipe
+ parameter dispositions"]
RUN --> P["Provenance
run ID · engine · versions"]
RUN --> E["Engine's own files
and statistics"]
```
From Python, `powderline.run()` returns a dictionary with the tables as
pandas DataFrames. The same tables are written as files with fixed names, so
a script finds them without asking which engine ran.
## The same statistics for every engine
PowderLine computes Rwp, Rexp, the goodness of fit and reduced χ² itself,
with one formula, over the points inside the fit window that have a positive
weight:
$$R_{wp} = 100 \sqrt{\frac{\sum_i w_i (y_{obs,i} - y_{calc,i})^2}{\sum_i w_i y_{obs,i}^2}}, \qquad
R_{exp} = 100 \sqrt{\frac{N - P}{\sum_i w_i y_{obs,i}^2}}, \qquad
\mathrm{GoF} = \frac{R_{wp}}{R_{exp}}, \qquad \chi^2_{red} = \mathrm{GoF}^2$$
N is the number of points used and P the number of parameters the engine
varied.
Why compute them again? The engines define them differently. They count
different points, cap values at 100 %, or use one name for two quantities.
With one formula over the same points, two models of the same data can be
compared directly. The engine's own values are kept in `engine_details`.
:::{note}
A lower Rwp means *this model* fits *these points* better. It doesn't mean one
engine is better than another. [Comparing engines](comparing-engines.md) shows
why.
:::
## Did the engine do what you asked?
Two counts in `engine_details` show it:
- `parameters_requested`: the independent parameters your recipe asks to
refine, with each symmetry-tied group counted once;
- `parameters_varied`: what the engine actually varied.
Engines quietly drop or merge parameters, so when fewer are varied than
requested you get a warning. `converged` says whether the engine reached its
convergence criterion: `true`, `false`, or `null` when the engine can't tell
(TOPAS, a GSAS-II peak fit) or nothing was refined.
## The output recipe
Every result includes an **output recipe**: your recipe with the refined
values written back, symmetry-derived values in their exact form, and any
defaults stated. Your flags, bounds, controls and data are unchanged. It is a
complete recipe of the same type, ready to run again.
```mermaid
flowchart LR
R1["recipe"] --> RUN1{{run}} --> O1["output recipe"]
O1 -- "swap in the next pattern" --> RUN2{{run}} --> O2["output recipe"]
O2 --> N["…"]
```
That is what makes chaining simple: calibrant to sample, or one pattern of a
series to the next. See [Run a series](../how-to/sequential-refinement.md).
`output_recipe_valid` says whether the output recipe passes validation as
written. It fails when the engine returned a value the schema refuses, such as
a negative crystallite size or an occupancy above 1. The recipe is still
returned and written so you can see what the engine produced, and the
warning `output_recipe_not_valid` names the value. A chained next step should
stop there.
### Parameter dispositions
`parameter_dispositions` lists every refinable value by its place in the
recipe, with the refined value, its ESD, and what happened to it:
| Disposition | Meaning |
|---|---|
| `varied` | refined by the engine |
| `held_by_user` | its flag was `false` |
| `held_by_symmetry` | fixed by the space group |
| `requested_not_varied` | its flag was `true`, but the engine did not vary it |
| `default_applied` | not in your recipe; PowderLine applied a documented default |
A column `at_limit` marks values that ended on a bound.
## Provenance
A recipe's `metadata` block is yours: sample IDs, scan IDs, where the data
live in your catalog, how the recipe was made. PowderLine never reads it and
carries it through to the output recipe.
PowderLine adds one entry of its own, `metadata.powderline_provenance`, to
every output recipe:
| Key | What |
|---|---|
| `parent_run_id` | the ID of the run that produced this recipe (the result's `run_id`) |
| `schema_name` | the recipe type |
| `engine`, `engine_version` | the engine and the version that ran |
| `powderline_version` | the PowderLine version |
| `created` | when, in UTC |
Each output recipe identifies the run that produced it. PowderLine replaces
any incoming `powderline_provenance` block rather than retaining its history.
To trace a whole series, your pipeline must archive each step's input and result
and record the input recipe's `parent_run_id` alongside the new result's `run_id`.
```mermaid
flowchart LR
M["metadata: scan 1042"] --> R1[recipe]
R1 --> A["run A"]
A --> O1["output recipe
parent_run_id = A"]
O1 --> B["run B"]
B --> O2["output recipe
parent_run_id = B"]
```
## When a run fails
A failed run never returns a result. It raises one of two errors:
| Error | Meaning | Example |
|---|---|---|
| `EngineExecutionError` | The engine ran and failed | The refinement diverged |
| `ExecutionBackendError` | The engine never ran | The GSAS-II server could not start |
Both carry `.reason`, a short code, and `.result`, the full failure record.
The output folder then holds the engine's own files and `failure.json`, the
same record with its provenance, and no result tables. PowderLine removes
its report tables before each run, so a table in the folder comes from a run
that succeeded. One GSAS-II diagnostics file is the exception: see
[Report files](../reference/outputs.md#report-files).
## Simulations
A **simulation** calculates the pattern of the recipe as written, refining
nothing. Each engine has its own way to ask for one: every flag `false` plus
`refinement_cycles: 1` (GSAS-II) or `iters: 0` (TOPAS), or no flag set
(easydiffraction). The result then says `simulation_mode: true`. The statistics
are computed in the same way, so against real data they show how good your
starting values are. See [Simulate a pattern](../how-to/simulate.md).