IO¶
Input readers and validated records for experiment boundaries.
- class diffBloch.io.AdpRecord(*, kind: tuple[Literal['Uiso', 'Uani', 'missing'], ...], u_iso: FloatArray, u_iso_su: FloatArray, uij_cif: FloatArray, uij_cif_su: FloatArray)[source][source]¶
Bases:
BaseModelAtomic displacement parameters, preserving CIF Uiso/Uani semantics and SUs.
- model_config = {'arbitrary_types_allowed': True, 'frozen': True}¶
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- u_iso: FloatArray¶
- u_iso_su: FloatArray¶
- uij_cif: FloatArray¶
- uij_cif_su: FloatArray¶
- class diffBloch.io.ExperimentalRecord(*, source_path: Path | None = None, unit_cell: FloatArray, cell_parameters: FloatArray, cell_parameters_su: FloatArray, wavelength: float, data_collection_geometry: Literal['continuous_rotation', 'precession'] = 'continuous_rotation', dstar_max: float | None = None, mosaicity_degrees: float | None = None, rotation_axis_position_degrees: float | None = None, ub_matrix: FloatArray, zone_axis_ids: IntArray, zone_axes: FloatArray, precession_angles: FloatArray, alphas: FloatArray, betas: FloatArray, omegas: FloatArray, scales: FloatArray, hkl: IntArray, intensities: FloatArray, sigmas: FloatArray, reflection_zone_axis_ids: IntArray)[source][source]¶
Bases:
BaseModelExperimental PETS reflection data keyed by rotation/zone-axis id.
- model_config = {'arbitrary_types_allowed': True, 'frozen': True}¶
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- unit_cell: FloatArray¶
- cell_parameters: FloatArray¶
- cell_parameters_su: FloatArray¶
- data_collection_geometry: Literal['continuous_rotation', 'precession']¶
- ub_matrix: FloatArray¶
- zone_axis_ids: IntArray¶
- zone_axes: FloatArray¶
- precession_angles: FloatArray¶
- alphas: FloatArray¶
- betas: FloatArray¶
- omegas: FloatArray¶
- scales: FloatArray¶
- hkl: IntArray¶
- intensities: FloatArray¶
- sigmas: FloatArray¶
- reflection_zone_axis_ids: IntArray¶
- class diffBloch.io.ParsedInput(record: T, diagnostics: tuple[ParseDiagnostic, ...] = ())[source][source]¶
Bases:
GenericAn IO record plus non-fatal diagnostics collected while parsing it.
- record: T¶
- diagnostics: tuple[ParseDiagnostic, ...] = ()¶
- class diffBloch.io.ParseDiagnostic(code: ParseDiagnosticCode, input_kind: InputKind, source_path: Path | None, message: str, details: Mapping[str, ~diffBloch.io.diagnostics.ParseDetail]=<factory>)[source][source]¶
Bases:
objectA non-fatal input parse decision worth surfacing at the app boundary.
- code: ParseDiagnosticCode¶
- input_kind: InputKind¶
- class diffBloch.io.StructureRecord(*, source_path: Path | None = None, unit_cell: FloatArray, cell_parameters: FloatArray, cell_parameters_su: FloatArray, spacegroup_hm: str, spacegroup_number: int | None = None, symops_R: FloatArray, symops_t: FloatArray, labels: tuple[str, ...], numbers: IntArray, frac_positions: FloatArray, frac_positions_su: FloatArray, occupancies: FloatArray, occupancies_su: FloatArray, adp: AdpRecord)[source][source]¶
Bases:
BaseModelAsymmetric-unit structure data in CIF convention.
Nominal arrays feed downstream kernels. The corresponding
*_suarrays preserve CIF standard uncertainties as provenance metadata for reporting or later optional penalties.- model_config = {'arbitrary_types_allowed': True, 'frozen': True}¶
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- unit_cell: FloatArray¶
- cell_parameters: FloatArray¶
- cell_parameters_su: FloatArray¶
- symops_R: FloatArray¶
- symops_t: FloatArray¶
- numbers: IntArray¶
- frac_positions: FloatArray¶
- frac_positions_su: FloatArray¶
- occupancies: FloatArray¶
- occupancies_su: FloatArray¶
- property uij_cif: FloatArray¶
Anisotropic ADP matrices; non-Uani rows are NaN.
- diffBloch.io.parse_experimental_block(block: Block, *, source_path: str | Path | None = None) ExperimentalRecord[source][source]¶
Parse a Gemmi PETS CIF-like block into a validated
ExperimentalRecord.
- diffBloch.io.parse_cif_number(value: Any) CifNumber[source][source]¶
Parse a CIF number and optional standard uncertainty.
A parenthesized SU is expressed in units of the final significant digit of the mantissa, so
0.0144(8)has SU0.0008and42(3)has SU3.
- diffBloch.io.parse_structure_block(block: Block, *, source_path: str | Path | None = None, load_hydrogens: bool = False) StructureRecord[source][source]¶
Parse a Gemmi CIF block into a validated
StructureRecord.- Parameters:
block – Parsed Gemmi CIF block.
source_path – Optional source path to retain in the record.
load_hydrogens – Include hydrogen atom sites when present. The default mirrors electron diffraction refinement practice where H sites are usually excluded from this boundary.
- diffBloch.io.read_experimental_data(path: str | Path) ExperimentalRecord[source][source]¶
Read a PETS
.cif_petsfile into a validatedExperimentalRecord.
- diffBloch.io.read_experimental_data_with_diagnostics(path: str | Path) ParsedInput[ExperimentalRecord][source][source]¶
Read a PETS
.cif_petsfile and report non-fatal parser decisions.
- diffBloch.io.read_structure(path: str | Path, *, load_hydrogens: bool = False) StructureRecord[source][source]¶
Read a structure CIF into a validated
StructureRecord.- Parameters:
path – CIF path.
load_hydrogens – Include hydrogen atom sites when present. The default mirrors electron diffraction refinement practice where H sites are usually excluded from this boundary.
- diffBloch.io.read_structure_with_diagnostics(path: str | Path, *, load_hydrogens: bool = False) ParsedInput[StructureRecord][source][source]¶
Read a structure CIF and report non-fatal parser decisions.
- diffBloch.io.symmetry_constraints(record: StructureRecord, *, symprec: float = 1e-3) SymmetryConstraints[source][source]¶
Return special-position constraint data for a validated structure record.
For each asymmetric-unit atom the site stabilizer
S = {(R, t) : R @ x0 + t == x0 (mod 1)}is collected from the record’s symmetry operators, and the projector onto the allowed-displacement subspace is the Reynolds averageP = (1/|S|) * sum_{R in S} Rwith offset(I - P) @ x0.Pis idempotent and its image is exactly the free degrees of freedom, soP @ raw + offsetkeeps the atom on its site for anyraw. The projector is built from the record’s symmetry operators (no diffpy); the ADP (Uij) equalities are extracted from diffpySymmetryConstraints.Ueqnskeyed on the record’s H-M symbol.
Validated IO records.
The core simulation code should receive arrays with stable shapes and units, not parser objects. These records are the trust boundary between file formats and differentiable kernels.
Record classes are pydantic models when they cross an IO/config boundary and need validation. Parser-local helpers can stay as lighter Python value objects, but public records should keep this validated boundary shape.
Standard uncertainties are stored as shape-aligned *_su arrays next to their nominal values,
with NaN meaning absent from the source file. Keep that parallel-array convention until an
uncertainty group needs behavior beyond validation, covariance storage, or multiple competing
representations. ADPs already use a grouped record because CIF Uiso, Uani, and missing ADPs have
different semantics.
uij_cif names the CIF-source ADP convention at the IO boundary. Constrained tensors currently
reuse that field name for ASU ADPs produced from raw parameters; downstream scattering code must
explicitly convert to reciprocal-space U* if that is the representation it consumes.
- class diffBloch.io.record.AdpRecord(*, kind: tuple[Literal['Uiso', 'Uani', 'missing'], ...], u_iso: FloatArray, u_iso_su: FloatArray, uij_cif: FloatArray, uij_cif_su: FloatArray)[source][source]¶
Bases:
BaseModelAtomic displacement parameters, preserving CIF Uiso/Uani semantics and SUs.
- model_config = {'arbitrary_types_allowed': True, 'frozen': True}¶
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- u_iso: FloatArray¶
- u_iso_su: FloatArray¶
- uij_cif: FloatArray¶
- uij_cif_su: FloatArray¶
- class diffBloch.io.record.StructureRecord(*, source_path: Path | None = None, unit_cell: FloatArray, cell_parameters: FloatArray, cell_parameters_su: FloatArray, spacegroup_hm: str, spacegroup_number: int | None = None, symops_R: FloatArray, symops_t: FloatArray, labels: tuple[str, ...], numbers: IntArray, frac_positions: FloatArray, frac_positions_su: FloatArray, occupancies: FloatArray, occupancies_su: FloatArray, adp: AdpRecord)[source][source]¶
Bases:
BaseModelAsymmetric-unit structure data in CIF convention.
Nominal arrays feed downstream kernels. The corresponding
*_suarrays preserve CIF standard uncertainties as provenance metadata for reporting or later optional penalties.- model_config = {'arbitrary_types_allowed': True, 'frozen': True}¶
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- unit_cell: FloatArray¶
- cell_parameters: FloatArray¶
- cell_parameters_su: FloatArray¶
- symops_R: FloatArray¶
- symops_t: FloatArray¶
- numbers: IntArray¶
- frac_positions: FloatArray¶
- frac_positions_su: FloatArray¶
- occupancies: FloatArray¶
- occupancies_su: FloatArray¶
- property uij_cif: FloatArray¶
Anisotropic ADP matrices; non-Uani rows are NaN.
- class diffBloch.io.record.ExperimentalRecord(*, source_path: Path | None = None, unit_cell: FloatArray, cell_parameters: FloatArray, cell_parameters_su: FloatArray, wavelength: float, data_collection_geometry: Literal['continuous_rotation', 'precession'] = 'continuous_rotation', dstar_max: float | None = None, mosaicity_degrees: float | None = None, rotation_axis_position_degrees: float | None = None, ub_matrix: FloatArray, zone_axis_ids: IntArray, zone_axes: FloatArray, precession_angles: FloatArray, alphas: FloatArray, betas: FloatArray, omegas: FloatArray, scales: FloatArray, hkl: IntArray, intensities: FloatArray, sigmas: FloatArray, reflection_zone_axis_ids: IntArray)[source][source]¶
Bases:
BaseModelExperimental PETS reflection data keyed by rotation/zone-axis id.
- model_config = {'arbitrary_types_allowed': True, 'frozen': True}¶
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- unit_cell: FloatArray¶
- cell_parameters: FloatArray¶
- cell_parameters_su: FloatArray¶
- data_collection_geometry: Literal['continuous_rotation', 'precession']¶
- ub_matrix: FloatArray¶
- zone_axis_ids: IntArray¶
- zone_axes: FloatArray¶
- precession_angles: FloatArray¶
- alphas: FloatArray¶
- betas: FloatArray¶
- omegas: FloatArray¶
- scales: FloatArray¶
- hkl: IntArray¶
- intensities: FloatArray¶
- sigmas: FloatArray¶
- reflection_zone_axis_ids: IntArray¶
CIF structure reader backed by gemmi.
- diffBloch.io.cif.read_structure(path: str | Path, *, load_hydrogens: bool = False) StructureRecord[source][source]¶
Read a structure CIF into a validated
StructureRecord.- Parameters:
path – CIF path.
load_hydrogens – Include hydrogen atom sites when present. The default mirrors electron diffraction refinement practice where H sites are usually excluded from this boundary.
- diffBloch.io.cif.read_structure_with_diagnostics(path: str | Path, *, load_hydrogens: bool = False) ParsedInput[StructureRecord][source][source]¶
Read a structure CIF and report non-fatal parser decisions.
- diffBloch.io.cif.parse_structure_block(block: Block, *, source_path: str | Path | None = None, load_hydrogens: bool = False) StructureRecord[source][source]¶
Parse a Gemmi CIF block into a validated
StructureRecord.- Parameters:
block – Parsed Gemmi CIF block.
source_path – Optional source path to retain in the record.
load_hydrogens – Include hydrogen atom sites when present. The default mirrors electron diffraction refinement practice where H sites are usually excluded from this boundary.
PETS CIF-like experimental data reader.
- diffBloch.io.pets.read_experimental_data(path: str | Path) ExperimentalRecord[source][source]¶
Read a PETS
.cif_petsfile into a validatedExperimentalRecord.
- diffBloch.io.pets.read_experimental_data_with_diagnostics(path: str | Path) ParsedInput[ExperimentalRecord][source][source]¶
Read a PETS
.cif_petsfile and report non-fatal parser decisions.