Skip to content

Python API ​

Signatures and docstrings of the public functions and classes in reflectosim at main (106f083), read from the source without importing it. The guides on this site say how the pieces fit together; this page is for looking up an argument.

reflectosim.cli ​

Command line: reflectosim sim | describe.

main ​

python
def main(argv: list[str] | None=None) -> int

reflectosim.dataset ​

Dataset files: HDF5 (with the `hdf5` extra) or compressed npz, chosen by the file suffix.

Arrays: `q` (Q,), `counts` and `reflectivity` (n, Q), `counts_scale` (n,), and one (n,) array per
parameter under `params/<name>` (HDF5) or `params.<name>` (npz). The metadata is one JSON string with
the priors, the seed, the resolution node count, the package versions and the conventions, enough
to regenerate the file.

metadata ​

python
def metadata(
    batch: Batch,
    stack: priors.StackPrior,
    instrument: priors.InstrumentPrior,
) -> dict

write ​

python
def write(
    path: str | Path,
    batch: Batch,
    stack: priors.StackPrior,
    instrument: priors.InstrumentPrior,
) -> Path

read ​

python
def read(path: str | Path) -> tuple[dict[str, np.ndarray], dict[str, np.ndarray], dict]
(arrays, params, metadata) of a dataset file.

reflectosim.noise ​

Counting noise for simulated curves (ReflectoFit DESIGN.md section 2, Counts).

poisson_counts ​

python
def poisson_counts(
    reflectivity: NDArray,
    counts_scale: NDArray | float,
    rng: np.random.Generator,
    dark: float = 0.0,
    read_sigma: float = 0.0,
) -> NDArray
Counts y ~ Poisson(S · R + dark) + N(0, read_sigma), S the counts at R = 1 per row.

`reflectivity` (B, Q) is the observed reflectivity before noise (I0 and background included);
`counts_scale` is S per row (B,) or one value. Dark counts and read noise are detector terms on
top of the background already in R; both default to off.

reflectosim.priors ​

Priors over structures and instruments.

Ranges are (low, high) tuples drawn uniformly; a range with low == high is a fixed value. Units as in
ReflectoFit: Å, 1e-6 Å⁻², Å⁻¹, degrees, mm.

OxidePrior ​

python
@dataclass(frozen=True, kw_only=True)
class OxidePrior:
    thickness: Range = (5.0, 25.0)
    roughness: Range = (1.0, 5.0)
    sld: Range = (17.2, 19.7)
    isld_ratio: Range = (0.013, 0.013)
A native oxide layer; the defaults are amorphous SiO₂ (2.0-2.3 g/cm³) on a Si wafer.

SubstratePrior ​

python
@dataclass(frozen=True, kw_only=True)
class SubstratePrior:
    sld: complex = field(default_factory=lambda: materials.sld('Si', 2.33))
    roughness: Range = (1.0, 5.0)

StackPrior ​

python
@dataclass(frozen=True, kw_only=True)
class StackPrior:
    n_layers: tuple[int, int]
    thickness: Range
    sld: Range
    oxide: Literal['under', 'over', 'none']
    roughness: Range = (0.0, 10.0)
    roughness_max_ratio: float | None = 0.25
    isld_ratio: Range = (0.0, 0.0)
    min_contrast: float = 0.0
    oxide_prior: OxidePrior = field(default_factory=OxidePrior)
    substrate: SubstratePrior = field(default_factory=SubstratePrior)
Random films on a substrate, top first.

`oxide` has no default on purpose: whether the native oxide lies under the film stack ("under",
on the substrate), on top of it ("over") or is absent ("none") changes the curves by tens of
percent and is an open decision (NaNIsaac DECISIONS #19); every prior states it.
Roughness is drawn from U[lo, min(hi, roughness_max_ratio · d)] for each layer. Adjacent media
(layer on layer, and the lowest layer on the medium below it) differ in Re SLD by at least
`min_contrast`; rows that fail are redrawn.

InstrumentPrior ​

python
@dataclass(frozen=True, kw_only=True)
class InstrumentPrior:
    sigma_q: Range = (0.0, 0.0)
    dq_over_q: Range = (0.0, 0.0)
    tth_offset: Range = (0.0, 0.0)
    i0: Range = (1.0, 1.0)
    log_background: Range | None = None
    kalpha2_ratio: Range = (0.0, 0.0)
    sample_length: Range | None = None
    beam_sigma: Range | None = None
    log_counts: Range = (8.0, 8.0)
    wavelength: float = 1.5406
    nodes: int | None = None
Per-curve instrument values. None switches a term off (footprint, background).

draw_stacks ​

python
def draw_stacks(
    prior: StackPrior,
    n: int,
    rng: np.random.Generator,
) -> dict[str, np.ndarray]
Parameter table of n stacks: layer{j}.{thickness,roughness,sld,isld} (NaN where a row has
fewer layers), oxide.* when present, substrate.*, n_layers.

draw_instruments ​

python
def draw_instruments(
    prior: InstrumentPrior,
    n: int,
    rng: np.random.Generator,
) -> dict[str, np.ndarray]

to_dict ​

python
def to_dict(prior) -> dict
JSON-ready form (complex as [re, im]).

load ​

python
def load(path: str | Path) -> tuple[StackPrior, InstrumentPrior]
Read a prior TOML: [stack] (with `oxide`), optional [oxide], [substrate], [instrument].

from_metadata ​

python
def from_metadata(meta: dict) -> tuple[StackPrior, InstrumentPrior]
The priors stored in a dataset's metadata (`dataset.read`), to regenerate it.

reflectosim.simulate ​

Draw stacks and instruments from priors and simulate their curves with ReflectoFit.

Curves before noise are `reflectofit.forward` for each row (this package has no physics of its own).
Rows with fewer layers than the prior's maximum are padded with zero-thickness layers that match the
medium below, which leaves the curve unchanged. The resolution nodes are chosen per curve (or fixed
by the prior), so a row's curve does not depend on how the work is chunked.

Batch ​

python
@dataclass
class Batch:
    q: NDArray
    params: dict[str, NDArray]
    packed: tuple[NDArray, NDArray, NDArray]
    n_layers: NDArray
    counts_scale: NDArray
    reflectivity: NDArray
    counts: NDArray
    oxide: str
    nodes: int | None
    seed: object

pack ​

python
def pack(prior: StackPrior, p: dict[str, NDArray]) -> tuple[NDArray, NDArray, NDArray]
(n, N) media arrays, ambient first: [ambient, oxide if over, layers padded, oxide if under,
substrate]. A missing layer copies the SLD of the medium below its stack, has zero thickness,
and carries that medium's roughness on its top interface, so it is invisible.

simulate ​

python
def simulate(
    prior: StackPrior,
    instrument: InstrumentPrior,
    q: NDArray,
    n: int,
    seed=0,
    chunk: int = 4096,
) -> Batch
n curves on the q grid [Å⁻¹], with structure and instrument drawn from the priors.

`seed` is an int or a tuple of ints (as ReflectoLearn#35: (20261024, n, j)); the parameters and
the noise use separate streams spawned from it.

Each project section is built from that project’s docs/ directory.