/bio-fastq-quality
Work with FASTQ quality scores using Biopython. Use when analyzing read quality, filtering by quality, trimming low-quality bases, or generating quality reports.
$ npx -y skills add FreedomIntelligence/OpenClaw-Medical-Skills --skill bio-fastq-quality --agent claude-codeHow it fires
How this skill gets triggered: by you, by Claude, or both.
- Fires itselfAuto-invocation. Claude auto-loads it when your prompt matches the work.Auto-invocation is when the right skill fires by itself at the right moment, driven by a FLOW.md router and a hook, instead of you invoking it by name. It is the difference between a skill being installed and a skill actually getting used.Read the full definition →
- You can call itInvoke it directly when you want it.
- Slash command
/bio-fastq-quality
Context preview
The summary Claude sees to decide when to auto-load this skill.
Work with FASTQ quality scores using Biopython. Use when analyzing read quality, filtering by quality, trimming low-quality bases, or generating quality reports.
SKILL.md
bio-fastq-quality.SKILL.mdname: bio-fastq-quality
description: Work with FASTQ quality scores using Biopython. Use when analyzing read quality, filtering by quality, trimming low-quality bases, or generating quality reports.
tool_type: python
primary_tool: Bio.SeqIO
Version Compatibility
Reference examples tested with: BioPython 1.83+
Before using code patterns, verify installed versions match. If versions differ:
- Python: `pip show <package>` then `help(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.
FASTQ Quality Scores
**"Filter my FASTQ reads by quality score"** → Access, analyze, and filter Phred quality scores, trim low-quality bases, and generate per-position quality profiles.
- Python: `SeqIO.parse()` with `letter_annotations['phred_quality']` (BioPython)
Analyze and manipulate FASTQ quality scores using Biopython.
Required Imports
from Bio import SeqIO
from Bio.Seq import Seq
Accessing Quality Scores
Quality scores are stored in `letter_annotations['phred_quality']` as a list of integers.
for record in SeqIO.parse('reads.fastq', 'fastq'):
qualities = record.letter_annotations['phred_quality']
print(record.id, qualities[:10]) # First 10 quality scoresQuality Score Basics
| Phred Score | Error Probability | Accuracy | |-------------|-------------------|----------| | 10 | 1 in 10 | 90% | | 20 | 1 in 100 | 99% | | 30 | 1 in 1000 | 99.9% | | 40 | 1 in 10000 | 99.99% |
Code Patterns
Calculate Average Quality per Read
for record in SeqIO.parse('reads.fastq', 'fastq'):
quals = record.letter_annotations['phred_quality']
avg_qual = sum(quals) / len(quals)
print(f'{record.id}: {avg_qual:.1f}')Filter Reads by Mean Quality
def high_quality_reads(records, min_avg_qual=20):
for record in records:
quals = record.letter_annotations['phred_quality']
if sum(quals) / len(quals) >= min_avg_qual:
yield record
records = SeqIO.parse('reads.fastq', 'fastq')
good_reads = high_quality_reads(records, min_avg_qual=25)
SeqIO.write(good_reads, 'filtered.fastq', 'fastq')Filter by Minimum Quality at Any Position
def all_bases_above(records, min_qual=20):
for record in records:
if min(record.letter_annotations['phred_quality']) >= min_qual:
yield recordTrim Low-Quality Ends (3' Trimming)
def trim_low_quality(record, min_qual=20):
quals = record.letter_annotations['phred_quality']
trim_pos = len(quals)
for i in range(len(quals) - 1, -1, -1):
if quals[i] >= min_qual:
trim_pos = i + 1
break
return record[:trim_pos]
records = SeqIO.parse('reads.fastq', 'fastq')
trimmed = (trim_low_quality(rec) for rec in records)
SeqIO.write(trimmed, 'trimmed.fastq', 'fastq')Sliding Window Quality Trim
**Goal:** Trim a read at the first position where average quality in a sliding window drops below threshold.
**Approach:** Slide a fixed-size window across quality scores; when the window average falls below the cutoff, truncate the record at that position.
**Reference (BioPython 1.83+):**
def sliding_window_trim(record, window_size=5, min_avg_qual=20):
quals = record.letter_annotations['phred_quality']
for i in range(len(quals) - window_size + 1):
window = quals[i:i + window_size]
if sum(window) / window_size < min_avg_qual:
return record[:i] if i > 0 else None
return recordQuality Statistics Summary
import statistics
all_quals = []
for record in SeqIO.parse('reads.fastq', 'fastq'):
all_quals.extend(record.letter_annotations['phred_quality'])
print(f'Mean quality: {statistics.mean(all_quals):.1f}')
print(f'Median quality: {statistics.median(all_quals):.1f}')
print(f'Min quality: {min(all_quals)}')
print(f'Max quality: {max(all_quals)}')Per-Position Quality Profile
**Goal:** Compute mean quality at each read position to identify systematic quality drops (e.g., read-end degradation).
**Approach:** Accumulate quality scores by position across all reads, then compute per-position means.
**Reference (BioPython 1.83+):**
from collections import defaultdict
position_quals = defaultdict(list)
for record in SeqIO.parse('reads.fastq', 'fastq'):
for i, q in enumerate(record.letter_annotations['phred_quality']):
position_quals[i].append(q)
for pos in sorted(position_quals.keys())[:20]:
quals = position_quals[pos]
print(f'Position {pos}: mean={sum(quals)/len(quals):.1f}')Count Reads by Quality Threshold
thresholds = [20, 25, 30, 35]
counts = {t: 0 for t in thresholds}
for record in SeqIO.parse('reads.fastq', 'fastq'):
avg = sum(record.letter_annotations['phred_quality']) / len(record.seq)
for t in thresholds:
if avg >= t:
counts[t] += 1
for t, c in counts.items():
print(f'Q>={t}: {c} reads')Remove N Bases and Low Quality Together
def clean_read(record, min_qual=20):
seq = str(record.seq)
quals = record.letter_annotations['phred_quality']
keep = [(s, q) for s, q in zip(seq, quals) if s != 'N' and q >= min_qual]
if not keep:
return None
new_seq, new_quals = zip(*keep)
new_record = record[:0] # Empty copy with same metadata
new_record.seq = Seq(''.join(new_seq))
new_record.letter_annotations['phred_quality'] = list(new_quals)
return new_recordFASTQ Format Variants
| Variant | Format String | Quality Encoding | ASCII Range | |---------|---------------|------------------|-------------| | Sanger/Illumina 1.8+ | `'fastq'` | Phred+33 (standard) | 33-126 | | Solexa | `'fastq-solexa'` | Solexa+64 | 59-126 | | Illumina 1.3-1.7 | `'fastq-illumina'` | Phred+64 | 64-126 |
Most modern data uses standard `'fastq'` (
Read more
name: bio-fastq-quality description: Work with FASTQ quality scores using Biopython. Use when analyzing read quality, filtering by quality, trimming low-quality bases, or generating quality reports. tool_type: python primary_tool: Bio.SeqIO
Version Compatibility
Reference examples tested with: BioPython 1.83+
Before using code patterns, verify installed versions match. If versions differ:
- Python: `pip show <package>` then `help(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.
FASTQ Quality Scores
**"Filter my FASTQ reads by quality score"** → Access, analyze, and filter Phred quality scores, trim low-quality bases, and generate per-position quality profiles.
- Python: `SeqIO.parse()` with `letter_annotations['phred_quality']` (BioPython)
Analyze and manipulate FASTQ quality scores using Biopython.
Required Imports
from Bio import SeqIO from Bio.Seq import Seq
Accessing Quality Scores
Quality scores are stored in `letter_annotations['phred_quality']` as a list of integers.
for record in SeqIO.parse('reads.fastq', 'fastq'):
qualities = record.letter_annotations['phred_quality']
print(record.id, qualities[:10]) # First 10 quality scoresQuality Score Basics
| Phred Score | Error Probability | Accuracy | |-------------|-------------------|----------| | 10 | 1 in 10 | 90% | | 20 | 1 in 100 | 99% | | 30 | 1 in 1000 | 99.9% | | 40 | 1 in 10000 | 99.99% |
Code Patterns
Calculate Average Quality per Read
for record in SeqIO.parse('reads.fastq', 'fastq'):
quals = record.letter_annotations['phred_quality']
avg_qual = sum(quals) / len(quals)
print(f'{record.id}: {avg_qual:.1f}')Filter Reads by Mean Quality
def high_quality_reads(records, min_avg_qual=20):
for record in records:
quals = record.letter_annotations['phred_quality']
if sum(quals) / len(quals) >= min_avg_qual:
yield record
records = SeqIO.parse('reads.fastq', 'fastq')
good_reads = high_quality_reads(records, min_avg_qual=25)
SeqIO.write(good_reads, 'filtered.fastq', 'fastq')Filter by Minimum Quality at Any Position
def all_bases_above(records, min_qual=20):
for record in records:
if min(record.letter_annotations['phred_quality']) >= min_qual:
yield recordTrim Low-Quality Ends (3' Trimming)
def trim_low_quality(record, min_qual=20):
quals = record.letter_annotations['phred_quality']
trim_pos = len(quals)
for i in range(len(quals) - 1, -1, -1):
if quals[i] >= min_qual:
trim_pos = i + 1
break
return record[:trim_pos]
records = SeqIO.parse('reads.fastq', 'fastq')
trimmed = (trim_low_quality(rec) for rec in records)
SeqIO.write(trimmed, 'trimmed.fastq', 'fastq')Sliding Window Quality Trim
**Goal:** Trim a read at the first position where average quality in a sliding window drops below threshold.
**Approach:** Slide a fixed-size window across quality scores; when the window average falls below the cutoff, truncate the record at that position.
**Reference (BioPython 1.83+):**
def sliding_window_trim(record, window_size=5, min_avg_qual=20):
quals = record.letter_annotations['phred_quality']
for i in range(len(quals) - window_size + 1):
window = quals[i:i + window_size]
if sum(window) / window_size < min_avg_qual:
return record[:i] if i > 0 else None
return recordQuality Statistics Summary
import statistics
all_quals = []
for record in SeqIO.parse('reads.fastq', 'fastq'):
all_quals.extend(record.letter_annotations['phred_quality'])
print(f'Mean quality: {statistics.mean(all_quals):.1f}')
print(f'Median quality: {statistics.median(all_quals):.1f}')
print(f'Min quality: {min(all_quals)}')
print(f'Max quality: {max(all_quals)}')Per-Position Quality Profile
**Goal:** Compute mean quality at each read position to identify systematic quality drops (e.g., read-end degradation).
**Approach:** Accumulate quality scores by position across all reads, then compute per-position means.
**Reference (BioPython 1.83+):**
from collections import defaultdict
position_quals = defaultdict(list)
for record in SeqIO.parse('reads.fastq', 'fastq'):
for i, q in enumerate(record.letter_annotations['phred_quality']):
position_quals[i].append(q)
for pos in sorted(position_quals.keys())[:20]:
quals = position_quals[pos]
print(f'Position {pos}: mean={sum(quals)/len(quals):.1f}')Count Reads by Quality Threshold
thresholds = [20, 25, 30, 35]
counts = {t: 0 for t in thresholds}
for record in SeqIO.parse('reads.fastq', 'fastq'):
avg = sum(record.letter_annotations['phred_quality']) / len(record.seq)
for t in thresholds:
if avg >= t:
counts[t] += 1
for t, c in counts.items():
print(f'Q>={t}: {c} reads')Remove N Bases and Low Quality Together
def clean_read(record, min_qual=20):
seq = str(record.seq)
quals = record.letter_annotations['phred_quality']
keep = [(s, q) for s, q in zip(seq, quals) if s != 'N' and q >= min_qual]
if not keep:
return None
new_seq, new_quals = zip(*keep)
new_record = record[:0] # Empty copy with same metadata
new_record.seq = Seq(''.join(new_seq))
new_record.letter_annotations['phred_quality'] = list(new_quals)
return new_recordFASTQ Format Variants
| Variant | Format String | Quality Encoding | ASCII Range | |---------|---------------|------------------|-------------| | Sanger/Illumina 1.8+ | `'fastq'` | Phred+33 (standard) | 33-126 | | Solexa | `'fastq-solexa'` | Solexa+64 | 59-126 | | Illumina 1.3-1.7 | `'fastq-illumina'` | Phred+64 | 64-126 |
Most modern data uses standard `'fastq'` (
The largest open-source medical AI skill library for OpenClaw.
Other skills on openclaw-medical-skills.
adaptyv
Cloud laboratory platform for automated protein testing and validation. Use when designing proteins and needing experimental validation including binding…
adhd-daily-planner
Time-blind friendly planning, executive function support, and daily structure for ADHD brains. Specializes in realistic time estimation, dopamine-aware task…
aeon
This skill should be used for time series machine learning tasks including classification, regression, clustering, forecasting, anomaly detection,…
agent-browser
Browse the web for any task — research topics, read articles, interact with web apps, fill forms, take screenshots, extract data, and test web pages. Use…

