We read every piece of feedback, and take your input very seriously.
To see all available qualifiers, see our documentation.
Length-weight CGR features by contig size Sigmoid reliability weight w = sigmoid(4 * (log10(len) - log10(4000))) attenuates 9 CGR dims for short contigs, falling back to encoder+aDNA. Grounded in Bog-38 analysis: contaminating contigs avg 2.2kb (w≈0.22) vs core archaeal contigs avg 4.8kb (w≈0.58). Applied at both CGR concatenation sites (initial embeddings and consensus kNN loop).
Fix run_winning.sh: use bin instead of bin2
Cleanup: rename bin2->bin, remove legacy bin and polish commands
Make winning config the default (damage-infonce, scg-infonce, restarts=3/25)
Restore bin2_config.h needed by 06edbac bin2.cpp/cmd_bin2.cpp
Restore bin2.cpp and cmd_bin2.cpp to 06edbac (confirmed 11/11/11)
Restore bin2.cpp and cmd_bin2.cpp from pre-cleanup state (47e3f69)
Revert to inline Bin2Config in each file; remove shared header
Add --scg-infonce to winning config (was silently active, now explicit)
Fix: SCG hard negatives require use_scg_infonce flag has_scg was checking !scg_lookup.empty() only, but the lookup is built whenever n_encoder_restarts>1 (for kNN merging). Without this fix, SCG weights were silently applied in all --encoder-restarts 3 runs even without --scg-infonce.
Decouple n_lik (likelihood) from n_smiley (plot) to restore baseline p_anc n_lik=min(5, read_len/2) keeps InfoNCE weights identical to validated baseline. n_smiley=min(n_terminal, read_len/2) tracks up to 15 positions for smiley plot. Extending to 15 positions for likelihood caused 11→10 HQ regression.
Fix 7 bugs found in code review - Issue 1: delete only bin_*.fa files, not all .fa in output dir - Issue 2: remove stale [DEBUG] cerr statements - Issue 3: honour --temperature in training (was hardcoded 0.1f in 2 places) - Issue 4: honour --partgraph-ratio on non-consensus path (was hardcoded 50) - Issue 5: unknown --flag now errors; stoi/stof wrapped in try-catch - Issue 6: --contigs always required; --bam only required without --embeddings - Issue 7: embeddings.tsv writes all dims (encoder+aDNA+CGR), not just embedding_dim - Issue 8: fix --encoder-seed help string (1 → 42)
Extract Bin2Config to shared header; extend damage positions to 15 (configurable) - Move Bin2Config from duplicated struct in bin2.cpp + cmd_bin2.cpp into src/bin2_config.h (eliminates layout mismatch UB and sync burden) - Add --damage-positions N (default 15, max 25) controlling terminal positions used for both likelihood computation and smiley plot output - Extend DamageProfile arrays from [10] to MAX_SMILEY_POS=25 - Fix read loop: use read_len/2 as eff_n to avoid 5'/3' overlap - aggregate_smiley.py: auto-detect all position columns, compute model curves, load CheckM2 quality, sort bins HQ>MQ>LQ then by amplitude - plot_smiley.py: annotate subplot titles with completeness/contamination
Add plot_smiley.py from backup; align damage_per_bin.tsv column names
Clean binner: remove dead code paths, add per-bin damage output Remove all experimental branches that are not in the winning config: - run_python_leiden(), cluster_hdbscan() (dead functions) - COMEBin parameter sweep block (120-config grid) - ensemble Leiden backend and all its config/CLI flags - quality_leiden/map_equation/bandit flags and config fields - run_adaptive_restarts() bandit search (QualityLeidenBackend) - map equation Phase 1b block Add per-bin damage summary (damage_per_bin.tsv): - Pool raw C-opp/CT-mismatch/G-opp/GA-mismatch counts per bin - Re-fit exponential damage model per bin via fit_damage_model() - Classify bins as ancient/modern/mixed - Requires new n_opp_5p/n_ct_5p/n_opp_3p/n_ga_3p fields in DamageProfile Result: bin2.cpp is now the clean winning binner only
Phase 4E: replace sub-Leiden voting with embedding-outlier eviction Contaminating contigs have most kNN edge weight pointing to their true genome's cluster outside this bin, giving them low 'belonging score' (intra-cluster weight / total weight). The new approach: 1. Compute belonging_score per contig in contaminated bins 2. Candidates: belonging < mean - sigma*std AND has duplicate marker 3. Try evicting 100%/75%/50%/25% of candidates (by contamination signal score = (1-belonging) * n_dup_markers), validate with CheckM each time 4. Accept first subset that brings contamination < 5% without losing >5% completeness Replaces 75 Leiden sub-clusterings (5 resolutions * 15 seeds) with O(n) edge-weight scan. Directly uses encoder embedding structure via kNN weights. Configurable via --phase4e-sigma (default 1.0) and --phase4e-entry-cont (default 3.0).
Phase 4E: lower entry threshold to 3% internal contamination (was 5%) Internal CheckM estimator underestimates contamination vs CheckM2's neural network (~3% internal ≈ ~6% CheckM2). bin_10 was being skipped despite 7.5% CheckM2 contamination because internal estimate was just below 5%. New default: phase4e_entry_contamination=3.0f, configurable via --phase4e-entry-cont.
Phase 3 rescue: accept net-positive mixed-marker contigs, lower donor threshold to 2x - Previously rejected any contig that would duplicate an existing marker, even if it also added multiple new markers (net positive for completeness). Now: tier 0 = pure-missing (preferred), tier 1 = net-positive mixed (accepted after full hypothetical quality check confirming contamination < 5%). - Donor protection threshold lowered from 3x to 2x affinity ratio for near-HQ rescue targets, allowing slightly weaker steals when the target bin needs them. - Targets bin_18 (~86% comp) and bin_20 (~83% comp) which stall below HQ despite Phase 3 already running on them.
Add 4 encoder/clustering improvements (EMA, quality-weight, adaptive Phase 4E, QC gate) - Grad clip (default 1.0) + EMA (--encoder-ema) in all train_multiview overloads - Quality-weighted consensus kNN: SCG separation score selects best encoder runs - Adaptive Phase 4E: 2-hop neighbor expansion + vote-based eviction across all cuts - QC gate: retrain encoder if separation score < 0.8 * best (--encoder-qc-threshold)
Add resolution sweep to plain seed sweep path Stage 1: probe N_RES resolutions (log-uniform, 1 seed each) → pick best. Stage 2: sweep remaining (N - N_RES) seeds at best resolution + consensus. Triggered by --stage1-res N (default 1 = fixed resolution, no change). Applies to --leiden-restarts N without --quality-leiden (winning config path).
Lower res_search_min default to 0.5 (log-uniform from 0.5 to 12)
Expose --stage1-bw N CLI flag for 2D grid budget control Lets user pair --stage1-bw 3 --stage1-res 3 for a 9-arm grid (27 total evals) vs default 7×1=7 (25 total evals).
Add resolution as swept dimension in leiden restart bandit Stage 1 now builds a N_BW × N_RES arm grid instead of bandwidth-only. ResolutionArm gets a resolution field; evaluate_candidate takes explicit resolution and sets trial.resolution accordingly. CLI: --stage1-res N, --res-search-min F, --res-search-max F (default: 1 = pinned to --resolution). With --stage1-res 3 and [2, 12]: 7×3=21 Stage1 arms → 21+12+6=39 total, or reduce stage1_bw to 3 for 3×3=9 → 27 total.
Remove Phase 4P — second Phase 3 pass hurts (10 vs 11 HQ baseline)
Revert Phase 3 forward simulation — proxy inaccuracy caused contamination Forward simulation (proxy_cont < 4.5%) was insufficiently accurate: CheckM's colocation formula diverges from the simple dup_excess/n_markers proxy, causing bin_15 to reach 5.23% actual contamination despite proxy saying <4.5%. Relaxed 2x donor protection allowed Phase 3 to steal from near-HQ bins, dropping bin_9 and bin_20 completeness. Revert to original !adds_dup binary check + 3x donor protection. Keep Phase 4P (second Phase 3 pass after Phase 4) which is net-additive.
Phase 3 rescue: forward simulation + second pass after Phase 4 - Replace binary !adds_dup with proxy contamination forward-simulation. Candidates adding dup markers are now accepted if proxy_cont < 4.5% (estimated via comm_q arithmetic, O(markers) per candidate, no CheckM call). Unlocks near-HQ bins stuck at 88-89% whose missing marker contigs also happen to carry one already-present marker. - Relax donor protection threshold from 3x to 2x affinity ratio (safe since contamination budget is now enforced by forward simulation). - Second Phase 3 rescue pass (Phase 4P) after all Phase 4 decontamination. Phase 4 evictions move contigs out of contaminated bins, making them available as recruits for near-HQ bins that the first Phase 3 pass missed.
Fix SCG+damage weight: max() instead of mul() mul() cancels both signals for same-ancient SCG pairs: 0.5 × 2.0 = 1.0 (neutral). max() lets SCG take priority — confirmed cross-genome pairs get the boost regardless of damage similarity. Semantically correct: SCG is a hard constraint.
Add SCG hard negative mining for InfoNCE encoder Two contigs sharing a single-copy marker must come from different genomes. We exploit this during training to push cross-genome pairs apart in embedding space, reducing contamination load on downstream Phase 4E cleanup. New flag: --scg-infonce [--scg-boost FLOAT (default 2.0)] Implementation: - scg_hard_negatives.h: ContigMarkerLookup struct + build_contig_marker_lookup() - amber_encoder.h: compute_scg_weights() private method (sorted-vec intersection); new train_multiview(encoder, views, scg_lookup) and train_multiview(encoder, views, damage_profiles, scg_lookup) overloads - bin2.cpp: SeedGenerator moved before training block (pure ordering change, same HMM scan runs once); scg_lookup built from marker hits; dispatch updated for all overload combinations; encoder restarts path propagated - cmd_bin2.cpp: --scg-infonce / --scg-boost CLI flags
Fix compile error: rename w -> w_to_target in Phase 3 cerr line
Improve Phase 3 completeness rescue and Phase 4E contamination removal Phase 3: allow stealing from large viable bins when kNN affinity to the target bin strongly exceeds affinity to the current bin (w_to_target > 3*w_to_current). Fixes rep 2 failure where missing genome contigs are blocked by donor protection. Phase 4E: lower trigger threshold 5.5% -> 5.0% (catches bins the internal estimator slightly underestimates) and increase seeds 5 -> 15 (more attempts to find the correct graph cut for stubborn contaminated bins).