Actions System Quick Reference¶
Quick access guide for developers working with the Actions System
Quick Start¶
Basic Usage¶
// Initialize (already done in renderer-modular.js)
const actionManager = new ActionManager(genomeBrowser);
// Add a copy action
actionManager.addAction(actionManager.ACTION_TYPES.COPY_SEQUENCE, 'chr1:1000-2000(+)', 'Copy promoter region', {
chromosome: 'chr1',
start: 1000,
end: 2000,
strand: '+',
});
// Execute all pending actions
await actionManager.executeAllActions();
Common Patterns¶
Pattern 1: Copy-Paste Sequence¶
// Copy
actionManager.handleCopySequence(); // Interactive (shows modal)
// OR
await actionManager.executeActionFunction('copySequence', {
chromosome: 'chr1',
start: 1000,
end: 2000,
strand: '+',
});
// Paste
actionManager.handlePasteSequence(); // Interactive (shows modal)
// OR
await actionManager.executeActionFunction('pasteSequence', {
chromosome: 'chr2',
start: 5000,
end: 5000,
});
// Execute
await actionManager.executeAllActions();
Pattern 2: Delete Region¶
// Add delete action
actionManager.addAction(actionManager.ACTION_TYPES.DELETE_SEQUENCE, 'chr1:1000-2000(+)', 'Delete 1kb region', {
chromosome: 'chr1',
start: 1000,
end: 2000,
strand: '+',
});
// Execute
await actionManager.executeAllActions();
Pattern 3: Insert Sequence¶
// Add insert action
actionManager.addAction(actionManager.ACTION_TYPES.INSERT_SEQUENCE, 'chr1:1000', 'Insert restriction site', {
chromosome: 'chr1',
start: 1000,
end: 1000,
insertSequence: 'GAATTC',
strand: '+',
});
// Execute
await actionManager.executeAllActions();
Pattern 4: Replace Region¶
// Add replace action
actionManager.addAction(
actionManager.ACTION_TYPES.REPLACE_SEQUENCE,
'chr1:1000-1006(+)',
'Replace with optimized codon',
{
chromosome: 'chr1',
start: 1000,
end: 1006,
newSequence: 'ATGATG',
strand: '+',
}
);
// Execute
await actionManager.executeAllActions();
MCP Function Calls¶
For AI/External Tools¶
// Copy sequence (MCP)
const result = await actionManager.executeActionFunction('copySequence', {
chromosome: 'chr1',
start: 1000,
end: 2000,
strand: '+',
});
// Get action list
const actions = actionManager.executeActionFunction('getActionList', {
status: 'pending', // or 'all', 'completed', 'failed'
});
// Execute actions
const execResult = await actionManager.executeActionFunction('executeActions', {
confirm: true,
});
// Clear actions
actionManager.executeActionFunction('clearActions', {
status: 'completed',
});
// Get clipboard
const clipboard = actionManager.executeActionFunction('getClipboardContent', {});
// Undo last action
await actionManager.executeActionFunction('undoLastAction', {});
Action Object Structure¶
{
id: 1, // Unique ID
type: 'copy_sequence', // Action type
target: 'chr1:1000-2000(+)', // Target location
details: 'Copy promoter region', // Description
metadata: {
chromosome: 'chr1',
start: 1000,
end: 2000,
strand: '+',
// ... type-specific fields
},
status: 'pending', // pending|executing|completed|failed
timestamp: Date, // Creation time
estimatedTime: 500, // Estimated ms
result: null, // Execution result
error: null // Error message
}
Status Codes¶
actionManager.STATUS = {
PENDING: 'pending', // Waiting to execute
EXECUTING: 'executing', // Currently running
COMPLETED: 'completed', // Successfully finished
FAILED: 'failed', // Execution failed
};
Action Types¶
actionManager.ACTION_TYPES = {
COPY_SEQUENCE: 'copy_sequence', // Copy to clipboard
CUT_SEQUENCE: 'cut_sequence', // Cut to clipboard
PASTE_SEQUENCE: 'paste_sequence', // Paste from clipboard
DELETE_SEQUENCE: 'delete_sequence', // Delete region
INSERT_SEQUENCE: 'insert_sequence', // Insert new sequence
REPLACE_SEQUENCE: 'replace_sequence', // Replace region
SEQUENCE_EDIT: 'sequence_edit', // Generic edit
};
Clipboard Operations¶
Get Clipboard Content¶
const clipboard = actionManager.clipboard;
if (clipboard) {
console.log('Type:', clipboard.type); // 'copy' or 'cut'
console.log('Sequence:', clipboard.sequence); // DNA string
console.log('Source:', clipboard.source); // 'chr1:1000-2000(+)'
console.log('Length:', clipboard.sequence.length); // Number of bp
console.log('Features:', clipboard.comprehensiveData.features); // Array
}
Check if Clipboard Has Data¶
if (actionManager.clipboard && actionManager.clipboard.sequence) {
// Clipboard has data
console.log(`Clipboard contains ${actionManager.clipboard.sequence.length} bp`);
} else {
// Clipboard empty
console.log('Clipboard is empty');
}
Selection Handling¶
Get Active Selection¶
const selection = actionManager.getActiveSelection();
if (selection.hasSelection) {
console.log('Chromosome:', selection.chromosome);
console.log('Start:', selection.start);
console.log('End:', selection.end);
console.log('Strand:', selection.strand);
console.log('Source:', selection.source); // 'manual', 'gene', 'selectedGene'
console.log('Name:', selection.name);
} else {
console.log('No active selection');
}
Queue Management¶
Get Queue Status¶
// Get all actions
const allActions = actionManager.actions;
// Get pending actions
const pending = actionManager.actions.filter(a => a.status === 'pending');
// Get completed actions
const completed = actionManager.actions.filter(a => a.status === 'completed');
// Get failed actions
const failed = actionManager.actions.filter(a => a.status === 'failed');
console.log(
`Total: ${allActions.length}, Pending: ${pending.length}, Completed: ${completed.length}, Failed: ${failed.length}`
);
Clear Queue¶
// Clear all actions
actionManager.clearAllActions();
// Clear only completed
actionManager.actions = actionManager.actions.filter(a => a.status !== 'completed');
actionManager.updateActionListUI();
// Clear only failed
actionManager.actions = actionManager.actions.filter(a => a.status !== 'failed');
actionManager.updateActionListUI();
Remove Specific Action¶
// Remove by ID
actionManager.removeAction(actionId);
// Remove by index
const index = 0;
actionManager.actions.splice(index, 1);
actionManager.updateActionListUI();
Feature Tracking¶
Collect Region Data¶
const data = await actionManager.collectComprehensiveData(
'chr1', // chromosome
1000, // start
2000, // end
'+' // strand
);
console.log('Region:', data.region);
console.log('Features:', data.features.length);
console.log('Variants:', data.variants.length);
console.log('Reads:', data.reads.length);
console.log('GC%:', data.metadata.gcContent);
Get Sequence for Region¶
const sequence = await actionManager.getSequenceForRegion(
'chr1', // chromosome
1000, // start
2000, // end
'+' // strand ('+' or '-')
);
console.log('Sequence:', sequence);
console.log('Length:', sequence.length);
Conflict Detection¶
Check for Conflicts¶
const pending = actionManager.actions.filter(a => a.status === 'pending');
const analysis = actionManager.checkActionConflicts(pending);
if (analysis.hasConflicts) {
console.log(`Found ${analysis.conflicts.length} conflicts`);
analysis.conflicts.forEach(conflict => {
console.log(`Conflict: ${conflict.description}`);
console.log(` Severity: ${conflict.severity}`);
console.log(` Chromosome: ${conflict.chromosome}`);
console.log(` Overlap: ${conflict.overlapStart}-${conflict.overlapEnd}`);
});
} else {
console.log('No conflicts detected');
}
Export¶
Generate GenBank File¶
// Automatic during execution
await actionManager.executeAllActions();
// GBK file automatically generated with action history
// Manual generation
const executionActionsCopy = [...actionManager.actions];
const executionGenomeData = actionManager.createGenomeDataCopy(originalData);
const executionId = `manual_${Date.now()}`;
await actionManager.generateComprehensiveGBK(executionActionsCopy, executionGenomeData, executionId);
Error Handling¶
Try-Catch Pattern¶
try {
await actionManager.executeAllActions();
console.log('✅ Actions executed successfully');
} catch (error) {
console.error('❌ Execution failed:', error);
// Check failed actions
const failed = actionManager.actions.filter(a => a.status === 'failed');
failed.forEach(action => {
console.error(`Failed action ${action.id}:`, action.error);
});
}
Validation Before Execution¶
// Validate before executing
const pending = actionManager.actions.filter(a => a.status === 'pending');
if (pending.length === 0) {
console.log('No pending actions to execute');
} else {
// Check conflicts
const analysis = actionManager.checkActionConflicts(pending);
if (analysis.hasConflicts) {
console.warn('Conflicts detected!');
// Show conflict dialog or handle
} else {
// Safe to execute
await actionManager.executeAllActions();
}
}
UI Integration¶
Show Action List¶
// Show action list modal
actionManager.showActionList();
// Update action list UI
actionManager.updateActionListUI();
// Update stats display
actionManager.updateStats();
Update Actions Track¶
// Notify track to update
actionManager.notifyActionsTrackUpdate();
// Check if visible
const trackActionsCheckbox = document.getElementById('trackActions');
const isVisible = trackActionsCheckbox && trackActionsCheckbox.checked;
if (isVisible) {
genomeBrowser.trackRenderer.updateActionsTrack();
}
Advanced Usage¶
Custom Action Metadata¶
actionManager.addAction(actionManager.ACTION_TYPES.COPY_SEQUENCE, 'chr1:1000-2000(+)', 'Copy for analysis', {
chromosome: 'chr1',
start: 1000,
end: 2000,
strand: '+',
// Custom metadata
experimentId: 'EXP001',
researcher: 'John Doe',
purpose: 'Promoter analysis',
tags: ['promoter', 'essential'],
notes: 'Region of interest for transcription factor binding',
});
Programmatic Action Creation¶
// Create multiple actions programmatically
const regions = [
{ chr: 'chr1', start: 1000, end: 2000 },
{ chr: 'chr2', start: 3000, end: 4000 },
{ chr: 'chr3', start: 5000, end: 6000 },
];
regions.forEach(region => {
actionManager.addAction(
actionManager.ACTION_TYPES.COPY_SEQUENCE,
`${region.chr}:${region.start}-${region.end}(+)`,
`Copy ${region.chr} region`,
{
chromosome: region.chr,
start: region.start,
end: region.end,
strand: '+',
}
);
});
console.log(`Created ${regions.length} actions`);
Monitor Execution Progress¶
// Track execution progress
let executedCount = 0;
const totalActions = actionManager.actions.filter(a => a.status === 'pending').length;
// Poll status during execution
const progressInterval = setInterval(() => {
const completed = actionManager.actions.filter(a => a.status === 'completed' || a.status === 'failed').length;
if (completed > executedCount) {
executedCount = completed;
const progress = ((executedCount / totalActions) * 100).toFixed(1);
console.log(`Progress: ${progress}% (${executedCount}/${totalActions})`);
}
if (executedCount >= totalActions || !actionManager.isExecuting) {
clearInterval(progressInterval);
console.log('Execution complete');
}
}, 100);
await actionManager.executeAllActions();
Debugging¶
Enable Verbose Logging¶
// Check execution state
console.log('Is executing:', actionManager.isExecuting);
console.log('Actions count:', actionManager.actions.length);
console.log('Clipboard:', actionManager.clipboard);
console.log('Modifications:', actionManager.sequenceModifications);
// Log all actions
actionManager.actions.forEach((action, index) => {
console.log(`Action ${index + 1}:`, {
id: action.id,
type: action.type,
target: action.target,
status: action.status,
metadata: action.metadata,
});
});
Inspect Sequence Modifications¶
// Get modifications for chromosome
const chrModifications = actionManager.sequenceModifications.get('chr1');
if (chrModifications) {
console.log(`Modifications on chr1:`, chrModifications);
chrModifications.forEach((mod, index) => {
console.log(` ${index + 1}. ${mod.type} at position ${mod.position}`);
});
} else {
console.log('No modifications on chr1');
}
Validate Action Queue¶
// Check for invalid actions
const invalid = actionManager.actions.filter(action => {
if (!action.type || !action.target || !action.metadata) {
return true;
}
const { start, end } = action.metadata;
if (start !== undefined && end !== undefined && start >= end) {
return true;
}
return false;
});
if (invalid.length > 0) {
console.warn(`Found ${invalid.length} invalid actions:`, invalid);
}
Troubleshooting¶
Problem: Actions not executing¶
Check:
- Is execution already running?
actionManager.isExecuting - Are there pending actions?
actionManager.actions.filter(a => a.status === 'pending') - Are there conflicts?
actionManager.checkActionConflicts(pending)
Solution:
if (actionManager.isExecuting) {
console.log('Already executing, please wait');
} else {
const pending = actionManager.actions.filter(a => a.status === 'pending');
if (pending.length === 0) {
console.log('No pending actions');
} else {
await actionManager.executeAllActions();
}
}
Problem: Clipboard empty¶
Check:
if (!actionManager.clipboard || !actionManager.clipboard.sequence) {
console.log('Clipboard is empty - please copy or cut sequence first');
} else {
console.log('Clipboard contains:', actionManager.clipboard.sequence.length, 'bp');
}
Problem: Features not updating¶
Check:
- Ensure original annotations backed up
- Check sequence modifications recorded
- Verify feature adjustment called
Solution:
// Force feature update
if (actionManager.genomeBrowser.trackRenderer) {
actionManager.genomeBrowser.trackRenderer.updateFeatureTrack();
}
Performance Tips¶
1. Batch Actions¶
// ✅ GOOD: Add all actions first, then execute once
regions.forEach(r => actionManager.addAction(...));
await actionManager.executeAllActions();
// ❌ BAD: Execute after each action
regions.forEach(async r => {
actionManager.addAction(...);
await actionManager.executeAllActions(); // Slow!
});
2. Clear Completed Actions¶
// Periodically clear completed actions to reduce queue size
if (actionManager.actions.length > 100) {
actionManager.actions = actionManager.actions.filter(a => a.status === 'pending' || a.status === 'executing');
actionManager.updateActionListUI();
}
3. Use Checkpoints for Large Operations¶
// Create checkpoint before major changes
const checkpointId = await checkpointManager.createCheckpoint(
'Before major editing',
checkpointManager.CHECKPOINT_TYPES.MANUAL
);
try {
// Perform operations
await actionManager.executeAllActions();
} catch (error) {
// Rollback on failure
await checkpointManager.rollbackToCheckpoint(checkpointId);
}
Best Practices¶
- Always validate inputs before creating actions
- Check for conflicts before execution
- Use descriptive names for actions
- Include comprehensive metadata for tracking
- Handle errors gracefully with try-catch
- Clear completed actions periodically
- Create checkpoints before major changes
- Monitor execution progress for long operations
- Test with small datasets first
- Document custom workflows for team
Related Documentation¶
- Full Actions System Documentation
- Improvement Proposal
- CheckpointManager Guide (if exists)
- MCP Integration Guide (if exists)
Last Updated: 2025-11-03
Maintainer: CodeXomics Team