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: BaseModel

Model 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].

value: float | None
refine_flag: bool | None
min_val: float | None
max_val: float | None
classmethod from_list(param_list)[source]

Create from [value, refine_flag, min, max] list format.

Parameters:

param_list (list)

Return type:

RefinementParameterModel

class powderline.schema.InstrumentBroadening(*, U=None, V=None, W=None, X=None, Y=None, Z=None, **extra_data)[source]

Bases: BaseModel

Instrument broadening parameters (Thompson-Cox-Hastings pseudo-Voigt).

Parameters:
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: BaseModel

Instrument correction parameters.

Parameters:
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: BaseModel

Instrument parameter settings for refinement.

Parameters:
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: BaseModel

Instrument configuration.

Parameters:
model_config: ClassVar[ConfigDict] = {'extra': 'allow'}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

description: str
initialization: list[dict[str, Any]]
parameterization: InstrumentParameterization | None
classmethod validate_initialization_structure(v)[source]

Ensure initialization is a list of two dicts.

class powderline.schema.ChebyshevBackground(*, num_coefficients, coefficients, refine_flag, **extra_data)[source]

Bases: BaseModel

Chebyshev polynomial background.

Parameters:
model_config: ClassVar[ConfigDict] = {'extra': 'allow'}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

num_coefficients: int
coefficients: list[float]
refine_flag: bool
classmethod validate_coefficients_length(v, info)[source]

Ensure number of coefficients matches num_coefficients.

class powderline.schema.SinglePeaksBackground(*, positions=None, intensities=None, pv_gaussian_sigma=None, pv_lorentzian_gamma=None, **extra_data)[source]

Bases: BaseModel

Single 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:
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
validate_peak_lists_same_length()[source]

Ensure all peak parameter lists have the same length.

class powderline.schema.SinglePeaks(*, positions=None, intensities=None, pv_gaussian_sigma_sq=None, pv_lorentzian_gamma=None, **extra_data)[source]

Bases: BaseModel

Single 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:
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
validate_peak_lists_same_length()[source]

Ensure all peak parameter lists have the same length.

class powderline.schema.BackgroundModel(*, chebyshev=None, single_peaks=None, **extra_data)[source]

Bases: BaseModel

Background model configuration.

Parameters:
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: BaseModel

Single peak fitting mode configuration.

Schema 0.25 Addition: Required for GSASII_SPF schema.

Parameters:
  • use_instrument_profile (bool)

  • extra_data (Any)

model_config: ClassVar[ConfigDict] = {'extra': 'allow'}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

use_instrument_profile: bool
class powderline.schema.RefinementControls(*, refinement_cycles=5, refinement_algorithm=None, single_peak_fitting_mode=None, **extra_data)[source]

Bases: BaseModel

Controls 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:
model_config: ClassVar[ConfigDict] = {'extra': 'allow'}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

refinement_cycles: int
refinement_algorithm: str | None
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: BaseModel

Unit 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:
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
classmethod validate_cell_lengths(v)[source]

Ensure unit cell lengths are positive.

classmethod validate_cell_angles(v)[source]

Ensure unit cell angles are between 0 and 180 degrees.

class powderline.schema.AtomParameters(*, x=None, y=None, z=None, occupancy=None, ADP, Uiso=None, Uaniso=None, **extra_data)[source]

Bases: BaseModel

Atomic 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:
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
ADP: str
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: BaseModel

Crystallite 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_config: ClassVar[ConfigDict] = {'extra': 'allow'}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

model: Literal['isotropic', 'uniaxial', 'ellipsoidal']
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
hkl_direction: list[int] | 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
validate_model_implementation()[source]

Validate that only implemented models are used.

Return type:

Self

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: BaseModel

Microstrain 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_config: ClassVar[ConfigDict] = {'extra': 'allow'}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

model: Literal['isotropic', 'uniaxial', 'generalized']
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
hkl_direction: list[int] | 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
validate_model_implementation()[source]

Validate that only implemented models are used.

Return type:

Self

class powderline.schema.PeakBroadening(*, size_broadening=None, strain_broadening=None, **extra_data)[source]

Bases: BaseModel

Phase-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:
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: BaseModel

Phase-specific refinement parameters.

Parameters:
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: BaseModel

Atomic structure definition.

Parameters:
model_config: ClassVar[ConfigDict] = {'extra': 'allow'}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

element: str
x: float
y: float
z: float
occupancy: float
Multiplicity: int | None
ADP: str
Uiso: float | None
Uaniso: dict[str, float | None] | None
class powderline.schema.UnitCellStructure(*, a, b, c, alpha, beta, gamma, volume=None, **extra_data)[source]

Bases: BaseModel

Unit 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].

