CoolFace
Apppublic

NavVerma/RNA_Accessibility_Probablity

sourceHugging Facemitupdated 4mo agoView on Hugging Face
0likes
app.py3476 linesDownload Raw Back to root
1"""2IAV Cas13d Guide Accessibility Predictor  v23Seek Labs — Infectious Disease Therapeutics4"""5 6import os7import io8import math9import warnings10import concurrent.futures11import numpy as np12import pandas as pd13import streamlit as st14import plotly.graph_objects as go15from plotly.subplots import make_subplots16 17warnings.filterwarnings("ignore")18 19# ─── Page config ──────────────────────────────────────────────────────────────20 21st.set_page_config(22    page_title="Cas13d Guide Accessibility · Seek Labs",23    page_icon="🧬",24    layout="wide",25    initial_sidebar_state="expanded",26)27 28# ─── Login gate ───────────────────────────────────────────────────────────────29# Reads credentials from HF Space secrets. Supports both new (USER+PASS) and30# legacy (PASSWORD only) configurations. If neither is set, the app is open31# (useful for local dev).32 33APP_USERNAME = (34    os.environ.get("GS_RNA_AUTH_USER")35    or os.environ.get("APP_USERNAME")36    or ""37).strip()38APP_PASSWORD = (39    os.environ.get("GS_RNA_AUTH_PASS")40    or os.environ.get("APP_PASSWORD")41    or ""42).strip()43 44if APP_PASSWORD:45    if not st.session_state.get("auth_ok"):46        st.markdown("### 🔒 Cas13d Guide Accessibility — sign in")47        with st.form("login_form", clear_on_submit=False):48            user_in = st.text_input(49                "Username",50                value="",51                placeholder="Username" if APP_USERNAME else "(no username required)",52                key="login_user",53            )54            pw_in = st.text_input(55                "Password",56                type="password",57                placeholder="Required to continue",58                key="login_pw",59            )60            submitted = st.form_submit_button("Sign in")61        if submitted:62            user_ok = (not APP_USERNAME) or (user_in.strip() == APP_USERNAME)63            pw_ok = pw_in == APP_PASSWORD64            if user_ok and pw_ok:65                st.session_state["auth_ok"] = True66                st.rerun()67            else:68                st.error("Incorrect username or password.")69                st.stop()70        else:71            st.stop()72 73# ─── ViennaRNA import ─────────────────────────────────────────────────────────74 75try:76    import RNA77except ImportError:78    st.error(79        "ViennaRNA is not installed. "80        "Add `vienna-rna` to `packages.txt` and `ViennaRNA` to `requirements.txt`."81    )82    st.stop()83 84try:85    from Bio import SeqIO86    from Bio.Align import PairwiseAligner as _PairwiseAligner87    _BIOPYTHON_OK = True88except ImportError:89    SeqIO = None90    _PairwiseAligner = None91    _BIOPYTHON_OK = False92 93# ─── Constants ────────────────────────────────────────────────────────────────94 95DEFAULT_WIN      = 2396PLFOLD_W         = 8097PLFOLD_L         = 4098PARALLEL_WORKERS = 499LONG_SEQ_THRESH  = 1500   # nt above which we subsample100SUBSAMPLE_STEP   = 5      # compute ED every Nth window for long seqs101 102# ─── SHAPE constraint settings ────────────────────────────────────────────────103# Mirska et al. 2023 (PMC10153785) — A/California/04/2009 (H1N1) SHAPE-MaP data.104# NAI (SHAPE) reactivities used as ViennaRNA pseudo-energy soft constraints.105# m=1.8, b=−0.6 are ViennaRNA defaults for RNA (pseudo-energy = m·ln(r+1) + b).106SHAPE_M              = 1.8107SHAPE_B              = -0.6108SHAPE_MIN_IDENTITY   = 0.85   # min identity to H1N1 reference to apply constraints109SHAPE_LONG_SEQ_THRESH = 1700  # raised threshold for SHAPE-constrained full PF110# Segments with high-quality in cellulo coverage in Mirska et al. (≥99% valid nts)111SHAPE_IN_CELLULO_SEGS = frozenset({5, 7, 8})112# Default SHAPE data path — override with MIRSKA_SHAPE_PATH env var or place113# the MOESM1 xlsx alongside app.py.114_DEFAULT_SHAPE_PATHS = [115    os.environ.get("MIRSKA_SHAPE_PATH", ""),116    os.path.join(os.path.dirname(__file__), "18_2023_4764_MOESM1_ESM.xlsx"),117    "18_2023_4764_MOESM1_ESM.xlsx",118]119 120GRADE_THRESHOLDS = {"Excellent": 0.55, "Good": 0.35, "Moderate": 0.15, "Poor": 0.0}121GRADE_COLORS     = {122    "Excellent": "#00C853", "Good": "#64DD17",123    "Moderate":  "#FFD600", "Poor": "#D50000",124}125 126# Gray Zone penalty tiers — replaces flat 30% penalty.127# Data-driven: penalty is derived from SHAPE reactivity when available.128# When in cellulo SHAPE is active, NO penalty (score already reflects in-cell129# accessibility). When in virio or no SHAPE, a conservative prior is used.130GZ_PENALTY_NO_SHAPE   = 0.15   # prior-only penalty when no SHAPE data loaded131GZ_PENALTY_IN_VIRIO   = 0.12   # max penalty for in virio SHAPE; scaled by (1 - NAI)132GZ_PENALTY_IN_CELLULO = 0.00   # no penalty — in cellulo score already captures occlusion133 134# Spacer positions 15–21 (1-indexed, 5′→3′) are mismatch-intolerant.135# A single mismatch at position 18 can reduce knockdown from ~70% to background.136# Konermann et al. Cell 2018; Wessels et al. Nat Biotechnol 2024.137SEED_POSITIONS = frozenset(range(15, 22))138 139# Count-based mismatch penalties (applied to base accessibility score).140# Seed-region mismatch (any position in SEED_POSITIONS) overrides these.141MM_PENALTY = {0: 0.00, 1: 0.15, 2: 0.30}142SEED_PENALTY = 0.80   # flat override — seed mismatch always takes precedence143 144# ─── RefSeq reference database (for autodetect + conservation) ───────────────145# H1N1 A/California/07/2009 (NCBI); H3N2 A/Hong Kong/15609/2015 (GISAID 3C.2a);146# H5N1 A/gull/France/22P015977/2022 (GISAID 2.3.4.4b); H7N9 A/Shanghai/2/2013 (GISAID)147 148REFSEQ_DB: dict[str, dict[int, str]] = {149    "H1N1_Cal07_2009": {150        1: "CAAACCATTTGAATGGATGTCAATCCGACTCTACTTTTCCTAAAAATTCCAGCGCAAAATGCCATAAGCACCACATTCCCTTATACTGGAGATCCTCCATACAGCCATGGAACAGGAACAGGATACACCATGGACACAGTAAACAGAACACACCAATACTCAGAAAAGGGAAAGTGGACGACAAACACAGAGACTGGTGCACCCCAGCTCAACCCGATTGATGGACCACTACCTGAGGATAATGAACCAAGTGGGTATGCACAAACAGACTGTGTTCTAGAGGCTATGGCTTTCCTTGAAGAATCCCACCCAGGAATATTTGAGAATTCATGCCTTGAAACAATGGAAGTTGTTCAACAAACAAGGGTAGATAAACTAACTCAAGGTCGCCAGACTTATGATTGGACATTAAACAGAAATCAACCGGCAGCAACTGCATTGGCCAACACCATAGAAGTCTTTAGATCGAATGGCCTAACAGCTAATGAGTCAGGAAGGCTAATAGATTTCTTAAAGGATGTAATGGAATCAATGAACAAAGAGGAAATAGAGATAACAACCCACTTTCAAAGAAAAAGGAGAGTAAGAGACAACATGACCAAGAAGATGGTCACGCAAAGAACAATAGGGAAGAAAAAACAAAGACTGAATAAGAGAGGCTATCTAATAAGAGCACTGACATTAAATACGATGACCAAAGATGCAGAGAGAGGCAAGTTAAAAAGAAGGGCTATCGCAACACCTGGGATGCAGATTAGAGGTTTCGTATACTTTGTTGAAACTTTAGCTAGGAGCATTTGCGAAAAGCTTGAACAGTCTGGGCTCCCAGTAGGGGGCAATGAAAAGAAGGCCAAACTGGCAAATGTTGTGAGAAAGATGATGACTAATTCACAAGACACAGAGATTTCTTTCACAATCACTGGGGACAACACTAAGTGGAATGAAAATCAAAATCCTCGAATGTTCCTGGCGATGATTACATATATCACCAGAAATCAACCCGAGTGGTTCAGAAACATCCTGAGCATGGCACCCATAATGTTCTCAAACAAAATGGCAAGACTAGGGAAAGGGTACATGTTCGAGAGTAAAAGAATGAAGATTCGAACACAAATACCAGCAGAAATGCTAGCAAGCATTGACCTGAAGTACTTCAATGAATCAACAAAGAAGAAAATTGAGAAAATAAGGCCTCTTCTAATAGATGGCACAGCATCACTGAGTCCTGGGATGATGATGGGCATGTTCAACATGCTAAGTACGGTCTTGGGAGTCTCGATACTGAATCTTGGACAAAAGAAATACACCAAGACAATATACTGGTGGGATGGGCTCCAATCATCCGACGATTTTGCTCTCATAGTGAATGCACCAAACCATGAGGGAATACAAGCAGGAGTGGACAGATTCTACAGGACCTGCAAGTTAGTGGGAATCAACATGAGCAAAAAGAAGTCCTATATAAATAAGACAGGGACATTTGAATTCACAAGCTTTTTTTATCGCTATGGATTTGTGGCTAATTTTAGCATGGAGCTACCCAGCTTTGGAGTGTCTGGAGTAAATGAATCAGCTGACATGAGTATTGGAGTAACAGTGATAAAGAACAACATGATAAACAATGACCTTGGACCTGCAACGGCCCAGATGGCTCTTCAATTGTTCATCAAAGACTACAGATACACATATAGGTGCCATAGGGGAGACACACAAATTCAGACGAGAAGATCATTTGAGTTAAAGAAGCTGTGGGATCAAACCCAATCAAAGGTAGGGCTATTAGTATCAGATGGAGGACCAAACTTATACAATATACGGAATCTTCACATTCCTGAAGTCTGCTTAAAATGGGAGCTAATGGATGATGATTATCGGGGAAGACTTTGTAATCCCCTGAATCCCTTTGTCAGTCATAAAGAGATTGATTCTGTAAACAATGCTGTGGTAATGCCAGCCCATGGTCCAGCCAAAAGCATGGAATATGATGCCGTTGCAACTACACATTCCTGGATTCCCAAGAGGAATCGTTCTATTCTCAACACAAGCCAAAGGGGAATTCTTGAGGATGAACAGATGTACCAGAAGTGCTGCAATCTATTCGAGAAATTTTTCCCTAGCAGTTCATATAGGAGACCGGTTGGAATTTCTAGCATGGTGGAGGCCATGGTGTCTAGGGCCCGGATTGATGCCAGGGTCGACTTCGAGTCTGGACGGATCAAGAAAGAAGAGTTCTCTGAGATCATGAAGATCTGTTCCACCATTGAAGAACTCAGACGGCAAAAATAATGAATTTAACTTGTCCTTCATGAAAAAATGC",  # PB2 2317 nt151        2: "TCAAATATATTCAATATGGAGAGAATAAAAGAACTGAGAGATCTAATGTCGCAGTCCCGCACTCGCGAGATACTCACTAAGACCACTGTGGACCATATGGCCATAATCAAAAAGTACACATCAGGAAGGCAAGAGAAGAACCCCGCACTCAGAATGAAGTGGATGATGGCAATGAGATACCCAATTACAGCAGACAAGAGAATAATGGACATGATTCCAGAGAGGAATGAACAAGGACAAACCCTCTGGAGCAAAACAAACGATGCTGGATCAGACCGAGTGATGGTATCACCTCTGGCCGTAACATGGTGGAATAGGAATGGCCCAACAACAAGTACAGTTCATTACCCTAAGGTATATAAAACTTATTTCGAAAAGGTCGAAAGGTTGAAACATGGTACCTTCGGCCCTGTCCACTTCAGAAATCAAGTTAAAATAAGGAGGAGAGTTGATACAAACCCTGGCCATGCAGATCTCAGTGCCAAGGAGGCACAGGATGTGATTATGGAAGTTGTTTTCCCAAATGAAGTGGGGGCAAGAATACTGACATCAGAGTCACAGCTGGCAATAACAAAAGAGAAGAAAGAAGAGCTCCAGGATTGTAAAATTGCTCCCTTGATGGTGGCGTACATGCTAGAAAGAGAATTGGTCCGTAAAACAAGGTTTCTCCCAGTAGCCGGCGGAACAGGCAGTGTTTATATTGAAGTGTTGCACTTAACCCAAGGGACGTGCTGGGAGCAGATGTACACTCCAGGAGGAGAAGTGAGAAATGATGATGTTGACCAAAGTTTGATTATCGCTGCTAGAAACATAGTAAGAAGAGCAGCAGTGTCAGCAGACCCATTAGCATCTCTCTTGGAAATGTGCCACAGCACACAGATTGGAGGAGTAAGGATGGTGGACATCCTTAGACAGAATCCAACTGAGGAACAAGCCGTAGACATATGCAAGGCAGCAATAGGGTTGAGGATTAGCTCATCTTTCAGTTTTGGTGGGTTCACTTTCAAAAGGACAAGCGGATCATCAGTCAAGAAAGAAGAAGAAGTGCTAACGGGCAACCTCCAAACACTGAAAATAAGAGTACATGAAGGGTATGAAGAATTCACAATGGTTGGGAGAAGAGCAACAGCTATTCTCAGAAAGGCAACCAGGAGATTGATCCAGTTGATAGTAAGCGGGAGAGACGAGCAGTCAATTGCTGAGGCAATAATTGTGGCCATGGTATTCTCACAGGAGGATTGCATGATCAAGGCAGTTAGGGGCGATCTGAACTTTGTCAATAGGGCAAACCAGCGACTGAACCCCATGCACCAACTCTTGAGGCATTTCCAAAAAGATGCAAAAGTGCTTTTCCAGAACTGGGGAATTGAATCCATCGACAATGTGATGGGAATGATCGGAATACTGCCCGACATGACCCCAAGCACGGAGATGTCGCTGAGAGGGATAAGAGTCAGCAAAATGGGAGTAGATGAATACTCCAGCACGGAGAGAGTGGTAGTGAGTATTGACCGATTTTTAAGGGTTAGAGATCAAAGAGGGAACGTACTATTGTCTCCCGAAGAAGTCAGTGAAACGCAAGGAACTGAGAAGTTGACAATAACTTATTCGTCATCAATGATGTGGGAGATCAATGGCCCTGAGTCAGTGCTAGTCAACACTTATCAATGGATAATCAGGAACTGGGAAATTGTGAAAATTCAATGGTCACAAGATCCCACAATGCTATACAACAAAATGGAATTTGAACCATTTCAGTCTCTTGTCCCTAAGGCAACCAGAAGCCGGTACAGTGGATTCGTAAGGACACTGTTCCAGCAAATGCGGGATGTGCTTGGGACATTTGACACTGTCCAAATAATAAAACTTCTCCCCTTTGCTGCTGCCCCACCAGAACAGAGTAGGATGCAATTTTCCTCATTGACTGTGAATGTGAGAGGATCAGGGTTGAGGATACTGGTAAGAGGCAATTCTCCAGTATTCAATTACAACAAGGCAACCAAACGACTTACAGTTCTTGGAAAGGATGCAGGTGCATTGACTGAAGATCCAGATGAAGGCACATCTGGGGTGGAGTCTGCTGTCCTGAGAGGATTTCTCATTTTGGGCAAAGAAGACAAGAGATATGGCCCAGCATTAAGCATCAATGAACTGAGCAATCTTGCAAAAGGAGAGAAGGCTAATGTGCTAATTGGGCAAGGGGACGTAGTGTTGGTAATGAAACGAAAACGGGACTCTAGCATACTTACTGACAGCCAGACAGCGACCAAAAGAATTCGGATGGCCATCAATTAGTGTCGAATTGTTTAAAAACGA",  # PB1 2316 nt152        3: "CAAAATGGAAGACTTTGTGCGACAATGCTTCAATCCAATGATCGTCGAGCTTGCGGAAAAGGCAATGAAAGAATATGGGGAAGATCCGAAAATCGAAACTAACAAGTTTGCTGCAATATGCACACATTTGGAAGTTTGTTTCATGTATTCGGATTTCCATTTCATCGACGAACGGGGTGAATCAATAATTGTAGAATCTGGTGACCCGAATGCACTATTGAAGCACCGATTTGAGATAATTGAAGGAAGAGACCGAATCATGGCCTGGACAGTGGTGAACAGTATATGTAACACAACAGGGGTAGAGAAGCCTAAATTTCTTCCTGATTTGTATGATTACAAAGAGAACCGGTTCATTGAAATTGGAGTAACACGGAGGGAAGTCCACATATATTACCTAGAGAAAGCCAACAAAATAAAATCTGAGAAGACACACATTCACATCTTTTCATTCACTGGAGAGGAGATGGCCACCAAAGCGGACTACACCCTTGACGAAGAGAGCAGGGCAAGAATCAAAACTAGGCTTTTCACTATAAGACAAGAAATGGCCAGTAGGAGTCTATGGGATTCCTTTCGTCAGTCCGAAAGAGGCGAAGAGACAATTGAAGAAAAATTTGAGATTACAGGAACTATGCGCAAGCTTGCCGACCAAAGTCTCCCACCGAACTTCCCCAGCCTTGAAAACTTTAGAGCCTATGTAGATGGATTCGAGCCGAACGGCTGCATTGAGGGCAAGCTTTCCCAAATGTCAAAAGAAGTGAACGCCAAAATTGAACCATTCTTGAGGACGACACCACGCCCCCTCAGATTGCCTGATGGGCCTCTTTGCCATCAGCGGTCAAAGTTCCTGCTGATGGATGCTCTGAAATTAAGTATTGAAGACCCGAGTCACGAGGGGGAGGGAATACCACTATATGATGCAATCAAATGCATGAAGACATTCTTTGGCTGGAAAGAGCCTAACATAGTCAAACCACATGAGAAAGGCATAAATCCCAATTACCTCATGGCTTGGAAGCAGGTGCTAGCAGAGCTACAGGACATTGAAAATGAAGAGAAGATCCCAAGGACAAAGAACATGAAGAGAACAAGCCAATTGAAGTGGGCACTCGGTGAAAATATGGCACCAGAAAAAGTAGACTTTGATGACTGCAAAGATGTTGGAGACCTTAAACAGTATGACAGTGATGAGCCAGAGCCCAGATCTCTAGCAAGCTGGGTCCAAAATGAATTCAATAAGGCATGTGAATTGACTGATTCAAGCTGGATAGAACTTGATGAAATAGGAGAAGATGTTGCCCCGATTGAACATATCGCAAGCATGAGGAGGAACTATTTTACAGCAGAAGTGTCCCACTGCAGGGCTACTGAATACATAATGAAGGGAGTGTACATAAATACGGCCTTGCTCAATGCATCCTGTGCAGCCATGGATGACTTTCAGCTGATCCCAATGATAAGCAAATGTAGGACCAAAGAAGGAAGACGGAAAACAAACCTGTATGGGTTCATTATAAAAGGAAGGTCTCATTTGAGAAATGATACTGATGTGGTGAACTTTGTAAGTATGGAGTTCTCACTCACTGACCCGAGACTGGAGCCACACAAATGGGAAAAATACTGTGTTCTTGAAATAGGAGACATGCTCTTGAGGACTGCGATAGGCCAAGTGTCGAGGCCCATGTTCCTATATGTGAGAACCAATGGAACCTCCAAGATCAAGATGAAATGGGGCATGGAAATGAGGCGCTGCCTTCTTCAGTCTCTTCAGCAGATTGAGAGCATGATTGAGGCCGAGTCTTCTGTCAAAGAGAAAGACATGACCAAGGAATTCTTTGAAAACAAATCGGAAACATGGCCAATCGGAGAGTCACCCAGGGGAGTGGAGGAAGGCTCTATTGGGAAAGTGTGCAGGACCTTACTGGCAAAATCTGTATTCAACAGTCTATATGCGTCTCCACAACTTGAGGGGTTTTCGGCTGAATCTAGAAAATTGCTTCTCATTGTTCAGGCACTTAGGGACAACCTGGAACCTGGAACCTTCGATCTTGGGGGGCTATATGAAGCAATCGAGGAGTGCCTGATTAATGATCCCTGGGTTTTGCTTAATGCATCTTGGTTCAACTCCTTCCTCACACATGCACTGAAGTAGTTGTGGCAATGCTACTATTTGCTATCCATACTGTCCA",  # PA 2192 nt153        4: "GGAAAACAAAAGCAACAAAAATGAAGGCAATACTAGTAGTTCTGCTATATACATTTGCAACCGCAAATGCAGACACATTATGTATAGGTTATCATGCGAACAATTCAACAGACACTGTAGACACAGTACTAGAAAAGAATGTAACAGTAACACACTCTGTTAACCTTCTAGAAGACAAGCATAACGGGAAACTATGCAAACTAAGAGGGGTAGCCCCATTGCATTTGGGTAAATGTAACATTGCTGGCTGGATCCTGGGAAATCCAGAGTGTGAATCACTCTCCACAGCAAGCTCATGGTCCTACATTGTGGAAACACCTAGTTCAGACAATGGAACGTGTTACCCAGGAGATTTCATCGATTATGAGGAGCTAAGAGAGCAATTGAGCTCAGTGTCATCATTTGAAAGGTTTGAGATATTCCCCAAGACAAGTTCATGGCCCAATCATGACTCGAACAAAGGTGTAACGGCAGCATGTCCTCATGCTGGAGCAAAAAGCTTCTACAAAAATTTAATATGGCTAGTTAAAAAAGGAAATTCATACCCAAAGCTCAGCAAATCCTACATTAATGATAAAGGGAAAGAAGTCCTCGTGCTATGGGGCATTCACCATCCATCTACTAGTGCTGACCAACAAAGTCTCTATCAGAATGCAGATGCATATGTTTTTGTGGGGTCATCAAGATACAGCAAGAAGTTCAAGCCGGAAATAGCAATAAGACCCAAAGTGAGGGATCGAGAAGGGAGAATGAACTATTACTGGACACTAGTAGAGCCGGGAGACAAAATAACATTCGAAGCAACTGGAAATCTAGTGGTACCGAGATATGCATTCGCAATGGAAAGAAATGCTGGATCTGGTATTATCATTTCAGATACACCAGTCCACGATTGCAATACAACTTGTCAAACACCCAAGGGTGCTATAAACACCAGCCTCCCATTTCAGAATATACATCCGATCACAATTGGAAAATGTCCAAAATATGTAAAAAGCACAAAATTGAGACTGGCCACAGGATTGAGGAATATCCCGTCTATTCAATCTAGAGGCCTATTTGGGGCCATTGCCGGTTTCATTGAAGGGGGGTGGACAGGGATGGTAGATGGATGGTACGGTTATCACCATCAAAATGAGCAGGGGTCAGGATATGCAGCCGACCTGAAGAGCACACAGAATGCCATTGACGAGATTACTAACAAAGTAAATTCTGTTATTGAAAAGATGAATACACAGTTCACAGCAGTAGGTAAAGAGTTCAACCACCTGGAAAAAAGAATAGAGAATTTAAATAAAAAAGTTGATGATGGTTTCCTGGACATTTGGACTTACAATGCCGAACTGTTGGTTCTATTGGAAAATGAAAGAACTTTGGACTACCACGATTCAAATGTGAAGAACTTATATGAAAAGGTAAGAAGCCAGCTAAAAAACAATGCCAAGGAAATTGGAAACGGCTGCTTTGAATTTTACCACAAATGCGATAACACGTGCATGGAAAGTGTCAAAAATGGGACTTATGACTACCCAAAATACTCAGAGGAAGCAAAATTAAACAGAGAAGAAATAGATGGGGTAAAGCTGGAATCAACAAGGATTTACCAGATTTTGGCGATCTATTCAACTGTCGCCAGTTCATTGGTACTGGTAGTCTCCCTGGGGGCAATCAGTTTCTGGATGTGCTCTAATGGGTCTCTACAGTGTAGAATATGTATTTAACATTAGGATTTCAGAAGCATGAGAAAAACAC",  # HA 1752 nt154        5: "GTAGATAATCACTCAATGAGTGACATCGAAGCCATGGCGTCTCAAGGCACCAAACGATCATATGAACAAATGGAGACTGGTGGGGAGCGCCAGGATGCCACAGAAATCAGAGCATCTGTCGGAAGAATGATTGGTGGAATCGGGAGATTCTACATCCAAATGTGCACTGAACTCAAACTCAGTGATTATGATGGACGACTAATCCAGAATAGCATAACAATAGAGAGGATGGTGCTTTCTGCTTTTGATGAGAGAAGAAATAAATACCTAGAAGAGCATCCCAGTGCTGGGAAGGACCCTAAGAAAACAGGAGGACCCATATATAGAAGAGTAGGCGGAAAGTGGATGAGAGAACTCATCCTTTATGACAAAGAAGAAATAAGGAGAGTTTGGCGCCAAGCAAACAATGGCGAAGATGCAACAGCAGGTCTTACTCATATCATGATTTGGCATTCCAACCTGAATGATGCCACATATCAGAGAACAAGAGCGCTTGTTCGCACCGGAATGGATCCCAGAATGTGCTCTCTAATGCAAGGTTCAACACTTCCCAGAAGGTCTGGTGCCGCAGGTGCTGCGGTGAAAGGAGTTGGAACAATAGCAATGGAGTTAATCAGAATGATCAAACGTGGAATCAATGACCGAAATTTCTGGAGGGGTGAAAATGGACGAAGGACAAGGGTTGCTTATGAAAGAATGTGCAATATCCTCAAAGGAAAATTTCAAACAGCTGCCCAGAGGGCAATGATGGATCAAGTAAGAGAAAGTCGAAACCCAGGAAACGCTGAGATTGAAGACCTCATTTTCCTGGCACGGTCAGCACTCATTCTGAGGGGATCAGTTGCACATAAATCCTGCCTGCCTGCTTGTGTGTATGGGCTTGCAGTAGCAAGTGGGCATGACTTTGAAAGGGAAGGGTACTCACTGGTCGGGATAGACCCATTCAAATTACTCCAAAACAGCCAAGTGGTCAGCCTGATGAGACCAAATGAAAACCCAGCTCACAAGAGTCAATTGGTGTGGATGGCATGCCACTCTGCTGCATTTGAAGATTTAAGAGTATCAAGTTTCATAAGAGGAAAGAAAGTGATTCCAAGAGGAAAGCTTTCCACAAGAGGGGTCCAGATTGCTTCAAATGAGAATGTGGAAACCATGGACTCCAATACCCTGGAACTGAGAAGCAGATACTGGGCCATAAGGACCAGGAGTGGAGGAAATACCAATCAACAAAAGGCATCCGCAGGCCAGATCAGTGTGCAGCCTACATTCTCAGTGCAGCGGAATCTCCCTTTTGAAAGAGCAACCGTTATGGCAGCATTCAGCGGGAACAATGAAGGACGGACATCCGACATGCGAACAGAAGTTATAAGAATGATGGAAAGTGCAAAGCCAGAAGATTTGTCCTTCCAGGGGCGGGGAGTCTTCGAGCTCTCGGACGAAAAGGCAACGAACCCGATCGTGCCTTCCTTTGACATGAGTAATGAAGGGTCTTATTTCTTCGGAGACAATGCAGAGGAGTATGACAGTTGAGGAAAAATACC",  # NP 1541 nt155        6: "AGTTTAAAATGAATCCAAACCAAAAGATAATAACCATTGGTTCGGTCTGTATGACAATTGGAATGGCTAACTTAATATTACAAATTGGAAACATAATCTCAATATGGATTAGCCACTCAATTCAACTTGGGAATCAAAATCAGATTGAAACATGCAATCAAAGCGTCATTACTTATGAAAACAACACTTGGGTAAATCAGACATATGTTAACATCAGCAACACCAACTTTGCTGCTGGACAGTCAGTGGTTTCCGTGAAATTAGCGGGCAATTCCTCTCTCTGCCCTGTTAGTGGATGGGCTATATACAGTAAAGACAACAGTGTAAGAATCGGTTCCAAGGGGGATGTGTTTGTCATAAGGGAACCATTCATATCATGCTCCCCCTTGGAATGCAGAACCTTCTTCTTGACTCAAGGGGCCTTGCTAAATGACAAACATTCCAATGGAACCATTAAAGACAGGAGCCCATATCGAACCCTAATGAGCTGTCCTATTGGTGAAGTTCCCTCTCCATACAACTCAAGATTTGAGTCAGTCGCTTGGTCAGCAAGTGCTTGTCATGATGGCATCAATTGGCTAACAATTGGAATTTCTGGCCCAGACAATGGGGCAGTGGCTGTGTTAAAGTACAACGGCATAATAACAGACACTATCAAGAGTTGGAGAAACAATATATTGAGAACACAAGAGTCTGAATGTGCATGTGTAAATGGTTCTTGCTTTACTGTAATGACCGATGGACCAAGTAATGGACAGGCCTCATACAAGATCTTCAGAATAGAAAAGGGAAAGATAGTCAAATCAGTCGAAATGAATGCCCCTAATTATCACTATGAGGAATGCTCCTGTTATCCTGATTCTAGTGAAATCACATGTGTGTGCAGGGATAACTGGCATGGCTCGAATCGACCGTGGGTGTCTTTCAACCAGAATCTGGAATATCAGATAGGATACATATGCAGTGGGATTTTCGGAGACAATCCACGCCCTAATGATAAGACAGGCAGTTGTGGTCCAGTATCGTCTAATGGAGCAAATGGAGTAAAAGGGTTTTCATTCAAATACGGCAATGGTGTTTGGATAGGGAGAACTAAAAGCATTAGTTCAAGAAACGGTTTTGAGATGATTTGGGATCCGAACGGATGGACTGGGACAGACAATAACTTCTCAATAAAGCAAGATATCGTAGGAATAAATGAGTGGTCAGGATATAGCGGGAGTTTTGTTCAGCATCCAGAACTAACAGGGCTGGATTGTATAAGACCTTGCTTCTGGGTTGAACTAATCAGAGGGCGACCCAAAGAGAACACAATCTGGACTAGCGGGAGCAGCATATCCTTTTGTGGTGTAAACAGTGACACTGTGGGTTGGTCTTGGCCAGACGGTGCTGAGTTGCCATTTACCATTGACAAGTAATTTGTTCAAAAAAC",  # NA 1432 nt156        7: "TAGATATTAAAGATGAGTCTTCTAACCGAGGTCGAAACGTACGTTCTTTCTATCATCCCGTCAGGCCCCCTCAAAGCCGAGATCGCGCAGAGACTGGAAAGTGTCTTTGCAGGAAAGAACACAGATCTTGAGGCTCTCATGGAATGGCTAAAGACAAGACCAATCTTGTCACCTCTGACTAAGGGAATTTTAGGATTTGTGTTCACGCTCACCGTGCCCAGTGAGCGAGGACTGCAGCGTAGACGCTTTGTCCAAAATGCCCTAAATGGGAATGGGGACCCGAACAACATGGATAGAGCAGTTAAACTATACAAGAAGCTCAAAAGAGAAATAACGTTCCATGGGGCCAAGGAGGTGTCACTAAGCTATTCAACTGGTGCACTTGCCAGTTGCATGGGCCTCATATACAACAGGATGGGAACAGTGACCACAGAAGCTGCTTTTGGTCTAGTGTGTGCCACTTGTGAACAGATTGCTGATTCACAGCATCGGTCTCACAGACAGATGGCTACTACCACCAATCCACTAATCAGGCATGAAAACAGAATGGTGCTGGCTAGCACTACGGCAAAGGCTATGGAACAGATGGCTGGATCGAGTGAACAGGCAGCGGAGGCCATGGAGGTTGCTAATCAGACTAGGCAGATGGTACATGCAATGAGAACTATTGGGACTCATCCTAGCTCCAGTGCTGGTCTGAAAGATGACCTTCTTGAAAATTTGCAGGCCTACCAGAAGCGAATGGGAGTGCAGATGCAGCGATTCAAGTGATCCTCTCGTCATTGCAGCAAATATCATTGGGATCTTGCACCTGATATTGTGGATTACTGATCGTCTTTTTTTCAAATGTATTTATCGTCGCTTTAAATACGGTTTGAAAAGAGGGCCTTCTACGGAAGGAGTGCCTGAGTCCATGAGGGAAGAATATCAACAGGAACAGCAGAGTGCTGTGGATGTTGACGATGGTCATTTTGTCAACATAGAGCTAGAGTAAAAAACTAC",  # M 1002 nt157        8: "GTGACAAAAACATAATGGACTCCAACACCATGTCAAGCTTTCAGGTAGACTGTTTCCTTTGGCATATCCGCAAGCGATTTGCAGACAATGGATTGGGTGATGCCCCATTCCTTGATCGGCTCCGCCGAGATCAAAAGTCCTTAAAAGGAAGAGGCAACACCCTTGGCCTCGATATCGAAACAGCCACTCTTGTTGGGAAACAAATCGTGGAATGGATCTTGAAAGAGGAATCCAGCGAGACACTTAGAATGACAATTGCATCTGTACCTACTTCGCGCTACCTTTCTGACATGACCCTCGAGGAAATGTCACGAGACTGGTTCATGCTCATGCCTAGGCAAAAGATAATAGGCCCTCTTTGCGTGCGATTGGACCAGGCGATCATGGAAAAGAACATAGTACTGAAAGCGAACTTCAGTGTAATCTTTAACCGATTAGAGACCTTGATACTACTAAGGGCTTTCACTGAGGAGGGAGCAATAGTTGGAGAAATTTCACCATTACCTTCTCTTCCAGGACATACTTATGAGGATGTCAAAAATGCAGTTGGGGTCCTCATCGGAGGACTTGAATGGAATGGTAACACGGTTCGAGTCTCTGAAAATATACAGAGATTCGCTTGGAGAAACTGTGATGAGAATGGGAGACCTTCACTACCTCCAGAGCAGAAATGAAAAGTGGCGAGAGCAATTGGGACAGAAATTTGAGGAAATAAGGTGGTTAATTGAAGAAATGCGGCACAGATTGAAAGCGACAGAGAATAGTTTCGAACAAATAACATTTATGCAAGCCTTACAACTACTGCTTGAAGTAGAACAAGAGATAAGAGCTTTCTCGTTTCAGCTTATTTAATGATAAAAAACCC",  # NS 865 nt158    },159    "H3N2_HK15609_2015": {160        1: "ATGGAAAGAATAAAAGAACTACGGAATCTAATGTCGCAGTCTCGCACTCGCGAGATACTGACAAAAACCACAGTGGACCATATGGCCATAATTAAGAAGTACACATCGGGGAGACAGGAAAAGAACCCGTCACTTAGGATGAAATGGATGATGGCAATGAAATATCCAATCACTGCTGACAAAAGGATAACAGAAATGGTTCCAGAGAGAAATGAACAAGGACAAACTCTATGGAGTAAAATGAGTGATGCTGGATCAGATAGAGTGATGGTATCACCTTTGGCTGTAACATGGTGGAATAGGAATGGACCCGTGACAAGTACGGTCCATTACCCAAAAGTGTACAAAACTTATTTCGACAAAGTCGAAAGGTTAAAACATGGAACCTTTGGCCCTGTCCATTTTAGAAATCAAGTCAAGATACGCAGAAGAGTAGACATAAACCCTGGTCATGCAGACCTCAGTGCCAAAGAGGCACAAGATGTAATTATGGAAGTTGTTTTTCCCAATGAAGTGGGAGCCAGAATACTAACATCAGAATCACAACTAACAATAACTAAAGAGAAAAAAGAAGAACTCCGAGATTGCAAAATTTCTCCCTTGATGGTCGCATACATGTTAGAGAGAGAACTTGTGCGGAAAACAAGATTTCTCCCAGTTGCTGGCGGAACAAGCAGTATATACATTGAAGTTTTACATTTGACTCAAGGAACGTGTTGGGAACAAATGTACACTCCAGGTGGAGGAGTGAGGAATGACGATGTTGACCAAAGCCTAATTATTGCGGCCAGGAACATAGTAAGAAGAGCCGCAGTGTCAGCAGATCCACTAGCATCTTTATTGGAGATGTGCCACAGCACGCAAATTGGCGGAACAAGGATGGTGGACATTCTTAAACAGAACCCGACTGAAGAACAAGCTGTGGATATATGCAAGGCTGCAATGGGATTGAGAATCAGCTCATCCTTCAGCTTTGGTGGCTTTACATTTAAAAGAACAAGCGGGTCGTCAGTCAAAAAAGAAGAAGAGGTTCTTACAGGCAATCTCCAAACATTGAGAATAAGAGTACATGAGGGGTATGAGGAGTTCACAATGGTGGGGAAAAGAGCAACAGCTATACTAAGAAAAGCAACCAGAAGATTGGTTCAACTCATAGTGAGTGGAAGAGACGAACAGTCAATAGCCGAAGCAATAATCGTGGCCATGGTGTTTTCACAAGAAGATTGCATGATAAAAGCAGTTAGAGGTGACCTGAATTTTGTCAACAGAGCAAATCAGCGGTTGAACCCCATGCATCAGCTTTTAAGGCATTTTCAGAAAGATGCGAAAGTGCTCTTTCAAAATTGGGGAGTTGAACACATCGACAGTGTGATGGGAATGGTTGGAGTATTACCAGATATGACTCCAAGCACAGAGATGTCAATGAGAGGAATAAGAGTCAGCAAAATGGGTGTGGATGAATACTCCAGTACAGAGAGGGTGGTGGTTAGCATTGATCGGTTTTTGAGAGTTCGAGACCAACGTGGGAATGTATTATTATCTCCTGAGGAGGTCAGTGAAACACAGGGAACTGAAAGACTGACAATAACTTATTCATCGTCGATGATGTGGGAGATTAACGGTCCTGAGTCGGTTTTGGTCAATACCTATCAATGGATCATCAGGAATTGGGAAGCTGTCAAAATTCAATGGTCTCAGAATCCTGCAATGTTGTACAACAAAATGGAATTTGAACCATTTCAATCTTTAGTCCCCAAGGCCACTAGAAGCCAATACAGTGGGTTTGTCAGAACTCTATTCCAACAAATGAGAGACGTACTTGGGACATTTGACACTGCCCAGATAATAAAGCTTCTCCCTTTTGCAGCTGCTCCACCGAAGCAAAGCAGAATGCAGTTCTCTTCACTGACTGTGAATGTGAGGGGATCAGGGATGAGAATACTTGTAAGGGGCAATTCTCCTGTATTCAACTACAACAAGACCACTAAAAGGCTAACAATTCTTGGAAAAGATGCCGGCACTTTAATTGAAGACCCAGATGAAAGCACATCCGGAGTGGAGTCCGCCGTCTTGAGAGGGTTCCTCATTATAGGTAAAGAAGACAGAAGATACGGACCAGCATTAAGCATCAATGAACTGAGTAACCTTGCAAAAGGGGAAAAGGCTAATGTGCTAATTGGGCAAGGAGACGTGGTGTTGGTAATGAAACGAAAACGGGACTCTAGTATACTTACTGACAGCCAGACAGCGACCAAAAGAATTCGGATGGCCATCAATTAA",  # PB2 2280 nt161        2: "ATGGATGTCAATCCGACTCTACTGTTCTTAAAAGTTCCAGCGCAAAATGCCATAAGCACAACATTCCCTTATACTGGAGATCCTCCATACAGCCATGGAACAGGGACAGGGTACACTATGGACACAGTCAACAGAACACACCAATACTCAGAGAGGGGGAAGTGGACAACAAATACAGAAACTGGGGCGCCCCAGCTCAACCCAATTGATGGACCACTACCTGAGGATAATGAACCAAGTGGATATGCACAAACAGACTGTGTCCTGGAGGCTATGGCCTTCCTTGAAGAATCCCACCCAGGTATCTTTGAGAACTCATGCCTTGAAACAATGGAAGCCGTTCAACAGACAAGGGTGGACAAACTAACCCAAGGTCGCCAGACTTATGATTGGACATTAAACAGGAACCAACCGGCAGCAACTGCATTAGCCAACACCATAGAAGTCTTTAGATCGAACGGATTAACAGCTAATGAATCAGGAAGGCTAATAGATTTCCTCAAGGATGTGATGGAATCAATGGATAAGGAGGAAATGGAGATAACAACACACTTTCAAAGAAAAAGGAGAGTAAGGGACAACATGACCAAGAAAATGGTCACACAAAGAACAATAGGGAAGAAAAAACAAAGGGTGAATAAGAGAGGCTACCTAATAAGAGCTTTGACATTGAACACGATGACCAAGGATGCAGAGAGAGGCAAATTAAAAAGAAGGGCTATTGCAACACCCGGGATGCAAATTAGAGGGTTCGTGTACTTCGTTGAAACTTTAGCTAGAAGCATTTGCGAAAAGCTTGAACAATCTGGACTTCCGGTTGGGGGTAATGAAAAGAAGGCCAAACTGGCAAATGTTGTGAGAAAAATGATGACTAATTCACAAGACACAGAGCTTTCTTTCACAATCACTGGGGACAACACTAAGTGGAATGAAAATCAAAACCCCCGAATGTTTTTGGCGATGATTACATACATCACAAAGAATCAACCTGAATGGTTCAGAAACATCCTGAGCATCGCACCAATAATGTTCTCAAACAAAATGGCAAGACTGGGAAAAGGATACATGTTCGAGAGTAAGAGAATGAAGCTCCGGACACAAATACCTGCAGAAATGCTAGCAAGCATTGACCTGAAGTATTTCAATGAATCAACAAGGAAGAAAATTGAGAAAATAAGGCCTCTTCTAATAGATGGCACAGCATCATTGAGCCCTGGAATGATGATGGGCATGTTCAACATGCTAAGTACAGTTTTAGGAGTCTCGATACTGAATCTTGGACAAAAGAAATACACCAAGACAACATACTGGTGGGATGGGCTCCAATCCTCAGACGATTTTGCCCTCATAGTGAATGCACCAAATCATGAGGGAATACAAGCAGGAGTGGATAGATTCTATAGGACCTGCAAGTTAGTGGGAATCAACATGAGCAAAAAGAAGTCCTATATAAATAAAACAGGGACATTTGAATTCACTAGCTTTTTTTATCGATATGGATTTGTGGCTAATTTTAGCATGGAGCTGCCAAGTTTTGGAGTGTCTGGAATAAACGAGTCAGCTGACATGAGCATTGGAGTAACAGTGATAAAGAACAACATGATAAATAATGACCTTGGACCAGCAACAGCCCAAATGGCTCTCCAATTGTTCATCAAAGATTACAGATACACGTATCGGTGCCATAGAGGAGACACACAAATCCAAACGAGAAGATCATTCGAGATAAAGAAGCTGTGGGATCAAACCCAATCAAGGACAGGACTATTGGTATCAGATGGGGGACCAAACTTATACAATATCCGGAATCTTCACATCCCTGAAGTCTGCTTAAAGTGGGAGCTGATGGATGAGAATTATCGGGGAAGACTTTGTAATCCCCTGAATCCCTTTGTCAGCCATAAAGAAATTGAATCTGTAAACAATGCTGTAGTAATGCCAGCCCATGGTCCGGCCAAAAGTATGGAATATGATGCCGTTGCAACTACACATTCCTGGATTCCCAAAAGGAACCGCTCTATTCTAAACACAAGCCAAAGGGGAATTCTTGAGGATGAACAGATGTACCAGAAGTGCTGCAACTTGTTCGAGAAATTTTTCCCTAGTAGTTCATATAGGAGACCGATTGGAATTTCTAGCATGGTGGAGGCCATGGTGTCTAGGGCCCGGATTGATGCCAGAATTGACTTCGAGTCTGGAAGGATTAAGAAGGAAGAGTTCTCTGAGATCATGAAGATCTGTTCCACCATTGAAGAACTCAGACGGCAAAAATAA",  # PB1 2274 nt162        3: "ATGGAAGATTTTGTGCGACAATGCTTCAACCCGATGATTGTCGAACTTGCAGAAAAAGCAATGAAAGAGTATGGGGAGGATCTGAAAATTGAAACCAACAAATTTGCAGCAATATGCACTCACTTGGAGGTGTGTTTCATGTATTCAGATTTCCATTTCATCAATGAACAAGGCGAATCAATAGTAGTAGAACTTGACGATCCAAATGCACTGTTAAAGCACAGATTTGAAATAATCGAGGGGAGAGACAGAACAATGGCCTGGACAGTAGTAAACAGTATCTGCAACACTACTGGAGCTGGAAAACCGAAGTTTCTACCGGATTTGTATGATTACAAAGAGAACAGATTCATCGAAATTGGAGTGACAAGGAGAGAAGTCCACATATATTACCTTGAAAAGGCCAATAAGATTAAATCTGAGAACACACACATTCACATTTTTTCATTCACTGGGGAGGAAATGGCCACAAAGGCAGACTACACTCTCGACGAGGAAAGCAGGGCTAGGATCAAAACCAGGCTGTTTACCATAAGACAAGAAATGGCCAACAGAGGCCTCTGGGATTCCTTTCGTCAGTCCGAAAGAGGCGAAGAAACAATTGAAGAAAAATTTGAAATCACAGGAACTATGCGCAGGCTTGCCGACCAAAGTCTCCCACCGAACTTCTCCTGCCTTGAGAATTTTAGAGCCTATGTGGATGGATTCGAACCGAACGGCTGCATTGAGGGCAAGCTTTCTCAAATGTCCAAAGAAGTGAATGCCCAAATTGAACCTTTTCTGAAGACAACACCAAGACCAATCAAACTTCCTAGTGGACCTCCTTGTTATCAGCGATCCAAATTCCTCCTGATGGATGCTTTGAAATTGAGCATTGAAGACCCAAGTCACGAAGGAGAAGGGATCCCATTATATGATGCGATCAAGTGCATAAAAACATTCTTTGGATGGAAAGAACCTTATATAGTCAAACCACACGAAAAGGGAATAAATTCAAATTACCTGCTGTCATGGAAGCAAGTACTGTCAGAATTGCAGGACATTGAAAATGAGGAGAAGATTCCAAGAACTAAAAACATGAAGAAAACGAGTCAACTGAAGTGGGCTCTTGGTGAAAACATGGCACCAGAGAAGGTAGACTTTGAAAACTGCAGAGACATAAGCGATTTGAAGCAATATGATAGTGAAGAACCTGAATTAAGGTCACTTTCAAGCTGGATACAGAGTGAGTTCAACAAGGCCTGTGAGCTAACTGATTCAGTCTGGATAGAGCTCGATGAAATTGGAGAGGACGTAGCCCCAATTGAACACATTGCAAGCATGAGAAGGAATTATTTCACAGCAGAGGTGTCCCATTGTAGAGCCACTGAATACATAATGAAAGGGGTATACATTAACACTGCCCTGCTCAATGCATCCTGTGCAGCAATGGACGATTTTCAACTAATTCCCATGATAAGCAAGTGCAGAACTAAAGAGGGAAGGCGAAAAACCAATTTATATGGATTCATCATAAAGGGAAGATCTCATCTGAGGAATGACACAGACGTGGTAAACTTTGTGAGCATGGAGTTTTCTCTCACAGATCCGAGACTTGAACCACATAAATGGGAGAAATATTGTGTCCTTGAGATAGGAGATATGTTACTAAGGAGTGCCATAGGCCAAATTTCAAGGCCGATGTTCTTGTATGTGAGGACAAACGGAACATCAAAAGTCAAAATGAAATGGGGAATGGAGATGAGACGTTGCCTCCTTCAGTCACTCCAGCAGATCGAGAGCATGATTGAAGCCGAGTCCTCAGTTAAAGAGAAAGACATGACCAAAGAGTTTTTTGAGAATAAATCAGAAGCATGGCCCATTGGGGAGTCCCCCAAAGGAGTGGAAGAAGGTTCCATTGGGAAAGTCTGTAGGACTCTATTGGCTAAGTCAGTATTCAATAGCCTGTATGCATCACCACAATTGGAAGGATTTTCAGCAGAGTCAAGAAAACTGCTCCTTATTGTTCAGGCTCTTAGGGACAAACTCGAACCTGGGACCTTTGATCTTGGGGGGCTATATGAAGCAATTGAGGAGTGCCTGATTAATGATCCCTGGGTTTTGCTCAATGCGTCTTGGTTCAACTCCTTCCTGACACATGCATTAAAATAG",  # PA 2151 nt163        4: "ATGAAGACTATCATTGCTTTGAGCTACATTCTATGTCTGGTTTTCGCTCAAAAAATTCCTGGAAATGACAATAGCACGGCAACGCTGTGCCTTGGGCACCATGCAGTACCAAACGGAACGATAGTGAAAACAATCACAAATGACCGAATTGAAGTTACTAATGCTACTGAGTTGGTTCAGAATTCCTCAATAGGTGAAATATGCGACAGTCCTCATCAGATCCTTGATGGAGAGAACTGCACACTAATAGATGCTCTATTGGGAGACCCTCAGTGTGATGGCTTTCAAAATAAGAAATGGGACCTTTTTGTTGAACGAAGCAAAGCCTACAGCAACTGTTACCCTTATGATGTGCCGGATTATGCCTCCCTTAGGTCACTAGTTGCCTCATCCGGCACACTGGAGTTTAACAATGAAAGCTTCAATTGGACTGGAGTCACTCAAAACGGAACAAGTTCTGCTTGCATAAGGAGATCTAGTAGTAGTTTCTTTAGTAGATTAAATTGGTTGACCCACTTAAACTACACATATCCAGCATTGAACGTGACTATGCCAAACAAGGAACAATTTGACAAATTGTACATTTGGGGGGTTCACCACCCGGGTACGGACAAGGACCAAATCTTCCTGTATGCTCAATCATCAGGAAGAATCACAGTATCTACCAAAAGAAGCCAACAAGCTGTAATCCCAAATATCGGATCTAGACCCAGAATAAGGGATATCCCTAGCAGAATAAGCATCTATTGGACAATAGTAAAACCGGGAGACATACTTTTGATTAACAGCACAGGGAATCTAATTGCTCCTAGGGGTTACTTCAAAATACGAAGTGGGAAAAGCTCAATAATGAGATCAGATGCACCCATTGGCAAATGCAAGTCTGAATGCATCACTCCAAATGGAAGCATTCCCAATGACAAACCATTCCAAAATGTAAACAGGATCACATACGGGGCCTGTCCCAGATATGTTAAGCATAGCACTCTGAAATTGGCAACAGGAATGCGAAATGTACCAGAGAAACAAACTAGAGGCATATTTGGCGCAATAGCGGGTTTCATAGAAAATGGTTGGGAGGGAATGGTGGATGGTTGGTACGGTTTCAGGCATCAAAATTCTGAGGGAAGAGGACAAGCAGCAGATCTCAAAAGCACTCAAGCAGCAATCGATCAAATCAATGGGAAGCTGAATCGGTTGATCGGGAAAACCAACGAGAAATTCCATCAGATTGAAAAAGAATTCTCAGAAGTAGAAGGAAGAGTTCAAGACCTTGAGAAATATGTTGAGGACACTAAAATAGATCTCTGGTCATACAACGCGGAGCTTCTTGTTGCCCTGGAGAACCAACATACAATTGATCTAACTGACTCAGAAATGAACAAACTGTTTGAAAAAACAAAGAAGCAACTGAGGGAAAATGCTGAGGATATGGGAAATGGTTGTTTCAAAATATACCACAAATGTGACAATGCCTGCATAGGATCAATAAGAAATGAAACTTATGACCACAATGTGTACAGGGATGAAGCATTAAACAACCGGTTCCAGATCAAGGGAGTTGAGCTGAAGTCAGGGTACAAAGATTGGATCCTATGGATTTCCTTTGCCATATCATGTTTTTTGCTTTGTGTTGCTTTGTTGGGGTTCATCATGTGGGCCTGCCAAAAGGGCAACATTAGATGCAACATTTGCATTTGA",  # HA 1701 nt164        5: "ATGGCGTCCCAAGGCACCAAACGGTCTTATGAACAGATGGAAACTGATGGAGATCGCCAGAATGCAACTGAGATTAGGGCATCCGTCGGGAAGATGATTGATGGAATTGGGAGATTCTACATCCAAATGTGCACTGAACTTAAACTCAGTGATCATGAAGGACGGTTGATCCAAAACAGCTTGACAATAGAGAAAATGGTACTCTCTGCTTTTGATGAAAGAAGGAATAAATACCTGGAAGAACACCCCAGCGCGGGGAAAGATCCCAAGAAAACTGGGGGGCCCATATACAGGAGAGTCGATGGGAAATGGATGAGGGAACTCGTCCTTTATGACAAAGAAGAAATAAGGCGAATCTGGCGCCAAGCCAACAATGGTGAGGATGCTACATCTGGTCTAACTCACATAATGATTTGGCATTCCAATTTGAATGATGCAACATACCAGAGGACAAGAGCTCTTGTTCGGACTGGAATGGATCCCAGAATGTGCTCTCTGATGCAGGGCTCGACTCTCCCTAGAAGGTCCGGAGCTGCAGGTGCTGCAGTCAAAGGAATCGGAACAATGGTGATGGAACTGATCAGAATGGTCAAACGGGGGATCAACGATCGAAATTTTTGGAGAGGTGAGAATGGGCGGAAAACAAGAAGTGCTTATGAGAGAATGTGCAACATTCTTAAAGGAAAATTTCAAACAGCTGCACAAAGAGCAATGGTGGATCAAGTTAGAGAAAGTCGGAACCCAGGAAACGCTGAGATCGAAGATCTCATATTTTTAGCAAGATCTGCACTGATATTGAGAGGATCAGTTGCTCACAAATCTTGCCTACCTGCCTGTGCATATGGACCTGCAGTATCCAGTGGTTATGACTTTGAAAAAGAGGGATATTCCTTGGTGGGAATAGACCCTTTCAAACTACTTCAAAATAGCCAAATATACAGCTTAATCAGACCTAATGAGAATCCAGCACACAAGAGTCAGCTGGTGTGGATGGCATGCCATTCTGCTGCATTTGAAGATTTAAGATTGTTAAGCTTCATCAGAGGGACAAAAGTATCTCCTCGGGGGAAACTGTCAACTAGAGGAGTACAAATTGCTTCAAATGAGAACATGGATAATATGGGATCAAGCACTCTTGAACTGAGAAGCGGGTACTGGGCCATAAGGACCAGGAGTGGAGGAAACACTAATCAACAGAGGGCCTCCGCAGGCCAAACCAGTGTGCAACCTACGTTTTCTGTACAAAGAAACCTCCCATTTGAAAAGTCAACCATCATGGCAGCATTCACTGGAAATACGGAGGGAAGAACTTCAGACATGAGGGCAGAAATCATAAGGATGATGGAAGGTGCAAAACCAGAAGAAGTGTCATTCCGGGGGAGGGGAGTTTTCGAGCTCTCAGACGAGAAGGCAGCGAACCCGATCGTGCCCTCTTTTGATATGAGTAACGAAGGATCTTATTTCTTCGGAGACAATGCAGAAGAGTACGACAATTAA",  # NP 1497 nt165        6: "ATGAATCCAAATCAAAAGATAATAACGATTGGCTCTGTTTCTCTCACCATTTCCACAATATGCTTCTTCATGCAAATTGCCATCCTGATAACTACTGTAACATTGCATTTCAAGCAATATGAATTCAACTCCCCCCCAAACAACCAAGTGATGCTGTGTGAACCAACAATAATAGAAAGAAACATAACAGAGATAGTGTATTTGACCAACACCACCATAGAGAAGGAAATATGCCCCAAACCAGCAGAATACAGAAATTGGTCAAAACCGCAATGTGGCATTACAGGATTTGCACCTTTCTCTAAGGACAATTCGATTAGGCTTTCCGCTGGTGGGGACATCTGGGTGACAAGAGAACCTTATGTGTCATGCGATCCTGACAAGTGTTATCAATTTGCCCTTGGACAGGGAACAACACTAAACAACGTGCATTCAAATAACACAGTACGTGATAGGACCCCTTATCGGACTCTATTGATGAATGAGTTGGGTGTTCCTTTCCATCTGGGGACCAAGCAAGTGTGCATAGCATGGTCCAGCTCAAGTTGTCACGATGGAAAAGCATGGCTGCATGTTTGTATAACGGGGGATGATAAAAATGCAACTGCTAGCTTCATTTACAATGGGAGGCTTGTAGATAGTGTTGTTTCATGGTCCAAAGATATTCTCAGGACCCAGGAGTCAGAATGCGTTTGTATCAATGGAACTTGTACAGTAGTAATGACTGATGGAAATGCTACAGGAAAAGCTGATACTAAAATACTATTCATTGAGGAGGGGAAAATCGTTCATACTAGCAAATTGTCAGGAAGTGCTCAGCATGTCGAAGAGTGCTCTTGCTATCCTCGATATCCTGGTGTCAGATGTGTCTGCAGAGACAACTGGAAAGGATCCAACCGGCCCATCGTAGATATAAACATAAAGGATCATAGCATTGTTTCCAGTTATGTGTGTTCAGGACTTGTCGGAGACACACCCAGAAAAAAAGACAGCTCCAGCAGTAGCCATTGTTTGAATCCTAACAATGAAGAAGGTGGTCATGGAGTGAAAGGCTGGGCCTTTGATGATGGAAATGACGTGTGGATGGGGAGAACAATCAACGAGACGTCACGCTTAGGGTATGAAACCTTCAAAGTCGTTGAAGGCTGGTCCAACCCTAAGTCCAAATTGCAGATAAATAGGCAAGTCATAGTTGACAGAGGTGATAGGTCCGGTTATTCTGGTATTTTCTCTGTTGAAGGCAAAAGCTGCATCAATCGGTGCTTTTATGTGGAGTTGATTAGGGGAAGAAAAGAGGAAACTGAAGTCTTGTGGACCTCAAACAGTATTGTTGTGTTTTGTGGCACCTCAGGTACATATGGAACAGGCTCATGGCCTGATGGGGCGGACCTCAATCTCATGCATATATAA",  # NA 1410 nt166        7: "ATGAGCCTTCTAACCGAGGTCGAAACGTATGTTCTCTCTATCGTTCCATCAGGCCCCCTCAAAGCCGAGATCGCGCAGAGACTTGAAGATGTCTTTGCTGGGAAAAACACAGATCTTGAGGCTCTCATGGAATGGCTAAAGACAAGACCAATTCTGTCACCTTTGACTAAGGGGATTTTAGGGTTTGTTTTCACGCTCACCGTGCCCAGTGAGCGAGGACTGCAGCGTAGACGCTTTGTCCAAAATGCCCTCAATGGGAATGGAGACCCAAATAACATGGACAAAGCAGTTAAACTGTATAGGAAACTTAAGAGGGAGATAACGTTCCACGGGGCCAAAGAAATAGCTCTCAGTTATTCTGCTGGTGCACTTGCCAGTTGCATGGGCCTCATATACAATAGGATGGGGGCTGTAACCACTGAAGTGGCATTTGGCCTGGTGTGTGCAACATGTGAGCAGATTGCTGATTCCCAGCACAGGTCTCATAGGCAGATGGTGGCAACAACCAATCCATTAATAAAACATGAGAACAGAATGGTTTTGGCCAGCACTACAGCTAAGGCTATGGAGCAAATGGCTGGATCAAGTGAGCAGGCAGCGGAGGCCATGGAGATTGCTAGTCAGGCCAGGCAGATGGTGCAGGCAATGAGAGCCATTGGGACTCATCCTAGTTCCAGTACTGGTCTAAGAGATGATCTTCTTGAAAATTTGCAGACCTATCAGAAACGAATGGGGGTGCAGATGCAACGATTCAAGTGACCCGCTTGTTGTTGCCGCGAATATCATTGGGATCTTGCACTTGATATTGTGGATTCTTGATCGTCTTTTTTTCAAATGCGTCTATCGACTCTTCAAACACGGCCTTAAAAGAGGCCCTTCTACGGAAGGAGTACCTGAGTCTATGAGGGAAGAATATCGAAAGGAACAGCAGAATGCTGTGGATGCTGACGACAGTCATTTTGTCAGCATAGAGTTGGAGTAA",  # M 982 nt167        8: "ATGGATTCCAACACTGTGTCAAGTTTCCAGGTAGATTGCTTTCTTTGGCATATCCGGAAACAAGTTGTAGACCAAAAACTGAGTGATGCCCCTTTCCTCGATCGGCTTCGCCGAGATCAGAGGTCCCTAAGGGGAAGAGGCAATACTCTCGGTCTAGACATCAAATCAGCCACCCATGTTGGAAAGCAAATCGTAAAAAAGATTCTGAAAGAAGAATCTGATGAGGCACTTAAAATGACCATGGTCTCAACACCTGCTTCGCGATACATAACTGACATGACTATTGAGGAATTGTCAAGAAACTGGTTCATGCTAATGCCCAAGCAGAAAGTGGAAGGACCTCTTTGCATCAGAATGGACCAGGCAATCATGGAGAAAAACATCATGTTAAAAGCGAATTTCAATGTGATTTTTGGCCGACTAGAGACCATAGTATTACTAAGGGCTTTCACCGAAGAGGGAGCAATTGTTGGCGAAATCTCACCATTGCCTTCTTTTCCAGGACATACTATTGAGGATGTCAAAAATGCAATTGGGGTCCTCATCGGAGGACTTGAATGGAATGATAACACAATTCGAGTCTCTAAAAATCTACAGAGATTCGCTTGGAGAAGCAGTAATGAGAATGGGGGACCTCCACTTACTCCAAAACAGAAACGGGAAATGGCGAGAACAGCTAGGTCAGAAGTTTGAAGAGATAAGATGGCTAATTGAAGAGGTGAGACACAGATTAAGAACAACTGAAAATAGCTTTGAACAAATAACATTCATGCAAGCATTACAACTACTGTTTGAAGTGGAACAGGAGATAAGAACTTTCTCATTTCAGCTTATTTAA",  # NS 838 nt168    },169    "H5N1_GullFr_2022": {170        1: "ATGGAGAGAATAAAAGAACTAAGAGATTTAATGTCGCAGTCTCGCACTCGCGAGATACTGACAAAAACCACTGTGGACCATATGGCCATAATAAAGAAATACACATCAGGAAGACAGGAGAAGAACCCTGCCCTCAGGATGAAGTGGATGATGGCAATGAAATATCCTATTACAGCAGACAAAAGAATAATGGAGATGATCCCTGAAAGGAATGAGCAAGGTCAGACTCTCTGGAGCAAAACAAATGACGCTGGATCAGACAGAGTGATGGTGTCACCTCTGGCTGTGACATGGTGGAATAGAAATGGGCCAACAACAAGTACAGTCCATTACCCAAAGGTTTACAAAACCTACTTTGAAAAAGTGGAAAGATTGAAACATGGAACCTTTGGCCCTGTTCACTTTCGAAATCAGGTTAAGATACGCCGCAGGGTTGACATAAACCCGGGTCATGCAGATCTCAGTGCCAAAGAAGCACAGGATGTCATCATGGAAGTCGTTTTCCCAAATGAAGTTGGAGCCAGGATATTGACATCAGAATCACAATTAACAATAACAAAGGAAAAGAAGGAGGAACTTCAGGACTGTAAGATTGCTCCTTTGATGGTGGCATACATGTTGGAGAGAGAACTGGTTCGAAAAACCAGATTTTTACCAGTAGCTGGCGGAACAAGCAGCGTATATATCGAAGTATTGCATTTGACTCAAGGGACCTGCTGGGAACAAATGTACACACCGGGAGGGGAAGTGAGAAATGATGATATTGATCAGAGTTTGATCATTGCTGCTAGAAATATCGTTAGGAGAGCAACAGTATCAGCAGACCCATTGGCTTCGCTCTTGGAAATGTGCCACAGTACACAAATTGGCGGAATAAGGATGGTAGACATTCTTAGACAGAACCCAACAGAAGAGCAAGCCGTGGATATATGCAAAGCAGCAATGGGTTTAAGAATCAGTTCATCCTTCAGCTTTGGAGGTTTCACTTTCAAAAGAACAAGTGGATCGTCTGTCAAAAGAGAAGAAGAAGTGCTCACAGGCAACCTCCAAACACTGAAAATAAGAGTACATGAAGGATATGAGGAATTCACAATGGTTGGACGGAGAGCTACAGCCATTTTAAGGAAAGCAACCAGAAGGCTGATCCAATTAATAGTGAGTGGAAGAGACGAGCAGTCAATCGCTGAAGCAATCATAGTGGCAATGGTTTTCTCACAAGAGGACTGCATGATAAAAGCAGTACGAGGTGATCTGAACTTTGTTAATAGAGCAAATCAGCGACTAAATCCTATGCATCAACTTCTGAGGCATTTCCAAAAGGATGCAAAAGTGCTGTTTCAAAACTGGGGGGTTGAACCAATTGACAATGTAATGGGGATGATTGGAATACTGCCTGACATGACCCCCAGCACGGAGATGTCACTGAGAGGAGTGAGAGTCAGCAAAATGGGAGTGGATGAATATTCCAGTACTGAGAGAGTGGTCGTGAGCATTGATCGTTTCTTGAGAGTCCGAGATCAAAGAGGAAACGTGCTCCTGTCTCCTGAGGAAGTTAGTGAAACACAGGGAACAGAGAAACTGACGATAACATATTCATCGTCCATGATGTGGGAAATCAATGGTCCGGAATCCGTGCTAGTCAACACATATCAATGGATCATCAGAAATTGGGAGACTGTGAAGATTCAATGGTCCCATGACCCTACGATGTTGTACAACAAGATGGAATTTGAGCCCTTCCAATCCTTGGTGCCCAAGGCTGCCAGAGGCCAGTATAGTGGATTTGTGAGGACATTGTTCCAGCAGATGCGTGATGTGCTGGGAACATTTGATACTGTCCAAATAATAAAGCTCCTGCCTTTTGCTGCAGCCCCACCGGAACAGAGTAGGATGCAGTTTTCCTCTCTGACTGTGAACGTAAGAGGTTCAGGAATGAGAATACTCGTGAGAGGCAACTCCCCTGTGTTCAACTATAACAAGGCCACCAAGAGACTCACAGTTCTTGGAAAGGATGCAGGTGCCTTGACAGAAGATCCAGATGAGGGAACAGCAAGAGTAGAGTCTGCAGTATTAAGAGGATTTCTAATTCTGGGCAAAGAGGACAAAAGATATGGACCAGCATTGAGCATCAACGAACTGAGCAATCTTGCGAAAGGGGAAAAGGCTAATGTGTTGATAGGGCAAGGAGACGTAGTATTGGTAATGAAACGGAAACGGGACTCTAGCATACTTACTGACAGCCAGACAGCGACCAAAAGAATTCGGATGGCCATCAATTAG",  # PB2 2280 nt171        2: "ATGGATGTCAATCCGACTCTACTTTTCTTAAAAGTGCCAGCGCAAGATGCCATAAGTACCACATTCCCTTACACTGGAGATCCTCCATACAGCCATGGAACAGGGACAGGATACACAATGGACACAGTCAACAGAACACATCAATACTCAGAAAAGGGAAAATGGACAACAAACACAGAAACCGGAGCACCTCAACTCAATCCAATTGATGGGCCACTACCTGAGGACAACGAACCGAGCGGATATGCACAAACAGATTGCGTGTTGGAAGCAATGGCTTTCCTTGAAGAGTCCCATCCAGGGATCTTTGAAAACTCTTGTCTTGAAACGATGGAAGTCGTTCAGCAAACAAGAGTGGACAAACTAACTCAAGGTCGCCAGACATATGACTGGACACTGAATAGAAACCAACCAGCTGCAACTGCCCTGGCCAACACTATAGAGGTCTACAGATCAAACGGTCTAACAGCCAATGAATCGGGGAGACTAATAGATTTCCTCAAGGATGTGATGGACTCAATGAATAAAGAAGAAATGGAAATAACAACACATTTCCAGAGAAAGAGAAGAGTAAGGGACAACATGACCAAGAAAATGGTCACACAAAGAACAATAGGAAAGAAGAAACAAAGGCTAAACAAGAGGAGCTACTTAATAAGAGCACTGACACTGAATACAATGACAAAAGATGCAGAAAGAGGCAAATTGAAGAGACGGGCGATTGCAACACCAGGGATGCAGATTAGAGGATTTGTGTACTTTGTCGAAACACTGGCAAGGAGCATCTGTGAAAAACTTGAGCAATCTGGACTCCCCGTTGGAGGGAATGAGAAGAAGGCTAAATTGGCAAATGTTGTGAGAAAAATGATGACTAACTCACAAGATACAGAGCTCTCCTTCACAATTACTGGAGATAACACCAAATGGAATGAGAATCAAAATCCTCGGATGTTTCTGGCAATGATAACATACATTACAAGAAACCAACCTGAATGGTTTAGGAATGTCTTGAGTATTGCCCCTATAATGTTCTCGAACAAAATGGCGAGATTGGGGAAAGGGTACATGTTTGAAAGTAAGAGCATGAAGTTACGGACACAAATACCTGCAGAAATGCTTGCAAACATTGACTTAAAATATTTCAATGAATCAACAAGAAAGAAAATCGAAAAAATAAGGCCTCTACTAATAGATGGCACTGCCTCATTGAGTCCTGGAATGATGATGGGCATGTTCAATATGCTGAGTACAGTATTAGGAGTTTCAATCCTAAATCTTGGGCAAAAGAAGTACACCAAAACCACATACTGGTGGGATGGACTCCAATCCTCTGATGATTTCGCCCTCATAGTAAATGCACCGAATCATGAGGGAATACAAGCAGGAGTGGATAGGTTCTATAGGACCTGCAAACTGGTCGGGATCAATATGAGCAAAAAGAAGTCTTACATAAACCGGACTGGAACATTTGAGTTCACAAGCTTTTTCTATCGCTATGGATTTGTGGCTAACTTCAGTATGGAGCTGCCCAGCTTTGGAGTTTCTGGGATCAATGAATCAGCTGACATGAGCATTGGCATCACAGTGATAAAGAACAACATGATAAACAATGACCTTGGACCAGCAACAGCTCAAATGGCCCTTCAACTATTCATCAAAGATTACAGGTACACGTACCGATGCCATAGAGGTGACACACAAATTCAAACGAGGAGATCATTCGAGCTGAAGAAGCTGTGGGAACAGACCCGTTCAAAGGCAGGACTGTTGGTGTCAGATGGAGGACCAAATCTATACAACATTCGGAATCTCCATATCCCAGAGGTCTGCTTGAAGTGGGAGCTGATGGACGAAGATTACCAGGGCAGGTTGTGTAATCCTCTGAACCCATTTGTCAGCCATAAAGAAATTGAGTCCGTAAACAATGCTGTGGTGATGCCAGCCCACGGTCCAGCCAAAAGCATGGAATATGATGCCGTTGCGACTACACACTCATGGATTCCTAAAAGGAATCGTTCCATTCTCAATACCAGTCAAAGGGGAATTCTTGAGGATGAACAGATGTACCAGAAATGCTGCGGTCTATTCGAGAAATTCTTTCCCAGTAGTTCATACAGGAGACCAGTTGGAATTTCCAGCATGGTGGAGGCCATGGTGTCTAGGGCCCGAATCGATGCACGCATTGATTTCGAATCTGGAAGGATCAAGAAGGAAGAGTTTGCTGAGATCATGAAGATCTGTTCCACCATTGAAGAGCTCAGACGGCAAAAATAG",  # PB1 2274 nt172        3: "ATGGAAGACTTTGTGCGACAATGCTTCAATCCGATGATTGTCGAGCTTGCGGAAAAGGCAATGAAAGAATATGGGGAGGATCCGAAAATTGAAACAAATAAGTTTGCTGCAATATGCACACACTTAGAAGTCTGTTTCATGTATTCGGATTTCCACTTCATTGATGAGCGAGGAGAATCAATAATTGTAGAACCTGGCGACCCGAATGTATTGCTGAAACACCGATTTGAAATAATCGAAGGGAGAGACCGAACAATGGCCTGGACAGTGGTGAATAGTATTTGCAACACCACAGGAGTCGACAAACCCAAATTTCTTCCAGATTTGTATGACTACAAAGAAAACCGGTTCATCGAAATCGGAGTGACACGAAGGGAAGTTCACATATACTATCTGGAAAAAGCCAACAAGATAAAATCAGAGAAAACACACATTCACATATTCTCATTCACCGGGGAGGAAATGGCCACTAAAGCAGACTATACCCTTGATGAAGAGAGCAGAGCAAGAATCAAAACCAGGCTGTTCACTATAAGGCAAGAAATGGCCAGTAGGGGTTTATGGGATTCCTTTCGTCAGTCCGAGAGAGGCGAAGAGACAATTGAAGAAAGATTTGAAATCACAGGAACCATGCGCAGGCTTGCCGACCAAAGTCTCCCACCGAACTTCTCCAGCCTTGAAAACTTTAGAGCCTATGTGGATGGATTCGAACCGAACGGCTGCATTGAGGGCAAGCTTTCTCAAATGTCAAAGGAAGTAAACGCCAGAATTGAGCCATTCTTGAAGACAACCCCACGGCCTCTTAGACTACCTGATGGCCCTCCTTGTTCTCAGCGATCGAAATTCTTGCTGATGGATGCCCTTAAATTAAGCATAGAAGACCCAAGTCATGAGGGGGAAGGTATACCACTATATGATGCAATCAAATGCATGAAGACATTTTTTGGCTGGAAAGAGCCCAATATTGTAAAACCACATGAAAAGGGCATAAACCCCAATTACCTCCTAGCTTGGAAGCAGGTGCTGTCAGAGCTCCAAGACCTTGAAAGTGAGGATAAAATCCCAAAAACAAAGAACATGAAGAAAACAAGCCAGTTGAAGTGGGCACTTGGTGAGAATATGGCACCAGAGAAAGTAGATTTTGAGGACTGCAAAGATGTTAGCGATCTAAGACAGTATGACAGTGATGAACCAGAGTCTAGATCGTTGGCAAGCTGGATCCAGAGTGAATTCAACAAAGCATGCGAATTAACAGATTCAAGTTGGATTGAACTTGATGAAATAGGGGAAGATGTTGCTCCAATTGAGCACATTGCAAGCATGAGAAGGAACTATTTCACAGCGGAAGTATCCCATTGCAGGGCTACTGAGTATATAATGAAGGGAGTGTATATAAATACAGCCCTGTTGAATGCATCCTGTGCAGCCATGGATGACTTCCAACTGATCCCGATGATAAGCAAGTGCAGAACCAAAGAAGGAAGACGGAAAACAAATCTGTATGGATTCATTATAAAAGGAAGATCTCATTTGAGAAATGATACAGATGTAGTAAACTTTGTAAGCATGGAATTCTCTCTCACTGACCCGAGGCTGGAGCCACACAAATGGGAAAAGTACTGTGTTCTCGAGATAGGAGACATGCTCCTACGGACTGCAATAGGCCAAGTGTCAAGGCCCATGTTCCTTTATGTGAGAACCAATGGTACTTCCAAGATCAAAATGAAATGGGGTATGGAGATGAGAAGATGCCTCCTTCAATCTCTTCAACAAATTGAGAGCATGATTGAGGCTGAATCTTCTGTCAAAGAAAAGGACATGACCAAGGAGTTCTTTGAGAACAAATCTGAAACATGGCCAATTGGAGAGTCGCCCAAAGGGGTAGAGGAAGGATCCATTGGAAAGGTGTGCAGGACATTACTAGCAAAATCTGTGTTTAATAGTCTATATGCATCTCCACAACTTGAGGGGTTTTCAGCCGAGTCAAGAAAATTGCTTCTCATTGTTCAGGCACTTAGGGACAACCTGGAACCTGGGACCTTCGATCTTGGGGGGCTATATGAAGCAATTGAGGAGTGCCTGATTAATGATCCCTGGGTTTTGCTTAATGCGTCTTGGTTCAACTCCTTCCTCACACATGCACTGAAATAG",  # PA 2151 nt173        4: "ATGGAGAACATAGTACTTCTTCTTGCAATAGTTAGCCTTGTTAAAAGTGATCAGATTTGCATTGGTTACCATGCAAATAATTCGACAGAGCAGGTTGACACGATAATGGAAAAGAACGTCACTGTTACACATGCCCAAGACATACTGGAAAAAACACACAACGGGAAGCTCTGTGATTTAAATGGGGTGAAGCCTCTGATTTTAAAGGATTGTAGTGTAGCTGGATGGCTCCTCGGAAACCCAATGTGCGACGAATTCATCAGAGTGCCGGAATGGTCCTACATAGTGGAGCGGGCTAATCCAGCTAATGACCTCTGTTACCCAGGGAGCCTCAATGACTATGAAGAACTGAAACACCTGTTGAGCAGAATAAATCATTTTGAGAAGATTCTTATCATCCCCAAGAGTTCCTGGCCAAATCATGAAACATCACTAGGGGTGAGCGCAGCTTGTCCATACCAGGGAGCGCCCTCCTTTTTCAGAAATGTGGTGTGGCTTATCAAAAAGAACGATGCATACCCAACAATAAAGATAAGCTACAATAATACCAATCGGGAAGATCTCTTGATACTGTGGGGGATTCATCATTCCAACAATGCAGAAGAACAGACAAATCTCTATAAAAACCCAACCACCTACATTTCAGTTGGAACATCAACTTTAAACCAGAGGTTGGTACCAAAAATAGCTACTAGATCCCAAGTAAACGGGCAACGTGGAAGAATGGACTTCTTCTGGACAATTTTAAAACCAGATGATGCAATCCATTTCGAGAGTAATGGAAATTTCATTGCTCCAGAATATGCATATAAAATTGTCAAGAAAGGGGACTCAACAATTATGAAAAGTGGAGTGGAATATGGCCATTGCAACACCAAATGTCAAACCCCAGTAGGAGCGATAAATTCTAGTATGCCATTCCACAACATACATCCTCTCACCATTGGGGAATGCCCCAAATACGTGAAGTCAAACAAGTTGGTCCTTGCGACTGGGCTCAGAAATAGTCCTCTAAGAGAAAAGAGAAGAAAAAGAGGCCTGTTTGGGGCGATAGCAGGGTTTATAGAGGGAGGATGGCAGGGAATGGTTGATGGTTGGTATGGGTACCATCATAGCAATGAGCAGGGGAGTGGGTACGCTGCGGACAAAGAATCCACCCAAAAGGCAATAGATGGAGTTACCAATAAGGTCAACTCAATCATTGACAAAATGAACACTCAATTTGAGGCAGTTGGAAGGGAGTTTAATAACTTAGAAAGGAGGATAGAGAATTTGAACAAGAAAATGGAAGACGGATTCCTAGATGTCTGGACCTATAATGCTGAACTTCTAGTTCTCATGGAAAACGAGAGGACTTTAGATTTCCATGATTCAAATGTCAAGAACCTTTACGACAAAGTCAGACTACAGCTTAGGGATAATGCAAAGGAGCTGGGTAATGGCTGTTTCGAATTCTATCACAAATGCGATAATGAATGTATGGAAAGTGTGAGAAATGGGACGTATGACTACCCTCAGTATTCAGAAGAAGCAAGATTAAAAAGAGAAGAAATAAGCGGAGTGAAATTAGAATCAATAGGAACTTACCAGATACTGTCAATTTATTCAACAGCGGCGAGTTCCCTAGCACTGGCAATCATGATAGCTGGTCTATCTTTATGGATGTGCTCCAATGGGTCGTTACAGTGCAGAATTTGCATTTAGATTTGTGAGCTCAGATTGTAGTTAAAAACACCCTTGTTTCTACT",  # HA 1748 nt174        5: "AGCAAAAGCAGGGTAGATAATCACTCACTGAGTGACATCCACATCATGGCGTCTCAAGGCACCAAACGATCTTATGAGCAGATGGAAACTGGTGGAGAACGCCAGAATGCCACTGAGATTCGGGCATCTGTCGGAAGGATGATTGGAGGAATCGGAAGATTCTACATACAGATGTGCACTGAACTCAAACTAAGTGACAATGAGGGAAGGCTGATACAAAACAGTATCACAATAGAGAGGATGGTCCTGTCTGCATTTGATGAGAGGAGGAACAGATACCTGGAGGAGCATCCCAGTGCTGGGAGAGATCCCAAGAAAACTGGTGGACCGATTTACAGAAGAAGAGAAGGGAAATGGGTGAGAGAATTGGTCCTATATGACAAGGAAGAGATAAGACGAATCTGGCGACAGGCAAACAATGGAGAAGATTCGACTGCTGGCCTCACCCATYTGATGATCTGGCATTCTAATTTGAATGATGCCACATATCAGAGGACCAGAGCCCTAGTGCGCACCGGGATGGACCCCAGGATGTGCTCCCTCATGCAGGGATCGACACTCCCAAGAAGGTCTGGAGCGGCTGGTGCAGCTGTAAAGGGGGTTGGGACAATGGTGATGGAGATCATCAGAATGATCAAAAGAGGGGTTAATGACCGTAACTTCTGGAGAGGTGAAAATGGGAGAAGAACAAGAATTGCTTATGAAAGGATGTGCAACATCCTCAAAGGGAAATTCCAAACAGCAGCACAACGAGCTATGATGGACCAGGTCAGAGAAAGCCGTAACCCTGGGAATGCTGAGATTGAGGACCTCATATTTTTGGCCAGGTCTGCCCTTATTCTAAGGGGAGCAGTGGCTCATAAGTCATGCCTGCCTGCCTGCGTGTATGGGCTTGCTGTAGCAAGTGGATATGACTTCGAGAGGGAAGGATATTCCCTTGTCGGGATAGACCCTTTCCGTCTGCTCCAAAACAGCCAAGTGTTCAGTCTAATCCGACCCAATGAAAATCCAGCACACAAGAGCCAATTGGTATGGATGGCGTGTCATTCTGCCGCATTTGAGGATTTGAGAGTGTCAAGTTTCATCAGGGGAACAAGAGTGTTGCCAAGAGGGCAACTATCCACAAGAGGTGTTCAAATTGCATCCAATGAGAACATGGAAACTATGAATTCCAGCACACTTGAACTAAGGAGCAAATACTGGGCAATAAGGACTAGAAGCGGAGGAAACACCAATCAACAAAGAGCATCAGCAGGACAAATCAGTGTACAACCTACCTTTTCAGTACAAAGGAACCTCCCTTTTGAAAGAGCGACAATCATGGCTGCATTTACAGGGAATGCAGAAGGAAGAACATCAGATATGAGGACTGAGATCATACGGATGATGGAAAGTGCAAGGCCAGAAGATGTGTCTTTCCAGGGGCGGGGAGTCTTCGAGCTCTCAGACGAAAAGGCCACGAACCCGATCGTGCCTTCCTTTGACATGAGTAAAGAAGGATCTTATTTCTTCGGAGACAATGCTGAGGAGTTTGACAGTTGAAGAAAAATACCCTTGTTTCTACT",  # NP 1565 nt175        6: "AGTTCAAAATGAATCCAAATCAAAGGATAATAACCACTGGATCAATCTGTATGGTAATTGGGATAGTCAGCTTGATGCTGCAAATTGGGAACATAATCTCAATATGGGTTAGCCATTCAATCCAAACAGGGAATCAATACCAGCCTGAACCATGCAATCAAAGCATCATTACCTATGAGAACAACACCTGGGTAAATCAGACGTATGTCAACATCAGCAATACCAATTTTCTTGCTGAGCAGGCTGTTACTTCGGTAACATTAGCGGGCAATTCATCTCTTTGCCCTATTAGTGGGTGGGCTATATACAGTAAGGACAACGGTATAAGAATTGGGTCCAAGGGGGATGTGTTTGTTATAAGAGAACCGTTCATCTCATGCTCCCACTTGGAATGCAGAACCTTTTTTCTGACCCAGGGAGCTCTGCTGAATGACAAACATTCTAATGGGACTGTTAAGGATAGAAGCCCCTATAGAACTTTGATGAGTTGTCCCGTGGGTGAGGCTCCTTCCCCGTACAATTCAAGATTTGAGTCTGTTGCTTGGTCGGCAAGTGCTTGTCATGATGGCATCAGTTGGCTGACAATCGGTATTTCTGGTCCAGACAATGGAGCTGTGGCTGTATTGAAGTACAATGGCATAATAACGGATACTATCAAGAGTTGGAGAAACAACATTTTGAGAACTCAAGAATCTGAATGTGCGTGCGTAAATGGCTCTTGCTTCACTGTAATGACAGATGGACCAAGCAATGGGCAGGCCTCATATAAAATCTTCAAGATAGAGAAAGGGAAAGTAGTCAAATCAGTTGAATTGAATGCCCCTAATTACCACTACGAGGAATGCTCCTGTTATCCTGATGCGGGTGAGATTATGTGTGTTTGCAGGGACAATTGGCATGGCTCAAACCGGCCGTGGGTATCTTTTAATCAAAATCTGGAGTATCAAATAGGATATATATGCAGTGGGGTTTTCGGAGACAACCCCCGCCCCAATGACGGAACAGGCAGTTGCAGTCCAATGTCCTCTAACGGGGCATATGGGGTAAAAGGGTTTTCATTTAAGTACGGTAATGGGGTTTGGATCGGAAGAACAAAAAGCACTAGTTCCAGGATCGGCTTTGAGATGATTTGGGATCCGAATGGGTGGACTGAGACGGACAGTAGTTTCTCAGTGAAGCAAGACATCGTAGCAATAACTGACTGGTCAGGATATAGTGGGACTTTTGTCCAGCACCCAGAACTGACAGGATTAGATTGCATGAGGCCTTGTTTCTGGGTTGAGCTGATTAGAGGGAGGCCCAAAGAGAACACAATTTGGACTAGCGGGAGCAGCATATCCTTTTGTGGTGTAAATAGTGACACTGTGGGTTGGTCGTGGCCAGACGGTGCTGAATTGCCATTCACCATTGACAAGTAGTTTGTTCAAAAAACT",  # NA 1433 nt176        7: "AGCAAAAGCAGGTAGATATTGAAAGATGAGTCTTCTAACCGAGGTCGAAACGTACGTTCTCTCTATCGTCCCGTCGGGCCCCCTCAAAGCCGAGATCGCGCAGAGACTTGAAGATGTCTTTGCAGGGAAGAACACCGATCTTGAGGCTCTCATGGAATGGCTAAAGACAAGACCAATCCTGTCACCTATGACTAAGGGGATTTTGGGATTTGTGTTCACGCTCACCGTGCCCAGTGAGCGAGGACTGCAGCGTAGACGCTTTGTCCAAAATGCTCTAAATGGAAATGGAGACCCAAACAACATGGACAGGGCAGTAAAACTGTACAAGAAATTGAAGAGAGAGATAACATTCCATGGGGCTAAAGAAGTTGCACTCAGTTACTCAACCGGTGCACTTGCCAGTTGTATGGGTCTCATATACAACAGGATGGGGACGGTGACCGCAGAAGTGGCATTGGGCCTAGTGTGTGCCACCTGTGAGCAGATTGCTGATTCACAGCATCGGTCTCACAGGCAGATAGCTACCACCACCAACCCACTAATCAGACATGAAAACAGAATGGTGTTGGCCAGTACTACAGCTAAGGCTATGGAGCAGATGGCTGGATCGAGTGAGCAAGCAGCGGAAGCCATGGAGGTTGCTAGTCAGGCTAGGCAAATGGTGCAAGCGATGAGGACCATTGGAACTCATCCTAGCTCCAGTGCCGGTCTGAGAGATGATCTCCTTGAAAATTTGCAGGCCTACCAAAAACGGATGGGAGTGCAACTGCAGCGATTCAAGTGATCCTCTCGTTATTGCCGCAAGTATCATTGGGATCTTGCACTTGATATTGTGGATTCTTGATCGCCTTTTCTTCAAATGCGTTTATCGTCGCCTTAAATACGGTTTGAAAAGAGGGCCTTCTACGGAAGGAGTACCTGAGTCCATGAGGGAAGAGTACCGGCAGGAACAGCAGAGTGCTGTGGATGTTGACGATGGTCATTTTGTCAACATAGAGCTGGAGTAAAAAACTACCTTGTTTCTACT",  # M 1027 nt177        8: "AGCAAAAGCAGGGTGACAAAAACATAATGGATTCAAACACTGTGTCAAGCTTTCAGGTAGACTGCTTTCTTTGGCATGTCCGCAAACGATTTGCAGACCAAGATATGGGTGATGCCCCATTCCTAGATCGGCTTCGCCGAGACCAAAAGTCCCTAAGAGGGAGAAGCAGCACTCTTGGTATCGACATTGAGGCAGCTACTCGCTCTGGGAAGCAGATAATAGAGCGGATTCTGGGTGAAGAATCAGACGAGGCACTGAAAATGACAATTGCCTCTGTGCCTGCATCCCGCTATATAACTGACATGACCACTGAAGAAATGTCAAGGGACTGGTTTATGCTTATGCCCAAGCAGAAGTTTGCTGGTCCCCTCTGCATCAAAATGGATCAGGCAATCATAGACAAAGACATCACACTGAAGGCAAATTTCAGTGTAATCTTCAACAGATTGGAAACTCTCGTGCTGCTGAGGGCTTTTACCAATGAGGGAGCAATAGTGGGCGAAATTTCACAATTGCCTTCTCTTCCAGGACATACTAGCGAGGATGTCAAAAATGCAATTGGAGTCCTCATCGGGGGACTTGAATGGAATGATAACACAGTTCGAATCTCTGAAAATCTACAGAGATTCGCTTGGGGAAGCAGTAATGAGAATGGGAGACCTCCATTCACTCCAGAGCAGAAACAGAAACTGGCGAGAACAATTGAGTCAGAAGTTTGAAGAAATGAGATGGTTGATTGAAGAAGTGAGACACAAGTTGAAGACAACAGAGAGTAGTTTTGAACAAATAACATTCATGCAAGCATTACAACTATTGCTTGAAGTGGAGCAAGAGATAAGGACTTTCTCGTTTCAGCTTATTTGATGATAAAAAACACCCTTGTTTCTACT",  # NS 890 nt178    },179    "H7N9_Shanghai_2013": {180        1: "ATGGAAAGAATAAAAGAACTAAGAGATTTGATGTCACAGTCTCGCACTCGCGAGATACTGACAAAAACAACTGTGGACCATATGGCCATAATCAAGAAATATACATCAGGAAGACAGGAGAAGAATCCTGCCCTTAGGATGAAGTGGATGATGGCAATGAAATATCCAATTACGGCAGACAAAAGGATAATGGAGATGATCCCGGAAAGAAATGAGCAAGGTCAGACCCTTTGGAGCAAGACAAATGATGCTGGATCAGACAGAGTGATGGTGTCACCTCTGGCTGTGACGTGGTGGAACAGAAATGGACCAACGACAAGCACAGTCCATTATCCAAAGGTCTATAAAACCTATTTTGAAAAGGTCGAAAGGCTAAAACATGGAACCTTCGGCCCCGTTCACTTCAGAAACCAGGTTAAAATACGCCGCAGGGTCGACATAAACCCGGGCCATGCAGATCTTAGTGCTAAAGAAGCACAGGATGTCATCATGGAGGTCGTATTCCCAAACGAAGTTGGAGCCAGAATATTGACATCAGAGTCACAGTTAACGATTACCAAGGAAAAGAAGAAGGAGCTTCAGGACTGCAAAATTGCCCCTTTAATGGTGGCTTACATGTTGGAGAGAGAACTGGTTCGCAAAACAAGATTCCTACCAGTAGCTGGAGGGACAAGCAGCGTGTATATCGAGGTGTTGCATTTGACCCAAGGGACCTGCTGGGAGCAAATGTACACACCGGGAGGGGAAGTGAGAAATGATGATGTTGATCAGAGTTTAATTATTGCTGCTAGAAATATTGTTAGAAGAGCAACAGTATCAGCAGACCCGTTGGCTTCGCTTTTGGAGATGTGCCATAGTACACAGATTGGCGGGATTAGGATGGTTGACATCCTTAGACAAAACCCAACAGAAGAACAGGCTGTGGATATATGTAAGGCAGCAATGGGTCTAAGGATCAGTTCATCCTTCAGCTTTGGAGGTTTCACTTTCAAAAGGACAAGTGGGTCATCTGTCAAAAGGGAAGAAGAAGTGCTCACAGGCAACCTCCAAACATTGAAAATAAGAGTACATGAAGGATATGAGGAATTCACAATGGTCGGGCGAAGAGCAACAGCCATTCTAAGGAAAGCAACCAGAAGACTGATCCAACTGATAGTGAGTGGGAAAGACGAGCAATCAATCGCCGAGGCAATCATAGTGGCAATGGTATTCTCACAAGAGGATTGTATGATAAAGGCAGTGAGAGGTGATTTGAACTTTGTCAACAGAGCAAACCAGCGGCTAAATCCCATGCATCAACTCCTGAGGCATTTCCAAAAGGATGCAAAGGTCCTGTTTCAAAACTGGGGAATTGAACCCATTGACAATGTAATGGGGATGATCGGAATATTGCCTGACATGACCCCCAGCACAGAGATGTCATTGAGAGGAGTGAGAGTTAGTAAAATGGGAGTAGATGAATATTCCAGCACTGAGAGAGTGGTCGTGAGTATTGATCGTTTCTTGAGGGTCCGAGACCAGAGGGGAAACGTACTCCTGTCTCCTGAAGAGGTTAGTGAAACACAGGGAACAGAAAAGCTGACTATAACATATTCATCGTCCATGATGTGGGAGATCAATGGTCCGGAATCAGTGCTAGTTAACACATATCAATGGATCATTAGAAATTGGGAAAATGTAAAGATTCAATGGTCCCAAGATCCTACAATGCTATACAATAAGATGGAATTTGAACCCTTTCAATCCCTAGTGCCTAAAGCTGCCAGGGGCCAATATAGTGGGTTCGTGAGGGTTCTATTCCAACAGATGCGTGACGTACTGGGAACATTTGACACTGTCCAAATAATAAAGCTATTACCATTTGCAGCAGCCCCGCCGAAGCAGAGTAGGATGCAGTTCTCTTCTCTAACTGTGAATGTGAGGGGTTCCGGAATGAGAATAGTTGTGAGAGGCAATTCTCCTGTGTTCAACTACAACAAGGCAACCAAGAGGCTTACGGTGCTTGGAAAGGATGCAGGTGCATTGATGGAAGACCCCGATGAGGGAACAGCAGGAGTGGAATCTGCGGTATTGAGGGGATTTCTGATTCTGGGCAAAGAAGACAAAAGATATGGGCCAGCATTGAGCATCAACGAATTGAGCAATCTTGCGAAAGGAGAGAAGGCTAATGTGTTGATAGGGCAAGGAGACGTTGTGTTGGTGATGAAACGGAAACGGGACTCTAGCATACTTACTGACAGTCAGACAGCGACCAAAAGGATTCGGATGGCCATCAATTAA",  # PB2 2280 nt181        2: "ATGGATGTCAATCCGACTTTACTTTTCTTGAAAGTGCCAGTGCAAAATGCTATAAGTACCACTTTCCCTTATACTGGAGACCCTCCATACAGCCATGGAACAGGAACAGGATACACCATGGACACAGTCAACAGAACACATAAATACTCAGAAAAAGGAAAGTGGACAACGAACACAGAGACTGGAGCACCCCAACTCAATCCAATTGATGGACCATTACCTGAGGACAACGAGCCGAGTGGGTATGCACAAACGGATTGTGTATTGGAAGCAATGGCTTTCCTTGAAGAATCTCACCCAGGGATCTTTGAAAACTCGTGTCTCGAAACGATGGAAATTGTTCAGCAAACAAGAGTGGATAAACTGACCCAAGGCCGCCAGACCTATGACTGGACGTTGAATAGAAATCAGCCGGCTGCTACCGCATTGGCCAACACTATAGAGGTATTCAGATCGAATGGCCTGACAGCCAATGAATCAGGAAGGTTGATCGATTTCCTCAAGGACGTGATGGATTCAATGGATAAGGAAGAAATGGAGATTACAACACATTTCCAGAGGAAGAGGAGAGTGAGGGACAACATGACCAAGAAAATGGTCACACAGAGAACAATAGGAAAGAAAAAACAAAGACTGAACAAAAGGAGCTACCTAATAAGAGCACTTACATTGAACACAATGACAAAGGATGCTGAAAGAGGCAAGCTGAAAAGGAGGGCAATCGCAACACCCGGGATGCAAATCAGAGGATTCGTGTATTTTGTAGAAGCACTAGCGAGGAGCATCTGTGAGAAACTTGAGCAATCTGGCCTCCCTGTCGGAGGGAATGAGAAGAAAGCTAAATTGGCAAATGTTGTGAGGAAGATGATGACTAATTCACAAGATACAGAGCTCTCCTTCACAATTACTGGGGACAACACCAAATGGAATGAGAATCAAAACCCCCGGATGTTTCTAGCAATGATAACATACATCACAAGAAACCAGCCAGAATGGTTTAGAAATGTCTTAAGCATTGCTCCTATAATGTTCTCAAACAAGATGGCGAGATTAGGAAAAGGGTACATGTTCGAAAGTAAGAGTATGAAGTTACGGACACAAGTACCAGCGGAAATGCTCGCAAATATTGACCTGAAATACTTCAACAAATCAACAAGAGAGAAAATCGAGAAAATAAGACCTCTACTGATAGATGGCACAGCCTCATTGAGTCCTGGAATGATGATGGGCATGTTCAACATGTTGAGTACAGTCTTAGGAGTTTCAATTCTGAATCTCGGGCAGAAGAAGTACACCAAAACCACATATTGGTGGGACGGACTCCAATCCTCAGATGACTTCGCCCTCATAGTGAATGCACCGAATCATGAGGGAATACAGGCAGGAGTAGATAGGTTCTATAGAACCTGCAAATTAGTTGGGATAAACATGAGCAAGAAGAAATCCTACATAAATCGGACAGGAACATTCGAATTCACAAGCTTTTTCTACCGCTATGGATTCGTAGCTAACTTCAGTATGGAGTTGCCCAGTTTTGGAGTGTCCGGGATTAATGAGTCAGCTGACATGAGCGTTGGTGTTACAGTAATAAAGAACAATATGATAAACAACGATCTTGGACCAGCAACAGCCCAAATGGCCCTTCAGCTATTTATCAAAGACTACAGATACACATACCGATGTCACAGGGGTGATACGCAAATTCAAACGAGGAGAGCATTCGAGCTGAAGAAGCTGTGGGAGCAGACCCGTTCGAAGGCAGGACTGTTGGTTTCAGATGGAGGGCCAAACCTGTACAATATCCGGAACCTCCACATTCCAGAGGTCTGCTTGAAATGGGAATTGATGGATGAAGACTACCAAGGCAGGTTGTGTAATCCTATGAACCCGTTTGTCAGTCATAAGGAAATTGATTCAGTCAACAATGCTGTGGTGATGCCAGCTCATGGCCCAGCCAAAAGCATGGAGTATGATGCCGTTGCAACCACACATTCATGGATTCCTAAGAGGAATCGCTCCATTCTCAACACCAGCCAAAGGGGGATTCTTGAGGACGAACAGATGTACCAGAAGTGCTGCAACCTATTCGAAAAGTTCTTCCCCAGCAGTTCGTACAGGAGGCCAGTTGGAATTTCCAGCATGGTGGAGGCCATGGTGTCTAGGGCCCGAATTGATGCACGAATTGACTTCGAATCTGGAAGGATTAAGAAAGAAGAGTTTGCTGAGATCATGAAGATCTGTTCCACCATTGAAGAGCTCAGACGGCAAAAATAG",  # PB1 2274 nt182        3: "ATGGAAGACTTTGTGCGACAGTGCTTCAATCCAATGATCGTCGAGCTTGCGGAAAAGGCAATGAAAGAATATGGGGAAGATCCGAAAATCGAAACAAACAAATTCGCATCAATATGCACACACTTAGAAGTCTGCTTCATGTACTCTGATTTCCACTTCATCGACGAACGAGGCGAATCAACTATAATAGAATCTGGCGATCCAAATGCGCTGCTGAAACACCGATTTGAAATAATCGAAGGGAGAGACCGAACAATGGCCTGGACAGTGGTGAATAGTATCTGCAACACCACAGGAGCCGAAAAACCCAAATTTCTCCCGGATCTGTATGACTACAAGGAAAACCGTTTCATTGAAATTGGAGTGACGAGGAGGGAAGTCCACATATATTACCTAGAGAAAGCCAATAAAATAAAATCCGAGAAGACACACATCCATATTTTTTCATTCACTGGAGAAGAGATGGCCACCAAAGCAGATTACACTCTTGACGAAGAAAGCAGGGCAAGAATCAAAACCAGGCTGTTCACCATAAGGCAGGAAATGGCCAGCAGGGGTCTATGGGATTCCTTTCGTCAGTCTGAAAGAGGCGAAGAAACAATTGAAGAAAGATTTGAAATCACAGGAACCATGCGCAGGCTTGCCGACCAAAGTCTCCCACCGAACTTCTCCAGCCTTGAAAACTTTAGAGCCTATGTGGATGGATTCGAACCGAACGGCTGCATTGAGGGCAAGCTTTCTCAGATGTCAAAAGAAGTGAACGCCAGAATTGAGCCATTTCTAAGAACAACACCACGCCCTCTCAGATTGCCTAATGGGCCTCCCTGCTCTCAGCGGTCGAAATTCTTGCTGATGGATGCTCTGAAATTAAGCATTGAGGACCCGAGCCACGAAGGGGAGGGGATACCGCTATATGATGCGATCAAATGCATGAAAACGTTCTTCGGGTGGAAAGAGCCCAACATTATCAAACCACATGAGAAAGGCATAAACCCCAATTATCTCCTGACTTGGAAGCAGGTGCTAGCAGAACTTCAGGACATTGAAAATGAAGAGAAGATTCCAAGGACAAAGAACATGAAGAAAACAAGCCAATTAAAGTGGGCACTCGGTGAGAACATGGCACCGGAGAAGGTGGACTTTGAGGATTGCAAAGATGTCAACGACTTGAAACAGTACAACAGTGATGAGCCAGAGCCCAGATCACTAGCATGTTGGATCCAGAATGAATTCAACAAGGCGTGTGAACTGACTGACTCAAGCTGGGTAGAACTTGATGAAATAGGGGAAGATGTTGCCCCAATCGAACACATTGCAAGCATGAGACGGAACTATTTTACAGCAGAGGTGTCCCACTGCAGGGCTACTGAATATATAATGAAGGGAGTGTACATAAATACAGCTTTGCTCAATGCATCTTGTGCAGCCATGGATGACTTTCAACTGATTCCAATGATAAGTAAATGTAGAACCAAAGAAGGAAGACGGAAAACAAACCTGTATGGATTCATTATAAAAGGAAGATCTCATTTGAGGAATGATACCGACGTGGTAAACTTTGTAAGTATGGAATTTTCCCTTACCGACCCAAGGTTGGAACCACATAAATGGGAAAAGTATTGTGTTCTTGAAATAGGGGACATGCTCCTGCGAACTGCAGTAGGCCAAGTGTCAAGACCCATGTTTCTGTATGTGAGAACCAATGGGACCTCCAAGATCAAGATGAAATGGGGTATGGAAATGAGACGCTGCCTTCTTCAATCTCTCCAACAGATTGAGAGCATGATTGAAGCTGAATCCTCCGTCAAAGAGAAAGACCTGACCAAAGAATTCTTTGAAAACAAATCAGAAACATGGCCAATTGGAGAGTCACCTAAAGGAGTGGAGGAAGGTTCCATCGGGAAGGTGTGCAGAACCTTACTAGCAAAATCTGTATTCAACAGCCTATATGCATCTCCGCAACTCGAGGGGTTCTCAGCTGAATCGAGAAAACTGCTACTCATTGTTCAGGCGCTTAGGGATAACCTGGAACCTGGAACCTTTGATCTTGAAGGGCTATATGAAGCAATCGAGGAGTGCCTGATTAATGATCCCTGGGTTTTGCTTAATGCATCTTGGTTCAACTCCTTCCTCACACATGCACTAAGATAG",  # PA 2151 nt183        4: "ATGAACACTCAAATCCTGGTATTCGCTCTGATTGCGATCATTCCAACAAATGCAGACAAAATCTGCCTCGGACATCATGCCGTGTCAAACGGAACCAAAGTAAACACATTAACTGAAAGAGGAGTGGAAGTCGTCAATGCAACTGAAACAGTGGAACGAACAAACATCCCCAGGATCTGCTCAAAAGGGAAAAGGACAGTTGACCTCGGTCAATGTGGACTCCTGGGGACAATCACTGGACCACCTCAATGTGACCAATTCCTAGAATTTTCAGCCGATTTAATTATTGAGAGGCGAGAAGGAAGTGATGTCTGTTATCCTGGGAAATTCGTGAATGAAGAAGCTCTGAGGCAAATTCTCAGAGAATCAGGCGGAATTGACAAGGAAGCAATGGGATTCACATACAGTGGAATAAGAACTAATGGAGCAACCAGTGCATGTAGGAGATCAGGATCTTCATTCTATGCAGAAATGAAATGGCTCCTGTCAAACACAGATAATGCTGCATTCCCGCAGATGACTAAGTCATATAAAAATACAAGAAAAAGCCCAGCTCTAATAGTATGGGGGATCCATCATTCCGTATCAACTGCAGAGCAAACCAAGCTATATGGGAGTGGAAACAAACTGGTGACAGTTGGGAGTTCTAATTATCAACAATCTTTTGTACCGAGTCCAGGAGCGAGACCACAAGTTAATGGTCTATCTGGAAGAATTGACTTTCATTGGCTAATGCTAAATCCCAATGATACAGTCACTTTCAGTTTCAATGGGGCTTTCATAGCTCCAGACCGTGCAAGCTTCCTGAGAGGAAAATCTATGGGAATCCAGAGTGGAGTACAGGTTGATGCCAATTGTGAAGGGGACTGCTATCATAGTGGAGGGACAATAATAAGTAACTTGCCATTTCAGAACATAGATAGCAGGGCAGTTGGAAAATGTCCGAGATATGTTAAGCAAAGGAGTCTGCTGCTAGCAACAGGGATGAAGAATGTTCCTGAGATTCCAAAAGGAAGAGGCCTATTTGGTGCTATAGCGGGTTTCATTGAAAATGGATGGGAAGGCCTAATTGATGGTTGGTATGGTTTCAGACACCAGAATGCACAGGGAGAGGGAACTGCTGCAGATTACAAAAGCACTCAATCGGCAATTGATCAAATAACAGGAAAATTAAACCGGCTTATAGAAAAAACCAACCAACAATTTGAGTTGATAGACAATGAATTCAATGAGGTAGAGAAGCAAATCGGTAATGTGATAAATTGGACCAGAGATTCTATAACAGAAGTGTGGTCATACAATGCTGAACTCTTGGTAGCAATGGAGAACCAGCATACAATTGATCTGGCTGATTCAGAAATGGACAAACTGTACGAACGAGTGAAAAGACAGCTGAGAGAGAATGCTGAAGAAGATGGCACTGGTTGCTTTGAAATATTTCACAAGTGTGATGATGACTGTATGGCCAGTATTAGAAATAACACCTATGATCACAGCAAATACAGGGAAGAGGCAATGCAAAATAGAATACAGATTGACCCAGTCAAACTAAGCAGCGGCTACAAAGATGTGATACTTTGGTTTAGCTTCGGGGCATCATGTTTCATACTTCTAGCCATTGTAATGGGCCTTGTCTTCATATGTGTAAAGAATGGAAACATGCGGTGCACTATTTGTATATAA",  # HA 1683 nt184        5: "ATGGCGTCTCAAGGCACCAAACGATCCTATGAACAGATGGAAACTGGTGGGGAACGCCAGAATGCTACTGAGATCAGGGCATCTGTTGGAAGAATGGTTAGCGGCATTGGGAGATTCTACATACAGATGTGTACAGAACTCAAACTCAGTGACAATGAAGGGAGGCTGATTCAGAACAGTATAACAATAGAGAGAATGGTACTCTCTGCATTTGATGAAAGAAGGAACAGATACCTGGAAGAGCACCCCAGTGCAGGAAAGGACCCTAAGAAAACTGGAGGTCCAATTTACAGGAGAAGAGACGGAAAATGGGTGAGAGAGCTGATCCTGTATGACAAAGAGGAAATCAGGAGAATTTGGCGACAAGCGAACAATGGAGAGGATGCAACTGCTGGTCTTACCCATCTGATGATATGGCATTCCAACCTGAATGATGCTACCTATCAGAGAACGAGAGCTCTCGTGCGTACTGGAATGGATCCCCGGATGTGCTCTCTGATGCAAGGATCAACTCTCCCGAGGAGATCTGGAGCTGCAGGTGCAGCAGTGAAGGGGATAGGGACAATGGTGATGGAACTGATTCGGATGATAAAACGAGGGATCAACGACCGGAATTTCTGGAGAGGCGAAAATGGAAGAAGGACAAGAATTGCATATGAGAGAATGTGCAACATCCTCAAAGGGAAATTCCAAACAGCAGCACAAAGGGCAATGATGGATCAAGTGCGAGAGAGCAGAAATCCTGGGAATGCTGAAATAGAAGATCTCATTTTTCTGGCAAGGTCTGCACTCATCCTGAGAGGATCAGTGGCTCATAAATCCTGCTTGCCTGCTTGTGTGTACGGACTTGCAGTGGCTAGTGGATATGACTTTGAGAGAGAAGGGTACTCCTTGGTTGGAATAGATCCTTTCCGTCTGCTTCAAAACAGCCAGGTCTTTAGTCTCATTAGACCAAATGAGAACCCAGCACATAAGAGCCAACTAGTGTGGATGGCATGCCACTCTGCAGCGTTTGAGGACCTTAGGGTCTCAAGTTTCATTAGAGGGACAAGAATGGTCCCAAGAGGACAGCTATCCACTAGAGGGGTTCAAATTGCTTCAAATGAGAACATGGAAGCAATGGACTCCAATACTCTTGAACTGAGAAGTAGATATTGGGCTATAAGAACCAGAAGCGGAGGGAACACCAACCAACAGAGGGCATCTGCAGGACAGGTCAGCGTTCAACCCACTTTCTCAGTACAGAGAAACCTTCCTTTCGAAAGAGCAACCATTATGGCAGCATTTACAGGAAATACTGAGGGTAGAACGTCTGACATGAGGACTGAAATCATAAGAATGATGGAAAGTGCCAGACCAGAAGATGTGTCATTCCAGGGGCGGGGAGTCTTCGAGCTCTCGGACGAAAAGGCAACGAACCCGATCGTGCCTTCCTTTGACATGAATAATGAAGGATCTTATTTCTTCGGAGACAATGCAGAGGAGTATGACAATTGA",  # NP 1497 nt185        6: "ATGAATCCAAATCAGAAGATTCTATGCACTTCAGCCACTGCTATCATAATAGGCGCAATCGCAGTACTCATTGGAATGGCAAACCTAGGATTGAACATAGGACTGCATCTAAAACCGGGCTGCAATTGCTCACACTCACAACCTGAAACAACCAACACAAGCCAAACAATAATAAACAACTATTATAATGAAACAAACATCACCAACATCCAAATGGAAGAGAGAACAAGCAGGAATTTCAATAACTTAACTAAAGGGCTCTGTACTATAAATTCATGGCACATATATGGGAAAGACAATGCAGTAAGAATTGGAGAGAGCTCGGATGTTTTAGTCACAAGAGAACCCTATGTTTCATGCGACCCAGATGAATGCAGGTTCTATGCTCTCAGCCAAGGAACAACAATCAGAGGGAAACACTCAAACGGAACAATACACGATAGGTCCCAGTATCGCGCCCTGATAAGCTGGCCACTATCATCACCGCCCACAGTGTACAACAGCAGGGTGGAATGCATTGGGTGGTCAAGTACTAGTTGCCATGATGGCAAATCCAGGATGTCAATATGTATATCAGGACCAAACAACAATGCATCTGCAGTAGTATGGTACAACAGAAGGCCTGTTGCAGAAATTAACACATGGGCCCGAAACATACTAAGAACACAGGAATCTGAATGTGTATGCCACAACGGCGTATGCCCAGTAGTGTTCACCGATGGGTCTGCCACTGGACCTGCAGACACAAGAATATACTATTTTAAAGAGGGGAAAATATTGAAATGGGAGTCTCTGACTGGAACTGCTAAGCATATTGAAGAATGCTCATGTTACGGGGAACGAACAGGAATTACCTGCACATGCAGGGACAATTGGCAGGGCTCAAATAGACCAGTGATTCAGATAGACCCAGTAGCAATGACACACACTAGTCAATATATATGCAGTCCTGTTCTTACAGACAATCCCCGACCGAATGACCCAAATATAGGTAAGTGTAATGACCCTTATCCAGGTAATAATAACAATGGAGTCAAGGGATTCTCATACCTGGATGGGGCTAACACTTGGCTAGGGAGGACAATAAGCACAGCCTCGAGGTCTGGATACGAGATGTTAAAAGTGCCAAATGCATTGACAGATGATAGATCAAAGCCCATTCAAGGTCAGACAATTGTATTAAACGCTGACTGGAGTGGTTACAGTGGATCTTTCATGGACTATTGGGCTGAAGGGGACTGCTATCGAGCGTGTTTTTATGTGGAGTTGATACGTGGAAGACCCAAGGAGGATAAAGTGTGGTGGACCAGCAATAGTATAGTATCGATGTGTTCCAGTACAGAATTCCTGGGACAATGGAACTGGCCTGATGGGGCTAAAATAGAGTACTTCCTCTAA",  # NA 1398 nt186        7: "ATGAGTCTTCTAACCGAGGTCGAAACGTACGTTCTCTCTATCATTCCATCAGGCCCCCTCAAAGCCGAGATCGCACAGAGACTTGAGGATGTTTTTGCAGGGAAGAACGCAGATCTCGAGGCTCTCATGGAGTGGATAAAGACAAGACCAATCCTGTCACCTCTGACTAAGGGGATTTTAGGGTTTGTGTTCACGCTCACCGTGCCCAGTGAGCGAGGACTGCAGCGTAGACGGTTTGTCCAAAACGCCCTAAATGGGAATGGAGACCCAAACAACATGGACAAGGCGGTTAAATTATACAAGAAACTGAAGAGGGAAATGACATTTCATGGAGCAAAGGAAGTTGCACTCAGTTACTCAACTGGTGCGCTTGCCAGCTGCATGGGTCTCATATACAACAGAATGGGGACTGTGACCGCAGAAGGGGCTCTTGGACTAGTATGTGCCACTTGTGAGCAGATTGCTGACGCACAACATCGGTCCCACAGGCAGATGGCGACTACTACTAACCCACTAATTAGGCATGAGAATAGAATGGTACTAGCCAGCACTACGGCTAAGGCTATGGAGCAGATGGCTGGATCAAGTGAACAGGCAGCGGAAGCCATGGAAGTTGCAAGTCAGGCTAGGCAAATGGTGCAGGCTATGAGAACAGTTGGGACTCACCCTAACTCCAGTACAGGTCTAAAAGATGATCTTATTGAAAATTTGCAGGCCTACCAGAACCGGATGGGAGTGCAACTGCAGCGGTTCAAGTGAGCCTCTAGTCGTTGCAGCTAACATTATTGGGATATTGCACTTGATATTGTGGATTCTTGATCGTCTTTTCTTCAAATGCATTTATCGTCGTTTTAAATACGGTTTGAAAAGAGGGCCTTCTACGGAAGGAATGCCTGAGTCTATGAGGGAAGAATATCGGCAGGAACAGCAGAATGCTGTGGATGTTGACGATGGTCATTTTGTCAACATAGAGCTGAAGTAA",  # M 982 nt187        8: "ATGGATTCCAATACTGTGTCAAGCTTCCAGGTAGACTGCTTTCTTTGGCATGTCCGCAAACGATTTGCAGACCAAGAAATGGGTGATGCCCCATTTCTAGACCGGCTTCGCCGAGATCAGAAGTCCCTGAGAGGAAGAAGCAGCACTCTTGGTCTGGACATCAGAACTGCCACGCGTGAAGGAAAGCATATAGTGGAGCGGATTTTAGAGGAAGAGTCAGATGAAGCATTTAAAATGAGTATTGCTTCAGTGCCAGCTCCACGCTATCTAACTGACATGACTCTTGAAGAAATGTCAAGAGATTGGTTAATGCTCATTCCCAAACAGAAAATAACAGGGTCCCTATGCATTAGAATGGACCAAGCAATAGTGGACAAAAACATCACATTGAAAGCAAATTTCAGTGTGATTTTCAATCGGCTTGAAGCCCTGATACTACTTAGAGCTTTTACGGAAGAAGGAGCAATTGTAGGCGAAATCTCACCATTACCTTCTCTTCCAGGACATACTGACAAGGATGTCAAAAATGCAATTGAGATCCTCATCGGAGGATTTGAATGGAATGATAACACAGTTCGAGTCTCTGAAACTCTACAGAGATTCGCTTGGAGAAGCAGCGATGAGGATGGGAGATCTCCACTCTCTACAAAGTAGAAACGGGAAATGGAGAGAACAGTTAAGCCAGAAGTTCGAAGAAATAAGATGGTTGATTGAAGAAGTACGACATAGATTAAAAATTACGGAGAATAGCTTTGAGCAAATAACTTTTATGCAAGCCTTACAACTATTGCTTGAAGTGGAGCAAGAGATAAGAACTTTCTCGTTTCAGCTTATTTAA",  # NS 838 nt188    },189}190 191# Maps friendly subtype name → RefSeq strain label192REFSEQ_SUBTYPE_MAP = {193    "H1N1": "H1N1_Cal07_2009",194    "H3N2": "H3N2_HK15609_2015",195    "H5N1": "H5N1_GullFr_2022",196    "H7N9": "H7N9_Shanghai_2013",197}198 199 200# ─── Segment autodetect + strain divergence functions ─────────────────────────201 202def _reverse_complement(seq: str) -> str:203    """Return reverse complement of a DNA sequence."""204    comp = str.maketrans("ACGTN", "TGCAN")205    return seq.upper().translate(comp)[::-1]206 207 208def _align_score(query: str, target: str) -> float:209    """210    Compute normalised alignment identity between query and target.211    Uses BioPython PairwiseAligner (local, DNA match/mismatch scoring).212    Returns identity fraction 0-1 relative to query length.213    Falls back to length-heuristic if BioPython unavailable.214    """215    if not _BIOPYTHON_OK or not query or not target:216        return 0.0217    try:218        aligner = _PairwiseAligner()219        aligner.mode            = "local"220        aligner.match_score     = 1221        aligner.mismatch_score  = -1222        aligner.open_gap_score  = -2223        aligner.extend_gap_score = -0.5224        score = aligner.score(query.upper(), target.upper())225        return float(score) / max(len(query), 1)226    except Exception:227        return 0.0228 229 230@st.cache_data(show_spinner=False)231def detect_segment(query: str, _cache_v: int = 3) -> dict | None:232    """233    Identify the most likely IAV segment for an input sequence. v3: cache bust.234    Returns dict with keys: seg_num, seg_name, strain_label, subtype, identity, ambiguous235    or None if no reasonable match found.236 237    Uses two-stage approach:238      1. Length filter — only align against segments within ±40% length of query239      2. PairwiseAligner (local, uncached) — pick highest normalised identity240    Reports ambiguous=True if top-2 scores are within 5 pp of each other.241    """242    if not _BIOPYTHON_OK or not query or len(query) < 100:243        return None244 245    query_clean = query.upper().replace("U", "T")246    qlen = len(query_clean)247 248    # Length-based candidate filter249    seg_lengths = {1:2341, 2:2341, 3:2233, 4:1778, 5:1565, 6:1413, 7:1027, 8:890}250    seg_name_map = {1:"PB2",2:"PB1",3:"PA",4:"HA",5:"NP",6:"NA",7:"M",8:"NS"}251 252    best_results = []  # (score, seg_num, strain_label, subtype)253    is_rc = False254 255    for subtype, strain_label in REFSEQ_SUBTYPE_MAP.items():256        strain_segs = REFSEQ_DB.get(strain_label, {})257        for seg_num, ref_seq in strain_segs.items():258            ref_len = len(ref_seq)259            # Skip segments whose length differs by >40% from query260            if abs(ref_len - qlen) / max(ref_len, qlen) > 0.40:261                continue262            score = _align_score(query_clean, ref_seq)263            best_results.append((score, seg_num, strain_label, subtype))264 265    if not best_results:266        return None267 268    best_results.sort(reverse=True)269    top_score, top_seg, top_strain, top_subtype = best_results[0]270 271    if top_score < 0.30:272        # Forward orientation failed — try reverse complement (handles negative-sense vRNA input)273        query_rc = _reverse_complement(query_clean)274        rc_results = []275        for subtype, strain_label in REFSEQ_SUBTYPE_MAP.items():276            strain_segs = REFSEQ_DB.get(strain_label, {})277            for seg_num, ref_seq in strain_segs.items():278                ref_len = len(ref_seq)279                if abs(ref_len - qlen) / max(ref_len, qlen) > 0.40:280                    continue281                score = _align_score(query_rc, ref_seq)282                rc_results.append((score, seg_num, strain_label, subtype))283 284        if rc_results:285            rc_results.sort(reverse=True)286            rc_top = rc_results[0][0]287            if rc_top >= 0.30:288                best_results = rc_results  # use RC results289                top_score, top_seg, top_strain, top_subtype = rc_results[0]290                # Mark as RC-detected for downstream use291                is_rc = True292            else:293                return None  # neither orientation matched294        else:295            return None296 297    # Check ambiguity: PB2 vs PB1 are both ~2341 nt and can confuse alignment298    ambiguous = False299    if len(best_results) > 1:300        second_score = best_results[1][0]301        if (top_score - second_score) < 0.05 and best_results[1][1] != top_seg:302            ambiguous = True303 304    # Map seg_num → IAV_SEGMENTS key305    seg_key_map = {306        1: "PB2 (Seg 1, ~2341 nt)", 2: "PB1 (Seg 2, ~2341 nt)",307        3: "PA (Seg 3, ~2233 nt)",  4: "HA (Seg 4, ~1778 nt)",308        5: "NP (Seg 5, ~1565 nt)",  6: "NA (Seg 6, ~1413 nt)",309        7: "M (Seg 7, ~1027 nt)",   8: "NS (Seg 8, ~890 nt)",310    }311 312    return {313        "seg_num":     top_seg,314        "seg_name":    seg_name_map[top_seg],315        "seg_key":     seg_key_map.get(top_seg),316        "strain_label": top_strain,317        "subtype":     top_subtype,318        "identity":    top_score,319        "ambiguous":   ambiguous,320        "is_rc":       is_rc,321        "all_results": best_results[:4],322    }323 324 325@st.cache_data(show_spinner=False)326def check_strain_divergence(query: str, seg_num: int, _cache_v: int = 2) -> list[dict]:327    """328    For a given query sequence and known segment, score it against all 4 subtypes329    and return divergence results sorted by identity descending.330    Flags segments where gray zone regions may have diverged.331    """332    if not query or seg_num not in range(1, 9):333        return []334 335    query_clean = query.upper().replace("U", "T")336    results = []337 338    for subtype, strain_label in REFSEQ_SUBTYPE_MAP.items():339        strain_segs = REFSEQ_DB.get(strain_label, {})340        ref_seq = strain_segs.get(seg_num)341        if not ref_seq:342            continue343        score = _align_score(query_clean, ref_seq)344        results.append({345            "subtype":      subtype,346            "strain_label": strain_label,347            "identity":     score,348        })349 350    results.sort(key=lambda x: x["identity"], reverse=True)351    return results352 353 354# Maps IAV_SEGMENTS selectbox key → integer segment number355SEG_CHOICE_TO_NUM: dict[str, int | None] = {356    "PB2 (Seg 1, ~2341 nt)": 1,357    "PB1 (Seg 2, ~2341 nt)": 2,358    "PA (Seg 3, ~2233 nt)":  3,359    "HA (Seg 4, ~1778 nt)":  4,360    "NP (Seg 5, ~1565 nt)":  5,361    "NA (Seg 6, ~1413 nt)":  6,362    "M (Seg 7, ~1027 nt)":   7,363    "NS (Seg 8, ~890 nt)":   8,364    "Custom / Unknown":       None,365}366 367# ─── Conservation scoring functions ───────────────────────────────────────────368 369@st.cache_data(show_spinner=False)370def compute_per_position_conservation(371    query: str, seg_num: int, strain_filter: list | None = None372) -> np.ndarray:373    """374    Per-position conservation of a query sequence against selected RefSeq strains.375    strain_filter: list of strain label keys to include (default: all 4).376    Returns fraction of included strains sharing the same base at each aligned position.377    Falls back to uniform 0.5 if BioPython unavailable or alignment fails.378    """379    if not _BIOPYTHON_OK or not query or seg_num is None:380        return np.ones(len(query)) * 0.5381 382    query_clean = query.upper().replace("U", "T")383    n = len(query_clean)384    match_counts = np.zeros(n, dtype=float)385    cover_counts = np.zeros(n, dtype=float)386 387    # Build subtype→label map filtered to requested strains388    _active_strains = {389        sub: lbl for sub, lbl in REFSEQ_SUBTYPE_MAP.items()390        if strain_filter is None or lbl in strain_filter391    }392    if not _active_strains:393        return np.ones(n) * 0.5394 395    for subtype, strain_label in _active_strains.items():396        ref_seq = REFSEQ_DB.get(strain_label, {}).get(seg_num, "")397        if not ref_seq:398            continue399        ref_clean = ref_seq.upper().replace("U", "T")400        try:401            aligner = _PairwiseAligner()402            aligner.mode             = "global"403            aligner.match_score      = 1404            aligner.mismatch_score   = -1405            aligner.open_gap_score   = -2406            aligner.extend_gap_score = -0.1407            aln = next(iter(aligner.align(query_clean, ref_clean)))408            q_blocks, r_blocks = aln.aligned409            for (qs, qe), (rs, re) in zip(q_blocks, r_blocks):410                for k in range(qe - qs):411                    qi, ri = qs + k, rs + k412                    if qi < n and ri < len(ref_clean):413                        cover_counts[qi] += 1414                        if query_clean[qi] == ref_clean[ri]:415                            match_counts[qi] += 1416        except Exception:417            continue418 419    conservation = np.where(cover_counts > 0, match_counts / cover_counts, 0.5)420 421    # If overall coverage is very low, try reverse complement (negative-sense input)422    mean_cover = float(cover_counts.mean())423    if mean_cover < 0.3:424        query_rc = _reverse_complement(query_clean)425        match_rc = np.zeros(n, dtype=float)426        cover_rc = np.zeros(n, dtype=float)427        for subtype, strain_label in _active_strains.items():428            ref_seq = REFSEQ_DB.get(strain_label, {}).get(seg_num, "")429            if not ref_seq:430                continue431            ref_clean = ref_seq.upper().replace("U", "T")432            try:433                aligner = _PairwiseAligner()434                aligner.mode = "global"435                aligner.match_score = 1; aligner.mismatch_score = -1436                aligner.open_gap_score = -2; aligner.extend_gap_score = -0.1437                aln = next(iter(aligner.align(query_rc, ref_clean)))438                q_blocks, r_blocks = aln.aligned439                for (qs, qe), (rs, re) in zip(q_blocks, r_blocks):440                    for k in range(qe - qs):441                        qi, ri = qs + k, rs + k442                        if qi < n and ri < len(ref_clean):443                            cover_rc[qi] += 1444                            if query_rc[qi] == ref_clean[ri]:445                                match_rc[qi] += 1446            except Exception:447                continue448        if float(cover_rc.mean()) > mean_cover:449            # RC gave better coverage — flip back to original orientation450            cons_rc = np.where(cover_rc > 0, match_rc / cover_rc, 0.5)451            conservation = cons_rc[::-1]  # reverse to match original query positions452 453    return conservation454 455 456def get_window_conservation(cons_arr: np.ndarray, win: int, n_windows: int) -> np.ndarray:457    """Sliding-window mean of per-position conservation, length = n_windows."""458    n = len(cons_arr)459    result = np.zeros(n_windows, dtype=float)460    for i in range(n_windows):461        end = min(i + win, n)462        result[i] = float(np.mean(cons_arr[i:end])) if end > i else 0.5463    return result464 465 466def apply_conservation_weighting(467    df: pd.DataFrame, win_cons: np.ndarray, alpha: float468) -> pd.DataFrame:469    """470    Returns df copy with 'score_cons' and 'conservation' columns added.471    score_cons = score × (alpha × win_cons + (1 - alpha))472    alpha=0 → pure accessibility; alpha=1 → fully conservation-weighted.473    """474    df2 = df.copy()475    blend = alpha * win_cons + (1.0 - alpha)476    df2["score_cons"]  = np.clip(df2["score"].values * blend, 0.0, 1.0).round(4)477    df2["conservation"] = np.round(win_cons, 4)478    return df2479 480 481# ─── Gray Zone definitions ────────────────────────────────────────────────────482# Mirska et al. (2023) PMC10153785483# strict  = tighter, experimentally best-supported boundaries484# permissive = wider, conservative / avoid-if-possible zones485 486IAV_SEGMENTS = {487    "PB2 (Seg 1, ~2341 nt)": {488        "length": 2341,489        "strict":     {"pkg_5p": (1,100),  "pkg_3p": (2241,2341), "promo_5p": (1,16),  "promo_3p": (2326,2341), "splice": [], "splice_spans": []},490        "permissive": {"pkg_5p": (1,150),  "pkg_3p": (2192,2341), "promo_5p": (1,20),  "promo_3p": (2321,2341), "splice": [], "splice_spans": []},491        "universal_motifs": [],492        "notes": "No known splice sites. PB2 cap-binding domain (318–483) is structurally constrained.",493    },494    "PB1 (Seg 2, ~2341 nt)": {495        "length": 2341,496        "strict":     {"pkg_5p": (1,100),  "pkg_3p": (2241,2341), "promo_5p": (1,16),  "promo_3p": (2326,2341), "splice": [], "splice_spans": []},497        "permissive": {"pkg_5p": (1,150),  "pkg_3p": (2192,2341), "promo_5p": (1,20),  "promo_3p": (2321,2341), "splice": [], "splice_spans": []},498        "universal_motifs": [],499        "notes": "PB1-F2 ORF overlaps nt 87–358. Frameshift-prone region.",500    },501    "PA (Seg 3, ~2233 nt)": {502        "length": 2233,503        "strict":     {"pkg_5p": (1,100),  "pkg_3p": (2133,2233), "promo_5p": (1,16),  "promo_3p": (2218,2233), "splice": [], "splice_spans": []},504        "permissive": {"pkg_5p": (1,150),  "pkg_3p": (2084,2233), "promo_5p": (1,20),  "promo_3p": (2213,2233), "splice": [], "splice_spans": []},505        "universal_motifs": [],506        "notes": "PA-X frameshift site ~nt 191 (X-ORF overlaps PA nt 1–191).",507    },508    "HA (Seg 4, ~1778 nt)": {509        "length": 1778,510        "strict":     {"pkg_5p": (1,100),  "pkg_3p": (1678,1778), "promo_5p": (1,16),  "promo_3p": (1763,1778), "splice": [], "splice_spans": []},511        "permissive": {"pkg_5p": (1,150),  "pkg_3p": (1629,1778), "promo_5p": (1,20),  "promo_3p": (1758,1778), "splice": [], "splice_spans": []},512        "universal_motifs": [],513        "notes": "HA cleavage site (324–330) is functionally critical. Subtype-dependent.",514    },515    "NP (Seg 5, ~1565 nt)": {516        "length": 1565,517        "strict":     {"pkg_5p": (1,70),   "pkg_3p": (1496,1565), "promo_5p": (1,16),  "promo_3p": (1550,1565), "splice": [], "splice_spans": []},518        "permissive": {"pkg_5p": (1,100),  "pkg_3p": (1466,1565), "promo_5p": (1,20),  "promo_3p": (1545,1565), "splice": [], "splice_spans": []},519        "universal_motifs": [(87, 115), (1527, 1550)],520        # 87–115:    Hairpin motif, predicted in all in virio and in cellulo environments.521        # 1527–1550: Terminal signal hairpin, overlaps 3′ packaging region in strict mode.522        # Mirska 2023 Table 5; Michalak 2019 (PMC6406010) vRNA5 structural context.523        "notes": (524            "Universal motifs at 87–115 (conserved hairpin) and 1527–1550 "525            "(terminal signal; overlaps 3′ pkg in strict mode → Constrained). "526            "Terminal panhandle: 1–16 / 1551–1565."527        ),528    },529    "NA (Seg 6, ~1413 nt)": {530        "length": 1413,531        "strict":     {"pkg_5p": (1,70),   "pkg_3p": (1343,1413), "promo_5p": (1,16),  "promo_3p": (1398,1413), "splice": [], "splice_spans": []},532        "permissive": {"pkg_5p": (1,100),  "pkg_3p": (1314,1413), "promo_5p": (1,20),  "promo_3p": (1393,1413), "splice": [], "splice_spans": []},533        "universal_motifs": [],534        "notes": "NA stalk length varies by strain; stalk-encoding region (51–180) may be constrained.",535    },536    "M (Seg 7, ~1027 nt)": {537        "length": 1027,538        "strict":     {"pkg_5p": (1,100),  "pkg_3p": (927,1027),  "promo_5p": (1,16),  "promo_3p": (1012,1027), "splice": [(51,740)],  "splice_spans": []},539        "permissive": {"pkg_5p": (1,150),  "pkg_3p": (878,1027),  "promo_5p": (1,20),  "promo_3p": (1007,1027), "splice": [(41,750)],  "splice_spans": [(41,750)]},540        "universal_motifs": [(35, 60), (144, 166), (339, 355), (788, 809)],541        # 35–60:   Near M2 ion-channel start; predicted in all environments/strains.542        # 144–166: Internal hairpin, highly conserved sequence and structure.543        # 339–355: Internal motif, all environments; often outside splice region.544        # 788–809: Overlaps splice acceptor (~740); Constrained in both GZ modes.545        # Mirska 2023 Table 6.546        "notes": (547            "M1/M2 splice: donor ~51, acceptor ~740. M2 ion channel initiates at nt 26. "548            "Permissive mode flags full intronic span (41–750). "549            "Universal motifs at 35–60, 144–166, 339–355, and 788–809 (Mirska 2023). "550            "788–809 overlaps splice acceptor → Constrained."551        ),552    },553    "NS (Seg 8, ~890 nt)": {554        "length": 890,555        "strict":     {"pkg_5p": (1,70),   "pkg_3p": (820,890),   "promo_5p": (1,16),  "promo_3p": (875,890),   "splice": [(30,502)],  "splice_spans": []},556        "permissive": {"pkg_5p": (1,100),  "pkg_3p": (791,890),   "promo_5p": (1,20),  "promo_3p": (870,890),   "splice": [(20,512)],  "splice_spans": [(20,512)]},557        "universal_motifs": [(261, 287), (312, 327)],558        # 261–287: Intronic hairpin; both motifs fall within the NS1/NEP splice region559        # 312–327: (donor ~30, acceptor ~502), so both are Constrained in all modes.560        # Mirska 2023 Table 7.561        "notes": (562            "NS1/NEP splice: donor ~30, acceptor ~502. "563            "Permissive mode flags full intronic span (20–512). "564            "Universal motifs at 261–287 and 312–327 (Mirska 2023); "565            "both are intronic → Constrained in all Gray Zone modes."566        ),567    },568    "Custom / Unknown": {569        "length": None,570        "strict":     {"pkg_5p": None, "pkg_3p": None, "promo_5p": None, "promo_3p": None, "splice": [], "splice_spans": []},571        "permissive": {"pkg_5p": None, "pkg_3p": None, "promo_5p": None, "promo_3p": None, "splice": [], "splice_spans": []},572        "universal_motifs": [],573        "notes": "No Gray Zone overlay applied.",574    },575}576 577GRAY_ZONE_MODE_HELP = """578**Strict mode** applies only the core, experimentally validated occluded regions:579the innermost packaging signals (~70–100 nt per end) and splice sites with tight580boundaries (±10 nt around donor/acceptor sites only).581Use this for targeted screening where you want to rule out only the most problematic582positions with strong experimental support.583 584**Permissive mode** applies wider, more conservative boundaries:585- Packaging signals: +50 nt per end (accounts for strain-to-strain variation, particularly586  relevant for HPAI H5N1 where packaging signal boundaries may differ from H1N1/H3N2).587- Splice donor/acceptor windows: ±20 nt.588- Full intronic span (donor to acceptor): flagged for Seg 7 (M, ~41–750 nt) and589  Seg 8 (NS, ~20–512 nt), because the splicing machinery occupies this region.590Use permissive mode when designing guides intended for broad-spectrum activity591across multiple IAV subtypes or clades.592 593**Structural basis:** The terminal packaging signals adopt conserved panhandle and594stem-loop structures that are physically inaccessible to Cas13d regardless of595thermodynamic predictions from single-sequence folding. The 5′/3′ promoter panhandle596(first and last ~13–16 nt) forms an imperfect RNA duplex essential for RdRp binding.597*(Mirska et al. Nucleic Acids Res. 2023; Gavazzi et al. Nucleic Acids Res. 2013)*598 599Both modes apply a 30% score penalty to guides overlapping a Gray Zone.600"""601 602# ─── Sequence utilities ───────────────────────────────────────────────────────603 604def clean_rna(raw: str) -> str:605    s = raw.upper().replace("T", "U")606    return "".join(c for c in s if c in "ACGU")607 608 609def parse_input(text: str, fasta_bytes: bytes | None) -> tuple[str, str]:610    """611    Returns (sequence, label).612    Priority: FASTA file > FASTA-formatted text > raw sequence text.613    """614    if fasta_bytes is not None and SeqIO is not None:615        records = list(SeqIO.parse(io.StringIO(fasta_bytes.decode("utf-8", errors="replace")), "fasta"))616        if records:617            rec = records[0]618            return clean_rna(str(rec.seq)), rec.description619    if text.strip().startswith(">") and SeqIO is not None:620        records = list(SeqIO.parse(io.StringIO(text.strip()), "fasta"))621        if records:622            rec = records[0]623            return clean_rna(str(rec.seq)), rec.description624    return clean_rna(text), "User sequence"625 626# ─── Core computation ─────────────────────────────────────────────────────────627 628# ─── SHAPE data loader ────────────────────────────────────────────────────────629 630@st.cache_data(show_spinner=False)631def load_mirska_shape_data(path: str) -> dict:632    """633    Parse per-nucleotide NAI (SHAPE) reactivities from Mirska et al. 2023 MOESM1.634    Returns dict: {(seg_num: int, context: str): tuple of floats (1-indexed; index 0 = 0.0 sentinel)}.635    context is 'in_cellulo' or 'in_virio'.636    Missing/excluded values (-999) → -1.0 (ViennaRNA ignores negatives as "no data").637    Only includes in cellulo data for segments with ≥99% valid coverage (5, 7, 8).638    """639    if not path or not os.path.exists(path):640        return {}641    try:642        import openpyxl as _opxl643        wb = _opxl.load_workbook(path, read_only=True, data_only=True)644    except Exception:645        return {}646 647    sheet_map = {648        "Table2 in virio MaP":     "in_virio",649        "Table 3. in cellulo MaP": "in_cellulo",650    }651    result = {}652 653    for sheet_name, context in sheet_map.items():654        if sheet_name not in wb.sheetnames:655            continue656        ws = wb[sheet_name]657        segs = {i: [] for i in range(1, 9)}658 659        for row in ws.iter_rows(min_row=5, values_only=True):660            if row is None:661                break662            for seg_idx in range(8):663                seg_num = seg_idx + 1664                base    = seg_idx * 11665                nt = row[base]666                if nt is None:667                    continue668                # Column layout per segment block (0-based within block):669                # 0=nt, 1=pos_DMS, 2=DMS_r1, 3=DMS_r2, 4=DMS_r3, 5=DMS_avg,670                # 6=pos_NAI, 7=NAI_r1, 8=NAI_r2, 9=NAI_r3, 10=NAI_avg671                nai = row[base + 10]672                if nai is None or (isinstance(nai, (int, float)) and nai <= -900):673                    nai = -1.0674                segs[seg_num].append(float(nai))675 676        for seg_num, vals in segs.items():677            if not vals:678                continue679            # Restrict in cellulo to segments with full coverage680            if context == "in_cellulo" and seg_num not in SHAPE_IN_CELLULO_SEGS:681                continue682            # Prepend sentinel so index 1 == nucleotide position 1683            result[(seg_num, context)] = tuple([0.0] + vals)684 685    return result686 687 688def _find_shape_file() -> str:689    """Return first existing path from the default search list, else ''."""690    for p in _DEFAULT_SHAPE_PATHS:691        if p and os.path.exists(p):692            return p693    return ""694 695 696def get_shape_for_segment(697    seg_num: int | None,698    best_identity: float,699    shape_data: dict,700) -> tuple[tuple | None, str, str]:701    """702    Resolve SHAPE reactivities for a detected segment.703 704    Returns (reactivities_tuple | None, context_used, message).705    Prefers in_cellulo; falls back to in_virio.706    Returns (None, '', caveat_message) if data is unavailable or identity too low.707    """708    if not shape_data or seg_num is None:709        return None, "", (710            "SHAPE constraint data not loaded. "711            "Place the Mirska et al. 2023 MOESM1 xlsx alongside app.py, or set the "712            "MIRSKA_SHAPE_PATH environment variable."713        )714    if best_identity < SHAPE_MIN_IDENTITY:715        return None, "", (716            f"Sequence identity to H1N1 reference is {best_identity*100:.0f}%, below the "717            f"{SHAPE_MIN_IDENTITY*100:.0f}% threshold for reliable SHAPE constraint transfer "718            f"from A/California/04/2009. Running unconstrained ViennaRNA."719        )720    for ctx in ["in_cellulo", "in_virio"]:721        key = (seg_num, ctx)722        if key in shape_data:723            if ctx == "in_cellulo":724                msg = (725                    "✅ **In cellulo SHAPE constraints active** (Mirska et al. 2023, "726                    "A/California/04/2009 H1N1). Reactivities reflect RNA structure inside "727                    "infected cells, implicitly accounting for NP-vRNP occlusion. "728                    "The *RNP occlusion* limitation listed in the methods panel is "729                    "substantially mitigated for this segment."730                )731            else:732                msg = (733                    "⚠️ **In virio SHAPE constraints active** (Mirska et al. 2023, "734                    "A/California/04/2009 H1N1). In cellulo data is unavailable for "735                    f"segment {seg_num}. Reactivities reflect vRNA structure inside purified "736                    "virions; NP-vRNP occlusion in infected cells is **not** captured. "737                    "Accessibility at internal regions may be slightly overestimated."738                )739            return shape_data[key], ctx, msg740 741    return None, "", (742        f"SHAPE data not found for segment {seg_num} in the loaded dataset."743    )744 745 746def _score_window_ed(args: tuple) -> tuple[int, float]:747    """Per-window ensemble defect. Designed for parallel execution."""748    i, w_seq, temperature = args749    md = RNA.md()750    md.temperature = float(temperature)751    fc_w = RNA.fold_compound(w_seq, md)752    ss_w, mfe_w = fc_w.mfe()753    fc_w.exp_params_rescale(mfe_w)754    fc_w.pf()755    return i, float(fc_w.ensemble_defect(ss_w))756 757 758@st.cache_data(show_spinner=False)759def compute_accessibility(760    seq: str,761    win: int = DEFAULT_WIN,762    temperature: float = 37.0,763    shape_reactivities: tuple | None = None,764) -> pd.DataFrame:765    """766    Full sliding-window accessibility pipeline.767 768    Returns DataFrame: position, pu, entropy, ensemble_defect, score.769    For sequences > LONG_SEQ_THRESH nt, ensemble defect is subsampled770    and interpolated; Pu and entropy are computed for every position.771 772    When shape_reactivities is provided (tuple, 1-indexed, −1.0 = missing):773      - SHAPE pseudo-energy soft constraints are applied to the ViennaRNA774        fold_compound before the partition function call.775      - Pᵤ is recomputed from the SHAPE-constrained BPP matrix instead of776        pfl_fold_up (for sequences ≤ SHAPE_LONG_SEQ_THRESH nt).777      - The raised SHAPE_LONG_SEQ_THRESH (1700 nt) allows segments 5/7/8 to778        benefit from full constrained PF.779    """780    n = len(seq)781    if n < win:782        return pd.DataFrame()783 784    # Use a higher threshold when SHAPE constraints are active so that785    # segments 5 (1565 nt), 7, and 8 get full SHAPE-constrained PF.786    _long_thresh = SHAPE_LONG_SEQ_THRESH if shape_reactivities is not None else LONG_SEQ_THRESH787    is_long = n > _long_thresh788 789    # ── Windowed Pu via pfl_fold_up (unconstrained baseline) ─────────────────790    # pfl_fold_up does not accept model details in this ViennaRNA build —791    # set the global temperature before the call and restore afterward.792    # When SHAPE is active and seq is short enough, this is overridden below793    # by the SHAPE-constrained BPP-derived Pu.794    W = min(PLFOLD_W, n)795    L = min(PLFOLD_L, W // 2)796    _prev_temp = RNA.cvar.temperature797    RNA.cvar.temperature = float(temperature)798    pu_raw = RNA.pfl_fold_up(seq, 1, W, L)799    RNA.cvar.temperature = _prev_temp800 801    def _safe_pu(entry) -> float:802        """ViennaRNA returns None at some terminal positions depending on version."""803        try:804            return float(entry[1])805        except (TypeError, IndexError, ValueError):806            return 0.0807 808    pu = [_safe_pu(pu_raw[i]) if i < len(pu_raw) else 0.0 for i in range(1, n + 1)]809 810    # Structural entropy811    # For short sequences: full partition function + BPP (accurate).812    # For long sequences (>_long_thresh): binary entropy from Pu — avoids813    # O(n³) partition function which times out on CPU for sequences >~1700 nt.814    if not is_long:815        _md_fc = RNA.md()816        _md_fc.temperature = float(temperature)817        fc = RNA.fold_compound(seq, _md_fc)818 819        # Apply SHAPE soft constraints when available820        _shape_applied = False821        if shape_reactivities is not None and len(shape_reactivities) > n:822            try:823                # ViennaRNA expects a list; index 0 ignored, indices 1..n used.824                sr = list(shape_reactivities[: n + 1])825                while len(sr) <= n:826                    sr.append(-1.0)827                fc.sc_add_SHAPE_reactivity(sr, SHAPE_M, SHAPE_B)828                _shape_applied = True829            except Exception:830                pass  # fall back silently to unconstrained831 832        ss_mfe, mfe = fc.mfe()833        fc.exp_params_rescale(mfe)834        fc.pf()835        bpp = fc.bpp()836 837        # When SHAPE constraints were applied, override Pu from the838        # constrained BPP matrix (more accurate than pfl_fold_up).839        if _shape_applied:840            pu = [841                max(0.0, min(1.0, 1.0 - sum(bpp[i][j] for j in range(1, n + 1) if j != i)))842                for i in range(1, n + 1)843            ]844 845        def _pos_entropy(i: int) -> float:846            paired = sum(bpp[i][j] for j in range(1, n + 1) if j != i)847            pu_i   = max(1e-10, min(1.0, 1.0 - paired))848            s      = sum(-bpp[i][j] * np.log10(bpp[i][j]) for j in range(1, n + 1) if bpp[i][j] > 1e-10)849            s     -= pu_i * np.log10(pu_i)850            return s851 852        raw_ent = [_pos_entropy(i) for i in range(1, n + 1)]853    else:854        # Binary entropy H(p) = -p·log2(p) - (1-p)·log2(1-p), normalised to 0-1.855        # Computed directly from pfl_fold_up Pu values — no BPP matrix needed.856        # SHAPE constraints are not applied to pfl_fold_up (API limitation), so857        # long sequences use the unconstrained Pu/entropy approximation.858        import math as _math859        def _binary_entropy(p: float) -> float:860            p = max(1e-10, min(1.0 - 1e-10, p))861            return -p * _math.log2(p) - (1.0 - p) * _math.log2(1.0 - p)862        raw_ent = [_binary_entropy(pu[i - 1]) for i in range(1, n + 1)]863 864    S_max  = max(raw_ent) if max(raw_ent) > 0 else 1.0865    S_norm = [s / S_max for s in raw_ent]866 867    # Ensemble defect: parallel, subsampled if long868    all_positions = list(range(n - win + 1))869    if is_long:870        sampled_pos = list(range(0, n - win + 1, SUBSAMPLE_STEP))871    else:872        sampled_pos = all_positions873 874    windows = [(i, seq[i: i + win], temperature) for i in sampled_pos]875    ed_map  = {}876    with concurrent.futures.ThreadPoolExecutor(max_workers=PARALLEL_WORKERS) as ex:877        for i, ed in ex.map(_score_window_ed, windows):878            ed_map[i] = ed879 880    # Interpolate ED for skipped positions881    if is_long and sampled_pos:882        sampled_arr = np.array(sampled_pos)883        ed_arr      = np.array([ed_map[p] for p in sampled_pos])884        full_arr    = np.array(all_positions)885        ed_interp   = np.interp(full_arr, sampled_arr, ed_arr)886        for idx, pos in enumerate(all_positions):887            ed_map[pos] = float(ed_interp[idx])888 889    # Assemble rows890    rows = []891    for i in all_positions:892        end      = i + win893        win_pu   = float(np.mean(pu[i:end]))894        win_entr = float(np.mean(S_norm[i:end]))895        score    = (1.0 - win_entr) * win_pu896        rows.append({897            "position":        i + 1,898            "pu":              round(win_pu,   4),899            "entropy":         round(win_entr, 4),900            "ensemble_defect": round(ed_map.get(i, 0.0), 4),901            "score":           round(score,    4),902            "ed_interpolated": is_long and (i not in set(sampled_pos)),903        })904 905    return pd.DataFrame(rows)906 907# ─── Gray Zone / Critical Feature logic ──────────────────────────────────────908 909def get_gz_regions(seg_info: dict, mode: str) -> dict:910    return seg_info.get(mode, seg_info.get("strict", {}))911 912 913# Maps gz dict keys → (short label for Gray Zone column, long label for Critical Feature column)914_GZ_FEATURE_LABELS = {915    "pkg_5p":   ("5′ Packaging Signal",    "5′ Packaging Signal (vRNP assembly)"),916    "pkg_3p":   ("3′ Packaging Signal",    "3′ Packaging Signal (vRNP assembly)"),917    "promo_5p": ("5′ Promoter/Panhandle",  "5′ Promoter/Panhandle (RdRp binding)"),918    "promo_3p": ("3′ Promoter/Panhandle",  "3′ Promoter/Panhandle (RdRp binding)"),919}920 921 922def is_in_gray_zone(pos: int, win: int, gz: dict) -> tuple[bool, list[str]]:923    """Returns (in_gz, [short_reason, ...]) for Gray Zone overlap."""924    end     = pos + win - 1925    reasons = []926 927    def overlaps(region) -> bool:928        return region is not None and not (end < region[0] or pos > region[1])929 930    for key, (short_label, _) in _GZ_FEATURE_LABELS.items():931        if overlaps(gz.get(key)):932            reasons.append(short_label)933 934    for ss_pair in gz.get("splice", []):935        for site in ss_pair:936            if overlaps((site - 10, site + 10)):937                reasons.append(f"Splice Site (~{site} nt)")938 939    for span in gz.get("splice_spans", []):940        if overlaps(span):941            lbl = f"Intronic/Spliced Region ({span[0]}–{span[1]} nt)"942            if not any("Splice Site" in r and str(span[0]) in r for r in reasons):943                reasons.append(lbl)944 945    return len(reasons) > 0, reasons946 947 948def get_critical_features(949    pos: int,950    win: int,951    gz: dict,952    universal_motifs: list[tuple[int, int]],953) -> str:954    """955    Returns a comma-separated string of all critical functional features956    overlapping this guide window. Covers Gray Zone elements AND universal957    structural motifs regardless of whether they fall inside a Gray Zone.958 959    This is the primary annotation for the 'critical_feature' column.960    A non-empty value means the guide targets a functionally important element —961    which is a POSITIVE signal when combined with high accessibility.962    """963    end      = pos + win - 1964    features = []965 966    def overlaps(region) -> bool:967        return region is not None and not (end < region[0] or pos > region[1])968 969    # Gray Zone elements (long labels)970    for key, (_, long_label) in _GZ_FEATURE_LABELS.items():971        if overlaps(gz.get(key)):972            features.append(long_label)973 974    for ss_pair in gz.get("splice", []):975        for site in ss_pair:976            if overlaps((site - 10, site + 10)):977                features.append(f"Splice Site (~{site} nt)")978 979    for span in gz.get("splice_spans", []):980        if overlaps(span):981            lbl = f"Intronic/Spliced Span ({span[0]}–{span[1]} nt)"982            if not any("Splice Site" in f and str(span[0]) in f for f in features):983                features.append(lbl)984 985    # Universal structural motifs (always annotated, even outside Gray Zones)986    for s, e in universal_motifs:987        if not (end < s or pos > e):988            features.append(f"Conserved Structural Motif ({s}–{e} nt)")989 990    return ", ".join(features)991 992 993def calc_gz_penalty(994    pos: int,995    win: int,996    gz: dict,997    shape_context: str,998    shape_reactivities: tuple | None,999) -> tuple[float, str]:1000    """1001    Compute the Gray Zone penalty fraction for this guide window.1002 1003    Returns (penalty_fraction, explanation_string).1004 1005    Logic:1006    - in_cellulo SHAPE active  → 0.00 (score already reflects in-cell accessibility)1007    - in_virio SHAPE active    → scaled by mean(1 − NAI) in window, capped at1008                                  GZ_PENALTY_IN_VIRIO; positions with missing data1009                                  (−1.0) are excluded from the mean.1010    - No SHAPE                 → flat GZ_PENALTY_NO_SHAPE prior1011    - Not in a Gray Zone       → 0.001012    """1013    in_gz, _ = is_in_gray_zone(pos, win, gz)1014    if not in_gz:1015        return 0.0, ""1016 1017    if shape_context == "in_cellulo":1018        return GZ_PENALTY_IN_CELLULO, (1019            "No penalty — in cellulo SHAPE constraints active; "1020            "in-cell accessibility already captured in score."1021        )1022 1023    if shape_context == "in_virio" and shape_reactivities is not None:1024        # Mean NAI reactivity over the guide window (skip missing −1.0 values)1025        window_reactivities = [1026            shape_reactivities[i]1027            for i in range(pos, min(pos + win, len(shape_reactivities)))1028            if shape_reactivities[i] >= 01029        ]1030        if window_reactivities:1031            mean_nai = sum(window_reactivities) / len(window_reactivities)1032            # Scale: high NAI (open) → low penalty; low NAI (closed) → higher penalty1033            penalty = round(GZ_PENALTY_IN_VIRIO * max(0.0, 1.0 - mean_nai), 4)1034        else:1035            penalty = GZ_PENALTY_IN_VIRIO  # no valid data, use max1036        return penalty, (1037            f"In virio SHAPE-scaled penalty ({penalty:.0%}); "1038            f"NP occlusion in infected cells not fully captured."1039        )1040 1041    # No SHAPE data — conservative prior1042    return GZ_PENALTY_NO_SHAPE, (1043        f"Prior penalty ({GZ_PENALTY_NO_SHAPE:.0%}); no experimental SHAPE data available."1044    )1045 1046 1047def grade_guide(1048    score: float,1049    in_gray: bool,1050    gz_penalty: float = GZ_PENALTY_NO_SHAPE,1051) -> tuple[str, float]:1052    """Grade a guide given its accessibility score and pre-computed gz_penalty."""1053    effective = score * (1.0 - gz_penalty) if in_gray else score1054    for label, thr in GRADE_THRESHOLDS.items():1055        if effective >= thr:1056            return label, round(effective, 4)1057    return "Poor", round(effective, 4)1058 1059 1060def find_guide_position(seq: str, spacer: str) -> tuple[int | None, str | None]:1061    """Returns (1-indexed position, strand) or (None, None) if not found."""1062    idx = seq.find(spacer)1063    if idx >= 0:1064        return idx + 1, "sense"1065    rc = spacer.translate(str.maketrans("ACGU", "UGCA"))[::-1]1066    idx = seq.find(rc)1067    return (idx + 1, "antisense") if idx >= 0 else (None, None)1068 1069 1070# ─── Fuzzy guide search ───────────────────────────────────────────────────────1071 1072def find_guide_position_fuzzy(1073    seq: str,1074    spacer: str,1075    max_mm: int = 2,1076) -> tuple[int | None, str | None, int, list[int]]:1077    """1078    Sliding-window Hamming distance search on both sense and antisense strands.1079    Returns (1-indexed_position, strand, mismatch_count, mismatch_positions).1080    mismatch_positions are always reported in spacer coordinates (1-indexed, 5′→3′).1081 1082    Priority: exact sense > exact antisense > fewest-mismatches sense/antisense.1083    For ties in mismatch count the leftmost hit wins.1084 1085    RC computation: spacer T→U (via clean_rna upstream), then ACGU→UGCA + reverse.1086    Antisense mismatch positions are converted from RC coordinates to spacer1087    coordinates: spacer_pos = len(spacer) − rc_pos_0indexed1088    so seed region (positions 15–21) maps correctly onto the RC comparison.1089    """1090    n, w = len(seq), len(spacer)1091    rc = spacer.translate(str.maketrans("ACGU", "UGCA"))[::-1]1092 1093    # ── Fast paths: exact match ───────────────────────────────────────────────1094    idx = seq.find(spacer)1095    if idx >= 0:1096        return idx + 1, "sense", 0, []1097 1098    idx = seq.find(rc)1099    if idx >= 0:1100        return idx + 1, "antisense", 0, []1101 1102    # ── Fuzzy scan: both strands, single pass ────────────────────────────────1103    best_pos: int | None = None1104    best_strand: str | None = None1105    best_mm   = max_mm + 11106    best_mmp: list[int] = []1107 1108    for i in range(n - w + 1):1109        window = seq[i : i + w]1110 1111        # Sense: mismatch positions are directly in spacer coordinates1112        mmp_s = [j + 1 for j, (a, b) in enumerate(zip(spacer, window)) if a != b]1113        if len(mmp_s) < best_mm:1114            best_pos, best_strand, best_mm, best_mmp = i + 1, "sense", len(mmp_s), mmp_s1115 1116        # Antisense: compare RC against window; convert positions to spacer coords1117        # RC[j] = complement(spacer[w-1-j])  →  spacer pos = w - j  (1-indexed)1118        mmp_a_idx = [j for j, (a, b) in enumerate(zip(rc, window)) if a != b]1119        if len(mmp_a_idx) < best_mm:1120            mmp_a = [w - j for j in mmp_a_idx]   # spacer-coordinate positions1121            best_pos, best_strand, best_mm, best_mmp = i + 1, "antisense", len(mmp_a_idx), mmp_a1122 1123    if best_pos is not None and best_mm <= max_mm:1124        return best_pos, best_strand, best_mm, best_mmp1125    return None, None, 0, []1126 1127 1128# ─── Mismatch penalty ─────────────────────────────────────────────────────────1129 1130def calc_mismatch_penalty(mm_count: int, mm_positions: list[int]) -> float:1131    """1132    Return the penalty fraction to apply to the base accessibility score.1133 1134    Rules (seed overrides count — penalties do NOT stack):1135      - 0 mismatches               → 0.001136      - 1 mismatch (no seed)       → 0.151137      - 2 mismatches (no seed)     → 0.301138      - Any mismatch in pos 15–21  → 0.80  (flat override)1139 1140    Positions in mm_positions are 1-indexed spacer positions (5′→3′).1141    """1142    if mm_count == 0:1143        return 0.01144    if any(p in SEED_POSITIONS for p in mm_positions):1145        return SEED_PENALTY1146    return MM_PENALTY.get(mm_count, 0.30)1147 1148 1149def format_mismatch_str(mm_count: int, mm_positions: list[int]) -> str:1150    """Human-readable mismatch report for the results table."""1151    if mm_count == 0:1152        return "0 (exact)"1153    parts = []1154    for p in sorted(mm_positions):1155        tag = " ★SEED" if p in SEED_POSITIONS else ""1156        parts.append(f"pos {p}{tag}")1157    return f"{mm_count} ({', '.join(parts)})"1158 1159 1160# ─── Universal Structural Motif labelling ────────────────────────────────────1161 1162def get_universal_label(1163    pos: int,1164    win: int,1165    universal_motifs: list[tuple[int, int]],1166    gz: dict,1167) -> str:1168    """1169    Return "Universal Candidate", "Universal Candidate (Constrained)", or "".1170    Kept for backward compatibility; critical_feature column is the primary annotation.1171    """1172    if not universal_motifs:1173        return ""1174    end = pos + win - 11175    is_univ = any(not (end < s or pos > e) for s, e in universal_motifs)1176    if not is_univ:1177        return ""1178    in_gz, _ = is_in_gray_zone(pos, win, gz)1179    return "Universal Candidate (Constrained)" if in_gz else "Universal Candidate"1180 1181 1182# ─── Bulk guide evaluation ────────────────────────────────────────────────────1183 1184def parse_bulk_guides(raw_text: str) -> list[dict]:1185    """1186    Parse bulk guide input. Accepts (one guide per line):1187      - Raw sequence only:           AUGCAUGCAUGCAUGCAUGCAUGC1188      - Name<TAB>Sequence:           guide_1\tAUGCAUGCAUGCAUGCAUGCAUGC1189      - Name, Sequence (CSV):        guide_1, AUGCAUGCAUGCAUGCAUGCAUGC1190      - FASTA format:                >guide_1\nAUGCAUGCAUGCAUGCAUGCAUGC1191    Returns list of {name, sequence}.1192    """1193    import re as _re1194    results = []1195 1196    # Handle FASTA blocks1197    if ">" in raw_text:1198        blocks = _re.split(r"\n(?=>)", raw_text.strip())1199        for block in blocks:1200            lines = block.strip().splitlines()

Showing the first 1,200 of 3476 lines. Download the file for the rest.