Refinement: the trajectory ends at its best step, steps try the positional weight halved too, the final ladder must win
Three changes to how the trajectory of commit 2bfb84bc4 moves and ends: - A step is taken while its trial lowers R-free or R-work by more than the tie and its R-free stays within the tie of the best so far; the trajectory then ends at its best step. On a deposited model, whose free set it was fitted to, R-work falls while R-free rises, and the trajectory now ends where it began instead of walking on while R-work falls. - Positional steps try the weight halved as well as doubled: at a fixed weight the geometry loosens as the model improves (the X-ray gradient grows with D) until the trials leave the bounds, which stopped 8dqb's trajectories at 2 A (angles > 2.0 deg at w0/128 by step 6). - The final ladder's choice replaces the trajectory's end only where it displaces it (geometry within bounds, R-free lower by more than the tie); before, its first rung was taken by default, two more cycles of movement that on deposited models cost R-free. Deposited models (14 parity sets), R-free after refinement vs refine-combined: mean +0.0058 -> +0.0016 (e.g. 7n2s +0.012 -> +0.003, 9rcs +0.013 -> -0.008, 7d98 +0.015 -> +0.003, 9yl4 +0.010 -> +0.003), the time halved against refine-combined. MD starts, median R-free (REFMAC 0-cycle scorer), previous commit -> this: 5f6m 0.167 -> 0.168, 8dqb 0.294 -> 0.297, 7arr 0.278 -> 0.290 (REFMAC 0.311), 11if 0.244 -> 0.245, 5reo 0.258 -> 0.259, 7d98 0.335 -> 0.335. Determinism: run A == run B == --trials-at-once 1 on 5reo, 9rcs and a 5f6m MD start. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015CeEGgpKdfkCTJb3YNMJcu (cherry picked from commit c2b55aab1aaff637d9484dec0d25003b5c4a3857)
This commit is contained in:
1 parent
bda90dbdd5
commit
3b06bcee78
2 files changed
+37
-17
No files matched your search
@@ -1327,8 +1327,13 @@ RefinementResult RefineModel(const gemmi::Structure &placed, const std::vector<M
|
||||
slot_stage.reset();
|
||||
logger.Debug("Refinement: {} weight trials at a time", trial_slots.size());
|
||||
|
||||
// Of a set of trials, the one kept: they come in order of trust and a later one displaces the best so far
|
||||
// only where its geometry is within bounds and its R-free lower by more than the tie. -1: none ran.
|
||||
// A trial displaces another only where its geometry is within bounds and its R-free lower by more than the
|
||||
// tie.
|
||||
auto displaces = [](const RefinementWeightTrial &t, const RefinementWeightTrial &b) {
|
||||
return t.within_bounds && (!b.within_bounds || t.r_free < b.r_free - R_FREE_TIE);
|
||||
};
|
||||
// Of a set of trials, the one kept: they come in order of trust, the first kept unless a later one displaces
|
||||
// it. -1: none ran.
|
||||
auto choose = [&](std::vector<TrialOutcome> &outcomes, const char *stage) {
|
||||
int best = -1;
|
||||
for (size_t k = 0; k < outcomes.size(); k++) {
|
||||
@@ -1337,8 +1342,7 @@ RefinementResult RefineModel(const gemmi::Structure &placed, const std::vector<M
|
||||
continue;
|
||||
logger.Info("Refinement, {}: {}", stage, o.line);
|
||||
result.trials.push_back(o.trial);
|
||||
const RefinementWeightTrial &t = o.trial, *b = best < 0 ? nullptr : &outcomes[best].trial;
|
||||
if (b == nullptr || (t.within_bounds && (!b->within_bounds || t.r_free < b->r_free - R_FREE_TIE)))
|
||||
if (best < 0 || displaces(o.trial, outcomes[best].trial))
|
||||
best = static_cast<int>(k);
|
||||
}
|
||||
return best;
|
||||
@@ -1359,29 +1363,41 @@ RefinementResult RefineModel(const gemmi::Structure &placed, const std::vector<M
|
||||
state = std::move(outcomes[k]);
|
||||
|
||||
// 2. The trajectory: steps of a few macro-cycles from where the last one ended, each trying the weights as they
|
||||
// are and, in turn, the positions' X-ray weight doubled and the B factors' divided and multiplied by four,
|
||||
// until a step lowers neither R-work nor R-free by more than the tie.
|
||||
// are and, in turn, the positions' X-ray weight halved and doubled (halved: the geometry loosens as the
|
||||
// model improves at one weight, until it leaves the bounds) and the B factors' divided and multiplied by
|
||||
// four.
|
||||
// A step is taken while it lowers R-free or R-work by more than the tie and its R-free stays within the tie
|
||||
// of the best so far; the trajectory ends at its best step (on a deposited model, whose free set it was
|
||||
// fitted to, R-work falls while R-free rises, and it ends where it began).
|
||||
TrialOutcome best = state;
|
||||
for (int step = 0; step < settings.max_steps && state.ran && !ctx.Cancelled(); step++) {
|
||||
const double w = state.trial.weight, adp = state.trial.adp_weight;
|
||||
std::vector<std::pair<double, double>> trials = {{w, adp}};
|
||||
if (step % 2 == 1 && adp > 0) {
|
||||
trials.emplace_back(w, adp / 4);
|
||||
trials.emplace_back(w, 4 * adp);
|
||||
} else if (2 * w <= w_max)
|
||||
trials.emplace_back(2 * w, adp);
|
||||
} else {
|
||||
trials.emplace_back(w / 2, adp);
|
||||
if (2 * w <= w_max)
|
||||
trials.emplace_back(2 * w, adp);
|
||||
}
|
||||
outcomes = RunTrials(trial_slots, trials, refinable, state.pos, state.b, &state.fit, settings.macro_cycles,
|
||||
settings);
|
||||
k = choose(outcomes, fmt::format("step {}", step + 1).c_str());
|
||||
if (k < 0)
|
||||
break;
|
||||
const bool converged = state.trial.r_free - outcomes[k].trial.r_free < R_FREE_TIE &&
|
||||
state.trial.r_work - outcomes[k].trial.r_work < R_FREE_TIE;
|
||||
state = std::move(outcomes[k]);
|
||||
if (converged)
|
||||
const RefinementWeightTrial &t = outcomes[k].trial;
|
||||
const bool gains = displaces(t, state.trial) || (t.within_bounds && t.r_work < state.trial.r_work - R_FREE_TIE);
|
||||
if (!gains || !(t.within_bounds && t.r_free < best.trial.r_free + R_FREE_TIE))
|
||||
break;
|
||||
state = std::move(outcomes[k]);
|
||||
if (displaces(state.trial, best.trial))
|
||||
best = state;
|
||||
}
|
||||
state = std::move(best);
|
||||
|
||||
// 3. The final weights: a short ladder from where the trajectory ended, tighter geometry first.
|
||||
// 3. The final weights: a short ladder from where the trajectory ended, tighter geometry first, its choice
|
||||
// kept where it displaces that.
|
||||
if (state.ran && !ctx.Cancelled()) {
|
||||
const double w = state.trial.weight, adp = state.trial.adp_weight;
|
||||
std::vector<std::pair<double, double>> trials;
|
||||
@@ -1391,7 +1407,7 @@ RefinementResult RefineModel(const gemmi::Structure &placed, const std::vector<M
|
||||
outcomes = RunTrials(trial_slots, trials, refinable, state.pos, state.b, &state.fit, settings.macro_cycles,
|
||||
settings);
|
||||
k = choose(outcomes, "final");
|
||||
if (k >= 0)
|
||||
if (k >= 0 && displaces(outcomes[k].trial, state.trial))
|
||||
state = std::move(outcomes[k]);
|
||||
}
|
||||
for (size_t s = 1; s < trial_slots.size(); s++)
|
||||
|
||||
Reference in new issue
Block a user