SKILL.md
Version Compatibility
Reference examples tested with: BioPython 1.83+
Before using code patterns, verify installed versions match. If versions differ:
- Python:
pip show <package>thenhelp(module.function)to check signatures
If code throws ImportError, AttributeError, or TypeError, introspect the installed package and adapt the example to match the actual API rather than retrying.
Base Editing Design
"Design a base editor guide for my C-to-T conversion" → Identify guide sequences that position the target nucleotide within the editing window of cytosine (CBE) or adenine (ABE) base editors, predicting editing outcomes and bystander effects.
- Python: editing window analysis with
Bio.Seq, BE-Hive outcome prediction
Base Editor Types
Cytosine Base Editors (CBE):
- Convert C to T (or G to A on opposite strand)
- Examples: BE3, BE4, BE4max, AncBE4max
- Editing window: Positions 4-8 (PAM-distal numbering)
Adenine Base Editors (ABE):
- Convert A to G (or T to C on opposite strand)
- Examples: ABE7.10, ABE8e, ABE8.20
- Editing window: Positions 4-7 (narrower than CBE)
Position numbering:
Position 1 = PAM-proximal (next to NGG)
Position 20 = PAM-distal (5' end of spacer)
Editing window is typically positions 4-8 from PAM-distal end
Find Editable Positions
Goal: Identify guide sequences that place a target nucleotide within the base editor's editing window while minimizing bystander edits.
Approach: Scan for PAM sites in both orientations, calculate where the target base falls within the spacer, filter guides where the target lands in the CBE (positions 4-8) or ABE (positions 4-7) editing window, and rank by fewest bystander bases in the window.
from Bio.Seq import Seq
import re
# Editing window positions (1-indexed from PAM-distal end)
# Position 1 is first nt of spacer, position 20 is adjacent to PAM
CBE_WINDOW = (4, 8) # BE4max optimal window
ABE_WINDOW = (4, 7) # ABE8e optimal window
def find_cbe_targets(sequence, target_c_position):
'''Find guides that place a C in the CBE editing window
Args:
sequence: DNA sequence containing the target C
target_c_position: 0-indexed position of C to edit
Returns:
List of guide options with editing predictions
'''
sequence = sequence.upper()
guides = []
# Search for PAMs that would place target C in window
for pam_match in re.finditer(r'(?=(.GG))', sequence):
pam_pos = pam_match.start()
# Calculate where target C falls in the spacer
spacer_start = pam_pos - 20
if spacer_start < 0:
continue
c_position_in_spacer = target_c_position - spacer_start + 1 # 1-indexed
# Check if C is in editing window
if CBE_WINDOW[0] <= c_position_in_spacer <= CBE_WINDOW[1]:
spacer = sequence[spacer_start:pam_pos]
# Find bystander Cs in window (may also be edited)
bystanders = []
for i in range(CBE_WINDOW[0] - 1, CBE_WINDOW[1]):
if i < len(spacer) and spacer[i] == 'C' and (spacer_start + i) != target_c_position:
bystanders.append(i + 1)
guides.append({
'spacer': spacer,
'pam_position': pam_pos,
'target_position_in_spacer': c_position_in_spacer,
'bystander_cs': bystanders,
'bystander_count': len(bystanders),
'strand': '+'
})
# Sort by fewest bystanders
return sorted(guides, key=lambda x: x['bystander_count'])
def find_abe_targets(sequence, target_a_position):
'''Find guides that place an A in the ABE editing window'''
sequence = sequence.upper()
guides = []
for pam_match in re.finditer(r'(?=(.GG))', sequence):
pam_pos = pam_match.start()
spacer_start = pam_pos - 20
if spacer_start < 0:
continue
a_position_in_spacer = target_a_position - spacer_start + 1
if ABE_WINDOW[0] <= a_position_in_spacer <= ABE_WINDOW[1]:
spacer = sequence[spacer_start:pam_pos]
bystanders = []
for i in range(ABE_WINDOW[0] - 1, ABE_WINDOW[1]):
if i < len(spacer) and spacer[i] == 'A' and (spacer_start + i) != target_a_position:
bystanders.append(i + 1)
guides.append({
'spacer': spacer,
'pam_position': pam_pos,
'target_position_in_spacer': a_position_in_spacer,
'bystander_as': bystanders,
'bystander_count': len(bystanders),
'strand': '+'
})
return sorted(guides, key=lambda x: x['bystander_count'])
