NavVerma/RNA_Accessibility_Probablity
0
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()