Optimization control options¶
Optimizer parameters are read from an .ini file (e.g. optimize.ini) by
topo.optimize.read_optimize_config(). For why the nscale needs
optimizing at all, see Why stability must be calibrated; for a worked run see the
tutorial Tutorial A.5 — Optimizing the contact nscale (nscale).
The file is a flat list of
key = valuelines.Comments: inline or on their own line, starting with
;or#.Keyword and value are separated by
=or:.Only
pdb_fileanddomain_defare required; everything else has a default.
Important
How this file differs from md.ini. The optimizer is not a simulation
engine — it drives topo.mdrun in a loop. So optimize.ini is one
flat key list that is split two ways when it is read:
the six optimizer controls (
ntraj,q_threshold,frame_fraction,max_rounds,min_contacts,outdir) are consumed by the optimizer and removed — they never reachmd.ini;every other key is treated as a simulation parameter and passed through verbatim into each round’s generated
round_N/md.ini.
There is no list of “allowed” simulation keys: the pass-through is
open-ended, so any option from Simulation control options may appear here and
will reach the MD run. The flip side is that a misspelled control key is
not an error — it is silently forwarded to md.ini as an unknown
simulation parameter, and the control keeps its default. Check the header of
optimization.log, which echoes the controls actually in force.
Two further consequences are covered below: the pass-through defaults are
not the md.ini defaults (Options), and a few keys
are overridden every round (Keys the optimizer overrides every round).
Running the optimizer¶
The optimizer lives in the package as topo.optimize. Once TOPO is
installed (pip install -e . from the repo root) either of these works:
topo-optimize -f optimize.ini # installed console command
python -m topo.optimize -f optimize.ini # module form
-f/--config is the only required argument: it names the optimize.ini
below, and is the one setting that cannot live inside that file. Every other
setting is a key in Options. Three of those keys also have a
command-line flag for overriding the file without editing it — -o/--outdir,
--device and --md-steps — each documented on its own row in that table.
A bare topo-optimize with no arguments prints help and exits.
Example optimize.ini:
; --- inputs (paths are resolved relative to THIS file) ---
pdb_file = P0A6E6.pdb ; all-atom reference (native contacts + geometry)
domain_def = domain.yaml ; initial domains + class; nscales get optimized
; --- per-trajectory production (passed through to each round's md.ini) ---
md_steps = 50_000 ; steps per trajectory — SET THIS (see note below)
nstxout = 100 ; trajectory write frequency (these frames feed Q)
nstlog = 100
ref_t = 300 ; K; stability protocol temperature
; Override an implicit default by adding it here, e.g. to run on CPU:
; device = CPU
; Optional: skip STRIDE entirely by pointing at a precomputed file. If
; omitted, STRIDE runs once up front (written to the optimization root)
; and every round reuses that file.
; stride_output_file = P0A6E6_stride.dat
; --- optimizer controls (consumed here; never reach md.ini) ---
ntraj = 10 ; independent trajectories per round (= n_copies)
q_threshold = 0.6688 ; a frame is "folded" for a unit if Q > this
frame_fraction = 0.98 ; a traj is "stable" if >= this fraction folded
max_rounds = 6 ; 5 ladder levels + median fallback
min_contacts = 0 ; 0 disables the too-few-contacts freeze
; outdir = opt_out ; optimization root; relative to THIS file.
; -o on the command line overrides it.
Note
Set md_steps explicitly. Its implicit default is only 10 000
steps (150 ps at dt = 0.015) — a smoke-test length, far too short to
distinguish a folded domain from an unfolded one, and the optimizer will
happily report “converged” on meaningless trajectories. The published
protocol uses ~1 µs per trajectory (≈ 6.7e7 steps at dt = 0.015).
Lower nstxout alongside it: at its 5000-step default a 10 000-step
round yields two frames per trajectory to compute Q from.
The seed domain_def file¶
domain_def is one of the two required inputs, and it is an ordinary
domain definition YAML — same n_residues and
intra_domains syntax. The optimizer, however, reads it as a seed for the
calibration it is about to run, not as a finished model, so several fields are
treated differently from a plain topo.mdrun:
Field |
Role in the optimizer |
|---|---|
|
Read and kept. The residue ranges define the scoring units: each
named domain is one unit that climbs its own nscale ladder. Assign every
residue you want calibrated — unlike the runner, the optimizer does
not collect leftover residues into an auto- |
|
Required here (the runner ignores it). It selects which nscale
ladder the domain climbs — |
|
Ignored and overwritten every round — this is the quantity being optimized. Any placeholder (or the seed value) is fine; round 1 resets it to ladder level 1. |
|
Not needed and ignored. The optimizer builds an interface unit for
every pair of domains automatically and calibrates each on the shared
|
|
Honored as in the runner: IDR residues are subtracted from every domain and dropped from Q so the stability score measures only the foldable core. See Disordered / IDR regions. |
A three-domain seed then looks like this — every domain carries residues
and class, nscale is a placeholder, there is deliberately no
inter_domains block, and an optional disordered: block marks a
C-terminal tail as intrinsically disordered:
n_residues: 400
intra_domains:
A:
residues: [1-120]
class: alpha # picks the alpha nscale ladder
nscale: 1.0 # placeholder -- reset to ladder level 1 each round
B:
residues: [121-260]
class: beta
nscale: 1.0
C:
residues: [261-400]
class: alpha-beta
nscale: 1.0
# No inter_domains block needed: the optimizer auto-creates and calibrates
# every domain pair (A-B, A-C, B-C) on the shared interface ladder.
disordered:
residues: [385-400] # C-terminal tail: native contacts removed
# eps_gen_kj: 2.25 # OPTIONAL, generic-attraction well (default 2.25)
# idr_scale: 1.0 # OPTIONAL, disorder scale (default 1.0)
The disordered: block is honored exactly as in the runner. Its residues are
subtracted from every domain before scoring — here residues 385–400 leave
domain C, so C is calibrated on residues 261–384 only — and every native
contact touching a disordered residue is dropped from Q, so each unit’s stability
verdict reflects only its foldable core. Disorder wins over domain membership: if
a disordered: range overlaps an intra_domains range, the overlapping
residues are governed by the disorder rules regardless of which domain lists
them. See Disordered / IDR regions for the full treatment and the optional
eps_gen_kj / idr_scale knobs.
Each round the optimizer writes a fresh round_N/domain.yaml with the current
ladder nscales (residues and class carried over from your seed), and the final
calibrated file is domain_optimized.yaml in the optimization root (see
What the optimizer writes below). Your seed file is never modified.
Tip
The minimal seed for the optimizer is therefore n_residues plus an
intra_domains block in which every domain carries residues and
class; nscale may be any placeholder and no inter_domains block is
required. See the Domain definition file (domain.yaml) scenarios for the YAML syntax.
Options¶
The keys fall into four categories:
System input & force field (
pdb_file,domain_def,stride_output_file) — the structure and domains the model is built from. The first two are the only required keys in the file.Per-trajectory production (
md_steps,nstxout) — passed through to each round’smd.ini. These are the two you should set yourself, since their defaults only describe a smoke test.Optimizer controls (
ntraj,q_threshold,frame_fraction,max_rounds,min_contacts,outdir) — consumed by the optimizer itself, and the only keys that do not reach the per-roundmd.ini.Protocol & hardware (
device,ref_t,minimize) — also passed through, but filled in from the optimizer’s own protocol defaults.deviceandminimizedeliberately differ from what the same key would default to in a plain Simulation control options run.
Option |
Type (default) |
Required |
Description |
|---|---|---|---|
System input & force field |
|||
|
str ( |
yes |
All-atom reference structure. Defines both the native contacts used for Q scoring and the geometry the model is built from. Resolved relative to the |
|
str ( |
yes |
Seed domain YAML. Its |
|
str ( |
no |
Precomputed STRIDE output. If omitted, STRIDE runs once up front, is written to the optimization root, and every round reuses that file (STRIDE depends only on the fixed structure, so it never changes). Resolved to an absolute path, since each round’s |
Per-trajectory production — passed through to each round’s |
|||
|
int ( |
no |
Set this explicitly (see the note above). Steps per trajectory, passed through to |
|
int ( |
no |
Steps between trajectory (DCD) writes, passed through to |
Optimizer controls — consumed here; never reach |
|||
|
int ( |
no |
Independent trajectories per round. Recommended: 10 trajectories, which is the default. Produced as a single multi-copy MD run ( |
|
float ( |
no |
A frame counts as folded for a unit if its fraction of native contacts Q > this value. See Native-contact analysis (the Q score). |
|
float ( |
no |
A trajectory is stable for a unit if at least this fraction of its frames are folded. A unit is stable only when all |
|
int ( |
no |
Hard cap on rounds. The default covers the normal case exactly: 5 ladder levels + the median fallback, climbing one level per round. More rounds are needed only if raising one unit’s nscale destabilizes an already-stable unit (rare). |
|
int ( |
no |
A domain or interface with fewer than this many native contacts is considered too weakly structured to fold: it is pinned at the first ladder level, frozen, and never optimized (it cannot otherwise stabilize, so it would drag every round to the fallback). |
|
str ( |
no |
Optimization root directory — the |
Protocol & hardware |
|||
|
str ( |
no |
Passed through to |
|
float ( |
no |
Passed through to |
|
bool ( |
no |
Passed through to |
The table covers the keys you are likely to set. The remaining implicit defaults fix the stability protocol’s ensemble and the model’s standard parameterization, and are rarely touched.
The ensemble. Every round samples constant-temperature dynamics: a Langevin
integrator at ref_t = 300 K with friction tau_t = 0.05 ps⁻¹
(tcoupl = yes), no pressure coupling (pcoupl = no), and no periodic box
(pbc = no). Nscale is therefore calibrated at fixed particle number and
temperature — this is canonical, constant-T sampling rather than a strict NVT
box run, since with pbc = no the chain is unbounded and there is no
simulation volume being held fixed. The thermostat is what makes the stability
verdict meaningful: Q is scored on thermal fluctuations at 300 K, so a unit
counts as stable only if it resists unfolding at the protocol temperature.
Parameterization and bookkeeping. dt = 0.015 (ps), model = topo,
restart = no (every round starts fresh), ppn = 4, nstlog = 5000,
nstchk = 5000. Setting any of these — or any ensemble key above — in
optimize.ini overrides the implicit value. The full set is
topo.optimize.IMPLICIT_DEFAULTS. Beyond these, any other key from
Simulation control options may appear and is passed through verbatim.
Keys the optimizer overrides every round¶
The optimizer owns the round layout and the multi-copy fan-out, so it rewrites
these keys when it expands optimize.ini into round_N/md.ini. Setting
them in optimize.ini has no effect — your value is silently replaced:
Key |
Value forced by the optimizer |
|---|---|
|
|
|
|
|
|
|
Rewritten to absolute paths; |
device and md_steps are also overridden, but only when you pass the
corresponding command-line flag; otherwise your .ini value stands.
What the optimizer writes¶
Everything lands under the optimization root — --outdir, else outdir in
the .ini, else opt_out/:
opt_out/
optimization.log # full report: per-round nscales, Q verdicts, convergence
domain_optimized.yaml # <- the calibrated model; this is the deliverable
round_1/
md.ini # generated: optimize.ini + implicit defaults + overrides
domain.yaml # this round's nscales
traj/
traj.dcd, traj.psf # the multi-copy run
traj_0.dcd ... # split per-copy trajectories
Q_0.csv ... # per-frame Q per unit, paired with traj_<k>.dcd
round_2/ ...
optimization.log is line-buffered and flushed per line, so tail -f works
during a long run. The per-round Q_<k>.csv files hold the Q time series
behind every stability decision — read them when a unit refuses to stabilize.
Warning
A non-converged run still writes domain_optimized.yaml. If a protein
does not stabilize within max_rounds, the optimizer leaves the unstable
units at their highest level (or the median fallback), writes the file
anyway, and flags the run with a boxed WARNING naming the unstable units.
The file’s presence is therefore not evidence of a calibrated model —
check the log for CONVERGED before using it.
Limitations¶
The optimization is not resumable: each invocation starts from ladder level 1 and re-runs every round. A long run that is interrupted must start over.