Skip to content

(FOR REFACTOR) cisTEM Refinement Strategy Analysis and Bug Documentation #556

Description

@bHimes

cisTEM Refinement Strategy Analysis and Bug Documentation

Executive Summary

This document summarizes the investigation into cisTEM's adaptive refinement strategies across three GUI panels (Manual, Auto, Ab Initio), documents critical bugs discovered in score calculation, and proposes fixes for variable naming confusion and logic errors.

Program Hierarchy

Manual Refinement Panel
    ├── User-controlled parameters
    ├── local_global_refine = user_choice (default: false)
    └── percent_used = 100%

Auto Refinement Panel
    ├── Adaptive strategy
    ├── local_global_refine = true (always)
    └── percent_used = 100%

Ab Initio 3D Panel
    ├── Initial model generation
    ├── local_global_refine = false (always)
    └── percent_used = ramped (20% → 100%)

Key Variables and Their Meanings

Control Variables (GUI → refine3d)

  • local_global_refine: Panel-level strategy flag

    • true = Auto panel (adaptive refinement)
    • false = Ab Initio (global search only) or Manual (user choice)
    • Passed via command line to refine3d
  • percent_used: Fraction of particles to refine

    • 100% for Manual and Auto panels
    • Ramped from 20% to 100% for Ab Initio

Particle State Variable

  • image_is_active: Per-particle alignment state
    • 1 = Aligned/active particle
    • 0 = Unaligned/needs global search
    • -1 = Excluded from refinement

Thread-Local Action Flags (in refine3d)

  • do_global_search_tl_: Perform global parameter search
  • do_local_refinement_tl_: Perform local refinement only

Logic Flow Trees

Manual Refinement Panel Logic

if (local_global_refine == false):
    ├── All particles: do_global_search_tl_ = true
    └── All particles: do_local_refinement_tl_ = false

Auto Refinement Panel Logic

if (local_global_refine == true):
    └── For each particle:
        ├── if (image_is_active == 1):
        │   ├── do_global_search_tl_ = false
        │   └── do_local_refinement_tl_ = true
        ├── if (image_is_active == 0):
        │   ├── do_global_search_tl_ = true
        │   └── do_local_refinement_tl_ = false
        └── if (image_is_active == -1):  [BUG]
            ├── do_global_search_tl_ = false
            └── do_local_refinement_tl_ = true  [Should skip!]

Ab Initio 3D Panel Logic

if (local_global_refine == false):
    └── For subset (percent_used):
        ├── Selected particles: do_global_search_tl_ = true
        └── Non-selected: Skip refinement

Particle State Transitions

Import → image_is_active = 0 (unaligned)
    ├── Global search succeeds → image_is_active = 1
    ├── Global search fails → image_is_active = 0
    └── User excludes → image_is_active = -1

image_is_active = 1 (aligned)
    ├── Local refinement → stays 1
    ├── Fails threshold → image_is_active = 0
    └── User excludes → image_is_active = -1

image_is_active = -1 (excluded)
    └── Should never be refined [BUG: currently treated as aligned]

Critical Bugs Discovered

Bug 1: Score Always Zero

Location: refine3d.cpp lines 1548-1602

Problem: Scores are only calculated when NOT doing parameter searches, but parameter searches are always done.

// Simplified logic showing the bug
if (number_of_search_dimensions > 0 && (do_global_search || do_local_refinement)) {
    // Calculate logP but NOT score
    output_parameters.logp = ReturnLogLikelihood(...);
    // score remains 0.0
} else {
    // This branch never executes in practice
    output_parameters.score = ReturnLogLikelihoodWithoutSearch(...);
}

// Later, negative scores are clamped to 0
if (output_parameters.score < 0.0)
    output_parameters.score = 0.0;  // Prevents recovery

Impact: Reconstruction weighting uses score=0 for all particles, losing frequency-dependent weighting benefits.

Fix: Calculate score during parameter searches or use logP for weighting.

Bug 2: Excluded Particles Refined

Location: refine3d.cpp lines 886-902

Problem: Particles with image_is_active == -1 (excluded) are incorrectly processed as aligned particles.

// Current buggy logic
if (local_global_refine) {
    if (input_parameters.image_is_active > 0.5f) {
        // Aligned particle - local refinement
        do_local_refinement_tl_ = true;
    } else {
        // This catches BOTH unaligned (0) AND excluded (-1)!
        do_global_search_tl_ = true;
    }
}

Fix: Explicitly check for -1 and skip refinement.

Proposed Variable Renaming

Current Confusing Names → Clear Names

  1. local_global_refineselect_adaptive_refinement

    • Better describes Auto panel's adaptive strategy
  2. global_search_localdo_global_search_tl_

    • Adds do_ prefix for action flag
    • Adds _tl_ suffix for thread-local
  3. global_local_refinementdo_local_refinement_tl_

    • Consistent naming pattern

Implementation Plan

Phase 1: Critical Bug Fixes

  1. Fix score calculation

    • Option A: Calculate score during parameter searches
    • Option B: Use logP instead of score for weighting
    • Option C: Implement proper Frealign score calculation
  2. Fix excluded particle handling

    if (input_parameters.image_is_active < -0.5f) {
        // Skip excluded particles entirely
        continue;
    }

Phase 2: Code Clarity

  1. Rename confusing variables

    • Update all references in refine3d.cpp
    • Update GUI panels that set these flags
    • Add clear comments explaining each variable's purpose
  2. Add comprehensive documentation

    • Doxygen comments for adaptive refinement logic
    • Document particle state transitions
    • Explain thread-local variable usage

Phase 3: Testing

  1. Verify score calculation

    • Add unit test for score calculation
    • Verify scores are non-zero in output star files
    • Test reconstruction weighting with real scores
  2. Test adaptive refinement

    • Verify excluded particles are skipped
    • Test state transitions during refinement
    • Validate Auto panel's adaptive behavior

Exposure Filtering Investigation

Original Concern

How does exposure filtering (dose weighting) affect reconstruction weighting?

Findings

  • Exposure filter is applied to CTF, not particle directly
  • CTF multiplies particle during insertion, effectively filtering it
  • Current bug (score=0) means exposure has NO effect on weighting
  • Once fixed, concern is potential over-weighting of damaged particles

Recommendation

After fixing score bug, investigate whether exposure-damaged particles need reduced weight in reconstruction to prevent over-weighting of noise.

Next Steps

  1. Immediate: Fix critical bugs (score calculation, excluded particles)
  2. Short-term: Implement variable renaming for clarity
  3. Medium-term: Add comprehensive documentation and tests
  4. Long-term: Optimize adaptive refinement strategies based on empirical results

Metadata

Metadata

Assignees

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions