API Reference
This page provides detailed documentation for PowderLine’s Python API.
Schema Module
Pydantic models for recipe validation.
Pydantic models for validating GSAS-II refinement recipe JSON files.
Schema 0.25 introduced a two-tier structure: schema_name + payload pattern. This enables distinct validation rules for Rietveld vs single peak fitting workflows.
Schema 0.26 changes recipe semantics without changing recipe shape: per-parameter refine flags are now honored for unit-cell parameters, atomic coordinates, and anisotropic displacement components (previously collapsed into GSAS-II’s lumped whole-cell / per-atom flags). A parameter refines iff it is present with refine_flag=true; absent or false means fixed. Symmetry-linked parameters (e.g. cubic a=b=c) refine together if any member is requested. See docs/SCHEMA_HISTORY.md.
- class powderline.schema.RefinementParameterModel(*, value, refine_flag, min_val=None, max_val=None)[source]
Bases:
BaseModelModel for the standard [value, refine_flag, min, max] parameter format.
- Parameters:
- model_config: ClassVar[ConfigDict] = {'extra': 'forbid'}
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- class powderline.schema.InstrumentBroadening(*, U=None, V=None, W=None, X=None, Y=None, Z=None, **extra_data)[source]
Bases:
BaseModelInstrument broadening parameters (Thompson-Cox-Hastings pseudo-Voigt).
- Parameters:
U (Annotated[tuple[float | None, bool | None, float | None, float | None], PlainSerializer(func=~powderline.schema.<lambda>, return_type=list, when_used=json)] | None)
V (Annotated[tuple[float | None, bool | None, float | None, float | None], PlainSerializer(func=~powderline.schema.<lambda>, return_type=list, when_used=json)] | None)
W (Annotated[tuple[float | None, bool | None, float | None, float | None], PlainSerializer(func=~powderline.schema.<lambda>, return_type=list, when_used=json)] | None)
X (Annotated[tuple[float | None, bool | None, float | None, float | None], PlainSerializer(func=~powderline.schema.<lambda>, return_type=list, when_used=json)] | None)
Y (Annotated[tuple[float | None, bool | None, float | None, float | None], PlainSerializer(func=~powderline.schema.<lambda>, return_type=list, when_used=json)] | None)
Z (Annotated[tuple[float | None, bool | None, float | None, float | None], PlainSerializer(func=~powderline.schema.<lambda>, return_type=list, when_used=json)] | None)
extra_data (Any)
- model_config: ClassVar[ConfigDict] = {'extra': 'allow'}
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- U: <lambda>, return_type=list, when_used=json)] | None
- V: <lambda>, return_type=list, when_used=json)] | None
- W: <lambda>, return_type=list, when_used=json)] | None
- X: <lambda>, return_type=list, when_used=json)] | None
- Y: <lambda>, return_type=list, when_used=json)] | None
- Z: <lambda>, return_type=list, when_used=json)] | None
- class powderline.schema.InstrumentCorrections(*, zero_shift=None, axial_divergence=None, **extra_data)[source]
Bases:
BaseModelInstrument correction parameters.
- Parameters:
zero_shift (Annotated[tuple[float | None, bool | None, float | None, float | None], PlainSerializer(func=~powderline.schema.<lambda>, return_type=list, when_used=json)] | None)
axial_divergence (Annotated[tuple[float | None, bool | None, float | None, float | None], PlainSerializer(func=~powderline.schema.<lambda>, return_type=list, when_used=json)] | None)
extra_data (Any)
- model_config: ClassVar[ConfigDict] = {'extra': 'allow'}
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- zero_shift: <lambda>, return_type=list, when_used=json)] | None
- axial_divergence: <lambda>, return_type=list, when_used=json)] | None
- class powderline.schema.InstrumentParameterization(*, wavelength=None, polarization=None, broadening=None, corrections=None, **extra_data)[source]
Bases:
BaseModelInstrument parameter settings for refinement.
- Parameters:
wavelength (Annotated[tuple[float | None, bool | None, float | None, float | None], PlainSerializer(func=~powderline.schema.<lambda>, return_type=list, when_used=json)] | None)
polarization (Annotated[tuple[float | None, bool | None, float | None, float | None], PlainSerializer(func=~powderline.schema.<lambda>, return_type=list, when_used=json)] | None)
broadening (InstrumentBroadening | None)
corrections (InstrumentCorrections | None)
extra_data (Any)
- model_config: ClassVar[ConfigDict] = {'extra': 'allow'}
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- wavelength: <lambda>, return_type=list, when_used=json)] | None
- polarization: <lambda>, return_type=list, when_used=json)] | None
- broadening: InstrumentBroadening | None
- corrections: InstrumentCorrections | None
- class powderline.schema.InstrumentModel(*, description, initialization, parameterization=None, **extra_data)[source]
Bases:
BaseModelInstrument configuration.
- Parameters:
- model_config: ClassVar[ConfigDict] = {'extra': 'allow'}
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- parameterization: InstrumentParameterization | None
- class powderline.schema.ChebyshevBackground(*, num_coefficients, coefficients, refine_flag, **extra_data)[source]
Bases:
BaseModelChebyshev polynomial background.
- model_config: ClassVar[ConfigDict] = {'extra': 'allow'}
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- class powderline.schema.SinglePeaksBackground(*, positions=None, intensities=None, pv_gaussian_sigma=None, pv_lorentzian_gamma=None, **extra_data)[source]
Bases:
BaseModelSingle peak background parameters (for background.single_peaks).
Width convention: uses Gaussian sigma (σ), not sigma squared (σ²). This is the natural convention for describing peak widths and matches scipy/TOPAS usage. Contrast with
SinglePeaks(peak-list peaks) which uses σ² to match GSAS-II’s internal Peak List storage format. See also:SinglePeaks.pv_gaussian_sigma_sq.- Parameters:
positions (list[Annotated[tuple[float | None, bool | None, float | None, float | None], PlainSerializer(func=~powderline.schema.<lambda>, return_type=list, when_used=json)]] | None)
intensities (list[Annotated[tuple[float | None, bool | None, float | None, float | None], PlainSerializer(func=~powderline.schema.<lambda>, return_type=list, when_used=json)]] | None)
pv_gaussian_sigma (list[Annotated[tuple[float | None, bool | None, float | None, float | None], PlainSerializer(func=~powderline.schema.<lambda>, return_type=list, when_used=json)]] | None)
pv_lorentzian_gamma (list[Annotated[tuple[float | None, bool | None, float | None, float | None], PlainSerializer(func=~powderline.schema.<lambda>, return_type=list, when_used=json)]] | None)
extra_data (Any)
- model_config: ClassVar[ConfigDict] = {'extra': 'allow'}
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- positions: list[~typing.Annotated[tuple[float | None, bool | None, float | None, float | None], ~pydantic.functional_serializers.PlainSerializer(func=~powderline.schema.<lambda>, return_type=list, when_used=json)]] | None
- intensities: list[~typing.Annotated[tuple[float | None, bool | None, float | None, float | None], ~pydantic.functional_serializers.PlainSerializer(func=~powderline.schema.<lambda>, return_type=list, when_used=json)]] | None
- pv_gaussian_sigma: list[~typing.Annotated[tuple[float | None, bool | None, float | None, float | None], ~pydantic.functional_serializers.PlainSerializer(func=~powderline.schema.<lambda>, return_type=list, when_used=json)]] | None
- pv_lorentzian_gamma: list[~typing.Annotated[tuple[float | None, bool | None, float | None, float | None], ~pydantic.functional_serializers.PlainSerializer(func=~powderline.schema.<lambda>, return_type=list, when_used=json)]] | None
- class powderline.schema.SinglePeaks(*, positions=None, intensities=None, pv_gaussian_sigma_sq=None, pv_lorentzian_gamma=None, **extra_data)[source]
Bases:
BaseModelSingle peak fitting parameters (for top-level single_peaks).
These peaks are fitted in the Peak List, allowing individual peak refinement independent of phase structure.
- Parameters:
positions (list[Annotated[tuple[float | None, bool | None, float | None, float | None], PlainSerializer(func=~powderline.schema.<lambda>, return_type=list, when_used=json)]] | None)
intensities (list[Annotated[tuple[float | None, bool | None, float | None, float | None], PlainSerializer(func=~powderline.schema.<lambda>, return_type=list, when_used=json)]] | None)
pv_gaussian_sigma_sq (list[Annotated[tuple[float | None, bool | None, float | None, float | None], PlainSerializer(func=~powderline.schema.<lambda>, return_type=list, when_used=json)]] | None)
pv_lorentzian_gamma (list[Annotated[tuple[float | None, bool | None, float | None, float | None], PlainSerializer(func=~powderline.schema.<lambda>, return_type=list, when_used=json)]] | None)
extra_data (Any)
- model_config: ClassVar[ConfigDict] = {'extra': 'allow'}
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- positions: list[~typing.Annotated[tuple[float | None, bool | None, float | None, float | None], ~pydantic.functional_serializers.PlainSerializer(func=~powderline.schema.<lambda>, return_type=list, when_used=json)]] | None
- intensities: list[~typing.Annotated[tuple[float | None, bool | None, float | None, float | None], ~pydantic.functional_serializers.PlainSerializer(func=~powderline.schema.<lambda>, return_type=list, when_used=json)]] | None
- pv_gaussian_sigma_sq: list[~typing.Annotated[tuple[float | None, bool | None, float | None, float | None], ~pydantic.functional_serializers.PlainSerializer(func=~powderline.schema.<lambda>, return_type=list, when_used=json)]] | None
- pv_lorentzian_gamma: list[~typing.Annotated[tuple[float | None, bool | None, float | None, float | None], ~pydantic.functional_serializers.PlainSerializer(func=~powderline.schema.<lambda>, return_type=list, when_used=json)]] | None
- class powderline.schema.BackgroundModel(*, chebyshev=None, single_peaks=None, **extra_data)[source]
Bases:
BaseModelBackground model configuration.
- Parameters:
chebyshev (ChebyshevBackground | None)
single_peaks (SinglePeaksBackground | None)
extra_data (Any)
- model_config: ClassVar[ConfigDict] = {'extra': 'allow'}
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- chebyshev: ChebyshevBackground | None
- single_peaks: SinglePeaksBackground | None
- class powderline.schema.SinglePeakFittingMode(*, use_instrument_profile, **extra_data)[source]
Bases:
BaseModelSingle peak fitting mode configuration.
Schema 0.25 Addition: Required for GSASII_SPF schema.
- model_config: ClassVar[ConfigDict] = {'extra': 'allow'}
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- class powderline.schema.RefinementControls(*, refinement_cycles=5, refinement_algorithm=None, single_peak_fitting_mode=None, **extra_data)[source]
Bases:
BaseModelControls for refinement execution.
Schema 0.25 Simplification: Removed multi-strategy refinement system from 0.24. PowderLine now executes a single refinement pass (proj.refine() for Rietveld, hist.refine_peaks() for SPF).
Future algorithm selection (e.g., Powell vs Levenberg-Marquardt) may be controlled via refinement_algorithm field.
- Parameters:
refinement_cycles (int)
refinement_algorithm (str | None)
single_peak_fitting_mode (SinglePeakFittingMode | None)
extra_data (Any)
- model_config: ClassVar[ConfigDict] = {'extra': 'allow'}
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- single_peak_fitting_mode: SinglePeakFittingMode | None
- class powderline.schema.UnitCellParameters(*, a=None, b=None, c=None, alpha=None, beta=None, gamma=None, **extra_data)[source]
Bases:
BaseModelUnit cell parameters (a, b, c, alpha, beta, gamma).
Schema 0.26 semantics: each parameter refines iff it is present with refine_flag=true; absent or false means fixed (held). Parameters that are symmetry-linked for the phase’s Laue class (e.g. cubic a=b=c, or the coupled monoclinic a/c/beta) refine together if any member is requested; flags on symmetry-fixed parameters (e.g. cubic angles) have no effect. Listing only the parameters you wish to refine is equivalent to listing all six with explicit flags.
- Parameters:
a (Annotated[tuple[float | None, bool | None, float | None, float | None], PlainSerializer(func=~powderline.schema.<lambda>, return_type=list, when_used=json)] | None)
b (Annotated[tuple[float | None, bool | None, float | None, float | None], PlainSerializer(func=~powderline.schema.<lambda>, return_type=list, when_used=json)] | None)
c (Annotated[tuple[float | None, bool | None, float | None, float | None], PlainSerializer(func=~powderline.schema.<lambda>, return_type=list, when_used=json)] | None)
alpha (Annotated[tuple[float | None, bool | None, float | None, float | None], PlainSerializer(func=~powderline.schema.<lambda>, return_type=list, when_used=json)] | None)
beta (Annotated[tuple[float | None, bool | None, float | None, float | None], PlainSerializer(func=~powderline.schema.<lambda>, return_type=list, when_used=json)] | None)
gamma (Annotated[tuple[float | None, bool | None, float | None, float | None], PlainSerializer(func=~powderline.schema.<lambda>, return_type=list, when_used=json)] | None)
extra_data (Any)
- model_config: ClassVar[ConfigDict] = {'extra': 'allow'}
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- a: <lambda>, return_type=list, when_used=json)] | None
- b: <lambda>, return_type=list, when_used=json)] | None
- c: <lambda>, return_type=list, when_used=json)] | None
- alpha: <lambda>, return_type=list, when_used=json)] | None
- beta: <lambda>, return_type=list, when_used=json)] | None
- gamma: <lambda>, return_type=list, when_used=json)] | None
- class powderline.schema.AtomParameters(*, x=None, y=None, z=None, occupancy=None, ADP, Uiso=None, Uaniso=None, **extra_data)[source]
Bases:
BaseModelAtomic position and displacement parameters.
Schema 0.26 semantics: each coordinate (x/y/z) and each anisotropic Uaniso component refines iff present with refine_flag=true; absent or false means fixed (held). Site-symmetry-linked components refine together if any member is requested; symmetry-fixed components ignore their flags.
- Parameters:
x (Annotated[tuple[float | None, bool | None, float | None, float | None], PlainSerializer(func=~powderline.schema.<lambda>, return_type=list, when_used=json)] | None)
y (Annotated[tuple[float | None, bool | None, float | None, float | None], PlainSerializer(func=~powderline.schema.<lambda>, return_type=list, when_used=json)] | None)
z (Annotated[tuple[float | None, bool | None, float | None, float | None], PlainSerializer(func=~powderline.schema.<lambda>, return_type=list, when_used=json)] | None)
occupancy (Annotated[tuple[float | None, bool | None, float | None, float | None], PlainSerializer(func=~powderline.schema.<lambda>, return_type=list, when_used=json)] | None)
ADP (str)
Uiso (Annotated[tuple[float | None, bool | None, float | None, float | None], PlainSerializer(func=~powderline.schema.<lambda>, return_type=list, when_used=json)] | None)
Uaniso (dict[str, Annotated[tuple[float | None, bool | None, float | None, float | None], PlainSerializer(func=~powderline.schema.<lambda>, return_type=list, when_used=json)] | None] | None)
extra_data (Any)
- model_config: ClassVar[ConfigDict] = {'extra': 'allow'}
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- x: <lambda>, return_type=list, when_used=json)] | None
- y: <lambda>, return_type=list, when_used=json)] | None
- z: <lambda>, return_type=list, when_used=json)] | None
- occupancy: <lambda>, return_type=list, when_used=json)] | None
- Uiso: <lambda>, return_type=list, when_used=json)] | None
- Uaniso: dict[str, ~typing.Annotated[tuple[float | None, bool | None, float | None, float | None], ~pydantic.functional_serializers.PlainSerializer(func=~powderline.schema.<lambda>, return_type=list, when_used=json)] | None] | None
- class powderline.schema.SizeBroadening(*, model='isotropic', isotropic_size=None, uniaxial_equatorial=None, uniaxial_axial=None, hkl_direction=None, S11=None, S22=None, S33=None, S12=None, S13=None, S23=None, LG_eta=None, **extra_data)[source]
Bases:
BaseModelCrystallite size broadening parameters.
Schema 0.25 Change: Renamed size to isotropic_size to prepare for future uniaxial/ellipsoidal size broadening support. Added model field to specify broadening geometry (isotropic, uniaxial, ellipsoidal).
Models: - isotropic: Single size parameter (currently implemented) - uniaxial: Equatorial and axial sizes with hkl direction (future) - ellipsoidal: Full S11-S23 tensor (future)
- Parameters:
model (Literal['isotropic', 'uniaxial', 'ellipsoidal'])
isotropic_size (Annotated[tuple[float | None, bool | None, float | None, float | None], PlainSerializer(func=~powderline.schema.<lambda>, return_type=list, when_used=json)] | None)
uniaxial_equatorial (Annotated[tuple[float | None, bool | None, float | None, float | None], PlainSerializer(func=~powderline.schema.<lambda>, return_type=list, when_used=json)] | None)
uniaxial_axial (Annotated[tuple[float | None, bool | None, float | None, float | None], PlainSerializer(func=~powderline.schema.<lambda>, return_type=list, when_used=json)] | None)
S11 (Annotated[tuple[float | None, bool | None, float | None, float | None], PlainSerializer(func=~powderline.schema.<lambda>, return_type=list, when_used=json)] | None)
S22 (Annotated[tuple[float | None, bool | None, float | None, float | None], PlainSerializer(func=~powderline.schema.<lambda>, return_type=list, when_used=json)] | None)
S33 (Annotated[tuple[float | None, bool | None, float | None, float | None], PlainSerializer(func=~powderline.schema.<lambda>, return_type=list, when_used=json)] | None)
S12 (Annotated[tuple[float | None, bool | None, float | None, float | None], PlainSerializer(func=~powderline.schema.<lambda>, return_type=list, when_used=json)] | None)
S13 (Annotated[tuple[float | None, bool | None, float | None, float | None], PlainSerializer(func=~powderline.schema.<lambda>, return_type=list, when_used=json)] | None)
S23 (Annotated[tuple[float | None, bool | None, float | None, float | None], PlainSerializer(func=~powderline.schema.<lambda>, return_type=list, when_used=json)] | None)
LG_eta (Annotated[tuple[float | None, bool | None, float | None, float | None], PlainSerializer(func=~powderline.schema.<lambda>, return_type=list, when_used=json)] | None)
extra_data (Any)
- model_config: ClassVar[ConfigDict] = {'extra': 'allow'}
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- isotropic_size: <lambda>, return_type=list, when_used=json)] | None
- uniaxial_equatorial: <lambda>, return_type=list, when_used=json)] | None
- uniaxial_axial: <lambda>, return_type=list, when_used=json)] | None
- S11: <lambda>, return_type=list, when_used=json)] | None
- S22: <lambda>, return_type=list, when_used=json)] | None
- S33: <lambda>, return_type=list, when_used=json)] | None
- S12: <lambda>, return_type=list, when_used=json)] | None
- S13: <lambda>, return_type=list, when_used=json)] | None
- S23: <lambda>, return_type=list, when_used=json)] | None
- LG_eta: <lambda>, return_type=list, when_used=json)] | None
- class powderline.schema.StrainBroadening(*, model='isotropic', isotropic_strain=None, uniaxial_equatorial=None, uniaxial_axial=None, hkl_direction=None, stephens_parameters=None, LG_eta=None, **extra_data)[source]
Bases:
BaseModelMicrostrain broadening parameters.
Schema 0.25 Change: Renamed strain to isotropic_strain to prepare for future uniaxial/generalized strain broadening support. Added model field to specify strain model (isotropic, uniaxial, generalized).
Models: - isotropic: Single strain parameter (currently implemented) - uniaxial: Equatorial and axial strains with hkl direction (future) - generalized: Stephens model - symmetry-dependent parameters based on Laue class (future)
Note: The generalized Stephens model requires complex parameterization that depends on the crystal symmetry (Laue class). Implementation deferred to Phase 2.
- Parameters:
model (Literal['isotropic', 'uniaxial', 'generalized'])
isotropic_strain (Annotated[tuple[float | None, bool | None, float | None, float | None], PlainSerializer(func=~powderline.schema.<lambda>, return_type=list, when_used=json)] | None)
uniaxial_equatorial (Annotated[tuple[float | None, bool | None, float | None, float | None], PlainSerializer(func=~powderline.schema.<lambda>, return_type=list, when_used=json)] | None)
uniaxial_axial (Annotated[tuple[float | None, bool | None, float | None, float | None], PlainSerializer(func=~powderline.schema.<lambda>, return_type=list, when_used=json)] | None)
stephens_parameters (dict[str, Annotated[tuple[float | None, bool | None, float | None, float | None], PlainSerializer(func=~powderline.schema.<lambda>, return_type=list, when_used=json)]] | None)
LG_eta (Annotated[tuple[float | None, bool | None, float | None, float | None], PlainSerializer(func=~powderline.schema.<lambda>, return_type=list, when_used=json)] | None)
extra_data (Any)
- model_config: ClassVar[ConfigDict] = {'extra': 'allow'}
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- isotropic_strain: <lambda>, return_type=list, when_used=json)] | None
- uniaxial_equatorial: <lambda>, return_type=list, when_used=json)] | None
- uniaxial_axial: <lambda>, return_type=list, when_used=json)] | None
- stephens_parameters: dict[str, ~typing.Annotated[tuple[float | None, bool | None, float | None, float | None], ~pydantic.functional_serializers.PlainSerializer(func=~powderline.schema.<lambda>, return_type=list, when_used=json)]] | None
- LG_eta: <lambda>, return_type=list, when_used=json)] | None
- class powderline.schema.PeakBroadening(*, size_broadening=None, strain_broadening=None, **extra_data)[source]
Bases:
BaseModelPhase-specific peak broadening from size and strain.
Schema 0.25 Change: Model field moved to individual size_broadening and strain_broadening classes to allow independent model selection.
- Parameters:
size_broadening (SizeBroadening | None)
strain_broadening (StrainBroadening | None)
extra_data (Any)
- model_config: ClassVar[ConfigDict] = {'extra': 'allow'}
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- size_broadening: SizeBroadening | None
- strain_broadening: StrainBroadening | None
- class powderline.schema.PhaseParameterization(*, scale=None, unit_cell=None, atoms=None, peak_broadening=None, **extra_data)[source]
Bases:
BaseModelPhase-specific refinement parameters.
- Parameters:
scale (Annotated[tuple[float | None, bool | None, float | None, float | None], PlainSerializer(func=~powderline.schema.<lambda>, return_type=list, when_used=json)] | None)
unit_cell (UnitCellParameters | None)
atoms (dict[str, AtomParameters] | None)
peak_broadening (PeakBroadening | None)
extra_data (Any)
- model_config: ClassVar[ConfigDict] = {'extra': 'allow'}
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- scale: <lambda>, return_type=list, when_used=json)] | None
- unit_cell: UnitCellParameters | None
- atoms: dict[str, AtomParameters] | None
- peak_broadening: PeakBroadening | None
- class powderline.schema.AtomStructure(*, element, x, y, z, occupancy=1.0, Multiplicity=None, ADP, Uiso=None, Uaniso=None, **extra_data)[source]
Bases:
BaseModelAtomic structure definition.
- Parameters:
- model_config: ClassVar[ConfigDict] = {'extra': 'allow'}
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- class powderline.schema.UnitCellStructure(*, a, b, c, alpha, beta, gamma, volume=None, **extra_data)[source]
Bases:
BaseModelUnit cell structure (actual values, not refinement parameters).
- Parameters:
- model_config: ClassVar[ConfigDict] = {'extra': 'allow'}
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- class powderline.schema.PhaseStructure(*, phase_name, space_group, unit_cell, atoms, **extra_data)[source]
Bases:
BaseModelPhase structure definition.
- Parameters:
phase_name (str)
space_group (str)
unit_cell (UnitCellStructure)
atoms (dict[str, AtomStructure])
extra_data (Any)
- model_config: ClassVar[ConfigDict] = {'extra': 'allow'}
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- unit_cell: UnitCellStructure
- atoms: dict[str, AtomStructure]
- class powderline.schema.PhaseModel(*, structure, parameterization=None, **extra_data)[source]
Bases:
BaseModelComplete phase definition.
- Parameters:
structure (PhaseStructure)
parameterization (PhaseParameterization | None)
extra_data (Any)
- model_config: ClassVar[ConfigDict] = {'extra': 'allow'}
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- structure: PhaseStructure
- parameterization: PhaseParameterization | None
- class powderline.schema.XRDDataModel(*, tth, Itth, Itth_weights, filename=None, **extra_data)[source]
Bases:
BaseModelXRD data arrays.
- Parameters:
- model_config: ClassVar[ConfigDict] = {'extra': 'allow'}
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- validate_arrays_wellformed()[source]
Reject ill-formed XRD data. PowderLine never repairs data — it rejects it.
Transforming raw data (unit conversion, weight derivation, handling background-subtracted negatives) is the job of the reader/parser that builds this block, not PowderLine. Here we only enforce that what arrives is usable:
arrays must be non-empty;
every tth / Itth / Itth_weights value must be finite (no NaN or inf) — this catches, e.g., a weight computed as 1/esd**2 with esd == 0 (inf);
tth must be strictly increasing (a powder pattern is monotonic in 2-theta);
weights must be >= 0 (a 0 weight legitimately excludes a point; a negative weight is nonsensical) and at least one weight must be > 0 (all-zero = nothing to fit).
A negative intensity is explicitly allowed: background-subtracted data legitimately dips below zero, so Itth is checked for finiteness only, not sign.
- class powderline.schema.PayloadModel(*, xrd_data, instrument=None, phases=None, asset_path=None, fit_range=None, background=None, single_peaks=None, refinement_controls, **extra_data)[source]
Bases:
BaseModelRefinement data payload containing all refinement parameters.
Payload structure: The payload contains recipe-specific refinement data, separated from top-level metadata (schema_name, schema_version). This allows distinct validation rules for different refinement types (Rietveld vs SPF) while maintaining a consistent outer structure.
Type Preservation: Refinement parameters use [value, refine_flag, min, max] format where refine_flag must remain boolean. Always export with model_dump(mode=’json’) to preserve types.
Validation rules: - GSASII_Rietveld: Requires phases and instrument - GSASII_SPF: Requires single_peaks, forbids phases
- Parameters:
xrd_data (XRDDataModel)
instrument (InstrumentModel | None)
phases (dict[str, PhaseModel] | None)
asset_path (str | None)
background (BackgroundModel | None)
single_peaks (SinglePeaks | None)
refinement_controls (RefinementControls)
extra_data (Any)
- model_config: ClassVar[ConfigDict] = {'extra': 'allow'}
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- xrd_data: XRDDataModel
- instrument: InstrumentModel | None
- phases: dict[str, PhaseModel] | None
- background: BackgroundModel | None
- single_peaks: SinglePeaks | None
- refinement_controls: RefinementControls
- class powderline.schema.RecipeModel(*, schema_name, schema_version, payload, **extra_data)[source]
Bases:
BaseModelTop-level refinement recipe model for schema 0.26.
Architecture: Two-tier structure (since schema 0.25) with schema metadata and payload:
{ "schema_name": "GSASII_Rietveld", "schema_version": "0.26.0", "payload": { "xrd_data": {...}, "phases": {...}, ... } }
Schema Types:
GSASII_Rietveld: Full Rietveld refinement (requires phases + instrument)GSASII_SPF: Single peak fitting only (requires single_peaks, forbids phases)
Validation Rules:
GSASII_Rietveld:
payload.phasesmust be present,payload.instrumentrequiredGSASII_SPF:
payload.single_peaksmust be present,payload.phasesmust be None
Breaking Changes from 0.24:
Removed multi-strategy refinement system (strategy, spf_first, iterative_cycles, etc.)
Removed sample_name, recipe_description, software_package from payload
Added schema_name for explicit workflow type declaration
Payload structure replaces flat top-level fields
Migration from 0.24 to 0.25:
// Old (0.24): { "schema_version": "0.24", "sample_name": "LaB6", "xrd_data": {...}, "phases": {...}, "refinement_controls": { "strategy": "structural_only", "refinement_cycles": 5 } } // New (0.25): { "schema_name": "GSASII_Rietveld", "schema_version": "0.26.0", "payload": { "xrd_data": {...}, "phases": {...}, "refinement_controls": { "refinement_cycles": 5 } } }
- Parameters:
schema_name (Literal['GSASII_Rietveld', 'GSASII_SPF'])
schema_version (str)
payload (PayloadModel)
extra_data (Any)
- model_config: ClassVar[ConfigDict] = {'extra': 'allow'}
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- payload: PayloadModel
Kicker Module
Main refinement workflow and parameter setting functions.
Key Functions
Template and Validation
- powderline.kicker.is_template_file(recipe_dict, input_path)[source]
Detect if the recipe file is a template that shouldn’t be run directly.
Uses two-level detection strategy: 1. Path contains “template” (case-insensitive) 2. Missing required fields based on schema_name (for GSASII_Rietveld or GSASII_SPF)
- Parameters:
- Returns:
A 2-tuple
(is_template, reason).is_templateis True if this appears to be a template, andreasonexplains why it was detected as a template. If not a template, returns(False, None).- Return type:
Examples
>>> is_template_file({}, Path("example_template/input.json")) (True, "filename or path contains 'template'")
>>> is_template_file({"schema_name": "GSASII_Rietveld", "payload": {"xrd_data": {...}}}, Path("example_LaB6/input.json")) (False, None)
Output Generation
Functions for exporting refinement results with uncertainty quantification.
- powderline.kicker.export_refined_parameters_csv(param_dict, output_file, proj=None, include_category=True)[source]
Export refined parameters to CSV file and return the DataFrame.
- Parameters:
param_dict (Dict[str, Dict[str, Any]]) – Dictionary from extract_refined_params_* functions
output_file (Path) – Path to output CSV file
proj (Any) – GSAS-II project object (optional, needed for phase/atom names)
include_category (bool) – If True, add ‘category’ and ‘descriptive_name’ columns (default: True)
- Returns:
DataFrame with the exported parameters, or None if param_dict is empty.
- Return type:
DataFrame | None
- Output CSV / DataFrame columns:
parameter_name: GSAS-II internal parameter name
descriptive_name: Human-readable parameter description (if include_category=True)
phase_name: Name of associated phase (None if not phase-specific)
phase_idx: Index of associated phase (None if not phase-specific)
atom_name: Label of associated atom (None if not atom-specific)
atom_idx: Index of associated atom (None if not atom-specific)
value: Refined value
esd: Estimated standard deviation (None for fixed parameters)
category: Parameter category (instrument, background, cell, etc.) if include_category=True
- powderline.kicker.calculate_cell_esds_from_A_matrix(phase_idx, proj, phase_name)[source]
Calculate unit cell parameter ESDs using GSAS-II’s reciprocal metric tensor conversion.
GSAS-II refines reciprocal metric tensor components (A-matrix: A11, A22, A33, A12, A13, A23) and this function converts those ESDs to direct lattice parameter ESDs (a, b, c, α, β, γ).
- Parameters:
- Returns:
The 7 ESDs, in order
[esd_a, esd_b, esd_c, esd_alpha, esd_beta, esd_gamma, esd_volume].- Return type:
- Raises:
RuntimeError – If covariance data is unavailable or the ESD calculation fails.
Note
The A-matrix parameters (A0-A5) in GSAS-II correspond to: A0=A11, A1=A22, A2=A33, A3=A12, A4=A13, A5=A23 (reciprocal metric tensor) NOT direct cell parameters a, b, c, α, β, γ.
- powderline.kicker.extract_refined_params_from_project(proj, verbose=False)[source]
Extract all refined parameters with their values and ESDs from proj.data.
Uses the covariance data stored in proj.data[‘Covariance’][‘data’] after refinement. This includes both independent and dependent parameters (via ComputeDepESD).
- Parameters:
- Returns:
Mapping of parameter names to
{"value": float, "esd": float}. Returns an empty dict if no covariance data is available.- Return type:
- Raises:
RuntimeError – If ComputeDepESD fails (dependent parameter ESDs cannot be calculated).
Example
>>> params = extract_refined_params_from_project(proj) >>> params[":0:U"] {"value": 47.406, "esd": 8.314}
Note
These helpers document the GSAS-II engine’s extraction path. ESDs (estimated
standard deviations) are read from GSAS-II’s covariance matrix
(proj.data['Covariance']). Unit cell ESDs require conversion from the reciprocal
metric tensor (A-matrix) to direct lattice parameters via calculate_cell_esds_from_A_matrix().
Post-Refinement Extraction Helpers (Private)
The four private _extract_* helpers encapsulate the post-refinement data
extraction and file-writing logic. They are not part of the public API but are
documented here for maintainers.
- powderline.kicker._extract_fit_profile(hist, output_dir)[source]
Extract fit profile arrays from histogram and save fit_profile.txt.
- powderline.kicker._extract_spf_peak_report(proj, hist, recipe, output_dir, verbose)[source]
Extract single peak fitting results and save report files.
Called only for
GSASII_SPFruns whererecipe.payload.single_peaksis set. Returns two column-oriented dicts (JSON-serializable) that are normalised to DataFrames byrun().Also writes: -
single_peaks_report.txt— per-peak widths and convergence status -peak_convergence_diagnostics.txt— only when peaks have issues- Parameters:
proj (Any) – GSAS-II project object after refinement.
hist (Any) – GSAS-II histogram object.
recipe (RecipeModel) – Validated RecipeModel.
output_dir (Path) – Directory to write report files.
verbose (bool) – If True, print convergence warnings to stdout.
- Returns:
(spf_peaks_data, spf_diagnostics_data)where each is a column-oriented dict, or({}, {})when single peaks are not used.- Return type:
- powderline.kicker._extract_phase_reports(proj, hist, recipe, param_dict, output_dir)[source]
Extract unit cell and peak list reports for all phases.
Writes
{phase}_unit_cell_report.csvand{phase}_peak_list_report.csvfor each phase.- Parameters:
proj (Any) – GSAS-II project object after refinement.
hist (Any) – GSAS-II histogram object.
recipe (RecipeModel) – Validated RecipeModel (used to check if phases exist).
param_dict (dict) – Refined parameter dict from
extract_refined_params_from_project()(needed for cell ESDs).output_dir (Path) – Directory to write CSV files.
- Returns:
(unit_cell_data, peak_list_data)— each is a{phase_name: list-of-records}dict (JSON-serializable).- Return type:
- powderline.kicker._extract_refined_parameters(param_dict, output_dir, proj, verbose)[source]
Export refined parameters to CSV and return as list-of-records.
- Parameters:
- Returns:
List of dicts (records) with the 9-column schema. Returns
[]whenparam_dictis empty (simulation mode, SPF, etc.).- Return type:
Background Functions
- powderline.kicker.set_chebyshev_background(proj, hist, chebyshev_dict, print_info=False)[source]
Set the Chebyshev background for a given histogram.
Chebyshev polynomials provide smooth curved backgrounds. Coefficients start at 0th order (constant term) and increase: [c0, c1, c2, …] represents c0 + c1*T1(x) + c2*T2(x) + … where Tn are Chebyshev polynomials.
The function manipulates proj.data[hist.name][‘Background’][0] which has structure: [background_type, refine_flag, num_coefficients, c0, c1, c2, …]
- Parameters:
proj (Any) – GSAS-II project object containing the histogram
hist (Any) – Histogram object to set the background for
chebyshev_dict (dict) – Dictionary containing Chebyshev background parameters: - num_coefficients (int): Number of Chebyshev coefficients - coefficients (list[float]): Coefficient values [c0, c1, c2, …] - refine_flag (bool): Whether to refine background during fitting
print_info (bool) – If True, print background configuration to stdout
- Returns:
None
- Raises:
ValueError – If number of coefficients doesn’t match list length or required background entries are missing
- Return type:
None
Examples
>>> chebyshev_dict = { ... 'num_coefficients': 3, ... 'coefficients': [100.0, -50.0, 10.0], ... 'refine_flag': True ... } >>> set_chebyshev_background(proj, hist, chebyshev_dict)
- powderline.kicker.set_single_peak_background(proj, hist, bkg_single_peaks_dict, print_info=False)[source]
Set single peak background for histogram using pseudo-Voigt profiles.
Single peaks are useful for modeling known impurity peaks or other non-background features that shouldn’t be included in the main phase refinement. Each peak is described by a pseudo-Voigt profile (weighted sum of Gaussian and Lorentzian).
Peak profile: I(2θ) = intensity * [η*L(2θ) + (1-η)*G(2θ)] where: - G(2θ) is Gaussian with width sigma - L(2θ) is Lorentzian with width gamma - η (eta) is mixing parameter (0=pure Gaussian, 1=pure Lorentzian)
- Parameters:
proj (Any) – GSAS-II project object
hist (Any) – Histogram object to set single peaks for
bkg_single_peaks_dict (dict) – Dictionary with keys: - positions: List of [[2θ, refine, min, max], …] for peak positions - intensities: List of [[I, refine, min, max], …] for peak heights - pv_gaussian_sigma: List of [[σ, refine, min, max], …] for Gaussian widths - pv_lorentzian_gamma: List of [[γ, refine, min, max], …] for Lorentzian widths All lists must have same length (number of peaks)
print_info (bool) – If True, print peak configuration to stdout
- Returns:
None
- Raises:
ValueError – If parameter lists have inconsistent lengths
- Return type:
None
Examples
>>> # Two single peaks at 2θ=35.5° and 42.0° >>> single_peaks = { ... 'positions': [[35.5, False, None, None], [42.0, False, None, None]], ... 'intensities': [[50.0, True, None, None], [30.0, True, None, None]], ... 'pv_gaussian_sigma': [[0.1, False, None, None], [0.1, False, None, None]], ... 'pv_lorentzian_gamma': [[0.05, False, None, None], [0.05, False, None, None]] ... } >>> set_single_peak_background(proj, hist, single_peaks)
Fit Range
Types
Refinement Parameter Format
Throughout the API, parameters use the format:
[value, refine_flag, min, max]
Where:
value(float): Current parameter valuerefine_flag(bool): True to refine, False to hold fixedmin(float | None): Minimum bound (placeholder, not enforced yet)max(float | None): Maximum bound (placeholder, not enforced yet)
Example:
"wavelength": [0.45236, false, null, null] # Fixed at 0.45236 Å
"scale": [1.0, true, null, null] # Refined starting from 1.0
Phase vs Histogram Parameters
Phase parameters: Belong to crystal structure (unit cell, atoms)
Histogram parameters: Belong to measurement (scale, broadening, background)
In multi-phase refinements, phase parameters are phase-specific, while histogram parameters are shared across all phases (except scale factors, which are phase-histogram pairs). Multi-phase refinement is fully supported.