torchref.refinement.targets.occupancy_floor_diagnostic module
Occupancy Floor Diagnostic for Time-Resolved Crystallography.
This module provides tools to estimate a lower bound on the activation fraction by analyzing electron density. The key insight is that negative electron density is unphysical - you cannot remove more electrons than were present.
For atoms that move in the excited state (e.g., waters, ligands): - The dark state has density ρ_dark at the original position - If the atom completely leaves, the light state has ρ_light ≈ 0 there - The observed difference is: Δρ = α × (ρ_light - ρ_dark) = -α × ρ_dark - The depth of the negative peak gives: α = |Δρ| / ρ_dark
If α is underestimated, the model must predict ρ_light < 0 to fit the data, which is unphysical. This provides a floor on α.
- class torchref.refinement.targets.occupancy_floor_diagnostic.OccupancyFloorDiagnostic(model_dark, model_light, grid_spacing=0.5, negative_threshold=-0.5)[source]
Bases:
objectDiagnostic tool to estimate activation fraction floor from electron density.
Analyzes the electron density of the light/refined model and checks for unphysical negative density, which indicates the activation fraction is too small.
- Parameters:
model_dark (ModelFT) – The dark/ground state model.
model_light (ModelFT) – The light/excited state model (the refined one, not MixedModel).
grid_spacing (float, optional) – Grid spacing in Angstroms for density calculation. Default is 0.5.
negative_threshold (float, optional) – Threshold below which density is considered “significantly negative”. Default is -0.5 (in sigma units after normalization).
Examples
Basic usage:
diagnostic = OccupancyFloorDiagnostic(model_dark, model_light_refine) result = diagnostic.analyze() print(f"Estimated alpha floor: {result['alpha_floor']:.3f}")
- compute_density_at_positions(model, positions, hkl)[source]
Compute electron density at specific positions using Fourier summation.
This is a simplified calculation that sums F_calc * exp(2πi * h·r).
- Parameters:
model (ModelFT) – Model to compute density from.
positions (torch.Tensor) – Positions in fractional coordinates, shape (N, 3).
hkl (torch.Tensor) – Miller indices, shape (M, 3).
- Returns:
Electron density values at each position, shape (N,).
- Return type:
- analyze_at_dark_positions(hkl, atom_mask=None)[source]
Analyze light model density at dark atom positions.
- Parameters:
hkl (torch.Tensor) – Miller indices for Fourier calculation.
atom_mask (torch.Tensor, optional) – Boolean mask selecting which atoms to analyze (e.g., waters only).
- Returns:
Dictionary with analysis results including: - ‘rho_dark’: Dark model density at atom positions - ‘rho_light’: Light model density at atom positions - ‘rho_ratio’: ρ_light / ρ_dark (should be ≥ 0) - ‘negative_mask’: Boolean mask of atoms with negative light density - ‘alpha_floor’: Estimated lower bound on activation fraction - ‘worst_atoms’: Indices of atoms with most negative density
- Return type:
- estimate_alpha_floor_from_difference_map(hkl, delta_F_obs, sigma_diff, n_peaks=10, sigma_cutoff=3.0)[source]
Estimate alpha floor from significant negative peaks in difference map.
For each significant negative peak in the difference map, estimate the minimum α that could produce that peak without requiring negative density in the light state.
- Parameters:
hkl (torch.Tensor) – Miller indices.
delta_F_obs (torch.Tensor) – Observed difference amplitudes (can be negative).
sigma_diff (torch.Tensor) – Uncertainties on difference amplitudes.
n_peaks (int, optional) – Number of peaks to analyze. Default is 10.
sigma_cutoff (float, optional) – Minimum significance (|ΔF|/σ) for peaks. Default is 3.0.
- Returns:
Dictionary with alpha floor estimates.
- Return type:
- class torchref.refinement.targets.occupancy_floor_diagnostic.NegativeDensityPenalty(mixed_model, model_dark, hkl, atom_mask=None, check_grid=False)[source]
Bases:
DeviceMixin,ModuleLoss term that penalizes negative electron density in the MIXED model.
This provides a soft constraint that prevents the activation fraction from being too small (which would require unphysical negative density).
The key insight: the MIXED state (not pure light) should have non-negative density everywhere. If α is too small and atoms have moved, the mixed model might predict negative density at some positions, which is unphysical.
- Parameters:
mixed_model (MixedModel) – The mixed model (combines dark and light states with fractions).
model_dark (ModelFT) – The dark/ground state model (provides reference positions to check).
hkl (torch.Tensor) – Miller indices for density calculation.
atom_mask (torch.Tensor, optional) – Mask selecting which atoms to monitor.
check_grid (bool, optional) – If True, also check density on a grid (more thorough but slower). Default is False.
- class torchref.refinement.targets.occupancy_floor_diagnostic.DisplacementRegularizer(model_light, model_dark, atom_mask=None, max_displacement=2.0)[source]
Bases:
DeviceMixin,ModuleRegularizer that penalizes large atomic displacements from reference structure.
This directly breaks the α-δF degeneracy by favoring solutions where atoms haven’t moved too far from the dark structure, which implies larger α.
The loss is: mean((xyz_light - xyz_dark)²)
- Parameters:
model_light (ModelFT) – The light model being refined.
model_dark (ModelFT) – The dark reference model (frozen).
atom_mask (torch.Tensor, optional) – Boolean mask selecting which atoms to include.
max_displacement (float, optional) – Maximum allowed displacement in Angstroms. Displacements beyond this are penalized quadratically. Default is 2.0 Å.
- class torchref.refinement.targets.occupancy_floor_diagnostic.DifferenceAmplitudeRegularizer(dataset_collection, mixed_model, model_dark)[source]
Bases:
DeviceMixin,ModuleRegularizer that encourages consistency between α and difference amplitudes.
The key insight: the ratio of calculated to observed difference amplitudes should be consistent. If α is too small, the model compensates by making larger structural changes, which changes this ratio in a detectable way.
When α is correct and the structure is correct, these should match. When α is too small and structure has moved too far, the pattern of |ΔF_calc| vs |ΔF_obs| will be distorted.
- Parameters:
dataset_collection (DatasetCollection) – Collection with ‘dark’ and ‘light’ datasets.
mixed_model (MixedModel) – The mixed model being refined.
model_dark (ModelFT) – The dark reference model.
- property hkl