Skill: aipoch-ai/fastqc-report-interpreter (version 0.1.0)

--- name: fastqc-report-interpreter description: Use when analyzing FASTQC quality reports from sequencing data, identifying quality issues in NGS datasets, or troubleshooting sequencing problems. Interprets quality metrics and provides actionable recommendations for RNA-seq, DNA-seq, and ChIP-seq data. allowed-tools: "Read Write Bash Edit" license: MIT metadata: skill-author: AIPOCH version: "1.0" --- # FASTQC Report Interpreter Analyze FASTQC quality control reports for Next-Generation Sequencing (NGS) data to assess data quality and identify issues. ## Quick Start ```python from scripts.fastqc_interpreter import FASTQCInterpreter interpreter = FASTQCInterpreter() # Analyze report analysis = interpreter.analyze("sample_fastqc.html") print(f"Overall Quality: {analysis.quality_status}") print(f"Issues Found: {analysis.issues}") ``` ## Core Capabilities ### 1. Quality Metrics Analysis ```python metrics = interpreter.parse_metrics("fastqc_data.txt") ``` **Key Metrics:** | Metric | Good | Warning | Fail | |--------|------|---------|------| | Per base sequence quality | Q > 28 | Q 20-28 | Q < 20 | | Per sequence quality scores | Peak at Q30 | Peak Q20-30 | Peak < Q20 | | Per base N content | < 5% | 5-20% | > 20% | | Sequence duplication | < 20% | 20-50% | > 50% | | Adapter content | < 5% | 5-10% | > 10% | ### 2. Issue Diagnosis ```python issues = interpreter.diagnose_issues(metrics) for issue in issues: print(f"{issue.severity}: {issue.description}") print(f"Recommendation: {issue.recommendation}") ``` **Common Issues:** **Low Quality at Read Ends** - **Cause**: Phasing effects, reagent depletion - **Solution**: Trim last 10-20 bases **Adapter Contamination** - **Cause**: Incomplete adapter removal - **Solution**: Re-run cutadapt/Trimmomatic with stricter parameters **High Duplication** - **Cause**: PCR over-amplification, low input - **Solution**: Use deduplication; consider library prep optimization **Per Base Sequence Content Bias** - **Cause**: Adapter dimers, non-random priming - **Solution**: Check for adapter contamination; randomize primers ### 3. Batch Analysis ```python batch_results = interpreter.analyze_batch( fastqc_files=["sample1_fastqc.html", "sample2_fastqc.html", ...], output_summary="batch_summary.csv" ) ``` ### 4. Recommendation Generation ```python recommendations = interpreter.get_recommendations( analysis, application="rna_seq", # or "dna_seq", "chip_seq" quality_threshold="high" ) ``` **Application-Specific Thresholds:** - **RNA-seq**: Acceptable duplication up to 40% (transcript abundance) - **DNA-seq**: Strict quality requirements (variant calling) - **ChIP-seq**: Moderate quality, focus on enrichment metrics ## CLI Usage ```bash # Analyze single report python scripts/fastqc_interpreter.py --input sample_fastqc.html # Batch analysis python scripts/fastqc_interpreter.py --batch "*fastqc.html" --output report.pdf # With custom thresholds python scripts/fastqc_interpreter.py --input fastqc.html --application rna_seq ``` ## Output Interpretation **PASS (Green)**: Proceed with analysis **WARNING (Yellow)**: Review but likely acceptable **FAIL (Red)**: Requires action before downstream analysis ## Troubleshooting Guide See `references/troubleshooting.md` for: - Platform-specific issues (Illumina, PacBio, Oxford Nanopore) - Library prep problem diagnosis - Downstream analysis impact assessment --- **Skill ID**: 205 | **Version**: 1.0 | **License**: MIT

path: scripts/main.py
content: #!/usr/bin/env python3
"""
FastQC Report Interpreter
Interpret NGS quality control reports in plain language.
"""

import argparse
import json


