Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
876df59
Added the Sba form factors for amino acid and martini3 beads. Changed…
IVinterbladh Apr 23, 2026
446002c
Updated python notebook for plotting results
IVinterbladh Apr 23, 2026
0ee45fd
removed the incorrect form factors from the single_bead.yaml
IVinterbladh Apr 23, 2026
3252edb
updated the default excluded_atomfile to the correct file
IVinterbladh Apr 23, 2026
b4dbb76
Added the sba amino acid form factors to singel_bead.yaml
IVinterbladh May 29, 2026
04deed8
Potential fix for pull request finding
IVinterbladh May 29, 2026
eadde46
Potential fix for pull request finding
IVinterbladh May 29, 2026
6bf10a4
Potential fix for pull request finding
IVinterbladh May 29, 2026
920ace1
Changed names and structure of csv files with coefficients and remove…
IVinterbladh Jun 12, 2026
9eed3a3
Merge branch 'sba_formfactors' of github.com:mlund/pripps into sba_fo…
IVinterbladh Jun 12, 2026
103824f
changed the structure of the polynomail excluded solvent to be part o…
IVinterbladh Jun 15, 2026
c6371ca
added the solvation option to debye and direct models (multipole alre…
IVinterbladh Jun 15, 2026
0b76be9
added some tests and removed unused lyzosyme test files
IVinterbladh Jun 16, 2026
69a0d3d
updated example python notebooks added possibility to print number of…
IVinterbladh Jun 16, 2026
7b0dd98
Merge branch 'master' into sba_formfactors
IVinterbladh Jun 16, 2026
0d59ab6
removed the python API of getting number of hydration shell grid poi…
IVinterbladh Jun 16, 2026
22b3521
Merge branch 'sba_formfactors' of github.com:mlund/pripps into sba_fo…
IVinterbladh Jun 16, 2026
65458c0
fixed open parentheses in cli.rs
IVinterbladh Jun 16, 2026
416329b
fixed error and added log to Cargo.toml so the python extension will …
IVinterbladh Jun 16, 2026
8ef9165
changed name of atomic+excluded to combined for the form factor files
IVinterbladh Jun 16, 2026
8183570
Remove excluded_atomfile parameter; minor cleanups
Jun 16, 2026
10bac8a
Rename ExcludedVolume::Polynomial to PerKind; clarify poly_ asset hea…
Jun 16, 2026
84a1836
Update examples to `excluded="per-kind"`; rename batch SBA script
Jun 16, 2026
aff8d14
Document excluded_solvent field and add !Linear example to README
Jun 16, 2026
0aa1d09
Refresh shipped form-factor files table in README
Jun 16, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
70 changes: 53 additions & 17 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,11 +29,11 @@ model = pr.multipole_model(
qmin=0.0,
qmax=0.5,
nq=500,
excluded="foxs", # FoXS-style excluded volume (16π Fraser)
volume_scale=1.0, # fit knob c₁ (scales excluded volume)
hydration="sasa", # FoXS-style SASA-weighted hydration shell
probe=1.8, # SASA probe radius (Å)
contrast_density=0.03, # fit knob c₂ (scales hydration)
excluded="foxs", # FoXS-style excluded volume (16π Fraser)
volume_scale=1.0, # fit knob c₁ (scales excluded volume)
Comment thread
IVinterbladh marked this conversation as resolved.
hydration="sasa", # FoXS-style SASA-weighted hydration shell
probe=1.8, # SASA probe radius (Å)
contrast_density=0.03, # fit knob c₂ (scales hydration)
bulk_electron_density=0.334, # e/ų, pure water
)

Expand Down Expand Up @@ -61,6 +61,15 @@ the fit knobs to the cached amplitudes — typically under a
millisecond each — so wrapping them in `scipy.minimize` or a grid
search is fluent.

For small structures or exact reference checks, `debye_model` accepts
the same solvent keyword arguments and exposes the same
`model.intensity(volume_scale, contrast_density)` interface. It caches
the exact Debye self and cross terms for atoms, excluded volume, and
hydration before fitting.
`direct_model` does the same for the explicit discrete-q transform,
caching the complex amplitudes before recombining and averaging
duplicate q magnitudes.

A full working example is in `pripps-py/examples/fit_lysozyme.py`,
which fits lysozyme against the shipped `tests/lysozyme/lyzexp.dat`
experimental dataset and reproduces FoXS's χ²/N ≈ 0.20:
Expand Down Expand Up @@ -99,7 +108,7 @@ print(f"c1={result.x[0]:.4f}, c2={result.x[1]:.4f}, χ²/N={result.fun:.4f}")

| Parameter | Values | Description |
|-----------|--------|-------------|
| `excluded` | `"disabled"`, `"fraser"`, `"foxs"`, `"grid"`, `"voronoi"` | Excluded-volume model |
| `excluded` | `"disabled"`, `"fraser"`, `"foxs"`, `"grid"`, `"voronoi"`, `"per-kind"` | Excluded-volume model |
| `hydration` | `"disabled"`, `"sasa"`, `"grid"`, `"voronoi"` | Hydration-shell model |
| `volume_scale` | float (default 1.0) | Scales excluded volume (PepsiSAXS `r₀`) |
| `excluded_spacing` | float (default 1.0) | Grid spacing (Å) for `excluded="grid"` |
Expand All @@ -122,6 +131,7 @@ subtracted from the atomic scattering via
| `foxs` | Same formula as `fraser` but with the FoXS 16π denominator: dummy form factor decays more slowly with q → larger excluded-volume subtraction at high q. Matches FoXS. | `displaced_volume` per atom kind |
| `grid` | Fills the molecular envelope with uniform grid cells, each carrying a Fraser Gaussian sized by cell volume (`spacing³`). Independent of per-atom displaced volumes. | `radius` per atom kind |
| `voronoi` | Per-atom Fraser Gaussians sized by individual Voronoi cell volumes. Derives displaced volumes geometrically — no tabulated volumes needed. Achieves χ²≈0.20 on lysozyme, comparable to `fraser`. | `radius` per atom kind |
| `per-kind` | Uses per-kind excluded-solvent form factors stored as `excluded_solvent` beside each atom/residue `formfactor` in the same YAML file. | `excluded_solvent` for referenced atom kinds |

The `fraser` and `foxs` models use per-atom displaced volumes from
the form-factor YAML (derived from `radius` as `(4/3)πr³` when
Expand Down Expand Up @@ -160,7 +170,10 @@ C: { ff: !Gaussian { qrange: [0.0, 1.0], ab: [[0.1, 2.0]], c: 0.4 },
NH: { radius: 1.009, displaced_volume: 7.606,
ff: !United { center: N, orbit: [[H, 1.009, 1]] } }
CA: { ff: !Alias C }
ALA: { ff: !Polynomial { qrange: [0.0, 0.75], coeff: [8.9, 0.0, 5.8, ...]} }
# Linear combination of other entries (no geometry), F(q) = Σ wᵢ Fᵢ(q):
H2O: { ff: !Linear [[O, 1.0], [H, 2.0]] }
ALA: { ff: !Polynomial { qrange: [0.0, 0.75], coeff: [8.9, 0.0, 5.8, ...]},
excluded_solvent: !Polynomial { qrange: [0.0, 0.75], coeff: [7.1, 0.0, 4.2, ...]} }
```

Supported form factor models:
Expand All @@ -179,29 +192,44 @@ Supported form factor models:
|----------|------|---------|---------------|
| `radius` | Å | SASA hydration, Fraser excluded volume | No — must be specified |
| `displaced_volume` | ų | Fraser excluded volume | Yes — defaults to (4/3)πr³ from `radius` if omitted |
| `excluded_solvent` | form factor | `per-kind` excluded volume | No — optional; required per species when using `--excluded per-kind` |

When `radius` is present but `displaced_volume` is omitted, the
displaced volume is automatically derived as the sphere volume
(4/3)πr³. Specify `displaced_volume` explicitly only for united-atom
groups (e.g. NH, SH) where the displaced volume includes implicit
hydrogens that the effective radius does not account for.

The optional `excluded_solvent` field stores a *second* form factor
(any of the models above) for the bulk solvent each species displaces,
sitting beside its in-vacuo `formfactor` in the same entry. It is read
only by the `per-kind` excluded-volume model (`--excluded per-kind`, or
`excluded="per-kind"` from Python), which subtracts this form factor —
scaled by `volume_scale` — instead of building a Gaussian dummy from
`radius`/`displaced_volume`. Every species present in the structure
must define it when `--excluded per-kind` is selected.

### Shipped form-factor files

| File | Description | Best for |
|------|-------------|----------|
| `assets/single_bead.yaml` | PepsiSAXS coefficients + coarse-grained residues; also covers united-atom kinds (CH/CH₂/NH/…) used by atomic PDBs | Cα / single-bead models; atomic PDBs with `--excluded voronoi` |
| `assets/foxs_formfactors.yaml` | Cromer-Mann (Int. Tables Vol. C), FoXS-compatible volumes and SASA radii | Atomic PDB files with `--excluded foxs` |

Both files use Gaussian b values in the standard s² = (q/4π)²
convention (International Tables / Cromer-Mann). The atomic
coefficients differ (Cromer-Mann vs Stovgaard-2010) and the
volume/radius tables match their respective tools.
| `assets/foxs_formfactors.yaml` | Cromer-Mann (Int. Tables Vol. C) atomic form factors, FoXS-compatible volumes and SASA radii | Atomic PDBs with `--excluded foxs` |
| `assets/gaussian_atoms.yaml` | Mixed table: residue single-bead polynomials plus atomic/united-atom Gaussians (CH/CH₂/NH/…) | Atomic PDBs with PepsiSAXS-style solvent models |
| `assets/stovgaard2010.yaml` | Per-residue form-factor centroids (one-body model, q ∈ [0, 0.75] Å⁻¹) from Stovgaard et al. 2010, <https://doi.org/10.1186/1471-2105-11-429> | Residue / Cα single-bead models |
| `assets/poly_amino_acid.yaml` | Amino-acid bead polynomials with a separate `excluded_solvent` polynomial per bead | Cα / single-bead with `--excluded per-kind` |
| `assets/poly_amino_acid_combined.yaml` | Amino-acid bead polynomials with the excluded solvent already folded into the form factor | Cα / single-bead with `--excluded disabled` |
| `assets/poly_martini.yaml` | Martini-3 bead polynomials with a separate `excluded_solvent` polynomial per bead | Martini-3 CG with `--excluded per-kind` |
| `assets/poly_martini_combined.yaml` | Martini-3 bead polynomials with the excluded solvent already folded into the form factor | Martini-3 CG with `--excluded disabled` |

Gaussian files use b values in the standard s² = (q/4π)² convention
(International Tables / Cromer-Mann). The atomic coefficients differ
(Cromer-Mann vs Stovgaard-2010) and the volume/radius tables match
their respective tools.

**Don't mix files with non-matching `--excluded` flags.** Each
YAML + excluded-volume convention is a self-consistent bundle:
`foxs_formfactors.yaml` was calibrated jointly with FoXS's
`K = 16π` Gaussian, while `single_bead.yaml` was calibrated with
`K = 16π` Gaussian, while `gaussian_atoms.yaml` was calibrated with
PepsiSAXS's `K = 4π`. Swapping the denominator gives atomic and
excluded contributions that were never fit together and yields
subtly biased intensities.
Expand Down Expand Up @@ -286,12 +314,20 @@ pripps -a atoms.yaml -i structure.pdb multipole --lmax 68 # fixed order
# With solvent correction — CSV output with 5 columns
pripps -a atoms.yaml -i structure.pdb -o intensity.csv \
multipole --excluded fraser --hydration sasa
pripps -a atoms.yaml -i structure.pdb -o intensity.csv \
debye --excluded fraser --hydration sasa

# Fit against experimental data (box-constrained Nelder-Mead over
# c₁ ∈ [0.5, 2.0] and c₂ ∈ [0.0, 0.1]; warns if the fit hits a bound)
pripps -a assets/foxs_formfactors.yaml -i structure.pdb \
-f experimental.dat -o fit.csv \
multipole --excluded foxs --hydration sasa
pripps -a assets/foxs_formfactors.yaml -i structure.pdb \
-f experimental.dat -o fit.csv \
debye --excluded foxs --hydration sasa
pripps -a assets/foxs_formfactors.yaml -i structure.pdb \
-f experimental.dat -o fit.csv \
direct --excluded foxs --hydration sasa

# Trajectory averaging — use `direct` so each frame's periodic box
# is honoured (multipole ignores PBC).
Expand All @@ -303,8 +339,8 @@ pripps -a atoms.yaml -i structure.pdb -x trajectory.xtc direct
| Scheme | Best for | Notes |
|---|---|---|
| `multipole` | Single structures, fitting loops | Fastest for large atomic PDBs; no periodic boundaries. |
| `direct` | MD trajectories with periodic box | Evaluates I(q) on discrete Miller-index q-vectors; each frame's box is picked up from the XTC. |
| `debye` | Small clusters, reference checks | Exact pair-distance sum; quadratic in atoms, fine under a few hundred. |
| `direct` | MD trajectories with periodic box | Evaluates I(q) on discrete Miller-index q-vectors; supports the same solvent fit knobs for single-frame fits. |
| `debye` | Small clusters, reference checks | Exact pair-distance sum with the same solvent and fit knobs as multipole; quadratic in atoms, fine under a few hundred. |

Output is CSV: `q,total` for vacuum, or
`q,total,atoms,excluded,hydration` when solvent is active.
Expand Down
Loading
Loading