a: float
b: float
c: float
alpha: float
beta: float
gamma: float
volume: float | None
class powderline.schema.PhaseStructure(*, phase_name, space_group, unit_cell, atoms, **extra_data)[source]

Bases: BaseModel

Phase structure definition.

Parameters:
model_config: ClassVar[ConfigDict] = {'extra': 'allow'}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

phase_name: str
space_group: str
unit_cell: UnitCellStructure
atoms: dict[str, AtomStructure]
class powderline.schema.PhaseModel(*, structure, parameterization=None, **extra_data)[source]

Bases: BaseModel

Complete phase definition.

Parameters:
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: BaseModel

XRD data arrays.

Parameters:
model_config: ClassVar[ConfigDict] = {'extra': 'allow'}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

tth: list[float]
Itth: list[float]
Itth_weights: list[float]
filename: str | None
validate_all_arrays_same_length()[source]

Ensure tth, Itth, and Itth_weights have the same length.

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: BaseModel

Refinement 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:
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
asset_path: str | None
fit_range: list[float | None] | None
background: BackgroundModel | None
single_peaks: SinglePeaks | None
refinement_controls: RefinementControls
classmethod validate_fit_range(v)[source]

Ensure fit_range is a list of length 2 if provided.

class powderline.schema.RecipeModel(*, schema_name, schema_version, payload, **extra_data)[source]

Bases: BaseModel

Top-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.phases must be present, payload.instrument required

  • GSASII_SPF: payload.single_peaks must be present, payload.phases must 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:
model_config: ClassVar[ConfigDict] = {'extra': 'allow'}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

schema_name: Literal['GSASII_Rietveld', 'GSASII_SPF']
schema_version: str
payload: PayloadModel
classmethod validate_schema_name(v)[source]

Validate that schema_name is in the accepted list.

classmethod validate_schema_version(v)[source]

Validate that the schema version is currently supported.

validate_payload_by_schema_name()[source]

Validate payload contents match schema_name requirements.

  • GSASII_Rietveld: Requires phases, instrument, instrument.initialization, refinement_controls

  • GSASII_SPF: Requires single_peaks, instrument.initialization, refinement_controls; forbids phases

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:
  • recipe_dict (dict) – Recipe dictionary loaded from JSON

  • input_path (Path) – Path to the JSON file

Returns:

A 2-tuple (is_template, reason). is_template is True if this appears to be a template, and reason explains why it was detected as a template. If not a template, returns (False, None).

Return type:

tuple[bool, str | None]

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:
  • phase_idx (int) – Phase index (0-based) for parameter naming (e.g., “0::A0”)

  • proj (Any) – GSAS-II project object after refinement

  • phase_name (str) – Name of the phase

Returns:

The 7 ESDs, in order [esd_a, esd_b, esd_c, esd_alpha, esd_beta, esd_gamma, esd_volume].

Return type:

list[float | None]

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:
  • proj (Any) – GSAS-II project object after refinement

  • verbose (bool) – If True, print progress messages.

Returns:

Mapping of parameter names to {"value": float, "esd": float}. Returns an empty dict if no covariance data is available.

Return type:

dict

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.

Parameters:
  • hist (Any) – GSAS-II histogram object after refinement.

  • output_dir (Path) – Directory to write fit_profile.txt.

Returns:

Column-oriented data (JSON-serializable) with keys two_theta, y_obs, y_weights, y_calc, y_diff, y_bkg, q_values, d_spacings.

Return type:

dict

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_SPF runs where recipe.payload.single_peaks is set. Returns two column-oriented dicts (JSON-serializable) that are normalised to DataFrames by run().

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:

tuple[dict, dict]

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.csv and {phase}_peak_list_report.csv for 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:

tuple[dict, dict]

powderline.kicker._extract_refined_parameters(param_dict, output_dir, proj, verbose)[source]

Export refined parameters to CSV and return as list-of-records.

Parameters:
  • param_dict (dict) – From extract_refined_params_from_project().

  • output_dir (Path) – Directory to write refined_parameters.csv.

  • proj (Any) – GSAS-II project object (for phase/atom name mappings).

  • verbose (bool) – If True, print export status to stdout.

Returns:

List of dicts (records) with the 9-column schema. Returns [] when param_dict is empty (simulation mode, SPF, etc.).

Return type:

list

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

powderline.kicker.set_fit_range_hist(hist, fit_range, print_info=False)[source]

Set fit range for histogram in GSAS-II project.

Parameters:
Return type:

None

Types

Refinement Parameter Format

Throughout the API, parameters use the format:

[value, refine_flag, min, max]

Where:

  • value (float): Current parameter value

  • refine_flag (bool): True to refine, False to hold fixed

  • min (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.