class FastQCInterpreter:
    """Interpret FastQC reports."""
    
    QC_THRESHOLDS = {
        "per_base_quality": {
            "good": {"min": 28, "description": "High quality reads"},
            "warning": {"min": 20, "description": "Acceptable quality"},
            "fail": {"min": 0, "description": "Poor quality, consider trimming"}
        },
        "per_sequence_quality": {
            "good": {"min_mean": 30, "description": "Excellent overall quality"},
            "warning": {"min_mean": 25, "description": "Good quality"},
            "fail": {"min_mean": 0, "description": "Check for systematic issues"}
        },
        "gc_content": {
            "good": {"deviation": 5, "description": "Normal GC distribution"},
            "warning": {"deviation": 10, "description": "Slightly abnormal GC"},
            "fail": {"deviation": 15, "description": "Possible contamination or bias"}
        },
        "adapter_content": {
            "good": {"max": 5, "description": "Minimal adapter contamination"},
            "warning": {"max": 10, "description": "Some adapter presence"},
            "fail": {"max": 100, "description": "Significant adapter contamination - trim required"}
        },
        "duplication_levels": {
            "good": {"max": 20, "description": "Low duplication - good library complexity"},
            "warning": {"max": 50, "description": "Moderate duplication"},
            "fail": {"max": 100, "description": "High duplication - check PCR cycles"}
        }
    }
    
    def interpret_module(self, module_name, module_data):
        """Interpret a single FastQC module."""
        thresholds = self.QC_THRESHOLDS.get(module_name, {})
        
        if not thresholds:
            return {"status": "unknown", "interpretation": "No interpretation available"}
        
        # Simplified interpretation logic
        status = "good"
        interpretation = thresholds["good"]["description"]
        
        # Check against thresholds (simplified)
        if module_data.get("failed", False):
            status = "fail"
            interpretation = thresholds["fail"]["description"]
        elif module_data.get("warning", False):
            status = "warning"
            interpretation = thresholds["warning"]["description"]
        
        return {
            "status": status,
            "interpretation": interpretation,
            "recommendations": self.get_recommendations(module_name, status)
        }
    
    def get_recommendations(self, module_name, status):
        """Get recommendations based on status."""
        recommendations = {
            "per_base_quality": {
                "fail": ["Trim low quality bases from 3' end", "Consider more stringent filtering"],
                "warning": ["Monitor quality in downstream analysis", "Consider trimming if issues persist"]
            },
            "adapter_content": {
                "fail": ["Trim adapters using cutadapt or Trimmomatic", "Re-check library prep protocol"],
                "warning": ["Mild adapter trimming recommended"]
            },
            "duplication_levels": {
                "fail": ["Reduce PCR cycles in library prep", "Consider starting with more input material"],
                "warning": ["Monitor for PCR artifacts in analysis"]
            },
            "gc_content": {
                "fail": ["Check for contamination", "Verify species matches expected genome"],
                "warning": ["Check GC bias in downstream analysis"]
            }
        }
        
        return recommendations.get(module_name, {}).get(status, ["No specific recommendations"])
    
    def interpret_report(self, fastqc_data):
        """Interpret complete FastQC report."""
        interpretations = {}
        
        for module_name, module_data in fastqc_data.items():
            interpretations[module_name] = self.interpret_module(module_name, module_data)
        
        return interpretations
    
    def print_report(self, interpretations):
        """Print interpreted report."""
        print(f"\n{'='*60}")
        print("FASTQC REPORT INTERPRETATION")
        print(f"{'='*60}\n")
        
        status_icons = {"good": "✓", "warning": "⚠", "fail": "✗", "unknown": "?"}
        
        for module, result in interpretations.items():
            icon = status_icons.get(result["status"], "?")
            print(f"{icon} {module.replace('_', ' ').title()}")
            print(f"   Status: {result['status'].upper()}")
            print(f"   {result['interpretation']}")
            
            if result.get("recommendations"):
                print("   Recommendations:")
                for rec in result["recommendations"]:
                    print(f"      • {rec}")
            print()
        
        print(f"{'='*60}\n")


def main():
    parser = argparse.ArgumentParser(description="FastQC Report Interpreter")
    parser.add_argument("--report", "-r", help="FastQC JSON report")
    parser.add_argument("--demo", action="store_true", help="Show demo interpretation")
    
    args = parser.parse_args()
    
    interpreter = FastQCInterpreter()
    
    if args.report:
        with open(args.report) as f:
            fastqc_data = json.load(f)
    else:
        # Demo data
        fastqc_data = {
            "per_base_quality": {"failed": False, "warning": False, "mean": 32},
            "per_sequence_quality": {"failed": False, "warning": False, "mean": 31},
            "gc_content": {"failed": False, "warning": True, "deviation": 8},
            "adapter_content": {"failed": False, "warning": False, "percent": 2},
            "duplication_levels": {"failed": True, "warning": False, "percent": 65}
        }
    
    interpretations = interpreter.interpret_report(fastqc_data)
    interpreter.print_report(interpretations)


if __name__ == "__main__":
    main()


Security scan verdicts — ClawScan: clean | static analysis: clean | VirusTotal: clean | SkillSpector: clean (LOW)