From bf4980883bafb512b05cef97e5c96fb01fd9a6bb Mon Sep 17 00:00:00 2001 From: Aleksey Drobin <43707931+adrobi@users.noreply.github.com> Date: Sun, 25 Oct 2026 01:22:47 +0300 Subject: [PATCH 01/44] Design spec: clone verification, peak analysis accuracy, UI refresh Co-Authored-By: Claude Opus 5.5 --- .../2026-10-25-clone-verification-design.md | 275 ++++++++++++++++++ 1 file changed, 275 insertions(+) create mode 100644 docs/superpowers/specs/2026-10-25-clone-verification-design.md diff --git a/docs/superpowers/specs/2026-10-25-clone-verification-design.md b/docs/superpowers/specs/2026-10-25-clone-verification-design.md new file mode 100644 index 0000000..2443beb --- /dev/null +++ b/docs/superpowers/specs/2026-10-25-clone-verification-design.md @@ -0,0 +1,275 @@ +# Проверка клонов, точность анализа пиков и новый интерфейс — дизайн + +Дата: 2026-10-25 · Статус: согласован в обсуждении, ждёт ревью спецификации + +## 1. Цель и сценарий + +Главный сценарий ab1kit после этой работы — **проверка клонов одного +конструкта**: в лаборатории отобрали 4–12 колоний, каждую отсеквенировали +1–4 праймерами; нужно быстро понять, какой клон правильный, а если нет — +где и какая ошибка. Остальные сценарии (генотипирование ожидаемых SNP, поиск +мутаций, просмотр/экспорт одного рида, батч-QC) сохраняются как есть. + +Пользователи — биологи, не биоинформатики. Платформа — Windows (как сейчас), +лицензия MIT. + +**Критерий успеха:** пользователь перетаскивает файл конструкта и папку с +ридами, задаёт регион проверки и за минуту видит по каждому клону вердикт, +а по каждому расхождению — хроматограммы всех ридов в этой позиции. + +### Принятые решения + +| Вопрос | Решение | +| --- | --- | +| Главный сценарий | Проверка клонов (B); остальные сохраняются | +| Формат конструкта | Основной — FASTA (без аннотаций); также GenBank и SnapGene `.dna`; Benchling — нет | +| Размер сессии | Один конструкт, 4–12 клонов × 1–4 рида | +| Группировка ридов в клоны | Автоматически по имени файла + ручная правка; свой шаблон-regex в настройках | +| Что проверяется | Регион, заданный пользователем; вне региона расхождения видны, но на вердикт не влияют | +| Архитектура UI | PySide6 Widgets, обновлённый стиль; без переписывания на QML/веб | +| Раскладка главного экрана | «Матрица»: все клоны строками на общей оси с референсом | + +## 2. Ядро (`chrom_core/`, без зависимостей от Qt, покрыто pytest) + +### 2.1 `reference.py` — загрузка конструкта + +- `load_construct(path) -> Construct`; формат по расширению (`.fa/.fasta/.fna/.txt`, + `.gb/.gbk/.genbank`, `.dna`) с проверкой содержимого; чтение через + `Bio.SeqIO` (`fasta`, `genbank`, `snapgene`). Берётся первая запись. +- `Construct`: `name`, `seq` (верхний регистр, IUPAC), `circular: bool`, + `features: list[Feature]` (может быть пустым). +- `Feature`: `name`, `kind` (`CDS`, `promoter`, `primer_bind`, …), `start`, + `end` (0-based, полуоткрытый), `strand` (+1/−1); фичи через начало + координат поддерживаются (`start > end` означает обёртку). +- `circular`: из файла для GenBank/SnapGene (topology); для FASTA — `True` по + умолчанию, переключается пользователем. +- Существующий `align.parse_sequence` остаётся для вставки текстом + (результат — `Construct` без фич, `circular=True`). + +### 2.2 `align.py` — кольцевой референс + +- Новая функция `align_to_construct(read, construct) -> ReadAlignment`. + Для линейного — вызывает существующий `align_read`. Для кольцевого — + выравнивает на `seq + seq[:len(read) + 50]`, затем приводит все + координаты (`ref_start/ref_end`, `ref_to_read`, `differences`) по модулю + длины. Для обёрнутого выравнивания `ref_end` может быть меньше + `ref_start`; добавляется метод `covers(pos)` и `covered_positions()`. +- `align_read` и его тесты не меняются. `MAX_REFERENCE_LENGTH` (100 т.п.н.) + действует на исходную длину конструкта. + +### 2.3 `peaks.py` — анализ вторичных пиков (выносится из `snps.py`) + +- `channel_baseline(chrom, i, span=20) -> dict[base, float]` — медиана + высоты пиков каждого канала среди ~20 ближайших вызванных баз этого + канала; нормирует разную яркость красителей. +- `peak_window(chrom, i)` — половина расстояния до соседних пиков (не + меньше 2 точек) вместо фиксированных ±5. +- `secondary_peak(chrom, i) -> SecondaryPeak(base, ratio, primary_base)` — + на **любой** позиции: нормированная высота сильнейшего канала вне + вызванной базы, делённая на нормированную высоту вызванной. +- `snps.py` и `verify.py` переходят на `peaks.py`; публичные сигнатуры + `call_snps`, `verify_expected`, `peak_heights` сохраняются (последняя + остаётся как обёртка). Добавляется `scan_secondary_peaks(chrom, + alignment, min_ratio)` — поиск гетерозигот/смесей по всему выровненному + риду, включая позиции, где вызвана референсная база. + +### 2.4 `clones.py` — проверка клонов + +**Группировка.** `group_reads(paths, pattern=None) -> Grouping`. +- По умолчанию: имя файла без расширения делится по `_`, `-`, `.`, пробелу; + метка праймера — последний токен, совпавший со словарём (`F`, `R`, `FW`, + `REV`, `FWD`, `T7`, `T7term`, `SP6`, `T3`, `M13F`, `M13R`, `pUC-F`, … — + регистр не важен; словарь расширяется в настройках); если совпадений со + словарём нет — последний токен. Клон — исходная подстрока имени **до** + токена праймера (с сохранением исходных разделителей), из которой убраны + хвостовые разделители, номер порядка праймера (`^\d$` непосредственно + перед праймером) и ведущая позиция лунки планшета (`^[A-H]\d{1,2}$`). + Если после этого клон пустой — файл попадает в «без клона». + Пример: `Achl_ACHLO006-09_1_F` → клон `Achl_ACHLO006-09`, праймер `F`. +- Свой шаблон — regex с именованными группами `clone` и `primer`. +- Нераспознанные файлы → группа «без клона» (в проверку не идут, пока + пользователь их не назначит). +- `Grouping` сериализуется вместе с ручными правками. + +**Проверка.** `verify_clone(construct, region, reads, params) -> CloneReport`. +- `region`: `(start, end)` в координатах конструкта, обёртка через начало + допустима для кольцевого. +- Для каждого рида: текущая версия с учётом сессии правок + (`<файл>.ab1kit.json`), выравнивание `align_to_construct`. Рид с + `alternatives > 1` помечается «неоднозначно» и не участвует в вердикте. +- **Покрытие** по позиции региона: число ридов, покрывающих её с Q ≥ `min_q` + (по умолчанию 20), отдельно по цепям. +- **Расхождения** (`CloneDifference`): замены, вставки, делеции из + выравниваний всех ридов, объединённые по позиции и типу; для каждого — + `support` (ридов с этим расхождением и Q ≥ `min_q`), `against` (ридов, + видящих референс с Q ≥ `min_q`), статус `confirmed` (support ≥ 1, + against = 0) / `disputed` (support ≥ 1, against ≥ 1) / `low_quality` + (support = 0, есть только низкокачественные). +- **Эффект** (если в конструкте есть CDS, перекрывающая позицию): для + замены — синонимичная / миссенс (`D45N`) / стоп; для вставки/делеции — + «сдвиг рамки» или «вставка/делеция в рамке». Без аннотаций — пусто. +- **Смешанность:** позиции региона, где `secondary_peak.ratio ≥ het_ratio` + (по умолчанию 0.40) хотя бы в одном риде с Q ≥ `min_q`. + +**Вердикт** (первое сработавшее правило): +1. `no_data` — ни один рид не выровнялся (или все неоднозначны); +2. `mixed` — ≥ `mixed_min_positions` (по умолчанию 3) позиций со вторым пиком; +3. `errors` — есть `confirmed` или `disputed` расхождение в регионе; +4. `incomplete` — есть позиции региона без покрытия с Q ≥ `min_q`; +5. `ok`. + +Дополнительно в отчёте: доля региона, покрытая обеими цепями. + +Пороги (`min_q`, `het_ratio`, `mixed_min_positions`) — в `VerifyParams`, +значения по умолчанию выше, настраиваются в интерфейсе. + +### 2.5 Проект и отчёты + +- `project.py`: файл `.ab1proj` (JSON) — путь к конструкту (относительный, + если рядом), `circular`, регион, список ридов с привязкой клон/праймер, + ручные правки группировки, `VerifyParams`. Версионируется полем `version`. +- Отчёт `clone_report_csv` / `clone_report_xlsx` (openpyxl): лист «Клоны» + (клон, вердикт, покрытие региона %, обе цепи %, расхождений, риды) и лист + «Расхождения» (клон, позиция, тип, ref→read, эффект, за/против, статус, + примечание). + +### 2.6 Производительность + +Сценарий 12 клонов × 4 рида на конструкте 10 т.п.н. замеряется тестом; +порог фиксируется по замеру с запасом ×2. В интерфейсе всё выполняется в +фоне, поэтому длительность влияет на ожидание, но не на отзывчивость. + +## 3. Интерфейс (`ui/`) + +### 3.1 Структура окна + +- Две вкладки-режима: **«Проверка конструкта»** (новый главный экран) и + **«Просмотр рида»** (нынешний просмотрщик с панелями анализа, проверки + SNP и батч-QC). +- Двойной клик по риду/расхождению → рид открывается в «Просмотре рида»; + после правки проверка пересчитывается. + +### 3.2 Экран «Проверка конструкта» (раскладка «матрица») + +1. **Строка-сводка:** имя конструкта, длина, кольцевая/линейная, регион; + счётчики клонов по вердиктам — каждый работает как фильтр. +2. **Матрица:** сверху дорожка референса (фичи, если есть; рамка региона — + задаётся протяжкой мышью или вводом координат). Ниже по строке на клон: + покрытие (цвет — одна/две цепи, бледный — Q < 20), метки расхождений + (цвет по статусу), плашка вердикта. Колёсико масштабирует общую ось. +3. **Детали:** по клику на метку — хроматограммы всех ридов клона в этой + позиции друг под другом, референс сверху; рядом таблица расхождений + клона (позиция, ref→read, эффект, за/против, статус). +4. **Пустое состояние:** подсказки «перетащите файл конструкта» и «…папку с + ридами» вместо пустых панелей. + +### 3.3 Окно группировки + +Таблица «файл → клон, праймер» с правкой ячеек; поле своего шаблона с +мгновенным предпросмотром; группа «без клона» выделена. + +### 3.4 Внешний вид + +- Единая QSS-тема поверх Fusion (светлая/тёмная), общая палитра статусов: + зелёный — подходит, красный — ошибки, жёлтый — неполное покрытие, + фиолетовый — смесь, серый — нет данных; легенда в строке-сводке. +- Иконки на панели инструментов: набор SVG под MIT/Apache-2.0 в + `ui/icons/` с файлом лицензии. +- Полоски качества раскрашены по Q (с легендой). +- Колонки таблиц подстраиваются под содержимое; полный текст длинных ячеек + во всплывающей подсказке. +- Исправления найденных ошибок: английское примечание в русском UI + (`verify.py` отдаёт непереведённую строку); «Ср. Q = 0» в батч-режиме + для ридов без данных качества → «—». + +### 3.5 Внутреннее устройство UI + +- `main_window.py` (1163 строки) разбивается: оболочка окна и меню; + `ui/read_view/` — существующие панели (диалоги поиска/обрезки, анализ, + проверка SNP, батч), каждая в своём файле; `ui/construct/` — сводка, + матрица, панель деталей, диалог группировки. +- Фоновые задачи: обёртка над `QThreadPool`/`QRunnable` с сигналами + прогресса, результата, ошибки и флагом отмены. Через неё — проверка + клонов, сканирование папки, отправка в BLAST. +- Все новые строки — через `_()` с переводами в `translations_en.py`. + +## 4. CLI (`chrom_cli.py`) + +- Без аргументов или с путём — запуск GUI (как сейчас). +- `ab1kit verify-clones --construct FILE [--region A-B] [--linear] + [--pattern REGEX] READS_DIR -o REPORT.(csv|xlsx)`; код возврата 0, если + есть хотя бы один клон `ok`, иначе 1; 2 — ошибка входных данных. +- `ab1kit qc READS_DIR [-o CSV]` и `ab1kit export READS_DIR --trim + [--fasta|--fastq] -o DIR` — над существующим `batch.py`. +- Реализация на `argparse`; подкоманды распознаются по первому аргументу, + путь к файлу/папке по-прежнему открывает GUI. + +## 5. Обработка ошибок + +- Нечитаемый `.ab1` или невыровнявшийся рид не прерывает проверку: рид + помечается в таблице с причиной, остальные обрабатываются. +- Пустой регион, регион вне конструкта, конструкт больше лимита — понятное + сообщение до запуска. +- Неоднозначное выравнивание (повторы) — рид помечен «неоднозначно», в + вердикт не идёт. +- Отмена фоновой задачи сохраняет предыдущий результат. +- Битый или устаревший `.ab1proj` — сообщение и открытие без проекта. + +## 6. Тестовые данные и тесты + +### 6.1 Данные + +- **Реальные риды:** sangeranalyseR (MIT), `inst/extdata/Allolobophora_chlorotica` + — 4 образца × F/R = 8 файлов (~1,7 МБ) в `tests/data/real/` с README + (источник, коммит, лицензия). +- **Референсы с NCBI:** запись COI *A. chlorotica*, соответствующая + образцам (accession подбирается BLAST-ом ридов и фиксируется в README), и + pUC19 (L09137, GenBank, кольцевая, с аннотациями). Скачиваются один раз + `scripts/fetch_test_data.py` (E-utilities) и коммитятся; тесты сеть не + используют. +- Наборы gear-genomics (GPL-3.0) не используются. + +### 6.2 Контролируемая истина + +- **Ошибки клона:** в копию референса вносится известная замена / + вставка / делеция; реальный рид даёт расхождение в известной позиции. +- **Смесь:** полусинтетическая копия реального рида, в которой под + выбранной позицией в другой канал добавлен пик формы соседнего реального + пика заданной высоты (30% и 50%). Генерируется в фикстуре, явно помечена. +- **Набор клонов:** «подходит» (реальные риды, неизменённый референс), + «ошибка» (изменённый референс), «неполный» (обрезанный рид), + «смесь» (полусинтетика), «нет данных» (рид другого гена). + +### 6.3 Проверки + +- Каждая внесённая ошибка найдена с верными позицией, типом, `support`. +- Ноль ложных расхождений в регионе на неизменённом референсе при Q ≥ 20. +- Второй пик 30% — не смесь, 50% — смесь (при `het_ratio` 0.40). +- Кольцевое выравнивание: рид через начало координат повёрнутого pUC19 + даёт непрерывное покрытие и верные координаты. +- Группировка имён sangeranalyseR и синтетических имён (`cl3_T7`, `A05_K3-F`, + `clone12.rev`); свой regex. +- Чтение FASTA/GenBank/SnapGene. BioPython не умеет писать `.dna`, поэтому + берётся образец из `Tests/SnapGene/` набора тестов BioPython (Biopython + License, как и нынешние `examples/`), с указанием источника в README. +- Регрессия: существующие тесты `snps`/`verify` проходят после выноса в + `peaks.py`; плюс прогон на реальных ридах. +- Производительность 12 × 4 на 10 т.п.н. (порог по замеру). +- GUI smoke в offscreen: экран проверки открывается, проект загружается, + матрица рисуется, фоновая задача завершается. + +## 7. Порядок работ + +Каждый шаг оставляет программу рабочей: + +1. Тестовые данные; `peaks.py`; исправления двух ошибок UI. +2. Ядро: `reference.py`, кольцевое выравнивание, `clones.py`, `.ab1proj`, + отчёты. +3. Интерфейс: тема и иконки, разбиение `main_window.py`, фоновые задачи, + экран «Проверка конструкта», окно группировки. +4. CLI. + +## 8. Вне рамок + +Планшеты на 96 ридов разных конструктов; автопоиск ORF в FASTA; `.scf`; +экспорт из Benchling; mafft/MSA; сборка контигов. From ab052346e04c23660a3d20a599c5ed58bc6c59b5 Mon Sep 17 00:00:00 2001 From: Aleksey Drobin <43707931+adrobi@users.noreply.github.com> Date: Sun, 25 Oct 2026 01:27:24 +0300 Subject: [PATCH 02/44] Implementation plan: clone verification, peak accuracy, UI refresh, CLI Co-Authored-By: Claude Opus 5.5 --- .../plans/2026-10-25-clone-verification.md | 611 ++++++++++++++++++ 1 file changed, 611 insertions(+) create mode 100644 docs/superpowers/plans/2026-10-25-clone-verification.md diff --git a/docs/superpowers/plans/2026-10-25-clone-verification.md b/docs/superpowers/plans/2026-10-25-clone-verification.md new file mode 100644 index 0000000..3419107 --- /dev/null +++ b/docs/superpowers/plans/2026-10-25-clone-verification.md @@ -0,0 +1,611 @@ +# Проверка клонов, точность пиков и новый интерфейс — план реализации + +> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking. + +**Goal:** ab1kit проверяет 4–12 клонов одного конструкта по заданному региону и показывает вердикт по каждому клону на экране-матрице, с хроматограммами всех ридов в месте каждого расхождения. + +**Architecture:** Вся логика — в UI-независимом `chrom_core/` (новые модули `peaks`, `reference`, `clones`, `effects`, `project`, `clone_report`; кольцевое выравнивание в `align`). Интерфейс на PySide6 Widgets: `main_window.py` разбивается на `ui/read_view/*`, новый экран — `ui/construct/*`, тяжёлые операции — через `ui/tasks.py` (`QThreadPool`). CLI — тонкая оболочка над ядром. + +**Tech Stack:** Python 3.11+, PySide6 ≥ 6.6, BioPython ≥ 1.83 (`Bio.Align`, `Bio.SeqIO`), openpyxl, pytest. + +**Spec:** `docs/superpowers/specs/2026-10-25-clone-verification-design.md` + +## Global Constraints + +- Python ≥ 3.11; новых runtime-зависимостей нет (только `biopython`, `PySide6`, `openpyxl`). +- `chrom_core/` не импортирует Qt. +- Все строки UI — через `tr("ключ")` из `i18n.py`; каждый новый ключ есть и в `RU` (`i18n.py`), и в `EN` (`translations_en.py`) — это проверяет `tests/test_i18n.py`. (В спецификации написано `_()` — в проекте функция называется `tr`.) +- Пороги по умолчанию: `min_q = 20`, `het_ratio = 0.40`, `mixed_min_positions = 3`; окно базовой линии `span = 20`; запас кольцевого выравнивания `+50` п.н.; лимит конструкта `MAX_REFERENCE_LENGTH = 100_000`. +- Тесты не ходят в сеть; данные из NCBI/GitHub скачиваются один раз скриптом и коммитятся. +- Данные с несовместимой с MIT лицензией (gear-genomics, GPL-3.0) в репозиторий не кладутся. +- Существующие тесты остаются зелёными после каждой задачи: `python -m pytest -q`. +- GUI-тесты — offscreen (`QT_QPA_PLATFORM=offscreen`), по образцу `tests/test_smoke_gui.py`. +- Палитра статусов: `ok` зелёный, `errors` красный, `incomplete` жёлтый, `mixed` фиолетовый, `no_data` серый — одни и те же цвета везде (матрица, сводка, отчёт XLSX). + +## Review Focus + +1. **Рид, развёрнутый реверс-комплементом в сессии правок** (`.ab1kit.json` с `reversed_complement: true`): покрытие и расхождения должны относиться к тем же позициям конструкта, что и у неразвёрнутого рида. Тест — Task 7. +2. **Регион через начало координат кольцевого конструкта** (`start > end`, например 4300–200 на 4420 п.н.): покрытие, расхождения и вердикт считаются по обёрнутому региону. Тест — Task 7. +3. **Рид без данных качества** (все Q = 0, как `examples/310.ab1`): расхождения не «подтверждаются», клон получает `incomplete`, а не `errors`; в батч-таблице «—» вместо 0. Тесты — Tasks 3 и 7. +4. **Конструкт с несколькими записями, строчными буквами или `N`**: берётся первая запись, верхний регистр, `N` в референсе не считается расхождением. Тесты — Tasks 4 и 7. +5. **Повторное секвенирование тем же праймером** (`cl3_T7.ab1` и `cl3_T7_2.ab1`) и **кириллица/пробелы в путях**: оба рида остаются в клоне `cl3`; проект и CLI работают с путями вида `D:\Данные\клоны 1\`. Тесты — Tasks 6, 10, 17. + +--- + +## Фаза 1 — данные, анализ пиков, исправления + +### Task 1: Корпус реальных тестовых данных + +**Files:** +- Create: `scripts/fetch_test_data.py` +- Create: `tests/data/real/` (8 файлов `.ab1`), `tests/data/refs/`, `tests/data/README.md` +- Create: `tests/clone_fixtures.py` +- Test: `tests/test_data_corpus.py` + +**Interfaces:** +- Produces (`tests/clone_fixtures.py`): + - `DATA: Path` = `tests/data` + - `REAL_READS: list[Path]` — 8 файлов, отсортированы + - `real_read(name: str) -> Chromatogram` + - `COI_GB: Path`, `PUC19_GB: Path`, `SNAPGENE_DNA: Path` + - `coi_reference() -> str` — последовательность COI, верхний регистр + +- [ ] **Step 1: Написать `scripts/fetch_test_data.py`.** Скачивает в `tests/data/`: + - из `https://raw.githubusercontent.com/roblanf/sangeranalyseR//inst/extdata/Allolobophora_chlorotica/ACHLO/` файлы `Achl_ACHLO006-09_{1_F,2_R}.ab1`, `Achl_ACHLO007-09_{1_F,2_R}.ab1`, `Achl_ACHLO040-09_{1_F,2_R}.ab1`, `Achl_ACHLO041-09_{1_F,2_R}.ab1` → `tests/data/real/`; `` — SHA HEAD на момент скачивания, зашит константой; + - pUC19 `L09137` в формате GenBank через `https://eutils.ncbi.nlm.nih.gov/entrez/eutils/efetch.fcgi?db=nuccore&id=L09137&rettype=gbwithparts&retmode=text` → `tests/data/refs/pUC19_L09137.gb`; + - COI: accession передаётся аргументом `--coi ACC` → `tests/data/refs/coi_.gb` (тот же efetch); + - SnapGene-образец из `https://raw.githubusercontent.com/biopython/biopython//Tests/SnapGene/sample-d.dna` → `tests/data/refs/sample-d.dna`. + Только `urllib`; идемпотентен (существующие файлы не перекачивает без `--force`). +- [ ] **Step 2: Подобрать accession COI.** Отправить `Achl_ACHLO006-09_1_F` в BLAST (`chrom_core.blast.build_request`/`submit`, результат открыть вручную) и выбрать запись GenBank *Allolobophora chlorotica* с аннотированной CDS, покрывающую рид целиком с идентичностью ≥ 98%. Запустить `python scripts/fetch_test_data.py --coi `. +- [ ] **Step 3: Написать `tests/data/README.md`** — источник каждого файла, commit/accession, лицензия (sangeranalyseR — MIT; BioPython — Biopython License; NCBI — public domain), пометка «полусинтетические данные генерируются в `tests/clone_fixtures.py`, на диске не лежат». +- [ ] **Step 4: Написать падающий тест** + +```python +# tests/test_data_corpus.py +from clone_fixtures import REAL_READS, COI_GB, PUC19_GB, SNAPGENE_DNA, real_read, coi_reference +from chrom_core.align import align_read + +def test_corpus_files_present(): + assert len(REAL_READS) == 8 + assert COI_GB.exists() and PUC19_GB.exists() and SNAPGENE_DNA.exists() + +def test_every_real_read_aligns_to_coi_with_high_identity(): + ref = coi_reference() + for path in REAL_READS: + aln = align_read(real_read(path.name).seq, ref) + assert aln.identity >= 0.97, path.name + assert aln.strand == ("+" if "_F" in path.name else "-") +``` + +- [ ] **Step 5: Запустить** `python -m pytest tests/test_data_corpus.py -v` → FAIL (`ModuleNotFoundError: clone_fixtures`). +- [ ] **Step 6: Реализовать `tests/clone_fixtures.py`** (константы и функции из Interfaces; `coi_reference` читает `COI_GB` через `Bio.SeqIO`). Добавить `pythonpath = ["tests"]` в `[tool.pytest.ini_options]` в `pyproject.toml`. +- [ ] **Step 7: Запустить** тест → PASS. Если идентичность ниже порога у отдельных ридов — сменить accession (Step 2), а не порог. +- [ ] **Step 8: Commit** `git add scripts/fetch_test_data.py tests/data tests/clone_fixtures.py tests/test_data_corpus.py pyproject.toml && git commit -m "Test corpus: real sangeranalyseR reads, COI and pUC19 references"` + +### Task 2: `peaks.py` — нормированный анализ вторичных пиков + +**Files:** +- Create: `chrom_core/peaks.py` +- Modify: `chrom_core/snps.py` (использует `peaks`), `chrom_core/verify.py:166-181` (то же) +- Test: `tests/test_peaks.py`; регрессия — `tests/test_snps.py`, `tests/test_verify.py` + +**Interfaces:** +- Consumes: `Chromatogram` (`chrom_core/abif.py`), `ReadAlignment` (`chrom_core/align.py`) +- Produces (`chrom_core/peaks.py`): + - `BASELINE_SPAN = 20` + - `peak_window(chrom: Chromatogram, i: int) -> int` — половина расстояния до ближайшего соседнего пика, не меньше 2 + - `channel_baseline(chrom: Chromatogram, i: int, span: int = BASELINE_SPAN) -> dict[str, float]` — для каждого канала медиана высот пиков тех из `span` ближайших (по индексу) вызванных баз, у которых этот канал — вызванная база; если таких нет — медиана высот всех `span` пиков по всем каналам + - `@dataclass(frozen=True) SecondaryPeak(primary_base: str, base: str, ratio: float | None)` + - `secondary_peak(chrom: Chromatogram, i: int) -> SecondaryPeak` — высоты в окне `peak_window`, делённые на `channel_baseline`; `ratio = норм. второй вне вызванных / норм. максимальный среди вызванных` + - `scan_secondary_peaks(chrom: Chromatogram, alignment: ReadAlignment, min_ratio: float, min_q: int) -> list[tuple[int, SecondaryPeak]]` — по всем `ref_pos` из `alignment.ref_to_read` (в ориентации `chrom`, как в `call_snps`), где `quality ≥ min_q` и `ratio ≥ min_ratio`; список `(ref_pos, SecondaryPeak)` по возрастанию `ref_pos` + - `peak_heights` остаётся в `snps.py` с прежней сигнатурой (обратная совместимость, используется UI-тултипами) + +- [ ] **Step 1: Написать падающие тесты** (синтетика через `make_chrom` из `tests/test_snps.py` — перенести её в `tests/clone_fixtures.py` и импортировать в обоих местах): + +```python +def test_weak_channel_normalisation_removes_false_het(): + # G-канал систематически вдвое слабее: «второй пик» G на 45% сырой высоты + # при норм. высоте ≈ 0.9·baseline A → ratio по сырым 0.45 (ложный het), + # после нормировки — сам G-пик нормален, а под A-пиком G 45/500 → < 0.40 + ... + assert secondary_peak(chrom, 10).ratio < 0.40 + +def test_true_het_detected_after_normalisation(): + ... # второй пик C на 50% → ratio ≈ 0.5 + assert secondary_peak(chrom, 10).base == "C" + assert 0.45 <= secondary_peak(chrom, 10).ratio <= 0.55 + +def test_peak_window_tracks_spacing(): + assert peak_window(chrom_spacing_10, 5) == 5 + assert peak_window(chrom_spacing_3, 5) == 2 + +def test_scan_finds_het_where_reference_base_was_called(): + # рид = референс, но под позицией 30 второй пик T на 50% + hits = scan_secondary_peaks(chrom, align_read(chrom.seq, ref), 0.40, 20) + assert [pos for pos, _ in hits] == [30] +``` + + Конкретные значения трасс — в теле тестов; утверждения — как выше. +- [ ] **Step 2: Запустить** `python -m pytest tests/test_peaks.py -v` → FAIL (`ModuleNotFoundError: chrom_core.peaks`). +- [ ] **Step 3: Реализовать `chrom_core/peaks.py`** по Interfaces. +- [ ] **Step 4: Перевести `call_snps` и `_verify_one` на `secondary_peak`.** Логика вердиктов не меняется, меняется только источник `ratio`/`secondary_base`. +- [ ] **Step 5: Добавить регрессию на реальных ридах** в `tests/test_peaks.py`: + +```python +def test_real_reads_have_no_mass_false_hets(): + ref = coi_reference() + for path in REAL_READS: + chrom = real_read(path.name) + aln = align_read(chrom.seq, ref) + hits = scan_secondary_peaks(chrom, aln, 0.40, 20) + assert len(hits) <= 2, (path.name, hits) +``` + +- [ ] **Step 6: Запустить всё** `python -m pytest -q` → PASS (включая `test_snps.py`, `test_verify.py`). Если старый тест SNP падает из-за нормировки, разобрать конкретный случай; менять ожидание теста можно только если новое значение ближе к истине — с комментарием в тесте. +- [ ] **Step 7: Commit** `git commit -m "peaks: normalised secondary-peak analysis at any read position"` + +### Task 3: Исправить две ошибки интерфейса + +**Files:** +- Modify: `chrom_core/verify.py` (`VariantVerdict`), `chrom_core/batch.py` (`FileReport`, `scan_folder`), `ui/main_window.py:722-757` (`_fill_verify_table`), `ui/batch_panel.py:76`, `i18n.py`, `translations_en.py` +- Test: `tests/test_verify.py`, `tests/test_batch.py`, `tests/test_smoke_gui.py` + +**Interfaces:** +- Produces: + - `VariantVerdict.note_code: str = ""` — коды: `only_snv`, `pos_outside_ref`, `ref_differs`, `deleted_in_read`, `outside_coverage`, `low_q` (с `note_args={"q": ..., "min_q": ...}`); поле `note_args: dict = field(default_factory=dict)`. Поле `note` (английский текст) остаётся — его пишут CSV/XLSX-отчёты. + - i18n-ключи `verify.note.` в RU и EN. + - `FileReport.mean_q: float | None` — `None`, если у рида все Q = 0. + +- [ ] **Step 1: Падающие тесты** + +```python +# test_verify.py +def test_ref_mismatch_carries_note_code(): ... + assert verdict.note_code == "ref_differs" + +# test_batch.py +def test_read_without_quality_reports_none_mean_q(folder): + by_name = {r.path.name: r for r in batch.scan_folder(folder)} + assert by_name["310.ab1"].mean_q is None + +# test_smoke_gui.py +def test_verify_table_note_is_localised(qapp, ...): + # русский UI, вариант с неверной ref-базой → ячейка «Примечание» + assert "table ref base" not in note_cell_text + assert note_cell_text == tr("verify.note.ref_differs") +``` + +- [ ] **Step 2: Запустить** → FAIL. +- [ ] **Step 3: Реализовать:** `_verify_one` заполняет `note_code`/`note_args`; `_fill_verify_table` показывает `tr(f"verify.note.{code}", **args)` (если код пуст — `note`); `scan_folder` ставит `mean_q=None` при `not any(chrom.quality)`; `BatchPanel` показывает `"—"` для `None`; `status` не меняется (рид без качества по-прежнему оценивается по длине обрезки). Проверить, что `summary_csv` пишет пустую ячейку для `None`. +- [ ] **Step 4: Запустить** `python -m pytest -q` → PASS. +- [ ] **Step 5: Commit** `git commit -m "Fix untranslated verify notes and Q=0 for reads without quality"` + +--- + +## Фаза 2 — ядро проверки клонов + +### Task 4: `reference.py` — загрузка конструкта + +**Files:** +- Create: `chrom_core/reference.py` +- Test: `tests/test_reference.py` + +**Interfaces:** +- Produces: + - `@dataclass(frozen=True) Feature(name: str, kind: str, start: int, end: int, strand: int)` — 0-based, полуоткрытый; `start > end` — фича через начало координат; `codon_start: int = 1` (из квалификатора `codon_start` для CDS) + - `@dataclass(frozen=True) Construct(name: str, seq: str, circular: bool, features: tuple[Feature, ...] = ())` с методом `with_circular(flag: bool) -> Construct` + - `load_construct(path: str | Path) -> Construct` — `.fa .fasta .fna .txt` → `fasta`, `.gb .gbk .genbank` → `genbank`, `.dna` → `snapgene`; неизвестное расширение — пробовать по первому символу (`>` → fasta, `LOCUS` → genbank), иначе `ValueError`. Первая запись; `seq.upper()`; недопустимые символы → `ValueError` (как `align.parse_sequence`). `circular` — из `record.annotations["topology"] == "circular"`; для FASTA — `True`. Имя фичи — первый из квалификаторов `label`, `gene`, `product`, `note`, иначе `kind`. Составные локации (`CompoundLocation`) через начало: `start` первой части, `end` последней. + - `construct_from_text(text: str, name: str = "pasted") -> Construct` — через `align.parse_sequence`, `circular=True` + +- [ ] **Step 1: Падающие тесты** + +```python +def test_genbank_puc19(): + c = load_construct(PUC19_GB) + assert len(c.seq) == 2686 and c.circular + assert any(f.kind == "CDS" for f in c.features) + +def test_snapgene_sample(): c = load_construct(SNAPGENE_DNA); assert c.seq and c.features + +def test_fasta_multi_record_lowercase(tmp_path): + p = tmp_path / "x.fasta"; p.write_text(">a\nacgtn\n>b\nTTTT\n") + c = load_construct(p) + assert c.seq == "ACGTN" and c.circular and c.features == () + +def test_unknown_extension_sniffed(tmp_path): ... # "x.seq" с ">"-заголовком → FASTA + +def test_garbage_rejected(tmp_path): ... # pytest.raises(ValueError) + +def test_with_circular_toggle(): assert not construct_from_text("ACGT").with_circular(False).circular +``` + +- [ ] **Step 2: Запустить** `python -m pytest tests/test_reference.py -v` → FAIL. +- [ ] **Step 3: Реализовать** по Interfaces. +- [ ] **Step 4: Запустить** → PASS. +- [ ] **Step 5: Commit** `git commit -m "reference: load constructs from FASTA, GenBank and SnapGene"` + +### Task 5: Кольцевое выравнивание + +**Files:** +- Modify: `chrom_core/align.py` (новые функции; `align_read` не меняется) +- Test: `tests/test_align_circular.py` + +**Interfaces:** +- Consumes: `Construct` (Task 4) +- Produces (`chrom_core/align.py`): + - `CIRCULAR_MARGIN = 50` + - `ReadAlignment` получает поле `ref_length: int = 0` и методы `covers(pos: int) -> bool`, `covered_positions() -> list[int]` (для обёрнутых — `ref_start..L-1, 0..ref_end-1`); `ref_end < ref_start` означает обёртку + - `align_to_construct(read: str, construct: Construct) -> ReadAlignment` — линейный: `align_read` + `ref_length`; кольцевой: `align_read(read, seq + seq[:len(read) + CIRCULAR_MARGIN])` (лимит проверяется по `len(construct.seq)`), затем все координаты `ref_*`, ключи `ref_to_read`, `Difference.ref_pos` — по модулю `L`; для `ref_end` используется `((ref_end - 1) % L) + 1` + - `gapped_sequences` для обёрнутого выравнивания работает по развёрнутому референсу (`seq + seq[:…]`) — передавать ему `construct.seq * 2` + +- [ ] **Step 1: Падающие тесты** (на реальном риде и COI): + +```python +def test_linear_matches_align_read(): ... # те же differences/identity, ref_length == len(ref) + +def test_read_across_origin_of_rotated_reference(): + ref = coi_reference(); aln0 = align_read(read.seq, ref) + mid = (aln0.ref_start + aln0.ref_end) // 2 + rotated = ref[mid:] + ref[:mid] + aln = align_to_construct(read.seq, Construct("rot", rotated, True)) + assert aln.ref_end < aln.ref_start # обёрнуто + assert len(aln.covered_positions()) == aln0.covered + assert [ (d.ref_pos - (len(ref) - mid)) % len(ref) for d in aln.differences ] \ + == [ d.ref_pos for d in aln0.differences ] + assert aln.covers(0) and aln.covers(len(ref) - 1) + +def test_same_rotation_linear_breaks_read(): + aln = align_to_construct(read.seq, Construct("rot", rotated, False)) + assert aln.covered < aln0.covered # без кольца рид рвётся + +def test_limit_applies_to_original_length(): ... # 100_000 п.н. кольцо проходит; 100_001 — ValueError +``` + +- [ ] **Step 2: Запустить** → FAIL. +- [ ] **Step 3: Реализовать** по Interfaces. +- [ ] **Step 4: Запустить** `python -m pytest -q` → PASS (включая старые `test_align.py`). +- [ ] **Step 5: Commit** `git commit -m "align: circular constructs with origin-spanning reads"` + +### Task 6: Группировка ридов в клоны + +**Files:** +- Create: `chrom_core/clones.py` (раздел группировки) +- Modify: `chrom_core/config.py` (`AppConfig.primer_tokens: list[str]`, `AppConfig.group_pattern: str = ""`) +- Test: `tests/test_grouping.py` + +**Interfaces:** +- Produces: + - `DEFAULT_PRIMER_TOKENS = ("F", "R", "FW", "FWD", "REV", "RV", "T7", "T7TERM", "SP6", "T3", "M13F", "M13R", "M13", "PUC-F", "PUC-R", "BGH", "CMV")` + - `@dataclass(frozen=True) ReadRef(path: Path, clone: str, primer: str)` + - `@dataclass Grouping(reads: list[ReadRef], unassigned: list[Path])` с методами `clones() -> dict[str, list[ReadRef]]` (порядок клонов — натуральная сортировка: `cl2` < `cl10`), `assign(path: Path, clone: str, primer: str) -> None`, `to_dict() -> dict`, `from_dict(d: dict) -> Grouping` + - `parse_name(stem: str, primer_tokens: Iterable[str] = DEFAULT_PRIMER_TOKENS) -> tuple[str, str] | None` — алгоритм из спецификации §2.4 (разделители `_ - .` и пробел; токен праймера — последний совпавший со словарём без учёта регистра, иначе последний токен; клон — исходная подстрока до токена праймера без хвостовых разделителей, без одиночной цифры прямо перед праймером и без ведущей лунки `^[A-H]\d{1,2}$`; хвостовой суффикс повтора `_2`/`-2` **после** токена праймера отбрасывается). Пустой клон → `None`. + - `group_reads(paths: Iterable[Path], pattern: str | None = None, primer_tokens=DEFAULT_PRIMER_TOKENS) -> Grouping` — при `pattern` используется `re.fullmatch` с группами `clone`, `primer`; несовпавшие → `unassigned`. Невалидный regex → `ValueError`. + +- [ ] **Step 1: Падающие тесты** + +```python +@pytest.mark.parametrize("stem,expected", [ + ("Achl_ACHLO006-09_1_F", ("Achl_ACHLO006-09", "F")), + ("Achl_ACHLO006-09_2_R", ("Achl_ACHLO006-09", "R")), + ("cl3_T7", ("cl3", "T7")), + ("cl3_T7_2", ("cl3", "T7")), # повторное секвенирование + ("A05_K3-F", ("K3", "F")), + ("clone12.rev", ("clone12", "rev")), + ("клон 14_SP6", ("клон 14", "SP6")), + ("T7", None), +]) +def test_parse_name(stem, expected): assert parse_name(stem) == expected + +def test_group_real_reads_into_four_clones(): + g = group_reads(REAL_READS) + assert len(g.clones()) == 4 and all(len(v) == 2 for v in g.clones().values()) + +def test_repeat_reads_both_kept(): ... # cl3_T7.ab1 + cl3_T7_2.ab1 → 2 рида в cl3 + +def test_custom_pattern_and_unassigned(): ... # r"(?PS\d+)-(?P\w+)" ; "junk" → unassigned + +def test_bad_regex_raises(): ... + +def test_natural_sort(): ... # cl2, cl10 + +def test_grouping_roundtrip_and_manual_assign(): ... +``` + +- [ ] **Step 2: Запустить** → FAIL. +- [ ] **Step 3: Реализовать** по Interfaces; `AppConfig` — новые поля со значениями по умолчанию (`list(DEFAULT_PRIMER_TOKENS)`, `""`). +- [ ] **Step 4: Запустить** `python -m pytest -q` → PASS. +- [ ] **Step 5: Commit** `git commit -m "clones: group reads into clones by file name"` + +### Task 7: Проверка клона и вердикт + +**Files:** +- Modify: `chrom_core/clones.py` (раздел проверки) +- Modify: `tests/clone_fixtures.py` (полусинтетика) +- Test: `tests/test_clone_verify.py` + +**Interfaces:** +- Consumes: `Construct` (Task 4), `align_to_construct`, `ReadAlignment.covers/covered_positions` (Task 5), `secondary_peak`, `scan_secondary_peaks` (Task 2), `ReadRef` (Task 6), `sessions.load_session/session_path`, `EditableRead.restore_state/current` +- Produces (`chrom_core/clones.py`): + - `@dataclass(frozen=True) VerifyParams(min_q: int = 20, het_ratio: float = 0.40, mixed_min_positions: int = 3)` + - `Region = tuple[int, int]` — 0-based полуоткрытый; `start > end` — через начало (только для кольцевого); `region_positions(region, length) -> list[int]`; `None` = весь конструкт + - `@dataclass(frozen=True) ReadResult(ref: ReadRef, alignment: ReadAlignment | None, error: str = "", ambiguous: bool = False)` + - `@dataclass(frozen=True) CloneDifference(ref_pos: int, kind: str, ref_base: str, read_base: str, support: int, against: int, low_quality: int, status: str, in_region: bool, effect: str = "")` — `status ∈ {"confirmed", "disputed", "low_quality"}` + - `@dataclass(frozen=True) CloneReport(clone: str, reads: tuple[ReadResult, ...], coverage: dict[int, tuple[int, int]], differences: tuple[CloneDifference, ...], mixed_positions: tuple[int, ...], verdict: str)` + свойства `region_coverage_pct: float`, `both_strands_pct: float`, `region_differences` (только `in_region`). `coverage[pos] = (ридов на «+», ридов на «−»)` с Q ≥ `min_q`, только для позиций региона + - `load_read(path: Path) -> Chromatogram` — с учётом сессии правок (как `batch._edited_read`, вынести её в общую функцию и переиспользовать) + - `verify_clone(construct: Construct, region: Region | None, reads: list[ReadRef], params: VerifyParams = VerifyParams(), annotate=None) -> CloneReport` — `annotate` — колбэк `(construct, CloneDifference) -> str` (эффект; подключается в Task 8) + - `verify_all(construct, region, grouping: Grouping, params, progress=None, cancelled=None) -> list[CloneReport]` — `progress(done: int, total: int)`, `cancelled() -> bool` (при `True` — `CancelledError` из `concurrent.futures`) +- Правила (спецификация §2.4): `N`/IUPAC в **референсе** — не расхождение; расхождение «подтверждает» рид с Q ≥ `min_q` в этой позиции (для вставки — Q соседних баз), «против» — рид, покрывающий позицию с референсной базой и Q ≥ `min_q`; `alternatives > 1` → `ambiguous=True`, рид исключается из покрытия и расхождений. Вердикт — первое сработавшее: `no_data`, `mixed`, `errors` (есть `confirmed` или `disputed` в регионе), `incomplete`, `ok`. +- Produces (`tests/clone_fixtures.py`): + - `mutate(seq: str, pos: int, kind: str, base: str = "") -> str` — `kind ∈ {"sub", "ins", "del"}` + - `with_secondary_peak(chrom: Chromatogram, index: int, base: str, ratio: float) -> Chromatogram` — копирует форму пика вызванной базы в канал `base`, масштабируя к `ratio` × высота основного пика + - `write_read(chrom: Chromatogram, folder: Path, name: str) -> Path` — сохраняет как сессию правок рядом с копией исходного `.ab1` (через `sessions.save_session`), чтобы `load_read` вернул изменённую хроматограмму + +- [ ] **Step 1: Падающие тесты** — один набор клонов, собранный фикстурой из реальных ридов `ACHLO006-09` (F+R), регион = покрытая обоими ридами часть COI: + +```python +def test_ok_clone(): assert report.verdict == "ok" and report.region_differences == () + +def test_substitution_found_with_support(): + ref = mutate(coi, P, "sub", other_base) # P внутри региона + r = verify_clone(Construct("c", ref, False), region, reads) + d, = r.region_differences + assert (d.ref_pos, d.kind, d.status, d.support, d.against) == (P, "substitution", "confirmed", 2, 0) + assert r.verdict == "errors" + +def test_insertion_and_deletion_found(): ... # mutate "del" → read shows insertion; "ins" → deletion + +def test_disputed_when_reads_disagree(): ... # мутация в одном риде (через write_read) → support 1, against 1, "disputed", verdict "errors" + +def test_outside_region_does_not_affect_verdict(): ... + +def test_incomplete_when_read_trimmed(): ... # только F, обрезан → "incomplete", region_coverage_pct < 100 + +def test_mixed_50_percent_flagged(): # 3 позиции с ratio 0.5 + assert r.verdict == "mixed" and len(r.mixed_positions) == 3 + +def test_mixed_30_percent_not_flagged(): ... # ratio 0.3 → "ok" + +def test_no_data_for_foreign_read(): ... # рид pUC19-несовместимый (COI-рид против pUC19) → "no_data" + +def test_reverse_complemented_session_same_result(): ... # Review Focus 1 + +def test_region_across_origin(): ... # повёрнутый кольцевой COI, регион start > end → те же расхождения (Review Focus 2) + +def test_read_without_quality_is_incomplete_not_errors(): ... # все Q=0 → "incomplete" (Review Focus 3) + +def test_reference_N_is_not_a_difference(): ... # Review Focus 4 + +def test_unreadable_file_marked_not_fatal(): ... # битый .ab1 → ReadResult.error, остальные обработаны + +def test_ambiguous_read_excluded(): ... # линейный конструкт = COI + COI → ReadResult.ambiguous, verdict "no_data" + +def test_invalid_region_rejected(): ... # пустой регион, вне конструкта, start > end на линейном → ValueError до выравнивания + +def test_verify_all_progress_and_cancel(): ... + +def test_performance_12_clones_x_4_reads(): + # конструкт ~10 т.п.н. = COI + случайный фланг (seed 1); 12 клонов × 4 рида из реальных + t = time.perf_counter(); verify_all(...); elapsed = time.perf_counter() - t + assert elapsed < LIMIT # LIMIT = 2 × замер на машине разработчика, вписать числом +``` + +- [ ] **Step 2: Запустить** `python -m pytest tests/test_clone_verify.py -v` → FAIL. +- [ ] **Step 3: Реализовать** фикстуры в `tests/clone_fixtures.py` и проверку в `chrom_core/clones.py` по Interfaces. +- [ ] **Step 4: Запустить** → PASS; замерить `test_performance…`, вписать `LIMIT` числом. +- [ ] **Step 5: Запустить всё** `python -m pytest -q` → PASS. +- [ ] **Step 6: Commit** `git commit -m "clones: per-clone coverage, merged differences and verdicts"` + +### Task 8: Эффект расхождения в CDS + +**Files:** +- Create: `chrom_core/effects.py` +- Test: `tests/test_effects.py` + +**Interfaces:** +- Consumes: `Construct`, `Feature` (Task 4), `CloneDifference` (Task 7) +- Produces: + - `difference_effect(construct: Construct, diff: CloneDifference) -> str` — первая CDS, содержащая `diff.ref_pos` (с учётом обёртки и `strand`, рамка из `codon_start`). Замена: `"synonymous"` / `"<номер>"` (однобуквенные коды, например `"D45N"`) / `"<номер>*"` для стопа; вставка/делеция: `"frameshift"`, если длина не кратна 3, иначе `"inframe_ins"` / `"inframe_del"`. Вне CDS или без фич — `""`. Трансляция — `Bio.Seq.translate`, таблица 11. + - Строка-код эффекта переводится в UI ключами `effect.synonymous`, `effect.frameshift`, `effect.inframe_ins`, `effect.inframe_del` (миссенс/стоп показываются как есть). + +- [ ] **Step 1: Падающие тесты** — на COI из GenBank (с CDS) и на pUC19 (`bla` на минус-цепи): + +```python +def test_synonymous_third_codon_position(): ... # замена 3-го нуклеотида кодона на синонимичный +def test_missense_label(): assert difference_effect(coi_c, d) == f"{aa_ref}{n}{aa_alt}" +def test_stop_gained(): assert difference_effect(...).endswith("*") +def test_frameshift_and_inframe(): ... +def test_minus_strand_cds_puc19(): ... # замена в bla даёт верный номер аминокислоты +def test_no_features_empty(): assert difference_effect(Construct("x", seq, False), d) == "" +``` + + Ожидаемые значения вычисляются в тесте из известного кодона, а не хардкодятся «на глаз». +- [ ] **Step 2: Запустить** → FAIL. +- [ ] **Step 3: Реализовать**; подключить `difference_effect` как `annotate` по умолчанию в `verify_clone`. +- [ ] **Step 4: Запустить** `python -m pytest -q` → PASS. +- [ ] **Step 5: Commit** `git commit -m "effects: amino-acid consequences of clone differences in CDS"` + +### Task 9: Отчёты по клонам + +**Files:** +- Create: `chrom_core/clone_report.py` +- Test: `tests/test_clone_report.py` + +**Interfaces:** +- Consumes: `CloneReport`, `CloneDifference` (Task 7) +- Produces: + - `clones_csv(reports: list[CloneReport]) -> str` — колонки `clone, verdict, region_coverage_pct, both_strands_pct, differences, reads` + - `differences_csv(reports: list[CloneReport]) -> str` — колонки `clone, position, kind, ref, read, effect, support, against, status, note`; `position` 1-based + - `STATUS_HEX: dict[str, tuple[str, str]]` — `verdict -> (светлая, тёмная)` hex-цвета для `ok, errors, incomplete, mixed, no_data` (единый источник палитры; UI импортирует его в Task 13) + - `clone_report_xlsx(path, reports: list[CloneReport], construct_name: str) -> None` — листы `Clones` и `Differences` с теми же колонками; ячейка вердикта залита светлым цветом из `STATUS_HEX` + - CSV в том же стиле, что `verify.verdicts_csv` (разделитель `,`, экранирование как `batch._csv_field`) + +- [ ] **Step 1: Падающие тесты** — строки заголовков, число строк, 1-based позиция, цвет заливки ячейки `errors` в XLSX (`openpyxl.load_workbook`). +- [ ] **Step 2: Запустить** → FAIL. +- [ ] **Step 3: Реализовать.** +- [ ] **Step 4: Запустить** → PASS. +- [ ] **Step 5: Commit** `git commit -m "clone_report: CSV and Excel reports for clone verification"` + +### Task 10: Проект `.ab1proj` + +**Files:** +- Create: `chrom_core/project.py` +- Test: `tests/test_project.py` + +**Interfaces:** +- Consumes: `Construct`, `load_construct` (Task 4), `Grouping` (Task 6), `VerifyParams`, `Region` (Task 7) +- Produces: + - `PROJECT_VERSION = 1` + - `@dataclass Project(construct_path: Path, circular: bool, region: Region | None, grouping: Grouping, params: VerifyParams)` + - `save_project(path: Path, project: Project) -> None` — JSON UTF-8 (`ensure_ascii=False`); пути к конструкту и ридам относительные к папке проекта, если лежат внутри неё, иначе абсолютные + - `load_project(path: Path) -> Project` — `ValueError` с понятным сообщением при битом JSON, чужом файле (`app != "ab1kit"`) или `version > PROJECT_VERSION` + +- [ ] **Step 1: Падающие тесты:** round-trip; относительные пути при переносе папки проекта; путь `tmp_path / "Данные" / "клоны 1"` (Review Focus 5); битый файл и будущая версия → `ValueError`. +- [ ] **Step 2: Запустить** → FAIL. +- [ ] **Step 3: Реализовать.** +- [ ] **Step 4: Запустить** `python -m pytest -q` → PASS. +- [ ] **Step 5: Commit** `git commit -m "project: .ab1proj files for clone verification sessions"` + +--- + +## Фаза 3 — интерфейс + +### Task 11: Фоновые задачи + +**Files:** +- Create: `ui/tasks.py` +- Modify: `ui/main_window.py` (`_scan_folder`, `_blast_submit` — через задачи) +- Test: `tests/test_ui_tasks.py` + +**Interfaces:** +- Produces: + - `class Task(QObject)` с сигналами `progress(int, int)`, `finished(object)`, `failed(str)`, `cancelled()`; методы `cancel()`, `is_cancelled() -> bool` + - `run_task(fn: Callable[[Callable[[int, int], None], Callable[[], bool]], object], parent: QObject) -> Task` — `fn(progress, is_cancelled)` выполняется в `QThreadPool.globalInstance()`; сигналы приходят в GUI-поток; исключение → `failed(str(exc))`; `CancelledError` → `cancelled` + - В строке состояния `MainWindow` — `QProgressBar` и кнопка «Отмена» (ключи `task.cancel`, `task.running`), видимые во время задачи + +- [ ] **Step 1: Падающие тесты** (offscreen, `qtbot`-free: крутить `QApplication.processEvents()` до сигнала с таймаутом 5 с): результат приходит в `finished`; исключение — в `failed`; отмена — в `cancelled`; GUI-поток не блокируется (таймер в GUI-потоке тикает, пока задача спит 0,3 с). +- [ ] **Step 2: Запустить** → FAIL. +- [ ] **Step 3: Реализовать** `ui/tasks.py`; перевести сканирование папки и BLAST на `run_task`. +- [ ] **Step 4: Запустить** `python -m pytest -q` → PASS. +- [ ] **Step 5: Commit** `git commit -m "ui: background tasks with progress and cancel"` + +### Task 12: Разбить `main_window.py` + +**Files:** +- Create: `ui/read_view/__init__.py`, `ui/read_view/dialogs.py` (`SearchDialog`, `TrimDialog`), `ui/read_view/analysis_dock.py`, `ui/read_view/verify_dock.py`, `ui/read_view/batch_dock.py` (+ перенос `ui/batch_panel.py`), `ui/read_view/read_view.py` (`ReadView(QMainWindow)` — всё, что сейчас относится к одному риду: вью, миникарта, доки, правка, обрезка, экспорт, поиск) +- Modify: `ui/main_window.py` — остаётся оболочка: меню «Файл/Вид/Справка», язык, тема, недавние файлы, `run()` +- Test: существующий `tests/test_smoke_gui.py` (без изменения утверждений; правятся только пути monkeypatch) + +**Interfaces:** +- Produces: + - `ReadView.open_path(path) -> bool`, `ReadView.refresh_read()`, `ReadView.current_model() -> EditableRead | None`, сигнал `ReadView.read_edited(Path)` (испускается после правки, undo/redo, обрезки и сохранения сессии) + - `MainWindow.read_view: ReadView`; публичные методы `MainWindow`, которые используют тесты (`open_path`, `apply_base_*`, `undo_read`, …), остаются как делегаты, чтобы `test_smoke_gui.py` не менялся по смыслу + +- [ ] **Step 1: Перенести код** без изменения поведения, по одному блоку (диалоги → доки → ReadView), после каждого — `python -m pytest tests/test_smoke_gui.py -q` → PASS. +- [ ] **Step 2: Проверить размер:** ни один файл в `ui/` не длиннее ~450 строк (`wc -l ui/*.py ui/read_view/*.py`). +- [ ] **Step 3: Запустить всё** `python -m pytest -q` → PASS. +- [ ] **Step 4: Commit** `git commit -m "ui: split main window into read_view modules (no behaviour change)"` + +### Task 13: Тема, иконки, палитра статусов + +**Files:** +- Create: `ui/style.qss` (светлая), `ui/style_dark.qss`, `ui/icons/*.svg` + `ui/icons/LICENSE` (набор Lucide, ISC/MIT — проверить лицензию при скачивании; иначе Tabler Icons, MIT), `ui/status.py` +- Modify: `ui/theme.py` (загрузка QSS), `ui/read_view/*` (иконки на тулбаре, растяжение колонок, тултипы длинных ячеек), `ui/chrom_view.py` (цвет полос качества по Q), `ab1kit.spec` (включить `ui/style*.qss`, `ui/icons`), `pyproject.toml` (`package-data` для `ui`) +- Test: `tests/test_smoke_gui.py` + +**Interfaces:** +- Produces (`ui/status.py`): + - `status_color(verdict: str, theme: str) -> QColor` — из `chrom_core.clone_report.STATUS_HEX` (Task 9) + - `quality_color(q: int, theme: str) -> QColor` — `<20` красный, `20–29` жёлтый, `≥30` зелёный (те же пороги, что миникарта) + - `status_chip(verdict: str, text: str) -> QLabel` — скруглённая плашка + - `icon(name: str) -> QIcon` + +- [ ] **Step 1: Падающие тесты:** у каждого действия тулбара есть иконка; `quality_color(15) != quality_color(35)`; таблицы растягивают последнюю колонку и имеют тултип с полным текстом примечания; QSS применяется (`app.styleSheet()` не пуст) в обеих темах. +- [ ] **Step 2: Запустить** → FAIL. +- [ ] **Step 3: Реализовать.** Пакет иконок: только используемые (~20 файлов). +- [ ] **Step 4: Запустить** `python -m pytest -q` → PASS; сделать скриншоты обеих тем через `scripts/render_preview.py` и посмотреть глазами. +- [ ] **Step 5: Commit** `git commit -m "ui: QSS theme, icons, unified status palette, coloured quality bars"` + +### Task 14: Строка-сводка и матрица клонов + +**Files:** +- Create: `ui/construct/__init__.py`, `ui/construct/summary_bar.py`, `ui/construct/matrix.py` +- Test: `tests/test_construct_ui.py` + +**Interfaces:** +- Consumes: `Construct`, `Region`, `CloneReport` (Tasks 4, 7), `status_color`, `status_chip` (Task 13) +- Produces: + - `SummaryBar(QWidget)`: `set_data(construct: Construct, region: Region | None, reports: list[CloneReport])`; сигнал `filter_changed(set[str])` — множество показываемых вердиктов (клик по счётчику переключает) + - `CloneMatrix(QWidget)` (собственная отрисовка `paintEvent`): `set_data(construct, region, reports)`, `set_filter(verdicts: set[str])`; дорожка референса (фичи прямоугольниками с подписью, рамка региона), строка на клон: покрытие (две цепи — насыщенный, одна — светлый, Q<20/нет — фон), метки расхождений цветом статуса, плашка вердикта справа. Колёсико — масштаб общей оси, перетаскивание — сдвиг. Протяжка по дорожке референса с зажатым Shift — задать регион. + - Сигналы: `difference_clicked(str, int)` (клон, `ref_pos`), `clone_clicked(str)`, `region_changed(object)` (`Region`) + - `CloneMatrix.hit_test(pos: QPoint) -> tuple[str, int] | None` — для тестов и кликов + +- [ ] **Step 1: Падающие тесты** (offscreen, данные — `verify_all` на наборе из Task 7): сводка показывает счётчики по вердиктам; фильтр скрывает строки; `hit_test` по координате метки возвращает `(clone, ref_pos)`; Shift-протяжка испускает `region_changed`; виджет рендерится в `QImage` без исключений в обеих темах; 12 строк помещаются в 600 px по высоте. +- [ ] **Step 2: Запустить** → FAIL. +- [ ] **Step 3: Реализовать.** +- [ ] **Step 4: Запустить** → PASS; отрендерить PNG матрицы и проверить глазами против макета B. +- [ ] **Step 5: Commit** `git commit -m "ui: construct summary bar and clone matrix"` + +### Task 15: Панель деталей расхождения + +**Files:** +- Create: `ui/construct/detail_pane.py` +- Test: `tests/test_construct_ui.py` + +**Interfaces:** +- Consumes: `CloneReport`, `ReadResult`, `load_read` (Task 7), `ChromatogramWidget` (`ui/chrom_view.py`: `set_chromatogram`, `set_reference`, `goto_base`, `set_highlights`) +- Produces: + - `DetailPane(QWidget)`: `show_clone(report: CloneReport, construct: Construct)`, `show_position(ref_pos: int)`; слева — стопка `ChromatogramWidget` по одному на рид клона (компактная высота, общий масштаб), каждый центрирован на базе, соответствующей `ref_pos` (через `alignment.ref_to_read` и ориентацию), с подсветкой; над стопкой — строка референса ±10 п.н.; справа — таблица расхождений клона (позиция 1-based, `ref→read`, эффект через `tr`, за/против, статус); выбор строки → `show_position` + - Сигнал `open_read(Path)` — по двойному клику на хроматограмму + +- [ ] **Step 1: Падающие тесты:** число хроматограмм = числу ридов клона с выравниванием; после `show_position(P)` центральная база каждого вью — та, что выровнена на `P`; для рида на минус-цепи — тоже; выбор строки таблицы вызывает `show_position`; двойной клик испускает `open_read`. +- [ ] **Step 2: Запустить** → FAIL. +- [ ] **Step 3: Реализовать.** +- [ ] **Step 4: Запустить** → PASS. +- [ ] **Step 5: Commit** `git commit -m "ui: difference detail pane with stacked chromatograms"` + +### Task 16: Экран «Проверка конструкта», группировка, связка с просмотрщиком + +**Files:** +- Create: `ui/construct/grouping_dialog.py`, `ui/construct/workspace.py` +- Modify: `ui/main_window.py` (вкладки «Проверка конструкта» / «Просмотр рида», меню «Проект»: новый/открыть/сохранить, экспорт отчёта), `i18n.py`, `translations_en.py` +- Test: `tests/test_construct_ui.py`, `tests/test_smoke_gui.py` + +**Interfaces:** +- Consumes: всё из Tasks 4–15; `run_task` (Task 11); `ReadView.read_edited` (Task 12) +- Produces: + - `GroupingDialog(QDialog)`: `__init__(grouping: Grouping, pattern: str, parent)`, `result_grouping() -> Grouping`, `result_pattern() -> str`; таблица «файл / клон / праймер» с правкой; поле шаблона с предпросмотром (невалидный regex — красная рамка, кнопка OK неактивна); строки «без клона» выделены + - `ConstructWorkspace(QWidget)`: `set_construct(path)`, `add_reads(paths)`, `set_region(region)`, `load_project(path)`, `save_project(path)`, `export_report(path)`; пустое состояние с двумя зонами перетаскивания (конструкт; папка/файлы ридов); любое изменение (конструкт, риды, группировка, регион, параметры, `read_edited`) → перезапуск `verify_all` через `run_task` с отменой предыдущего; сигнал `open_read(Path)` + - Поля параметров `min_q`, `het_ratio`, `mixed_min_positions` и галочка «кольцевая» — в строке над матрицей; сохраняются в проекте + - `MainWindow`: вкладка «Проверка конструкта» первая и активна при старте без аргументов; `open_read` → переключение на «Просмотр рида» + `open_path`; `ab1kit file.ab1proj` открывает проект + +- [ ] **Step 1: Падающие тесты:** перетаскивание COI `.gb` и 8 реальных ридов → после завершения задачи 4 строки в матрице и вердикты как в Task 7 (для неизменённого референса — все `ok` или `incomplete`); правка рида в «Просмотре рида» (замена базы в позиции расхождения) → пересчёт и смена вердикта; сохранение/открытие проекта восстанавливает регион и группировку; битый `.ab1proj` → сообщение и пустое рабочее пространство без исключения; недопустимый регион → сообщение, проверка не запускается; отмена пересчёта оставляет прежние вердикты в матрице; `GroupingDialog` с невалидным regex блокирует OK; пустое состояние видно без данных; все новые ключи есть в RU и EN. +- [ ] **Step 2: Запустить** → FAIL. +- [ ] **Step 3: Реализовать.** +- [ ] **Step 4: Запустить** `python -m pytest -q` → PASS. +- [ ] **Step 5: Ручная проверка:** запустить `ab1kit`, пройти сценарий из критерия успеха спецификации (перетащить конструкт и папку, задать регион, открыть расхождение, перейти в рид, поправить, вернуться) в светлой и тёмной теме, RU и EN. Обновить скриншоты `docs/screenshots/` (`scripts/render_preview.py`), добавить скриншот экрана проверки. +- [ ] **Step 6: Commit** `git commit -m "ui: construct verification workspace with grouping and project files"` + +--- + +## Фаза 4 — CLI и выпуск + +### Task 17: Подкоманды CLI, документация, версия + +**Files:** +- Modify: `chrom_cli.py`, `README.md`, `CHANGELOG.md`, `pyproject.toml` (`version = "1.1.0"`) +- Test: `tests/test_cli.py` + +**Interfaces:** +- Consumes: `load_construct`, `group_reads`, `verify_all`, `VerifyParams`, `clones_csv`/`differences_csv`/`clone_report_xlsx`, `batch.scan_folder`/`summary_csv`/`batch_export` +- Produces: + - `main(argv) -> int`: если `argv[0] in {"verify-clones", "qc", "export"}` — `argparse`-подкоманда, иначе GUI (как сейчас) + - `verify-clones --construct FILE [--region A-B] [--linear] [--pattern REGEX] [--min-q N] [--het-ratio X] READS_DIR -o REPORT` — `A-B` 1-based включительно → `Region(A-1, B)`; `.xlsx` → `clone_report_xlsx`, `.csv` → `clones_csv` в `REPORT` и `differences_csv` в `REPORT` с суффиксом `_differences.csv`; печать короткой таблицы клонов в stdout; код возврата 0 — есть хотя бы один `ok`, 1 — нет, 2 — ошибка входных данных (сообщение в stderr) + - `qc READS_DIR [-o CSV]` — `scan_folder` + `summary_csv` (stdout без `-o`) + - `export READS_DIR --trim [--fasta|--fastq] -o DIR` — `batch_export` + +- [ ] **Step 1: Падающие тесты:** `verify-clones` на `tmp_path / "Данные клоны"` с копиями реальных ридов и COI → код 0, XLSX с листами `Clones`/`Differences`; на изменённом референсе — строка с `errors`; без ридов/битый конструкт → 2; `qc` печатает CSV; `export` создаёт файлы; `main([])` и `main(["x.ab1"])` по-прежнему вызывают GUI (`monkeypatch` на `ui.main_window.run`). +- [ ] **Step 2: Запустить** → FAIL. +- [ ] **Step 3: Реализовать.** +- [ ] **Step 4: Документация:** в README — раздел «Clone verification» (сценарий, формат имён, шаблон, вердикты, CLI-пример) и новый скриншот; CHANGELOG — `[1.1.0]` с Added/Changed/Fixed по задачам 2–17. +- [ ] **Step 5: Запустить всё** `python -m pytest -q` → PASS; собрать exe `pyinstaller ab1kit.spec` и запустить — экран проверки открывается, иконки и тема на месте. +- [ ] **Step 6: Commit** `git commit -m "CLI subcommands verify-clones/qc/export; docs and v1.1.0"` From 2cd6d198c3addd1a425c83cb8faca370054e592d Mon Sep 17 00:00:00 2001 From: Aleksey Drobin <43707931+adrobi@users.noreply.github.com> Date: Sun, 25 Oct 2026 01:40:24 +0300 Subject: [PATCH 03/44] Test corpus: real sangeranalyseR reads, COI and pUC19 references Co-Authored-By: Claude Sonnet 5.5 --- pyproject.toml | 1 + scripts/fetch_test_data.py | 87 +++++++++++++ tests/clone_fixtures.py | 26 ++++ tests/data/README.md | 36 ++++++ tests/data/real/Achl_ACHLO006-09_1_F.ab1 | Bin 0 -> 216576 bytes tests/data/real/Achl_ACHLO006-09_2_R.ab1 | Bin 0 -> 215996 bytes tests/data/real/Achl_ACHLO007-09_1_F.ab1 | Bin 0 -> 213387 bytes tests/data/real/Achl_ACHLO007-09_2_R.ab1 | Bin 0 -> 214468 bytes tests/data/real/Achl_ACHLO040-09_1_F.ab1 | Bin 0 -> 210808 bytes tests/data/real/Achl_ACHLO040-09_2_R.ab1 | Bin 0 -> 210388 bytes tests/data/real/Achl_ACHLO041-09_1_F.ab1 | Bin 0 -> 214651 bytes tests/data/real/Achl_ACHLO041-09_2_R.ab1 | Bin 0 -> 214899 bytes tests/data/refs/coi_HM417896.gb | 78 +++++++++++ tests/data/refs/pUC19_L09137.gb | 157 +++++++++++++++++++++++ tests/data/refs/sample-d.dna | Bin 0 -> 15730 bytes tests/test_data_corpus.py | 36 ++++++ 16 files changed, 421 insertions(+) create mode 100644 scripts/fetch_test_data.py create mode 100644 tests/clone_fixtures.py create mode 100644 tests/data/README.md create mode 100644 tests/data/real/Achl_ACHLO006-09_1_F.ab1 create mode 100644 tests/data/real/Achl_ACHLO006-09_2_R.ab1 create mode 100644 tests/data/real/Achl_ACHLO007-09_1_F.ab1 create mode 100644 tests/data/real/Achl_ACHLO007-09_2_R.ab1 create mode 100644 tests/data/real/Achl_ACHLO040-09_1_F.ab1 create mode 100644 tests/data/real/Achl_ACHLO040-09_2_R.ab1 create mode 100644 tests/data/real/Achl_ACHLO041-09_1_F.ab1 create mode 100644 tests/data/real/Achl_ACHLO041-09_2_R.ab1 create mode 100644 tests/data/refs/coi_HM417896.gb create mode 100644 tests/data/refs/pUC19_L09137.gb create mode 100644 tests/data/refs/sample-d.dna create mode 100644 tests/test_data_corpus.py diff --git a/pyproject.toml b/pyproject.toml index 3ad6ba9..03835c5 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -27,3 +27,4 @@ py-modules = ["chrom_cli", "i18n", "translations_en"] [tool.pytest.ini_options] testpaths = ["tests"] +pythonpath = ["tests"] diff --git a/scripts/fetch_test_data.py b/scripts/fetch_test_data.py new file mode 100644 index 0000000..0512201 --- /dev/null +++ b/scripts/fetch_test_data.py @@ -0,0 +1,87 @@ +"""One-time download of the real-data test corpus into ``tests/data``. + +Usage:: + + python scripts/fetch_test_data.py --coi ACCESSION [--force] + +Uses only ``urllib``. Idempotent: files that already exist are skipped +unless ``--force`` is given. Tests never touch the network; the downloaded +files are committed to the repository. +""" + +from __future__ import annotations + +import argparse +import time +import urllib.parse +import urllib.request +from pathlib import Path + +DATA = Path(__file__).resolve().parent.parent / "tests" / "data" + +SANGER_COMMIT = "4c5ebc9298a873c209819f12b7dfd85e126f1406" +BIOPYTHON_COMMIT = "2fbe8755bb44731e60b7bd1e2cc55cf34d94e15b" + +SANGER_BASE = ( + "https://raw.githubusercontent.com/roblanf/sangeranalyseR/" + f"{SANGER_COMMIT}/inst/extdata/Allolobophora_chlorotica/ACHLO/" +) +SNAPGENE_URL = ( + "https://raw.githubusercontent.com/biopython/biopython/" + f"{BIOPYTHON_COMMIT}/Tests/SnapGene/sample-d.dna" +) +EFETCH = "https://eutils.ncbi.nlm.nih.gov/entrez/eutils/efetch.fcgi" + +READS = [ + f"Achl_{sample}_{suffix}.ab1" + for sample in ("ACHLO006-09", "ACHLO007-09", "ACHLO040-09", "ACHLO041-09") + for suffix in ("1_F", "2_R") +] + +_last_ncbi_request = 0.0 + + +def _download(url: str) -> bytes: + request = urllib.request.Request(url, headers={"User-Agent": "ab1kit-fetch-test-data"}) + with urllib.request.urlopen(request, timeout=60) as response: + return response.read() + + +def _genbank_url(accession: str) -> str: + query = urllib.parse.urlencode( + {"db": "nuccore", "id": accession, "rettype": "gbwithparts", "retmode": "text"} + ) + return f"{EFETCH}?{query}" + + +def _fetch(url: str, target: Path, force: bool, ncbi: bool = False) -> None: + global _last_ncbi_request + if target.exists() and not force: + print(f"skip {target.relative_to(DATA)}") + return + if ncbi: # stay polite: at most ~3 requests per second + wait = 0.4 - (time.monotonic() - _last_ncbi_request) + if wait > 0: + time.sleep(wait) + _last_ncbi_request = time.monotonic() + target.parent.mkdir(parents=True, exist_ok=True) + target.write_bytes(_download(url)) + print(f"fetched {target.relative_to(DATA)}") + + +def main(argv: list[str] | None = None) -> None: + parser = argparse.ArgumentParser(description=__doc__) + parser.add_argument("--coi", metavar="ACC", help="GenBank accession of the COI reference") + parser.add_argument("--force", action="store_true", help="re-download existing files") + args = parser.parse_args(argv) + + for name in READS: + _fetch(SANGER_BASE + name, DATA / "real" / name, args.force) + _fetch(_genbank_url("L09137"), DATA / "refs" / "pUC19_L09137.gb", args.force, ncbi=True) + if args.coi: + _fetch(_genbank_url(args.coi), DATA / "refs" / f"coi_{args.coi}.gb", args.force, ncbi=True) + _fetch(SNAPGENE_URL, DATA / "refs" / "sample-d.dna", args.force) + + +if __name__ == "__main__": + main() diff --git a/tests/clone_fixtures.py b/tests/clone_fixtures.py new file mode 100644 index 0000000..e99bb6b --- /dev/null +++ b/tests/clone_fixtures.py @@ -0,0 +1,26 @@ +"""Shared fixtures for clone-verification tests: the real-data corpus in ``tests/data``.""" + +from __future__ import annotations + +from pathlib import Path + +from Bio import SeqIO + +from chrom_core import read_ab1 +from chrom_core.abif import Chromatogram + +DATA = Path(__file__).resolve().parent / "data" + +REAL_READS: list[Path] = sorted((DATA / "real").glob("*.ab1")) + +COI_GB = DATA / "refs" / "coi_HM417896.gb" +PUC19_GB = DATA / "refs" / "pUC19_L09137.gb" +SNAPGENE_DNA = DATA / "refs" / "sample-d.dna" + + +def real_read(name: str) -> Chromatogram: + return read_ab1(DATA / "real" / name) + + +def coi_reference() -> str: + return str(SeqIO.read(COI_GB, "genbank").seq).upper() diff --git a/tests/data/README.md b/tests/data/README.md new file mode 100644 index 0000000..d9666ad --- /dev/null +++ b/tests/data/README.md @@ -0,0 +1,36 @@ +# Test data corpus + +Downloaded once by `scripts/fetch_test_data.py --coi HM417896` and committed. +Tests never use the network. Semi-synthetic data is generated in +`tests/clone_fixtures.py` and is not stored on disk. + +| File | Source | Pin | License | +|---|---|---|---| +| `real/Achl_ACHLO{006,007,040,041}-09_{1_F,2_R}.ab1` (8 files) | [sangeranalyseR](https://github.com/roblanf/sangeranalyseR) `inst/extdata/Allolobophora_chlorotica/ACHLO/` | commit `4c5ebc9298a873c209819f12b7dfd85e126f1406` | MIT | +| `refs/pUC19_L09137.gb` | NCBI nuccore `L09137` (efetch, `gbwithparts`) | accession | public domain | +| `refs/coi_HM417896.gb` | NCBI nuccore `HM417896.1` (efetch, `gbwithparts`) | accession | public domain | +| `refs/sample-d.dna` | [Biopython](https://github.com/biopython/biopython) `Tests/SnapGene/sample-d.dna` | commit `2fbe8755bb44731e60b7bd1e2cc55cf34d94e15b` | Biopython License | + +## Why HM417896 as the COI reference + +*Allolobophora chlorotica* is a cryptic-species aggregate: its mitochondrial COI +lineages differ by up to ~16%. The four samples fall into at least three +lineages, so no single GenBank record is >= 97% identical to all eight reads. + +Candidates were found with NCBI E-utilities (esearch on `Allolobophora chlorotica` +COI/COX1, ~930 records) and checked locally with `chrom_core.align.align_read`. +HM417896.1 (voucher AC2, iBOL/BOLD mirror, 658 bp, annotated CDS) is the record +that fits the most reads and is the one that matches the ACHLO006-09 / 007-09 +lineage: + +| Read | strand | identity vs HM417896 | +|---|---|---| +| ACHLO006-09 F / R | + / - | 0.995 / 0.973 | +| ACHLO007-09 F / R | + / - | 0.995 / 0.992 | +| ACHLO040-09 F / R | + / - | 0.822 / 0.821 | +| ACHLO041-09 F / R | + / - | 0.836 / 0.818 | + +ACHLO040-09 and ACHLO041-09 are other lineages: their best records in GenBank are +KC569719.1 (040 F: 0.986) and HM417923.1 (041 F: 0.997). They are kept in the +corpus on purpose as real, divergent-from-reference reads (useful as a +"many real differences" case); the corpus test treats them separately. diff --git a/tests/data/real/Achl_ACHLO006-09_1_F.ab1 b/tests/data/real/Achl_ACHLO006-09_1_F.ab1 new file mode 100644 index 0000000000000000000000000000000000000000..bef826013da0329d3da945637f7b215ebae1ace9 GIT binary patch literal 216576 zcmcGXh2K?G_P9^odtbUsx&@>|x}=d(P%N-O0h6#>?8F{N$L<(sbaX}?#|{(~5DAg) z2I+dg&vVYq??3px_jB%h?m0WxUbWX+d+$Dd2M-7)Oh13p)F24LxHzcA|7(MwY!Jk~ zx&8nBSEJ9!ktYuB->>C>w(Z*W@6)zr+sn- zF?}yRXX^Pq`g7N@W1DV$rcOQQ>XRp3GoeS9PTfwPFm=*77Y(0r@wpSG_V|A#bPL)a z-@eUN7X^hjUD~v7->FUM;g?=fuT8t->b0Z%{^McJqHn@jCAJ@cE;7DQ!7G+70~L z%H3AlxRn&U_`id+yC`W#@mjvukY;`HGV<=>>00i$7Ox=1My_>y?@XU;PoJ$T-a_rx zxQjQIXYQ?hn|ddA=C@7j__cww>qxUVz1zf--+8iyw0nzJ^K7}ff|wKs)BbJZiGABe zIos3HvmWl`>5er0W}fdz+pra=?c(`1(m6hxXubW~O3CX$%@T%N$2XP*`oC4VIt5c0G9=g;mABrDK-Wv6|HDNU@yKSCDH}Iu^@GYkM4xwLBAY zTS>Q!C+kVOlK)$|+nTn_{A;++(wWm%S>7f}TShv^Nx0iLA-*E{{D?xtk?Qiar6jMFw!3dujXHd3njh4?mFZa=bi z{KkLVWG`3oW_|G@T4`HWl6EoqR-~!3)-L6_kl4saybv1pW)1ml`7(OyxNhc&uwP2a zwm5@$28A_gZ`P4|efr#9*pJ1Ow3PoVcrM=An+%7R@@5%t{Jnv6|AV}AwTiZ8lr*2x zmXgN0mXT(4@vq#k{BH}_({I}<^{yn(3VyBPBb_bfdrz8nG4JfxGM+61&dYhajy`SS z`6}*zCEqfxtPXp-kd*#j$omDPwX97%SwbDwxSckNE%s8#EKge|u2`NU<0!4cQ0-kV>D?q=+=|2tF8`Uj)GlXl1F@u`ip!v0wTBE9I>sQTVEqV=bZ-X~A)v zpSFDoy|;I()Anv4-{!Q9wo+(I=Th4yKDK!k6!kmlg@PlNjrwxxk`oJmdDLnkn&HVp zQg7pzeOkzyY#bbK%a+@UVYVuRr=ughm!;$DXfNWubZgJ7*Ae=SU$#QbutZ125frPI z@x6dwi+C%9y)4gsV&iZ8mqxN$#3gasKB~t^rM5?!w*S(;V<@B@AEmzfh!7OY8Rr&X zY>h3I|4L(~l(Q~N>r*PpAH;b}k*5kLdo6r2d>0RvkjmO@Z-$*qxfjB}Q}1SS*)HKO z4tkf-nv`Rk){t^8&!rAO_Rp5tKgVAEPWpB{vp(7)N6XO_(qfQ2Q_2xG%NTPxqWYa! zu`_LlFjG?hk0*&C+xXblOxD?Yxteq%7A;TfSL1Um)iup6wA2XYb;@aBZ(3!+5`Ig! zaw~gb>P$A+Z}lYQf*2$o$q~dr@m@TzOsPsLRR+uLR?~WGU!B&j79o~wNK7$#{yYA|?<)8|mQbBp% zI@c(sWz0U9W9+7WA##BF4pWv|vv>AtV+tMl@MhX&y&I^HTF^et=bU6Sa(D+N?q*(; z1SObNl}kSbW>?O7a{S6Mv$0)aI)6J#U5CiQh4x=e9fzpz2;Y0TiYePU-8N@M&i}aI zOUvV+Oi(>2qGy#Uv376_JuJ_xxCAq$vb@h*19?K`RwbyJ`5e6unR}HD%JW@<_c`vX zP)_Nf0^e16S}CZ;lUhL|U{yP4$Gq$KpnottI6W8_ObN~o&JQL9Ck0)CzCrh(MbJ6u z5%ddA2u=+y2_^?O1vdxp1z!c<2RnidL2(!aTZ7+%?}A5ydxDE8p?A?!NY27E2YAo;0rKanHTY_7IJAKz|UqkUI$O$sg#?hhUe9t%DWHis3%3&VNQjCerO zIysszmETn8QFysfF8_7DYHn=uYBDhym)wvWp4*zAl3$nqGXGKjwA|CVcFD5j^5o%U zZ?0+X{oK#FhjZs8_r&|-=FwH*{_s!Xl(0=$C2SO)6h0iTiB5~F#6KpN|OE*;+)?@r1m4dXB3H{v02&1g?tF}^Qpl+4cEo9~prI)7gN!rYz7 zVszk;Xe#lw96g|U7Zns|)5p9PM84`v5n2fqfp!fxR$QG@8K_~+!G zx%cv)=I0d}{-#Aw>UL0)*_k|}1yMXB|aC{m#elheh9=bY_8qR<^PE0w+2%Ze% z*9fTV6zJ^)sId>6pch=IX>e>%Bd7z9s|RnZ9yAQ<^W1l>;11oP-$798c&KY4*!Wf0 zG`uTZ9!-pvF%qq!UD3-?oAC2+5>R<5xSHArkf$BoYycdq2RvXfwGO4Ek(6{&Foc@B zz@OR$$H6~q1P$PB$HDCgvF|_zJ+B}qA^r78D=~s`SQ(8hl`qqyp^5>@XrX%HzrFW;0b25D9W;oEd zVI1BQZi-HgHbz^c-=n`qH$-*Ahr*`d{43D-xO6-Qrd)Y2^`1g|MgZrr)H>K_)+!I|2-EE8G=&fjMxI3H{wg}e2g(e{ZMv`L;5Ex6o zGw7o@K8X^q=cz4fLv3wS4C>CNoTYU;z&5y<9C;3~JlTmBL}4<}d|b_pMi+C`tn zgX0zPAMuX(lekaxdUQg#Gn^Y$i5`tFNiNJa&uz;$$+yitko+V58LDm>{w3@h{D35X z6N&Up@FCZGz~jqcTi7t16>g0#iuT9n$IIf?@rQA(=>Di#_(@n7YX3HP7asagxb%PE zuCvMgL-0pU-73$VFW__vFzrj-ol?lvfkQ=Th&lAa;-CoqQoT`)Ft2{e6`_UhMjPH|8s1cfCzb<_ zRmtC&UoC;PdS^}GTOB^9)>xh21^&zV%AlW?Rd1yXwbvs-IdtEIXZRxir{ zNcGs5?>gjeobvl>DMu|u>hfuMi8?JhH9ic=QGd?!DGP_qG}aQ-Tmz1L3}uw1CDmwO z5>%vi{T``4O+N~}Q9EwP`!ck>h$p4_F3U$vxGoshi1&3i+<>=DfpT+TEpKVcD3?q7P=PnKXm+ zC=@GGS7o5mIE8N`-W*S^w&ZHTrzb6F1k{>PMle0X1QICud*Hl98WM1FKhA#xmbwx+!L z{I5aHHGy%hRQfjNe=S;Ci`F#gi;#t69N9q{!Fql)n{@z=>)${EF13&#qLKj*?4Iav54t8d@Z!b6zkcEZ!Lupnhkl&Ubg| zzht(1sCWbKW8Q3IcD^#D7(ji_ zb?qV4$D0zQVE#v*M3#W5UMoXK; ze4#kJIs7BKG1?1e$Pp(br4XL9MpZ1jAhLNaG zJ;%|CreJ-W^nYvUu{FPXaUDyQG>r9ZWKR-b(Jf!SbEx1sh9z_Bf3 zT8Gj*ra2qaqHaLGJy5R=oZFI4o5Cs3@#(4dI0Q&v6TBH76Hbq+Mt_Y5#vjFB$MfPR z;?~hS;pXrfbl~H|{^2uGo9NlN6LZQPNs0Ko__AnEbZ%5STpDhRdPT1?2pn68{&!1o1@OKM?d%M=_(0k{3O#B(SaLf3J_mTJ^LGPA%0GE4 z5e@uTCUyhXO2oQASXtf{hcFgctbofv%-&1HVuH2PaK zHCzuJ~Z`Qv3zdqjq>-I5eCd{t$JG zR>dRZH{(O`c4SLkY%`m~GlDJX>er@N(VW^Ur1e)uFFOQZI|R2q49Ag67T{I~Z47*s z51fo=yp>0(B^BVf#oQ71L82(*-E!izlzr-R+#R9Rt?<8Xl(WOqxz8+&a$I6GsBH(= zE}qIa^U!eF6yJ+d-d@Vmsl5PS-2&G&`s5%SGN$E9j#5D-^2z1Ux`0_}zKPqQj50v9 z0`IXt!ikH0POHn2G6%$~0DZY>^)#i{%Thco;;prprM@EGs(Y!El;>@ol%nb|s!gD- zW?+{T-I(#M%KsYB;jz%CT0sqR)S&gpP>!|)-__z7+9)klCL_Ta;YyTQlk!{fPEAJc z*o4v=lA}7$DwDSXI8%=_N{iS&rqUpxoT{X0#7hYO&;wpeh^!D_Y=s<;ho|4Vcky#KG^ zpkNs@EA5SE@;M2eWD4J>fj^V5&OIKi2U0*MBUL2bU<0!=L*&7sTlgJ-cvUJv)WC3-im8y_F7g;(_o z-wXQ(8?lU?18;Etrabji2Hl|~|0~kA8vL&XE~v%$s|I&vxmV7Lb5bf}!-$q7-!^(- z&V*J;LC$7qZ+cgt2YYF6rjt3Bs0mz}F!pU3%YksKQE=ynf}gR=UK@TN#Zfuz7bW3M zW5Xs`+wO(>DoAC}t5IFX_Q;X2=5xOdKZJf2y{~%OcHxQ8W3mT&)|0XWy4TaL z$KGhLKX@wb8!w|b&}bkdsf?sC+6x~HHbs+t3jM`3cSuR!#1f73{DW1zE^E@w2 zU6pxWhMM;Ctccd=Cpp9jm7rX7a9UvGn=xWWv7zshMj9whNhK+@EF)5i-__)`;E`NR zJ-#F!6f{gm%Mmk{?hvKO>7);_OD~Q-GWBL+>Uge&ut2@dfKV;+${ov7vi8pQU}9#) z>jajag0~SVS0`CD>m}g+&=z?z31#E0e-X`2D4cj9N z`yeMjN0zn=9}MS)`=UNktEf!)G4sSK*u3w?>e2@aJ(iIPQv9q+G=_ zT%iSZwoR$-j$mDQZnz-2JZ^~o@(vc3m*YnG2&#nlhpn(oUyJrvkCv%Xm!-uuXlq^C zS}z^(l8i?h9Z8$^rmfL?w=ccd_h|H-KD-@i%ax3J7WJNHkz~dyGV5`y89`-ikVfWh zr#I535oUT%jgeVJ@APCkBQkDIAEsX6Exb3p4P++hyVJ@japny&h5P2 z%eP+b_59XrufKLV&$a+dy|$K7Os!jq2-w6EW5)DS8^0;d>gQccIeOtuwVS8gNoQQp zZb~r{$Tl4$$g;*7~L>cMCFIQNmt`KLT7fa{kd<$g*a)-x?j+K?_c@x+KG zxyMTK3hVvw8hMK`XU1O`C9s`q8)ZT*(jcWdN0XW@2dP5Oc0f&PBSwe{TcRKt&ob%Q z)&`Tcp>;{My7B0YUxX)wzeIP(HR89ETFIcKZBilrXPiW*hqJ?Oc%^Pe9(Dw4Yl9cg zODpkTIbJcPPd&n!-36-`xLG!(RiiHV(nER4Q7|agqQF-@zxD+ab_)7 z!pOK+acp}^9Rc+@ikmq8@=r~J~jAX9j@DuaYn3eRwi}^Bo|8;mFPr!EjLc9?D zzI1d)xGuactPp&H<@_9G38ymK(NA?6P;!PnlUeM_Z~*?f#?jN!?{SCt^7z8ILG*ky zAlwsv8(zY^|D*5_o`;{~_VJDJmGLxYJpYIWhAYB8_)zCDuG1)K5S-mvYfCtHYi2%G z;ege^`qt^_JJULo{^-x1fuHZ0U|v{_+2mv4+9-^gM1!KX;ZbzW>0x>7`>!$XmmvlE zF^>I#o!*H4l+}V6baS3MV{em6mF}rD>Bn=e?5!Bt_KdtbxHg4mq;3UHXmO~C3~5fD zI*d&#$~u$F$d zEMBj|iL~`>XlDYgyplQcYj|)!15e(@Tl93?13&Z;y!YMkrd$^7j;12B-ayj6i8MPU zdL=F&Ujv@ZgKQFz&ixrPh4$VM$Wj}1Kn8t zlT^%&k)PTowJB>wJ-~Bkb@JkJDHp9p=@sdJbFgOw^Q-TIz2Ok}S`yWWdNUd)gui0t z9*8yKuZ+^UK)(YJuR;kWXm_@5!&!rNTBF63N!n`nbE)?jHRiez*JNO~phqFUv{RtR zBl*-*)W6h6Y~fzsS+2HQwGy85RN1OEI9q38UD_tp&h`Td`%;$?(9hn8(Qd}bcZYM_ zgFo*`*b038M^q81RXHpU7ejMH!vg-W2a#@FNnL~fR0R*v=;#$zT*wX#>>a-OLTM0>n-IX_m@uSu^;^9xHdn!+C5)MiZeH6`F{d0JDOR*4re zznsltAL3~Zv<5XyXBjEXfVIB1!{9}+c)vrI(}y4WSz>nn!q&Kyn4x~jyUEsEX)J}u$A6BFM5lz`g{KB<8G)Oi z^$x(<=m%}lddM=1k9b!^ziV+-N&Bm`*E+91Ob?u1w<`3$5xM+T3d*+E+T$IA3S7qS z83mI0dbH?h?P&>~8gbEvZ~Zw#;2bw%Pb?SqgsW~07s0Le)5ZsgPZ~lb&p(m9my+vP zO4CYH7x^ZASce`xqcp06RmOa@q&K~h*v3HIOf1s8-~hg%NpQX|!(XGyQFSb+uZ7Qr zcVN4`9uN3Ij7c8{9lUDJ+;H76pUqwCOA6JDTIPoC7P=A<NOr1JC^vS9%^i$ zk$1J}eG}g6v#Q3E8bHX1MLkK)kf3e(^aT(5GD5?_!WWs-RSbvIzl~TIFNAkr0Eey> zE)1^>8{x5k6m8=~q(f66tBq63gOQL@k{m}oOrYPxV1o4JELWe2+Ll^eJ<@gp&c;=A z0}`X)9iy4?zXcb+7<U-7SRgTij@T>vt(I3(RO+wrohsO1JSUK!Rgpx95F`Cx9KzC@E57rRZFp*w&V{|G~ z0`^Wm(rO3>S4w#b^MC#`Ux%`@b!=+w&a#|)IRjeHm93$0mS(K5>#>}N9OZJ}zY}WO zkT=~_VzG?Gy2(?^&WcTEZYcE*Vbv-u^-Ma zEpI1Jw9aJlxJKdnW-FI*{YI!d8#JQZ6>P42Sw#*0cV1zXy|Lm(RU55qbh5F%>)_4K z%hpqxYX-Cmt>gDfE>|Y$moo;}R$IPt=dN$i_GFB)tI~`NcFmBn!A9a6O}!fTIpCC%K?@9)AzJ5LUn`^ZXG|^fo>8v` z?lvF2l0iKjmD_pd@{J zt;yX9f0*&GZz8SAg?GcZ>O`ZXd(h|p9la4v!BV%4ILw*h`QhbwTV^va=nxGi?xknc zKB|q!ZFcy2_&oW(35$_%lgPJ%`OP0hz+4=~=;7Cg#|7Jw5%;&k8Agwf2?;_Rc`7a>ZbRzTLV& zR!feYq5_;wc`xMUbJ~Xw0{aqpNshw(l#besuz7T@ z>;Oiv6u@$1BKKP0)D_eX;oj7$28rGW*2Z zt*lIY8p7p`2N}qSOiSm@%b72p2|xRHxE@aYOZWltaCb8zW z(WdBM#3Nlq1n>eD!w)Z6X(*sp(;Mj*(wrDLtL0X#(>j?avH zA`|#_?c0$Q9#Uj^`311jYPHuCLWNPzxJ#;)!i!h~Z4IQ*8h8j^<|>u_Ja<)(HqMQF z@1P`BTc>FcicQ?fOI#zM9;Uvk?Hz5FRNnu=z3X(hkWSm4>k_pz${}4*r96-yZ|BNt z*A8cGt~Aw}m&q^J)n+RmT{EKH&b7)~6%X;o6(p{%aD9jUbnU`+{wqE9P(C<7d$3T^ zwgcR0HFv#)7D7D;%ARa(oU+kXeAeem6)l!~sL2(DuG`S=E2Lbhp#JZAap7%xZHG!W zS9!P!Ln*8EQfak`cdlx524NYF8NNtbxsDR>Yk=olC^1_Z z(Nm`AnQ#`w`UU8;K3t&_mX--{pnnG2!vYrXvEdb1ImR*Tt&6I#DR_=ZQ|F||gJJ49 zMYMud@q9K@hY)kbR`b0Lj8Q%*fvwdQRL(~-++!^aeE%S2NR6)CI1C@rM+Rl`TrVN= zfE?-UOz6XJlv6oceUyIs?W+F6;JF$Gz5@E9WN_9eFVnZ62Sa%xzfybB|5k>QeWven zKX1Tf%5k>opBxT8#~bLKJaQdplX@1Wkaqj$bOQo}e2V-05#o%jpv zWHc6|dEpUgc?=q6^Kb|J;CAd#2be=Xfc;}MJpXv|I#<_w-UzL45SEsEh+o`E{z1V0 zI&`9$*tMpj$u%H8eI8Ma)5&Rsn^sxp2!*US8Be24&fSe6DT_>KO4&W&Oc%oWp9pq` zb;8rad(pV7!GDHEO^Nhgfko%yurn(M-i3D=!P1UiWsz$}b625%)o5cA`kl=L>(N^y zy1UVaR!FVWm?z$fXZ6My$7EzH<^Sxf_e<=d5~Y7}m$C)dmYvYgRx+M1;Hw zgj|c$o>H_tYt1DNf!efXWF8P^^kAd79ziv`xjV{#eF3ShKb_~R%c_BCInb-94-T0{ zPn4hHLn9#FES-U!%8c#>;y{`L!Fj~2bc(Kw9z=(EH+m=<#!UbH@U-9%R=r1qwhym$U60|Am@-U;BtYMg4L9NfrA2tX)5#_M%K?SBENUfyF}^-Ft~*UPRn_Z>(iQ z(MOICt25&&5zJw2!!=+`U$CG7u#E9<>RpstmFUiO(s(bSLp|yrY9OX`e3T$^5$!+n zp1tsxy(tWpLK#QrJ?$)_EaTLaWq1((o6mJ*>YB{5vmTLF{t@w19sqadt@=)$G1!&L zeMdsBZIp=iBU8KnEoS_-lS@rSyOUNcy%S~luRe^;guYaTf@*RZ{n?XQ<#@R0^Uz8| z=;T>6fsxVO(Y&ZQE=io)-ssO!LuC59;V5R^uY=#Gkwbf4Jz9)@OvwfCK}!X@iqIN& zC2{n@1KPxViC@nCT`3`tXpDB)9(?GBrh5r|X9FIJ5$GnrF%uuaJaiN`tT9m?w8anL z1GS*pzhY56gB)F;)yDKdE1+JV($ufEXAku|0U_$uRw2DOtE@(vjPp2iZBD(t!G&>H zL-33QJD`S(&~IKxBYg`k=5F+v&S6>T`0upqTJ+Zw!9hJwEwC^eac1=9<@my9(I(gV zEGI_%SMENB@}EPizckgHk4^Cis~vb?tOLH{6mJ-fbj0NPYP(v~wE|4SrvEo$=0b4u zE<8NBsC3j7&AkDd`|5BGQT(IBQo$<5=sNi3ne?C|&}avRPl2~T6D%a^s+C|u{t>(HabY7g^M7E`ISpvHpdZ>>l}Biw;F7XXDXa(kAmfGC4u~3AfyT}6jF#m; z+NzX1N-3>?+A@VWeoSDkq_<~9{N4{oC0Ixp)#p_khg00Rlv-esTMqtF+3IP z%3oQ{unGHDHDp--unF2jl`v2I&HHd9@mXtdqqHwlkUq~p_C2$y`*u4u~r~kq?YR^(?E?4FpZXH_o`7l#Y+vYqBDch&YHkz#?<+s)}ejrZ}DG` zyjr*Tmhx*-tWC>PW6#z(yYG>DxR)4hO7~kLdYLDB()E06!QIYtee~AoOhS9Eka85< zaVfI|6?5k-#@KKp?&P9cFW~tpwh?p1TezG!33l%Sqva#cN^|s5POps72cKdnWiz8C zb%?ak{-DPsv&IK$LfvY`$_3Z`L0(}fk%wb*6`&bv>;mJ(+qF%D*Xx;VD z(|W*ThQV*{B{KL!^uO|92c+g@*v7tqUv6g}`C@n{lJq#%2+zerc0P2ZMYCy2soFx+ zsPSCTGIeO@si}UP_BNB|mFXE&MZ2Aw+umC6DdU`ttUWI{8&3TKv&a`|!8_<~ub?&F z3+Yv1QRs`$;QR7@r~C`O63tDbaGJQuqGQ zwjEFlEWINL^m!?F2 zF{4+CkV`9WNJ>kWa+MQVluNejgY@Mb_b6j06*-F~?mv~BQkJ_H*cM}Qw(&Nb56i3E zYe3tiu`>3{y^(~aeR1aOb9ZMDqQWAxt~!s`Qfq8nW`UJ@$xkcgvCeQ0r<~>hIjwCi zwQDI@K@MYrjGd7;J33k0wI|r;{b_sL0ZdM8?1>R1S{K~W%6YZ$mCISN46Y0o6Puib6}X>|rTQtbcr^Ij3||e=wv_6;R_~rR zlQ89{N&sj4?hquum*cyimVHRM9W?1|Qs0&F-u;*Z-Uo%vVeYjd*uzYr9<%O*nwOy6 z+zUO90`Ke7%JR?`)J0$AyQwvRp1OB}5=XA8zt8&Bg@wKR+I~Ctw|>W8`Qf;^H=Fil z<)Ay}DB0W! z1^dgOohk2}C)Na;wS{PX*Y2u4$LOqln#%c5Ri4%0msWj!Xq9>5T*4UgEY`d(5~vQ( z^=Q@QSp{bEM#2n5Ce1(sJWZVCH$-5z2|LlYJFtlS1)IoCNXN5j_p!`je`PO#TbKmxJXLCWo&+S-k8ItRJ@INrFW$f62przfQLhk@ZlYUqLW;XLL@ z7xHU75k-^mQ{INpe=swrB53ss0U}!`l=}?Ih;4hBh^mir|vD5^+=zmz0Z27)*z>5=9JdwoKM<6 zl=gNL+(3_~Z}my4#j6R)Ki2Ty*^ckD(`(7L498ZO?WWawZ>>%3-2Hlljq?Vjzxuc_ zmTBZBH5z^Ej$F=Yw(?d;**Z0t%q}dJsL$I1V_-IuUmoqKix2W?p`v`t<~{P|jOz+} z(}+uAg%D8VP@8bCRCFUWd9AswZ7^=BQmWr)>q^wf-4o{~ynXLMy$g}+wUD;e!>YtD z1+1iBg4gVM-d+PGpMWK{7V+r&;g-&Bjoj8>B8PVVp_fDbL5{26NR2}a{Z6>B-`Vb+ z_B)$LIdil9&V2N3D4`F4EzTQ_ffi4&nNyCD#%eu`0>6~#yO?t`0{n94T0OBwptzQ| z0W>;>c)Lrnuf7*73roQRIxst!27kOC-g6n8{A_05C-JN`Ue89@So6%E%ZFvq!Iwkx z|Hig-5q6$|DaRCEuEHSFpZ4fumgaWSZ~K!`rr4klgFSQkZl5i2K?$w)VfUXX86_8OS#{m5*^wm{?ty8`=11r|k z@U1VgCM<>9Ek`^14IS-M?8tXuzn%>D>II)`g>bfjRz~vZJybHd=Gxtp z+^=IS^M$LCbhF^2V?TxzEUz;OR8*@C0a!6(7J|T-Ph1rARM_D?{8d3tJa;JGa%FtNmL0tPv!7ZH=3X(&w(^HxA0@ zW$2sI(tTC3we5Por=s)T3ruHmU5DlHTZA*4G!gU#s-il^9*Q%>P*S$ngd z<=S9PQ{-hgM#lEvN957#VA(uqYYdjl_rhiPT+d=%@mtZycy2euwc_UZ1f8UB~aBqrX3F&rkz?`lttNop6+4kUX|`nC(m5Zo%2+6U3U*Q zW<(v`J%;6=Mw2Y&`UCCQ9S^nbxGSrB8@l(Mn(c4ocF#vGJMN9Sn0H#bmU6kT<_7N6 z{5KVUL!PB*{n_4v?g;9Box;!=fO5z96YVwTS5~=Cv0AMhUoCq*bvegSIw-?^=e~XF zy1%pD!o4O}Q;v}~_GSxOue(7SJF}2)^JiMUdlR}}?OJlp<66kwT&`u@&t*?b_jCM} z_se)|yv%Y+vLDV1w*EJUMp(EXr4VqpN!z=Ee2dcbi@9^}KcVUViMG-w?hWbQrb|*t zxl8RfE_WssW{c9&+%?pFLtRnt9*j%*p2x4Bif5DZJDx10jf?p#;{SZEW#kr~zmnG9 zztNY4X&Jv2|IE7|NV}Bhzw)up1w37v_Du+8wf#U1j;XsBF5o-c^VHp#v)U|Gxcx*u zKXd;hsaB=s{hF3we3JW`E=+52kIbLBUsn7*E&G|2i+TRPeNDv@+xrWt{QjL^mNlPm zabXE1F5udbmgX3^-{NAPEGG3r%A7|k;VQ&_r2KW{{hoY|wELMZ=Giawdnw~-Y3}Jc zpSCZj+=Xe&=ThP#-nz@{{50JU-2KAcJW8BP9@B{(U#EH8x7M=#{*@=cr={8IMcgf- zWOoX6Z({p4hhK|$H;42-|Bm}#>76BJa9TjEOL%YIdDLfr7w}u?{>Yo}(vhCWn1935 zg_QdfDdzIA6=K6e`u8jMVyiG-NWNu!TmP@TcSlNlWSYg~v*dX^&Dw8I=kS@$wS*GH zcy~*kL%rttj&uuBjGIGVOI!5cQkHQ4Bdrp?v-w`a`_*YmcSBvwIEb(FDdT7I&E~)5 z3DJ3!I-9$>R z$&VHSmv6cMCCzR5vnlUO%FVFR9{cn+N-+1l^p`n(YX2?c7xLHx|1ajLBfcc+8(EXk|-K|&LlB3N7g3^>D_7mmI<<0M;5{HG^oZ`>8&oJ_5p12RQSost8 zLep{kopkfK6L+(b6NBcbJ(^3&-}BUzmia9y?Te%EWBL)A3-~4NW_3#4bAg3@{DS4E9z@azX@cQH@rq-_@xV&9KxT|e<_4k?A}Y_RDE+PHvs^SOK{_Wr;}OtWwH{uj!# z-O}Llv{ch9=eLwD^?pNH(yy@jDecQIX;}-?TITZP$F$b3crVs|$8X0+Ty%85=UyE7 zJ}vQo@Gyli`ib8BNR3~mbu-LfaCW(TgH`fb7_4(>3%N$ocHGWk#ZgDjMIFZj;c^p3Mi$8l2Bes3VSS8Nb&P2 zRr1}`Xx4Ex?yNJ1iZrxPZCsGi-QOkx_QKMg6Wv}k7MbPP_=R@?8`9;6p~ z)LlQIRZNQ<^b6MOh1TKXlS`T7c_PiEslUQfIuVl;v@DzykNeN~4U zGiSj*w`QTUgC}c&!B%+}rD!v9tffKwXIe)APb#HnEB~@+nrycTy(Glprg<}p+L3Y< zDcSJ>U%*Uh-^d7|qrYY?^;xd{&Q_Q>ZpL$Ido$ufTd`E7%{jB6igWvbb#^w5u&_S; z#rlZE6?uZb7wrvVrZMA=ls0F%LS|oeX9BU?HGpDf#@(cJMwHRDKG$dH9d@4*)-A$G zE5YTB(>D?a-izf%3^zi@ebM;^=Z4$z--t)!7~J`sG}LkziqG=9s-dgE^7@WO{R zkEFb`fbE>V7nsaUMJcbv7N>l+u> zwNuJn{Vg8ax6B?b%!RdHPVvm>UTI3>`%}hFz16ZO@GHe7kv`85tWRaO^JegSF zC`(^TJ|&1YdiRA92ZY&roax`r9#EBg|qQPmLRRjwbTZDs)Rri&_6W*ch9ib)~*l4Xm_Kl#2RTJJI_wZ zVw9D%ppGM_605{Bu~e$oU!rH5GRQ3-^P}g-zN<~abIGa9^~44(dRp*>t`wTBDON_w zx8(0e7CM^Jb>?{y+TyNUPa45P!uxb}8Bep8S*Cr#2S|IBw$i=YkR{3om5HWxB!r#O z9ZH)Fi1-0;vw}6Sx|w#CLhB^*AQ_`<01siu9fE*^-t;Nj#D6?2+T+c-wY+q?8c@ zmC3flZ#4knDz~v_v|yfWu@@nN>q6o6hVE)n(NodIqRSdvD@~W-WI6ai$xh;8B0fGHP6HzBT@7^FlS-z zAf^@L!HLOfq*JP~@Xi?xdsP7&_cL`3R=RUCIo-R9*fB~p&ZPpEakF|n^m*xFF}B?u zS@nMu;URE+8EemYUy1y#B&?YFt84SW4*m(h-Ou=cJIA|zLBB#}JQ%L0b`M(p749M0 z2p>-?ybpTv`w_V}5#Nhz3Puxw(;a_OUpz!7@uoj%hG5elidU!u_g#2?GCuZ!_&ZJ` z?J3+(Ag??1Pr-L|H{SH?@N{?r#Km~quHnf&_*JgJGvYZL!ztAj<3=sGlmBo^7|q>j z*5%%qg{>tan<2vm5NG|5)AW zwevLwu?THnnN=kpDC(L&KDi>E#D3>x*->XQ@fEf4L)IZydK;gOM42og%3(eG#upJI zUKhV?H=>58;J=^l@ao?+e1w6JBmE9c88wC=&LExMT8o?u+L2$Amve!{W+G=iEd2 zI@c3`+MKqFKSzE+E#{Kce)k)Va{FJVLya8BDqt%ns|1+SzyTRm_@aX=Xkvzx> zlp*26oPY9u{Cx6m?!o*ug_ecIh0hC3^S|U<04Tx9aH~ z1igE1fp3Na-Qir_fUPHTOab^*(v3SXgWLmDC!xP<4l)7^o1AP+ z>ckgBSF$?#YIf(T6o%{oU6)AXQp95QByQ?$_C~Ike3?JCu&%@pCAXKls8pkpkCbRt z=$bn@UJ-rDdhDU;IWvDD`cnwpLO-U`@_Xpf3#_<%5RAN=v33O9e|QLEVtm$BV1qCm z&RDij{rOE8ubwG2y7TXyK<5FVaUD>95eO_IHfufYidhr&F{l2t;1r39xi|97^G!JO zr+xBb(u5t17bnA$)tuV#Rqh|T=aWrI&v;PuD64~qh6z0UKk(|Oh&6kS*sW)wv^#0< zW8j!OaXkrsJ`cV>newoy=^C10@Q0z$#FdQJEnL^Y-JXFiUt(NV((9k#a+}$ErI?tQ ziBQH<@ngwT@VKJFdxgIhUd(UF?a$qitCSqd4a!%~e_bdPS{F)krqaZuecUy=o|R=? z!xqG(FQZLAr6*au2dr+Tp4)-p9klBaAb1-scmbS!i@HCh=H;YaLA2Z%~{#J zEP4(6?UlPFw>$rGeq8RKjBES2TXaeIa@dBJ&L`i?^zKpmJOgaJ0W7?MTBgx2Pga`A zc-_E=+{wEq=-)%o>(lU`FIdyG2dugpx%EaoGr2O?EB7TQM3u{pNxtAzlrik0+CIKD zDU;lvE0L?a2a=Pa&NK|;ow8zIG$N_GF)mT z7;-K2`v@G{h|t%ldm*Q5EQ%hCKh2fNpIkVt@Im2lVNCv+T(x*}w1rhtSD;J$ot79c zcuC6Z+?~1|b({npjD|`E!voZ8&Q32+h;i4v$<%NIRCQj;_s)in+!fpNSFQnj0GvNcA0VrqkY^_Cx|Q_PX~iV^ zeKBQS1H7&Pv+sb?Cz9?)uA6vw7Z`XId7lQ7w?VC9{U+9$T?^-XhEqp&CQl?kC3BKz z+4<$%=nYPncoFQZOO#0jrfmyzM5R>+%SML(jylId{upaWe_$Wg)yZSY>|}Ftds2w+V+Zm|tXixcmO{$>3+?HC^rsm>;#x-U zMqu&`^#3*#u@b7^2;HwhyIeuU`^`}kcyq_x!}&>t>kGFP+UM`jy#RgmV2`9_Ij%yUQge?gxgO5 z2W~;jc0V^|<_+M+<4D2}*!_4pG5%k$3j8f(_wnHsQA0-g>fEdO?S&DA^_&Lw4A34F zmtwW^BVi?=`4?#8QE>2PDCc&le=>T4(O3gmV%4lf8h__MTu-cmx=q@5dDQ_61dY-^kB+Kn7Z+RF9zCz^SJz!!Nq}8ze z@cbY7J^7XS+Q}F3)zRCm*Et!v_6kyNI#hHv^yGPf7g35&uA~j)X~Stysk5rVw9)fP z`cm(er1TsqbzA%3Ov{t8)P+t>xt^y74&&}Rpg0d)c_r!?t>i4GmB~=xvphZ_dLgQg z-dKZCdL0-)0LDFpJiHf3e-$(z{_#1C$m8shbC~kF zC7u?Aeo&(cQQ{d1g}m6Mq?6XG)tKdbZixF)b|xO! zng4OfL8Zw=N*)2E-L?Eg+TqEao`N9W4y4XZHy@Am=|^h!^K@i9CBw1u@=U!Rw6_j# z-95S?^=M%*ioPAPs#S{b?mK@2v$`34-vbmL59YH^z`fDPxOvhv*`J$`o6WeiNV+l` zx`*8@)%QFHa5C+fMBX#N$|7-obA3{iQT~iw|1J-k!jX`7VH8dWVjUQHb(QYa<{2w(x$8yklgKdv{GJRoUc~=f zg7;ZV|6(+ZQ^$Tz#v~sn%Q@Ba2G05@7foe1o#TlRew$R+0>^WK+Av1;RNCUnC+(?! zAmwY}=>^`L#0a`CfommPC*zJBok%~7yP?#0Yw#wsiksO%obm=zQmqufS`h=>mGa#g)%BmQZX7|LX<)YF>ggD2 zeJ4}z2vUxuh3pA`n?Rwnb} z|8O3br*G^+7T*SkamITArH`X^+8IXk?HRPgsi8Zt><%4x8cZW>Zw=^o6?$EhyBU$#%eCFe!%sgG*9K^rwXW^vXSz&f`wJl=t3+UNH;WxfVY17vy>kc36BY{x110 z->WdRs9(|Sq7j7&`R2@5y0a%~$gYA{$Nx^wg^vt>YL|ULm>B)Lx;vlX8wC2?GZeThhu1oEMt#J@3 z|RzafRQ_NA43XH%5ks82Ea=0=dLpS z$z`4L{vp)Soi<1bZOG?IFw)~7%Ct@HSm+*&?jbykH(C@=0|Q)9Rhxso}V1fE#dsvhx50ii>--QM*obC4KG8>{14c21*0K1 z8b|r=i!g>3jisg`;Hzt_JS{BSBc?4p*Asr+Yf?LhEBS>|Z$9pX(u_B4X;lx}tqo)p zr5F|8hn~AqsW0i(UOb)g_LLLe1s2Q-{vMVHXR-s<^PIzYQSvofU`pKZ_s}KgkJu^e^)urXP<%r;eJkQdYl>H z&-qL9uXAef(A+u6Om?DtmetqCK@;~dOXvp7-6dE^cLC%SRv(^^Pa#$ZIJql_XVyufYIDQ6qzF%9I)f5DA5$G<7JTI?G@HB8 z#$IOUiu&Pm?C)Qdy^=TOzRlOj56YjC>ziE18MXgrANLtyX*9Cu(8=BcYM!C2webvU z^_)!Yb_40hFj~@qntFk89cig2yY(PN2kLhxD0hTXQXUJvc7-20T0_9e4t%?ZwLG#D zDLpHp6JzYIpPj(8)|8|aZ$#f~k;nCT?lC%yUW%8>!)!0+wzS0apl=4Y_kfEJqcz{h z=W#5~JHqoA-vjYm$=$i@@{RI+^A&S5;p#DaSx;aM+-PP>i{St-BDJ)~P38VMbn~`o zs_mjb;#WAg>GNbqvMza$6W)%CuH)RMGguq`BYNV~Xl-}G$!~%Nrn?@WnbUny`DiA4 zi7!ZcB-4{yl4kK;oO;}!^?MDG9uETfbHRDf&^{a8Vmi!^c=szJXIIcli|tY-KqI(TBBd01GuNBqYJskjdr9{iVvixjYXI%;PfNSf@+6 zwwc?aqw%@yB>P!BIj(_!pc^~pxv$HQ?BX~Rjb{h?Y1!z5=yI@PX6VlFKVbJzW7aQn z8}xQ_`gsM5WyA3KsAcp(T#cRY-;H<2PsWW|{c$@py&pN5sseVG3h@Q;{P>&rd$fU} z?73cznmRED)$XaaLkp>EVD!#B0sig4zi}_;;XHv&XjJ?q66#e>@qRdJ%G|sma`ii) z=XxOR!4v7}O+a7QP~y#P4hKx?0)y|bY57lHaO%+qefg7;^3jQlO>oZOq- zoz!M;@?NY}sl(dS8uarEILTLV@wLoB=QC@1kDT8!qplym7EOuAC&P2M=Kox{qVPju zWPV4!R<2omg#F7~hkt?Ieq?m-0xmbvANO^T65Q8T+*N-$kuewr4d^lG!>=AG2RRPB zYX<%_pyiF>7VWs)J5en4l(EeA?Z}@-D$n9{ZIr&a(Oj2M*F*Hu6UW_&;#S)GN!T6h z>BP84GBkH{zC-?tLf8Dke8b$dq%rpT(^+-f1PjAg(Clb!6^;B5r zQWg1ctDKwEqwUAj4|PiCn%cB)1hT7G<+Lao5iMjUdok9@ao8Z<;*{cf;ZQ6vo^h?0 zQz_xfHTP7uC$9c#&3{jH9RLJ8RnQfCYWCMb1N)fwEs4(I9J-qErL35$8O@DO;&k`( z!N?C8-!mAY6H|O>N6Xy5%##s35wj(~yYi-K$^q4OJh`|h*x}CoZGm`S^6G`s2Q`5< zUB+y9CV09Ef6?sdCM>(ZacafvWKVJU)N%x{VrM53r;R z>D_hPIiX%@q2_-04T$G*HKIGHW&4@xpLS-N`K4>5oR~at7@q+WimU z-S{ZFAZ|rJhb4C+^QJS`yAIpKknowXD_DCgJft_&*(L2)b70qy`aMxgd~+3FWm=-v z={otw)O9TQp1asJmj&0C9JOHqxv z`cRT5^tPgO&*1V5D9<^+0M2m^koU}B&xdaV&h(=!XN|q!DU;yPC#SryJNZ2i(>?Xv z38-tTag8K>3)*))Bk740`t?udb1ItUg<$b$aPeHYLnqqR4XQt$oZ8aQDTozGEky`=cM@%A84Ym~#{-MrGJJUz@!{S&jd8{m`w4t`@Nf_tMp8rRLqxmazk&E1o`KUalW^s4ym=pA;dJ&(Qm z7a&(h#jnSIj$h-<;a$kV6WC*T6B^A9c29pM+8qy#FN@EMPm4Bl;_6k*rq*y`))4Mj z#?#|PNtI+Q67&sD8`;R|bseL6|Hso=z*|){f1lka?!9z(cXzjnf^>(VAf+N8E#2MS zm+o%q?hpj>sf8IFSe#XVrfs6fsg9O$<824SVV7Boq9n`8n*IV6a~8_eX8ncCT2b{ zcZn7=fECI>DVe4?@BAFk>9?ZVD|z{@3JKY{PgQu7Szi0>KgCOpR8zW0CjjmtVt`aI@AzoY8*k5u$ajoxmui8TwV5)DnLWl z7uC3tmqfaFZLmlBsn%A(sysc*!&7D9C_#@@pG6g(wHB#1c42<0HclqKsaj4pAM&Mr zepUh)O3y4tTY2caG*M}>nSh1#(iD7C-6B<#R~?c(94W;pm5n0{Pt+_*tCm%>2hvM- z-viSJ?dB++k6*~gx6rC)y~4`d%^qrhVm+naNffnBzcuqx)uuhzl-HVsJiVF{=P~GeXsrO~$wMK)(>M&+3n*6g^jU8s%J7eE`*;6<18p9LpXf z{+oj%s(X=z`Bsgd%tD->6d%}W%X$Ztbyw=7>dxxP5}7U9~wj958BbI=#f?`Mp( zGd#Nq{i~0(tZX3{@MHXhFJY$Dl-jhVu^Z2|zhG3!$oia+NSPQcEPYwc8ZmE*+7K-B zgJYTDnJM9vF+Pr}5~Av?D;H@3dZx+)s_LRD36i&j2ciyDXH7+aQqV)`V9J@QJ?N@` zF4;(&QM!V1Rcc4Ka>u6P8E^5-w|v%FJg8AF{ILs}@gV z=2})*RfQ~050pbj-U`*(O2x0-w3>~cXXL6H@V`c^Z>^9p+xYLVpnYi;d&tmI841;Z z2d&1-^47e87pe?7VZS#jV|Ck%b#DyXTr;37O{_dmm({imBb9_%94b)W!76a^=1_v7 zue!l6_mi`+4s`)bnf;M+FIlb?fUC`+<@e-u+=lkDEas%fx*+z97dx-%%CT`kix5DmC8+>o<;T~>e_zo%ySkyW$jH=TKWc#Jd4Vt zZOxUI2QTezy|HFn4XG`Bz^spl%7b^8qB_%6D>b#P79qXYL*LkIeoak|wMKGe_33c% z)<|Ks7@a7-JY!U~BVoE^3$4S+pYZW{y=KTQydc&p>ieM({1U)_t&1nb?(uLvpO5 z_>^l-a;UhnvHojvWInp;GL8ib{ z`USGv7GUr__@~~gR=BF5B&20!Ly(N6v5WT+@8j;{;| zdO}1O*LU$q)w|HjlLR=Zj=XYZlJOqsB;cGf#HtR5YI;b*RJBOy2FjF_p5KahRK_LM zYK!BKL)F}rcOe1SsrIs}u4Lqy!t^4nAmZ4PWJFAQBf_jVmvD^SLFp`R3-CE=&g|dO)IhN z1JZaD5g_aBcfhxa?>8Hb_W2a;Z5TRwUaYY1tc2)SZ;%|S6J@mt=o|37jp%yg(0IE8 z?;%jv1USI#INOP&sLR}xBqC@TKJ?l40jGq0$L>JY?;_NTNkFVdK4xhdT3s`r^JtBc zHBwczl|fgSrcAiSIF<{DN^6rop>-k=$IByS)$+A&Y3!r15pBjYRGt{bCRi|vS;LWh zj##~|?^%1tVZ9hdBx6D}n4zq{-*RVF+K}!eYRd*R;{r+L08YltDKoS3W<@d&E3=Gn zMtG5v8A%UJ3-~Lwyaw$V@ilyk)s3~(xoc(qY;HEkn-$H>ammYk*B5LDXO;MXSntw?w@l;*@0ENTk?ziGUB+h&dDAm`@Ghb%=AgCop`y9 z6reR}3F0F1U8vT9szyZcN)fQK^GdH2*O8{1npQJ#T_T{Xo=A4m(JUNE3JetS8>urv z-ge@O74fTF%*xTCY7WXGtd^9|QdLLZ0X0SXYJZFJi+Qvucq+q~sw^krm5|~(Nkq^R817sR8!q{*=SVTI4%!wpwN#K%0>M^@r;b7BPvF~CBor?@#&s=K- ztg=>D*7dqn7vGCD;tHAU@?wuuu5Vf9tFz9E&kBRYOH}t;`lzZtOMj8%os+%`Yo(h< z(MP?KaxN>q$i{WDpj70)yev8RFRPrg?XGOGIOq-X&jE4mf=te=hRy#NzZZFSwkQ=N94VS}SB<);f`a zo~GuT^s#(gBaK!$hDvd_JW+ZpSFY+YmZjC)T%mk9(!*3gUJ|JC0Y;vg4PLFfjulx; z6j{~~nXe0Dk~X^t6GKH~GF1(xny;*ERx6@=R#QV2p4K)Gt5QjR69D?bY)uXIO^1w8v_p;$j+fyydTtGw`m9iE}yZAYuiffa-OR;P6;?5)T>LqJv8)FaJ z_;T}45=4Y)r4qB|D{PuMy<{- zwbcT+D{G>>+#OldS7Whv$m81r4z4kiphh8g5XejkqWw^5r4aSxDQR-1>-=T;JY zOaGZq%zkDiGYURkmF#LKvHbr;f4>EC^=PpS(EOAqN;a!Xn~KZo!4>M+XeeyM~wVUD}gnd*Cb?^AJBEiF?$|&7c;^{{LN#Gz37kP zOS>{VvYM9$60&p2moK;pI+9Uj;}Tzy^r4Zdj&W6v$S*A`YEv**x`HHRWrLUJQF|cj z(XOJ*gcpK?Vj2{Cp=h1joNdK7?X0QhKS4Ot2uLYnOy0CMz)Y26o6)m&;E!IiYU2{``7%3Oh!{}r@-6#Lc@ySzQY{@$KR6zBKW8ml%H zTx$|3HP9$UjNl>gWH?+#9!d578%8Dndrd|$fTOK>Peo^(3cYM*XNd!!SWR7%dgiZI zVPZ)RVe9xEZ&GjbvANx>VEhhVWCo`;<6Rrgs5L{X3tJCbstIJ90h#t3ZB6^#X!Vyk zm)ToWikW>wRfi2$3afxs9Z8}Du`oBW$i*`bg1@PKPyTp%`aP}W1n#o1$-*FdP{c|l z=1aLYzHG7R`H_R@gq-J@n2Lr%>SaUjao|)*`K5#?9 zb`V@&F=ev+R-wnL%B^vf^f}=tJW*UtySBcEy0#Hp=#p)52vy-4!Dp{nmGCom#qv1; zE7e2nRGp})k(&A%ap7qJ)`pzWZhF&YhtLAn)|^Dt9RpAL(0j!$D;h*u=VVWjTqx-y z3Ez^j$|q(8&45gl7Kufb)0E{yHJhlBi-e~-M#xdfBOafU^Ad4wGUO6j0~~%!2A75> zjZ*DNG7BOFscxEV{E~L0pGty|S5C55L=Q~BHL4n_{c&nX`hGIzFJdQ@O|T;Ga?D#9 zo~D}Ol5DkVE80VLSVj3n*79WBTZAjKfHATcDe^#ml6*+9(#0i7D3V0hA$fpOa-X!a z6wE{pu8YSpRj-tlGzZTufV88hrJ=v7W}Acas+27mBx1pm4NF!y=~t3abf4r2=?e10 z2nxyhFTGm(4dr=L-M|dMG>hLuX|b|<3d^NoYZX@9s-$+sjCO)Hx`7QN@xuJ=M}Ypz zERQ!ITP@(T8<9V@u=;i;ieR?+sd1f*zzMKaZD1|!&b%w8{c}cAgC48;vTA%sEH#p; zWx0#gB$ss|BO}mgi}9@>zhz@c3%}LsDw|v}#J-lJ50cFb@RB5ds5kVRWsbEL+0#8W1nO4VlcRu)o4(ximW63-{&cor*hU(Tm4@vcF2Nl)fj~Ity4Fq{Xy6 zN0nz&p_L@%N_o{(+RTFVk_&E} z3~gsL5=%Dr8*OLx?#FCv1;`E86Wyxft9*>oEE6!-@~x|anY=MM!9MBJ5zn^lezNK) zt|h>K^&}H8PPN;KgtGS@Q&0X_0VJ^nPO$5 zh-m4WN8Ke2)}rr8!6w<(axnkmfwI09;0nb@XRz`d_ocdC zNE?TUtI3aTx+Lp-3_IBNAcxmB@)8ww1nIt$FLPA}=L+&P**POV%}=3USqig5Q_=>9 z!H*8&iHM6f_$l~5mF&SMurv=aCL&3tH9V|M^H{5X#ESP7vm_5w#PXn-$if`Sax9HA zQUzO)51PLS_m{md3D_3|Q>D$za*zo~$`>cjT>uQJ z4vzeU{Id+*vH{%>wm4$V+0D8z{`aBbhaS?WF9f5Mcf?L;Mj3s@(E$vkL zwES7Ju__)}mT*<<)=r+;NP9Pkkk81T!@k&fX2CngkVCl@yK8cyIo^bCFXc*kTN^Pe zl5UGI9@$mXfe{6nOUXpyyNYzyTBDd&tsnAyWaC=dsAW-=-zYa%$TpnL@0Ic#C-aYr z*U9soo%= z=pxODw62ba>IQYM#v&UhQ;uBV(-DZ5;-wl};%I5XYgsQ8^;eYVXa%dp%Gn;An~ZHW zgm(QY8p^k5tb>`oPRL{5qV+{l8CSc`w_vCE+1Hc?Ge_Ewxd6$_AuhgvF@c(>ABnEZ zhu)RK_`v%J{QGP6A0?tMtH6M6j6#trvXRP@SB6i;V2F>%S}&PJQ8}ggm7k-ES(MjL z718C#$_SjbPAaZW_EK3TRcSma*UB=M7rIXe4#~==b`;b730Kz!p29ngwJ58HbV_-n zBD<*jFiX?mk5|E|_h4E}y!93p-pqs|mDP4v&91EG8l9%U?tiIDzl>it!)VdKzu#4j#4} z$Pm+z6gCpGcaQITsk62g3&D6K?)unyLiF<}G1^1X0TtOL3t>^9AgM^%mSr82heTfJ z1k6f0da1QhvXuP$S@;z1l08yB0NH3|0arYge5bO-7iG-#;CcPwr89_=d%QVS+CD5O6tf@FU3J*eV5l-kwx+uNVbtzTYcZZy*ka1V zEs7f+wwG;CQhzYE2kVdY_Pp@6F!#%YBnU>N5!K$*il)^~+4oZ-PiqZU4LfsnSN2mt7G)inEXmB8f$^k@f~iW|B0o9RsRc5sxG3xku4(x+?`oC3$FlkhebK zw-9_H@~>*pRq-Xfxx|kgLB>nQc)G#|Zz7Fc#a?#{e0vK{ea$GNu$}B=ZI@-LHdvsT zhg|eem7P^xT(#?!N8Mu#WU8Z|(iJ2PVY}wKFnvzs>tw1FptU^_{Z}0^=~m+EMfoP* zM*?4xl6E2MdPd%|r>Ed0FJBt&B(8~egN#+)n<&~*rBGGd)Uyg*yk|^7$hW-f7QM5`IZnm)@MozfyjdL|m!a%|(kD7?XC@#L#2S zw=h|ni}V-m7m}w|+_@|(y=v7;%kJw_%WL+{4q=s9Y21ZReMFm1i5~q5?l6=UBb(vC zBagyQ_hYS@4#jQcz1_$}7Jy0c(D&Fu+aMn`gTJ=H1`wB6rKL!E<&2cbbkkUg>cS?qs6Jk;?SSpW#D#;;^a`CO$tYmBNb5Ydz6FR?kMl{qEjC<%3yLC@#_ zy-z{PeQYGff>a!vOflq(Z0ylZfJ}7;tz;(hZ%-&obz!C96z18|cBM^-O65(F%&%&^ z!ltzJOLC`po4mrR%_({i#mmQ=6nIKImlr@>Q1h=H7+SGPF*ZfQr1m+X>aT0fQ#Ax} za#3^+~{zT8(pdrfg*P8aaB5|A|UMLNkMj^OvZrVsedzp;*ME`C; zI~>Of(H1VQm0uC>ie(pu%I_mfhUh_6hXe`jSJS>WRRWX0LD6~N@SF}jZ!%KV8QLv{ zd_5Q#Y+)KGTsk)IGNF1g=UE%Yck)LYPhNwwvXJVd`i`mM+lcjTuTJ&Gh zK`Ho54aZdFBURFsZ(lX}lJHyHO+HF-bNRl67vlTU{|f?N#ejUvTywSJUk^QEvE+xs`M=G zn+$ALJb`?NiujiWKyh%2W0cG*si_dZWj~M&L$SMs=)ZJJ*<-XKNQ#yGEz5%9;|lRs zTy0_6mn}i_BCJ&uSvJ1QV<1gXQgSxnr+p@hQ_IgiisY2nHWJ4qf0wjn$;y$~>NH@V zV)`Uq=isPb1(;W5yy@UuxF>-b`{DWT(D@QzH4L(2APRg@OvySRqpB3mm_Nz%l^BoK zHo+#$kQ&xjAR6xZbf*0Lch`%zms$zr&~TKL34Z0R43_-J#l zfX82O`Rj1@UpPC4K8;5=Ima%p)6CpUxN3K#uQ}lOZetPhVr@89I<&U6XzhdG8Z~%^ zEYy;Pq<<=|CO3F2jW`}}>FvUONi$j@lk#6Oe`}cYsPk4fK=K4~y>gQ(qn+{*Q;UlJMDj(d8kXu3 zDods^4J*H$YA;2;QPrDlcFL*vhEecGOoB4oDaWbuZz_wOMMR3S3#-naG9W7BuyQVv z@sKN2huh_9W!QGe8tF27$cu_`;ide;%G4LBf29n6%9E{Jn#uvFtkKFKsVuh2A*|Y5 zij9fn^i~E=W%!I#S5nSHRbY$cVpZlp^+BWf!07ZO<(-aH8I_knBT>$4Wmx1m@KxLe z^MWLanUwR9tDbXISt^z5Hj--Onkvcod z{H^?hks6`O&=|>K?B|Q6=bC$EFjOvP4X%1*5Nl|fR~tObEc6}CuaWaR@_URh#aPaf~er6enzqu zs~)AYG$Qr$Ka!7pa^W!6`lU|E>`Q{z=axb$QiKjpL@@rmCF2 zWGw%eZ(sFSh1r@d<)atfDMC$<)J*vqj`=32tLl|S&Gy}SI>nb!Z`IrGo^lrYhGgnk*uiV85)12 zvbvtB+|0`FsyP;RUFWx|SSqWvXd3!q&UAMqr?>D{vmi*S9nHC_4Cwjl-BZ4Q;Jd~p zj24zDhrh<8{K%ppWw{nSw5mjERf-ywnObzD{H&^!t31DtXv5Em%r{|-av(=)3`FW3 zsG>lmDxvx-EWORW;*`pgEC`7zlyz1x5#NYpiI3!bzQb{4y`^?1v?~GFhs>WUk5JQt{wkxsIE$YJ+qbEyCW&ZAk`eiYeYrua zhPVVPiNB6=4$Krqi{7+Sh%!{ST-G>c#3!nrR^Z{tT>7PYjM0*wIIFk`kE4hO_qKAAL#iuG6C+AogxJ7EC_?fl!i`CoUI!RE- z8PE9bXU&ENgk{P@P4;G
}bHi+~txfZ#J^O~U$?IZOfK`I-2T%Jgr2^`SjI^}-$<7>ef)yk0cN#1zwRGpY0 zV~@Y6q zv@q2a)fH*zpZ18v;k&e&C|XiogMa;=>R!JB5iJVh0iXe7dp^34@cw)hKA7pz3Xig%CClSFN@)O%>7HfID| zjUK&(J{VlBJxSm#@WDGlD~bMp%Z!WJ`3LwY)41vo_&bxC5o(Yk*+=a9ktlcVRaUgQ z?Bl9lo`T=f#T5&o7%QxKK!W|?+?^NJh)G=LFp4IRGm;7MG_b@@HJ5 zB&x#4#l-YI61x%R8jt&_{Q+#mJrsqm_zRC7XjhdgxEk0Ev?D?m=oE}PF0Xi;)9flD zUoj!@EbdWdSZTNNysH{)WG{Dsr)YlVy-|Jv`5v^}C>|q{*ONU2JXetvkqWd4c#_K% ziXs#Cg}D|^D^3p-k^xDLM0hUWP86*xl3#vn+00WietEp*2T`Pl_87?Cm;qacEV8n` zD3&8K9_>rg-U``9H741xhca6rZMdu9wAM_>#@PmwSA;2qWSH zJ?*bhB!hNWg?WysQaecnJ?#S0?s?hpMTcqqR+I2e{ybTev@=UP=3G95Jj3Rf?6DT@ zY6raHCLF(I?MlePm?QBx^5zK2%9bCWw_^N)9Fc!e`^U74Mv*G=Hp!nrU1Vm<<(cY5 z8pa=iy~Z2jyYN}NcjUG4xFgcCAg+qaQGP2KIVuZTYCZ)aS*^v9L=zFqm>?iuigqa| z1HU|evYKgj)MA+4sYlu+rM(RiTUk1;Ps}gH)5u>G%{lD}k@q$^w#+n~QG}A(m8VX- zH-bPYG3{x0o$Trv=}8(eMEM33C6tby%Hpp0A?=e@G*muDsz^&wPsA24tG9N8DRMBs z4;T5qQt=c;j>vCZfF}sw6nV%#C~!n$O5~3sKG!OKF%x6f9LZ9xeGr-h?M{i|TE*3A zcZVPw$pRw(KyrGg9d+{2DC>gSmp4c`HDp5<{>Zm0SZHsrVu%#erPwjq0~N=q9U$@u ziGDO%MKsD2E}xeCMCyau(Y_q{9u>J3$w;A$YzcXe=0x7Yr2bqf>P#NQWQ;++B<=l@ zH(gm0v^!cm2sJCRP%08eUT8&AD!wf~XXFi%)l{R3>{!u0P{o@@Y^$0VjY<5;@@E=P z2>ej^C`+KIMtG|k6rWY3qWUb4mCnfWn2RTf#>7v=jaA25J4{90f}*03Gy8DRXf(S8 z{bvfc@;HXLD<|zMazH!u6Z%h3P7EExhW5OPQJ@G zA-WM~RV0(RXkwnEI9%nQl(ZS4cTt#dBP~4^^$SCy`4*vLaYJQm$-xor3{}L6JTeIw zk!n?IMpJTB@j-?8)HvlKm#0@duH<7CcBmEkd==NAdDOU+mmo4a#l~nSit>4+2R6z= zmz?_)ffUJMAxxDIL^vvpmA6bj=fYeopO#=I?~c4NiZ4|Jh4#5A&PEiIoo~7?Gp(1x z_n;Xp$hqwFHR8`#9HJs=WJMP&llo&w$F~UPiyr04RK&30ul-x%70SF2@u>;-6rrpc z(C%`LUlBjzOi8i)D;7de)xPzNTq(@e-e<)ws*myt$b+S5y!7-XK3C`Dx(FW-7Hhwi zqF*E4_Q>8o`3ki|Cpl*XBT>6@W<~m`IKIsEIv>_{)fUn7mHVe6c605GuYq4gei-c{ zRNhfV?I;%d6V4XIqomks-Jv}e^4(Mbc9|HRt}DqM<+xfA8OpU(khv{Gi;BOh!Z~FP zQ(UF8M^@rf5&f$Dpg1w@;LzTRukbu6zg#OnvQIwTKG^k@Cw?^X9-W99>W@Ej5I*WD z_*{Au7o?on%8R8KCgsTmH@zL=qS1V-YSnS@7MJ9QW0N!yA?VIQwO_}iA_r#*rn z=`23BJw)qoB`#wN|F`4q*}#!Kc`RwDzRi9AMn;%YJyv6z=V{aJ|-EK4j-dCpWMY9|lJ3*ad$ zPri&2oXta?lqB3;fO8q}1g673Ux5~q;n{A=9be+zE{lI{0Qr#m5obXBlJPh30|VK! zKg90r{NUaS)DG?pXNyV_^;uNQs3hTQ;gR80;X6^IqCbhg8dEF!PV~a4j^S3Jk->k0 z%R{L{8^V*K(nk%6N*x{)${5(^m2xiGZ|xx29*)``JDHce+q|d2^ug7^i@|+?-2uzJ z?VKckT^aJFyt6-X^15Gohk^-1^TRu$;ztz-UkrT+wG8eIHVGaKRSJ)Z+7dlC`cd@R z=p0e`!as!0gx-bgN5w=}ipd?*FeYbo>8NJm5}`7|ZNUSfOrb;JPs2^Z8AJ1e1-w=6 zw@xm*342a%+G*_HoO51-z_w87aQX0W;lIN*LIZ=#0^0+Jg9Sq)!<(aX#MF#A7PBaN zZunksg%|7Gwd+yWWi>HOF~(Iq&CSe5)*5nY@AMJ}jKIs_gkb(ae{Zo{*NL*OlCvQn z(HCD417YLOdx2N)88iDAzRTOp_UuxlbX zHpD-!>KB{An+rr$ouQ34U`JMFuQz+tN>Xm{>-Ykt|1?RWpec!~jyZOJJ zt9RqUTuWr$8m?3AiP=!nCjM`xjjhn#aK^qA@BVPkPl7I2@j07O52O9rKxP=!xRLAT zbN6xLm^RasYtV^H{?>$GaChTZvj{s*&pJiiWdSFcAh<7-CU`1v#vALJ_7SU#IhtMf zwG9_`b3M|sPGr9$6_2ZtYqSA@O~Job_}Ut4d@qr~krHWC1-+xTx+0J%f-^ccM1B>g=A z1l9wKJ$&B@?Jt9Os2Y*#n@oeB%;k;+z(O^SjsUNPK(af&%l2SFO*oh0LWcmAVL)TK z@4p`g6`Di0YM zZ46u_BfO(BF=D^6v+#^{#eVA+@$z^_0)@O+-U#;_r@UR#YC`Ur3dAp-GPZ+Dug&S! z_jXHXr~59@A=o<T?T{jt`>pwBp{kFF|dt+rex45NaGaO18YlR8q<`vL_Q%B`)^|4XIZN5mxRQ(*6Nul;&2F-5_8s?gZ$zMfFb~y_;=0?MQTFFn zMzbN&*zKvTQw*+J6u9Mu_htuYKBtWy@XtlW%j{tvKzplD{H_fYigaK=D?x23(;YC*P_zV;1w;1=efhI zEwXR8!vdv)S3}!FS3(Kl&)uE1c3$@28C;Q!_D?_+M}hT4F!cghyN9;5b8{!ywg$Y8 zg*xZ(nh(8?;d?h$*SV~n%C9w=BR>*-(u3Fx)$HiOuYurg8)BMNF`_F+27%d%U3+YJ z#C`-A*;mGWbDOonspK9B(hsbicWm?_SbTK>&B7JobSoAf1tNLpc_%oaNdFe=m$Osp z-$3G@M#FvP6LX=QVe{D!umI{?!l=ZJCi*>C%e52WRdcv@EKeQ4=%;gb4wSf>ReinB z{pNEn7W$6m*KXi<3CJA=<4=I|=a|Pkex|pcKc$4Aib!TeGcsl`BdDI8)I&s+cn4feU}C_X1~#VXFs;jTga zRvxzIz(7^DMlpij^n53CulhwR>CZ_h?=^Bl9`L6Kk?1|xGg81xW&hw@_htoagpP!V zgv*9{1+#e{-TKa0=Nspq7dNmfR4#lhYH(DO@XC-KNaeh?+gU`?8#9PhNdxr<;K2XD zfgTX~^N`QK;SdSI&mwT3uh^5+fXJIUW;XM-9dz2e*8?+y(?bb^_k!`f>25)?6c;s% z5&cpPX=xihR=nI?dOx1gEkrsKgtWtP9CO-^x#`Kw4dR$8pv~m19Hry9ekj`lOBwtSJQy|Mj)@e{IkAsCpTrokd@k)9wbYKLeM%f&91w47$muDw`YwkIu3J909wI@!Cy`YqJ=Uvl`&i=R3OmQU2WfF6`o0ru|Bkwp81W2*S-SQ zTK%u{%Y>dAvOl5)^Vfu@bTL-4^eyqQyWZr$f1w89;^811Jg(Q&jj^xU zqp6fK-zymSEp#mE`{=sSUq#Ig?G7A9f=*+{SYfj>`DB8x_bxU8#+MoL)WWqdgVcKS+-jqiO^?h(&C{ zx%T}332m<*Yj82Lot$*)czNM-_d~-%YeJ#GDzB?^(QZh^hXIUb9N1A3ic1Uqr9;+s zp|5CYCmrvS$dbw6G#Q`+apHKKONI>~vwyCz|3p2hFBsAYycSJJwC+oe0bc zb`FjRmhx`6Yn;^9L-V3pm^>+M&_ruNRoWv|1>RZ}>9{#LK1!RnY!?f{eqeYo@F8%_ zd*aS?n%HrvP4u;K6N(!HF1FxZ2h9EvEPiY*um;$V+&Yg-?X`1RHxZo$GcRs_u+64fe%#rZ?pnO&TLHT<9%&M_T5m z2JIJSrD#jkd@|s?}&l6C!Wlc%UtVYq}*2Y{jwH41!PUi5v*eF&66QB)Wbnn5DV(lc>KlV^( zw0kBnH2665CR{o68|!6$cLa6scA5Lk4Cpdl!0nu1c}~{d=d2%p8Ya@~CHVU-^vZwW z$p3NV17}Y2+Cwj>1i=66aNwu#;zV5WH+QIF;(j2a%Dk7*v|s!D9Sszz{v&$n1!RDu z+(V=~YkNFqFRl^IeX7`ajC*eb?^o&QlQeknG7X{4~56-3n>n&177rk|ro*ps!b0Q?BvM_#FR~UG&;Hy8x_>g<5{*^M={hs%7_dqr5r6)S)lJ z@k4JyNdvdNL2gpVwdYgCv%C98;D=BmEM(22T7++eI?<=%&J`yYb*e^DEp`%GVcDqr zQIDf)hO-Bodb8XVPG$QluFQvC+Q6XTgV4p${m`u7vfN)`A}C8UWAoXv{F^AXy}4UDTmcm1&Y^(D@}EAaaos^7uxyqnew zr-6GukR55GeyD5kao~Zs(fx!GyY^?HCk4JnFhEayV`!V)lKiSBWmO(kP04_pqUqIVyxK@_sBXFEw=+9QpY^0Sn|I;PULN{mO3Adr3BYfZE za}2d2`_o>|oZ|H-ly{9^>)|Gg;UXuYvp=BR`{4OK?%K~2cfohI(Bt_$SrxL6as4)~ zm#upi=cMt^^tG4MQ0xn&urPc`lHm(zGaEejce9<9-Y)O7c0X|!c?mt+t>sKYC)hA(cxh&8B4A52;uq(R`^4KEFuZMEW;d7PTF1=m=9f@iS!CzG ziP7JHPPCgb%>b9C0Nru)XaW72&Y2VR{v^lO10!W3T80H+nm^KGjPft;J_SwhgC8FT zch=C#1-SYXxM*7B$m~dnF|6RdS(T<@3!m?ta36TnyqDDFuH!Cox*^p+v4&DdWvp|} z%N$IOMR0yp&hV^oyx@1!n6 zus_d6cUZvuMlqhF;K(T;J&V?r{d6t8noGN~{7#@p^T6wo*kpz?PYZdkWNuUgYc#Z^ zyj{|Zr2)$leucBYa{qqrUq~yef;)tsF5}xaW_}}A?qE*mGlsF;JNc9dTZUY`#2-qHG$;8uS1`QI)9;d-SW6_h z24HO+R+ZAsZ%y=u+h%|3ODg!5b^dcZx_`L4-4ae0yE~kHH}@?;-c3w@;()ooGB-Ej zAV-+-bq*`a>E7InYr*n z-9YR56E4uk+wV?v*s1cfi%fwWH4be6O_I&Y5L*v>KR$$Qsufh$Yba&MPS`7p7$o2;Btp z5Agp3bDs)(MR9mnQMA&}XuUrH4pAX=rMnPsM=QJ+ zf8rtRW-p<}?*r`r-yq8z!=sQW_#yODC>ZP;sOxof{<5D_GrJ^p!#lhEy~~`v9;z8i z6>QGgRA?gqk=wqi-I%%(SKaAeAMbo1k$29k>9%po;oxDBavcZKQ->B%@A1uW`78!`0b zPgabJJX>;iWCgkchJElcEFLhGG%ReX%6#uIn@~&jy1kNBv4;D?%j)iNYdaI|<oEXx$Mj?+~Oj zWqFj3za9R7mRSDVvJHGv8Gcx4qw5f6jJf zMN-5-NACEUdpfal^rA)8YwU}}A#N_-BOl&5X7d`D_Y=7CmPQ(5|XStA=ndde)x4b)cVh*|*r5r?sSas^i^~qu=52>&&k{9Pddl zzUEhVd?2bptXg6n8BZr#P`%^M9Q&U8lv%trBhtR|?woIn&0E*}$oNL`#7_Jl$gh5k zq9td0a!z-RW$o2I+pe7J#;YygRME91SE}y4YSXKqojKo*c#EHSjxxZu=V({j{E?@% zr4OnDp~`03VXhI5;JCi`<-e-A3<8eBcv?694`fc|16B>fp8OxfXD_bo%~fOht)8k9 z=TP3`SSwcm_uX**TWFPWz}^qweFCUpIJUK!Ru8+TlgZ8QPIoW5H{4#%W@P!_t>R`E zEOF(azlYGBJUyEInY68H$DQbFf5xCJO!IicZY0SatXJF6DsHi&S? z{mMz?gs8fd2HgE%RxobCXVM`-Z-qNA@?{apPn-RIPGFwr()Lnb@&v2{SLU!@$>u*F zoSqJBCj<8moEyRKSk6wSXT$j~PuCE7C%?pWKG)I04BDB`?-3lG#M$Y7i|gs@P9*iy zVBkS|u?#x-#mCB{$P#}8oy5?i^rA0;(+KdhIS~Xq?C+c?XO#1o^RLs}NnqEc@{MP< zH!fkx$qiKRz#k5=h93sT$7p{y)EUb>sh6@x%md?>1F2o~LB6Zu^kyM5Bxz*>$1bq4 zoZnJ+lCgHJbEBzr zS{FOd1nfNXkxPoe-NURI4sWt!Frw_V(Al`icnsFQHBMItPd2`(_s(?qT?uQ1RmCbt zw(%=yfIm>(`>gkgH;(FWTiq(ZFvw=bf-^ko|O) znGg%p1azA0SOkg#K^N}a6ixLHD#+T_Q+vNN#VzNKcW1c;sp9wzYu{o#tBt{m5m=@2 zAPv4@rM(Y_zsOw3=6@VmsMho`;3p|jcykaa3oDi||C;4#%-{@QJqNf>=36ZIF&&7@ zJ2@MUBcG_`2w7O953ZxN4b0IQ+D6L2*Zvj>NnUs?i^v|Yk!1_8ZoZ)|UqL&)lf=0| z{nIU;=WcK_JHzd<)c4ClUQrM0vi6(TKsPIdPLzo@0!Rbph@;qvkM0+%sh!Wh@6@D* z++46Gy*=Ez!m84Z+#@55(yS(bGPccN=_qKifhePR#09owQz0S>sTIRwx zrLn2{w){Nuacuz}s$aUBQK_EgR$lWM{bYX6=8o}5_WhvL-W(GpNaoj>nfy{E)p^j$ zK={o7zE1^GlBty$OtnP@aMx5g)%Tp2S5MSGlb*)H1150x2YA#V`Zb1gLuq9+cS++{ z|5Y7uEbT4gd0Xl03Fhw=+0PB+*RJGfOas?H!Rj~!t@n}_<)s6*0c6bK)+p*!HNe6> z35$Mp^ttR{ekxY%6s)tEu`4P6?ocZ$btD%cZEtepyK$XcPIdd7UBJ3%4YKM`@v}Yg zOI_Tr-1A;xFC9ViMV$`zJ}5S9=EH(t9w}2k!g=&^D9|6qt1nQR#F&IN%lI|}NX>&n zXZu(-pU+v0WfMmgO|lNm+QzSST(N-T@@7uub1V05_J0Y&(`ipo90F8F0n3rhaBrSD zhR=yyKZxg!0Foo%1DdOOzD6Klr?MxE=dJqi;#_@zu6(kSX=gClF1yeSdbFJ9tpUO( z!Gu%rv-RM|ZeH^lmAKAC)`qF{a0>mCO=7UmOXVS-Myra~8^Jm8*73}icxN{_`(U6k zfR%DQPanc_me9^DTG4tkm8+-mKbAhOqqTLwLGe1jLRb62MOB|v{DO40^Bg$|9jkAb zv8){B*l{GMjc~V%NKU^Zt>59dFnKLBxsU6&K=sGrd2x~V-$}ZMlN3WHorCwOiuux- zW!JRdI@6tpyiPb(9D_=aKatP4A>Nh^SmV25yKV$UmIiBbK*dGDm{Gt0}?|(~F*iO5hlYr_y zzdLuGiB4X7B{4s$@R@`R7`4z962Y@Bz^@KsS6T`z&H7@eT7nK2#) zbIt>yQ)C)U=*x}SksAx~{2H>;k}Y_Mm6N*d`~@>F*SxR2v0ei&Kn3Ie_C&^d%j`*> z_HjHZmoH%>4FF}?2nF>GKwoQ+Vu>Eaxr2=PfqD9u)yLE?c;sEYCDQ8BBJ1X7g((4# zPl`nT9_kfqled-Q${&3pC4QALs*kj%vhsvY&1$dOxAAM?|P!4NzFV>dc{GUUl zn6jqK$MUtxUIYIp^`#O`Y61?xw&Jqw&W2=>MZZW%Px52mu1qh!N6*`W zJ-eTk*}7qGa*8?Eo!4##*5wOMA^RycV@KKzINs3tKwZ^ofo6e~fir=h*-TXqT>KA@ z(+B&4lNp=6;dXVedL_NtUJ>^kcV|QnsRwPOBnF}r)SH`C^#Uu_GkS5xr-|)Q$Z7c2 zW;n(z_`)9ezRRDbmLe`y$@VN)Ee4YhbKP$L8N2wdJTZ6BHR*p|$NVtdS;q;%j7>Wb|0k z7>dq&DH)D)#PqS2rG)}=qvJJ0dyhpc}5_ni)Sp?88&P3?xP`Guj@pS<+mm)>-2FE!j5&J!oC-P{^)MHAguz_%c+VXX4G zw1bZ7Gx8B+SWjm5z~k`=l@D`~dB3aO%l-r{eWI0z>M14hh%Y2gI}aF-+XIL{fOlO2 zFRsJU6lZ>z73diFcZlPPEB_5%y&rr#%L;ahYosNe!BR!kEY_BjtWIa(*ZaYv-Qdu9 zFc=Jln(i~#k9=FxHQzd;E1zHmFu&*Ux%M?e-_s(=0`1r5$jF{`l;AVTBlvHoT3xoOR9p z)~Dd;7AKuE+PQ;1a>LmK?_XqBxBjvYS_`d*)?47e!pV!|+04o3#I@Jh7Fp@Tie=_8w2I(T;qxLFnWT7M#!0{AFQYC^}ecRNL#y>2n; z%ole)pbzD>Z`mvCqxLOly89W@)~&$Uz(0XM1J48910k=cyV?!2GEHF3JWPG&MO;zG z>jeLbahJL&odHfFdoi_Y=Tp7jat1js+{|b+uJha(V(+)}Qw=*r9hap@&YKlu_jZ^VJ4LGfY{YOtm4(7xh!}^pF#76 zZzX)qd>&<A8ZE!9%gf7^X?1gZxXy(0+ zeb%05r?nGUH_+Ptwu@0a^PQ6&d{_aLdO03)L>?-D6fhS<%NMZ}_W()_u*X+{hDHNj z$NbJbXjQfLaOW-R7REYroaIghX1hDJ3vY7oTjTF$KY_!K2*Kug=F7P*Mjd%vn+FiSsA`F6K{4cMlXF>agp_qXHJlBU)V6kj^I?(?v7w&XYpS({R)0`I2+-!Ry9^p8)4b{|#_q_p% zz3JBgCnu6;N%&T7=rOf%j&-FXTCdi|t*lThkjNEbxrA?uSDlV@J``zt5i+>EK9T6+ z85~#S>ty8eWn8(6@vNe++qqKu+f=TU*JeH~jOPD5G=?RdQ zg4*)4rfkFW{}~>zLe$NB1U_wGwF@CVOt%N)A^F?7ZC%FZkj4Jl-sr?Q4V)5A1?mmI zv3pt1sDOIh{1lm0x#bcek1F#20yDOjk*a5#p_ZLc%VnN@3`(K)3ukpszV2Pn)p2I@ zS0vms-1ivHTml<-FDm&ttey|8VNgd``%mX{B&*6!4*R3skNBIm=1U~cO04gaWv*dF!?0>JVkO#a_qPjTa1=(}QaaR7K z#Xx!skYCOG%5U@wGqD`FoaC51NGHMOKYZ#s%W8Jax1X%w%1vB3ABY^}df7xabJs@h z*u!tpfaX|Gm2S4epGC#A-vcingYWl|YCP;o>3C&kF1{oC-&<?QW28*;1>pXm4vk`4gXW%MOTz0zFh9oPOgL;&&w+Z zma;so73J{4REM|JM1t6iRX#P9Z!TizI*QcPm&lQFPEyB4+Nxlkw7zB5dm(>ZVcq=! z>dptQ#0P_`5e2f6U0+4b308ch!CQ7qdo{Cp1F3wAJ(UVTh3v%EW3-shk(HL(mz>nj zmrfn<*ue6604-!76@u2-$KcINk#%0Xo^ufmBfY(r__mo=A}X4yBG*V?+9|*&vLQ3H zBl2WB9@KW`e^z;Gf%Vd^Ww+zW&EVYEt&!A>J8up)<8$9?aH$5+``pLSPmsB%Vk3-# zBQCZ=%#LN3u(%*4okQ?VFIS1iDqkc&C|l$B%^{++L&w*=JQ zJV@>EymmG?`=8bj>S8^m(nl&H1p6X`rZW=4rIm48aokT>F(uP{K!<(BY8~*k)x2O> zc2>HPWUzfg#_c6YHlJEQTdPxW!Zu$$*z;B$9eb$&}~}_gRM@u)5zs zTDpcz@R2q7xx92(4eBso0~q5IINdZ_EY8ZA&;E`vp1@lCz+PtWVU=vaD$(BF1^;VA z#dD|E}z5 zaFBcS=s6O`9s2h>E0{c{x9H(3dc4P%M&w1i#|&LXHr0-%qDcEakwxd4aj23sn3|@g z@SY`P?VN=y7R$=jz^-d&X6;IAXSHj9y%(Jv&KFu$ksd;D?k}L1)YLa>&B}V3wN-KE zRpFF9(S|qRl}tm0rQ241JjssT8QJt0YxyaBhuy&7D(quS3(xohj(^Ze<)kFKE82c& zkGG3je^_&@wCIkN(H>tA4ZM-|)}Z%~;u#0fk+U-|d#vo>|8Xd|y1gE_P6E!|?XR$W zl(kc_*3N*Q?>a@DmQGKnyVJ;iZy&KMTD!2lp`5j-}ncVB8L@JO#|g zM7zFXEw68_W##!BTsTY3u*{ZWPDE~gXNQ8UWE3ZeBM(mhm!f zYUiet(q2xiZzn4S{b@_|z$5s;Xtb?1w7nEKtfjYwId>MD`nOhV>bRYx{-V;5HgcQj}^f$e$N_5JfRG;mDrW&BS)n-=A;#lG8&_YhTl$`@Fr)$T6EuX=my0U&Q zVQec|+dF_o#nB)0*wwiDC;MN=#9~_#+30WRqL#Ij_@94)QA&2r^#`sQq0uO4N)&bn zd_ThHTQK@M)O?!H3mm=4_v7I5Ro3(ytd{Z){K2)-=u{_Sk1s(fvSJqR^++e{uxG~d ze;)tWu;y)tlPMPLBrDrBEO3(Ni$dpH&~nO}!>Hj^)Ea{vyMjvd`>e561uHq6wyPNz z&1o<^rXX~8pC_Mz+sU%2*t*kD-UWL2k^Z3zu=)hRiK560vw?eD_}4eP4L%xS(R78jaTx_t&Bl?Ru1sAtx&ow zi^_$2n0t0{Y!~PEbH!rrn8*MAKx7%~y5vL26uyO1JgbAA%=I?BB} zfUcshP5~j=Gyj2Ko z*0IL_YIQLGK{ISbm5GUP>=M3>={gvuD5MAU2U&v^aVnP6PfEHPg8pzur`_4?lK^cv?Tthi?NFxxVgv;Hruz-;(s z0Ntz{k@fqqD&}V#4}sCz|LF(X!~6@<-eQu?Ilp?YNXFK;K^*R-|A!V zDsWaAq?e&*X#ZD#B;g+DGz0i1pH)vNLvfX3_?*UjII?kX&J6{pExR=>d9Ml1xwGzzR2Zcx!Y1O2 z8Ah+h@!auTFE5LZPlJ9ILvu5@e=5Ic(ThcVi{+ZNzUH;gr^`*y+76CxrB{3CzA<3sD9!(?DJibDKcSEBFYP!t@ckR z=eZw{ofLIn3_0pM^yQJ@+;%*xIjN9)*>aJST2dYFhV=@6UJOwnY5DftPDG4QdsdKz z_HHaXvM`OXE8C8>-D*Vr&dKz~L3*1EE!0LcD*$c8LoaaA?%$vZ$O@O0Q5VLR*$CZY zDVj=Id<7?wA1h%=*n!6R6f4m)B=#hBaId!vmGCVVO6w#pvLGzY68!}GO`K#$X@F%l4>F- zG7oae=XNWko%*bisra3fRj~y6;iph(H;%Tj8za?k02VI#Zf*SNCzZgW8|M5Lv-LN2jS%Z^PS&kb=(tm`Y{a3~`8Rm=H-TqK#P!YR#M5sf zKCXlrFb)EX@0r&G;OY(VXgipFiau)J=`LSGJx3p}g5k=OaFr(>=bDpz-{N~$mq0g5 zp^24HkoNjdWu2CvbRhIR5Zdm;uffop;!d=hPlBpqp|I7ovXvF%2_6k;iY<{jSAbDP z&2Pc|oydD7FWGn$*>}swoLbEA zYBEP82G53JC7){UWX))e^pp!J;5bifjua3NI#Dix4R}tKeW43|??+$z!!MK*WdOaO z=Enn#;EExPb~I0$%C}Km(*ob>c+U5Ph;R%w442y`0sKdPTBd$Ci>C&8RN&;W2Dr`OTi- z$z3aqeACqW%*u--`qWlyL)?jR0!pjq-4WcH1>fn5#@ifv=?x_uF>P#! zO~KJs<{>y%TqMkk<}N%3&CFs{NuC03*Fsm0hQB^zRM#2HuRb;XfjlUU@h#GZ%duO2 z4`m6Cb#@VyS=Fj(bwCc-jh6EZT=F4xga5LQS-b2w)>Z2Q-0nRq^?qxMp7IcwZ59~El&R>!DIB)y1j(9OW$I^hw=MvVY6O2&CFhcoF>~3=U zFXn2?Vjr-R)|Pq6#qk1GXkLu}o;l@vjQsBB*FDT@UtmPIoKu$XF&q7mzU2v4$uDIt zG8yeWkCliU(Z*-R=MctZ<}OX*<=BnwiKcGJ8sB(U9mX@C>CMcw5n8+@dr#joUtP^= z_|s_o`(ra04R4{hC_y?`A&XP!ed@4J_&t)d6M5K%#H>dKHX~VE$X{jjZ8p7ZKK;q9 zSdbqR?ab=bxs=mOXt7o7{ymPgUr1kHKeC#&g-Oh@TL$Z1o-p2pWWA5fJ%=9hoVw?3 zT?N?+cW z8QCSw%kE)D_-3>s%yfgI^QpbZX^+ov{T}Y*D`|<9$?LC?qLW#JYE3In2kZT=$S$L8 zd`NmcSHBCbvlZRp_+I<>Eu?h2?VmKE$+_5rLfR`bbJAX*4Xtz_@Ub+3A?W_+vG5v(IDS#a1GhE9lAJjcsS#a5SrmpJ6?^3rT&M9{3E_bw)B$85yg< zxsP3p{a=Wl&&cUm#t(lXcaw+%+g?h*wUV!>r%xHP5*fdz2riAPf<%2Vx@XA_M)=_7Moc-nSwQLK9~@#10=U@{2D?m-T2jySUTdf2jPw)oZg_ub-}L~a0B_(6L(!m`!GW7P8@>> zaU8LZ!e4(v=u7CM2(K@$2jQ{{eop3>>_r{+J{yeRfw(ytpWVToGu#n`FCJZAm}TT| zl2=G3X?Z_~2JgDys~uO@;OfrvE|hmGe#r?WN0a$&&+iWWlKZ>^R}LQ$@8r#FkDs=L z+YOgph_w%BcRe#sB;5W%+J}(W5x6=j<9Ool#iuI?p>*JFJHqINZ{M`V zMKe;^iI1GGxx8ta(VSegB)-msQ;*Qv5YkB*O^Bx{Z_Hf|E}I8WJMgA4Zad*tHoqRc z=}Zi=#OkXLzXtKNJ0a^zR;MPs=|PO$0$(9R=n42~6NKEBRJG$y7*-~?QrM95t;M9A!lo9?8eGv(cr@CMRSx*~V7CyQ3tinn4A4!}oet{yy> zTc`&4%HiE0;%m(n@(+t7DZ~9R(q)Ot)7Y7}y>Z!>U)FICp6I3(f4lMNi)4n(V73q6 zx1|Ky;aheid55}?i|(Ye3BFqMZEedvXPI>5Th=%EYs1wxz{zZoA)cq)hN4Z%`PDk30e8A=8N}0`@IqEr^DEY+Oi|5(Fzb+> zR```!P}lN`%6-*02&*kQm#eWQ{^V0t3v?mnrnxh5oy4!js|ww$tI$%NRI zGBk>dX`Z_fw%m0m;#wqDLlL#M9-sE)z|h4ZZ35<|QZ4Rh4k((YxDHRvWfT0$v@2Sw z7@Vzw_{BEuL|D3L6}+#*lSbT$-P#a0qUg%$CLXQNP9WcM&DA1RvTU9R3g_{-XwMt@ zDXkOB+OiNWRAkSPFLqb21k1Tb{*h%1owj;f*NsFw2mZ_M# z%Dl{A%}7-Z-kKZHf@MWDW%?0gwJv|ZcIB)RK~&v{4XJtH5VY&~jRnPH{lh8Mf_{aHGVxB$Y~%X=q4VaS z@Vha-Ws_A`WmAf3=H~nrQCInC6r`{v>1fTpB`=3~Yut6^jcrR!(J4q%bABuRhNZsi z$y>2b)v3x)Q=Zw*WQ0^=)opD^X>Z)LA)K~6?TU-mJU>22S9{VT)2;ZnYRx9dtK55y z_+2lM)7n8@8=r5R5`r>kNht674<$e}-nyi^4k;BCxfWq6=Q8}s*e7qd?06yjrpFqgwxDhFk`!=jGWk|`iB(lkY+FL~FrrgWBZfaW*q8yusXU}er zpj?TDD<5BHQfLW+`LjvY??K1xG!o@Y2iEgI^-HjaW9{a93*n^z@vo=xjN)cf%}NK z{{@D=oGl@@kvw;@Ety04LcW7JMqZD9amhO;pOHL7GKR^dwUsA^B{Pcg%7G*QjeK-+ z0m)1xKh=k@@W?nLgPZJ8@;`k;%%6R;K zdyu}JxZIB0ugQ_DLAzmm*%rK$YiAQKWr~t_Z98d{G3HY~vQ^3O12-XeAyd*P#9syx zu!Lk-l10iA3c0q-^$wnf+&;1znNqowWNb19S%%~;3TxGxg4raplE!;<$V`)nnDx05Ql`K;HC!S66dYO>Wl zQ7bAXrc{|yA6T+s{jTA+^|6DuJ8*B>Z6iBz?`JhF&=}Y9#@1xIw+H!N&C_K;y50#S zYzyhwyk{xp^A;y&HMU2%Y%|ugIL1; zeVezIxhXZ}+jz5{(BI_On!vBVjb{Tn{)o5o4sHm-Q?57QU#+?=@Vzd0x01YXAeBmt zWoVkikd@@{w=S&%Yi%>GExQ%Ow}$UE{8A#rH*XWlYM#8uGw*z}hSd6g3njFTIMg!s z!G^GrTrTJBx;;xs#JuK$lp;TY2*? zzI?V7f3|v`tRW6HmF2EZFnv1-`z=1oxO(|L?w8?4*;~%dk)LX64^)@7`l3AH+P$O zVjFxnNTqr#>?c=|K4rxgX8GEynQKc@Hcvy`g`2JTHcm$cySY=ZY~!*`*@sx?_R#XO z${ebul0EhVLbX@k$Yq^v3~F-&<@-Ld$xQhPrL%^ZOoydq3>$f)j#cB>!-u1ufI*nP zNk&2YYMJQds@+8&jF$3P%eUrS!BMFkgI~b8_b>iBrnT>OTrba| zoZ9m7?jZ&_svTL%&?-mf9_}57*z-6FakTB2+EH-Gmn`qF=?Lcu&Mur8>>&hM1RdM_ zE0|BnH0T)8Sr2T2yp?CuaW1JLR%aKw|BCd;cPXEmV+?o|oqI8Fkzt6L4)bg_2n=!e5!Il7u94IShu(cx&OJB6HY^tOPZHQ$|J` zd3TQHyC$xy@J_~dS>Y-ZZv|$F@=}GI>?iWPJ~Mk*qHrfeyv$ThnA=uo_UTGmF5j*v z%3I^CwMT|)%A?q^D8drrY-|PYWjF18?9p3dh4K*lAm6jI-Ve*d1ZVClbDpey^n6a< zt&IO3B%nE|PMog0DpfDpH8C0FhMS{La+cu=@cF*N0_#?+5U$2L;R1F_PA7&E!agTB zg?=ek3paCS+_U~OvAGb3`(pM=F2maCe0+&SGK<}g8K9LcX7?hWmG?q+NJjGAk9~n5 zT>V+yod}A`G_GL*x_k*S%p{%(_?nKNlW{u{dx+75T!e2iXT+HiPeA+=(bg^oci>E( z&toU&bgmhs!5y75a5XVV^&~=bCr6x`Gq@LxM$~anv4|X^#TS^-SYvi%XKojz^LTuH zasb>Hzsq`|Osg_&vc_hXP2HM!H$D+tg{JIHwGQ^_|3nxMlHW(LLD5pwQ~3`P=1tgE zXxX)xG7*jCI&3}8CMD;P-s>s7t9h;+*yFfc!Jd6*aM~+!)?iB_ogAB5oW3|Sp4mSA zVrpe_2{;FJu>Whtu2y6A`#oK#ExooDo3LsrixtFKk+(n)sv3JczAITZxh3^l`keHG z=>e(f$tyshm>N4dIv+c*9@M8N?L~+C9r+j2L8O6&!O8t%>i9y+QH1|Ou3?n;WXfz7 zwJ`!Wi@6i;{T6oJ-ef_eEtUmaqjO^g@o6wKq|z5Y)|f`l(feaGeX9oGl|cAuv7RuoY?zOTLW0ZY8R}Y^=H-Z zB-U$2aCPK;-(bh39pByA;~K)wfxBHp`1Iwz7kA@$H-i0#;e{ zsbpU2L8!e5&)p$+qQ(=BtC#Nabj6SRE?u~DKVtyy`tq58JX*dY(%gj{{odV9_Si3r zd=*_EuadYjH7WC?tb#JrzzBUg^UL(dsb^9rCO=7CogS6`DsxWesLVwAnB*&oGvY;9 z^$o@1b7Taj5cc#vllm~_E~3NjSODD^NZ*;r;axcj)qbiV<_DT_!z{eHy@dyrcsY`DU-3Z&3wvh1TJ$aL)RbW zml}#|_bB?XQr9!kTE4+HiSxUHU0*F~+JlESF_s^HF*!N)d3s~! zotbx~x267;tRH_lHV?b4dm@9_g%=a>18ieLE3%i^AJ*muly-L5YqB$6i|cqSg13Tx z{f|VWB6u*8wH`x!5AwiI!?&PPbv_xh574)z~$UN6HfR_w4#> zb-b0G|F^LeeFVKBcFc`|C8;QazeNjZby`As&ZVWxhgCwm5;v-do!|@6OTWU-;x()o zcG51kvEQGKzWFNpLTqhfQR-N@Rnl44XYR~goZ6X;#m|m)#t!L*NJFeJwosezk;~U< zM|Tj@-Du_;&_364or_*MixxDSYaDU8cRd{)JU7_EwuYyZE?Fz?BZRl<^1dc-eIkpZ zpoGU~BonF6Gq;s#ROZPt1F{Oz7o@Th?PGrhbMXcC{gc>Qcy?K4f!ArpcXR!koT$Yv zBSbNkqeVb>YKhU6&n*A4Wjs?m4iIf)xn!!vWT^2+opQ#ET``g>5e zZvf5xeJp!!LYq{G)WF_p3$`b(lEc-c^Z~Th(}XQD&pE^;FT@30ayrf7IvuTaE;&0D zshNW8oyN1d08nl zrM4w+;v{UP*wK{upRjXCW7qK&_4GFFaTTS8MHaROaWr4~$WhphCXpv{21#B<;Y z-;;TF<_1uo+oWnG?g9&-9k_N|lI2s~(wAm7%AAqjnEE@|kY!`Lqc28NU^;Z62967? zM?8z;xjZq7WEk=KBQo+hz0zuWCC``t0sGtgXc-S6ah}(-9A;w`FqwSLLdIrO`=X1T z8~hRnET4C0(Qk?<@;sI`|Hi&V+pzkPOQY3ewd13cC#5!KE-zEH%vo@H^-V7W54ctA zndoht>No{UP0|)g(cgSayLy4tJ%p@X#phzae?`BcwV}9V;@18F{l1GcMsaK>kEgv3 z!!G5o(f+Xk@duM#)19*-WzH)*xooOT@63FQy!4#Z zDTzO`nRr4Km@~APYX08B0Hsx;{B6 z(K@y)x)BSTIT6o?y+Q1^l1s64K&rH5;WP+#{U=8 Gl>UP|>(mw=s|%Df}} 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 literal 0 HcmV?d00001 diff --git a/tests/data/real/Achl_ACHLO006-09_2_R.ab1 b/tests/data/real/Achl_ACHLO006-09_2_R.ab1 new file mode 100644 index 0000000000000000000000000000000000000000..51b5fe63fa3d5d90b1519b8f89ec040160aa55bf GIT binary patch literal 215996 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"%cv&@zm0XpCv&G2LPmh2lfnO^kVZ!! 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 E3t7s^asU7T literal 0 HcmV?d00001 diff --git a/tests/data/real/Achl_ACHLO007-09_1_F.ab1 b/tests/data/real/Achl_ACHLO007-09_1_F.ab1 new file mode 100644 index 0000000000000000000000000000000000000000..8dfd46330904194ecff16fd7d20d16729dfd8d80 GIT binary patch literal 213387 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
mmHRiI+g9L{DHPp(Xx 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 z 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 IYy7X_7mjhbod5s; literal 0 HcmV?d00001 diff --git a/tests/data/real/Achl_ACHLO007-09_2_R.ab1 b/tests/data/real/Achl_ACHLO007-09_2_R.ab1 new file mode 100644 index 0000000000000000000000000000000000000000..b55e8900ef68794fe84e74be6ee4c7ef1423fa8d GIT binary patch literal 214468 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 literal 0 HcmV?d00001 diff --git a/tests/data/real/Achl_ACHLO040-09_2_R.ab1 b/tests/data/real/Achl_ACHLO040-09_2_R.ab1 new file mode 100644 index 0000000000000000000000000000000000000000..86abb77ceb7298bfa6a8796730efd3e0e78fa4f9 GIT binary patch literal 210388 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 literal 0 HcmV?d00001 diff --git a/tests/data/real/Achl_ACHLO041-09_1_F.ab1 b/tests/data/real/Achl_ACHLO041-09_1_F.ab1 new file mode 100644 index 0000000000000000000000000000000000000000..b66d36f6828392a742c37794da770cdae52117cf GIT binary patch literal 214651 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

>KO_l^G5UW}l6hkJ6xu+o}P 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

hxRs2KQwOFyjA;GoB(b_*UsJ9u()zPG^b@; zbl={VWiwZ8TwJ=WVG?t{ef7qc(JhV99W3p^@^M>h8+MeQVdhGhq5Y_HfkZ|FP&%z4v>^sj8*UsQYY>gH9IWBL^D-h62B z_=?h&xhHR5x_Q*BnJrbN^M|bJGj4Wt(1{xcZ`4-7dT7~658 + /gene="COI" + CDS <1..>658 + /gene="COI" + /codon_start=2 + /transl_table=5 + /product="cytochrome oxidase subunit 1" + /protein_id="ADK40636.1" + /translation="TLYFILGVWAGMVGAGMSLLIRIELSQPGAFLGSDQLYNTIVTA + HAFVMIFFLVMPVFIGGFGNWLLPLMLGAPDMAFPRLNNMSFWLLPPSLILLVSSAAV + EKGAGTGWTVYPPLASNLAHAGPSVDLAIFSLHLAGASSILGAINFITTVINMRWSGL + RLERIPLFVWAVLITVVLLLLSLPVLAGAITMLLTDRNLNTSFFDPAGGGDPILYQHL + F" +ORIGIN + 1 aactttatat tttattctgg gcgtctgagc aggaatggtt ggagccggta taagacttct + 61 aattcgaatc gagctaagac aaccaggagc gttcctgggc agagaccaac tatacaatac + 121 tatcgttact gcacacgcat ttgtaataat cttctttcta gtaatgcctg tattcatcgg + 181 gggattcgga aactggcttt tacctttaat acttggagcc cccgatatag cattccctcg + 241 actcaacaac atgagattct gactacttcc cccatcactg atccttttag tgtcctctgc + 301 ggcggtagaa aaaggcgctg gtacggggtg aactgtttat ccgcctctag caagaaatct + 361 tgcccacgca ggcccgtctg tagatttagc catcttttcc cttcatttag cgggtgcgtc + 421 ttctattcta ggggctatta attttatcac cacagttatt aatatgcgtt gaagaggatt + 481 acgtcttgaa cgaattcccc tgtttgtctg agctgtgcta attacagttg ttcttctact + 541 tctatcttta ccagtgctag caggtgccat taccatactt cttaccgacc gaaacctcaa + 601 tacttcattc tttgatcctg ccggtggtgg agaccccatc ctctaccaac acttattc +// + diff --git a/tests/data/refs/pUC19_L09137.gb b/tests/data/refs/pUC19_L09137.gb new file mode 100644 index 0000000..40467ad --- /dev/null +++ b/tests/data/refs/pUC19_L09137.gb @@ -0,0 +1,157 @@ +LOCUS SYNPUC19CV 2686 bp DNA circular SYN 22-MAY-2002 +DEFINITION Cloning vector pUC19c, complete sequence. +ACCESSION L09137 X02514 +VERSION L09137.2 +KEYWORDS . +SOURCE Cloning vector pUC19c + ORGANISM Cloning vector pUC19c + other sequences; artificial sequences; vectors. +REFERENCE 1 (bases 1 to 2686) + AUTHORS Yanisch-Perron,C., Vieira,J. and Messing,J. + TITLE Improved M13 phage cloning vectors and host strains: nucleotide + sequences of the M13mp18 and pUC19 vectors + JOURNAL Gene 33 (1), 103-119 (1985) + PUBMED 2985470 +REFERENCE 2 (bases 1 to 2686) + AUTHORS Chambers,S.P., Prior,S.E., Barstow,D.A. and Minton,N.P. + TITLE The pMTL nic- cloning vectors. I. Improved pUC polylinker regions + to facilitate the use of sonicated DNA for nucleotide sequencing + JOURNAL Gene 68 (1), 139-149 (1988) + PUBMED 2851488 +REFERENCE 3 (bases 1 to 2686) + AUTHORS Gilbert,W. + TITLE Obtained from VecBase 3.0 + JOURNAL Unpublished +REFERENCE 4 (bases 1 to 2686) + AUTHORS Messing,J. + TITLE Direct Submission + JOURNAL Submitted (27-APR-1993) Department of Biochemistry, University of + Minnesota, St. Paul, MN 55108, USA +REFERENCE 5 (bases 1 to 2686) + AUTHORS Messing,J. + TITLE Direct Submission + JOURNAL Submitted (11-APR-2002) Rutgers, The State University of New + Jersey, Waksman Institute of Microbiology, 190 Frelinghuysen Road, + Piscataway, NJ 08854-8020, USA + REMARK Sequence update by submitter +COMMENT On Apr 11, 2002 this sequence version replaced L09137.1. + These data and their annotation were supplied to GenBank by Will + Gilbert under the auspices of the GenBank Currator Program. pUC19c + - Cloning vector (beta-galactosidase mRNA on complementary strand) + ENTRY PUC19C #TYPE DNA CIRCULAR TITLE pUC19c - + Cloning vector + (beta-galactosidase mRNA on complementary strand) + DATE 03-FEB-1986 + #sequence 16-DEC-1986 + ACCESSION VB0033 + SOURCE artificial + COLLECTION ATCC 37254 + REFERENCE + #number + #authors Norrander J., Kempe T., Messing J. + #journal Gene (1983) 26: 101-106 + REFERENCE + #number 1 + #authors Yanisch-Perron C., Vieira J., Messing J. + #journal Gene (1985) 33: 103-119 + #comment shows the complete compiled sequence + REFERENCE + #number 2 + #authors Chambers,S.P., et al. + #journal Gene (1988) 68: 139-149 + #describes mutation at nt1308 and its effect on copy number + REFERENCE + #number + #authors Pouwels P.H., Enger-Valk B.E., Brammar W.J. + #book Cloning Vectors, Elsvier 1985 and supplements + #comment vector I-A-iv-20 + COMMENT + This Sequence was obtained 3-MAR-1986 from J. Messing, Waksman + Institute, NJ on floppy disk. + Revised 16-DEC-1986 by F. Pfeiffer: + 1062/3 'AT' to 'TA' to match revised sequence of PBR322 + The beta-galactosidase mRNA sequence including the multiple + cloning site of M13mp19 is on the strand complementary to that + shown. + KEYWORDS + CROSSREFERENCE + #complement + VecBase(3):pUC19 + #prerevised + GenBank(50):M11662, EMBL(11):ARPuc19 + #parent + VecBase(3):pUC13, VecBase(3):M13mp19, VecSource(3):bGal19 + PARENT + Features of pUC19c (2686 bp) + residue source + 1- 137 2074-2210 pBR322 + 138- 237 2252-2351 pBR322 + 238- 395 1461-1304 (c) Lac-Operon + 396- 452 57- 1 (c) polylinker of M13mp19 + 455- 682 1298-1071 (c) Lac-Operon + 683-2686 2352-4355 pBR322 + Conflict (cfl) and Mutations (mut): + pUC19c source + mut 1308 A G 2977 pBR322 linked to increased copy number + mut 1942 A G 3611 pBR322 + mut 2243 T C 3912 pBR322 + FEATURE + 1629-2417 789-1 (c) Ap-R; b-lactamase + POLYLINKER HindIII-SphI-PstI-SalI-XbaI-BamHI-SmaI-KpnI-SacI-EcoRI + SELECTION + #resistance Ap + #indicator beta-galactosidase + SUMMARY pUC19c #length 2686 #checksum 4465. +FEATURES Location/Qualifiers + source 1..2686 + /organism="Cloning vector pUC19c" + /mol_type="genomic DNA" + /db_xref="taxon:174689" +ORIGIN + 1 tcgcgcgttt cggtgatgac ggtgaaaacc tctgacacat gcagctcccg gagacggtca + 61 cagcttgtct gtaagcggat gccgggagca gacaagcccg tcagggcgcg tcagcgggtg + 121 ttggcgggtg tcggggctgg cttaactatg cggcatcaga gcagattgta ctgagagtgc + 181 accatatgcg gtgtgaaata ccgcacagat gcgtaaggag aaaataccgc atcaggcgcc + 241 attcgccatt caggctgcgc aactgttggg aagggcgatc ggtgcgggcc tcttcgctat + 301 tacgccagct ggcgaaaggg ggatgtgctg caaggcgatt aagttgggta acgccagggt + 361 tttcccagtc acgacgttgt aaaacgacgg ccagtgaatt cgagctcggt acccggggat + 421 cctctagagt cgacctgcag gcatgcaagc ttggcgtaat catggtcata gctgtttcct + 481 gtgtgaaatt gttatccgct cacaattcca cacaacatac gagccggaag cataaagtgt + 541 aaagcctggg gtgcctaatg agtgagctaa ctcacattaa ttgcgttgcg ctcactgccc + 601 gctttccagt cgggaaacct gtcgtgccag ctgcattaat gaatcggcca acgcgcgggg + 661 agaggcggtt tgcgtattgg gcgctcttcc gcttcctcgc tcactgactc gctgcgctcg + 721 gtcgttcggc tgcggcgagc ggtatcagct cactcaaagg cggtaatacg gttatccaca + 781 gaatcagggg ataacgcagg aaagaacatg tgagcaaaag gccagcaaaa ggccaggaac + 841 cgtaaaaagg ccgcgttgct ggcgtttttc cataggctcc gcccccctga cgagcatcac + 901 aaaaatcgac gctcaagtca gaggtggcga aacccgacag gactataaag ataccaggcg + 961 tttccccctg gaagctccct cgtgcgctct cctgttccga ccctgccgct taccggatac + 1021 ctgtccgcct ttctcccttc gggaagcgtg gcgctttctc atagctcacg ctgtaggtat + 1081 ctcagttcgg tgtaggtcgt tcgctccaag ctgggctgtg tgcacgaacc ccccgttcag + 1141 cccgaccgct gcgccttatc cggtaactat cgtcttgagt ccaacccggt aagacacgac + 1201 ttatcgccac tggcagcagc cactggtaac aggattagca gagcgaggta tgtaggcggt + 1261 gctacagagt tcttgaagtg gtggcctaac tacggctaca ctagaagaac agtatttggt + 1321 atctgcgctc tgctgaagcc agttaccttc ggaaaaagag ttggtagctc ttgatccggc + 1381 aaacaaacca ccgctggtag cggtggtttt tttgtttgca agcagcagat tacgcgcaga + 1441 aaaaaaggat ctcaagaaga tcctttgatc ttttctacgg ggtctgacgc tcagtggaac + 1501 gaaaactcac gttaagggat tttggtcatg agattatcaa aaaggatctt cacctagatc + 1561 cttttaaatt aaaaatgaag ttttaaatca atctaaagta tatatgagta aacttggtct + 1621 gacagttacc aatgcttaat cagtgaggca cctatctcag cgatctgtct atttcgttca + 1681 tccatagttg cctgactccc cgtcgtgtag ataactacga tacgggaggg cttaccatct + 1741 ggccccagtg ctgcaatgat accgcgagac ccacgctcac cggctccaga tttatcagca + 1801 ataaaccagc cagccggaag ggccgagcgc agaagtggtc ctgcaacttt atccgcctcc + 1861 atccagtcta ttaattgttg ccgggaagct agagtaagta gttcgccagt taatagtttg + 1921 cgcaacgttg ttgccattgc tacaggcatc gtggtgtcac gctcgtcgtt tggtatggct + 1981 tcattcagct ccggttccca acgatcaagg cgagttacat gatcccccat gttgtgcaaa + 2041 aaagcggtta gctccttcgg tcctccgatc gttgtcagaa gtaagttggc cgcagtgtta + 2101 tcactcatgg ttatggcagc actgcataat tctcttactg tcatgccatc cgtaagatgc + 2161 ttttctgtga ctggtgagta ctcaaccaag tcattctgag aatagtgtat gcggcgaccg + 2221 agttgctctt gcccggcgtc aatacgggat aataccgcgc cacatagcag aactttaaaa + 2281 gtgctcatca ttggaaaacg ttcttcgggg cgaaaactct caaggatctt accgctgttg + 2341 agatccagtt cgatgtaacc cactcgtgca cccaactgat cttcagcatc ttttactttc + 2401 accagcgttt ctgggtgagc aaaaacagga aggcaaaatg ccgcaaaaaa gggaataagg + 2461 gcgacacgga aatgttgaat actcatactc ttcctttttc aatattattg aagcatttat + 2521 cagggttatt gtctcatgag cggatacata tttgaatgta tttagaaaaa taaacaaata + 2581 ggggttccgc gcacatttcc ccgaaaagtg ccacctgacg tctaagaaac cattattatc + 2641 atgacattaa cctataaaaa taggcgtatc acgaggccct ttcgtc +// + diff --git a/tests/data/refs/sample-d.dna b/tests/data/refs/sample-d.dna new file mode 100644 index 0000000000000000000000000000000000000000..30a1efabc9ce0d5f33043cf76cbc8a27b59de7e1 GIT binary patch literal 15730 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 str: + return "+" if "_F" in name else "-" + + +def test_corpus_files_present(): + assert len(REAL_READS) == 8 + assert COI_GB.exists() and PUC19_GB.exists() and SNAPGENE_DNA.exists() + + +def test_every_real_read_aligns_to_coi_with_high_identity(): + ref = coi_reference() + for path in REAL_READS: + if any(s in path.name for s in DIVERGENT_SAMPLES): + continue + aln = align_read(real_read(path.name).seq, ref) + assert aln.identity >= 0.97, path.name + assert aln.strand == _expected_strand(path.name) + + +def test_divergent_lineage_reads_still_align_on_the_right_strand(): + ref = coi_reference() + names = [p.name for p in REAL_READS if any(s in p.name for s in DIVERGENT_SAMPLES)] + assert len(names) == 4 + for name in names: + aln = align_read(real_read(name).seq, ref) + assert aln.strand == _expected_strand(name), name + assert 0.75 <= aln.identity < 0.97, name From 2954b65d1239506685ca98f091b717f9b6355ff4 Mon Sep 17 00:00:00 2001 From: Aleksey Drobin <43707931+adrobi@users.noreply.github.com> Date: Sun, 25 Oct 2026 01:41:19 +0300 Subject: [PATCH 04/44] Test corpus: per-sample COI references for divergent lineages Co-Authored-By: Claude Sonnet 5.5 --- scripts/fetch_test_data.py | 8 ++-- tests/clone_fixtures.py | 17 +++++++ tests/data/README.md | 37 +++++++--------- tests/data/refs/coi_HM417923.gb | 78 +++++++++++++++++++++++++++++++++ tests/data/refs/coi_KC569719.gb | 62 ++++++++++++++++++++++++++ tests/test_data_corpus.py | 27 ++++-------- 6 files changed, 186 insertions(+), 43 deletions(-) create mode 100644 tests/data/refs/coi_HM417923.gb create mode 100644 tests/data/refs/coi_KC569719.gb diff --git a/scripts/fetch_test_data.py b/scripts/fetch_test_data.py index 0512201..0c2d26b 100644 --- a/scripts/fetch_test_data.py +++ b/scripts/fetch_test_data.py @@ -2,7 +2,7 @@ Usage:: - python scripts/fetch_test_data.py --coi ACCESSION [--force] + python scripts/fetch_test_data.py --coi ACC [--coi ACC ...] [--force] Uses only ``urllib``. Idempotent: files that already exist are skipped unless ``--force`` is given. Tests never touch the network; the downloaded @@ -71,15 +71,15 @@ def _fetch(url: str, target: Path, force: bool, ncbi: bool = False) -> None: def main(argv: list[str] | None = None) -> None: parser = argparse.ArgumentParser(description=__doc__) - parser.add_argument("--coi", metavar="ACC", help="GenBank accession of the COI reference") + parser.add_argument("--coi", metavar="ACC", action="append", default=[], help="GenBank accession of a COI reference (repeatable)") parser.add_argument("--force", action="store_true", help="re-download existing files") args = parser.parse_args(argv) for name in READS: _fetch(SANGER_BASE + name, DATA / "real" / name, args.force) _fetch(_genbank_url("L09137"), DATA / "refs" / "pUC19_L09137.gb", args.force, ncbi=True) - if args.coi: - _fetch(_genbank_url(args.coi), DATA / "refs" / f"coi_{args.coi}.gb", args.force, ncbi=True) + for acc in args.coi: + _fetch(_genbank_url(acc), DATA / "refs" / f"coi_{acc}.gb", args.force, ncbi=True) _fetch(SNAPGENE_URL, DATA / "refs" / "sample-d.dna", args.force) diff --git a/tests/clone_fixtures.py b/tests/clone_fixtures.py index e99bb6b..12ce9ad 100644 --- a/tests/clone_fixtures.py +++ b/tests/clone_fixtures.py @@ -14,6 +14,15 @@ REAL_READS: list[Path] = sorted((DATA / "real").glob("*.ab1")) COI_GB = DATA / "refs" / "coi_HM417896.gb" + +# Sample prefix -> COI accession of the closest-lineage reference (A. chlorotica +# is a cryptic aggregate; see tests/data/README.md). HM417896 is the primary one. +SAMPLE_REFERENCE: dict[str, str] = { + "Achl_ACHLO006-09": "HM417896", + "Achl_ACHLO007-09": "HM417896", + "Achl_ACHLO040-09": "KC569719", + "Achl_ACHLO041-09": "HM417923", +} PUC19_GB = DATA / "refs" / "pUC19_L09137.gb" SNAPGENE_DNA = DATA / "refs" / "sample-d.dna" @@ -24,3 +33,11 @@ def real_read(name: str) -> Chromatogram: def coi_reference() -> str: return str(SeqIO.read(COI_GB, "genbank").seq).upper() + + +def reference_for(read_name: str) -> str: + """COI sequence (upper case) of the lineage-matched reference for a real read.""" + for prefix, accession in SAMPLE_REFERENCE.items(): + if read_name.startswith(prefix): + return str(SeqIO.read(DATA / "refs" / f"coi_{accession}.gb", "genbank").seq).upper() + raise KeyError(read_name) diff --git a/tests/data/README.md b/tests/data/README.md index d9666ad..f2e2e5f 100644 --- a/tests/data/README.md +++ b/tests/data/README.md @@ -1,6 +1,6 @@ # Test data corpus -Downloaded once by `scripts/fetch_test_data.py --coi HM417896` and committed. +Downloaded once by `scripts/fetch_test_data.py --coi HM417896 --coi KC569719 --coi HM417923` and committed. Tests never use the network. Semi-synthetic data is generated in `tests/clone_fixtures.py` and is not stored on disk. @@ -8,29 +8,26 @@ Tests never use the network. Semi-synthetic data is generated in |---|---|---|---| | `real/Achl_ACHLO{006,007,040,041}-09_{1_F,2_R}.ab1` (8 files) | [sangeranalyseR](https://github.com/roblanf/sangeranalyseR) `inst/extdata/Allolobophora_chlorotica/ACHLO/` | commit `4c5ebc9298a873c209819f12b7dfd85e126f1406` | MIT | | `refs/pUC19_L09137.gb` | NCBI nuccore `L09137` (efetch, `gbwithparts`) | accession | public domain | -| `refs/coi_HM417896.gb` | NCBI nuccore `HM417896.1` (efetch, `gbwithparts`) | accession | public domain | +| `refs/coi_{HM417896,KC569719,HM417923}.gb` | NCBI nuccore (efetch, `gbwithparts`) | accessions | public domain | | `refs/sample-d.dna` | [Biopython](https://github.com/biopython/biopython) `Tests/SnapGene/sample-d.dna` | commit `2fbe8755bb44731e60b7bd1e2cc55cf34d94e15b` | Biopython License | -## Why HM417896 as the COI reference +## COI references (per-lineage) *Allolobophora chlorotica* is a cryptic-species aggregate: its mitochondrial COI -lineages differ by up to ~16%. The four samples fall into at least three -lineages, so no single GenBank record is >= 97% identical to all eight reads. +lineages differ by up to ~16%, so no single GenBank record is >= 97% identical to +all eight reads. Candidates were found with NCBI E-utilities (esearch, ~930 +records) and checked locally with `chrom_core.align.align_read`. Each record +below is an iBOL/BOLD mirror with an annotated CDS; `SAMPLE_REFERENCE` in +`tests/clone_fixtures.py` maps each sample to its reference. +`coi_reference()` is HM417896, the primary reference for ACHLO006/007. -Candidates were found with NCBI E-utilities (esearch on `Allolobophora chlorotica` -COI/COX1, ~930 records) and checked locally with `chrom_core.align.align_read`. -HM417896.1 (voucher AC2, iBOL/BOLD mirror, 658 bp, annotated CDS) is the record -that fits the most reads and is the one that matches the ACHLO006-09 / 007-09 -lineage: - -| Read | strand | identity vs HM417896 | +| Accession | Samples | Identity F / R | |---|---|---| -| ACHLO006-09 F / R | + / - | 0.995 / 0.973 | -| ACHLO007-09 F / R | + / - | 0.995 / 0.992 | -| ACHLO040-09 F / R | + / - | 0.822 / 0.821 | -| ACHLO041-09 F / R | + / - | 0.836 / 0.818 | +| `HM417896.1` (voucher AC2, 658 bp) | ACHLO006-09 | 0.995 / 0.973 | +| | ACHLO007-09 | 0.995 / 0.992 | +| `KC569719.1` (voucher Acy224, 625 bp) | ACHLO040-09 | 0.986 / 0.977 | +| `HM417923.1` (voucher B2, 658 bp) | ACHLO041-09 | 0.997 / 0.989 | -ACHLO040-09 and ACHLO041-09 are other lineages: their best records in GenBank are -KC569719.1 (040 F: 0.986) and HM417923.1 (041 F: 0.997). They are kept in the -corpus on purpose as real, divergent-from-reference reads (useful as a -"many real differences" case); the corpus test treats them separately. +Cross-lineage: ACHLO040-09 F against HM417896 is only 0.822 identical (041: +0.836; 006/007 against KC569719/HM417923: 0.82-0.84), which makes it a real +"different lineage" read for later tests. diff --git a/tests/data/refs/coi_HM417923.gb b/tests/data/refs/coi_HM417923.gb new file mode 100644 index 0000000..c9e8b53 --- /dev/null +++ b/tests/data/refs/coi_HM417923.gb @@ -0,0 +1,78 @@ +LOCUS HM417923 658 bp DNA linear INV 25-JUL-2016 +DEFINITION Allolobophora chlorotica voucher B2 cytochrome oxidase subunit 1 + (COI) gene, partial cds; mitochondrial. +ACCESSION HM417923 +VERSION HM417923.1 +DBLINK BioProject: PRJNA37833 +KEYWORDS BARCODE. +SOURCE mitochondrion Allolobophora chlorotica + ORGANISM Allolobophora chlorotica + Eukaryota; Metazoa; Spiralia; Lophotrochozoa; Annelida; Clitellata; + Oligochaeta; Crassiclitellata; Lumbricina; Lumbricidae; + Lumbricinae; Allolobophora. +REFERENCE 1 (bases 1 to 658) + AUTHORS Dupont,L., Lazrek,F., Porco,D., King,R.A., Rougerie,R., + Symondson,W.O.C., Livet,A., Richard,B., Decaens,T., Butt,K. and + Mathieu,J. + TITLE New insight into the genetic structure of the Allolobophora + chlorotica aggregate in Europe using microsatellite and + mitochondrial data + JOURNAL Pedobiologia (Jena) (2011) In press +REFERENCE 2 (bases 1 to 658) + CONSRTM International Barcode of Life (iBOL) + TITLE iBOL Data Release + JOURNAL Unpublished +REFERENCE 3 (bases 1 to 658) + CONSRTM International Barcode of Life (iBOL) + TITLE Direct Submission + JOURNAL Submitted (01-JUN-2010) Biodiversity Institute of Ontario, + University of Guelph, 50 Stone Rd West, Guelph, Ontario N1G2W1, + Canada +COMMENT ##International Barcode of Life (iBOL)Data-START## + Barcode Index Number :: BOLD:AAA2176 + Order Assignment :: Haplotaxida + iBOL Working Group :: iBOL:WG1.9 + iBOL Release Status :: Phase 2 + ##International Barcode of Life (iBOL)Data-END## +FEATURES Location/Qualifiers + source 1..658 + /organism="Allolobophora chlorotica" + /organelle="mitochondrion" + /mol_type="genomic DNA" + /specimen_voucher="B2" + /db_xref="BOLD:ACHLO041-09.COI-5P" + /db_xref="taxon:302034" + /geo_loc_name="France: Seine-saint-Denis, Ile de France, + centre IRD Bondy" + /lat_lon="50.2769 N 2.52444 E" + /collection_date="07-Apr-2009" + /PCR_primers="fwd_seq: + tgtaaaacgacggccagtggtcaacaaatcataaagatattgg, rev_seq: + caggaaacagctatgactaaacttcagggtgaccaaaaaatca" + gene <1..>658 + /gene="COI" + CDS <1..>658 + /gene="COI" + /codon_start=2 + /transl_table=5 + /product="cytochrome oxidase subunit 1" + /protein_id="ADK40663.1" + /translation="TLYFILGVWAGMVGAGMSLLIRIELSQPGAFLGSDQLYNTIVTA + HAFVMIFFLVMPVFIGGFGNWLLPLMLGAPDMAFPRLNNMSFWLLPPSLILLVSSAAV + EKGAGTGWTVYPPLASNIAHAGPSVDLAIFSLHLAGASSILGAINFITTVINMRWSGL + RLERIPLFVWAVLITVVLLLLSLPVLAGAITMLLTDRNLNTSFFDPAGGGDPILYQHL + F" +ORIGIN + 1 aactctatac tttattttag gcgtctgagc aggaatggta ggagctggta taagactcct + 61 aattcgaatt gagctaagac agccgggagc attcctagga agggatcagc tctataatac + 121 tattgtaact gctcacgcat ttgtaataat tttctttcta gtaatacctg tatttattgg + 181 ggggttcggt aattgacttc tacctttaat acttggagcc cctgacatgg cattcccacg + 241 acttaacaac ataagattct gactccttcc cccgtcacta attcttctag tgtcctctgc + 301 tgcagtagaa aaaggtgcag gaactggatg aactgtttat ccgcccctag caagaaatat + 361 tgctcatgcc ggcccatctg tagacttagc tattttttct cttcatttag cgggtgcttc + 421 atcaatctta ggggccatta attttattac tactgttatt aacatgcgat gaagaggctt + 481 acgacttgaa cgaatcccat tattcgtttg agccgtacta atcacagtgg tgcttctact + 541 cctatcccta ccagtgttag ccggtgcaat tactatatta cttaccgatc gaaatctaaa + 601 tacctccttc tttgatcctg ctgggggtgg agatccaatc ctatatcaac acttattc +// + diff --git a/tests/data/refs/coi_KC569719.gb b/tests/data/refs/coi_KC569719.gb new file mode 100644 index 0000000..5eb1867 --- /dev/null +++ b/tests/data/refs/coi_KC569719.gb @@ -0,0 +1,62 @@ +LOCUS KC569719 625 bp DNA linear INV 01-JAN-2015 +DEFINITION Allolobophora chlorotica voucher Acy224 cytochrome oxidase subunit + 1 (COI) gene, partial cds; mitochondrial. +ACCESSION KC569719 +VERSION KC569719.1 +KEYWORDS . +SOURCE mitochondrion Allolobophora chlorotica + ORGANISM Allolobophora chlorotica + Eukaryota; Metazoa; Spiralia; Lophotrochozoa; Annelida; Clitellata; + Oligochaeta; Crassiclitellata; Lumbricina; Lumbricidae; + Lumbricinae; Allolobophora. +REFERENCE 1 (bases 1 to 625) + AUTHORS Dupont,L., Gresille,Y., Richard,B., Decaens,T. and Mathieu,J. + TITLE Fine-scale spatial genetic structure of two earthworm species, + Allolobophora chlorotica and Aporrectodea icterica (Annelida, + Clitellata) in temperate pastures related to dispersal constraints + JOURNAL Unpublished +REFERENCE 2 (bases 1 to 625) + AUTHORS Dupont,L., Gresille,Y., Richard,B., Decaens,T. and Mathieu,J. + TITLE Direct Submission + JOURNAL Submitted (01-FEB-2013) UMR7618 BIOEMCO IBIOS, Faculte des Sciences + et Technologie UPEC, 61 Avn General de Gaulle, Creteil, IDF 94010, + France +FEATURES Location/Qualifiers + source 1..625 + /organism="Allolobophora chlorotica" + /organelle="mitochondrion" + /mol_type="genomic DNA" + /specimen_voucher="Acy224" + /db_xref="taxon:302034" + /haplogroup="L2" + /geo_loc_name="France" + /collection_date="01-Apr-2009" + /PCR_primers="fwd_name: lco1490, fwd_seq: + ggtcaacaaatcataaagatattgg, rev_name: hco2198, rev_seq: + taaacttcagggtgaccaaaaaatca" + gene <1..>625 + /gene="COI" + CDS <1..>625 + /gene="COI" + /codon_start=2 + /transl_table=5 + /product="cytochrome oxidase subunit 1" + /protein_id="AHB64231.1" + /translation="SLLIRIELSQPGAFLGSDQLYNTIVTAHAFVMIFFLVMPVFIGG + FGNWLLPLMLGAPDMAFPRLNNMSFWLLPPSLILLVSSAAVEKGAGTGWTVYPPLASN + IAHAGPSVDLAIFSLHLAGASSILGAINFITTVINMRWSGLRLERIPLFVWAVLITVV + LLLLSLPVLAGAITMLLTDRNLNTSFFDPAGGGDPILYQHLFWFFGHP" +ORIGIN + 1 aagactccta attcgaattg agctaagaca gccgggagca tttctaggaa gggatcaact + 61 ctataacact attgtaactg ctcacgcatt tgtaataatt ttctttctag taatacctgt + 121 atttattggg gggttcggta attgacttct gcctttaata cttggagccc ctgacatggc + 181 attcccacgt cttaacaaca taagattttg actccttccc ccatcactaa tccttctagt + 241 atcctctgct gcagtagaaa agggtgcggg aactggatga actgtttatc cacccctagc + 301 aagaaacatt gctcatgccg gcccatctgt agacttagct attttttctc ttcatttagc + 361 aggtgcttca tcaatcttgg gtgccattaa ttttattact actgttatta atatacgatg + 421 aagaggctta cgacttgaac gaatcccatt attcgtttga gccgtactaa ttacagtggt + 481 ccttctactc ttatccttac cagtattagc cggtgcaatt actatactac ttaccgatcg + 541 aaatctaaat acctccttct ttgaccctgc tggaggtggg gatccaatcc tatatcaaca + 601 cttattctga ttttttggtc accct +// + diff --git a/tests/test_data_corpus.py b/tests/test_data_corpus.py index 57d4450..3ee01cd 100644 --- a/tests/test_data_corpus.py +++ b/tests/test_data_corpus.py @@ -1,11 +1,8 @@ -from clone_fixtures import REAL_READS, COI_GB, PUC19_GB, SNAPGENE_DNA, real_read, coi_reference +from clone_fixtures import ( + REAL_READS, COI_GB, PUC19_GB, SNAPGENE_DNA, real_read, coi_reference, reference_for, +) from chrom_core.align import align_read -# ACHLO040-09 and ACHLO041-09 belong to other, deeply divergent lineages of the -# Allolobophora chlorotica aggregate than the single GenBank COI record we ship -# (HM417896, matches ACHLO006-09/007-09). See tests/data/README.md. -DIVERGENT_SAMPLES = ("ACHLO040-09", "ACHLO041-09") - def _expected_strand(name: str) -> str: return "+" if "_F" in name else "-" @@ -17,20 +14,12 @@ def test_corpus_files_present(): def test_every_real_read_aligns_to_coi_with_high_identity(): - ref = coi_reference() for path in REAL_READS: - if any(s in path.name for s in DIVERGENT_SAMPLES): - continue - aln = align_read(real_read(path.name).seq, ref) + aln = align_read(real_read(path.name).seq, reference_for(path.name)) assert aln.identity >= 0.97, path.name - assert aln.strand == _expected_strand(path.name) + assert aln.strand == _expected_strand(path.name), path.name -def test_divergent_lineage_reads_still_align_on_the_right_strand(): - ref = coi_reference() - names = [p.name for p in REAL_READS if any(s in p.name for s in DIVERGENT_SAMPLES)] - assert len(names) == 4 - for name in names: - aln = align_read(real_read(name).seq, ref) - assert aln.strand == _expected_strand(name), name - assert 0.75 <= aln.identity < 0.97, name +def test_achlo040_is_a_different_lineage_from_the_primary_reference(): + aln = align_read(real_read("Achl_ACHLO040-09_1_F.ab1").seq, coi_reference()) + assert aln.identity < 0.90 From 236340f80beb80da8fef2f8fcd742e4d22a62212 Mon Sep 17 00:00:00 2001 From: Aleksey Drobin <43707931+adrobi@users.noreply.github.com> Date: Sun, 25 Oct 2026 01:47:13 +0300 Subject: [PATCH 05/44] peaks: normalised secondary-peak analysis at any read position Co-Authored-By: Claude Opus 5.5 --- chrom_core/peaks.py | 175 ++++++++++++++++++++++++++++++++++++++++ chrom_core/snps.py | 27 +++---- chrom_core/verify.py | 12 +-- tests/clone_fixtures.py | 42 ++++++++++ tests/test_peaks.py | 136 +++++++++++++++++++++++++++++++ tests/test_snps.py | 35 +------- tests/test_verify.py | 28 +------ 7 files changed, 370 insertions(+), 85 deletions(-) create mode 100644 chrom_core/peaks.py create mode 100644 tests/test_peaks.py diff --git a/chrom_core/peaks.py b/chrom_core/peaks.py new file mode 100644 index 0000000..9f548e0 --- /dev/null +++ b/chrom_core/peaks.py @@ -0,0 +1,175 @@ +"""Normalised secondary-peak analysis: the single source of double-peak calls. + +Raw channel heights are not comparable between dyes: one channel can be +systematically weaker than the others along the whole read, which inflates +(or hides) a "second peak" ratio measured on raw intensities. Here every +channel height at a position is divided by that channel's local baseline — +the median height of nearby peaks where that channel was the called base — +and the ratio is taken between normalised heights. + +The measurement window follows the local peak spacing (half the distance to +the nearest neighbouring peak) so a neighbour's peak never leaks in. +""" + +from __future__ import annotations + +from dataclasses import dataclass +from statistics import median + +from chrom_core.abif import Chromatogram +from chrom_core.align import ReadAlignment +from chrom_core.seqops import IUPAC + +BASELINE_SPAN = 20 # nearest called bases used for a channel's baseline +MIN_WINDOW = 2 # smallest half-window, trace points +_LONE_PEAK_WINDOW = 5 # half-window for a read with a single peak + + +@dataclass(frozen=True) +class SecondaryPeak: + primary_base: str # strongest (normalised) channel among the called alleles + base: str # strongest channel outside the called alleles; '' if none + ratio: float | None # normalised secondary / primary; None if unmeasurable + + +def peak_window(chrom: Chromatogram, i: int) -> int: + """Half the distance to the nearest neighbouring peak, at least 2.""" + peaks = chrom.peak_indices + gaps = [] + if i > 0: + gaps.append(peaks[i] - peaks[i - 1]) + if i + 1 < len(peaks): + gaps.append(peaks[i + 1] - peaks[i]) + if not gaps: + return _LONE_PEAK_WINDOW + return max(MIN_WINDOW, min(gaps) // 2) + + +def _heights(chrom: Chromatogram, i: int) -> dict[str, float]: + """Per-channel peak height within ``peak_window`` of called peak ``i``. + + A channel's height is its tallest *local maximum* strictly inside the + window, or its value at the called peak position if that is higher. A + plain window maximum is not used: at half the peak spacing a neighbour's + peak is still ~half its height, so its rising/falling shoulder at the + window edge would masquerade as a second peak (on real reads this alone + produced dozens of false double peaks per read). + """ + peak = chrom.peak_indices[i] + window = peak_window(chrom, i) + heights = {} + for base, trace in chrom.traces.items(): + if not 0 <= peak < len(trace): + heights[base] = 0.0 + continue + best = trace[peak] + lo = max(0, peak - window) + hi = min(len(trace) - 1, peak + window) + for k in range(lo + 1, hi): + if trace[k - 1] <= trace[k] >= trace[k + 1] and trace[k] > best: + best = trace[k] + heights[base] = float(best) + return heights + + +def _called(chrom: Chromatogram, i: int) -> str: + return chrom.seq[i].upper() + + +def _neighbours(n: int, i: int, span: int) -> list[int]: + """The ``span`` indices nearest to ``i`` (excluding ``i``) within [0, n).""" + out: list[int] = [] + d = 1 + while len(out) < span and (i - d >= 0 or i + d < n): + if i - d >= 0: + out.append(i - d) + if len(out) < span and i + d < n: + out.append(i + d) + d += 1 + return out + + +def _baseline(chrom: Chromatogram, i: int, span: int, heights_of) -> dict[str, float]: + per_channel: dict[str, list[float]] = {base: [] for base in chrom.traces} + primaries: list[float] = [] + for j in _neighbours(len(chrom.seq), i, span): + heights = heights_of(j) + called = _called(chrom, j) + if called in per_channel: + per_channel[called].append(heights[called]) + primaries.append(heights[called]) + else: # mixed / N call: its tallest channel stands in for the peak height + primaries.append(max(heights.values(), default=0.0)) + fallback = median(primaries) if primaries else 0.0 + return { + base: median(values) if values else fallback + for base, values in per_channel.items() + } + + +def channel_baseline( + chrom: Chromatogram, i: int, span: int = BASELINE_SPAN +) -> dict[str, float]: + """Per-channel baseline height around read position ``i``. + + For each channel: the median height of that channel over the ``span`` + nearest called bases whose called base is that channel. A channel never + called nearby falls back to the median peak height of all ``span`` peaks. + """ + return _baseline(chrom, i, span, lambda j: _heights(chrom, j)) + + +def _secondary(heights: dict[str, float], baseline: dict[str, float], called: str) -> SecondaryPeak: + norm = { + base: h / baseline[base] if baseline.get(base, 0) > 0 else h + for base, h in heights.items() + } + called_alleles = set(IUPAC.get(called, "ACGT")) & set(norm) + if not called_alleles: + called_alleles = set(norm) + primary_base = max(sorted(called_alleles), key=lambda b: norm[b]) + primary = norm[primary_base] + outside = [b for b in sorted(norm) if b not in called_alleles] + if not outside: + return SecondaryPeak(primary_base, "", None) + base = max(outside, key=lambda b: norm[b]) + ratio = norm[base] / primary if primary > 0 else None + return SecondaryPeak(primary_base, base, ratio) + + +def secondary_peak(chrom: Chromatogram, i: int) -> SecondaryPeak: + """Strongest second channel under the called peak ``i``, normalised per dye.""" + return _secondary(_heights(chrom, i), channel_baseline(chrom, i), _called(chrom, i)) + + +def scan_secondary_peaks( + chrom: Chromatogram, + alignment: ReadAlignment, + min_ratio: float, + min_q: int, +) -> list[tuple[int, SecondaryPeak]]: + """Every covered reference position whose read peak has a second peak. + + ``chrom`` is the read in its displayed orientation (as for ``call_snps``); + positions with quality below ``min_q`` are skipped. Sorted by ``ref_pos``. + """ + n = len(chrom.seq) + cache: dict[int, dict[str, float]] = {} + + def heights_of(j: int) -> dict[str, float]: + if j not in cache: + cache[j] = _heights(chrom, j) + return cache[j] + + hits: list[tuple[int, SecondaryPeak]] = [] + for ref_pos in sorted(alignment.ref_to_read): + idx = alignment.ref_to_read[ref_pos] + if alignment.strand == "-": + idx = n - 1 - idx + if not 0 <= idx < n or chrom.quality[idx] < min_q: + continue + baseline = _baseline(chrom, idx, BASELINE_SPAN, heights_of) + peak = _secondary(heights_of(idx), baseline, _called(chrom, idx)) + if peak.ratio is not None and peak.ratio >= min_ratio: + hits.append((ref_pos, peak)) + return hits diff --git a/chrom_core/snps.py b/chrom_core/snps.py index 56be395..7c97c70 100644 --- a/chrom_core/snps.py +++ b/chrom_core/snps.py @@ -4,7 +4,8 @@ - ``homozygous`` — clean single peak of a non-reference base; - ``heterozygous``— double peak: a second channel rises to at least ``het_ratio`` of the primary height at the same position (classic ~50/50 - Sanger het), or the basecaller itself emitted an IUPAC mixed base; + Sanger het; heights normalised per dye, see :mod:`chrom_core.peaks`), or + the basecaller itself emitted an IUPAC mixed base; - ``low_quality`` — phred below ``min_q``; reported but flagged untrusted. """ @@ -14,6 +15,7 @@ from chrom_core.abif import Chromatogram from chrom_core.align import ReadAlignment +from chrom_core.peaks import secondary_peak from chrom_core.seqops import IUPAC DEFAULT_MIN_Q = 20 @@ -41,7 +43,7 @@ class SnpCall: read_base: str # called base at the position (may itself be IUPAC) kind: str # 'homozygous' | 'heterozygous' | 'low_quality' quality: int - ratio: float | None # secondary/primary peak height; None if unmeasurable + ratio: float | None # normalised secondary/primary peak height; None if unmeasurable iupac: str # code summarizing the observed alleles note: str = "" @@ -49,7 +51,10 @@ class SnpCall: def peak_heights( chrom: Chromatogram, read_index: int, window: int = PEAK_WINDOW ) -> dict[str, float]: - """Max trace intensity per channel around the called peak.""" + """Raw max trace intensity per channel around the called peak (tooltips). + + Not used for het calls: those go through :func:`chrom_core.peaks.secondary_peak`. + """ peak = chrom.peak_indices[read_index] heights = {} for base, trace in chrom.traces.items(): @@ -80,21 +85,9 @@ def call_snps( continue quality = chrom.quality[read_idx] called = chrom.seq[read_idx].upper() - heights = peak_heights(chrom, read_idx) - + peak = secondary_peak(chrom, read_idx) called_concrete = set(IUPAC.get(called, "ACGT")) - primary = max(heights.get(b, 0.0) for b in called_concrete) or max( - heights.values() - ) - secondary_base, secondary = max( - ((b, h) for b, h in heights.items()), key=lambda kv: kv[1] - ) - # the strongest channel should be one of the called alleles; the - # secondary candidate is the strongest channel outside them - outside = [(b, h) for b, h in heights.items() if b not in called_concrete] - if outside: - secondary_base, secondary = max(outside, key=lambda kv: kv[1]) - ratio = secondary / primary if primary > 0 else None + secondary_base, ratio = peak.base, peak.ratio alleles = set(called_concrete) if ratio is not None and ratio >= het_ratio: diff --git a/chrom_core/verify.py b/chrom_core/verify.py index e35397c..012a5f2 100644 --- a/chrom_core/verify.py +++ b/chrom_core/verify.py @@ -22,7 +22,8 @@ from chrom_core.abif import Chromatogram from chrom_core.align import ReadAlignment from chrom_core.seqops import IUPAC -from chrom_core.snps import DEFAULT_HET_RATIO, DEFAULT_MIN_Q, alleles_to_iupac, peak_heights +from chrom_core.peaks import secondary_peak +from chrom_core.snps import DEFAULT_HET_RATIO, DEFAULT_MIN_Q, alleles_to_iupac @dataclass(frozen=True) @@ -169,15 +170,10 @@ def _verify_one( read_idx = alignment.ref_to_read[pos] quality = chrom.quality[read_idx] - heights = peak_heights(chrom, read_idx) called = chrom.seq[read_idx].upper() called_alleles = set(IUPAC.get(called, "ACGT")) - primary = max((heights.get(b, 0) for b in called_alleles), default=0) or max( - heights.values(), default=0 - ) - outside = [(b, h) for b, h in heights.items() if b not in called_alleles] - secondary_base, secondary = max(outside, key=lambda kv: kv[1]) if outside else ("", 0) - ratio = secondary / primary if primary > 0 else None + peak = secondary_peak(chrom, read_idx) + secondary_base, ratio = peak.base, peak.ratio alleles = set(called_alleles) if ratio is not None and ratio >= het_ratio and secondary_base: diff --git a/tests/clone_fixtures.py b/tests/clone_fixtures.py index 12ce9ad..d2ea9d9 100644 --- a/tests/clone_fixtures.py +++ b/tests/clone_fixtures.py @@ -8,6 +8,7 @@ from chrom_core import read_ab1 from chrom_core.abif import Chromatogram +from chrom_core.seqops import IUPAC DATA = Path(__file__).resolve().parent / "data" @@ -41,3 +42,44 @@ def reference_for(read_name: str) -> str: if read_name.startswith(prefix): return str(SeqIO.read(DATA / "refs" / f"coi_{accession}.gb", "genbank").seq).upper() raise KeyError(read_name) + + +SPACING = 10 # trace points between called bases in synthetic chromatograms + + +def make_chrom( + seq: str, + quality: int = 40, + heights: dict[tuple[int, str], float] | None = None, + spacing: int = SPACING, + primary: dict[str, float] | None = None, +) -> Chromatogram: + """Synthetic chromatogram: clean primary peaks, optional extra heights. + + ``heights`` maps (base index, channel) -> trace value at that peak, e.g. + {(10, "C"): 500} models a secondary C peak at read position 10. + ``primary`` overrides the height of a called peak per channel (default + 1000), e.g. {"G": 500} models a systematically weak G dye. + """ + heights = heights or {} + primary = primary or {} + n = len(seq) + total = (n + 1) * spacing + traces = {base: [80] * total for base in "ACGT"} + peaks = [] + for i, called in enumerate(seq.upper()): + peak = (i + 1) * spacing + peaks.append(peak) + # an IUPAC called base lights up all of its channels + active = set(IUPAC[called]) if called in IUPAC else set("ACGT") + for base in "ACGT": + traces[base][peak] = primary.get(base, 1000) if base in active else 60 + for (index, base), value in heights.items(): + traces[base][(index + 1) * spacing] = value + return Chromatogram( + sample_id="synthetic", + seq=seq, + quality=(quality,) * n, + traces={b: tuple(t) for b, t in traces.items()}, + peak_indices=tuple(peaks), + ) diff --git a/tests/test_peaks.py b/tests/test_peaks.py new file mode 100644 index 0000000..a83b709 --- /dev/null +++ b/tests/test_peaks.py @@ -0,0 +1,136 @@ +import random +from dataclasses import replace + +from chrom_core.align import align_read +from chrom_core.peaks import ( + SecondaryPeak, + channel_baseline, + peak_window, + scan_secondary_peaks, + secondary_peak, +) +from chrom_core.snps import peak_heights +from clone_fixtures import REAL_READS, make_chrom, real_read, reference_for + + +def _random_seq(seed: int, n: int = 120) -> str: + rng = random.Random(seed) + return "".join(rng.choice("ACGT") for _ in range(n)) + + +def test_weak_channel_normalisation_removes_false_het() -> None: + # The G dye is systematically half as bright: every called G peak is 500 + # high, every other called peak 1000. At position 10 (called G) the A + # channel shows 225 — 45% of the raw G height, a false het by raw ratio. + # Normalised, the G peak itself is at its baseline (500/500 = 1.0) while + # A is 225/1000 = 0.225 of its own baseline -> ratio well below 0.40. + seq = list(_random_seq(1, 40)) + seq[10] = "G" + seq = "".join(seq) + chrom = make_chrom(seq, primary={"G": 500}, heights={(10, "A"): 225}) + raw = peak_heights(chrom, 10) + assert raw["A"] / raw["G"] >= 0.40 # the raw ratio would call a het + peak = secondary_peak(chrom, 10) + assert peak.primary_base == "G" + assert peak.base == "A" + assert peak.ratio < 0.40 + + +def test_true_het_detected_after_normalisation() -> None: + seq = list(_random_seq(2, 40)) + seq[10] = "A" + seq = "".join(seq) + chrom = make_chrom(seq, heights={(10, "C"): 500}) # second C peak at 50% + peak = secondary_peak(chrom, 10) + assert peak.base == "C" + assert 0.45 <= peak.ratio <= 0.55 + + +def test_peak_window_tracks_spacing() -> None: + chrom_spacing_10 = make_chrom("ACGTACGTAC", spacing=10) + chrom_spacing_3 = make_chrom("ACGTACGTAC", spacing=3) + assert peak_window(chrom_spacing_10, 5) == 5 + assert peak_window(chrom_spacing_3, 5) == 2 + + +def test_neighbour_shoulder_is_not_a_second_peak() -> None: + # Position 11 is a broad A peak (spacing 10): its rising flank reaches + # 600 at the edge of position 10's window. A plain window maximum would + # read that as a 60% second peak; it is a slope, not a peak. + seq = "CGTACGTACGCAGTCGATCGAT" + chrom = make_chrom(seq) + assert seq[10] == "C" and seq[11] == "A" + a = list(chrom.traces["A"]) + for k, v in zip(range(111, 120), (300, 350, 400, 500, 600, 700, 800, 900, 950)): + a[k] = v + a[105:111] = [100, 120, 150, 180, 220, 260] + chrom = replace(chrom, traces={**chrom.traces, "A": tuple(a)}) + assert peak_heights(chrom, 10)["A"] >= 600 # raw window max sees the shoulder + peak = secondary_peak(chrom, 10) + assert peak.ratio < 0.40 + + +def test_channel_baseline_uses_called_peaks_per_channel() -> None: + seq = "ACGT" * 10 + chrom = make_chrom(seq, primary={"G": 500}) + baseline = channel_baseline(chrom, 20) + assert baseline == {"A": 1000.0, "C": 1000.0, "G": 500.0, "T": 1000.0} + + +def test_channel_baseline_falls_back_when_channel_never_called() -> None: + # no T is called anywhere: T falls back to the median of all called peaks + chrom = make_chrom("ACG" * 15, primary={"G": 400}) + baseline = channel_baseline(chrom, 20) + assert baseline["G"] == 400.0 + assert baseline["T"] == 1000.0 # median of 1000/1000/400 heights + + +def test_secondary_peak_without_outside_channel_is_unmeasurable() -> None: + chrom = make_chrom("ACGTNACGTA") + peak = secondary_peak(chrom, 4) + assert peak == SecondaryPeak(primary_base=peak.primary_base, base="", ratio=None) + + +def test_scan_finds_het_where_reference_base_was_called() -> None: + ref = list(_random_seq(3)) + if ref[30] == "T": + ref[30] = "A" + ref = "".join(ref) + # the read equals the reference, but under position 30 a T peak at 50% + chrom = make_chrom(ref, heights={(30, "T"): 500}) + hits = scan_secondary_peaks(chrom, align_read(chrom.seq, ref), 0.40, 20) + assert [pos for pos, _ in hits] == [30] + assert hits[0][1].base == "T" + + +def test_scan_maps_reverse_strand_to_displayed_read() -> None: + from chrom_core.seqops import reverse_complement + + forward = list(_random_seq(4)) + if forward[30] == "T": + forward[30] = "A" + forward = "".join(forward) + chrom = make_chrom(forward, heights={(30, "T"): 500}) + ref = reverse_complement(forward) + aln = align_read(chrom.seq, ref) + assert aln.strand == "-" + hits = scan_secondary_peaks(chrom, aln, 0.40, 20) + assert [pos for pos, _ in hits] == [len(forward) - 1 - 30] + + +def test_scan_skips_low_quality() -> None: + ref = list(_random_seq(5)) + if ref[30] == "T": + ref[30] = "A" + ref = "".join(ref) + chrom = make_chrom(ref, quality=10, heights={(30, "T"): 500}) + assert scan_secondary_peaks(chrom, align_read(chrom.seq, ref), 0.40, 20) == [] + + +def test_real_reads_have_no_mass_false_hets() -> None: + assert REAL_READS + for path in REAL_READS: + chrom = real_read(path.name) + aln = align_read(chrom.seq, reference_for(path.name)) + hits = scan_secondary_peaks(chrom, aln, 0.40, 20) + assert len(hits) <= 2, (path.name, hits) diff --git a/tests/test_snps.py b/tests/test_snps.py index 51b800a..519b296 100644 --- a/tests/test_snps.py +++ b/tests/test_snps.py @@ -4,44 +4,13 @@ import pytest from chrom_core import read_ab1 -from chrom_core.abif import Chromatogram from chrom_core.align import align_read -from chrom_core.seqops import IUPAC, reverse_complement +from chrom_core.seqops import reverse_complement from chrom_core.snps import alleles_to_iupac, call_snps, peak_heights +from clone_fixtures import make_chrom EXAMPLES = Path(__file__).resolve().parent.parent / "examples" -SPACING = 10 # trace points between called bases - - -def make_chrom(seq: str, quality: int = 40, heights: dict[tuple[int, str], float] | None = None) -> Chromatogram: - """Synthetic chromatogram: clean primary peaks, optional extra heights. - - ``heights`` maps (base index, channel) -> trace value at that peak, e.g. - {(10, "C"): 500} models a secondary C peak at read position 10. - """ - heights = heights or {} - n = len(seq) - total = (n + 1) * SPACING - traces = {base: [80] * total for base in "ACGT"} - peaks = [] - for i, called in enumerate(seq.upper()): - peak = (i + 1) * SPACING - peaks.append(peak) - # an IUPAC called base lights up all of its channels - active = set(IUPAC[called]) if called in IUPAC else set("ACGT") - for base in "ACGT": - traces[base][peak] = 1000 if base in active else 60 - for (index, base), value in heights.items(): - traces[base][(index + 1) * SPACING] = value - return Chromatogram( - sample_id="synthetic", - seq=seq, - quality=(quality,) * n, - traces={b: tuple(t) for b, t in traces.items()}, - peak_indices=tuple(peaks), - ) - def test_alleles_to_iupac() -> None: assert alleles_to_iupac({"A"}) == "A" diff --git a/tests/test_verify.py b/tests/test_verify.py index bdb9ef4..52c55fd 100644 --- a/tests/test_verify.py +++ b/tests/test_verify.py @@ -11,35 +11,9 @@ verify_expected, verdicts_csv, ) +from clone_fixtures import make_chrom EXAMPLES = Path(__file__).resolve().parent.parent / "examples" -SPACING = 10 - - -def make_chrom(seq: str, quality: int = 40, heights: dict | None = None) -> object: - from chrom_core.abif import Chromatogram - from chrom_core.seqops import IUPAC - - heights = heights or {} - n = len(seq) - total = (n + 1) * SPACING - traces = {base: [80] * total for base in "ACGT"} - peaks = [] - for i, called in enumerate(seq.upper()): - peak = (i + 1) * SPACING - peaks.append(peak) - active = set(IUPAC[called]) if called in IUPAC else set("ACGT") - for base in "ACGT": - traces[base][peak] = 1000 if base in active else 60 - for (index, base), value in heights.items(): - traces[base][(index + 1) * SPACING] = value - return Chromatogram( - sample_id="synthetic", - seq=seq, - quality=(quality,) * n, - traces={b: tuple(t) for b, t in traces.items()}, - peak_indices=tuple(peaks), - ) # ------------------------------------------------------------------- parsing From ac89e132a324b372a24d0677fc7e98e2be2e796f Mon Sep 17 00:00:00 2001 From: Aleksey Drobin <43707931+adrobi@users.noreply.github.com> Date: Sun, 25 Oct 2026 01:51:36 +0300 Subject: [PATCH 06/44] Fix untranslated verify notes, Q=0 mean for reads without quality, reverse-strand indexing Co-Authored-By: Claude Sonnet 5.5 --- chrom_core/batch.py | 15 ++++++++--- chrom_core/verify.py | 48 +++++++++++++++++++++++----------- i18n.py | 6 +++++ tests/test_batch.py | 11 ++++++++ tests/test_smoke_gui.py | 50 +++++++++++++++++++++++++++++++++++ tests/test_verify.py | 58 +++++++++++++++++++++++++++++++++++++++++ translations_en.py | 6 +++++ ui/batch_panel.py | 5 +++- ui/main_window.py | 32 ++++++++++++++++++++--- 9 files changed, 207 insertions(+), 24 deletions(-) diff --git a/chrom_core/batch.py b/chrom_core/batch.py index 90f867e..b047192 100644 --- a/chrom_core/batch.py +++ b/chrom_core/batch.py @@ -19,7 +19,7 @@ class FileReport: path: Path length: int = 0 - mean_q: float = 0.0 + mean_q: float | None = 0.0 # None: the read carries no quality values (all Q = 0) q20: int = 0 trim_start: int = 0 trim_end: int = 0 @@ -34,7 +34,10 @@ def status(self) -> str: """One of 'ok', 'warn', 'bad', 'error'.""" if self.error: return "error" - if self.trimmed_length >= MIN_OK_LENGTH and self.mean_q >= MIN_OK_MEAN_Q: + if ( + self.trimmed_length >= MIN_OK_LENGTH + and (self.mean_q or 0.0) >= MIN_OK_MEAN_Q + ): return "ok" if self.trimmed_length >= MIN_WARN_LENGTH: return "warn" @@ -56,7 +59,11 @@ def scan_folder(folder: str | Path, window: int = 20, min_q: int = 20) -> list[F FileReport( path=path, length=len(chrom.seq), - mean_q=round(sum(chrom.quality) / max(1, len(chrom.quality)), 1), + mean_q=( + round(sum(chrom.quality) / len(chrom.quality), 1) + if any(chrom.quality) + else None + ), q20=sum(1 for q in chrom.quality if q >= 20), trim_start=start, trim_end=end, @@ -130,7 +137,7 @@ def summary_csv(reports: list[FileReport]) -> str: for value in ( report.path.name, report.length, - report.mean_q, + "" if report.mean_q is None else report.mean_q, report.q20, report.trimmed_length, report.status, diff --git a/chrom_core/verify.py b/chrom_core/verify.py index 012a5f2..42bf607 100644 --- a/chrom_core/verify.py +++ b/chrom_core/verify.py @@ -17,7 +17,7 @@ from __future__ import annotations -from dataclasses import dataclass +from dataclasses import dataclass, field from chrom_core.abif import Chromatogram from chrom_core.align import ReadAlignment @@ -42,7 +42,12 @@ class VariantVerdict: quality: int | None = None ratio: float | None = None read_pos: int | None = None # 0-based index in the displayed read - note: str = "" + note: str = "" # English text for CSV/XLSX reports + note_code: str = "" # key for the localised UI text: verify.note. + note_args: dict = field(default_factory=dict) + + +_COMPLEMENT = {"A": "T", "C": "G", "G": "C", "T": "A"} # ------------------------------------------------------------------- parsing @@ -151,24 +156,33 @@ def _verify_one( and (len(variant.ref) == 1 or variant.ref in (".", "", "-")) ) if not is_snv: - return VariantVerdict(variant, "unsupported", "", note="only SNV rows are supported") + return VariantVerdict( + variant, "unsupported", "", note="only SNV rows are supported", note_code="only_snv" + ) if not 0 <= pos < len(reference): - return VariantVerdict(variant, "unsupported", "", note="position outside the reference") + return VariantVerdict( + variant, "unsupported", "", note="position outside the reference", + note_code="pos_outside_ref", + ) if variant.ref not in (".", "", "-") and variant.ref.upper() != reference[pos]: return VariantVerdict( - variant, "ref_mismatch", reference[pos], note="table ref base differs from the reference" + variant, "ref_mismatch", reference[pos], + note="table ref base differs from the reference", note_code="ref_differs", ) if pos not in alignment.ref_to_read: - note = ( - "deleted in the read" - if alignment.ref_start <= pos < alignment.ref_end - else "outside read coverage" - ) - return VariantVerdict(variant, "no_data", "", note=note) - - read_idx = alignment.ref_to_read[pos] + if alignment.ref_start <= pos < alignment.ref_end: + note, code = "deleted in the read", "deleted_in_read" + else: + note, code = "outside read coverage", "outside_coverage" + return VariantVerdict(variant, "no_data", "", note=note, note_code=code) + + # ref_to_read indexes the read in its aligned orientation; map it back to + # the displayed read (chrom) for '-' strand. + n = len(chrom.seq) + reverse = alignment.strand == "-" + read_idx = n - 1 - alignment.ref_to_read[pos] if reverse else alignment.ref_to_read[pos] quality = chrom.quality[read_idx] called = chrom.seq[read_idx].upper() called_alleles = set(IUPAC.get(called, "ACGT")) @@ -178,11 +192,14 @@ def _verify_one( alleles = set(called_alleles) if ratio is not None and ratio >= het_ratio and secondary_base: alleles.add(secondary_base) + if reverse: # express the observation on the reference strand + alleles = {_COMPLEMENT[a] for a in alleles} observed = alleles_to_iupac(alleles) if quality < min_q: return VariantVerdict( - variant, "low_quality", observed, quality, ratio, read_idx, f"Q{quality} < {min_q}" + variant, "low_quality", observed, quality, ratio, read_idx, f"Q{quality} < {min_q}", + "low_q", {"q": quality, "min_q": min_q}, ) alt_alleles = set(IUPAC.get(variant.alt, variant.alt)) @@ -221,6 +238,7 @@ def verdicts_xlsx(path, verdicts: list[VariantVerdict], sample_id: str = "") -> """Excel report via openpyxl (imported lazily; optional dependency).""" try: from openpyxl import Workbook + from openpyxl.styles import Font except ImportError as exc: # pragma: no cover - depends on environment raise RuntimeError("openpyxl is required for Excel reports: pip install openpyxl") from exc @@ -230,7 +248,7 @@ def verdicts_xlsx(path, verdicts: list[VariantVerdict], sample_id: str = "") -> header = ("sample",) + _CSV_HEADER sheet.append(header) for cell in sheet[1]: - cell.font = cell.font.copy(bold=True) + cell.font = Font(bold=True) for v in verdicts: ratio = round(v.ratio, 2) if v.ratio is not None else None sheet.append( diff --git a/i18n.py b/i18n.py index 3eb5254..da3cba2 100644 --- a/i18n.py +++ b/i18n.py @@ -79,6 +79,12 @@ "verify.ref_mismatch": "ref не совпал", "verify.low_quality": "низкое качество", "verify.unsupported": "не поддерживается", + "verify.note.only_snv": "поддерживаются только замены одного нуклеотида", + "verify.note.pos_outside_ref": "позиция вне референса", + "verify.note.ref_differs": "ref-основание из таблицы не совпадает с референсом", + "verify.note.deleted_in_read": "делеция в риде", + "verify.note.outside_coverage": "вне покрытия рида", + "verify.note.low_q": "Q{q} < {min_q}", "verify.summary": "{n} позиций: {confirmed} подтверждено, {het} гетерозигот, {notfound} не подтверждено, {nodata} без данных", "verify.need_reference": "Сначала загрузите референс и выровняйте чтение", "verify.save_csv": "Сохранить CSV…", diff --git a/tests/test_batch.py b/tests/test_batch.py index 01685c2..4b31ab5 100644 --- a/tests/test_batch.py +++ b/tests/test_batch.py @@ -101,3 +101,14 @@ def test_summary_csv(folder: Path) -> None: def test_csv_field_quoting() -> None: assert batch._csv_field("plain") == "plain" assert batch._csv_field('a"b;c') == '"a""b;c"' + + +def test_read_without_quality_reports_none_mean_q(folder: Path) -> None: + by_name = {r.path.name: r for r in batch.scan_folder(folder)} + assert by_name["310.ab1"].mean_q is None + assert by_name["3730.ab1"].mean_q is not None + row = next( + line for line in batch.summary_csv(list(by_name.values())).splitlines() + if line.startswith("310.ab1") + ) + assert row.split(";")[2] == "" diff --git a/tests/test_smoke_gui.py b/tests/test_smoke_gui.py index 9ac345e..11a5155 100644 --- a/tests/test_smoke_gui.py +++ b/tests/test_smoke_gui.py @@ -287,3 +287,53 @@ def test_session_autosave_and_restore(qapp, monkeypatch, tmp_path): assert reopened.read_model.modified reopened.close() assert sidecar.exists() + + +def test_verify_table_note_is_localised(qapp): + import i18n + from chrom_core.config import AppConfig + from i18n import tr + from ui.main_window import MainWindow + + sample = next(p for p in AB1 if "3730" in p.name) + i18n.set_language("ru") + try: + window = MainWindow(AppConfig(recent_files=[], language="ru")) + assert window.open_path(sample) + seq = "".join(window.read_model.seq) + ref = seq[100:400] + window._set_reference_seq(ref) + wrong = "A" if ref[50] != "A" else "C" + window._verify_variants(f"name;pos;ref;alt\nsnp;51;{wrong};T\n") + note_cell_text = window.verify_table.item(0, 7).text() + assert "table ref base" not in note_cell_text + assert note_cell_text == tr("verify.note.ref_differs") + window.close() + finally: + i18n.set_language("ru") + + +def test_reverse_read_reference_overlay_in_displayed_orientation(qapp): + from chrom_core.config import AppConfig + from clone_fixtures import DATA, reference_for + from ui.main_window import MainWindow + + name = "Achl_ACHLO006-09_2_R.ab1" + window = MainWindow(AppConfig(recent_files=[])) + assert window.open_path(DATA / "real" / name) + window._set_reference_seq(reference_for(name)) + assert window.alignment.strand == "-" + + letters, mapping = window.chrom_view.reference + seq = window.read_model.seq + assert mapping and all(0 <= idx < len(seq) for idx in mapping.values()) + matches = sum(letters[pos].upper() == seq[idx].upper() for pos, idx in mapping.items()) + assert matches / len(mapping) > 0.9 + + # the "№ базы" column shows displayed 1-based indices + for row in range(window.diff_table.rowCount()): + shown = window.diff_table.item(row, 4).text() + ref_pos = int(window.diff_table.item(row, 0).text()) - 1 + if shown and ref_pos in mapping: + assert int(shown) - 1 == mapping[ref_pos] + window.close() diff --git a/tests/test_verify.py b/tests/test_verify.py index 52c55fd..1a2aba6 100644 --- a/tests/test_verify.py +++ b/tests/test_verify.py @@ -170,6 +170,64 @@ def test_ref_mismatch(setup) -> None: assert verdicts[0].observed == reference[50] +def test_ref_mismatch_carries_note_code(setup) -> None: + reference = setup + wrong_ref = "A" if reference[50] != "A" else "C" + verdicts, _ = _verify(reference, reference, [ExpectedVariant(51, wrong_ref, "T")]) + assert verdicts[0].note_code == "ref_differs" + assert verdicts[0].note # English text stays for CSV/XLSX + + +def test_other_note_codes(setup) -> None: + reference = setup + verdicts, _ = _verify(reference, reference, [ExpectedVariant(51, "AT", "GC")]) + assert verdicts[0].note_code == "only_snv" + verdicts, _ = _verify(reference, reference, [ExpectedVariant(5000, ".", "A")]) + assert verdicts[0].note_code == "pos_outside_ref" + read = reference[:40] + reference[60:] + verdicts, _ = _verify(reference, read, [ExpectedVariant(51, reference[50], "A")]) + assert verdicts[0].note_code == "deleted_in_read" + alt = "T" if reference[50] != "T" else "A" + chrom = make_chrom(confirmed_case(reference, 50, alt), quality=10) + verdicts, _ = _verify(reference, confirmed_case(reference, 50, alt), + [ExpectedVariant(51, reference[50], alt)], chrom=chrom) + assert verdicts[0].note_code == "low_q" + assert verdicts[0].note_args == {"q": 10, "min_q": 20} + + +_COMP = {"A": "T", "C": "G", "G": "C", "T": "A"} + + +@pytest.mark.parametrize("name", ["Achl_ACHLO006-09_1_F.ab1", "Achl_ACHLO006-09_2_R.ab1"]) +def test_real_read_confirmed_on_both_strands(name) -> None: + from clone_fixtures import real_read, reference_for + + chrom = real_read(name) + reference = reference_for(name) + alignment = align_read("".join(chrom.seq), reference) + assert alignment.strand == ("-" if name.endswith("_R.ab1") else "+") + n = len(chrom.seq) + checked = 0 + for pos, oriented_idx in sorted(alignment.ref_to_read.items()): + if pos < 100: + continue + idx = oriented_idx if alignment.strand == "+" else n - 1 - oriented_idx + if chrom.quality[idx] < 30 or chrom.seq[idx].upper() not in "ACGT": + continue + base = chrom.seq[idx].upper() + ref_strand = base if alignment.strand == "+" else _COMP[base] + verdict = verify_expected( + alignment, chrom, reference, [ExpectedVariant(pos + 1, ".", ref_strand)] + )[0] + assert verdict.verdict == "confirmed", (pos, verdict) + assert verdict.observed == ref_strand + assert verdict.read_pos == idx + checked += 1 + if checked >= 40: + break + assert checked == 40 + + def test_low_quality(setup) -> None: reference = setup read = confirmed_case(reference, 50, "T" if reference[50] != "T" else "A") diff --git a/translations_en.py b/translations_en.py index 3efc92a..1515770 100644 --- a/translations_en.py +++ b/translations_en.py @@ -72,6 +72,12 @@ "verify.ref_mismatch": "ref mismatch", "verify.low_quality": "low quality", "verify.unsupported": "unsupported", + "verify.note.only_snv": "only SNV rows are supported", + "verify.note.pos_outside_ref": "position outside the reference", + "verify.note.ref_differs": "table ref base differs from the reference", + "verify.note.deleted_in_read": "deleted in the read", + "verify.note.outside_coverage": "outside read coverage", + "verify.note.low_q": "Q{q} < {min_q}", "verify.summary": "{n} positions: {confirmed} confirmed, {het} heterozygous, {notfound} not confirmed, {nodata} no data", "verify.need_reference": "Load a reference and align the read first", "verify.save_csv": "Save CSV…", diff --git a/ui/batch_panel.py b/ui/batch_panel.py index c9cd77c..6919cef 100644 --- a/ui/batch_panel.py +++ b/ui/batch_panel.py @@ -73,7 +73,10 @@ def show_reports(self, reports: list[FileReport]) -> None: for row, report in enumerate(reports): self._set_item(row, 0, report.path.name, data=str(report.path)) self._set_item(row, 1, report.length if not report.error else "") - self._set_item(row, 2, report.mean_q if not report.error else "") + self._set_item( + row, 2, + "" if report.error else "—" if report.mean_q is None else report.mean_q, + ) self._set_item(row, 3, report.q20 if not report.error else "") self._set_item(row, 4, report.trimmed_length if not report.error else "") status = QTableWidgetItem(STATUS_TEXT[report.status]) diff --git a/ui/main_window.py b/ui/main_window.py index 7fc29cf..bd38279 100644 --- a/ui/main_window.py +++ b/ui/main_window.py @@ -41,7 +41,7 @@ from chrom_core.editing import INSERT_LETTERS, IUPAC_LETTERS from chrom_core.snps import call_snps from chrom_core.verify import parse_expected, verify_expected, verdicts_csv, verdicts_xlsx -from chrom_core.seqops import find_matches +from chrom_core.seqops import find_matches, reverse_complement from i18n import set_language, tr from ui.batch_panel import BatchPanel from ui.chrom_view import ChromatogramWidget @@ -536,6 +536,28 @@ def _set_reference_seq(self, sequence: str) -> None: else: self.statusBar().showMessage(tr("analysis.need_read"), 5000) + def _reference_overlay(self) -> tuple[str, dict[int, int]]: + """Reference letters and ref -> index mapping in the *displayed* read's + orientation (the alignment indexes the reverse complement on '-').""" + alignment = self.alignment + if alignment.strand == "+": + return self.reference_seq, alignment.ref_to_read + n = len(self.read_model.seq) + return ( + reverse_complement(self.reference_seq)[::-1], # complement, same ref indexing + {pos: n - 1 - idx for pos, idx in alignment.ref_to_read.items()}, + ) + + def _displayed_diff_index(self, diff) -> int | None: + """0-based index of ``diff`` in the displayed read (None for deletions).""" + if diff.read_pos is None: + return None + if self.alignment.strand == "+": + return diff.read_pos + n = len(self.read_model.seq) + span = len(diff.read_base) if diff.kind == "insertion" else 1 + return n - diff.read_pos - span + def _clear_reference(self) -> None: self.reference_seq = "" self.alignment = None @@ -552,7 +574,8 @@ def _realign(self) -> None: QMessageBox.warning(self, tr("analysis.ref.title"), str(exc)) self._clear_reference() return - self.chrom_view.set_reference(self.reference_seq, self.alignment.ref_to_read) + letters, ref_to_read = self._reference_overlay() + self.chrom_view.set_reference(letters, ref_to_read) chrom = self.read_model.current() self.snp_calls = call_snps( self.alignment, chrom, @@ -612,7 +635,8 @@ def _fill_diff_table(self) -> None: diff.ref_base, diff.read_base, (call.read_pos + 1 if call is not None - else diff.read_pos + 1 if diff.read_pos is not None else ""), + else shown + 1 if (shown := self._displayed_diff_index(diff)) is not None + else ""), verdict, call.quality if call is not None else "", f"{call.ratio:.2f}" if call is not None and call.ratio is not None else "", @@ -745,7 +769,7 @@ def _fill_verify_table(self) -> None: labels.get(v.verdict, v.verdict), v.observed, v.quality if v.quality is not None else "", - v.note, + tr(f"verify.note.{v.note_code}", **v.note_args) if v.note_code else v.note, ] for col, value in enumerate(values): item = QTableWidgetItem() From faabf635ae1e55c372e2bd4937b31d00a4dd2be0 Mon Sep 17 00:00:00 2001 From: Aleksey Drobin <43707931+adrobi@users.noreply.github.com> Date: Sun, 25 Oct 2026 01:54:07 +0300 Subject: [PATCH 07/44] reference: load constructs from FASTA, GenBank and SnapGene Co-Authored-By: Claude Sonnet 5.5 --- chrom_core/reference.py | 91 +++++++++++++++++++++++++++++++++++++++++ tests/test_reference.py | 90 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 181 insertions(+) create mode 100644 chrom_core/reference.py create mode 100644 tests/test_reference.py diff --git a/chrom_core/reference.py b/chrom_core/reference.py new file mode 100644 index 0000000..8a9cc21 --- /dev/null +++ b/chrom_core/reference.py @@ -0,0 +1,91 @@ +"""Reference constructs (plasmid / insert): loading from FASTA, GenBank, SnapGene.""" +from __future__ import annotations + +from dataclasses import dataclass, replace +from pathlib import Path + +from Bio import SeqIO + +from .align import parse_sequence + +_FORMAT_BY_EXT = { + ".fa": "fasta", ".fasta": "fasta", ".fna": "fasta", ".txt": "fasta", + ".gb": "genbank", ".gbk": "genbank", ".genbank": "genbank", + ".dna": "snapgene", +} +_NAME_QUALIFIERS = ("label", "gene", "product", "note") + + +@dataclass(frozen=True) +class Feature: + """Annotated region; 0-based, half-open. start > end: wraps the origin.""" + + name: str + kind: str + start: int + end: int + strand: int + codon_start: int = 1 + + +@dataclass(frozen=True) +class Construct: + name: str + seq: str + circular: bool + features: tuple[Feature, ...] = () + + def with_circular(self, flag: bool) -> Construct: + return replace(self, circular=flag) + + +def construct_from_text(text: str, name: str = "pasted") -> Construct: + return Construct(name, parse_sequence(text), True) + + +def _detect_format(path: Path) -> str: + fmt = _FORMAT_BY_EXT.get(path.suffix.lower()) + if fmt: + return fmt + with open(path, "rb") as fh: + head = fh.read(512).lstrip() + if head.startswith(b">"): + return "fasta" + if head.startswith(b"LOCUS"): + return "genbank" + raise ValueError(f"cannot determine reference format of {path.name}") + + +def _feature(f) -> Feature: + loc = f.location + parts = list(loc.parts) + if loc.strand == -1: + parts.reverse() # Biopython lists complement(join()) parts in transcript order + start, end = int(parts[0].start), int(parts[-1].end) + q = f.qualifiers + name = next((q[k][0] for k in _NAME_QUALIFIERS if q.get(k)), f.type) + try: + codon_start = int(q["codon_start"][0]) if f.type == "CDS" else 1 + except (KeyError, IndexError, ValueError): + codon_start = 1 + return Feature(str(name), f.type, start, end, int(loc.strand or 0), codon_start) + + +def load_construct(path: str | Path) -> Construct: + path = Path(path) + fmt = _detect_format(path) + try: + record = next(SeqIO.parse(path, fmt), None) + except Exception as exc: # Biopython raises assorted parser errors + raise ValueError(f"cannot parse {path.name} as {fmt}: {exc}") from exc + if record is None: + raise ValueError(f"no sequence records in {path.name}") + seq = parse_sequence(str(record.seq)) + if not seq: + raise ValueError(f"empty sequence in {path.name}") + if fmt == "fasta": + circular, features = True, () + else: + circular = record.annotations.get("topology") == "circular" + features = tuple(_feature(f) for f in record.features) + return Construct(record.id or path.stem, seq, circular, features) diff --git a/tests/test_reference.py b/tests/test_reference.py new file mode 100644 index 0000000..ce563a4 --- /dev/null +++ b/tests/test_reference.py @@ -0,0 +1,90 @@ +import pytest +from Bio import SeqIO + +from clone_fixtures import COI_GB, PUC19_GB, SNAPGENE_DNA +from chrom_core.reference import Construct, Feature, construct_from_text, load_construct + + +def test_genbank_puc19(): + c = load_construct(PUC19_GB) + assert len(c.seq) == len(SeqIO.read(PUC19_GB, "genbank").seq) and c.circular + # The committed L09137 record annotates only "source" (no CDS); CDS is covered by COI below. + assert [f.kind for f in c.features] == ["source"] + + +def test_coi_has_cds(): + assert any(f.kind == "CDS" for f in load_construct(COI_GB).features) + + +def test_puc19_length_is_2686(): + assert len(load_construct(PUC19_GB).seq) == 2686 + + +def test_snapgene_sample(): + c = load_construct(SNAPGENE_DNA) + assert c.seq and c.features + + +def test_coi_cds_codon_start_and_name(): + c = load_construct(COI_GB) + cds = [f for f in c.features if f.kind == "CDS"] + assert cds and all(f.codon_start in (1, 2, 3) for f in cds) + rec = SeqIO.read(COI_GB, "genbank") + want = int(next(f for f in rec.features if f.type == "CDS").qualifiers.get("codon_start", ["1"])[0]) + assert cds[0].codon_start == want + assert all(f.name for f in c.features) + + +def test_fasta_multi_record_lowercase(tmp_path): + p = tmp_path / "x.fasta" + p.write_text(">a\nacgtn\n>b\nTTTT\n") + c = load_construct(p) + assert c.seq == "ACGTN" and c.circular and c.features == () + + +def test_unknown_extension_sniffed_fasta(tmp_path): + p = tmp_path / "x.seq" + p.write_text(">a\nACGT\n") + assert load_construct(p).seq == "ACGT" + + +def test_unknown_extension_sniffed_genbank(tmp_path): + p = tmp_path / "x.seq" + p.write_bytes(PUC19_GB.read_bytes()) + assert len(load_construct(p).seq) == 2686 + + +def test_garbage_rejected(tmp_path): + p = tmp_path / "x.seq" + p.write_text("hello world") + with pytest.raises(ValueError): + load_construct(p) + + +def test_invalid_chars_rejected(tmp_path): + p = tmp_path / "x.fa" + p.write_text(">a\nAC!GT\n") + with pytest.raises(ValueError): + load_construct(p) + + +def test_with_circular_toggle(): + assert not construct_from_text("ACGT").with_circular(False).circular + + +def test_construct_from_text_defaults(): + c = construct_from_text(">x\nacgt\n") + assert c == Construct("pasted", "ACGT", True, ()) + + +def test_origin_spanning_feature(tmp_path): + p = tmp_path / "o.gb" + p.write_text( + "LOCUS t 12 bp DNA circular SYN 01-JAN-2000\n" + "FEATURES Location/Qualifiers\n" + " misc_feature join(9..12,1..3)\n" + ' /label="wrap"\n' + "ORIGIN\n 1 acgtacgtac gt\n//\n" + ) + f = load_construct(p).features[0] + assert (f.name, f.start, f.end, f.strand, f.codon_start) == ("wrap", 8, 3, 1, 1) From 474b04e6a4f1c56274c264e1d9b79e3713e2623d Mon Sep 17 00:00:00 2001 From: Aleksey Drobin <43707931+adrobi@users.noreply.github.com> Date: Sun, 25 Oct 2026 01:54:31 +0300 Subject: [PATCH 08/44] tests: well-formed LOCUS line in reference test Co-Authored-By: Claude Sonnet 5.5 --- tests/test_reference.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/test_reference.py b/tests/test_reference.py index ce563a4..0f9317b 100644 --- a/tests/test_reference.py +++ b/tests/test_reference.py @@ -80,7 +80,7 @@ def test_construct_from_text_defaults(): def test_origin_spanning_feature(tmp_path): p = tmp_path / "o.gb" p.write_text( - "LOCUS t 12 bp DNA circular SYN 01-JAN-2000\n" + "LOCUS t 12 bp DNA circular SYN 01-JAN-2000\n" "FEATURES Location/Qualifiers\n" " misc_feature join(9..12,1..3)\n" ' /label="wrap"\n' From 20706df18f8546b5b963d2a8a701a90f22624ec0 Mon Sep 17 00:00:00 2001 From: Aleksey Drobin <43707931+adrobi@users.noreply.github.com> Date: Fri, 30 Oct 2026 01:55:50 +0300 Subject: [PATCH 09/44] align: circular constructs with origin-spanning reads Co-Authored-By: Claude Opus 5.5 --- chrom_core/align.py | 160 ++++++++++++++++++++++++++------ tests/test_align_circular.py | 171 +++++++++++++++++++++++++++++++++++ 2 files changed, 305 insertions(+), 26 deletions(-) create mode 100644 tests/test_align_circular.py diff --git a/chrom_core/align.py b/chrom_core/align.py index 7417ca6..f07a2fc 100644 --- a/chrom_core/align.py +++ b/chrom_core/align.py @@ -14,17 +14,22 @@ from __future__ import annotations -from dataclasses import dataclass +from dataclasses import dataclass, replace +from typing import TYPE_CHECKING from Bio import Align from chrom_core.seqops import IUPAC, reverse_complement +if TYPE_CHECKING: # reference.py imports this module; avoid a runtime cycle + from chrom_core.reference import Construct + MATCH_SCORE = 2.0 MISMATCH_SCORE = -3.0 GAP_OPEN = -10.0 GAP_EXTEND = -1.0 MAX_REFERENCE_LENGTH = 100_000 +CIRCULAR_MARGIN = 50 # extra unrolled bases past len(read) for circular constructs @dataclass(frozen=True) @@ -40,8 +45,8 @@ class Difference: class ReadAlignment: strand: str # '+' or '-', relative to the read as passed in score: float - ref_start: int # covered reference span, 0-based [start, end) - ref_end: int + ref_start: int # covered reference span, 0-based [start, end); + ref_end: int # ref_end < ref_start: wraps the origin of a circle read_start: int read_end: int ref_to_read: dict[int, int] # covered ref position -> read index @@ -50,11 +55,29 @@ class ReadAlignment: alternatives: int # number of co-optimal alignments (1 = unique) oriented_read: str # the read in its aligned orientation blocks: list # biopython aligned blocks, for gapped reconstruction + # (unrolled coordinates for circular constructs) + ref_length: int = 0 # construct length (0 = unknown, from align_read) + + @property + def wraps(self) -> bool: + return self.ref_end < self.ref_start @property def covered(self) -> int: + if self.wraps: + return self.ref_length - self.ref_start + self.ref_end return self.ref_end - self.ref_start + def covers(self, pos: int) -> bool: + if self.wraps: + return self.ref_start <= pos < self.ref_length or 0 <= pos < self.ref_end + return self.ref_start <= pos < self.ref_end + + def covered_positions(self) -> list[int]: + if self.wraps: + return list(range(self.ref_start, self.ref_length)) + list(range(self.ref_end)) + return list(range(self.ref_start, self.ref_end)) + def _make_aligner() -> Align.PairwiseAligner: aligner = Align.PairwiseAligner() @@ -85,20 +108,33 @@ def parse_sequence(text: str) -> str: return seq -def align_read(read: str, reference: str) -> ReadAlignment: - """Align a (possibly reverse-strand) read into the reference.""" +def _clean(read: str, reference: str) -> tuple[str, str]: read = "".join(read.split()).upper() reference = "".join(reference.split()).upper() if not read: raise ValueError("empty read") if not reference: raise ValueError("empty reference") - if len(reference) > MAX_REFERENCE_LENGTH: + return read, reference + + +def _check_length(length: int) -> None: + if length > MAX_REFERENCE_LENGTH: raise ValueError( - f"reference of {len(reference)} bp is too long for exact alignment " + f"reference of {length} bp is too long for exact alignment " f"(limit {MAX_REFERENCE_LENGTH})" ) + +def align_read(read: str, reference: str) -> ReadAlignment: + """Align a (possibly reverse-strand) read into the reference.""" + read, reference = _clean(read, reference) + _check_length(len(reference)) + return _align(read, reference) + + +def _align(read: str, reference: str) -> ReadAlignment: + """align_read without the size limit (callers check it on the real length).""" aligner = _make_aligner() best: tuple[float, object, str, str] | None = None for strand, oriented in (("+", read), ("-", reverse_complement(read))): @@ -114,6 +150,34 @@ def align_read(read: str, reference: str) -> ReadAlignment: except Exception: # counting can blow up on pathological repeats alternatives = 0 # "unknown" + ref_to_read, differences, identity = _walk_blocks(blocks, reference, oriented) + differences.sort(key=lambda d: (d.ref_pos, d.kind)) + if blocks: + ref_start, ref_end = int(blocks[0][0][0]), int(blocks[-1][0][1]) + read_start, read_end = int(blocks[0][1][0]), int(blocks[-1][1][1]) + else: # no similarity at all: empty alignment (everything became free end gaps) + ref_start = ref_end = read_start = read_end = 0 + + return ReadAlignment( + strand=strand, + score=score, + ref_start=ref_start, + ref_end=ref_end, + read_start=read_start, + read_end=read_end, + ref_to_read=ref_to_read, + differences=differences, + identity=identity, + alternatives=alternatives, + oriented_read=oriented, + blocks=blocks, + ) + + +def _walk_blocks( + blocks: list, reference: str, oriented: str +) -> tuple[dict[int, int], list[Difference], float]: + """Per-position mapping, differences (unsorted) and identity of a block list.""" ref_to_read: dict[int, int] = {} differences: list[Difference] = [] matches = 0 @@ -145,28 +209,69 @@ def align_read(read: str, reference: str) -> ReadAlignment: Difference(int(t0 + k), "substitution", ref_base, read_base, int(q0 + k)) ) prev_t, prev_q = t1, q1 - - differences.sort(key=lambda d: (d.ref_pos, d.kind)) identity = matches / columns if columns else 0.0 - if blocks: - ref_start, ref_end = int(blocks[0][0][0]), int(blocks[-1][0][1]) - read_start, read_end = int(blocks[0][1][0]), int(blocks[-1][1][1]) - else: # no similarity at all: empty alignment (everything became free end gaps) - ref_start = ref_end = read_start = read_end = 0 + return ref_to_read, differences, identity - return ReadAlignment( - strand=strand, - score=score, + +def align_to_construct(read: str, construct: Construct) -> ReadAlignment: + """Align a read to a construct; circular constructs allow reads across the origin. + + Linear: ``align_read`` plus ``ref_length``. Circular: the read is aligned to + the unrolled sequence ``seq + seq[:len(read) + CIRCULAR_MARGIN]`` and every + ``ref_*`` coordinate, ``ref_to_read`` key and ``Difference.ref_pos`` is + reported modulo ``L = len(seq)`` (``ref_end`` as ``((ref_end - 1) % L) + 1``), + so ``ref_end < ref_start`` means the span wraps the origin. ``blocks`` stay + in unrolled coordinates: pass ``construct.seq * 2`` to ``gapped_sequences``. + + A read longer than the circle can align over the same positions twice. The + first pass (in alignment order, from the alignment start) is kept: blocks + are clipped at ``start + L``, so at most L positions are reported, each + once, and identity/differences are computed over the clipped alignment. + Full coverage is normalised to ``(0, L)``. Differences are listed in + alignment order (the part after the origin last). The size limit applies + to ``L``, not to the unrolled sequence. + """ + read, seq = _clean(read, construct.seq) + L = len(seq) + _check_length(L) + if not construct.circular: + return replace(_align(read, seq), ref_length=L) + + unrolled = seq + seq[: len(read) + CIRCULAR_MARGIN] + raw = _align(read, unrolled) + if not raw.blocks: + return replace(raw, ref_length=L) + + shift = (raw.blocks[0][0][0] // L) * L # make the alignment start in the first copy + limit = raw.blocks[0][0][0] - shift + L + clipped = [] + for (t0, t1), (q0, q1) in raw.blocks: + t0, t1 = t0 - shift, t1 - shift + if t0 >= limit: + break + if t1 > limit: + q1 = q0 + (limit - t0) + t1 = limit + clipped.append(((int(t0), int(t1)), (int(q0), int(q1)))) + + ref_to_read, differences, identity = _walk_blocks(clipped, unrolled, raw.oriented_read) + differences.sort(key=lambda d: (d.ref_pos, d.kind)) # unrolled order = alignment order + ref_start, ref_end = clipped[0][0][0], clipped[-1][0][1] + if ref_end - ref_start >= L: + ref_start, ref_end = 0, L + else: + ref_start, ref_end = ref_start % L, ((ref_end - 1) % L) + 1 + return replace( + raw, ref_start=ref_start, ref_end=ref_end, - read_start=read_start, - read_end=read_end, - ref_to_read=ref_to_read, - differences=differences, + read_start=clipped[0][1][0], + read_end=clipped[-1][1][1], + ref_to_read={p % L: q for p, q in ref_to_read.items()}, + differences=[replace(d, ref_pos=d.ref_pos % L) for d in differences], identity=identity, - alternatives=alternatives, - oriented_read=oriented, - blocks=blocks, + blocks=clipped, + ref_length=L, ) @@ -175,8 +280,11 @@ def gapped_sequences(alignment: ReadAlignment, reference: str) -> tuple[str, str reference = reference.upper() ref_aligned: list[str] = [] read_aligned: list[str] = [] - prev_t = alignment.ref_start - prev_q = alignment.read_start + if not alignment.blocks: + return "", "" + # start at the first block (== ref_start/read_start for align_read; for a + # circular alignment the blocks are in unrolled coordinates) + (prev_t, _), (prev_q, _) = alignment.blocks[0] for (t0, t1), (q0, q1) in alignment.blocks: ref_aligned.extend(reference[prev_t:t0]) read_aligned.extend("-" * (t0 - prev_t)) diff --git a/tests/test_align_circular.py b/tests/test_align_circular.py new file mode 100644 index 0000000..f7ba1e9 --- /dev/null +++ b/tests/test_align_circular.py @@ -0,0 +1,171 @@ +import random + +import pytest + +from clone_fixtures import coi_reference, real_read +from chrom_core.align import ( + CIRCULAR_MARGIN, + MAX_REFERENCE_LENGTH, + align_read, + align_to_construct, + gapped_sequences, +) +from chrom_core.reference import Construct + +READ_NAME = "Achl_ACHLO006-09_1_F.ab1" + + +@pytest.fixture(scope="module") +def read_seq() -> str: + return real_read(READ_NAME).seq + + +@pytest.fixture(scope="module") +def ref() -> str: + return coi_reference() + + +@pytest.fixture(scope="module") +def insert_read(read_seq, ref) -> str: + """The part of the real read that lies inside the COI reference. + + The raw read (703 bp) overhangs BOTH ends of the 658 bp reference. Biopython's + end gaps are free on one sequence per end only, so on an unrolled circle the + 44-base junk tail is cheaper aligned onto the start of the circle than gapped + — the read then legitimately "covers" the whole ring. A clone read sits + inside its construct, so the rotation tests use the inside part. + """ + full = align_read(read_seq, ref) + return read_seq[full.read_start:full.read_end] + + +@pytest.fixture(scope="module") +def aln0(insert_read, ref): + return align_read(insert_read, ref) + + +@pytest.fixture(scope="module") +def mid(aln0) -> int: + m = (aln0.ref_start + aln0.ref_end) // 2 + # the new origin must fall well inside the read's covered span + assert aln0.ref_start + 100 < m < aln0.ref_end - 100 + return m + + +@pytest.fixture(scope="module") +def rotated(ref, mid) -> str: + return ref[mid:] + ref[:mid] + + +def _random_seq(n: int, seed: int) -> str: + rng = random.Random(seed) + return "".join(rng.choice("ACGT") for _ in range(n)) + + +def test_margin_constant() -> None: + assert CIRCULAR_MARGIN == 50 + + +def test_linear_matches_align_read(read_seq, ref) -> None: + aln0 = align_read(read_seq, ref) + aln = align_to_construct(read_seq, Construct("coi", ref, False)) + assert aln.differences == aln0.differences + assert aln.identity == aln0.identity + assert (aln.ref_start, aln.ref_end) == (aln0.ref_start, aln0.ref_end) + assert aln.ref_to_read == aln0.ref_to_read + assert aln.ref_length == len(ref) + assert aln.covered == aln0.covered + assert aln.covered_positions() == list(range(aln0.ref_start, aln0.ref_end)) + assert aln0.ref_start > 0 + assert aln.covers(aln0.ref_start) and not aln.covers(aln0.ref_start - 1) + + +def test_read_across_origin_of_rotated_reference(insert_read, ref, aln0, mid, rotated) -> None: + aln = align_to_construct(insert_read, Construct("rot", rotated, True)) + L = len(ref) + assert aln.ref_length == L + assert aln.ref_end < aln.ref_start # wrapped + assert len(aln.covered_positions()) == aln0.covered + assert aln.covered == aln0.covered + assert [(d.ref_pos - (L - mid)) % L for d in aln.differences] == [ + d.ref_pos for d in aln0.differences + ] + assert aln.covers(0) and aln.covers(L - 1) + assert aln.identity == pytest.approx(aln0.identity) + # every key is a real construct position; the mapping is the rotation of aln0's + assert all(0 <= p < L for p in aln.ref_to_read) + assert {(p + mid) % L: q for p, q in aln.ref_to_read.items()} == aln0.ref_to_read + # gapped reconstruction over the unrolled reference gives the same pair + assert gapped_sequences(aln, rotated * 2) == gapped_sequences(aln0, ref) + + +def test_same_rotation_linear_breaks_read(insert_read, aln0, rotated) -> None: + aln = align_to_construct(insert_read, Construct("rot", rotated, False)) + assert aln.covered < aln0.covered # without the ring the read is cut at the origin + # only one side of the origin can be aligned: roughly half of the read's span + assert aln.covered <= aln0.covered * 0.6 + assert aln.ref_end >= aln.ref_start + + +def test_real_read_longer_than_circular_construct(read_seq, ref) -> None: + assert len(read_seq) > len(ref) + aln = align_to_construct(read_seq, Construct("coi", ref, True)) + positions = aln.covered_positions() + assert len(positions) == len(set(positions)) <= len(ref) + assert all(0 <= p < len(ref) for p in positions) + assert set(aln.ref_to_read) <= set(positions) + assert all(0 <= d.ref_pos < len(ref) for d in aln.differences) + assert aln.covered == len(positions) + + +def test_tandem_read_longer_than_circle_reports_each_position_once() -> None: + circle = _random_seq(300, seed=7) + read = (circle * 3)[50:50 + 400] # wraps the circle more than once + aln = align_to_construct(read, Construct("small", circle, True)) + L = len(circle) + positions = aln.covered_positions() + assert len(positions) == L and sorted(positions) == list(range(L)) + assert aln.covered == L + assert (aln.ref_start, aln.ref_end) == (0, L) + assert all(aln.covers(p) for p in range(L)) + assert sorted(aln.ref_to_read) == list(range(L)) + # the first pass over the circle wins: read index 0 sits at construct position 50 + assert aln.ref_to_read[50] == 0 + assert aln.ref_to_read[49] == L - 1 + assert aln.differences == [] + assert aln.identity == 1.0 + ref_g, read_g = gapped_sequences(aln, circle * 2) + assert len(ref_g) == L and ref_g == read_g == read[:L] + + +def test_wrapped_coordinates_minus_strand() -> None: + from chrom_core.seqops import reverse_complement + + circle = _random_seq(500, seed=11) + insert = circle[420:] + circle[:90] # 170 bp across the origin + aln = align_to_construct(reverse_complement(insert), Construct("c", circle, True)) + assert aln.strand == "-" + assert (aln.ref_start, aln.ref_end) == (420, 90) + assert aln.covered == 170 + assert aln.covered_positions() == list(range(420, 500)) + list(range(90)) + assert aln.ref_to_read[420] == 0 and aln.ref_to_read[0] == 80 and aln.ref_to_read[89] == 169 + assert not aln.covers(90) and not aln.covers(419) + + +def test_wrapped_differences_are_mod_length() -> None: + circle = _random_seq(400, seed=3) + insert = list(circle[350:] + circle[:60]) # covers 350..399, 0..59 + insert[55] = "A" if insert[55] != "A" else "C" # construct position 5 + aln = align_to_construct("".join(insert), Construct("c", circle, True)) + assert [(d.ref_pos, d.kind) for d in aln.differences] == [(5, "substitution")] + + +def test_limit_applies_to_original_length() -> None: + big = _random_seq(MAX_REFERENCE_LENGTH, seed=5) + read = big[1000:1030] + aln = align_to_construct(read, Construct("big", big, True)) + assert aln.ref_length == MAX_REFERENCE_LENGTH + with pytest.raises(ValueError): + align_to_construct(read, Construct("big", big + "A", True)) + with pytest.raises(ValueError): + align_to_construct(read, Construct("big", big + "A", False)) From 1437a428d9bee8cda4b6773aafcad8ec88571073 Mon Sep 17 00:00:00 2001 From: Aleksey Drobin <43707931+adrobi@users.noreply.github.com> Date: Fri, 30 Oct 2026 01:59:36 +0300 Subject: [PATCH 10/44] align: count circular alternatives distinct modulo construct length Co-Authored-By: Claude Opus 5.5 --- chrom_core/align.py | 58 +++++++++++++++++++++++++++++------- tests/test_align_circular.py | 19 ++++++++++++ 2 files changed, 67 insertions(+), 10 deletions(-) diff --git a/chrom_core/align.py b/chrom_core/align.py index f07a2fc..a6ac417 100644 --- a/chrom_core/align.py +++ b/chrom_core/align.py @@ -30,6 +30,7 @@ GAP_EXTEND = -1.0 MAX_REFERENCE_LENGTH = 100_000 CIRCULAR_MARGIN = 50 # extra unrolled bases past len(read) for circular constructs +MAX_COUNTED_ALTERNATIVES = 1000 # co-optimal paths examined to dedupe the circular copy @dataclass(frozen=True) @@ -130,11 +131,14 @@ def align_read(read: str, reference: str) -> ReadAlignment: """Align a (possibly reverse-strand) read into the reference.""" read, reference = _clean(read, reference) _check_length(len(reference)) - return _align(read, reference) + return _align(read, reference)[0] -def _align(read: str, reference: str) -> ReadAlignment: - """align_read without the size limit (callers check it on the real length).""" +def _align(read: str, reference: str) -> tuple[ReadAlignment, object]: + """align_read without the size limit (callers check it on the real length). + + Also returns biopython's co-optimal alignments for the winning strand. + """ aligner = _make_aligner() best: tuple[float, object, str, str] | None = None for strand, oriented in (("+", read), ("-", reverse_complement(read))): @@ -171,7 +175,32 @@ def _align(read: str, reference: str) -> ReadAlignment: alternatives=alternatives, oriented_read=oriented, blocks=blocks, - ) + ), alignments + + +def _circular_alternatives(raw: ReadAlignment, alignments, L: int) -> int: + """Co-optimal alignments distinct modulo L. + + A read in the first ``len(read) + CIRCULAR_MARGIN`` bases also matches the + unrolled copy, shifted by exactly L; such pairs count once. 0 stays + "unknown". Beyond ``MAX_COUNTED_ALTERNATIVES`` paths the raw count is + returned: an upper bound, and at least half of it is distinct (at most two + copies of any path fit in the unrolled sequence), so it stays > 1. + """ + if raw.alternatives <= 1 or raw.alternatives > MAX_COUNTED_ALTERNATIVES: + return raw.alternatives + distinct = set() + try: + for alignment in alignments: + ts, qs = alignment.aligned + shift = (int(ts[0][0]) // L) * L if len(ts) else 0 + distinct.add(tuple( + (int(t0) - shift, int(t1) - shift, int(q0), int(q1)) + for (t0, t1), (q0, q1) in zip(ts, qs) + )) + except Exception: # same "unknown" convention as align_read + return 0 + return len(distinct) def _walk_blocks( @@ -227,20 +256,28 @@ def align_to_construct(read: str, construct: Construct) -> ReadAlignment: first pass (in alignment order, from the alignment start) is kept: blocks are clipped at ``start + L``, so at most L positions are reported, each once, and identity/differences are computed over the clipped alignment. - Full coverage is normalised to ``(0, L)``. Differences are listed in - alignment order (the part after the origin last). The size limit applies - to ``L``, not to the unrolled sequence. + ``score`` however stays that of the unclipped raw alignment. Full coverage + is normalised to ``(0, L)``. + + For a wrapped alignment ``differences`` is in alignment order — positions + after the origin come last — not ascending by ``ref_pos``. + + ``alternatives`` counts co-optimal alignments distinct modulo L, so the + unrolled copy of the construct's start is not mistaken for a repeat. + + The size limit applies to ``L``, not to the unrolled sequence. """ read, seq = _clean(read, construct.seq) L = len(seq) _check_length(L) if not construct.circular: - return replace(_align(read, seq), ref_length=L) + return replace(_align(read, seq)[0], ref_length=L) unrolled = seq + seq[: len(read) + CIRCULAR_MARGIN] - raw = _align(read, unrolled) + raw, alignments = _align(read, unrolled) + alternatives = _circular_alternatives(raw, alignments, L) if not raw.blocks: - return replace(raw, ref_length=L) + return replace(raw, ref_length=L, alternatives=alternatives) shift = (raw.blocks[0][0][0] // L) * L # make the alignment start in the first copy limit = raw.blocks[0][0][0] - shift + L @@ -270,6 +307,7 @@ def align_to_construct(read: str, construct: Construct) -> ReadAlignment: ref_to_read={p % L: q for p, q in ref_to_read.items()}, differences=[replace(d, ref_pos=d.ref_pos % L) for d in differences], identity=identity, + alternatives=alternatives, blocks=clipped, ref_length=L, ) diff --git a/tests/test_align_circular.py b/tests/test_align_circular.py index f7ba1e9..648aa1b 100644 --- a/tests/test_align_circular.py +++ b/tests/test_align_circular.py @@ -169,3 +169,22 @@ def test_limit_applies_to_original_length() -> None: align_to_construct(read, Construct("big", big + "A", True)) with pytest.raises(ValueError): align_to_construct(read, Construct("big", big + "A", False)) + + +def test_read_in_unrolled_prefix_is_not_ambiguous() -> None: + circle = _random_seq(1000, seed=21) + read = circle[10:210] # also present in the unrolled copy of the start + aln = align_to_construct(read, Construct("c", circle, True)) + assert (aln.ref_start, aln.ref_end) == (10, 210) + assert aln.alternatives == 1 + assert align_to_construct(read, Construct("c", circle, False)).alternatives == 1 + + +def test_genuine_repeat_in_circle_stays_ambiguous() -> None: + circle = list(_random_seq(1000, seed=23)) + repeat = _random_seq(100, seed=24) + circle[20:120] = repeat # inside the unrolled prefix as well + circle[600:700] = repeat + circle = "".join(circle) + aln = align_to_construct(repeat, Construct("c", circle, True)) + assert aln.alternatives == 2 From 6f4d061dc60eeb3376038541532300c9c3d7e168 Mon Sep 17 00:00:00 2001 From: Aleksey Drobin <43707931+adrobi@users.noreply.github.com> Date: Fri, 30 Oct 2026 02:01:46 +0300 Subject: [PATCH 11/44] clones: group reads into clones by file name Co-Authored-By: Claude Sonnet 5.5 --- chrom_core/clones.py | 139 +++++++++++++++++++++++++++++++++++++++++ chrom_core/config.py | 4 ++ tests/test_grouping.py | 101 ++++++++++++++++++++++++++++++ 3 files changed, 244 insertions(+) create mode 100644 chrom_core/clones.py create mode 100644 tests/test_grouping.py diff --git a/chrom_core/clones.py b/chrom_core/clones.py new file mode 100644 index 0000000..559441d --- /dev/null +++ b/chrom_core/clones.py @@ -0,0 +1,139 @@ +"""Clone verification: grouping reads into clones by file name.""" + +from __future__ import annotations + +import re +from dataclasses import dataclass, field +from pathlib import Path +from typing import Iterable + +DEFAULT_PRIMER_TOKENS = ( + "F", "R", "FW", "FWD", "REV", "RV", "T7", "T7TERM", "SP6", "T3", + "M13F", "M13R", "M13", "PUC-F", "PUC-R", "BGH", "CMV", +) + +_SEP = r"[_\-. ]" +_TOKEN_RE = re.compile(r"[^_\-. ]+") +_WELL_RE = re.compile(r"[A-H]\d{1,2}") +_MAX_PRIMER_PARTS = 3 # "pUC-F" spans two tokens + + +def _norm(text: str) -> str: + return re.sub(f"{_SEP}+", "-", text).upper() + + +@dataclass(frozen=True) +class ReadRef: + path: Path + clone: str + primer: str + + +def _natural_key(text: str) -> list: + return [ + (0, int(part), "") if part.isdigit() else (1, 0, part.casefold()) + for part in re.split(r"(\d+)", text) + if part != "" + ] + + +@dataclass +class Grouping: + reads: list[ReadRef] = field(default_factory=list) + unassigned: list[Path] = field(default_factory=list) + + def clones(self) -> dict[str, list[ReadRef]]: + out: dict[str, list[ReadRef]] = {} + for ref in self.reads: + out.setdefault(ref.clone, []).append(ref) + return {k: out[k] for k in sorted(out, key=_natural_key)} + + def assign(self, path: Path, clone: str, primer: str) -> None: + """Put ``path`` into ``clone`` (moving it if already grouped or unassigned).""" + path = Path(path) + self.unassigned = [p for p in self.unassigned if p != path] + ref = ReadRef(path, clone, primer) + for i, old in enumerate(self.reads): + if old.path == path: + self.reads[i] = ref + return + self.reads.append(ref) + + def to_dict(self) -> dict: + return { + "reads": [ + {"path": str(r.path), "clone": r.clone, "primer": r.primer} + for r in self.reads + ], + "unassigned": [str(p) for p in self.unassigned], + } + + @classmethod + def from_dict(cls, d: dict) -> "Grouping": + return cls( + reads=[ + ReadRef(Path(r["path"]), r["clone"], r["primer"]) + for r in d.get("reads", []) + ], + unassigned=[Path(p) for p in d.get("unassigned", [])], + ) + + +def parse_name( + stem: str, primer_tokens: Iterable[str] = DEFAULT_PRIMER_TOKENS +) -> tuple[str, str] | None: + """Split a file stem into ``(clone, primer)``; ``None`` if no clone remains.""" + tokens = list(_TOKEN_RE.finditer(stem)) + if not tokens: + return None + known = {_norm(t) for t in primer_tokens} + best: tuple[int, int] | None = None # (start, end) in ``stem`` + for i in range(len(tokens)): + for j in range(i, min(i + _MAX_PRIMER_PARTS, len(tokens))): + start, end = tokens[i].start(), tokens[j].end() + if _norm(stem[start:end]) not in known: + continue + # the last match wins; on equal end the longer (earlier start) one + if best is None or end > best[1] or (end == best[1] and start < best[0]): + best = (start, end) + if best is None: + best = (tokens[-1].start(), tokens[-1].end()) + start, end = best + primer = stem[start:end] + clone = re.sub(f"{_SEP}+$", "", stem[:start]) + clone = re.sub(rf"(?:^|{_SEP})\d$", "", clone) # primer order number + clone = re.sub(f"{_SEP}+$", "", clone) + clone = re.sub(rf"^{_WELL_RE.pattern}(?:{_SEP}+|$)", "", clone) # plate well + clone = re.sub(f"^{_SEP}+", "", clone) + return (clone, primer) if clone else None + + +def group_reads( + paths: Iterable[Path], + pattern: str | None = None, + primer_tokens: Iterable[str] = DEFAULT_PRIMER_TOKENS, +) -> Grouping: + """Group reads into clones by file name (default rules or a custom regex).""" + rx = None + if pattern: + try: + rx = re.compile(pattern) + except re.error as exc: + raise ValueError(f"invalid grouping pattern: {exc}") from exc + if not {"clone", "primer"} <= set(rx.groupindex): + raise ValueError("grouping pattern needs named groups 'clone' and 'primer'") + tokens = tuple(primer_tokens) + grouping = Grouping() + for p in map(Path, paths): + if rx is not None: + m = rx.fullmatch(p.stem) + parsed = (m.group("clone") or "", m.group("primer") or "") if m else None + if parsed is not None and not parsed[0]: + parsed = None + else: + parsed = parse_name(p.stem, tokens) + if parsed is None: + grouping.unassigned.append(p) + else: + grouping.reads.append(ReadRef(p, parsed[0], parsed[1])) + return grouping diff --git a/chrom_core/config.py b/chrom_core/config.py index aada4a6..e79d1bb 100644 --- a/chrom_core/config.py +++ b/chrom_core/config.py @@ -7,6 +7,8 @@ from dataclasses import asdict, dataclass, field from pathlib import Path +from .clones import DEFAULT_PRIMER_TOKENS + @dataclass class AppConfig: @@ -17,6 +19,8 @@ class AppConfig: theme: str = "light" # "light" | "dark" language: str = "ru" # "ru" | "en" recent_files: list[str] = field(default_factory=list) + primer_tokens: list[str] = field(default_factory=lambda: list(DEFAULT_PRIMER_TOKENS)) + group_pattern: str = "" # regex with named groups clone/primer; "" = by file name def config_dir() -> Path: diff --git a/tests/test_grouping.py b/tests/test_grouping.py new file mode 100644 index 0000000..0f61230 --- /dev/null +++ b/tests/test_grouping.py @@ -0,0 +1,101 @@ +from pathlib import Path + +import pytest + +from chrom_core.clones import ( + DEFAULT_PRIMER_TOKENS, + Grouping, + ReadRef, + group_reads, + parse_name, +) +from chrom_core.config import AppConfig, load_config +from tests.clone_fixtures import REAL_READS + + +@pytest.mark.parametrize("stem,expected", [ + ("Achl_ACHLO006-09_1_F", ("Achl_ACHLO006-09", "F")), + ("Achl_ACHLO006-09_2_R", ("Achl_ACHLO006-09", "R")), + ("cl3_T7", ("cl3", "T7")), + ("cl3_T7_2", ("cl3", "T7")), # repeat sequencing + ("A05_K3-F", ("K3", "F")), + ("clone12.rev", ("clone12", "rev")), + ("клон 14_SP6", ("клон 14", "SP6")), + ("T7", None), +]) +def test_parse_name(stem, expected): + assert parse_name(stem) == expected + + +def test_parse_name_fallback_to_last_token_and_custom_tokens(): + assert parse_name("cl3_xyz") == ("cl3", "xyz") + assert parse_name("cl3_XYZ", ["xyz"]) == ("cl3", "XYZ") + assert parse_name("single") is None + + +def test_parse_name_multi_part_primer_token(): + assert parse_name("cl5_pUC-F") == ("cl5", "pUC-F") + + +def test_default_tokens_contents(): + assert "T7TERM" in DEFAULT_PRIMER_TOKENS and len(DEFAULT_PRIMER_TOKENS) == 17 + + +def test_group_real_reads_into_four_clones(): + g = group_reads(REAL_READS) + assert len(g.clones()) == 4 and all(len(v) == 2 for v in g.clones().values()) + assert g.unassigned == [] + + +def test_repeat_reads_both_kept(): + g = group_reads([Path("d/cl3_T7.ab1"), Path("d/cl3_T7_2.ab1")]) + assert [r.path.name for r in g.clones()["cl3"]] == ["cl3_T7.ab1", "cl3_T7_2.ab1"] + + +def test_custom_pattern_and_unassigned(): + g = group_reads( + [Path("S1-fw.ab1"), Path("S12-rv.ab1"), Path("junk.ab1")], + pattern=r"(?PS\d+)-(?P\w+)", + ) + assert list(g.clones()) == ["S1", "S12"] + assert g.clones()["S12"][0].primer == "rv" + assert g.unassigned == [Path("junk.ab1")] + + +def test_bad_regex_raises(): + with pytest.raises(ValueError): + group_reads([Path("a.ab1")], pattern="(unclosed") + with pytest.raises(ValueError): + group_reads([Path("a.ab1")], pattern=r"(\w+)") # no named groups + + +def test_no_clone_goes_to_unassigned(): + g = group_reads([Path("T7.ab1")]) + assert g.reads == [] and g.unassigned == [Path("T7.ab1")] + + +def test_natural_sort(): + paths = [Path(f"cl{n}_T7.ab1") for n in (10, 2, 1)] + assert list(group_reads(paths).clones()) == ["cl1", "cl2", "cl10"] + + +def test_grouping_roundtrip_and_manual_assign(): + g = group_reads([Path("cl1_T7.ab1"), Path("junk.ab1")]) + g.assign(Path("junk.ab1"), "cl1", "SP6") + g.assign(Path("cl1_T7.ab1"), "cl2", "T7") # reassign moves, never duplicates + assert g.unassigned == [] + assert [(r.clone, r.primer) for r in g.reads] == [("cl2", "T7"), ("cl1", "SP6")] + d = g.to_dict() + assert all(isinstance(r["path"], str) for r in d["reads"]) + assert Grouping.from_dict(d) == g + assert ReadRef(Path("a"), "c", "p") in Grouping.from_dict( + {"reads": [{"path": "a", "clone": "c", "primer": "p"}], "unassigned": []} + ).reads + + +def test_config_new_fields_and_old_files(tmp_path): + cfg = AppConfig() + assert cfg.primer_tokens == list(DEFAULT_PRIMER_TOKENS) and cfg.group_pattern == "" + f = tmp_path / "c.json" + f.write_text('{"theme": "dark"}', encoding="utf-8") + assert load_config(f).primer_tokens == list(DEFAULT_PRIMER_TOKENS) From 923ce4d8646d6e0b97257b5f544260e61be19849 Mon Sep 17 00:00:00 2001 From: Aleksey Drobin <43707931+adrobi@users.noreply.github.com> Date: Fri, 30 Oct 2026 02:02:17 +0300 Subject: [PATCH 12/44] clones: keep a lone well-shaped token as the clone name Co-Authored-By: Claude Sonnet 5.5 --- chrom_core/clones.py | 12 ++++++++++-- tests/test_grouping.py | 2 ++ 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/chrom_core/clones.py b/chrom_core/clones.py index 559441d..71bff5f 100644 --- a/chrom_core/clones.py +++ b/chrom_core/clones.py @@ -82,7 +82,14 @@ def from_dict(cls, d: dict) -> "Grouping": def parse_name( stem: str, primer_tokens: Iterable[str] = DEFAULT_PRIMER_TOKENS ) -> tuple[str, str] | None: - """Split a file stem into ``(clone, primer)``; ``None`` if no clone remains.""" + """Split a file stem into ``(clone, primer)``; ``None`` if no clone remains. + + The primer is the last dictionary token (else the last token). The clone is + the text before it, minus trailing separators, a lone digit (primer order) + and a leading plate well (``A05``) -- the well is stripped only when another + clone token follows it, so ``B2_F`` is clone ``B2``. Anything after the + primer (e.g. a repeat suffix ``_2``) is ignored. + """ tokens = list(_TOKEN_RE.finditer(stem)) if not tokens: return None @@ -103,7 +110,8 @@ def parse_name( clone = re.sub(f"{_SEP}+$", "", stem[:start]) clone = re.sub(rf"(?:^|{_SEP})\d$", "", clone) # primer order number clone = re.sub(f"{_SEP}+$", "", clone) - clone = re.sub(rf"^{_WELL_RE.pattern}(?:{_SEP}+|$)", "", clone) # plate well + # leading plate well, only if another clone token follows it + clone = re.sub(rf"^{_WELL_RE.pattern}{_SEP}+(?=[^_\-. ])", "", clone) clone = re.sub(f"^{_SEP}+", "", clone) return (clone, primer) if clone else None diff --git a/tests/test_grouping.py b/tests/test_grouping.py index 0f61230..9a56421 100644 --- a/tests/test_grouping.py +++ b/tests/test_grouping.py @@ -21,6 +21,8 @@ ("A05_K3-F", ("K3", "F")), ("clone12.rev", ("clone12", "rev")), ("клон 14_SP6", ("клон 14", "SP6")), + ("B2_F", ("B2", "F")), # lone well-shaped token is the clone + ("A1_F", ("A1", "F")), ("T7", None), ]) def test_parse_name(stem, expected): From ced205777679c447c40d41f1ae3b951252b704fe Mon Sep 17 00:00:00 2001 From: Aleksey Drobin <43707931+adrobi@users.noreply.github.com> Date: Fri, 30 Oct 2026 02:16:50 +0300 Subject: [PATCH 13/44] clones: per-clone coverage, merged differences and verdicts verify_clone/verify_all with VerifyParams, ReadResult, CloneDifference and CloneReport; reads are quality-trimmed before alignment and mapped back to full displayed indices. load_read (session-aware) replaces batch._edited_read. Also fixes EditableRead.reverse_complement mapping peaks against the last peak instead of the trace length, which misplaced every peak of a flipped read relative to its flipped traces. Co-Authored-By: Claude Opus 5.5 --- chrom_core/batch.py | 16 +- chrom_core/clones.py | 337 ++++++++++++++++++++++++++++++++- chrom_core/editing.py | 6 +- tests/clone_fixtures.py | 103 +++++++++- tests/test_clone_verify.py | 373 +++++++++++++++++++++++++++++++++++++ tests/test_editing.py | 6 +- 6 files changed, 819 insertions(+), 22 deletions(-) create mode 100644 tests/test_clone_verify.py diff --git a/chrom_core/batch.py b/chrom_core/batch.py index b047192..30a5dec 100644 --- a/chrom_core/batch.py +++ b/chrom_core/batch.py @@ -6,7 +6,7 @@ from pathlib import Path from chrom_core import read_ab1, trim_window -from chrom_core import sessions +from chrom_core.clones import load_read from chrom_core.editing import EditableRead from chrom_core.export import to_fasta, to_fastq, write_text @@ -72,18 +72,6 @@ def scan_folder(folder: str | Path, window: int = 20, min_q: int = 20) -> list[F return reports -def _edited_read(path: Path) -> EditableRead: - """Parse a file and apply its editing session sidecar when present.""" - model = EditableRead(read_ab1(path)) - data = sessions.load_session(sessions.session_path(path)) - if data and data.get("source") == path.name: - try: - model.restore_state(data) - except (KeyError, TypeError, ValueError): - pass - return model - - def batch_export( reports: list[FileReport], out_dir: str | Path, @@ -102,7 +90,7 @@ def batch_export( dest: Path | None = None error = "" try: - model = _edited_read(report.path) + model = EditableRead(load_read(report.path)) start, end = trim_window(model.quality, window=window, min_q=min_q) if end - start >= 2: model.apply_trim(start, end) diff --git a/chrom_core/clones.py b/chrom_core/clones.py index 71bff5f..e258556 100644 --- a/chrom_core/clones.py +++ b/chrom_core/clones.py @@ -1,12 +1,22 @@ -"""Clone verification: grouping reads into clones by file name.""" +"""Clone verification: grouping reads into clones, per-clone checks and verdicts.""" from __future__ import annotations import re -from dataclasses import dataclass, field +from concurrent.futures import CancelledError +from dataclasses import dataclass, field, replace from pathlib import Path from typing import Iterable +from chrom_core import sessions +from chrom_core.abif import Chromatogram, read_ab1 +from chrom_core.align import Difference, ReadAlignment, align_to_construct +from chrom_core.editing import EditableRead +from chrom_core.peaks import scan_secondary_peaks +from chrom_core.reference import Construct +from chrom_core.seqops import iupac_compatible, reverse_complement +from chrom_core.trim import trim_window + DEFAULT_PRIMER_TOKENS = ( "F", "R", "FW", "FWD", "REV", "RV", "T7", "T7TERM", "SP6", "T3", "M13F", "M13R", "M13", "PUC-F", "PUC-R", "BGH", "CMV", @@ -145,3 +155,326 @@ def group_reads( else: grouping.reads.append(ReadRef(p, parsed[0], parsed[1])) return grouping + + +# ------------------------------------------------------------------ verification + +MIN_ALIGNED_BP = 50 # a read counts as aligned only past both thresholds +MIN_IDENTITY = 0.80 +TRIM_WINDOW = 20 # quality trimming before alignment (sliding window) + +Region = tuple[int, int] # 0-based half-open; start > end wraps the origin (circular only) + + +@dataclass(frozen=True) +class VerifyParams: + min_q: int = 20 + het_ratio: float = 0.40 + mixed_min_positions: int = 3 + + +@dataclass(frozen=True) +class ReadResult: + ref: ReadRef + alignment: ReadAlignment | None # None when ``error`` is set + error: str = "" # "no_alignment" or why the file could not be used + ambiguous: bool = False # alternatives > 1: excluded from the verdict + + +@dataclass(frozen=True) +class CloneDifference: + ref_pos: int + kind: str # 'substitution' | 'deletion' | 'insertion' (before ref_pos) + ref_base: str + read_base: str + support: int # reads showing it with Q >= min_q + against: int # reads showing the reference there with Q >= min_q + low_quality: int # reads showing it with Q < min_q + status: str # 'confirmed' | 'disputed' | 'low_quality' + in_region: bool + effect: str = "" + + +@dataclass(frozen=True) +class CloneReport: + clone: str + reads: tuple[ReadResult, ...] + coverage: dict[int, tuple[int, int]] # region position -> (reads on +, reads on -) + differences: tuple[CloneDifference, ...] + mixed_positions: tuple[int, ...] + verdict: str # 'no_data' | 'mixed' | 'errors' | 'incomplete' | 'ok' + + def _pct(self, test) -> float: + if not self.coverage: + return 0.0 + hits = sum(1 for v in self.coverage.values() if test(v)) + return 100.0 * hits / len(self.coverage) + + @property + def region_coverage_pct(self) -> float: + return self._pct(lambda v: v[0] + v[1] > 0) + + @property + def both_strands_pct(self) -> float: + return self._pct(lambda v: v[0] > 0 and v[1] > 0) + + @property + def region_differences(self) -> tuple[CloneDifference, ...]: + return tuple(d for d in self.differences if d.in_region) + + +def _check_region(region: Region | None, length: int, circular: bool) -> Region: + if region is None: + return (0, length) + start, end = region + if not (0 <= start < length and 0 <= end <= length): + raise ValueError(f"region {start}..{end} lies outside the construct (0..{length})") + if start == end: + raise ValueError("empty region") + if start > end and not circular: + raise ValueError("a region across the origin needs a circular construct") + return (start, end) + + +def region_positions(region: Region | None, length: int) -> list[int]: + """Construct positions of ``region`` in order (``None``: the whole construct).""" + start, end = _check_region(region, length, circular=True) + if start < end: + return list(range(start, end)) + return list(range(start, length)) + list(range(end)) + + +def _load(path: Path) -> tuple[Chromatogram, bool]: + """Current chromatogram (editing session applied) and its reversed flag.""" + path = Path(path) + model = EditableRead(read_ab1(path)) + data = sessions.load_session(sessions.session_path(path)) + if data and data.get("source") == path.name: + try: + model.restore_state(data) + except (KeyError, TypeError, ValueError): + pass + return model.current(), model.reversed_complement + + +def load_read(path: Path) -> Chromatogram: + """Parse a read and apply its editing session sidecar when present.""" + return _load(path)[0] + + +def _align_trimmed(chrom: Chromatogram, construct: Construct, min_q: int) -> ReadAlignment: + """Align the quality-trimmed read; indices refer to the full displayed read. + + Trimming keeps low-quality overhangs from wrapping around a circle. A read + without a usable window (e.g. no quality values at all) is aligned whole. + """ + n = len(chrom.seq) + start, end = trim_window(chrom.quality, window=TRIM_WINDOW, min_q=min_q) + if end - start < 2: + start, end = 0, n + al = align_to_construct(chrom.seq[start:end], construct) + if (start, end) == (0, n): + return al + off = start if al.strand == "+" else n - end + return replace( + al, + read_start=al.read_start + off, + read_end=al.read_end + off, + ref_to_read={p: i + off for p, i in al.ref_to_read.items()}, + differences=[ + d if d.read_pos is None else replace(d, read_pos=d.read_pos + off) + for d in al.differences + ], + oriented_read=chrom.seq.upper() if al.strand == "+" + else reverse_complement(chrom.seq.upper()), + blocks=[(t, (q0 + off, q1 + off)) for t, (q0, q1) in al.blocks], + ) + + +class _Read: + """An aligned read used for the verdict: quality lookups at reference sites.""" + + def __init__(self, chrom: Chromatogram, al: ReadAlignment, strand: str, circular: bool): + self.chrom, self.al, self.circular = chrom, al, circular + self.strand = strand # physical strand: a reverse-complemented display is undone + self.map = al.ref_to_read + + def q(self, idx: int) -> int: + n = len(self.chrom.seq) + d = idx if self.al.strand == "+" else n - 1 - idx + return self.chrom.quality[d] if 0 <= d < n else 0 + + def _mapped_from(self, pos: int, step: int) -> int | None: + """Read index of the nearest mapped position beyond ``pos`` towards ``step``.""" + p = pos + for _ in range(self.al.ref_length): + p += step + if self.circular: + p %= self.al.ref_length + if not self.al.covers(p): + return None + if p in self.map: + return self.map[p] + return None + + def gap_q(self, pos: int) -> int: + """Q of the read bases flanking a deleted position or an insertion point.""" + left = self._mapped_from(pos, -1) + right = self.map[pos] if pos in self.map else self._mapped_from(pos, +1) + if left is None or right is None: + return 0 + return min(self.q(left), self.q(right)) + + def site_q(self, pos: int) -> int | None: + """Q at a reference position (flanks if deleted); None if not covered.""" + if not self.al.covers(pos): + return None + return self.q(self.map[pos]) if pos in self.map else self.gap_q(pos) + + def difference_q(self, d: Difference) -> int: + return self.q(d.read_pos) if d.kind == "substitution" else self.gap_q(d.ref_pos) + + def shows_reference(self, d: Difference, ref: str, min_q: int) -> bool: + m, pos = self.map, d.ref_pos + if d.kind == "insertion": + prev = (pos - 1) % len(ref) + return (prev in m and pos in m and m[pos] == m[prev] + 1 + and min(self.q(m[prev]), self.q(m[pos])) >= min_q) + return (pos in m and self.al.oriented_read[m[pos]] == ref[pos] + and self.q(m[pos]) >= min_q) + + +def _informative(d: Difference) -> bool: + """N/IUPAC in the reference is never a difference; an ambiguous read call + compatible with the reference base (e.g. N) is a no-call, not a difference.""" + if d.kind != "insertion" and d.ref_base not in "ACGT": + return False + if d.kind == "substitution" and d.read_base not in "ACGT": + return not iupac_compatible(d.read_base, d.ref_base) + return True + + +def _status(support: int, against: int) -> str: + if support == 0: + return "low_quality" + return "disputed" if against else "confirmed" + + +def _verdict(used, mixed, differences, coverage, params: VerifyParams) -> str: + if not used: + return "no_data" + if len(mixed) >= params.mixed_min_positions: + return "mixed" + if any(d.in_region and d.status != "low_quality" for d in differences): + return "errors" + if any(plus + minus == 0 for plus, minus in coverage.values()): + return "incomplete" + return "ok" + + +def verify_clone( + construct: Construct, + region: Region | None, + reads: list[ReadRef], + params: VerifyParams = VerifyParams(), + annotate=None, +) -> CloneReport: + """Check one colony's reads against ``construct`` within ``region``. + + ``annotate(construct, difference) -> str`` fills ``CloneDifference.effect``. + """ + L = len(construct.seq) + positions = region_positions(_check_region(region, L, construct.circular), L) + in_region = set(positions) + ref = construct.seq.upper() + + results: list[ReadResult] = [] + used: list[_Read] = [] + for read_ref in reads: + try: + chrom, flipped = _load(read_ref.path) + al = _align_trimmed(chrom, construct, params.min_q) + except Exception as exc: # unreadable / unalignable file: mark it, go on + results.append(ReadResult(read_ref, None, error=str(exc) or type(exc).__name__)) + continue + if al.covered < MIN_ALIGNED_BP or al.identity < MIN_IDENTITY: + results.append(ReadResult(read_ref, None, error="no_alignment")) + continue + ambiguous = al.alternatives > 1 + results.append(ReadResult(read_ref, al, ambiguous=ambiguous)) + if not ambiguous: + strand = al.strand if not flipped else {"+": "-", "-": "+"}[al.strand] + used.append(_Read(chrom, al, strand, construct.circular)) + + coverage: dict[int, tuple[int, int]] = {} + for pos in positions: + good = [r.strand for r in used + if r.al.covers(pos) and r.site_q(pos) >= params.min_q] + coverage[pos] = (good.count("+"), good.count("-")) + + # merge per (position, kind, read base): reads showing it, with their Q + found: dict[tuple, tuple[Difference, list[_Read], list[int]]] = {} + for r in used: + for d in r.al.differences: + if _informative(d): + entry = found.setdefault((d.ref_pos, d.kind, d.read_base), (d, [], [])) + entry[1].append(r) + entry[2].append(r.difference_q(d)) + + differences = [] + for key in sorted(found): + d, showing, quals = found[key] + support = sum(1 for q in quals if q >= params.min_q) + against = sum(1 for r in used + if r not in showing and r.shows_reference(d, ref, params.min_q)) + inside = d.ref_pos in in_region or ( + d.kind == "insertion" and (d.ref_pos - 1) % L in in_region) + cd = CloneDifference( + d.ref_pos, d.kind, d.ref_base, d.read_base, support, against, + len(quals) - support, _status(support, against), inside, + ) + if annotate is not None: + cd = replace(cd, effect=annotate(construct, cd) or "") + differences.append(cd) + + mixed = tuple(sorted({ + pos + for r in used + for pos, _ in scan_secondary_peaks(r.chrom, r.al, params.het_ratio, params.min_q) + if pos in in_region + })) + + return CloneReport( + clone=reads[0].clone if reads else "", + reads=tuple(results), + coverage=coverage, + differences=tuple(differences), + mixed_positions=mixed, + verdict=_verdict(used, mixed, differences, coverage, params), + ) + + +def verify_all( + construct: Construct, + region: Region | None, + grouping: Grouping, + params: VerifyParams = VerifyParams(), + progress=None, + cancelled=None, +) -> list[CloneReport]: + """``verify_clone`` for every clone of ``grouping``, in natural name order. + + ``progress(done, total)`` is called after each clone; ``cancelled()`` is + polled before each one and, when true, raises + ``concurrent.futures.CancelledError``. + """ + _check_region(region, len(construct.seq), construct.circular) + groups = grouping.clones() + reports = [] + for done, reads in enumerate(groups.values(), start=1): + if cancelled is not None and cancelled(): + raise CancelledError() + reports.append(verify_clone(construct, region, reads, params)) + if progress is not None: + progress(done, len(groups)) + return reports diff --git a/chrom_core/editing.py b/chrom_core/editing.py index fff1162..4fcd81e 100644 --- a/chrom_core/editing.py +++ b/chrom_core/editing.py @@ -120,9 +120,9 @@ def reverse_complement(self) -> None: n = len(self.seq) self.seq = list(reverse_complement("".join(self.seq))) self.quality.reverse() - if self.peaks: - last = self.peaks[-1] - self.peaks = [last - p for p in reversed(self.peaks)] + # current() reverses the traces over their full length: map peaks the same way + last = len(next(iter(self.original.traces.values()))) - 1 + self.peaks = [last - p for p in reversed(self.peaks)] self.edited = {n - 1 - k: v for k, v in self.edited.items()} self.reversed_complement = not self.reversed_complement diff --git a/tests/clone_fixtures.py b/tests/clone_fixtures.py index d2ea9d9..30dad17 100644 --- a/tests/clone_fixtures.py +++ b/tests/clone_fixtures.py @@ -2,12 +2,17 @@ from __future__ import annotations +import shutil +import struct +from dataclasses import replace +from functools import cache from pathlib import Path from Bio import SeqIO -from chrom_core import read_ab1 -from chrom_core.abif import Chromatogram +from chrom_core import read_ab1, sessions +from chrom_core.abif import DEFAULT_DYE_ORDER, Chromatogram +from chrom_core.peaks import channel_baseline, peak_window from chrom_core.seqops import IUPAC DATA = Path(__file__).resolve().parent / "data" @@ -83,3 +88,97 @@ def make_chrom( traces={b: tuple(t) for b, t in traces.items()}, peak_indices=tuple(peaks), ) + + +# ---------------------------------------------------------------- semi-synthetic + + +def mutate(seq: str, pos: int, kind: str, base: str = "") -> str: + """``seq`` with a substitution / insertion (before ``pos``) / deletion at ``pos``.""" + if kind == "sub": + return seq[:pos] + base + seq[pos + 1:] + if kind == "ins": + return seq[:pos] + base + seq[pos:] + if kind == "del": + return seq[:pos] + seq[pos + 1:] + raise ValueError(kind) + + +def with_secondary_peak(chrom: Chromatogram, index: int, base: str, ratio: float) -> Chromatogram: + """Add a second peak in channel ``base`` under called base ``index``. + + The called peak's shape is copied into ``base`` (so it is a real local + maximum, as ``peaks`` measures it), scaled so the *dye-normalised* + secondary/primary ratio is ``ratio``. + """ + called = chrom.seq[index].upper() + baseline = channel_baseline(chrom, index) + scale = ratio * baseline[base] / baseline[called] + centre = chrom.peak_indices[index] + window = peak_window(chrom, index) + source = chrom.traces[called] + trace = list(chrom.traces[base]) + for k in range(max(0, centre - window + 1), min(len(trace), centre + window)): + trace[k] = max(trace[k], round(source[k] * scale)) + traces = dict(chrom.traces) + traces[base] = tuple(trace) + return replace(chrom, traces=traces) + + +@cache +def _source_by_sample_id() -> dict[str, Path]: + return {read_ab1(p).sample_id: p for p in REAL_READS} + +_DYE_OF = {base: tag for tag, base in DEFAULT_DYE_ORDER.items()} +_RC_CHANNEL = {"A": "T", "T": "A", "C": "G", "G": "C"} + + +def _flip(traces: dict[str, tuple[int, ...]]) -> dict[str, tuple[int, ...]]: + """Display traces of a reverse-complemented read <-> file traces.""" + return {b: tuple(reversed(traces[_RC_CHANNEL[b]])) for b in traces} + + +def _mismatches(a: dict, b: dict) -> int: + return sum(x != y for base in a for x, y in zip(a[base], b[base])) + + +def _patch_traces(path: Path, traces: dict[str, tuple[int, ...]]) -> None: + """Overwrite the DATA9-12 dye channels of an ABIF file in place (same lengths).""" + data = bytearray(path.read_bytes()) + _, _, _, _, count, _, offset = struct.unpack(">4siHHiii", data[6:30]) + wanted = {_DYE_OF[b]: values for b, values in traces.items()} + for e in range(count): + entry = offset + 28 * e + name, number, _, _, n, _, where = struct.unpack(">4siHHiii", data[entry:entry + 24]) + tag = f"{name.decode('latin-1')}{number}" + if tag in wanted: + assert n == len(wanted[tag]), "trace length must not change" + data[where:where + 2 * n] = struct.pack(f">{n}h", *wanted[tag]) + path.write_bytes(bytes(data)) + + +def write_read(chrom: Chromatogram, folder: Path, name: str) -> Path: + """Save a modified real read as ``folder/name`` + editing session. + + The source ``.ab1`` (found by sample id) is copied; the called bases, + quality and peak positions go to the session sidecar, so ``load_read`` + returns ``chrom``. A reverse-complemented display is detected from the + traces; traces changed by ``with_secondary_peak`` are written into the copy. + """ + source = _source_by_sample_id()[chrom.sample_id] + path = Path(folder) / (name if name.lower().endswith(".ab1") else name + ".ab1") + shutil.copyfile(source, path) + original = read_ab1(source).traces + flipped = _mismatches(_flip(chrom.traces), original) < _mismatches(chrom.traces, original) + file_traces = _flip(chrom.traces) if flipped else dict(chrom.traces) + if file_traces != original: + _patch_traces(path, file_traces) + sessions.save_session(sessions.session_path(path), { + "source": path.name, + "seq": chrom.seq, + "quality": list(chrom.quality), + "peaks": list(chrom.peak_indices), + "edited": [], + "reversed_complement": flipped, + }) + return path diff --git a/tests/test_clone_verify.py b/tests/test_clone_verify.py new file mode 100644 index 0000000..13453b9 --- /dev/null +++ b/tests/test_clone_verify.py @@ -0,0 +1,373 @@ +"""Per-clone verification: coverage, merged differences and verdicts. + +The base clone is the real pair ``Achl_ACHLO006-09`` F+R against its own COI +reference (HM417896, 658 bp). Errors are introduced into the *reference* +(``mutate``), so the unmodified reads report them, or into a read through an +editing session (``write_read``), which is how a user's edits reach the check. +""" + +from __future__ import annotations + +import random +import time +from concurrent.futures import CancelledError +from dataclasses import replace + +import pytest + +from chrom_core import clones +from chrom_core.clones import ( + MIN_IDENTITY, + CloneReport, + VerifyParams, + load_read, + region_positions, + verify_all, + verify_clone, +) +from chrom_core.align import align_to_construct +from chrom_core.clones import Grouping, ReadRef +from chrom_core.editing import EditableRead +from chrom_core.peaks import secondary_peak +from chrom_core.reference import Construct, load_construct +from clone_fixtures import ( + DATA, + PUC19_GB, + coi_reference, + mutate, + real_read, + with_secondary_peak, + write_read, +) + +F_NAME = "Achl_ACHLO006-09_1_F.ab1" +R_NAME = "Achl_ACHLO006-09_2_R.ab1" +F_PATH = DATA / "real" / F_NAME +R_PATH = DATA / "real" / R_NAME +# The part of COI covered by both trimmed reads: F aligns 6..658, R 0..647. +REGION = (6, 647) +P = 250 # inside the region; context AAC[A]TGA, no homopolymer +OUTSIDE = 652 # covered by F only, outside the region + + +@pytest.fixture(scope="module") +def coi() -> str: + return coi_reference() + + +def _reads(f=F_PATH, r=R_PATH) -> list[ReadRef]: + out = [] + if f is not None: + out.append(ReadRef(f, "c1", "F")) + if r is not None: + out.append(ReadRef(r, "c1", "R")) + return out + + +def _construct(seq: str, circular: bool = False) -> Construct: + return Construct("c", seq, circular) + + +def _f_index(coi: str, ref_pos: int) -> int: + """Displayed index in the F read of reference position ``ref_pos``.""" + al = align_to_construct(real_read(F_NAME).seq, _construct(coi)) + assert al.strand == "+" + return al.ref_to_read[ref_pos] + + +def test_ok_clone(coi): + report = verify_clone(_construct(coi), REGION, _reads()) + assert report.verdict == "ok" and report.region_differences == () + assert report.region_coverage_pct == 100.0 + assert 0 < report.both_strands_pct <= 100.0 + assert set(report.coverage) == set(range(*REGION)) + assert all(r.error == "" and not r.ambiguous for r in report.reads) + + +def test_substitution_found_with_support(coi): + ref = mutate(coi, P, "sub", "G") + r = verify_clone(_construct(ref), REGION, _reads()) + d, = r.region_differences + assert (d.ref_pos, d.kind, d.status, d.support, d.against) == (P, "substitution", "confirmed", 2, 0) + assert (d.ref_base, d.read_base, d.in_region) == ("G", "A", True) + assert r.verdict == "errors" + + +def test_insertion_and_deletion_found(coi): + # base missing from the reference -> the reads show an insertion + r = verify_clone(_construct(mutate(coi, P, "del")), REGION, _reads()) + d, = r.region_differences + assert (d.ref_pos, d.kind, d.read_base, d.status, d.support) == (P, "insertion", "A", "confirmed", 2) + assert r.verdict == "errors" + # extra base in the reference -> the reads show a deletion + r = verify_clone(_construct(mutate(coi, P, "ins", "G")), REGION, _reads()) + d, = r.region_differences + assert (d.ref_pos, d.kind, d.ref_base, d.status, d.support) == (P, "deletion", "G", "confirmed", 2) + assert r.verdict == "errors" + + +def test_disputed_when_reads_disagree(coi, tmp_path): + # A C peak 4x the called A under P, then the call edited to C: the trace + # agrees with the edit (no artificial double peak at P). + i = _f_index(coi, P) + model = EditableRead(with_secondary_peak(real_read(F_NAME), i, "C", 4.0)) + model.set_base(i, "C") + assert secondary_peak(model.current(), i).ratio < VerifyParams().het_ratio + f = write_read(model.current(), tmp_path, F_NAME) + r = verify_clone(_construct(coi), REGION, _reads(f=f)) + d, = r.region_differences + assert (d.ref_pos, d.kind, d.read_base, d.support, d.against, d.status) == ( + P, "substitution", "C", 1, 1, "disputed") + assert r.verdict == "errors" + + +def test_outside_region_does_not_affect_verdict(coi): + r = verify_clone(_construct(mutate(coi, OUTSIDE, "sub", "A")), REGION, _reads()) + assert r.verdict == "ok" and r.region_differences == () + d, = r.differences + assert (d.ref_pos, d.in_region, d.status) == (OUTSIDE, False, "confirmed") + + +def test_incomplete_when_read_trimmed(coi, tmp_path): + model = EditableRead(real_read(F_NAME)) + model.apply_trim(100, 400) + f = write_read(model.current(), tmp_path, F_NAME) + r = verify_clone(_construct(coi), REGION, _reads(f=f, r=None)) + assert r.verdict == "incomplete" + assert r.region_coverage_pct < 100 + assert r.both_strands_pct == 0.0 + + +def _mixed_read(coi, tmp_path, ratio: float, positions) -> object: + chrom = real_read(F_NAME) + for pos in positions: + i = _f_index(coi, pos) + other = next(b for b in "ACGT" if b != chrom.seq[i]) + chrom = with_secondary_peak(chrom, i, other, ratio) + assert secondary_peak(chrom, i).ratio == pytest.approx(ratio, abs=0.05) + return write_read(chrom, tmp_path, F_NAME) + + +MIXED_AT = (200, 300, 400) + + +def test_mixed_50_percent_flagged(coi, tmp_path): + # The real R read itself has two second peaks in the region (595, 596): + # below the 3-position threshold, so the unmodified clone stays "ok". + baseline = verify_clone(_construct(coi), REGION, _reads()).mixed_positions + assert len(baseline) < VerifyParams().mixed_min_positions + f = _mixed_read(coi, tmp_path, 0.5, MIXED_AT) + r = verify_clone(_construct(coi), REGION, _reads(f=f)) + assert r.verdict == "mixed" + added = tuple(p for p in r.mixed_positions if p not in baseline) + assert added == MIXED_AT and len(added) == 3 + + +def test_mixed_50_percent_single_read_counts_exactly(coi, tmp_path): + f = _mixed_read(coi, tmp_path, 0.5, MIXED_AT) + r = verify_clone(_construct(coi), REGION, _reads(f=f, r=None)) + assert r.verdict == "mixed" and r.mixed_positions == MIXED_AT + + +def test_mixed_30_percent_not_flagged(coi, tmp_path): + f = _mixed_read(coi, tmp_path, 0.3, MIXED_AT) + r = verify_clone(_construct(coi), REGION, _reads(f=f)) + assert r.verdict == "ok" + assert not set(MIXED_AT) & set(r.mixed_positions) + + +def test_no_data_for_foreign_read(): + puc19 = load_construct(PUC19_GB) + raw = align_to_construct(real_read(F_NAME).seq, puc19) + assert raw.identity < MIN_IDENTITY or raw.covered < clones.MIN_ALIGNED_BP + r = verify_clone(puc19, None, [ReadRef(F_PATH, "c1", "F")]) + assert r.verdict == "no_data" + res, = r.reads + assert (res.error, res.alignment) == ("no_alignment", None) + + +def test_reverse_complemented_session_same_result(coi, tmp_path): + construct = _construct(mutate(coi, P, "sub", "G")) + plain = verify_clone(construct, REGION, _reads()) + paths = [] + for path, name in ((F_PATH, F_NAME), (R_PATH, R_NAME)): + model = EditableRead(real_read(name)) + model.reverse_complement() + paths.append(write_read(model.current(), tmp_path, name)) + flipped = verify_clone(construct, REGION, _reads(*paths)) + assert flipped.verdict == plain.verdict == "errors" + assert flipped.differences == plain.differences + assert flipped.coverage == plain.coverage # strands are physical, not displayed + assert flipped.mixed_positions == plain.mixed_positions + assert [r.alignment.strand for r in flipped.reads] == ["-", "+"] + + +def test_region_across_origin(coi, tmp_path): + # COI + a random spacer, so the circle is longer than a read; rotated so + # the origin falls inside COI and the region wraps it. The reads are cut + # to their COI part: their real flanks would align to the random spacer + # as noise. + paths = [] + for name in (F_NAME, R_NAME): + model = EditableRead(real_read(name)) + model.apply_trim(40, 640) + paths.append(write_read(model.current(), tmp_path, name)) + rng = random.Random(2) + plasmid = mutate(coi, P, "sub", "G") + "".join(rng.choice("ACGT") for _ in range(400)) + L, k = len(plasmid), 300 + rotated = plasmid[k:] + plasmid[:k] + region = ((REGION[0] - k) % L, (REGION[1] - k) % L) + assert region[0] > region[1] + linear = verify_clone(_construct(plasmid), REGION, _reads(*paths)) + circ = verify_clone(_construct(rotated, circular=True), region, _reads(*paths)) + assert all(x.alignment.wraps and not x.ambiguous for x in circ.reads) + assert circ.verdict == linear.verdict == "errors" + assert [replace(d, ref_pos=(d.ref_pos + k) % L) for d in circ.differences] == list( + linear.differences) + assert circ.region_differences[0].ref_pos == (P - k) % L + assert circ.region_coverage_pct == linear.region_coverage_pct > 90.0 + assert circ.both_strands_pct == linear.both_strands_pct > 50.0 + assert {(p + k) % L: v for p, v in circ.coverage.items()} == linear.coverage + + +def test_region_positions(): + assert region_positions((2, 5), 10) == [2, 3, 4] + assert region_positions((8, 2), 10) == [8, 9, 0, 1] + assert region_positions(None, 4) == [0, 1, 2, 3] + + +def test_read_without_quality_is_incomplete_not_errors(coi, tmp_path): + model = EditableRead(real_read(F_NAME)) + model.apply_trim(20, 680) # drop the noisy ends: no quality, no trimming + chrom = model.current() + chrom = replace(chrom, quality=(0,) * len(chrom.seq)) + f = write_read(chrom, tmp_path, F_NAME) + r = verify_clone(_construct(mutate(coi, P, "sub", "G")), REGION, _reads(f=f, r=None)) + assert r.verdict == "incomplete" + assert r.region_coverage_pct == 0.0 + d, = r.region_differences + assert (d.ref_pos, d.status, d.support, d.low_quality) == (P, "low_quality", 0, 1) + + +def test_reference_N_is_not_a_difference(coi): + ref = mutate(coi, P, "sub", "N") + ref = mutate(ref, P + 10, "sub", "R") # IUPAC too (coi[260] is compatible or not, never counted) + r = verify_clone(_construct(ref), REGION, _reads()) + assert r.verdict == "ok" and r.differences == () + + +def test_unreadable_file_marked_not_fatal(coi, tmp_path): + broken = tmp_path / "c1_X.ab1" + broken.write_bytes(b"definitely not an ABIF file") + reads = _reads() + [ReadRef(broken, "c1", "X")] + r = verify_clone(_construct(coi), REGION, reads) + assert r.verdict == "ok" + bad = r.reads[-1] + assert bad.error and bad.error != "no_alignment" and bad.alignment is None + assert all(x.alignment is not None for x in r.reads[:2]) + + +def test_ambiguous_read_excluded(coi, tmp_path): + # reads trimmed well inside COI: no overhang can favour one of the copies + paths = [] + for name in (F_NAME, R_NAME): + model = EditableRead(real_read(name)) + model.apply_trim(100, 500) + paths.append(write_read(model.current(), tmp_path, name)) + r = verify_clone(_construct(coi + coi), None, _reads(*paths)) + assert all(x.ambiguous for x in r.reads) + assert r.verdict == "no_data" + assert all(v == (0, 0) for v in r.coverage.values()) + + +@pytest.mark.xfail(strict=True, reason=( + "alternatives counts co-optimal gap placements, so an indel in a homopolymer " + "marks every read ambiguous and the clone becomes no_data (see task-7 report)")) +def test_homopolymer_deletion_is_an_error_not_no_data(coi): + r = verify_clone(_construct(mutate(coi, 200, "ins", "T")), REGION, _reads()) # TTTT -> TTTTT + assert r.verdict == "errors" + assert [(d.kind, d.status) for d in r.region_differences] == [("deletion", "confirmed")] + + +@pytest.mark.parametrize("region, circular", [ + ((10, 10), True), # empty + ((0, 659), False), # past the end + ((-1, 10), False), + ((658, 5), True), # start outside the construct + ((500, 100), False), # wraps on a linear construct +]) +def test_invalid_region_rejected(coi, monkeypatch, region, circular): + def boom(*a, **k): + raise AssertionError("aligned before validating the region") + monkeypatch.setattr(clones, "align_to_construct", boom) + monkeypatch.setattr(clones, "_load", boom) + with pytest.raises(ValueError): + verify_clone(_construct(coi, circular), region, _reads()) + with pytest.raises(ValueError): + verify_all(_construct(coi, circular), region, Grouping(_reads()), VerifyParams()) + + +def test_verify_all_progress_and_cancel(coi): + grouping = Grouping([ + ReadRef(F_PATH, "c2", "F"), ReadRef(R_PATH, "c2", "R"), + ReadRef(F_PATH, "c1", "F"), + ]) + calls = [] + reports = verify_all(_construct(coi), REGION, grouping, VerifyParams(), + progress=lambda d, t: calls.append((d, t))) + assert [r.clone for r in reports] == ["c1", "c2"] + assert all(isinstance(r, CloneReport) for r in reports) + assert [r.verdict for r in reports] == ["incomplete", "ok"] + assert calls == [(1, 2), (2, 2)] + + calls.clear() + with pytest.raises(CancelledError): + verify_all(_construct(coi), REGION, grouping, VerifyParams(), + progress=lambda d, t: calls.append((d, t)), + cancelled=lambda: bool(calls)) + assert calls == [(1, 2)] + + +def test_annotate_sets_effect(coi): + seen = [] + + def annotate(construct, diff): + seen.append((construct.name, diff.ref_pos)) + return "effect!" + + r = verify_clone(_construct(mutate(coi, P, "sub", "G")), REGION, _reads(), annotate=annotate) + assert [d.effect for d in r.differences] == ["effect!"] + assert seen == [("c", P)] + + +def test_load_read_applies_session(tmp_path): + model = EditableRead(real_read(F_NAME)) + model.set_base(10, "A") + model.apply_trim(5, 300) + path = write_read(model.current(), tmp_path, F_NAME) + chrom = load_read(path) + assert chrom.seq == "".join(model.seq) + assert chrom.quality == tuple(model.quality) + + +# Measured 2026-10-30 on the developer machine: 12.2-13.3 s (3 runs; the +# exact DP alignment against 10 kb dominates). LIMIT = 2 x 13.3, rounded up. +LIMIT = 27.0 + + +def test_performance_12_clones_x_4_reads(coi): + rng = random.Random(1) + flank = "".join(rng.choice("ACGT") for _ in range(10_000 - len(coi))) + construct = _construct(coi + flank) # ~10 kb + names = ["Achl_ACHLO006-09_1_F.ab1", "Achl_ACHLO006-09_2_R.ab1", + "Achl_ACHLO007-09_1_F.ab1", "Achl_ACHLO007-09_2_R.ab1"] + grouping = Grouping([ + ReadRef(DATA / "real" / n, f"clone{c}", n[-5]) for c in range(12) for n in names + ]) + t = time.perf_counter() + reports = verify_all(construct, None, grouping, VerifyParams()) + elapsed = time.perf_counter() - t + print(f"verify_all 12x4 on {len(construct.seq)} bp: {elapsed:.2f} s") + assert len(reports) == 12 + assert all(r.verdict != "no_data" for r in reports) + assert elapsed < LIMIT diff --git a/tests/test_editing.py b/tests/test_editing.py index 141f43e..5b6dee5 100644 --- a/tests/test_editing.py +++ b/tests/test_editing.py @@ -65,10 +65,14 @@ def test_reverse_complement(model: EditableRead) -> None: chrom = model.current() # flipped traces: A channel is original T channel reversed assert chrom.traces["A"] == tuple(reversed(model.original.traces["T"])) - # rc twice restores sequence and quality + # peaks follow the flipped traces (reversed over the full trace length) + last = len(model.original.traces["A"]) - 1 + assert chrom.peak_indices == tuple(last - p for p in reversed(model.original.peak_indices)) + # rc twice restores sequence, quality and peaks model.reverse_complement() assert "".join(model.seq) == seq assert model.quality == list(model.original.quality) + assert model.peaks == list(model.original.peak_indices) assert not model.reversed_complement From a46c6197bef2cd658a0a381f695fe86d18981cf9 Mon Sep 17 00:00:00 2001 From: Aleksey Drobin <43707931+adrobi@users.noreply.github.com> Date: Fri, 30 Oct 2026 02:21:27 +0300 Subject: [PATCH 14/44] align: count distinct placements; clones: ambiguity by placements ReadAlignment.placements clusters co-optimal paths whose reference spans overlap (mod L for circular constructs), so alternative gap positions in a homopolymer are one placement. verify_clone marks a read ambiguous only for placements > 1; alternatives is unchanged. Co-Authored-By: Claude Opus 5.5 --- chrom_core/align.py | 55 ++++++++++++++++++++++++++++++++++-- chrom_core/clones.py | 4 +-- tests/test_align.py | 21 ++++++++++++++ tests/test_align_circular.py | 15 +++++++++- tests/test_clone_verify.py | 27 +++++++++++++----- 5 files changed, 109 insertions(+), 13 deletions(-) diff --git a/chrom_core/align.py b/chrom_core/align.py index a6ac417..db70d2e 100644 --- a/chrom_core/align.py +++ b/chrom_core/align.py @@ -31,6 +31,7 @@ MAX_REFERENCE_LENGTH = 100_000 CIRCULAR_MARGIN = 50 # extra unrolled bases past len(read) for circular constructs MAX_COUNTED_ALTERNATIVES = 1000 # co-optimal paths examined to dedupe the circular copy +MAX_PLACEMENT_PATHS = 100 # co-optimal paths examined to count distinct placements @dataclass(frozen=True) @@ -58,6 +59,9 @@ class ReadAlignment: blocks: list # biopython aligned blocks, for gapped reconstruction # (unrolled coordinates for circular constructs) ref_length: int = 0 # construct length (0 = unknown, from align_read) + placements: int = 1 # distinct (non-overlapping) co-optimal placements; + # 0 = unknown. Unlike ``alternatives``, alternative + # gap positions inside one placement count once. @property def wraps(self) -> bool: @@ -134,10 +138,11 @@ def align_read(read: str, reference: str) -> ReadAlignment: return _align(read, reference)[0] -def _align(read: str, reference: str) -> tuple[ReadAlignment, object]: +def _align(read: str, reference: str, L: int | None = None) -> tuple[ReadAlignment, object]: """align_read without the size limit (callers check it on the real length). Also returns biopython's co-optimal alignments for the winning strand. + ``L``: the circle length when ``reference`` is an unrolled circle. """ aligner = _make_aligner() best: tuple[float, object, str, str] | None = None @@ -175,9 +180,52 @@ def _align(read: str, reference: str) -> tuple[ReadAlignment, object]: alternatives=alternatives, oriented_read=oriented, blocks=blocks, + placements=_placements(alignments, L), ), alignments +def _placements(alignments, L: int | None = None) -> int: + """Clusters of co-optimal paths whose reference spans overlap. + + Up to ``MAX_PLACEMENT_PATHS`` paths are examined. With ``L`` (circular, + unrolled reference) spans are compared modulo L, so the unrolled copy of + the start is the same placement. 0 when iterating the paths fails. + """ + spans: list[tuple[int, int]] = [] + try: + for k, alignment in enumerate(alignments): + if k >= MAX_PLACEMENT_PATHS: + break + ts = alignment.aligned[0] + if len(ts): + spans.append((int(ts[0][0]), int(ts[-1][1]))) + except Exception: + return 0 + if not spans: + return 1 + + if L: # start in the first copy; compare with the neighbouring copies too + spans = [(t0 % L, t0 % L + t1 - t0) for t0, t1 in spans] + shifts = (-L, 0, L) if L else (0,) + + def overlap(a: tuple[int, int], b: tuple[int, int]) -> bool: + return any(a[0] < b[1] + s and b[0] + s < a[1] for s in shifts) + + parent = list(range(len(spans))) + + def root(i: int) -> int: + while parent[i] != i: + parent[i] = parent[parent[i]] + i = parent[i] + return i + + for i in range(len(spans)): + for j in range(i): + if overlap(spans[i], spans[j]): + parent[root(i)] = root(j) + return len({root(i) for i in range(len(spans))}) + + def _circular_alternatives(raw: ReadAlignment, alignments, L: int) -> int: """Co-optimal alignments distinct modulo L. @@ -263,7 +311,8 @@ def align_to_construct(read: str, construct: Construct) -> ReadAlignment: after the origin come last — not ascending by ``ref_pos``. ``alternatives`` counts co-optimal alignments distinct modulo L, so the - unrolled copy of the construct's start is not mistaken for a repeat. + unrolled copy of the construct's start is not mistaken for a repeat; + ``placements`` likewise compares reference spans modulo L. The size limit applies to ``L``, not to the unrolled sequence. """ @@ -274,7 +323,7 @@ def align_to_construct(read: str, construct: Construct) -> ReadAlignment: return replace(_align(read, seq)[0], ref_length=L) unrolled = seq + seq[: len(read) + CIRCULAR_MARGIN] - raw, alignments = _align(read, unrolled) + raw, alignments = _align(read, unrolled, L) alternatives = _circular_alternatives(raw, alignments, L) if not raw.blocks: return replace(raw, ref_length=L, alternatives=alternatives) diff --git a/chrom_core/clones.py b/chrom_core/clones.py index e258556..63f857a 100644 --- a/chrom_core/clones.py +++ b/chrom_core/clones.py @@ -178,7 +178,7 @@ class ReadResult: ref: ReadRef alignment: ReadAlignment | None # None when ``error`` is set error: str = "" # "no_alignment" or why the file could not be used - ambiguous: bool = False # alternatives > 1: excluded from the verdict + ambiguous: bool = False # placements > 1: excluded from the verdict @dataclass(frozen=True) @@ -400,7 +400,7 @@ def verify_clone( if al.covered < MIN_ALIGNED_BP or al.identity < MIN_IDENTITY: results.append(ReadResult(read_ref, None, error="no_alignment")) continue - ambiguous = al.alternatives > 1 + ambiguous = al.placements > 1 # distinct placements, not co-optimal paths results.append(ReadResult(read_ref, al, ambiguous=ambiguous)) if not ambiguous: strand = al.strand if not flipped else {"+": "-", "-": "+"}[al.strand] diff --git a/tests/test_align.py b/tests/test_align.py index cb0aa0e..c931509 100644 --- a/tests/test_align.py +++ b/tests/test_align.py @@ -104,6 +104,27 @@ def test_ambiguous_repetitive_reference_flagged() -> None: assert a.identity == 1.0 +def test_homopolymer_indel_is_one_placement() -> None: + import random + rng = random.Random(5) + left = "".join(rng.choice("ACGT") for _ in range(80)) + right = "".join(rng.choice("ACGT") for _ in range(80)) + reference = left + "GTTTTC" + right + read = left + "GTTTTTC" + right # one extra T in the run + a = align_read(read, reference) + assert a.alternatives > 1 # co-optimal gap placements ... + assert a.placements == 1 # ... but a single placement + + +def test_distinct_repeat_copies_are_two_placements() -> None: + import random + rng = random.Random(6) + unit = "".join(rng.choice("ACGT") for _ in range(60)) + spacer = "".join(rng.choice("ACGT") for _ in range(200)) + a = align_read(unit, spacer[:50] + unit + spacer + unit + spacer[50:]) + assert a.placements == 2 + + def test_empty_inputs_raise(reference: str) -> None: with pytest.raises(ValueError): align_read("", reference) diff --git a/tests/test_align_circular.py b/tests/test_align_circular.py index 648aa1b..028abf8 100644 --- a/tests/test_align_circular.py +++ b/tests/test_align_circular.py @@ -177,7 +177,9 @@ def test_read_in_unrolled_prefix_is_not_ambiguous() -> None: aln = align_to_construct(read, Construct("c", circle, True)) assert (aln.ref_start, aln.ref_end) == (10, 210) assert aln.alternatives == 1 - assert align_to_construct(read, Construct("c", circle, False)).alternatives == 1 + assert aln.placements == 1 + linear = align_to_construct(read, Construct("c", circle, False)) + assert (linear.alternatives, linear.placements) == (1, 1) def test_genuine_repeat_in_circle_stays_ambiguous() -> None: @@ -188,3 +190,14 @@ def test_genuine_repeat_in_circle_stays_ambiguous() -> None: circle = "".join(circle) aln = align_to_construct(repeat, Construct("c", circle, True)) assert aln.alternatives == 2 + assert aln.placements == 2 + + +def test_homopolymer_indel_across_origin_is_one_placement() -> None: + circle = _random_seq(1000, seed=31) + circle = circle[:995] + "GTTTC" # a TTT run just before the origin + read = circle[900:996] + "TTTT" + circle[999:] + circle[:100] # one extra T + aln = align_to_construct(read, Construct("c", circle, True)) + assert aln.wraps + assert aln.alternatives > 1 + assert aln.placements == 1 diff --git a/tests/test_clone_verify.py b/tests/test_clone_verify.py index 13453b9..c480cef 100644 --- a/tests/test_clone_verify.py +++ b/tests/test_clone_verify.py @@ -275,16 +275,27 @@ def test_ambiguous_read_excluded(coi, tmp_path): model.apply_trim(100, 500) paths.append(write_read(model.current(), tmp_path, name)) r = verify_clone(_construct(coi + coi), None, _reads(*paths)) - assert all(x.ambiguous for x in r.reads) + assert all(x.ambiguous and x.alignment.placements == 2 for x in r.reads) + assert r.verdict == "no_data" + + +def test_genuine_repeat_single_read_is_no_data(coi, tmp_path): + model = EditableRead(real_read(F_NAME)) + model.apply_trim(100, 500) + f = write_read(model.current(), tmp_path, F_NAME) + rng = random.Random(3) + spacer = "".join(rng.choice("ACGT") for _ in range(300)) + r = verify_clone(_construct(coi + spacer + coi), None, _reads(f=f, r=None)) + res, = r.reads + assert res.ambiguous and res.alignment.placements == 2 assert r.verdict == "no_data" assert all(v == (0, 0) for v in r.coverage.values()) -@pytest.mark.xfail(strict=True, reason=( - "alternatives counts co-optimal gap placements, so an indel in a homopolymer " - "marks every read ambiguous and the clone becomes no_data (see task-7 report)")) def test_homopolymer_deletion_is_an_error_not_no_data(coi): + # co-optimal gap placements inside a run are one placement, not ambiguity (R15) r = verify_clone(_construct(mutate(coi, 200, "ins", "T")), REGION, _reads()) # TTTT -> TTTTT + assert all(x.alignment.alternatives > 1 and not x.ambiguous for x in r.reads) assert r.verdict == "errors" assert [(d.kind, d.status) for d in r.region_differences] == [("deletion", "confirmed")] @@ -350,9 +361,10 @@ def test_load_read_applies_session(tmp_path): assert chrom.quality == tuple(model.quality) -# Measured 2026-10-30 on the developer machine: 12.2-13.3 s (3 runs; the -# exact DP alignment against 10 kb dominates). LIMIT = 2 x 13.3, rounded up. -LIMIT = 27.0 +# Measured 2026-10-30 on the developer machine, after placements (R15) were +# added: 15.1-15.5 s (3 runs; the exact DP alignment against 10 kb dominates). +# LIMIT = 2 x 15.5, rounded up. +LIMIT = 32.0 def test_performance_12_clones_x_4_reads(coi): @@ -370,4 +382,5 @@ def test_performance_12_clones_x_4_reads(coi): print(f"verify_all 12x4 on {len(construct.seq)} bp: {elapsed:.2f} s") assert len(reports) == 12 assert all(r.verdict != "no_data" for r in reports) + assert not any(x.ambiguous or x.error for r in reports for x in r.reads) assert elapsed < LIMIT From 58510f6358050121075d7a15808e804faa88bf34 Mon Sep 17 00:00:00 2001 From: Aleksey Drobin <43707931+adrobi@users.noreply.github.com> Date: Fri, 30 Oct 2026 02:26:58 +0300 Subject: [PATCH 15/44] effects: amino-acid consequences of clone differences in CDS Co-Authored-By: Claude Sonnet 5.5 --- chrom_core/clones.py | 9 ++- chrom_core/effects.py | 88 +++++++++++++++++++++++++++ tests/test_effects.py | 137 ++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 231 insertions(+), 3 deletions(-) create mode 100644 chrom_core/effects.py create mode 100644 tests/test_effects.py diff --git a/chrom_core/clones.py b/chrom_core/clones.py index 63f857a..7002114 100644 --- a/chrom_core/clones.py +++ b/chrom_core/clones.py @@ -12,6 +12,7 @@ from chrom_core.abif import Chromatogram, read_ab1 from chrom_core.align import Difference, ReadAlignment, align_to_construct from chrom_core.editing import EditableRead +from chrom_core.effects import difference_effect from chrom_core.peaks import scan_secondary_peaks from chrom_core.reference import Construct from chrom_core.seqops import iupac_compatible, reverse_complement @@ -377,11 +378,12 @@ def verify_clone( region: Region | None, reads: list[ReadRef], params: VerifyParams = VerifyParams(), - annotate=None, + annotate=difference_effect, ) -> CloneReport: """Check one colony's reads against ``construct`` within ``region``. - ``annotate(construct, difference) -> str`` fills ``CloneDifference.effect``. + ``annotate(construct, difference) -> str`` fills ``CloneDifference.effect`` + (default: ``difference_effect``; ``None`` leaves it empty). """ L = len(construct.seq) positions = region_positions(_check_region(region, L, construct.circular), L) @@ -461,6 +463,7 @@ def verify_all( params: VerifyParams = VerifyParams(), progress=None, cancelled=None, + annotate=difference_effect, ) -> list[CloneReport]: """``verify_clone`` for every clone of ``grouping``, in natural name order. @@ -474,7 +477,7 @@ def verify_all( for done, reads in enumerate(groups.values(), start=1): if cancelled is not None and cancelled(): raise CancelledError() - reports.append(verify_clone(construct, region, reads, params)) + reports.append(verify_clone(construct, region, reads, params, annotate)) if progress is not None: progress(done, len(groups)) return reports diff --git a/chrom_core/effects.py b/chrom_core/effects.py new file mode 100644 index 0000000..cb990df --- /dev/null +++ b/chrom_core/effects.py @@ -0,0 +1,88 @@ +"""Amino-acid consequences of clone differences inside CDS features.""" + +from __future__ import annotations + +from typing import TYPE_CHECKING + +from Bio.Seq import Seq + + +if TYPE_CHECKING: + from chrom_core.clones import CloneDifference + from chrom_core.reference import Construct, Feature + +TRANSLATION_TABLE = 11 +_BASES = frozenset("ACGT") +_COMPLEMENT = str.maketrans("ACGT", "TGCA") + + +def _feature_positions(feature: Feature, length: int) -> list[int]: + """Construct positions of ``feature`` in transcript order (wrap and strand aware).""" + if feature.start <= feature.end: + pos = list(range(feature.start, feature.end)) + else: + pos = list(range(feature.start, length)) + list(range(0, feature.end)) + return pos[::-1] if feature.strand == -1 else pos + + +def _translate(codon: str) -> str: + return str(Seq(codon).translate(table=TRANSLATION_TABLE)) + + +def difference_effect(construct: Construct, diff: CloneDifference) -> str: + """Effect of ``diff`` on the first CDS of ``construct`` that contains it. + + Substitution: ``"synonymous"``, ``"D45N"`` (one-letter codes, amino-acid + number counted from the CDS start, frame from ``codon_start``) or + ``"W12*"`` for a stop. Insertion/deletion: ``"frameshift"`` when the length + is not a multiple of 3, else ``"inframe_ins"`` / ``"inframe_del"``. The + length is that of this one ``CloneDifference``: a multi-base deletion + arrives as several one-base differences, each of which is reported as + ``"frameshift"``. ``""`` outside any CDS, with no features, or when the + read base is not A/C/G/T or the codon is incomplete. + """ + seq = construct.seq.upper() + length = len(seq) + if not length: + return "" + for feature in construct.features: + if feature.kind != "CDS": + continue + pos = _feature_positions(feature, length) + index = {p: i for i, p in enumerate(pos)} + if diff.ref_pos not in index: + continue + if diff.kind == "insertion": + if (diff.ref_pos - 1) % length not in index: + continue + return "frameshift" if len(diff.read_base) % 3 else "inframe_ins" + if diff.kind == "deletion": + return "frameshift" if len(diff.ref_base.replace("-", "")) % 3 else "inframe_del" + if diff.kind != "substitution": + return "" + alt = diff.read_base.upper() + if len(alt) != 1 or alt not in _BASES: + return "" + offset = index[diff.ref_pos] - (feature.codon_start - 1) + if offset < 0: + return "" + number, within = divmod(offset, 3) + first = number * 3 + feature.codon_start - 1 + codon_pos = pos[first:first + 3] + if len(codon_pos) < 3: + return "" + if feature.strand == -1: # positions are in transcript order: complement only + alt = alt.translate(_COMPLEMENT) + codon = "".join(seq[p].translate(_COMPLEMENT) for p in codon_pos) + else: + codon = "".join(seq[p] for p in codon_pos) + mutated = codon[:within] + alt + codon[within + 1:] + return _label(codon, mutated, number + 1) + return "" + + +def _label(codon: str, mutated: str, number: int) -> str: + ref_aa, alt_aa = _translate(codon), _translate(mutated) + if ref_aa == alt_aa: + return "synonymous" + return f"{ref_aa}{number}{alt_aa}" diff --git a/tests/test_effects.py b/tests/test_effects.py new file mode 100644 index 0000000..26d0935 --- /dev/null +++ b/tests/test_effects.py @@ -0,0 +1,137 @@ +"""Amino-acid effects of clone differences inside CDS features.""" + +from dataclasses import replace + +from Bio.Seq import Seq + +from chrom_core.clones import CloneDifference +from chrom_core.effects import difference_effect +from chrom_core.reference import Construct, Feature, load_construct +from chrom_core.seqops import reverse_complement +from tests.clone_fixtures import COI_GB + +COMP = {"A": "T", "C": "G", "G": "C", "T": "A"} + + +def aa(codon: str) -> str: + return str(Seq(codon).translate(table=11)) + + +def sub(pos: int, ref: str, alt: str) -> CloneDifference: + return CloneDifference(pos, "substitution", ref, alt, 2, 0, 0, "confirmed", True) + + +def coi(): + c = load_construct(COI_GB) + cds = next(f for f in c.features if f.kind == "CDS") + return c, cds + + +def codon_at(c, cds, n: int) -> tuple[int, str]: + """Start position and codon of amino acid ``n`` (1-based) on the plus strand.""" + start = cds.start + cds.codon_start - 1 + (n - 1) * 3 + return start, c.seq[start:start + 3].upper() + + +def alt_changing(codon: str, within: int, synonymous: bool, avoid_stop=True) -> str: + for b in "ACGT": + if b == codon[within]: + continue + new = codon[:within] + b + codon[within + 1:] + if (aa(new) == aa(codon)) == synonymous and not (avoid_stop and aa(new) == "*"): + return b + raise AssertionError("no such alternative") + + +def test_synonymous_third_codon_position(): + c, cds = coi() + start, codon = codon_at(c, cds, 10) + alt = alt_changing(codon, 2, synonymous=True) + assert aa(codon[:2] + alt) == aa(codon) + assert difference_effect(c, sub(start + 2, codon[2], alt)) == "synonymous" + + +def test_missense_label(): + c, cds = coi() + n = 45 + start, codon = codon_at(c, cds, n) + alt = alt_changing(codon, 0, synonymous=False) + d = sub(start, codon[0], alt) + aa_ref, aa_alt = aa(codon), aa(alt + codon[1:]) + assert difference_effect(c, d) == f"{aa_ref}{n}{aa_alt}" + + +def test_stop_gained(): + c, cds = coi() + for n in range(2, 200): + start, codon = codon_at(c, cds, n) + for within in range(3): + for b in "ACGT": + new = codon[:within] + b + codon[within + 1:] + if b != codon[within] and aa(new) == "*" and aa(codon) != "*": + got = difference_effect(c, sub(start + within, codon[within], b)) + assert got == f"{aa(codon)}{n}*" + return + raise AssertionError("no stop-gaining substitution found") + + +def test_frameshift_and_inframe(): + c, cds = coi() + pos = cds.start + 30 + ins1 = CloneDifference(pos, "insertion", "-", "A", 2, 0, 0, "confirmed", True) + ins3 = replace(ins1, read_base="ACG") + del1 = CloneDifference(pos, "deletion", c.seq[pos], "-", 2, 0, 0, "confirmed", True) + assert difference_effect(c, ins1) == "frameshift" + assert difference_effect(c, ins3) == "inframe_ins" + assert difference_effect(c, del1) == "frameshift" + + +def test_minus_strand_cds(): + """Mirrored COI on the minus strand (controller ruling R11). + + pUC19's GenBank has no CDS (only 'source'), so ``bla`` cannot be used: the + COI construct is reverse-complemented and its CDS mirrored to strand -1. + """ + c, cds = coi() + L = len(c.seq) + rc = Construct( + "coi_rc", reverse_complement(c.seq.upper()), False, + (replace(cds, start=L - cds.end, end=L - cds.start, strand=-1),), + ) + for n in (1, 45, 100): + start, codon = codon_at(c, cds, n) + for within, synonymous in ((0, False), (2, True)): + alt = alt_changing(codon, within, synonymous) + plus = difference_effect(c, sub(start + within, codon[within], alt)) + mpos = L - 1 - (start + within) + assert rc.seq[mpos] == COMP[codon[within]] + minus = difference_effect(rc, sub(mpos, COMP[codon[within]], COMP[alt])) + assert minus == plus + + +def test_wrapping_cds(): + c, cds = coi() + # rotate so the CDS crosses the origin + shift = 100 + seq = c.seq.upper() + L = len(seq) + rot = Construct( + "rot", seq[shift:] + seq[:shift], True, + (replace(cds, start=(cds.start - shift) % L, end=(cds.start + 600 - shift) % L),), + ) + start, codon = codon_at(c, cds, 45) + alt = alt_changing(codon, 0, synonymous=False) + d = sub((start - shift) % L, codon[0], alt) + assert difference_effect(rot, d) == f"{aa(codon)}45{aa(alt + codon[1:])}" + + +def test_outside_cds_empty(): + c, cds = coi() + only = Construct("x", c.seq, False, (replace(cds, start=100, end=200),)) + assert difference_effect(only, sub(5, c.seq[5], "A" if c.seq[5] != "A" else "C")) == "" + + +def test_no_features_empty(): + c, _ = coi() + plain = Construct("x", c.seq, False) + assert difference_effect(plain, sub(10, "A", "C")) == "" From 514cd4c92961d6a6a266451402cc0770ca0b71cf Mon Sep 17 00:00:00 2001 From: Aleksey Drobin <43707931+adrobi@users.noreply.github.com> Date: Fri, 30 Oct 2026 02:32:10 +0300 Subject: [PATCH 16/44] clone_report: CSV and Excel reports for clone verification Co-Authored-By: Claude Sonnet 5.5 --- chrom_core/batch.py | 8 +- chrom_core/clone_report.py | 107 +++++++++++++++++++++++++ tests/test_clone_report.py | 160 +++++++++++++++++++++++++++++++++++++ 3 files changed, 273 insertions(+), 2 deletions(-) create mode 100644 chrom_core/clone_report.py create mode 100644 tests/test_clone_report.py diff --git a/chrom_core/batch.py b/chrom_core/batch.py index 30a5dec..cc3efcf 100644 --- a/chrom_core/batch.py +++ b/chrom_core/batch.py @@ -108,13 +108,17 @@ def batch_export( return results -def _csv_field(value) -> str: +def csv_field(value, sep: str = ";") -> str: + """One CSV field, quoted when it contains ``sep``, a quote or a line break.""" text = str(value) - if any(ch in text for ch in ';"\n'): + if any(ch in text for ch in f'{sep}"\n\r'): text = '"' + text.replace('"', '""') + '"' return text +_csv_field = csv_field + + def summary_csv(reports: list[FileReport]) -> str: """Semicolon-separated summary (opens cleanly in RU-locale Excel).""" lines = ["file;length;mean_q;q20;trimmed_length;status;error"] diff --git a/chrom_core/clone_report.py b/chrom_core/clone_report.py new file mode 100644 index 0000000..16fe010 --- /dev/null +++ b/chrom_core/clone_report.py @@ -0,0 +1,107 @@ +"""CSV and Excel reports for clone verification (shared by the UI and the CLI).""" + +from __future__ import annotations + +from chrom_core.batch import csv_field +from chrom_core.clones import CloneDifference, CloneReport + +# verdict -> (light, dark) hex colours; the single source of the status palette. +STATUS_HEX: dict[str, tuple[str, str]] = { + "ok": ("#c6efce", "#2e7d32"), + "errors": ("#ffc7ce", "#c62828"), + "incomplete": ("#ffeb9c", "#f9a825"), + "mixed": ("#e1d5f0", "#7b1fa2"), + "no_data": ("#e0e0e0", "#757575"), +} + +CLONES_HEADER = ("clone", "verdict", "region_coverage_pct", "both_strands_pct", + "differences", "reads") +DIFFERENCES_HEADER = ("clone", "position", "kind", "ref", "read", "effect", + "support", "against", "status", "note") + + +def _plural(n: int, word: str) -> str: + return f"{n} {word}" if n == 1 else f"{n} {word}s" + + +def _note(d: CloneDifference) -> str: + """Short remark: ``disputed: N read(s) against`` / ``low quality: N read(s)``, + plus ``outside region`` (joined by `` / ``); empty for a confirmed in-region one.""" + parts = [] + if d.status == "disputed": + parts.append(f"disputed: {_plural(d.against, 'read')} against") + elif d.status == "low_quality": + parts.append(f"low quality: {_plural(d.low_quality, 'read')}") + if not d.in_region: + parts.append("outside region") + return " / ".join(parts) + + +def _clone_row(r: CloneReport) -> tuple: + # ``reads``: file names of every read of the clone (used or not), joined by "|". + names = "|".join(read.ref.path.name for read in r.reads) + return (r.clone, r.verdict, round(r.region_coverage_pct, 1), round(r.both_strands_pct, 1), + len(r.differences), names) + + +def _difference_rows(reports: list[CloneReport]): + for r in reports: + for d in r.differences: + # position is 1-based; an insertion is reported before this position + yield (r.clone, d.ref_pos + 1, d.kind, d.ref_base, d.read_base, d.effect, + d.support, d.against, d.status, _note(d)) + + +def _fmt(value) -> str: + return f"{value:.1f}" if isinstance(value, float) else str(value) + + +def _csv(header, rows) -> str: + lines = [",".join(header)] + for row in rows: + lines.append(",".join(csv_field(_fmt(v), sep=",") for v in row)) + return "\n".join(lines) + "\n" + + +def clones_csv(reports: list[CloneReport]) -> str: + """One row per clone, comma-separated.""" + return _csv(CLONES_HEADER, (_clone_row(r) for r in reports)) + + +def differences_csv(reports: list[CloneReport]) -> str: + """One row per difference of every clone (outside-region ones included).""" + return _csv(DIFFERENCES_HEADER, _difference_rows(reports)) + + +def clone_report_xlsx(path, reports: list[CloneReport], construct_name: str) -> None: + """Excel report: sheets ``Clones`` and ``Differences``; the verdict cell is filled + with its light ``STATUS_HEX`` colour. ``construct_name`` is the workbook title.""" + try: + from openpyxl import Workbook + from openpyxl.styles import Font, PatternFill + except ImportError as exc: # pragma: no cover - depends on environment + raise RuntimeError("openpyxl is required for Excel reports: pip install openpyxl") from exc + + book = Workbook() + book.properties.title = construct_name + clones = book.active + clones.title = "Clones" + diffs = book.create_sheet("Differences") + for sheet, header in ((clones, CLONES_HEADER), (diffs, DIFFERENCES_HEADER)): + sheet.append(header) + for cell in sheet[1]: + cell.font = Font(bold=True) + for r in reports: + clones.append(_clone_row(r)) + palette = STATUS_HEX.get(r.verdict) + if palette: + colour = palette[0].lstrip("#").upper() + clones.cell(row=clones.max_row, column=2).fill = PatternFill( + "solid", start_color=colour, end_color=colour) + for row in _difference_rows(reports): + diffs.append(row) + for sheet, widths in ((clones, (16, 12, 20, 18, 12, 50)), + (diffs, (16, 10, 14, 8, 8, 14, 9, 9, 12, 30))): + for i, width in enumerate(widths): + sheet.column_dimensions[chr(ord("A") + i)].width = width + book.save(path) diff --git a/tests/test_clone_report.py b/tests/test_clone_report.py new file mode 100644 index 0000000..1215f48 --- /dev/null +++ b/tests/test_clone_report.py @@ -0,0 +1,160 @@ +"""CSV / Excel reports for clone verification, built from real reads (HM417896 COI).""" + +from __future__ import annotations + +import csv +import io +from dataclasses import replace + +import pytest +from openpyxl import load_workbook + +from chrom_core import batch +from chrom_core.clone_report import ( + STATUS_HEX, + clone_report_xlsx, + clones_csv, + differences_csv, +) +from chrom_core.clones import Grouping, ReadRef, verify_all, verify_clone +from chrom_core.reference import Construct, load_construct +from clone_fixtures import COI_GB, DATA, REAL_READS, coi_reference, mutate + +F = DATA / "real" / "Achl_ACHLO006-09_1_F.ab1" +R = DATA / "real" / "Achl_ACHLO006-09_2_R.ab1" +REGION = (6, 647) +P = 250 # inside the region +OUTSIDE = 652 # covered by F only, outside the region + +assert F in REAL_READS and R in REAL_READS + + +@pytest.fixture(scope="module") +def coi() -> str: + return coi_reference() + + +def _reads(clone: str, *paths_primers) -> list[ReadRef]: + return [ReadRef(p, clone, primer) for p, primer in paths_primers] + + +@pytest.fixture(scope="module") +def reports(coi): + """c1: clean (ok) and c2: substitution at P and outside-region one at OUTSIDE.""" + clean = verify_clone(Construct("c", coi, False), REGION, _reads("c1", (F, "F"), (R, "R"))) + bad_ref = mutate(mutate(coi, P, "sub", "G" if coi[P] != "G" else "A"), + OUTSIDE, "sub", "G" if coi[OUTSIDE] != "G" else "A") + bad = verify_clone(Construct("c", bad_ref, False), REGION, _reads("c2", (F, "F"), (R, "R"))) + return [clean, bad] + + +def _rows(text: str) -> list[list[str]]: + return list(csv.reader(io.StringIO(text))) + + +def test_clones_csv_header_and_rows(reports): + rows = _rows(clones_csv(reports)) + assert rows[0] == ["clone", "verdict", "region_coverage_pct", "both_strands_pct", + "differences", "reads"] + assert len(rows) == 3 + c1, c2 = rows[1], rows[2] + assert c1[:2] == ["c1", "ok"] + assert c1[2] == "100.0" and c1[3] == "97.0" # F and R overlap on most of the region + assert c1[4] == "0" + assert c1[5] == f"{F.name}|{R.name}" + assert c2[:2] == ["c2", "errors"] + assert c2[4] == str(len(reports[1].differences)) + + +def test_clones_csv_empty(): + assert clones_csv([]).splitlines() == [ + "clone,verdict,region_coverage_pct,both_strands_pct,differences,reads"] + + +def test_differences_csv_header_position_and_notes(reports): + rows = _rows(differences_csv(reports)) + assert rows[0] == ["clone", "position", "kind", "ref", "read", "effect", + "support", "against", "status", "note"] + body = rows[1:] + assert len(body) == len(reports[1].differences) == 2 # clean clone contributes none + by_pos = {int(r[1]): r for r in body} + assert set(by_pos) == {P + 1, OUTSIDE + 1} # 1-based + inside, outside = by_pos[P + 1], by_pos[OUTSIDE + 1] + assert inside[0] == "c2" and inside[2] == "substitution" + assert inside[8] == "confirmed" and inside[9] == "" + assert inside[6] == "2" and inside[7] == "0" + assert outside[9] == "outside region" + + +def test_differences_note_variants(): + from chrom_core.clone_report import _note + from chrom_core.clones import CloneDifference + + def diff(**kw): + base = dict(ref_pos=1, kind="substitution", ref_base="A", read_base="G", support=1, + against=0, low_quality=0, status="confirmed", in_region=True) + return CloneDifference(**{**base, **kw}) + + assert _note(diff()) == "" + assert _note(diff(status="disputed", against=1)) == "disputed: 1 read against" + assert _note(diff(status="disputed", against=3)) == "disputed: 3 reads against" + assert _note(diff(status="low_quality", support=0, low_quality=2)) == "low quality: 2 reads" + assert _note(diff(status="low_quality", support=0, low_quality=1, in_region=False)) == \ + "low quality: 1 read / outside region" + + +def test_csv_quotes_commas_and_quotes(): + from chrom_core.clones import CloneReport + weird = CloneReport('a,"b"', (), {}, (), (), "no_data") + rows = _rows(clones_csv([weird])) + assert rows[1][0] == 'a,"b"' + assert len(rows[1]) == 6 + assert batch.csv_field("x,y", sep=",") == '"x,y"' + assert batch.csv_field("x,y") == "x,y" + + +def test_xlsx_sheets_and_fill(reports, tmp_path): + path = tmp_path / "r.xlsx" + clone_report_xlsx(path, reports, "COI") + book = load_workbook(path) + assert book.sheetnames == ["Clones", "Differences"] + clones, diffs = book["Clones"], book["Differences"] + assert [c.value for c in clones[1]] == ["clone", "verdict", "region_coverage_pct", + "both_strands_pct", "differences", "reads"] + assert clones.max_row == 3 + assert clones["B2"].value == "ok" and clones["B3"].value == "errors" + assert clones["B3"].fill.fgColor.rgb[-6:] == STATUS_HEX["errors"][0].lstrip("#").upper() + assert clones["B2"].fill.fgColor.rgb[-6:] == STATUS_HEX["ok"][0].lstrip("#").upper() + assert clones["B1"].font.bold + assert clones["C2"].value == 100.0 + assert diffs.max_row == 3 + assert diffs["B2"].value in (P + 1, OUTSIDE + 1) + assert book.properties.title == "COI" + + +def test_status_hex_palette(): + assert set(STATUS_HEX) == {"ok", "errors", "incomplete", "mixed", "no_data"} + for light, dark in STATUS_HEX.values(): + for colour in (light, dark): + assert len(colour) == 7 and colour[0] == "#" + int(colour[1:], 16) + assert len({light for light, _ in STATUS_HEX.values()}) == 5 + + +def test_end_to_end_effect_from_cds_construct(coi, tmp_path): + construct = load_construct(COI_GB) + assert any(f.kind == "CDS" for f in construct.features) + alt = "G" if coi[P] != "G" else "A" + mutated = replace(construct, seq=mutate(construct.seq, P, "sub", alt)) + grouping = Grouping([ReadRef(F, "c1", "F"), ReadRef(R, "c1", "R")]) + + [report] = verify_all(mutated, REGION, grouping) + [diff] = [d for d in report.differences if d.in_region] + assert diff.effect + + [plain] = verify_all(mutated, REGION, grouping, annotate=None) + assert [d.effect for d in plain.differences] == [""] * len(plain.differences) + + rows = _rows(differences_csv([report])) + row = next(r for r in rows[1:] if int(r[1]) == P + 1) + assert row[5] == diff.effect From 0c040b35e5a6085bd1fefc0c7c2c4a582be625b4 Mon Sep 17 00:00:00 2001 From: Aleksey Drobin <43707931+adrobi@users.noreply.github.com> Date: Fri, 30 Oct 2026 02:34:26 +0300 Subject: [PATCH 17/44] project: .ab1proj files for clone verification sessions Co-Authored-By: Claude Sonnet 5.5 --- chrom_core/project.py | 103 +++++++++++++++++++++++++++++++++++++++ tests/test_project.py | 109 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 212 insertions(+) create mode 100644 chrom_core/project.py create mode 100644 tests/test_project.py diff --git a/chrom_core/project.py b/chrom_core/project.py new file mode 100644 index 0000000..92561da --- /dev/null +++ b/chrom_core/project.py @@ -0,0 +1,103 @@ +"""``.ab1proj`` project files: a clone-verification session on disk.""" + +from __future__ import annotations + +import json +import os +from dataclasses import dataclass +from pathlib import Path + +from chrom_core.clones import Grouping, Region, VerifyParams + +PROJECT_VERSION = 1 + + +@dataclass +class Project: + construct_path: Path + circular: bool + region: Region | None + grouping: Grouping + params: VerifyParams + + +def _to_stored(path: Path, base: Path) -> str: + """Relative POSIX path when ``path`` is inside ``base``, else absolute.""" + absolute = Path(os.path.abspath(path)) + try: + return absolute.relative_to(base).as_posix() + except ValueError: + return str(absolute) + + +def _from_stored(text: str, base: Path) -> Path: + p = Path(text) + return p if p.is_absolute() else base / p + + +def save_project(path: Path, project: Project) -> None: + path = Path(path) + base = Path(os.path.abspath(path.parent)) + grouping = project.grouping.to_dict() + for r in grouping["reads"]: + r["path"] = _to_stored(Path(r["path"]), base) + grouping["unassigned"] = [ + _to_stored(Path(p), base) for p in grouping["unassigned"] + ] + p = project.params + payload = { + "app": "ab1kit", + "version": PROJECT_VERSION, + "construct_path": _to_stored(project.construct_path, base), + "circular": project.circular, + "region": list(project.region) if project.region is not None else None, + "grouping": grouping, + "params": { + "min_q": p.min_q, + "het_ratio": p.het_ratio, + "mixed_min_positions": p.mixed_min_positions, + }, + } + path.write_text(json.dumps(payload, ensure_ascii=False, indent=2), encoding="utf-8") + + +def load_project(path: Path) -> Project: + path = Path(path) + try: + data = json.loads(path.read_text(encoding="utf-8")) + except json.JSONDecodeError as e: + raise ValueError(f"Project file is not valid JSON: {path} ({e})") from e + except (OSError, UnicodeDecodeError) as e: + raise ValueError(f"Cannot read project file: {path} ({e})") from e + if not isinstance(data, dict) or data.get("app") != "ab1kit": + raise ValueError(f"Not an ab1kit project file: {path}") + version = data.get("version") + if not isinstance(version, int) or version > PROJECT_VERSION: + raise ValueError( + f"Unsupported project version {version!r} (this ab1kit supports " + f"up to version {PROJECT_VERSION}): {path}" + ) + base = Path(os.path.abspath(path.parent)) + try: + grouping = Grouping.from_dict( + { + "reads": [ + {**r, "path": str(_from_stored(r["path"], base))} + for r in data["grouping"].get("reads", []) + ], + "unassigned": [ + str(_from_stored(p, base)) + for p in data["grouping"].get("unassigned", []) + ], + } + ) + region = data["region"] + return Project( + construct_path=_from_stored(data["construct_path"], base), + circular=bool(data["circular"]), + region=(int(region[0]), int(region[1])) if region is not None else None, + grouping=grouping, + params=VerifyParams(**data["params"]), + ) + except (KeyError, TypeError, ValueError, IndexError) as e: + raise ValueError(f"Project file is incomplete or damaged: {path} ({e!r})") from e diff --git a/tests/test_project.py b/tests/test_project.py new file mode 100644 index 0000000..8e8a680 --- /dev/null +++ b/tests/test_project.py @@ -0,0 +1,109 @@ +import json +import shutil +from pathlib import Path + +import pytest + +from chrom_core.clones import Grouping, ReadRef, VerifyParams +from chrom_core.project import PROJECT_VERSION, Project, load_project, save_project + + +def _make(folder: Path, outside: Path | None = None) -> Project: + reads = [ + ReadRef(folder / "reads" / "c1_F.ab1", "c1", "F"), + ReadRef(folder / "reads" / "c1_R.ab1", "c1", "R"), + ] + unassigned = [folder / "x.ab1"] + if outside is not None: + reads.append(ReadRef(outside / "far.ab1", "c2", "F")) + return Project( + construct_path=folder / "plasmid.gb", + circular=True, + region=(900, 100), + grouping=Grouping(reads=reads, unassigned=unassigned), + params=VerifyParams(min_q=25, het_ratio=0.3, mixed_min_positions=4), + ) + + +def test_round_trip(tmp_path): + proj = _make(tmp_path, outside=tmp_path.parent / "elsewhere") + f = tmp_path / "s.ab1proj" + save_project(f, proj) + assert load_project(f) == proj + + +def test_whole_construct_region_none(tmp_path): + proj = _make(tmp_path) + proj.region = None + f = tmp_path / "s.ab1proj" + save_project(f, proj) + assert load_project(f).region is None + + +def test_paths_relative_and_posix_inside_folder(tmp_path): + outside = tmp_path.parent / "elsewhere" + f = tmp_path / "s.ab1proj" + save_project(f, _make(tmp_path, outside)) + data = json.loads(f.read_text(encoding="utf-8")) + assert data["app"] == "ab1kit" + assert data["version"] == PROJECT_VERSION + assert data["construct_path"] == "plasmid.gb" + paths = [r["path"] for r in data["grouping"]["reads"]] + assert paths[0] == "reads/c1_F.ab1" + assert Path(paths[2]).is_absolute() + + +def test_moved_folder_still_resolves(tmp_path): + src = tmp_path / "a" + src.mkdir() + save_project(src / "s.ab1proj", _make(src)) + dst = tmp_path / "b" / "moved" + dst.parent.mkdir() + shutil.move(str(src), str(dst)) + loaded = load_project(dst / "s.ab1proj") + assert loaded == _make(dst) + + +def test_cyrillic_folder_with_space(tmp_path): + folder = tmp_path / "Данные" / "клоны 1" + folder.mkdir(parents=True) + f = folder / "проект.ab1proj" + proj = _make(folder) + save_project(f, proj) + assert "Данные" not in f.read_text(encoding="utf-8") + assert load_project(f) == proj + moved = tmp_path / "Другие данные" / "клоны 1" + moved.parent.mkdir() + shutil.move(str(folder), str(moved)) + assert load_project(moved / "проект.ab1proj") == _make(moved) + + +def test_corrupt_json(tmp_path): + f = tmp_path / "s.ab1proj" + f.write_text("{not json", encoding="utf-8") + with pytest.raises(ValueError, match="JSON"): + load_project(f) + + +def test_foreign_file(tmp_path): + f = tmp_path / "s.ab1proj" + f.write_text(json.dumps({"app": "other", "version": 1}), encoding="utf-8") + with pytest.raises(ValueError, match="ab1kit"): + load_project(f) + + +def test_future_version(tmp_path): + f = tmp_path / "s.ab1proj" + f.write_text( + json.dumps({"app": "ab1kit", "version": PROJECT_VERSION + 1}), + encoding="utf-8", + ) + with pytest.raises(ValueError, match="version"): + load_project(f) + + +def test_missing_fields(tmp_path): + f = tmp_path / "s.ab1proj" + f.write_text(json.dumps({"app": "ab1kit", "version": 1}), encoding="utf-8") + with pytest.raises(ValueError): + load_project(f) From e4387772fd78f122249fee90207234046102ca2c Mon Sep 17 00:00:00 2001 From: Aleksey Drobin <43707931+adrobi@users.noreply.github.com> Date: Fri, 30 Oct 2026 10:01:19 +0300 Subject: [PATCH 18/44] ui: background tasks with progress and cancel Co-Authored-By: Claude Sonnet 5.5 --- i18n.py | 3 + tests/test_smoke_gui.py | 11 +++ tests/test_ui_tasks.py | 163 ++++++++++++++++++++++++++++++++++++++++ translations_en.py | 3 + ui/main_window.py | 93 +++++++++++++++++++++-- ui/tasks.py | 99 ++++++++++++++++++++++++ 6 files changed, 364 insertions(+), 8 deletions(-) create mode 100644 tests/test_ui_tasks.py create mode 100644 ui/tasks.py diff --git a/i18n.py b/i18n.py index da3cba2..240a1bc 100644 --- a/i18n.py +++ b/i18n.py @@ -154,6 +154,9 @@ "batch.col.q20": "Q≥20", "batch.col.trim": "После обрезки", "batch.col.status": "Статус", + "task.cancel": "Отмена", + "task.running": "Выполняется…", + "task.cancelled": "Операция отменена", "batch.scan_done": "Просканировано файлов: {n}", "batch.exported": "Экспортировано: {n}, ошибок: {err}", "batch.export_dir": "Куда экспортировать", diff --git a/tests/test_smoke_gui.py b/tests/test_smoke_gui.py index 11a5155..a7772f2 100644 --- a/tests/test_smoke_gui.py +++ b/tests/test_smoke_gui.py @@ -29,6 +29,16 @@ def no_config_writes(monkeypatch, tmp_path): monkeypatch.setattr(sessions, "session_path", lambda _p: tmp_path / "session.json") +def _wait_for(app, predicate, timeout=5.0): + import time + + deadline = time.monotonic() + timeout + while not predicate() and time.monotonic() < deadline: + app.processEvents() + time.sleep(0.005) + assert predicate() + + def test_entry_point_importable(): from chrom_cli import main from ui.main_window import MainWindow, run @@ -156,6 +166,7 @@ def test_batch_panel_flow(qapp, monkeypatch, tmp_path): window = MainWindow(AppConfig(recent_files=[])) window.show() window._scan_folder(EXAMPLES) + _wait_for(qapp, lambda: window.batch_panel.table.rowCount() > 0) assert window.batch_dock.isVisible() assert window.batch_panel.table.rowCount() == len(AB1) diff --git a/tests/test_ui_tasks.py b/tests/test_ui_tasks.py new file mode 100644 index 0000000..c4ac2b7 --- /dev/null +++ b/tests/test_ui_tasks.py @@ -0,0 +1,163 @@ +"""Background task runner tests (offscreen, no pytest-qt).""" + +import os + +os.environ.setdefault("QT_QPA_PLATFORM", "offscreen") + +import time +from concurrent.futures import CancelledError + +from pathlib import Path + +import pytest + +AB1 = sorted((Path(__file__).resolve().parent.parent / "examples").glob("*.ab1")) + + +@pytest.fixture(scope="module") +def qapp(): + from PySide6.QtWidgets import QApplication + + return QApplication.instance() or QApplication([]) + + +@pytest.fixture() +def parent(qapp): + from PySide6.QtCore import QObject + + return QObject() + + +def _wait(qapp, predicate, timeout=5.0): + deadline = time.monotonic() + timeout + while not predicate() and time.monotonic() < deadline: + qapp.processEvents() + time.sleep(0.005) + return predicate() + + +def _collect(task): + events = [] + task.finished.connect(lambda v: events.append(("finished", v))) + task.failed.connect(lambda m: events.append(("failed", m))) + task.cancelled.connect(lambda: events.append(("cancelled", None))) + task.progress.connect(lambda d, t: events.append(("progress", (d, t)))) + return events + + +def test_result_delivered_in_finished(qapp, parent): + from PySide6.QtCore import QObject + + from ui.tasks import run_task + + task = run_task(lambda progress, is_cancelled: (progress(1, 2), 42)[1], parent) + events = _collect(task) + assert _wait(qapp, lambda: any(e[0] == "finished" for e in events)) + assert ("finished", 42) in events + assert ("progress", (1, 2)) in events + + +def test_exception_goes_to_failed(qapp, parent): + from PySide6.QtCore import QObject + + from ui.tasks import run_task + + def boom(progress, is_cancelled): + raise ValueError("bad thing") + + task = run_task(boom, parent) + events = _collect(task) + assert _wait(qapp, lambda: bool(events)) + assert events == [("failed", "bad thing")] + + +def test_cancel_emits_cancelled_and_drops_result(qapp, parent): + from PySide6.QtCore import QObject + + from ui.tasks import run_task + + def loop(progress, is_cancelled): + for _ in range(500): + if is_cancelled(): + raise CancelledError() + time.sleep(0.01) + return "late" + + task = run_task(loop, parent) + events = _collect(task) + task.cancel() + assert task.is_cancelled() + assert _wait(qapp, lambda: bool(events)) + assert events == [("cancelled", None)] + + +def test_cancel_drops_late_result_of_uninterruptible_fn(qapp, parent): + from PySide6.QtCore import QObject + + from ui.tasks import run_task + + task = run_task(lambda p, c: (time.sleep(0.2), "late")[1], parent) + events = _collect(task) + task.cancel() + assert _wait(qapp, lambda: bool(events)) + assert events == [("cancelled", None)] + + +def test_gui_thread_not_blocked(qapp, parent): + from PySide6.QtCore import QObject, QTimer + + from ui.tasks import run_task + + ticks = [] + timer = QTimer() + timer.timeout.connect(lambda: ticks.append(1)) + timer.start(20) + task = run_task(lambda p, c: (time.sleep(0.3), "ok")[1], parent) + events = _collect(task) + assert _wait(qapp, lambda: bool(events)) + timer.stop() + assert events == [("finished", "ok")] + assert len(ticks) >= 5 + + +def test_signals_delivered_in_gui_thread(qapp, parent): + from PySide6.QtCore import QObject, QThread + + from ui.tasks import run_task + + threads = [] + task = run_task(lambda p, c: 1, parent) + task.finished.connect(lambda v: threads.append(QThread.currentThread())) + assert _wait(qapp, lambda: bool(threads)) + assert threads[0] is qapp.thread() + + +@pytest.mark.skipif(not AB1, reason="no example .ab1 files") +def test_main_window_blast_uses_task_and_cancel_drops_result(qapp, monkeypatch, tmp_path): + from chrom_core import blast + from chrom_core.config import AppConfig + from ui.main_window import MainWindow + + monkeypatch.setattr("ui.main_window.save_config", lambda *a, **k: None) + opened = [] + monkeypatch.setattr( + "ui.main_window.QDesktopServices.openUrl", lambda url: opened.append(url) + ) + monkeypatch.setattr(blast, "submit", lambda params, timeout=20: (time.sleep(0.2), "RID1")[1]) + window = MainWindow(AppConfig(recent_files=[])) + window.show() + assert window.open_path(AB1[0]) + window._blast_submit() + assert window.task_cancel_button.isVisible() + assert window.task_progress.isVisible() + assert _wait(qapp, lambda: bool(opened)) + assert _wait(qapp, lambda: not window.task_progress.isVisible()) + + opened.clear() + window._blast_submit() + window.task_cancel_button.click() + assert _wait(qapp, lambda: not window.task_progress.isVisible()) + time.sleep(0.3) + qapp.processEvents() + assert opened == [] + window.close() diff --git a/translations_en.py b/translations_en.py index 1515770..a6ec709 100644 --- a/translations_en.py +++ b/translations_en.py @@ -147,6 +147,9 @@ "batch.col.q20": "Q≥20", "batch.col.trim": "After trim", "batch.col.status": "Status", + "task.cancel": "Cancel", + "task.running": "Working…", + "task.cancelled": "Operation cancelled", "batch.scan_done": "Scanned files: {n}", "batch.exported": "Exported: {n}, errors: {err}", "batch.export_dir": "Export to folder", diff --git a/ui/main_window.py b/ui/main_window.py index bd38279..c5b4526 100644 --- a/ui/main_window.py +++ b/ui/main_window.py @@ -22,6 +22,7 @@ QMainWindow, QMenu, QMessageBox, + QProgressBar, QPushButton, QScrollBar, QSpinBox, @@ -46,6 +47,7 @@ from ui.batch_panel import BatchPanel from ui.chrom_view import ChromatogramWidget from ui.minimap import MiniMap +from ui.tasks import Task, run_task from ui.theme import app_qss, theme as palette try: @@ -185,8 +187,63 @@ def __init__(self, config: AppConfig | None = None) -> None: self.setAcceptDrops(True) self.set_theme(self.config.theme) self.statusBar().showMessage(tr("status.ready")) + self._build_task_status() self._fill_recent_menu() + # ------------------------------------------------------------------ tasks + def _build_task_status(self) -> None: + self._active_tasks: set[Task] = set() + self.task_progress = QProgressBar() + self.task_progress.setMaximumWidth(180) + self.task_progress.setFormat(tr("task.running")) + self.task_cancel_button = QPushButton(tr("task.cancel")) + self.task_cancel_button.clicked.connect(self._cancel_tasks) + for widget in (self.task_progress, self.task_cancel_button): + self.statusBar().addPermanentWidget(widget) + widget.hide() + + def _cancel_tasks(self) -> None: + for task in list(self._active_tasks): + task.cancel() + + def _start_task(self, fn, on_finished, error_title: str) -> Task: + """Run ``fn`` in the background; ``on_finished(result)`` runs in the GUI + thread unless the task was cancelled or failed.""" + task = run_task(fn, self) + self._active_tasks.add(task) + self.task_progress.setRange(0, 0) # busy until progress arrives + self.task_progress.show() + self.task_cancel_button.show() + + def release() -> None: + self._active_tasks.discard(task) + if not self._active_tasks: + self.task_progress.hide() + self.task_cancel_button.hide() + + def on_progress(done: int, total: int) -> None: + if total > 0: + self.task_progress.setRange(0, total) + self.task_progress.setValue(done) + + def on_failed(message: str) -> None: + release() + QMessageBox.warning(self, error_title, message) + + def on_cancelled() -> None: + release() + self.statusBar().showMessage(tr("task.cancelled"), 5000) + + def on_done(result: object) -> None: + release() + on_finished(result) + + task.progress.connect(on_progress) + task.failed.connect(on_failed) + task.cancelled.connect(on_cancelled) + task.finished.connect(on_done) + return task + # ------------------------------------------------------------------ setup def _build_toolbar(self) -> None: bar = QToolBar() @@ -673,12 +730,21 @@ def _blast_submit(self) -> None: return seq = "".join(self.read_model.seq) try: - rid = blast_api.submit(blast_api.build_request(seq)) + params = blast_api.build_request(seq) except (OSError, RuntimeError, ValueError) as exc: QMessageBox.warning(self, tr("menu.analysis.blast"), str(exc)) return - QDesktopServices.openUrl(QUrl(blast_api.result_url(rid))) - self.statusBar().showMessage(tr("blast.sent", rid=rid), 10000) + + def done(rid: object) -> None: + QDesktopServices.openUrl(QUrl(blast_api.result_url(str(rid)))) + self.statusBar().showMessage(tr("blast.sent", rid=rid), 10000) + + # urllib cannot be interrupted: on cancel the late RID is dropped. + self._start_task( + lambda progress, is_cancelled: blast_api.submit(params, timeout=20), + done, + tr("menu.analysis.blast"), + ) def _switch_language(self, code: str) -> None: self.config.language = code @@ -812,12 +878,23 @@ def _open_folder_dialog(self) -> None: self._scan_folder(Path(folder)) def _scan_folder(self, folder: Path) -> None: - self.batch_reports = batch.scan_folder( - folder, self.config.trim_window, self.config.trim_min_q + window, min_q = self.config.trim_window, self.config.trim_min_q + + def done(reports: object) -> None: + self.batch_reports = reports # type: ignore[assignment] + self.batch_panel.show_reports(self.batch_reports) + self.batch_dock.show() + self.statusBar().showMessage( + tr("batch.scan_done", n=len(self.batch_reports)), 5000 + ) + + # scan_folder reports no progress and is not interruptible: on cancel + # its late result is dropped and the table stays as it was. + self._start_task( + lambda progress, is_cancelled: batch.scan_folder(folder, window, min_q), + done, + tr("menu.file.open_folder"), ) - self.batch_panel.show_reports(self.batch_reports) - self.batch_dock.show() - self.statusBar().showMessage(tr("batch.scan_done", n=len(self.batch_reports)), 5000) def _batch_export(self) -> None: if not self.batch_reports: diff --git a/ui/tasks.py b/ui/tasks.py new file mode 100644 index 0000000..8e3b8fe --- /dev/null +++ b/ui/tasks.py @@ -0,0 +1,99 @@ +"""Background tasks: run a function in the global thread pool with progress, +cancellation and GUI-thread signal delivery.""" + +from __future__ import annotations + +from collections.abc import Callable +from concurrent.futures import CancelledError +import threading + +from PySide6.QtCore import QObject, QRunnable, QThreadPool, Signal, Slot + +ProgressFn = Callable[[int, int], None] +CancelFn = Callable[[], bool] +TaskFn = Callable[[ProgressFn, CancelFn], object] + +# Strong references to running tasks (and, through them, their runnables) so +# they are not garbage-collected mid-run. +_running: set[Task] = set() + + +class Task(QObject): + """Handle of a background task. Public signals are emitted in the GUI thread. + + Exactly one of ``finished`` / ``failed`` / ``cancelled`` is emitted. After + ``cancel()`` the task always ends with ``cancelled``: a result that arrives + late (an uninterruptible call such as urllib) is dropped. + """ + + progress = Signal(int, int) + finished = Signal(object) + failed = Signal(str) + cancelled = Signal() + + # Worker -> GUI hand-off. Connected to a slot of this QObject (which lives + # in the GUI thread), so emission from the worker is queued. + _event = Signal(str, object) + + def __init__(self, fn: TaskFn, parent: QObject | None = None) -> None: + super().__init__(parent) + self._fn = fn + self._cancel_event = threading.Event() + self._done = False + self._event.connect(self._dispatch) + self._runnable = _Runnable(self) + + def cancel(self) -> None: + self._cancel_event.set() + + def is_cancelled(self) -> bool: + return self._cancel_event.is_set() + + def _start(self) -> None: + _running.add(self) + QThreadPool.globalInstance().start(self._runnable) + + @Slot(str, object) + def _dispatch(self, kind: str, payload: object) -> None: + if self._done: + return + if kind == "progress": + if not self.is_cancelled(): + self.progress.emit(*payload) # type: ignore[misc] + return + self._done = True + _running.discard(self) + if kind == "cancelled" or self.is_cancelled(): + self.cancelled.emit() + elif kind == "failed": + self.failed.emit(str(payload)) + else: + self.finished.emit(payload) + + +class _Runnable(QRunnable): + def __init__(self, task: Task) -> None: + super().__init__() + self.setAutoDelete(False) + self._task = task + + def run(self) -> None: + task = self._task + try: + result = task._fn( + lambda done, total: task._event.emit("progress", (int(done), int(total))), + task.is_cancelled, + ) + except CancelledError: + task._event.emit("cancelled", None) + except Exception as exc: # noqa: BLE001 - reported through ``failed`` + task._event.emit("failed", str(exc)) + else: + task._event.emit("finished", result) + + +def run_task(fn: TaskFn, parent: QObject) -> Task: + """Run ``fn(progress, is_cancelled)`` in the global thread pool.""" + task = Task(fn, parent) + task._start() + return task From 2fdde1bcacbd590b64fdd1cdcbf3206cc04e6ca3 Mon Sep 17 00:00:00 2001 From: Aleksey Drobin <43707931+adrobi@users.noreply.github.com> Date: Fri, 30 Oct 2026 10:04:15 +0300 Subject: [PATCH 19/44] ui: tasks cancel on close, last-start-wins per key, safe on destroyed parent Co-Authored-By: Claude Sonnet 5.5 --- tests/test_ui_tasks.py | 99 +++++++++++++++++++++++++++++++++++++----- ui/main_window.py | 15 ++++++- ui/tasks.py | 26 ++++++++--- 3 files changed, 122 insertions(+), 18 deletions(-) diff --git a/tests/test_ui_tasks.py b/tests/test_ui_tasks.py index c4ac2b7..2596fba 100644 --- a/tests/test_ui_tasks.py +++ b/tests/test_ui_tasks.py @@ -46,8 +46,6 @@ def _collect(task): def test_result_delivered_in_finished(qapp, parent): - from PySide6.QtCore import QObject - from ui.tasks import run_task task = run_task(lambda progress, is_cancelled: (progress(1, 2), 42)[1], parent) @@ -58,8 +56,6 @@ def test_result_delivered_in_finished(qapp, parent): def test_exception_goes_to_failed(qapp, parent): - from PySide6.QtCore import QObject - from ui.tasks import run_task def boom(progress, is_cancelled): @@ -72,8 +68,6 @@ def boom(progress, is_cancelled): def test_cancel_emits_cancelled_and_drops_result(qapp, parent): - from PySide6.QtCore import QObject - from ui.tasks import run_task def loop(progress, is_cancelled): @@ -87,13 +81,12 @@ def loop(progress, is_cancelled): events = _collect(task) task.cancel() assert task.is_cancelled() + assert events == [("cancelled", None)] # emitted immediately assert _wait(qapp, lambda: bool(events)) assert events == [("cancelled", None)] def test_cancel_drops_late_result_of_uninterruptible_fn(qapp, parent): - from PySide6.QtCore import QObject - from ui.tasks import run_task task = run_task(lambda p, c: (time.sleep(0.2), "late")[1], parent) @@ -104,7 +97,7 @@ def test_cancel_drops_late_result_of_uninterruptible_fn(qapp, parent): def test_gui_thread_not_blocked(qapp, parent): - from PySide6.QtCore import QObject, QTimer + from PySide6.QtCore import QTimer from ui.tasks import run_task @@ -121,7 +114,7 @@ def test_gui_thread_not_blocked(qapp, parent): def test_signals_delivered_in_gui_thread(qapp, parent): - from PySide6.QtCore import QObject, QThread + from PySide6.QtCore import QThread from ui.tasks import run_task @@ -161,3 +154,89 @@ def test_main_window_blast_uses_task_and_cancel_drops_result(qapp, monkeypatch, qapp.processEvents() assert opened == [] window.close() + + +def test_base_exception_still_terminal(qapp, parent): + from ui.tasks import run_task + + def bail(progress, is_cancelled): + raise KeyboardInterrupt() + + task = run_task(bail, parent) + events = _collect(task) + assert _wait(qapp, lambda: bool(events)) + assert events == [("failed", "KeyboardInterrupt")] + + +def test_parent_deleted_mid_run_is_clean(qapp, capfd): + import shiboken6 + from PySide6.QtCore import QObject + + from ui import tasks + from ui.tasks import run_task + + def slow(progress, is_cancelled): + time.sleep(0.2) + progress(1, 2) + raise RuntimeError("after delete") + + parent = QObject() + run_task(slow, parent) + shiboken6.delete(parent) + assert _wait(qapp, lambda: not tasks._running) + time.sleep(0.05) + assert "Traceback" not in capfd.readouterr().err + assert not tasks._running + + +@pytest.mark.skipif(not AB1, reason="no example .ab1 files") +def test_scan_last_start_wins(qapp, monkeypatch, tmp_path): + from chrom_core import batch + from chrom_core.config import AppConfig + from ui.main_window import MainWindow + + monkeypatch.setattr("ui.main_window.save_config", lambda *a, **k: None) + real = batch.scan_folder + + def fake(folder, *a, **k): + if folder.name == "slow": + time.sleep(0.4) + return real(folder.parent, *a, **k)[:1] + return real(folder.parent, *a, **k)[:2] + + monkeypatch.setattr(batch, "scan_folder", fake) + window = MainWindow(AppConfig(recent_files=[])) + window.show() + ex = AB1[0].parent + window._scan_folder(ex / "slow") + window._scan_folder(ex / "fast") + assert _wait(qapp, lambda: window.batch_panel.table.rowCount() == min(2, len(AB1))) + time.sleep(0.6) + qapp.processEvents() + assert window.batch_panel.table.rowCount() == min(2, len(AB1)) + assert not window.task_progress.isVisible() + window.close() + + +@pytest.mark.skipif(not AB1, reason="no example .ab1 files") +def test_second_blast_cancels_first(qapp, monkeypatch): + from chrom_core import blast + from chrom_core.config import AppConfig + from ui.main_window import MainWindow + + monkeypatch.setattr("ui.main_window.save_config", lambda *a, **k: None) + opened = [] + monkeypatch.setattr( + "ui.main_window.QDesktopServices.openUrl", lambda url: opened.append(url.toString()) + ) + rids = iter(["FIRST", "SECOND"]) + monkeypatch.setattr(blast, "submit", lambda params, timeout=20: (time.sleep(0.2), next(rids))[1]) + window = MainWindow(AppConfig(recent_files=[])) + assert window.open_path(AB1[0]) + window._blast_submit() + window._blast_submit() + assert _wait(qapp, lambda: bool(opened)) + time.sleep(0.4) + qapp.processEvents() + assert len(opened) == 1 + window.close() diff --git a/ui/main_window.py b/ui/main_window.py index c5b4526..ad1a540 100644 --- a/ui/main_window.py +++ b/ui/main_window.py @@ -193,6 +193,7 @@ def __init__(self, config: AppConfig | None = None) -> None: # ------------------------------------------------------------------ tasks def _build_task_status(self) -> None: self._active_tasks: set[Task] = set() + self._keyed_tasks: dict[str, Task] = {} self.task_progress = QProgressBar() self.task_progress.setMaximumWidth(180) self.task_progress.setFormat(tr("task.running")) @@ -206,10 +207,15 @@ def _cancel_tasks(self) -> None: for task in list(self._active_tasks): task.cancel() - def _start_task(self, fn, on_finished, error_title: str) -> Task: + def _start_task(self, fn, on_finished, error_title: str, key: str = "") -> Task: """Run ``fn`` in the background; ``on_finished(result)`` runs in the GUI - thread unless the task was cancelled or failed.""" + thread unless the task was cancelled or failed. A new task with the + same ``key`` cancels the previous one (last start wins).""" + if key and key in self._keyed_tasks: + self._keyed_tasks.pop(key).cancel() task = run_task(fn, self) + if key: + self._keyed_tasks[key] = task self._active_tasks.add(task) self.task_progress.setRange(0, 0) # busy until progress arrives self.task_progress.show() @@ -217,6 +223,8 @@ def _start_task(self, fn, on_finished, error_title: str) -> Task: def release() -> None: self._active_tasks.discard(task) + if key and self._keyed_tasks.get(key) is task: + del self._keyed_tasks[key] if not self._active_tasks: self.task_progress.hide() self.task_cancel_button.hide() @@ -744,6 +752,7 @@ def done(rid: object) -> None: lambda progress, is_cancelled: blast_api.submit(params, timeout=20), done, tr("menu.analysis.blast"), + key="blast", ) def _switch_language(self, code: str) -> None: @@ -894,6 +903,7 @@ def done(reports: object) -> None: lambda progress, is_cancelled: batch.scan_folder(folder, window, min_q), done, tr("menu.file.open_folder"), + key="scan", ) def _batch_export(self) -> None: @@ -1236,6 +1246,7 @@ def _save_session(self) -> None: self.statusBar().showMessage(tr("session.saved"), 3000) def closeEvent(self, event) -> None: # noqa: N802 + self._cancel_tasks() if self.read_model is not None and self._path is not None: sidecar = sessions.session_path(self._path) try: diff --git a/ui/tasks.py b/ui/tasks.py index 8e3b8fe..78630fb 100644 --- a/ui/tasks.py +++ b/ui/tasks.py @@ -44,7 +44,13 @@ def __init__(self, fn: TaskFn, parent: QObject | None = None) -> None: self._runnable = _Runnable(self) def cancel(self) -> None: + """Request cancellation (call from the GUI thread). ``cancelled`` is + emitted at once; whatever the worker produces later is ignored.""" self._cancel_event.set() + if not self._done: + self._done = True + _running.discard(self) + self.cancelled.emit() def is_cancelled(self) -> bool: return self._cancel_event.is_set() @@ -63,7 +69,7 @@ def _dispatch(self, kind: str, payload: object) -> None: return self._done = True _running.discard(self) - if kind == "cancelled" or self.is_cancelled(): + if kind == "cancelled": self.cancelled.emit() elif kind == "failed": self.failed.emit(str(payload)) @@ -79,17 +85,25 @@ def __init__(self, task: Task) -> None: def run(self) -> None: task = self._task + def emit(kind: str, payload: object) -> None: + try: + task._event.emit(kind, payload) + except RuntimeError: # Task was destroyed with its parent + _running.discard(task) + try: result = task._fn( - lambda done, total: task._event.emit("progress", (int(done), int(total))), + lambda done, total: emit("progress", (int(done), int(total))), task.is_cancelled, ) except CancelledError: - task._event.emit("cancelled", None) - except Exception as exc: # noqa: BLE001 - reported through ``failed`` - task._event.emit("failed", str(exc)) + emit("cancelled", None) + except BaseException as exc: # noqa: BLE001 - reported through ``failed`` + emit("failed", str(exc) or type(exc).__name__) else: - task._event.emit("finished", result) + emit("finished", result) + finally: + _running.discard(task) def run_task(fn: TaskFn, parent: QObject) -> Task: From df1f57ceddb1b058847817992404acc8250673b3 Mon Sep 17 00:00:00 2001 From: Aleksey Drobin <43707931+adrobi@users.noreply.github.com> Date: Fri, 30 Oct 2026 10:12:09 +0300 Subject: [PATCH 20/44] ui: split main window into read_view modules (no behaviour change) Co-Authored-By: Claude Sonnet 5.5 --- ab1kit.spec | 2 +- pyproject.toml | 2 +- tests/test_smoke_gui.py | 30 +- tests/test_ui_tasks.py | 10 +- ui/main_window.py | 1123 ++--------------- ui/read_view/__init__.py | 5 + ui/read_view/analysis_dock.py | 104 ++ .../batch_dock.py} | 75 +- ui/read_view/dialogs.py | 149 +++ ui/read_view/menus.py | 115 ++ ui/read_view/read_view.py | 742 +++++++++++ ui/read_view/verify_dock.py | 87 ++ 12 files changed, 1390 insertions(+), 1054 deletions(-) create mode 100644 ui/read_view/__init__.py create mode 100644 ui/read_view/analysis_dock.py rename ui/{batch_panel.py => read_view/batch_dock.py} (59%) create mode 100644 ui/read_view/dialogs.py create mode 100644 ui/read_view/menus.py create mode 100644 ui/read_view/read_view.py create mode 100644 ui/read_view/verify_dock.py diff --git a/ab1kit.spec b/ab1kit.spec index b21c6f7..57335b5 100644 --- a/ab1kit.spec +++ b/ab1kit.spec @@ -9,7 +9,7 @@ a = Analysis( pathex=[], binaries=[], datas=[], - hiddenimports=["chrom_core", "ui", "i18n", "translations_en"], + hiddenimports=["chrom_core", "ui", "ui.read_view", "i18n", "translations_en"], hookspath=[], excludes=["tkinter", "matplotlib", "numpy.tests"], noarchive=False, diff --git a/pyproject.toml b/pyproject.toml index 03835c5..74be108 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -22,7 +22,7 @@ dev = ["pytest>=8"] ab1kit = "chrom_cli:main" [tool.setuptools] -packages = ["chrom_core", "ui"] +packages = ["chrom_core", "ui", "ui.read_view"] py-modules = ["chrom_cli", "i18n", "translations_en"] [tool.pytest.ini_options] diff --git a/tests/test_smoke_gui.py b/tests/test_smoke_gui.py index a7772f2..f6aa9dd 100644 --- a/tests/test_smoke_gui.py +++ b/tests/test_smoke_gui.py @@ -24,6 +24,7 @@ def no_config_writes(monkeypatch, tmp_path): """Keep tests away from the real config and from session sidecars next to the example files (closing a modified window autosaves one).""" monkeypatch.setattr("ui.main_window.save_config", lambda *a, **k: None) + monkeypatch.setattr("ui.read_view.read_view.save_config", lambda *a, **k: None) from chrom_core import sessions monkeypatch.setattr(sessions, "session_path", lambda _p: tmp_path / "session.json") @@ -78,7 +79,7 @@ def test_open_broken_file_shows_error(qapp, monkeypatch): shown = {} monkeypatch.setattr( - "ui.main_window.QMessageBox.critical", + "ui.read_view.read_view.QMessageBox.critical", lambda *a, **k: shown.setdefault("called", True), ) window = MainWindow(AppConfig(recent_files=[])) @@ -131,7 +132,7 @@ def test_trim_dialog_wiring(qapp, monkeypatch): warned = {} monkeypatch.setattr( - "ui.main_window.QMessageBox.warning", + "ui.read_view.read_view.QMessageBox.warning", lambda *a, **k: warned.setdefault("called", True), ) sample = next(p for p in AB1 if "3730" in p.name) # high-quality read @@ -160,7 +161,7 @@ def test_batch_panel_flow(qapp, monkeypatch, tmp_path): from ui.main_window import MainWindow monkeypatch.setattr( - "ui.main_window.QFileDialog.getExistingDirectory", + "ui.read_view.read_view.QFileDialog.getExistingDirectory", lambda *a, **k: str(tmp_path / "export"), ) window = MainWindow(AppConfig(recent_files=[])) @@ -216,7 +217,7 @@ def test_reference_alignment_flow(qapp, monkeypatch, tmp_path): out = tmp_path / "aligned.fasta" monkeypatch.setattr( - "ui.main_window.QFileDialog.getSaveFileName", + "ui.read_view.read_view.QFileDialog.getSaveFileName", lambda *a, **k: (str(out), "FASTA (*.fasta)"), ) window._export_aligned() @@ -267,7 +268,7 @@ def test_expected_snp_verification_flow(qapp, monkeypatch, tmp_path): out = tmp_path / "report.csv" monkeypatch.setattr( - "ui.main_window.QFileDialog.getSaveFileName", + "ui.read_view.read_view.QFileDialog.getSaveFileName", lambda *a, **k: (str(out), "CSV (*.csv)"), ) window._save_verify_csv() @@ -348,3 +349,22 @@ def test_reverse_read_reference_overlay_in_displayed_orientation(qapp): if shown and ref_pos in mapping: assert int(shown) - 1 == mapping[ref_pos] window.close() + + +@pytest.mark.skipif(not AB1, reason="no example .ab1 files") +def test_read_view_emits_read_edited_on_edit_and_undo(qapp): + from chrom_core.config import AppConfig + from ui.main_window import MainWindow + + window = MainWindow(AppConfig(recent_files=[])) + emitted = [] + window.read_view.read_edited.connect(emitted.append) + assert window.read_view.open_path(AB1[0]) + assert emitted == [] # opening is not an edit + assert window.read_view.current_model() is window.read_model + + window.read_view.apply_base_change(0, "N") + assert emitted == [Path(AB1[0])] + window.read_view.undo_read() + assert emitted == [Path(AB1[0])] * 2 + window.close() diff --git a/tests/test_ui_tasks.py b/tests/test_ui_tasks.py index 2596fba..5a707b1 100644 --- a/tests/test_ui_tasks.py +++ b/tests/test_ui_tasks.py @@ -132,9 +132,11 @@ def test_main_window_blast_uses_task_and_cancel_drops_result(qapp, monkeypatch, from ui.main_window import MainWindow monkeypatch.setattr("ui.main_window.save_config", lambda *a, **k: None) + + monkeypatch.setattr("ui.read_view.read_view.save_config", lambda *a, **k: None) opened = [] monkeypatch.setattr( - "ui.main_window.QDesktopServices.openUrl", lambda url: opened.append(url) + "ui.read_view.read_view.QDesktopServices.openUrl", lambda url: opened.append(url) ) monkeypatch.setattr(blast, "submit", lambda params, timeout=20: (time.sleep(0.2), "RID1")[1]) window = MainWindow(AppConfig(recent_files=[])) @@ -196,6 +198,8 @@ def test_scan_last_start_wins(qapp, monkeypatch, tmp_path): from ui.main_window import MainWindow monkeypatch.setattr("ui.main_window.save_config", lambda *a, **k: None) + + monkeypatch.setattr("ui.read_view.read_view.save_config", lambda *a, **k: None) real = batch.scan_folder def fake(folder, *a, **k): @@ -225,9 +229,11 @@ def test_second_blast_cancels_first(qapp, monkeypatch): from ui.main_window import MainWindow monkeypatch.setattr("ui.main_window.save_config", lambda *a, **k: None) + + monkeypatch.setattr("ui.read_view.read_view.save_config", lambda *a, **k: None) opened = [] monkeypatch.setattr( - "ui.main_window.QDesktopServices.openUrl", lambda url: opened.append(url.toString()) + "ui.read_view.read_view.QDesktopServices.openUrl", lambda url: opened.append(url.toString()) ) rids = iter(["FIRST", "SECOND"]) monkeypatch.setattr(blast, "submit", lambda params, timeout=20: (time.sleep(0.2), next(rids))[1]) diff --git a/ui/main_window.py b/ui/main_window.py index ad1a540..6de6e90 100644 --- a/ui/main_window.py +++ b/ui/main_window.py @@ -1,4 +1,5 @@ -"""Main ab1kit window: toolbar, menus, overview map, chromatogram, docks.""" +"""ab1kit shell window: File/View/Help menus, language, theme, recent files, +background-task status bar. The single-read viewer lives in ``ui.read_view``.""" from __future__ import annotations @@ -6,49 +7,20 @@ from importlib.metadata import PackageNotFoundError, version as pkg_version from pathlib import Path -from PySide6.QtCore import QMarginsF, QSizeF, Qt, QUrl, Signal -from PySide6.QtGui import QAction, QColor, QDesktopServices, QDragEnterEvent, QDropEvent, QPageSize, QPainter, QPdfWriter +from PySide6.QtGui import QAction, QDragEnterEvent, QDropEvent from PySide6.QtWidgets import ( QApplication, - QCheckBox, - QDialog, - QDockWidget, - QFileDialog, - QFormLayout, - QHBoxLayout, - QInputDialog, - QLabel, - QLineEdit, QMainWindow, - QMenu, QMessageBox, QProgressBar, QPushButton, - QScrollBar, - QSpinBox, - QPlainTextEdit, - QTableWidget, - QTableWidgetItem, - QToolBar, - QVBoxLayout, - QWidget, ) -from chrom_core import Chromatogram, EditableRead, batch, read_ab1, trim_window -from chrom_core import blast as blast_api -from chrom_core import export, sessions -from chrom_core.align import ReadAlignment, align_read, gapped_sequences, parse_sequence from chrom_core.config import AppConfig, load_config, save_config -from chrom_core.editing import INSERT_LETTERS, IUPAC_LETTERS -from chrom_core.snps import call_snps -from chrom_core.verify import parse_expected, verify_expected, verdicts_csv, verdicts_xlsx -from chrom_core.seqops import find_matches, reverse_complement from i18n import set_language, tr -from ui.batch_panel import BatchPanel -from ui.chrom_view import ChromatogramWidget -from ui.minimap import MiniMap +from ui.read_view import ReadView from ui.tasks import Task, run_task -from ui.theme import app_qss, theme as palette +from ui.theme import app_qss try: VERSION = pkg_version("ab1kit") @@ -56,95 +28,31 @@ VERSION = "dev" -class SearchDialog(QDialog): - def __init__(self, parent=None) -> None: - super().__init__(parent) - self.setWindowTitle(tr("search.title")) - layout = QVBoxLayout(self) - self.edit = QLineEdit() - self.edit.setPlaceholderText(tr("search.pattern")) - self.reverse_box = QCheckBox(tr("search.reverse")) - button = QPushButton(tr("search.button")) - button.setDefault(True) - button.clicked.connect(self.accept) - layout.addWidget(self.edit) - layout.addWidget(self.reverse_box) - layout.addWidget(button) - - def pattern(self) -> str: - return self.edit.text().strip().upper() - - def want_reverse(self) -> bool: - return self.reverse_box.isChecked() - - -class TrimDialog(QDialog): - """Non-modal quality-trim dialog; preview streams into the chromatogram.""" - - region_changed = Signal(int, int) - apply_requested = Signal(int, int) - - def __init__(self, quality_fn, window: int, min_q: int, total: int, parent=None) -> None: - super().__init__(parent) - self.setWindowTitle(tr("trim.title")) - self.quality_fn = quality_fn - self.total = total - self._region = (0, total) - - layout = QVBoxLayout(self) - form = QFormLayout() - self.window_spin = QSpinBox() - self.window_spin.setRange(2, 100) - self.window_spin.setValue(window) - self.minq_spin = QSpinBox() - self.minq_spin.setRange(0, 60) - self.minq_spin.setValue(min_q) - form.addRow(QLabel(tr("trim.window")), self.window_spin) - form.addRow(QLabel(tr("trim.minq")), self.minq_spin) - layout.addLayout(form) - self.preview = QLabel() - layout.addWidget(self.preview) - buttons = QWidget() - row = QVBoxLayout(buttons) - apply_button = QPushButton(tr("trim.apply")) - apply_button.setDefault(True) - apply_button.clicked.connect(self._apply) - close_button = QPushButton(tr("dialog.close")) - close_button.clicked.connect(self.close) - row.addWidget(apply_button) - row.addWidget(close_button) - layout.addWidget(buttons) - - self.window_spin.valueChanged.connect(self._recompute) - self.minq_spin.valueChanged.connect(self._recompute) - self._recompute() - - def window_value(self) -> int: - return self.window_spin.value() - - def minq_value(self) -> int: - return self.minq_spin.value() - - def _recompute(self) -> None: - start, end = trim_window(self.quality_fn(), self.window_spin.value(), self.minq_spin.value()) - self._set_region(start, end) - self.region_changed.emit(start, end) - - def _set_region(self, start: int, end: int) -> None: - self._region = (start, end) - self.preview.setText(tr("trim.preview", n=end - start, total=self.total)) - - def set_region(self, start: int, end: int) -> None: - """Sync preview when the user drags trim handles in the view.""" - self._set_region(start, end) - - def _apply(self) -> None: - start, end = self._region - self.apply_requested.emit(start, end) - self.close() +def _delegate(name: str) -> property: + """Read-only view onto ``ReadView.`` (keeps the old MainWindow API).""" + return property(lambda self: getattr(self.read_view, name)) class MainWindow(QMainWindow): + # State and widgets that used to live on the window itself. + read_model = _delegate("read_model") + chrom_view = _delegate("chrom_view") + minimap = _delegate("minimap") + trim_dialog = _delegate("trim_dialog") + reference_seq = _delegate("reference_seq") + alignment = _delegate("alignment") + snp_calls = _delegate("snp_calls") + variant_verdicts = _delegate("variant_verdicts") + batch_reports = _delegate("batch_reports") + batch_panel = _delegate("batch_panel") + batch_dock = _delegate("batch_dock") + diff_dock = _delegate("diff_dock") + diff_table = _delegate("diff_table") + verify_dock = _delegate("verify_dock") + verify_table = _delegate("verify_table") + undo_action = _delegate("undo_action") + redo_action = _delegate("redo_action") + def __init__(self, config: AppConfig | None = None) -> None: super().__init__() self.config = config or load_config() @@ -152,38 +60,13 @@ def __init__(self, config: AppConfig | None = None) -> None: self.setWindowTitle("ab1kit") self.resize(1200, 780) - self._path: Path | None = None - self.read_model: EditableRead | None = None - self.trim_dialog: TrimDialog | None = None - self.batch_reports: list[batch.FileReport] = [] - self.reference_seq: str = "" - self.alignment: ReadAlignment | None = None - self.snp_calls: list = [] - self.variant_verdicts: list = [] - self._search_ranges: list[tuple[int, int]] = [] - self._search_pos = -1 - - self.chrom_view = ChromatogramWidget() - self.minimap = MiniMap() - self.scrollbar = QScrollBar(Qt.Orientation.Horizontal) - - central = QWidget() - layout = QVBoxLayout(central) - layout.setContentsMargins(0, 0, 0, 0) - layout.setSpacing(0) - layout.addWidget(self.minimap) - layout.addWidget(self.chrom_view, 1) - layout.addWidget(self.scrollbar) - self.setCentralWidget(central) + self.read_view = ReadView(self.config, self._start_task) + self.setCentralWidget(self.read_view) + self.read_view.file_opened.connect(self._push_recent) + self.read_view.status_message.connect(self.statusBar().showMessage) + self.read_view.title_changed.connect(self.setWindowTitle) - self._channel_boxes: dict[str, QCheckBox] = {} - self._build_toolbar() - self._build_info_dock() - self._build_batch_dock() - self._build_analysis_dock() - self._build_verify_dock() self._build_menus() - self._connect() self.setAcceptDrops(True) self.set_theme(self.config.theme) self.statusBar().showMessage(tr("status.ready")) @@ -252,105 +135,28 @@ def on_done(result: object) -> None: task.finished.connect(on_done) return task - # ------------------------------------------------------------------ setup - def _build_toolbar(self) -> None: - bar = QToolBar() - bar.setMovable(False) - self.addToolBar(bar) - - def add(text: str, slot, shortcut: str | None = None) -> None: - action = QAction(text, self) - if shortcut: - action.setShortcut(shortcut) - action.triggered.connect(slot) - bar.addAction(action) - - add(tr("tb.open"), self._open_dialog) - bar.addSeparator() - add(tr("tb.zoom_in"), self.chrom_view.zoom_in, "Ctrl++") - add(tr("tb.zoom_out"), self.chrom_view.zoom_out, "Ctrl+-") - add(tr("tb.fit"), self.chrom_view.zoom_fit) - add(tr("tb.reset"), self.chrom_view.zoom_reset) - bar.addSeparator() - for base in "ACGT": - box = QCheckBox(base) - box.setChecked(True) - box.toggled.connect( - lambda on, b=base: self.chrom_view.set_visible_channel(b, on) - ) - bar.addWidget(box) - self._channel_boxes[base] = box + # ------------------------------------------------------------------ menus def _build_menus(self) -> None: file_menu = self.menuBar().addMenu(tr("menu.file")) self._file_menu = file_menu open_action = QAction(tr("menu.file.open"), self) open_action.setShortcut("Ctrl+O") - open_action.triggered.connect(self._open_dialog) + open_action.triggered.connect(self.read_view.open_dialog) file_menu.addAction(open_action) open_folder = QAction(tr("menu.file.open_folder"), self) open_folder.setShortcut("Ctrl+Shift+O") - open_folder.triggered.connect(self._open_folder_dialog) + open_folder.triggered.connect(self.read_view.open_folder_dialog) file_menu.addAction(open_folder) self.recent_menu = file_menu.addMenu(tr("menu.file.recent")) - save_session = QAction(tr("menu.file.save_session"), self) - save_session.setShortcut("Ctrl+S") - save_session.triggered.connect(self._save_session) - file_menu.addAction(save_session) - export_menu = file_menu.addMenu(tr("menu.file.export")) - for text, slot in ( - (tr("menu.file.export_fasta"), self._export_fasta), - (tr("menu.file.export_fastq"), self._export_fastq), - (tr("menu.file.export_png"), self._export_png), - (tr("menu.file.export_pdf"), self._export_pdf), - ): - action = QAction(text, self) - action.triggered.connect(slot) - export_menu.addAction(action) - file_menu.addSeparator() - copy_action = QAction(tr("menu.file.copy_seq"), self) - copy_action.setShortcut("Ctrl+Shift+C") - copy_action.triggered.connect(self._copy_sequence) - file_menu.addAction(copy_action) + self.read_view.add_file_actions(file_menu) file_menu.addSeparator() exit_action = QAction(tr("menu.file.exit"), self) exit_action.setShortcut("Ctrl+Q") exit_action.triggered.connect(self.close) file_menu.addAction(exit_action) - edit_menu = self.menuBar().addMenu(tr("menu.edit")) - self.undo_action = QAction(tr("menu.edit.undo"), self) - self.undo_action.setShortcut("Ctrl+Z") - self.undo_action.triggered.connect(self.undo_read) - self.undo_action.setEnabled(False) - edit_menu.addAction(self.undo_action) - self.redo_action = QAction(tr("menu.edit.redo"), self) - self.redo_action.setShortcut("Ctrl+Y") - self.redo_action.triggered.connect(self.redo_read) - self.redo_action.setEnabled(False) - edit_menu.addAction(self.redo_action) - edit_menu.addSeparator() - find_action = QAction(tr("menu.edit.find"), self) - find_action.setShortcut("Ctrl+F") - find_action.triggered.connect(self._search) - edit_menu.addAction(find_action) - find_next = QAction(tr("menu.edit.find_next"), self) - find_next.setShortcut("F3") - find_next.triggered.connect(self._find_next) - edit_menu.addAction(find_next) - goto_action = QAction(tr("menu.edit.goto"), self) - goto_action.setShortcut("Ctrl+G") - goto_action.triggered.connect(self._goto) - edit_menu.addAction(goto_action) - edit_menu.addSeparator() - revcomp_action = QAction(tr("menu.edit.revcomp"), self) - revcomp_action.setShortcut("Ctrl+R") - revcomp_action.triggered.connect(self.reverse_complement_read) - edit_menu.addAction(revcomp_action) - trim_action = QAction(tr("menu.edit.trim"), self) - trim_action.setShortcut("Ctrl+T") - trim_action.triggered.connect(self._open_trim_dialog) - edit_menu.addAction(trim_action) + self.read_view.add_edit_menu(self.menuBar().addMenu(tr("menu.edit"))) view_menu = self.menuBar().addMenu(tr("menu.view")) self.dark_action = QAction(tr("menu.view.dark_theme"), self) @@ -360,24 +166,7 @@ def _build_menus(self) -> None: lambda on: self.set_theme("dark" if on else "light") ) view_menu.addAction(self.dark_action) - smooth_action = QAction(tr("menu.view.smoothing"), self) - smooth_action.setCheckable(True) - smooth_action.toggled.connect(self.chrom_view.set_smoothing) - view_menu.addAction(smooth_action) - profile_action = QAction(tr("menu.view.quality_profile"), self) - profile_action.setCheckable(True) - profile_action.toggled.connect(self.minimap.set_profile) - view_menu.addAction(profile_action) - info_action = QAction(tr("menu.view.file_info"), self) - info_action.setCheckable(True) - info_action.toggled.connect(self.info_dock.setVisible) - self.info_dock.visibilityChanged.connect(info_action.setChecked) - view_menu.addAction(info_action) - batch_action = QAction(tr("menu.view.batch_panel"), self) - batch_action.setCheckable(True) - batch_action.toggled.connect(self.batch_dock.setVisible) - self.batch_dock.visibilityChanged.connect(batch_action.setChecked) - view_menu.addAction(batch_action) + self.read_view.add_view_actions(view_menu) lang_menu = view_menu.addMenu(tr("menu.view.language")) self._lang_actions = {} for code, label in (("ru", tr("lang.ru")), ("en", tr("lang.en"))): @@ -388,27 +177,7 @@ def _build_menus(self) -> None: lang_menu.addAction(action) self._lang_actions[code] = action - analysis_menu = self.menuBar().addMenu(tr("menu.analysis")) - reference_action = QAction(tr("menu.analysis.reference"), self) - reference_action.setShortcut("Ctrl+L") - reference_action.triggered.connect(self._reference_dialog) - analysis_menu.addAction(reference_action) - clear_ref = QAction(tr("menu.analysis.clear_reference"), self) - clear_ref.triggered.connect(self._clear_reference) - analysis_menu.addAction(clear_ref) - analysis_menu.addSeparator() - export_aligned = QAction(tr("menu.analysis.export_aligned"), self) - export_aligned.triggered.connect(self._export_aligned) - analysis_menu.addAction(export_aligned) - analysis_menu.addSeparator() - verify_action = QAction(tr("menu.analysis.verify"), self) - verify_action.setShortcut("Ctrl+Shift+V") - verify_action.triggered.connect(self._verify_dialog) - analysis_menu.addAction(verify_action) - analysis_menu.addSeparator() - blast_action = QAction(tr("menu.analysis.blast"), self) - blast_action.triggered.connect(self._blast_submit) - analysis_menu.addAction(blast_action) + self.read_view.add_analysis_menu(self.menuBar().addMenu(tr("menu.analysis"))) help_menu = self.menuBar().addMenu(tr("menu.help")) about_action = QAction(tr("menu.help.about"), self) @@ -417,344 +186,6 @@ def _build_menus(self) -> None: ) help_menu.addAction(about_action) - def _build_info_dock(self) -> None: - self.info_dock = QDockWidget(tr("info.title"), self) - self.info_dock.setWidget(QWidget()) - self.addDockWidget(Qt.DockWidgetArea.RightDockWidgetArea, self.info_dock) - self.info_dock.hide() - - def _build_batch_dock(self) -> None: - self.batch_dock = QDockWidget(tr("batch.title"), self) - self.batch_panel = BatchPanel() - self.batch_dock.setWidget(self.batch_panel) - self.addDockWidget(Qt.DockWidgetArea.BottomDockWidgetArea, self.batch_dock) - self.batch_dock.hide() - self.batch_panel.open_requested.connect(self.open_path) - self.batch_panel.export_button.clicked.connect(self._batch_export) - self.batch_panel.csv_button.clicked.connect(self._batch_save_csv) - - def _build_analysis_dock(self) -> None: - self.diff_dock = QDockWidget(tr("analysis.diffs.title"), self) - self.diff_table = QTableWidget(0, 8) - self.diff_table.setHorizontalHeaderLabels( - [ - tr("analysis.col.pos"), - tr("analysis.col.kind"), - tr("analysis.col.ref"), - tr("analysis.col.read"), - tr("analysis.col.readpos"), - tr("snp.col.verdict"), - tr("snp.col.q"), - tr("snp.col.ratio"), - ] - ) - self.diff_table.verticalHeader().setVisible(False) - self.diff_table.setEditTriggers(QTableWidget.EditTrigger.NoEditTriggers) - self.diff_table.setSortingEnabled(True) - self.diff_dock.setWidget(self.diff_table) - self.addDockWidget(Qt.DockWidgetArea.RightDockWidgetArea, self.diff_dock) - self.diff_dock.hide() - - def _build_verify_dock(self) -> None: - self.verify_dock = QDockWidget(tr("verify.title"), self) - self.verify_table = QTableWidget(0, 8) - self.verify_table.setHorizontalHeaderLabels( - [ - tr("verify.col.name"), - tr("verify.col.pos"), - tr("verify.col.ref"), - tr("verify.col.alt"), - tr("verify.col.verdict"), - tr("verify.col.observed"), - tr("verify.col.q"), - tr("verify.col.note"), - ] - ) - self.verify_table.verticalHeader().setVisible(False) - self.verify_table.setEditTriggers(QTableWidget.EditTrigger.NoEditTriggers) - self.verify_table.setSortingEnabled(True) - buttons = QWidget() - row = QHBoxLayout(buttons) - csv_button = QPushButton(tr("verify.save_csv")) - csv_button.clicked.connect(self._save_verify_csv) - xlsx_button = QPushButton(tr("verify.save_xlsx")) - xlsx_button.clicked.connect(self._save_verify_xlsx) - row.addWidget(csv_button) - row.addWidget(xlsx_button) - row.addStretch(1) - container = QWidget() - layout = QVBoxLayout(container) - layout.setContentsMargins(0, 0, 0, 0) - layout.addWidget(self.verify_table) - layout.addWidget(buttons) - self.verify_dock.setWidget(container) - self.addDockWidget(Qt.DockWidgetArea.BottomDockWidgetArea, self.verify_dock) - self.verify_dock.hide() - - def _connect(self) -> None: - self.chrom_view.view_changed.connect(self._sync_from_view) - self.chrom_view.cursor_info.connect(self.statusBar().showMessage) - self.chrom_view.base_clicked.connect(self._on_base_clicked) - self.minimap.request_center.connect(self.chrom_view.center_on_point) - self.scrollbar.valueChanged.connect( - lambda value: self.chrom_view.set_offset(float(value)) - ) - - # ---------------------------------------------------------------- opening - def open_path(self, path: str | Path) -> bool: - try: - chrom = read_ab1(path) - except Exception as exc: # user-facing: any parse failure becomes a dialog - QMessageBox.critical(self, tr("err.open_failed"), f"{path}:\n{exc}") - return False - self._path = Path(path) - model = EditableRead(chrom) - restored = self._try_restore_session(model) - self.read_model = model - self._search_ranges = [] - self._search_pos = -1 - self.chrom_view.set_chromatogram(model.current()) - self.chrom_view.set_edited(model.edited) - self.minimap.set_chromatogram(model.current()) - self.minimap.set_highlights([]) - self._push_recent(str(self._path)) - self._refresh_info(model.current()) - self._sync_actions() - if self.reference_seq: - self._realign() - n = len(model.seq) - mean_q = sum(model.quality) / max(1, n) - message = tr("status.file", n=n, q=mean_q) - if restored: - message += " · " + tr("session.loaded") - self.statusBar().showMessage(message, 8000) - self.setWindowTitle(f"ab1kit — {self._path.name}" + ("*" if model.modified else "")) - return True - - def _try_restore_session(self, model: EditableRead) -> bool: - sidecar = sessions.session_path(self._path) - data = sessions.load_session(sidecar) - if not data or data.get("source") != self._path.name: - return False - try: - model.restore_state(data) - except (KeyError, TypeError, ValueError): - return False - return True - - def _open_dialog(self) -> None: - path, _ = QFileDialog.getOpenFileName( - self, - tr("menu.file.open"), - str(self._path.parent) if self._path else "", - "Sanger chromatograms (*.ab1);;All files (*)", - ) - if path: - self.open_path(path) - - # --------------------------------------------------------------- analysis - def _reference_dialog(self) -> None: - dialog = QDialog(self) - dialog.setWindowTitle(tr("analysis.ref.title")) - dialog.resize(480, 240) - layout = QVBoxLayout(dialog) - edit = QPlainTextEdit() - edit.setPlaceholderText(tr("analysis.ref.paste")) - layout.addWidget(edit) - - def from_file() -> None: - path, _ = QFileDialog.getOpenFileName( - dialog, tr("analysis.ref.from_file"), "", "Sequence (*.fasta *.fa *.txt);;All files (*)" - ) - if path: - edit.setPlainText(Path(path).read_text(encoding="utf-8", errors="replace")) - - file_button = QPushButton(tr("analysis.ref.from_file")) - file_button.clicked.connect(from_file) - layout.addWidget(file_button) - - ok = QPushButton("OK") - ok.clicked.connect(dialog.accept) - cancel = QPushButton(tr("dialog.close")) - cancel.clicked.connect(dialog.reject) - row = QWidget() - row_layout = QHBoxLayout(row) - row_layout.addWidget(ok) - row_layout.addWidget(cancel) - layout.addWidget(row) - - if dialog.exec() != QDialog.DialogCode.Accepted: - return - try: - sequence = parse_sequence(edit.toPlainText()) - except ValueError as exc: - QMessageBox.warning(self, tr("analysis.ref.title"), str(exc)) - return - if not sequence: - return - self._set_reference_seq(sequence) - - def _set_reference_seq(self, sequence: str) -> None: - self.reference_seq = sequence - if self.read_model is not None: - self._realign() - else: - self.statusBar().showMessage(tr("analysis.need_read"), 5000) - - def _reference_overlay(self) -> tuple[str, dict[int, int]]: - """Reference letters and ref -> index mapping in the *displayed* read's - orientation (the alignment indexes the reverse complement on '-').""" - alignment = self.alignment - if alignment.strand == "+": - return self.reference_seq, alignment.ref_to_read - n = len(self.read_model.seq) - return ( - reverse_complement(self.reference_seq)[::-1], # complement, same ref indexing - {pos: n - 1 - idx for pos, idx in alignment.ref_to_read.items()}, - ) - - def _displayed_diff_index(self, diff) -> int | None: - """0-based index of ``diff`` in the displayed read (None for deletions).""" - if diff.read_pos is None: - return None - if self.alignment.strand == "+": - return diff.read_pos - n = len(self.read_model.seq) - span = len(diff.read_base) if diff.kind == "insertion" else 1 - return n - diff.read_pos - span - - def _clear_reference(self) -> None: - self.reference_seq = "" - self.alignment = None - self.chrom_view.set_reference(None) - self.diff_table.setRowCount(0) - self.diff_dock.hide() - - def _realign(self) -> None: - if not (self.read_model and self.reference_seq): - return - try: - self.alignment = align_read("".join(self.read_model.seq), self.reference_seq) - except ValueError as exc: - QMessageBox.warning(self, tr("analysis.ref.title"), str(exc)) - self._clear_reference() - return - letters, ref_to_read = self._reference_overlay() - self.chrom_view.set_reference(letters, ref_to_read) - chrom = self.read_model.current() - self.snp_calls = call_snps( - self.alignment, chrom, - min_q=self.config.snp_min_q, het_ratio=self.config.het_ratio, - ) - self._fill_diff_table() - self.diff_dock.setVisible(bool(self.alignment.differences)) - pct = f"{self.alignment.identity * 100:.1f}" - if self.alignment.differences: - message = tr( - "analysis.status", - n=len(self.alignment.differences), - pct=pct, - rstart=self.alignment.ref_start + 1, - rend=self.alignment.ref_end, - ) - else: - message = tr("analysis.no_diffs") - if self.snp_calls: - counts = {k: sum(1 for c in self.snp_calls if c.kind == k) - for k in ("homozygous", "heterozygous", "low_quality")} - message += " · " + tr( - "snp.summary", - homo=counts["homozygous"], - het=counts["heterozygous"], - low=counts["low_quality"], - ) - if self.alignment.alternatives > 1: - message += " · " + tr("analysis.ambiguous", n=self.alignment.alternatives) - self.statusBar().showMessage(message, 8000) - - def _fill_diff_table(self) -> None: - kind_labels = { - "substitution": tr("analysis.kind.substitution"), - "deletion": tr("analysis.kind.deletion"), - "insertion": tr("analysis.kind.insertion"), - } - verdict_labels = { - "homozygous": tr("snp.homozygous"), - "heterozygous": tr("snp.heterozygous"), - "low_quality": tr("snp.low_quality"), - } - calls_by_ref = {c.ref_pos: c for c in getattr(self, "snp_calls", [])} - diffs = self.alignment.differences if self.alignment else [] - self.diff_table.setSortingEnabled(False) - self.diff_table.setRowCount(len(diffs)) - for row, diff in enumerate(diffs): - call = calls_by_ref.get(diff.ref_pos) - verdict = "" - if call is not None: - verdict = verdict_labels.get(call.kind, call.kind) - if call.kind == "heterozygous": - verdict += f" ({call.iupac})" - values = [ - diff.ref_pos + 1, - kind_labels.get(diff.kind, diff.kind), - diff.ref_base, - diff.read_base, - (call.read_pos + 1 if call is not None - else shown + 1 if (shown := self._displayed_diff_index(diff)) is not None - else ""), - verdict, - call.quality if call is not None else "", - f"{call.ratio:.2f}" if call is not None and call.ratio is not None else "", - ] - for col, value in enumerate(values): - item = QTableWidgetItem() - item.setData(Qt.ItemDataRole.DisplayRole, value) - if call is not None and col == 5 and call.kind == "heterozygous": - item.setForeground(QColor("#a05000")) - self.diff_table.setItem(row, col, item) - self.diff_table.setSortingEnabled(True) - - def _export_aligned(self) -> None: - if not (self.alignment and self.reference_seq and self.read_model): - return - path = self._export_target( - tr("menu.analysis.export_aligned"), ".aligned.fasta", "FASTA (*.fasta)" - ) - if not path: - return - ref_aligned, read_aligned = gapped_sequences(self.alignment, self.reference_seq) - sample = self._export_id() - strand = "reverse" if self.alignment.strand == "-" else "forward" - content = ( - export.to_fasta(f"{sample}_reference[{self.alignment.ref_start + 1}-{self.alignment.ref_end}]", ref_aligned) - + export.to_fasta(f"{sample}_read_{strand}", read_aligned) - ) - export.write_text(path, content) - self.statusBar().showMessage(tr("export.done", path=path), 5000) - - # ------------------------------------------------------------------ BLAST - def _blast_submit(self) -> None: - if not self.read_model: - return - seq = "".join(self.read_model.seq) - try: - params = blast_api.build_request(seq) - except (OSError, RuntimeError, ValueError) as exc: - QMessageBox.warning(self, tr("menu.analysis.blast"), str(exc)) - return - - def done(rid: object) -> None: - QDesktopServices.openUrl(QUrl(blast_api.result_url(str(rid)))) - self.statusBar().showMessage(tr("blast.sent", rid=rid), 10000) - - # urllib cannot be interrupted: on cancel the late RID is dropped. - self._start_task( - lambda progress, is_cancelled: blast_api.submit(params, timeout=20), - done, - tr("menu.analysis.blast"), - key="blast", - ) - def _switch_language(self, code: str) -> None: self.config.language = code save_config(self.config) @@ -762,178 +193,13 @@ def _switch_language(self, code: str) -> None: action.setChecked(other == code) QMessageBox.information(self, tr("menu.view.language"), tr("lang.restart")) - # ------------------------------------------------- expected SNP verification - def _verify_dialog(self) -> None: - if not (self.read_model and self.alignment and self.reference_seq): - self.statusBar().showMessage(tr("verify.need_reference"), 6000) - return - path, _ = QFileDialog.getOpenFileName( - self, - tr("menu.analysis.verify"), - str(self._path.parent) if self._path else "", - "Variants (*.vcf *.csv *.tsv *.txt);;All files (*)", - ) - if not path: - return - try: - text = Path(path).read_text(encoding="utf-8", errors="replace") - except OSError as exc: - QMessageBox.warning(self, tr("verify.title"), str(exc)) - return - self._verify_variants(text) - - def _verify_variants(self, text: str) -> None: - try: - variants, warnings = parse_expected(text) - except ValueError as exc: - QMessageBox.warning(self, tr("verify.title"), str(exc)) - return - if not variants: - QMessageBox.warning(self, tr("verify.title"), tr("search.none")) - return - self.variant_verdicts = verify_expected( - self.alignment, - self.read_model.current(), - self.reference_seq, - variants, - min_q=self.config.snp_min_q, - het_ratio=self.config.het_ratio, - ) - self._fill_verify_table() - self.verify_dock.show() - self.chrom_view.set_snp_marks( - [(v.read_pos, v.verdict) for v in self.variant_verdicts if v.read_pos is not None] - ) - counts = {k: sum(1 for v in self.variant_verdicts if v.verdict == k) - for k in ("confirmed", "heterozygous", "not_found", "no_data")} - message = tr( - "verify.summary", - n=len(self.variant_verdicts), - confirmed=counts["confirmed"], - het=counts["heterozygous"], - notfound=counts["not_found"], - nodata=counts["no_data"], - ) - if warnings: - message += f" · {len(warnings)} ⚠" - self.statusBar().showMessage(message, 10000) - - def _fill_verify_table(self) -> None: - labels = { - "confirmed": tr("verify.confirmed"), - "heterozygous": tr("verify.heterozygous"), - "not_found": tr("verify.not_found"), - "no_data": tr("verify.no_data"), - "ref_mismatch": tr("verify.ref_mismatch"), - "low_quality": tr("verify.low_quality"), - "unsupported": tr("verify.unsupported"), - } - colors = { - "confirmed": "#1e9e1e", - "heterozygous": "#e0a000", - "not_found": "#e02020", - } - self.verify_table.setSortingEnabled(False) - self.verify_table.setRowCount(len(self.variant_verdicts)) - for row, v in enumerate(self.variant_verdicts): - values = [ - v.variant.name, - v.variant.position, - v.variant.ref, - v.variant.alt, - labels.get(v.verdict, v.verdict), - v.observed, - v.quality if v.quality is not None else "", - tr(f"verify.note.{v.note_code}", **v.note_args) if v.note_code else v.note, - ] - for col, value in enumerate(values): - item = QTableWidgetItem() - item.setData(Qt.ItemDataRole.DisplayRole, value) - if col == 4 and v.verdict in colors: - item.setForeground(QColor(colors[v.verdict])) - self.verify_table.setItem(row, col, item) - self.verify_table.setSortingEnabled(True) - - def _save_verify_csv(self) -> None: - if not self.variant_verdicts: - return - path, _ = QFileDialog.getSaveFileName( - self, tr("verify.save_csv"), "snp_report.csv", "CSV (*.csv)" - ) - if path: - export.write_text(path, verdicts_csv(self.variant_verdicts)) - self.statusBar().showMessage(tr("export.done", path=path), 5000) - - def _save_verify_xlsx(self) -> None: - if not self.variant_verdicts: - return - path, _ = QFileDialog.getSaveFileName( - self, tr("verify.save_xlsx"), "snp_report.xlsx", "Excel (*.xlsx)" - ) - if not path: - return - try: - verdicts_xlsx(path, self.variant_verdicts, sample_id=self._export_id()) - except RuntimeError as exc: - QMessageBox.warning(self, tr("verify.save_xlsx"), str(exc)) - return - self.statusBar().showMessage(tr("export.done", path=path), 5000) - - # ------------------------------------------------------------------ batch - def _open_folder_dialog(self) -> None: - start = str(self._path.parent) if self._path else "" - folder = QFileDialog.getExistingDirectory(self, tr("menu.file.open_folder"), start) - if folder: - self._scan_folder(Path(folder)) - - def _scan_folder(self, folder: Path) -> None: - window, min_q = self.config.trim_window, self.config.trim_min_q - - def done(reports: object) -> None: - self.batch_reports = reports # type: ignore[assignment] - self.batch_panel.show_reports(self.batch_reports) - self.batch_dock.show() - self.statusBar().showMessage( - tr("batch.scan_done", n=len(self.batch_reports)), 5000 - ) - - # scan_folder reports no progress and is not interruptible: on cancel - # its late result is dropped and the table stays as it was. - self._start_task( - lambda progress, is_cancelled: batch.scan_folder(folder, window, min_q), - done, - tr("menu.file.open_folder"), - key="scan", - ) - - def _batch_export(self) -> None: - if not self.batch_reports: - return - out_dir = QFileDialog.getExistingDirectory(self, tr("batch.export_dir")) - if not out_dir: - return - results = batch.batch_export( - self.batch_reports, - Path(out_dir), - window=self.config.trim_window, - min_q=self.config.trim_min_q, - ) - exported = sum(1 for _, dest, error in results if dest and not error) - errors = sum(1 for _, _, error in results if error) - self.statusBar().showMessage( - tr("batch.exported", n=exported, err=errors), 8000 - ) - - def _batch_save_csv(self) -> None: - if not self.batch_reports: - return - path, _ = QFileDialog.getSaveFileName( - self, tr("batch.csv"), "batch_summary.csv", "CSV (*.csv)" - ) - if path: - export.write_text(path, batch.summary_csv(self.batch_reports)) - self.statusBar().showMessage(tr("export.done", path=path), 5000) + def set_theme(self, name: str) -> None: + self.config.theme = name + self.read_view.apply_theme(name) + QApplication.instance().setStyleSheet(app_qss(name == "dark")) + save_config(self.config) + # ----------------------------------------------------------- recent, drops def dragEnterEvent(self, event: QDragEnterEvent) -> None: # noqa: N802 urls = event.mimeData().urls() if urls and urls[0].toLocalFile().lower().endswith(".ab1"): @@ -962,302 +228,71 @@ def _fill_recent_menu(self) -> None: ) self.recent_menu.addAction(action) - # ------------------------------------------------------------------ view - def _sync_from_view(self) -> None: - total = self.chrom_view._total_points() - visible = self.chrom_view._visible_points() - self.scrollbar.blockSignals(True) - self.scrollbar.setRange(0, max(0, int(total - visible))) - self.scrollbar.setPageStep(max(1, int(visible))) - self.scrollbar.setValue(int(self.chrom_view.offset)) - self.scrollbar.blockSignals(False) - self.minimap.set_view(self.chrom_view.offset, visible, total) - def set_theme(self, name: str) -> None: - self.config.theme = name - colors = palette(name) - self.chrom_view.set_theme(colors) - self.minimap.set_theme(colors) - for base, box in self._channel_boxes.items(): - box.setStyleSheet( - f"QCheckBox {{ color: {colors['bases'][base]}; font-weight: bold; padding: 0 4px; }}" - ) - QApplication.instance().setStyleSheet(app_qss(name == "dark")) - save_config(self.config) - - # --------------------------------------------------------------- editing - def _sync_actions(self) -> None: - model = self.read_model - self.undo_action.setEnabled(bool(model and model.can_undo)) - self.redo_action.setEnabled(bool(model and model.can_redo)) + # ------------------------------------------------- delegates to the read view + def open_path(self, path: str | Path) -> bool: + return self.read_view.open_path(path) def refresh_read(self) -> None: - if self.read_model is None: - return - chrom = self.read_model.current() - self.chrom_view.set_chromatogram(chrom, keep_view=True) - self.chrom_view.set_edited(self.read_model.edited) - self.minimap.set_chromatogram(chrom) - self.minimap.set_highlights([]) - self._search_ranges = [] - self._search_pos = -1 - self._refresh_info(chrom) - self._sync_actions() - self.setWindowTitle( - f"ab1kit — {self._path.name}" + ("*" if self.read_model.modified else "") - ) - if self.reference_seq: - self._realign() + self.read_view.refresh_read() def apply_base_change(self, index: int, base: str) -> None: - if self.read_model: - self.read_model.set_base(index, base) - self.refresh_read() + self.read_view.apply_base_change(index, base) def apply_base_insert(self, index: int, base: str) -> None: - if self.read_model: - self.read_model.insert_base(index, base) - self.refresh_read() + self.read_view.apply_base_insert(index, base) def apply_base_delete(self, index: int) -> None: - if self.read_model: - self.read_model.delete_base(index) - self.refresh_read() + self.read_view.apply_base_delete(index) def apply_trim_range(self, start: int, end: int) -> None: - if not self.read_model: - return - try: - self.read_model.apply_trim(start, end) - except ValueError as exc: - QMessageBox.warning(self, tr("trim.title"), str(exc)) - return - self.chrom_view.set_trim_region(None) - self.refresh_read() - self.statusBar().showMessage(tr("trim.status", n=len(self.read_model.seq))) + self.read_view.apply_trim_range(start, end) def undo_read(self) -> None: - if self.read_model and self.read_model.undo(): - self.refresh_read() + self.read_view.undo_read() def redo_read(self) -> None: - if self.read_model and self.read_model.redo(): - self.refresh_read() + self.read_view.redo_read() def reverse_complement_read(self) -> None: - if self.read_model: - self.read_model.reverse_complement() - self.refresh_read() - - def _on_base_clicked(self, index: int, global_pos) -> None: - if self.read_model is None: - return - menu = QMenu(self) - change = menu.addMenu(tr("edit.change")) - for letter in IUPAC_LETTERS: - change.addAction(letter, lambda l=letter: self.apply_base_change(index, l)) - insert_left = menu.addMenu(tr("edit.insert_left")) - for letter in INSERT_LETTERS: - insert_left.addAction(letter, lambda l=letter: self.apply_base_insert(index, l)) - insert_right = menu.addMenu(tr("edit.insert_right")) - for letter in INSERT_LETTERS: - insert_right.addAction(letter, lambda l=letter: self.apply_base_insert(index + 1, l)) - menu.addSeparator() - menu.addAction(tr("edit.delete"), lambda: self.apply_base_delete(index)) - menu.exec(global_pos) - - # ------------------------------------------------------------------ trim - def _open_trim_dialog(self) -> None: - if self.read_model is None or self.trim_dialog is not None: - return - start, end = trim_window( - self.read_model.quality, self.config.trim_window, self.config.trim_min_q - ) - self.chrom_view.set_trim_region((start, end)) - dialog = TrimDialog( - lambda: self.read_model.quality, - self.config.trim_window, - self.config.trim_min_q, - len(self.read_model.seq), - self, - ) - self.trim_dialog = dialog - dialog.region_changed.connect( - lambda start, end: self.chrom_view.set_trim_region((start, end)) - ) - self.chrom_view.trim_range_changed.connect(dialog.set_region) - dialog.apply_requested.connect(self._apply_trim_from_dialog) - dialog.finished.connect(self._trim_dialog_closed) - dialog.show() + self.read_view.reverse_complement_read() - def _apply_trim_from_dialog(self, start: int, end: int) -> None: - if self.trim_dialog is not None: - self.config.trim_window = self.trim_dialog.window_value() - self.config.trim_min_q = self.trim_dialog.minq_value() - save_config(self.config) - self.apply_trim_range(start, end) - - def _trim_dialog_closed(self) -> None: - dialog = self.trim_dialog - self.trim_dialog = None - if dialog is not None: - try: - self.chrom_view.trim_range_changed.disconnect(dialog.set_region) - except RuntimeError: - pass - self.chrom_view.set_trim_region(None) - - # ---------------------------------------------------------------- search - def _search(self) -> None: - if self.chrom_view.chrom is None: - return - dialog = SearchDialog(self) - if dialog.exec() != QDialog.DialogCode.Accepted: - return - pattern = dialog.pattern() - if not pattern: - return - seq = self.chrom_view.chrom.seq - try: - fwd = find_matches(pattern, seq) - rev = find_matches(pattern, seq, reverse=True) if dialog.want_reverse() else [] - except ValueError as exc: - QMessageBox.warning(self, tr("search.title"), str(exc)) - return - ranges = [(i, i + len(pattern)) for i in fwd + rev] - self.chrom_view.set_highlights(ranges) - self.minimap.set_highlights(ranges) - self._search_ranges = ranges - self._search_pos = -1 - if ranges: - self.statusBar().showMessage( - tr("search.found", n=len(ranges), f=len(fwd), r=len(rev)) - ) - self._find_next() - else: - self.statusBar().showMessage(tr("search.none")) - - def _find_next(self) -> None: - if not self._search_ranges: - return - self._search_pos = (self._search_pos + 1) % len(self._search_ranges) - self.chrom_view.goto_base(self._search_ranges[self._search_pos][0] + 1) - - # ----------------------------------------------------------- goto and info - def _goto(self) -> None: - chrom = self.chrom_view.chrom - if chrom is None: - return - number, ok = QInputDialog.getInt( - self, tr("goto.title"), tr("goto.label"), 1, 1, len(chrom.seq) - ) - if ok: - self.chrom_view.goto_base(number) - - def _refresh_info(self, chrom: Chromatogram) -> None: - page = QWidget() - form = QFormLayout(page) - form.setContentsMargins(8, 8, 8, 8) + def _set_reference_seq(self, sequence: str) -> None: + self.read_view._set_reference_seq(sequence) - def row(label: str, value) -> None: - widget = QLabel(str(value)) - widget.setWordWrap(True) - form.addRow(QLabel(label), widget) + def _reference_overlay(self) -> tuple[str, dict[int, int]]: + return self.read_view._reference_overlay() - row(tr("info.file"), self._path) - row(tr("info.length"), len(chrom.seq)) - row(tr("info.mean_q"), f"{sum(chrom.quality) / max(1, len(chrom.quality)):.1f}") - row(tr("info.q20"), sum(1 for q in chrom.quality if q >= 20)) - meta_keys = ( - ("sample", "meta.sample"), - ("instrument", "meta.instrument"), - ("run_date", "meta.run_date"), - ("run_time", "meta.run_time"), - ("project", "meta.project"), - ("capillary", "meta.capillary"), - ("mobility", "meta.mobility"), - ("comment", "meta.comment"), - ) - for key, label_key in meta_keys: - if key in chrom.metadata: - row(tr(label_key), chrom.metadata[key]) - self.info_dock.setWidget(page) + def _clear_reference(self) -> None: + self.read_view._clear_reference() - # ------------------------------------------------------- export and sessions - def _export_target(self, caption: str, suffix: str, pattern: str) -> str | None: - default = (self._path.stem if self._path else "read") + suffix - path, _ = QFileDialog.getSaveFileName(self, caption, default, pattern) - return path or None + def _export_aligned(self) -> None: + self.read_view._export_aligned() - def _export_fasta(self) -> None: - if not self.read_model: - return - path = self._export_target(tr("menu.file.export_fasta"), ".fasta", "FASTA (*.fasta)") - if path: - export.write_text(path, export.to_fasta(self._export_id(), "".join(self.read_model.seq))) - self.statusBar().showMessage(tr("export.done", path=path), 5000) + def _blast_submit(self) -> None: + self.read_view._blast_submit() - def _export_fastq(self) -> None: - if not self.read_model: - return - path = self._export_target(tr("menu.file.export_fastq"), ".fastq", "FASTQ (*.fastq)") - if path: - content = export.to_fastq( - self._export_id(), "".join(self.read_model.seq), self.read_model.quality - ) - export.write_text(path, content) - self.statusBar().showMessage(tr("export.done", path=path), 5000) + def _verify_variants(self, text: str) -> None: + self.read_view._verify_variants(text) - def _export_id(self) -> str: - return self.read_model.current().sample_id if self.read_model else "read" + def _fill_verify_table(self) -> None: + self.read_view._fill_verify_table() - def _export_png(self) -> None: - path = self._export_target(tr("menu.file.export_png"), ".png", "PNG (*.png)") - if path and self.chrom_view.grab().save(path): - self.statusBar().showMessage(tr("export.done", path=path), 5000) + def _save_verify_csv(self) -> None: + self.read_view._save_verify_csv() - def _export_pdf(self) -> None: - path = self._export_target(tr("menu.file.export_pdf"), ".pdf", "PDF (*.pdf)") - if not path: - return - pixmap = self.chrom_view.grab() - writer = QPdfWriter(path) - writer.setPageSize(QPageSize(QSizeF(pixmap.width(), pixmap.height()), QPageSize.Unit.Point)) - writer.setPageMargins(QMarginsF(0, 0, 0, 0)) - painter = QPainter(writer) - painter.drawPixmap(0, 0, writer.width(), writer.height(), pixmap) - painter.end() - self.statusBar().showMessage(tr("export.done", path=path), 5000) + def _scan_folder(self, folder: Path) -> None: + self.read_view._scan_folder(folder) - def _copy_sequence(self) -> None: - if self.read_model: - QApplication.clipboard().setText("".join(self.read_model.seq)) - self.statusBar().showMessage( - tr("copy.done", n=len(self.read_model.seq)), 3000 - ) + def _batch_export(self) -> None: + self.batch_dock.export_trimmed() - def _save_session(self) -> None: - if self.read_model is None or self._path is None: - return - sessions.save_session( - sessions.session_path(self._path), - {"source": self._path.name, **self.read_model.to_dict()}, - ) - self.statusBar().showMessage(tr("session.saved"), 3000) + def _open_trim_dialog(self) -> None: + self.read_view._open_trim_dialog() def closeEvent(self, event) -> None: # noqa: N802 self._cancel_tasks() - if self.read_model is not None and self._path is not None: - sidecar = sessions.session_path(self._path) - try: - if self.read_model.modified: - sessions.save_session( - sidecar, {"source": self._path.name, **self.read_model.to_dict()} - ) - elif sidecar.exists(): - sidecar.unlink() - except OSError: - pass + self.read_view.autosave_session() super().closeEvent(event) diff --git a/ui/read_view/__init__.py b/ui/read_view/__init__.py new file mode 100644 index 0000000..dfb6a74 --- /dev/null +++ b/ui/read_view/__init__.py @@ -0,0 +1,5 @@ +"""Single-read viewer package.""" + +from ui.read_view.read_view import ReadView + +__all__ = ["ReadView"] diff --git a/ui/read_view/analysis_dock.py b/ui/read_view/analysis_dock.py new file mode 100644 index 0000000..0877466 --- /dev/null +++ b/ui/read_view/analysis_dock.py @@ -0,0 +1,104 @@ +"""Reference-comparison dock: table of differences with SNP verdicts.""" + +from __future__ import annotations + +from PySide6.QtCore import Qt +from PySide6.QtGui import QColor +from PySide6.QtWidgets import QDockWidget, QTableWidget, QTableWidgetItem, QWidget + +from chrom_core.align import ReadAlignment +from chrom_core.seqops import reverse_complement +from i18n import tr + + +def reference_overlay( + alignment: ReadAlignment, reference_seq: str, read_length: int +) -> tuple[str, dict[int, int]]: + """Reference letters and ref -> index mapping in the *displayed* read's + orientation (the alignment indexes the reverse complement on '-').""" + if alignment.strand == "+": + return reference_seq, alignment.ref_to_read + n = read_length + return ( + reverse_complement(reference_seq)[::-1], # complement, same ref indexing + {pos: n - 1 - idx for pos, idx in alignment.ref_to_read.items()}, + ) + + +def displayed_diff_index(alignment: ReadAlignment, diff, read_length: int) -> int | None: + """0-based index of ``diff`` in the displayed read (None for deletions).""" + if diff.read_pos is None: + return None + if alignment.strand == "+": + return diff.read_pos + n = read_length + span = len(diff.read_base) if diff.kind == "insertion" else 1 + return n - diff.read_pos - span + + +class DiffDock(QDockWidget): + def __init__(self, parent: QWidget | None = None) -> None: + super().__init__(tr("analysis.diffs.title"), parent) + self.diff_table = QTableWidget(0, 8) + self.diff_table.setHorizontalHeaderLabels( + [ + tr("analysis.col.pos"), + tr("analysis.col.kind"), + tr("analysis.col.ref"), + tr("analysis.col.read"), + tr("analysis.col.readpos"), + tr("snp.col.verdict"), + tr("snp.col.q"), + tr("snp.col.ratio"), + ] + ) + self.diff_table.verticalHeader().setVisible(False) + self.diff_table.setEditTriggers(QTableWidget.EditTrigger.NoEditTriggers) + self.diff_table.setSortingEnabled(True) + self.setWidget(self.diff_table) + + def fill(self, alignment: ReadAlignment | None, snp_calls: list, read_length: int) -> None: + kind_labels = { + "substitution": tr("analysis.kind.substitution"), + "deletion": tr("analysis.kind.deletion"), + "insertion": tr("analysis.kind.insertion"), + } + verdict_labels = { + "homozygous": tr("snp.homozygous"), + "heterozygous": tr("snp.heterozygous"), + "low_quality": tr("snp.low_quality"), + } + calls_by_ref = {c.ref_pos: c for c in snp_calls} + diffs = alignment.differences if alignment else [] + self.diff_table.setSortingEnabled(False) + self.diff_table.setRowCount(len(diffs)) + for row, diff in enumerate(diffs): + call = calls_by_ref.get(diff.ref_pos) + verdict = "" + if call is not None: + verdict = verdict_labels.get(call.kind, call.kind) + if call.kind == "heterozygous": + verdict += f" ({call.iupac})" + values = [ + diff.ref_pos + 1, + kind_labels.get(diff.kind, diff.kind), + diff.ref_base, + diff.read_base, + (call.read_pos + 1 if call is not None + else shown + 1 if (shown := displayed_diff_index(alignment, diff, read_length)) is not None + else ""), + verdict, + call.quality if call is not None else "", + f"{call.ratio:.2f}" if call is not None and call.ratio is not None else "", + ] + for col, value in enumerate(values): + item = QTableWidgetItem() + item.setData(Qt.ItemDataRole.DisplayRole, value) + if call is not None and col == 5 and call.kind == "heterozygous": + item.setForeground(QColor("#a05000")) + self.diff_table.setItem(row, col, item) + self.diff_table.setSortingEnabled(True) + + def clear(self) -> None: + self.diff_table.setRowCount(0) + self.hide() diff --git a/ui/batch_panel.py b/ui/read_view/batch_dock.py similarity index 59% rename from ui/batch_panel.py rename to ui/read_view/batch_dock.py index 6919cef..a11ee2e 100644 --- a/ui/batch_panel.py +++ b/ui/read_view/batch_dock.py @@ -1,11 +1,16 @@ -"""Batch panel: a QC table over a folder of .ab1 files.""" +"""Batch dock: a QC table over a folder of .ab1 files, with scan and export.""" from __future__ import annotations +from collections.abc import Callable +from pathlib import Path + from PySide6.QtCore import Qt, Signal from PySide6.QtGui import QColor from PySide6.QtWidgets import ( QCheckBox, + QDockWidget, + QFileDialog, QHBoxLayout, QHeaderView, QPushButton, @@ -15,7 +20,9 @@ QWidget, ) +from chrom_core import batch, export from chrom_core.batch import FileReport +from chrom_core.config import AppConfig from i18n import tr STATUS_TEXT = {"ok": "✓", "warn": "⚠", "bad": "✗", "error": "✗"} @@ -107,3 +114,69 @@ def _double_clicked(self, item: QTableWidgetItem) -> None: path = path_item.data(Qt.ItemDataRole.UserRole) if path: self.open_requested.emit(str(path)) + + +class BatchDock(QDockWidget): + """Dock around :class:`BatchPanel`; owns folder scanning and batch export. + + ``start_task`` is the shell's background-task runner; ``message`` is + emitted for status-bar text (text, timeout in ms). + """ + + open_requested = Signal(str) + message = Signal(str, int) + + def __init__(self, config: AppConfig, start_task: Callable, parent: QWidget | None = None) -> None: + super().__init__(tr("batch.title"), parent) + self.config = config + self._start_task = start_task + self.reports: list[batch.FileReport] = [] + self.batch_panel = BatchPanel() + self.setWidget(self.batch_panel) + self.batch_panel.open_requested.connect(self.open_requested) + self.batch_panel.export_button.clicked.connect(self.export_trimmed) + self.batch_panel.csv_button.clicked.connect(self.save_csv) + + def scan_folder(self, folder: Path) -> None: + window, min_q = self.config.trim_window, self.config.trim_min_q + + def done(reports: object) -> None: + self.reports = reports # type: ignore[assignment] + self.batch_panel.show_reports(self.reports) + self.show() + self.message.emit(tr("batch.scan_done", n=len(self.reports)), 5000) + + # scan_folder reports no progress and is not interruptible: on cancel + # its late result is dropped and the table stays as it was. + self._start_task( + lambda progress, is_cancelled: batch.scan_folder(folder, window, min_q), + done, + tr("menu.file.open_folder"), + key="scan", + ) + + def export_trimmed(self) -> None: + if not self.reports: + return + out_dir = QFileDialog.getExistingDirectory(self, tr("batch.export_dir")) + if not out_dir: + return + results = batch.batch_export( + self.reports, + Path(out_dir), + window=self.config.trim_window, + min_q=self.config.trim_min_q, + ) + exported = sum(1 for _, dest, error in results if dest and not error) + errors = sum(1 for _, _, error in results if error) + self.message.emit(tr("batch.exported", n=exported, err=errors), 8000) + + def save_csv(self) -> None: + if not self.reports: + return + path, _ = QFileDialog.getSaveFileName( + self, tr("batch.csv"), "batch_summary.csv", "CSV (*.csv)" + ) + if path: + export.write_text(path, batch.summary_csv(self.reports)) + self.message.emit(tr("export.done", path=path), 5000) diff --git a/ui/read_view/dialogs.py b/ui/read_view/dialogs.py new file mode 100644 index 0000000..4d0524f --- /dev/null +++ b/ui/read_view/dialogs.py @@ -0,0 +1,149 @@ +"""Dialogs used by the single-read view.""" + +from __future__ import annotations + +from pathlib import Path + +from PySide6.QtCore import Signal +from PySide6.QtWidgets import ( + QCheckBox, + QDialog, + QFileDialog, + QFormLayout, + QHBoxLayout, + QLabel, + QLineEdit, + QPlainTextEdit, + QPushButton, + QSpinBox, + QVBoxLayout, + QWidget, +) + +from chrom_core import trim_window +from i18n import tr + + +class SearchDialog(QDialog): + def __init__(self, parent=None) -> None: + super().__init__(parent) + self.setWindowTitle(tr("search.title")) + layout = QVBoxLayout(self) + self.edit = QLineEdit() + self.edit.setPlaceholderText(tr("search.pattern")) + self.reverse_box = QCheckBox(tr("search.reverse")) + button = QPushButton(tr("search.button")) + button.setDefault(True) + button.clicked.connect(self.accept) + layout.addWidget(self.edit) + layout.addWidget(self.reverse_box) + layout.addWidget(button) + + def pattern(self) -> str: + return self.edit.text().strip().upper() + + def want_reverse(self) -> bool: + return self.reverse_box.isChecked() + + +class TrimDialog(QDialog): + """Non-modal quality-trim dialog; preview streams into the chromatogram.""" + + region_changed = Signal(int, int) + apply_requested = Signal(int, int) + + def __init__(self, quality_fn, window: int, min_q: int, total: int, parent=None) -> None: + super().__init__(parent) + self.setWindowTitle(tr("trim.title")) + self.quality_fn = quality_fn + self.total = total + self._region = (0, total) + + layout = QVBoxLayout(self) + form = QFormLayout() + self.window_spin = QSpinBox() + self.window_spin.setRange(2, 100) + self.window_spin.setValue(window) + self.minq_spin = QSpinBox() + self.minq_spin.setRange(0, 60) + self.minq_spin.setValue(min_q) + form.addRow(QLabel(tr("trim.window")), self.window_spin) + form.addRow(QLabel(tr("trim.minq")), self.minq_spin) + layout.addLayout(form) + self.preview = QLabel() + layout.addWidget(self.preview) + buttons = QWidget() + row = QVBoxLayout(buttons) + apply_button = QPushButton(tr("trim.apply")) + apply_button.setDefault(True) + apply_button.clicked.connect(self._apply) + close_button = QPushButton(tr("dialog.close")) + close_button.clicked.connect(self.close) + row.addWidget(apply_button) + row.addWidget(close_button) + layout.addWidget(buttons) + + self.window_spin.valueChanged.connect(self._recompute) + self.minq_spin.valueChanged.connect(self._recompute) + self._recompute() + + def window_value(self) -> int: + return self.window_spin.value() + + def minq_value(self) -> int: + return self.minq_spin.value() + + def _recompute(self) -> None: + start, end = trim_window(self.quality_fn(), self.window_spin.value(), self.minq_spin.value()) + self._set_region(start, end) + self.region_changed.emit(start, end) + + def _set_region(self, start: int, end: int) -> None: + self._region = (start, end) + self.preview.setText(tr("trim.preview", n=end - start, total=self.total)) + + def set_region(self, start: int, end: int) -> None: + """Sync preview when the user drags trim handles in the view.""" + self._set_region(start, end) + + def _apply(self) -> None: + start, end = self._region + self.apply_requested.emit(start, end) + self.close() + + +def ask_reference_text(parent: QWidget) -> str | None: + """Modal dialog for pasting/loading a reference; returns the raw text + when accepted, ``None`` otherwise.""" + dialog = QDialog(parent) + dialog.setWindowTitle(tr("analysis.ref.title")) + dialog.resize(480, 240) + layout = QVBoxLayout(dialog) + edit = QPlainTextEdit() + edit.setPlaceholderText(tr("analysis.ref.paste")) + layout.addWidget(edit) + + def from_file() -> None: + path, _ = QFileDialog.getOpenFileName( + dialog, tr("analysis.ref.from_file"), "", "Sequence (*.fasta *.fa *.txt);;All files (*)" + ) + if path: + edit.setPlainText(Path(path).read_text(encoding="utf-8", errors="replace")) + + file_button = QPushButton(tr("analysis.ref.from_file")) + file_button.clicked.connect(from_file) + layout.addWidget(file_button) + + ok = QPushButton("OK") + ok.clicked.connect(dialog.accept) + cancel = QPushButton(tr("dialog.close")) + cancel.clicked.connect(dialog.reject) + row = QWidget() + row_layout = QHBoxLayout(row) + row_layout.addWidget(ok) + row_layout.addWidget(cancel) + layout.addWidget(row) + + if dialog.exec() != QDialog.DialogCode.Accepted: + return None + return edit.toPlainText() diff --git a/ui/read_view/menus.py b/ui/read_view/menus.py new file mode 100644 index 0000000..5d7959a --- /dev/null +++ b/ui/read_view/menus.py @@ -0,0 +1,115 @@ +"""Read-specific menu items, appended by the shell into its own menus. + +Shortcuts, order and enabled-state handling are the ones the single window +used to have; the actions are parented to the view so they live with it. +""" + +from __future__ import annotations + +from PySide6.QtGui import QAction +from PySide6.QtWidgets import QMenu + +from i18n import tr + + +def add_file_actions(view, file_menu: QMenu) -> None: + """Save session, export submenu, copy sequence (between 'Recent' and 'Exit').""" + save_session = QAction(tr("menu.file.save_session"), view) + save_session.setShortcut("Ctrl+S") + save_session.triggered.connect(view._save_session) + file_menu.addAction(save_session) + export_menu = file_menu.addMenu(tr("menu.file.export")) + for text, slot in ( + (tr("menu.file.export_fasta"), view._export_fasta), + (tr("menu.file.export_fastq"), view._export_fastq), + (tr("menu.file.export_png"), view._export_png), + (tr("menu.file.export_pdf"), view._export_pdf), + ): + action = QAction(text, view) + action.triggered.connect(slot) + export_menu.addAction(action) + file_menu.addSeparator() + copy_action = QAction(tr("menu.file.copy_seq"), view) + copy_action.setShortcut("Ctrl+Shift+C") + copy_action.triggered.connect(view._copy_sequence) + file_menu.addAction(copy_action) + + +def add_edit_actions(view, edit_menu: QMenu) -> None: + view.undo_action = QAction(tr("menu.edit.undo"), view) + view.undo_action.setShortcut("Ctrl+Z") + view.undo_action.triggered.connect(view.undo_read) + view.undo_action.setEnabled(False) + edit_menu.addAction(view.undo_action) + view.redo_action = QAction(tr("menu.edit.redo"), view) + view.redo_action.setShortcut("Ctrl+Y") + view.redo_action.triggered.connect(view.redo_read) + view.redo_action.setEnabled(False) + edit_menu.addAction(view.redo_action) + edit_menu.addSeparator() + find_action = QAction(tr("menu.edit.find"), view) + find_action.setShortcut("Ctrl+F") + find_action.triggered.connect(view._search) + edit_menu.addAction(find_action) + find_next = QAction(tr("menu.edit.find_next"), view) + find_next.setShortcut("F3") + find_next.triggered.connect(view._find_next) + edit_menu.addAction(find_next) + goto_action = QAction(tr("menu.edit.goto"), view) + goto_action.setShortcut("Ctrl+G") + goto_action.triggered.connect(view._goto) + edit_menu.addAction(goto_action) + edit_menu.addSeparator() + revcomp_action = QAction(tr("menu.edit.revcomp"), view) + revcomp_action.setShortcut("Ctrl+R") + revcomp_action.triggered.connect(view.reverse_complement_read) + edit_menu.addAction(revcomp_action) + trim_action = QAction(tr("menu.edit.trim"), view) + trim_action.setShortcut("Ctrl+T") + trim_action.triggered.connect(view._open_trim_dialog) + edit_menu.addAction(trim_action) + + +def add_view_actions(view, view_menu: QMenu) -> None: + """Smoothing, quality profile, info and batch docks (after 'Dark theme').""" + smooth_action = QAction(tr("menu.view.smoothing"), view) + smooth_action.setCheckable(True) + smooth_action.toggled.connect(view.chrom_view.set_smoothing) + view_menu.addAction(smooth_action) + profile_action = QAction(tr("menu.view.quality_profile"), view) + profile_action.setCheckable(True) + profile_action.toggled.connect(view.minimap.set_profile) + view_menu.addAction(profile_action) + info_action = QAction(tr("menu.view.file_info"), view) + info_action.setCheckable(True) + info_action.toggled.connect(view.info_dock.setVisible) + view.info_dock.visibilityChanged.connect(info_action.setChecked) + view_menu.addAction(info_action) + batch_action = QAction(tr("menu.view.batch_panel"), view) + batch_action.setCheckable(True) + batch_action.toggled.connect(view.batch_dock.setVisible) + view.batch_dock.visibilityChanged.connect(batch_action.setChecked) + view_menu.addAction(batch_action) + + +def add_analysis_actions(view, analysis_menu: QMenu) -> None: + reference_action = QAction(tr("menu.analysis.reference"), view) + reference_action.setShortcut("Ctrl+L") + reference_action.triggered.connect(view._reference_dialog) + analysis_menu.addAction(reference_action) + clear_ref = QAction(tr("menu.analysis.clear_reference"), view) + clear_ref.triggered.connect(view._clear_reference) + analysis_menu.addAction(clear_ref) + analysis_menu.addSeparator() + export_aligned = QAction(tr("menu.analysis.export_aligned"), view) + export_aligned.triggered.connect(view._export_aligned) + analysis_menu.addAction(export_aligned) + analysis_menu.addSeparator() + verify_action = QAction(tr("menu.analysis.verify"), view) + verify_action.setShortcut("Ctrl+Shift+V") + verify_action.triggered.connect(view._verify_dialog) + analysis_menu.addAction(verify_action) + analysis_menu.addSeparator() + blast_action = QAction(tr("menu.analysis.blast"), view) + blast_action.triggered.connect(view._blast_submit) + analysis_menu.addAction(blast_action) diff --git a/ui/read_view/read_view.py b/ui/read_view/read_view.py new file mode 100644 index 0000000..66e1065 --- /dev/null +++ b/ui/read_view/read_view.py @@ -0,0 +1,742 @@ +"""Single-read viewer: chromatogram, minimap, editing, trim, search, analysis docks.""" + +from __future__ import annotations + +from collections.abc import Callable +from pathlib import Path + +from PySide6.QtCore import QMarginsF, QSizeF, Qt, QUrl, Signal +from PySide6.QtGui import QAction, QDesktopServices, QPageSize, QPainter, QPdfWriter +from PySide6.QtWidgets import ( + QApplication, + QCheckBox, + QDialog, + QDockWidget, + QFileDialog, + QFormLayout, + QInputDialog, + QLabel, + QMainWindow, + QMenu, + QMessageBox, + QScrollBar, + QToolBar, + QVBoxLayout, + QWidget, +) + +from chrom_core import Chromatogram, EditableRead, read_ab1, trim_window +from chrom_core import blast as blast_api +from chrom_core import export, sessions +from chrom_core.align import ReadAlignment, align_read, gapped_sequences, parse_sequence +from chrom_core.config import AppConfig, save_config +from chrom_core.editing import INSERT_LETTERS, IUPAC_LETTERS +from chrom_core.snps import call_snps +from chrom_core.verify import parse_expected, verify_expected, verdicts_csv, verdicts_xlsx +from chrom_core.seqops import find_matches +from i18n import tr +from ui.chrom_view import ChromatogramWidget +from ui.minimap import MiniMap +from ui.read_view import menus +from ui.read_view.analysis_dock import DiffDock, displayed_diff_index, reference_overlay +from ui.read_view.batch_dock import BatchDock +from ui.read_view.dialogs import SearchDialog, TrimDialog, ask_reference_text +from ui.read_view.verify_dock import VerifyDock +from ui.theme import theme as palette + + +class ReadView(QMainWindow): + """Everything that belongs to one open read. Embedded by the shell window. + + The shell supplies ``start_task`` (background-task runner, see + ``MainWindow._start_task``) and listens to the signals below; the view + never touches its parent. + """ + + read_edited = Signal(Path) # after a base edit, undo/redo, trim, revcomp, session save + file_opened = Signal(str) + status_message = Signal(str, int) # text, timeout in ms (0 = until replaced) + title_changed = Signal(str) + + def __init__(self, config: AppConfig, start_task: Callable, parent: QWidget | None = None) -> None: + super().__init__(parent) + self.config = config + self._start_task = start_task + self._path: Path | None = None + self.read_model: EditableRead | None = None + self.trim_dialog: TrimDialog | None = None + self.reference_seq: str = "" + self.alignment: ReadAlignment | None = None + self.snp_calls: list = [] + self.variant_verdicts: list = [] + self._search_ranges: list[tuple[int, int]] = [] + self._search_pos = -1 + + self.chrom_view = ChromatogramWidget() + self.minimap = MiniMap() + self.scrollbar = QScrollBar(Qt.Orientation.Horizontal) + + central = QWidget() + layout = QVBoxLayout(central) + layout.setContentsMargins(0, 0, 0, 0) + layout.setSpacing(0) + layout.addWidget(self.minimap) + layout.addWidget(self.chrom_view, 1) + layout.addWidget(self.scrollbar) + self.setCentralWidget(central) + + self._channel_boxes: dict[str, QCheckBox] = {} + self._build_toolbar() + self._build_docks() + self._connect() + + def _say(self, text: str, timeout: int = 0) -> None: + self.status_message.emit(text, timeout) + + # ------------------------------------------------------------------ setup + def _build_toolbar(self) -> None: + bar = QToolBar() + bar.setMovable(False) + self.addToolBar(bar) + + def add(text: str, slot, shortcut: str | None = None) -> None: + action = QAction(text, self) + if shortcut: + action.setShortcut(shortcut) + action.triggered.connect(slot) + bar.addAction(action) + + add(tr("tb.open"), self.open_dialog) + bar.addSeparator() + add(tr("tb.zoom_in"), self.chrom_view.zoom_in, "Ctrl++") + add(tr("tb.zoom_out"), self.chrom_view.zoom_out, "Ctrl+-") + add(tr("tb.fit"), self.chrom_view.zoom_fit) + add(tr("tb.reset"), self.chrom_view.zoom_reset) + bar.addSeparator() + for base in "ACGT": + box = QCheckBox(base) + box.setChecked(True) + box.toggled.connect( + lambda on, b=base: self.chrom_view.set_visible_channel(b, on) + ) + bar.addWidget(box) + self._channel_boxes[base] = box + + def _build_docks(self) -> None: + self.info_dock = QDockWidget(tr("info.title"), self) + self.info_dock.setWidget(QWidget()) + self.addDockWidget(Qt.DockWidgetArea.RightDockWidgetArea, self.info_dock) + self.info_dock.hide() + + self.batch_dock = BatchDock(self.config, self._start_task) + self.batch_panel = self.batch_dock.batch_panel + self.addDockWidget(Qt.DockWidgetArea.BottomDockWidgetArea, self.batch_dock) + self.batch_dock.hide() + self.batch_dock.open_requested.connect(self.open_path) + self.batch_dock.message.connect(self._say) + + self.diff_dock = DiffDock() + self.diff_table = self.diff_dock.diff_table + self.addDockWidget(Qt.DockWidgetArea.RightDockWidgetArea, self.diff_dock) + self.diff_dock.hide() + + self.verify_dock = VerifyDock() + self.verify_table = self.verify_dock.verify_table + self.addDockWidget(Qt.DockWidgetArea.BottomDockWidgetArea, self.verify_dock) + self.verify_dock.hide() + self.verify_dock.csv_button.clicked.connect(self._save_verify_csv) + self.verify_dock.xlsx_button.clicked.connect(self._save_verify_xlsx) + + @property + def batch_reports(self) -> list: + return self.batch_dock.reports + + def current_model(self) -> EditableRead | None: + return self.read_model + + # ------------------------------------------------------------------ menus + # The shell owns the menu bar and its order; it asks the view to append + # the read-specific items (see ``menus.py``) at the right places. + def add_file_actions(self, menu: QMenu) -> None: + menus.add_file_actions(self, menu) + + def add_edit_menu(self, menu: QMenu) -> None: + menus.add_edit_actions(self, menu) + + def add_view_actions(self, menu: QMenu) -> None: + menus.add_view_actions(self, menu) + + def add_analysis_menu(self, menu: QMenu) -> None: + menus.add_analysis_actions(self, menu) + + def _connect(self) -> None: + self.chrom_view.view_changed.connect(self._sync_from_view) + self.chrom_view.cursor_info.connect(self._say) + self.chrom_view.base_clicked.connect(self._on_base_clicked) + self.minimap.request_center.connect(self.chrom_view.center_on_point) + self.scrollbar.valueChanged.connect( + lambda value: self.chrom_view.set_offset(float(value)) + ) + + + def open_path(self, path: str | Path) -> bool: + try: + chrom = read_ab1(path) + except Exception as exc: # user-facing: any parse failure becomes a dialog + QMessageBox.critical(self, tr("err.open_failed"), f"{path}:\n{exc}") + return False + self._path = Path(path) + model = EditableRead(chrom) + restored = self._try_restore_session(model) + self.read_model = model + self._search_ranges = [] + self._search_pos = -1 + self.chrom_view.set_chromatogram(model.current()) + self.chrom_view.set_edited(model.edited) + self.minimap.set_chromatogram(model.current()) + self.minimap.set_highlights([]) + self.file_opened.emit(str(self._path)) + self._refresh_info(model.current()) + self._sync_actions() + if self.reference_seq: + self._realign() + n = len(model.seq) + mean_q = sum(model.quality) / max(1, n) + message = tr("status.file", n=n, q=mean_q) + if restored: + message += " · " + tr("session.loaded") + self._say(message, 8000) + self.title_changed.emit(f"ab1kit — {self._path.name}" + ("*" if model.modified else "")) + return True + + def _try_restore_session(self, model: EditableRead) -> bool: + sidecar = sessions.session_path(self._path) + data = sessions.load_session(sidecar) + if not data or data.get("source") != self._path.name: + return False + try: + model.restore_state(data) + except (KeyError, TypeError, ValueError): + return False + return True + + def open_dialog(self) -> None: + path, _ = QFileDialog.getOpenFileName( + self, + tr("menu.file.open"), + str(self._path.parent) if self._path else "", + "Sanger chromatograms (*.ab1);;All files (*)", + ) + if path: + self.open_path(path) + + # --------------------------------------------------------------- analysis + + # --------------------------------------------------------------- analysis + def _reference_dialog(self) -> None: + text = ask_reference_text(self) + if text is None: + return + try: + sequence = parse_sequence(text) + except ValueError as exc: + QMessageBox.warning(self, tr("analysis.ref.title"), str(exc)) + return + if not sequence: + return + self._set_reference_seq(sequence) + + def _set_reference_seq(self, sequence: str) -> None: + self.reference_seq = sequence + if self.read_model is not None: + self._realign() + else: + self._say(tr("analysis.need_read"), 5000) + + def _reference_overlay(self) -> tuple[str, dict[int, int]]: + return reference_overlay(self.alignment, self.reference_seq, len(self.read_model.seq)) + + def _displayed_diff_index(self, diff) -> int | None: + return displayed_diff_index(self.alignment, diff, len(self.read_model.seq)) + + def _clear_reference(self) -> None: + self.reference_seq = "" + self.alignment = None + self.chrom_view.set_reference(None) + self.diff_dock.clear() + + def _realign(self) -> None: + if not (self.read_model and self.reference_seq): + return + try: + self.alignment = align_read("".join(self.read_model.seq), self.reference_seq) + except ValueError as exc: + QMessageBox.warning(self, tr("analysis.ref.title"), str(exc)) + self._clear_reference() + return + letters, ref_to_read = self._reference_overlay() + self.chrom_view.set_reference(letters, ref_to_read) + chrom = self.read_model.current() + self.snp_calls = call_snps( + self.alignment, chrom, + min_q=self.config.snp_min_q, het_ratio=self.config.het_ratio, + ) + self.diff_dock.fill(self.alignment, self.snp_calls, len(self.read_model.seq)) + self.diff_dock.setVisible(bool(self.alignment.differences)) + pct = f"{self.alignment.identity * 100:.1f}" + if self.alignment.differences: + message = tr( + "analysis.status", + n=len(self.alignment.differences), + pct=pct, + rstart=self.alignment.ref_start + 1, + rend=self.alignment.ref_end, + ) + else: + message = tr("analysis.no_diffs") + if self.snp_calls: + counts = {k: sum(1 for c in self.snp_calls if c.kind == k) + for k in ("homozygous", "heterozygous", "low_quality")} + message += " · " + tr( + "snp.summary", + homo=counts["homozygous"], + het=counts["heterozygous"], + low=counts["low_quality"], + ) + if self.alignment.alternatives > 1: + message += " · " + tr("analysis.ambiguous", n=self.alignment.alternatives) + self._say(message, 8000) + + def _export_aligned(self) -> None: + if not (self.alignment and self.reference_seq and self.read_model): + return + path = self._export_target( + tr("menu.analysis.export_aligned"), ".aligned.fasta", "FASTA (*.fasta)" + ) + if not path: + return + ref_aligned, read_aligned = gapped_sequences(self.alignment, self.reference_seq) + sample = self._export_id() + strand = "reverse" if self.alignment.strand == "-" else "forward" + content = ( + export.to_fasta(f"{sample}_reference[{self.alignment.ref_start + 1}-{self.alignment.ref_end}]", ref_aligned) + + export.to_fasta(f"{sample}_read_{strand}", read_aligned) + ) + export.write_text(path, content) + self._say(tr("export.done", path=path), 5000) + + def _blast_submit(self) -> None: + if not self.read_model: + return + seq = "".join(self.read_model.seq) + try: + params = blast_api.build_request(seq) + except (OSError, RuntimeError, ValueError) as exc: + QMessageBox.warning(self, tr("menu.analysis.blast"), str(exc)) + return + + def done(rid: object) -> None: + QDesktopServices.openUrl(QUrl(blast_api.result_url(str(rid)))) + self._say(tr("blast.sent", rid=rid), 10000) + + # urllib cannot be interrupted: on cancel the late RID is dropped. + self._start_task( + lambda progress, is_cancelled: blast_api.submit(params, timeout=20), + done, + tr("menu.analysis.blast"), + key="blast", + ) + + + def _verify_dialog(self) -> None: + if not (self.read_model and self.alignment and self.reference_seq): + self._say(tr("verify.need_reference"), 6000) + return + path, _ = QFileDialog.getOpenFileName( + self, + tr("menu.analysis.verify"), + str(self._path.parent) if self._path else "", + "Variants (*.vcf *.csv *.tsv *.txt);;All files (*)", + ) + if not path: + return + try: + text = Path(path).read_text(encoding="utf-8", errors="replace") + except OSError as exc: + QMessageBox.warning(self, tr("verify.title"), str(exc)) + return + self._verify_variants(text) + + def _verify_variants(self, text: str) -> None: + try: + variants, warnings = parse_expected(text) + except ValueError as exc: + QMessageBox.warning(self, tr("verify.title"), str(exc)) + return + if not variants: + QMessageBox.warning(self, tr("verify.title"), tr("search.none")) + return + self.variant_verdicts = verify_expected( + self.alignment, + self.read_model.current(), + self.reference_seq, + variants, + min_q=self.config.snp_min_q, + het_ratio=self.config.het_ratio, + ) + self._fill_verify_table() + self.verify_dock.show() + self.chrom_view.set_snp_marks( + [(v.read_pos, v.verdict) for v in self.variant_verdicts if v.read_pos is not None] + ) + counts = {k: sum(1 for v in self.variant_verdicts if v.verdict == k) + for k in ("confirmed", "heterozygous", "not_found", "no_data")} + message = tr( + "verify.summary", + n=len(self.variant_verdicts), + confirmed=counts["confirmed"], + het=counts["heterozygous"], + notfound=counts["not_found"], + nodata=counts["no_data"], + ) + if warnings: + message += f" · {len(warnings)} ⚠" + self._say(message, 10000) + + def _fill_verify_table(self) -> None: + self.verify_dock.fill(self.variant_verdicts) + + def _save_verify_csv(self) -> None: + if not self.variant_verdicts: + return + path, _ = QFileDialog.getSaveFileName( + self, tr("verify.save_csv"), "snp_report.csv", "CSV (*.csv)" + ) + if path: + export.write_text(path, verdicts_csv(self.variant_verdicts)) + self._say(tr("export.done", path=path), 5000) + + def _save_verify_xlsx(self) -> None: + if not self.variant_verdicts: + return + path, _ = QFileDialog.getSaveFileName( + self, tr("verify.save_xlsx"), "snp_report.xlsx", "Excel (*.xlsx)" + ) + if not path: + return + try: + verdicts_xlsx(path, self.variant_verdicts, sample_id=self._export_id()) + except RuntimeError as exc: + QMessageBox.warning(self, tr("verify.save_xlsx"), str(exc)) + return + self._say(tr("export.done", path=path), 5000) + + + # ------------------------------------------------------------------ batch + def open_folder_dialog(self) -> None: + start = str(self._path.parent) if self._path else "" + folder = QFileDialog.getExistingDirectory(self, tr("menu.file.open_folder"), start) + if folder: + self._scan_folder(Path(folder)) + + def _scan_folder(self, folder: Path) -> None: + self.batch_dock.scan_folder(folder) + + # ------------------------------------------------------------------ view + def _sync_from_view(self) -> None: + total = self.chrom_view._total_points() + visible = self.chrom_view._visible_points() + self.scrollbar.blockSignals(True) + self.scrollbar.setRange(0, max(0, int(total - visible))) + self.scrollbar.setPageStep(max(1, int(visible))) + self.scrollbar.setValue(int(self.chrom_view.offset)) + self.scrollbar.blockSignals(False) + self.minimap.set_view(self.chrom_view.offset, visible, total) + + def apply_theme(self, name: str) -> None: + colors = palette(name) + self.chrom_view.set_theme(colors) + self.minimap.set_theme(colors) + for base, box in self._channel_boxes.items(): + box.setStyleSheet( + f"QCheckBox {{ color: {colors['bases'][base]}; font-weight: bold; padding: 0 4px; }}" + ) + + # --------------------------------------------------------------- editing + def _sync_actions(self) -> None: + model = self.read_model + self.undo_action.setEnabled(bool(model and model.can_undo)) + self.redo_action.setEnabled(bool(model and model.can_redo)) + + def refresh_read(self) -> None: + if self.read_model is None: + return + chrom = self.read_model.current() + self.chrom_view.set_chromatogram(chrom, keep_view=True) + self.chrom_view.set_edited(self.read_model.edited) + self.minimap.set_chromatogram(chrom) + self.minimap.set_highlights([]) + self._search_ranges = [] + self._search_pos = -1 + self._refresh_info(chrom) + self._sync_actions() + self.title_changed.emit( + f"ab1kit — {self._path.name}" + ("*" if self.read_model.modified else "") + ) + if self.reference_seq: + self._realign() + + def _after_edit(self) -> None: + self.refresh_read() + self.read_edited.emit(self._path) + + def apply_base_change(self, index: int, base: str) -> None: + if self.read_model: + self.read_model.set_base(index, base) + self._after_edit() + + def apply_base_insert(self, index: int, base: str) -> None: + if self.read_model: + self.read_model.insert_base(index, base) + self._after_edit() + + def apply_base_delete(self, index: int) -> None: + if self.read_model: + self.read_model.delete_base(index) + self._after_edit() + + def apply_trim_range(self, start: int, end: int) -> None: + if not self.read_model: + return + try: + self.read_model.apply_trim(start, end) + except ValueError as exc: + QMessageBox.warning(self, tr("trim.title"), str(exc)) + return + self.chrom_view.set_trim_region(None) + self._after_edit() + self._say(tr("trim.status", n=len(self.read_model.seq))) + + def undo_read(self) -> None: + if self.read_model and self.read_model.undo(): + self._after_edit() + + def redo_read(self) -> None: + if self.read_model and self.read_model.redo(): + self._after_edit() + + def reverse_complement_read(self) -> None: + if self.read_model: + self.read_model.reverse_complement() + self._after_edit() + + def _on_base_clicked(self, index: int, global_pos) -> None: + if self.read_model is None: + return + menu = QMenu(self) + change = menu.addMenu(tr("edit.change")) + for letter in IUPAC_LETTERS: + change.addAction(letter, lambda l=letter: self.apply_base_change(index, l)) + insert_left = menu.addMenu(tr("edit.insert_left")) + for letter in INSERT_LETTERS: + insert_left.addAction(letter, lambda l=letter: self.apply_base_insert(index, l)) + insert_right = menu.addMenu(tr("edit.insert_right")) + for letter in INSERT_LETTERS: + insert_right.addAction(letter, lambda l=letter: self.apply_base_insert(index + 1, l)) + menu.addSeparator() + menu.addAction(tr("edit.delete"), lambda: self.apply_base_delete(index)) + menu.exec(global_pos) + + # ------------------------------------------------------------------ trim + def _open_trim_dialog(self) -> None: + if self.read_model is None or self.trim_dialog is not None: + return + start, end = trim_window( + self.read_model.quality, self.config.trim_window, self.config.trim_min_q + ) + self.chrom_view.set_trim_region((start, end)) + dialog = TrimDialog( + lambda: self.read_model.quality, + self.config.trim_window, + self.config.trim_min_q, + len(self.read_model.seq), + self, + ) + self.trim_dialog = dialog + dialog.region_changed.connect( + lambda start, end: self.chrom_view.set_trim_region((start, end)) + ) + self.chrom_view.trim_range_changed.connect(dialog.set_region) + dialog.apply_requested.connect(self._apply_trim_from_dialog) + dialog.finished.connect(self._trim_dialog_closed) + dialog.show() + + def _apply_trim_from_dialog(self, start: int, end: int) -> None: + if self.trim_dialog is not None: + self.config.trim_window = self.trim_dialog.window_value() + self.config.trim_min_q = self.trim_dialog.minq_value() + save_config(self.config) + self.apply_trim_range(start, end) + + def _trim_dialog_closed(self) -> None: + dialog = self.trim_dialog + self.trim_dialog = None + if dialog is not None: + try: + self.chrom_view.trim_range_changed.disconnect(dialog.set_region) + except RuntimeError: + pass + self.chrom_view.set_trim_region(None) + + # ---------------------------------------------------------------- search + def _search(self) -> None: + if self.chrom_view.chrom is None: + return + dialog = SearchDialog(self) + if dialog.exec() != QDialog.DialogCode.Accepted: + return + pattern = dialog.pattern() + if not pattern: + return + seq = self.chrom_view.chrom.seq + try: + fwd = find_matches(pattern, seq) + rev = find_matches(pattern, seq, reverse=True) if dialog.want_reverse() else [] + except ValueError as exc: + QMessageBox.warning(self, tr("search.title"), str(exc)) + return + ranges = [(i, i + len(pattern)) for i in fwd + rev] + self.chrom_view.set_highlights(ranges) + self.minimap.set_highlights(ranges) + self._search_ranges = ranges + self._search_pos = -1 + if ranges: + self._say( + tr("search.found", n=len(ranges), f=len(fwd), r=len(rev)) + ) + self._find_next() + else: + self._say(tr("search.none")) + + def _find_next(self) -> None: + if not self._search_ranges: + return + self._search_pos = (self._search_pos + 1) % len(self._search_ranges) + self.chrom_view.goto_base(self._search_ranges[self._search_pos][0] + 1) + + # ----------------------------------------------------------- goto and info + def _goto(self) -> None: + chrom = self.chrom_view.chrom + if chrom is None: + return + number, ok = QInputDialog.getInt( + self, tr("goto.title"), tr("goto.label"), 1, 1, len(chrom.seq) + ) + if ok: + self.chrom_view.goto_base(number) + + def _refresh_info(self, chrom: Chromatogram) -> None: + page = QWidget() + form = QFormLayout(page) + form.setContentsMargins(8, 8, 8, 8) + + def row(label: str, value) -> None: + widget = QLabel(str(value)) + widget.setWordWrap(True) + form.addRow(QLabel(label), widget) + + row(tr("info.file"), self._path) + row(tr("info.length"), len(chrom.seq)) + row(tr("info.mean_q"), f"{sum(chrom.quality) / max(1, len(chrom.quality)):.1f}") + row(tr("info.q20"), sum(1 for q in chrom.quality if q >= 20)) + meta_keys = ( + ("sample", "meta.sample"), + ("instrument", "meta.instrument"), + ("run_date", "meta.run_date"), + ("run_time", "meta.run_time"), + ("project", "meta.project"), + ("capillary", "meta.capillary"), + ("mobility", "meta.mobility"), + ("comment", "meta.comment"), + ) + for key, label_key in meta_keys: + if key in chrom.metadata: + row(tr(label_key), chrom.metadata[key]) + self.info_dock.setWidget(page) + + # ------------------------------------------------------- export and sessions + def _export_target(self, caption: str, suffix: str, pattern: str) -> str | None: + default = (self._path.stem if self._path else "read") + suffix + path, _ = QFileDialog.getSaveFileName(self, caption, default, pattern) + return path or None + + def _export_fasta(self) -> None: + if not self.read_model: + return + path = self._export_target(tr("menu.file.export_fasta"), ".fasta", "FASTA (*.fasta)") + if path: + export.write_text(path, export.to_fasta(self._export_id(), "".join(self.read_model.seq))) + self._say(tr("export.done", path=path), 5000) + + def _export_fastq(self) -> None: + if not self.read_model: + return + path = self._export_target(tr("menu.file.export_fastq"), ".fastq", "FASTQ (*.fastq)") + if path: + content = export.to_fastq( + self._export_id(), "".join(self.read_model.seq), self.read_model.quality + ) + export.write_text(path, content) + self._say(tr("export.done", path=path), 5000) + + def _export_id(self) -> str: + return self.read_model.current().sample_id if self.read_model else "read" + + def _export_png(self) -> None: + path = self._export_target(tr("menu.file.export_png"), ".png", "PNG (*.png)") + if path and self.chrom_view.grab().save(path): + self._say(tr("export.done", path=path), 5000) + + def _export_pdf(self) -> None: + path = self._export_target(tr("menu.file.export_pdf"), ".pdf", "PDF (*.pdf)") + if not path: + return + pixmap = self.chrom_view.grab() + writer = QPdfWriter(path) + writer.setPageSize(QPageSize(QSizeF(pixmap.width(), pixmap.height()), QPageSize.Unit.Point)) + writer.setPageMargins(QMarginsF(0, 0, 0, 0)) + painter = QPainter(writer) + painter.drawPixmap(0, 0, writer.width(), writer.height(), pixmap) + painter.end() + self._say(tr("export.done", path=path), 5000) + + def _copy_sequence(self) -> None: + if self.read_model: + QApplication.clipboard().setText("".join(self.read_model.seq)) + self._say( + tr("copy.done", n=len(self.read_model.seq)), 3000 + ) + + def _save_session(self) -> None: + if self.read_model is None or self._path is None: + return + sessions.save_session( + sessions.session_path(self._path), + {"source": self._path.name, **self.read_model.to_dict()}, + ) + self._say(tr("session.saved"), 3000) + self.read_edited.emit(self._path) + + def autosave_session(self) -> None: + """Called by the shell on close: keep unsaved edits in the sidecar.""" + if self.read_model is not None and self._path is not None: + sidecar = sessions.session_path(self._path) + try: + if self.read_model.modified: + sessions.save_session( + sidecar, {"source": self._path.name, **self.read_model.to_dict()} + ) + elif sidecar.exists(): + sidecar.unlink() + except OSError: + pass diff --git a/ui/read_view/verify_dock.py b/ui/read_view/verify_dock.py new file mode 100644 index 0000000..6403fea --- /dev/null +++ b/ui/read_view/verify_dock.py @@ -0,0 +1,87 @@ +"""Expected-SNP verification dock: verdict table with CSV/XLSX buttons.""" + +from __future__ import annotations + +from PySide6.QtCore import Qt +from PySide6.QtGui import QColor +from PySide6.QtWidgets import ( + QDockWidget, + QHBoxLayout, + QPushButton, + QTableWidget, + QTableWidgetItem, + QVBoxLayout, + QWidget, +) + +from i18n import tr + + +class VerifyDock(QDockWidget): + def __init__(self, parent: QWidget | None = None) -> None: + super().__init__(tr("verify.title"), parent) + self.verify_table = QTableWidget(0, 8) + self.verify_table.setHorizontalHeaderLabels( + [ + tr("verify.col.name"), + tr("verify.col.pos"), + tr("verify.col.ref"), + tr("verify.col.alt"), + tr("verify.col.verdict"), + tr("verify.col.observed"), + tr("verify.col.q"), + tr("verify.col.note"), + ] + ) + self.verify_table.verticalHeader().setVisible(False) + self.verify_table.setEditTriggers(QTableWidget.EditTrigger.NoEditTriggers) + self.verify_table.setSortingEnabled(True) + buttons = QWidget() + row = QHBoxLayout(buttons) + self.csv_button = QPushButton(tr("verify.save_csv")) + self.xlsx_button = QPushButton(tr("verify.save_xlsx")) + row.addWidget(self.csv_button) + row.addWidget(self.xlsx_button) + row.addStretch(1) + container = QWidget() + layout = QVBoxLayout(container) + layout.setContentsMargins(0, 0, 0, 0) + layout.addWidget(self.verify_table) + layout.addWidget(buttons) + self.setWidget(container) + + def fill(self, verdicts: list) -> None: + labels = { + "confirmed": tr("verify.confirmed"), + "heterozygous": tr("verify.heterozygous"), + "not_found": tr("verify.not_found"), + "no_data": tr("verify.no_data"), + "ref_mismatch": tr("verify.ref_mismatch"), + "low_quality": tr("verify.low_quality"), + "unsupported": tr("verify.unsupported"), + } + colors = { + "confirmed": "#1e9e1e", + "heterozygous": "#e0a000", + "not_found": "#e02020", + } + self.verify_table.setSortingEnabled(False) + self.verify_table.setRowCount(len(verdicts)) + for row, v in enumerate(verdicts): + values = [ + v.variant.name, + v.variant.position, + v.variant.ref, + v.variant.alt, + labels.get(v.verdict, v.verdict), + v.observed, + v.quality if v.quality is not None else "", + tr(f"verify.note.{v.note_code}", **v.note_args) if v.note_code else v.note, + ] + for col, value in enumerate(values): + item = QTableWidgetItem() + item.setData(Qt.ItemDataRole.DisplayRole, value) + if col == 4 and v.verdict in colors: + item.setForeground(QColor(colors[v.verdict])) + self.verify_table.setItem(row, col, item) + self.verify_table.setSortingEnabled(True) From b118e6057c98703cc3604760babf70d1a926e0c2 Mon Sep 17 00:00:00 2001 From: Aleksey Drobin <43707931+adrobi@users.noreply.github.com> Date: Fri, 30 Oct 2026 10:15:19 +0300 Subject: [PATCH 21/44] ui: ReadView owns undo/redo actions; broaden read_edited tests Co-Authored-By: Claude Sonnet 5.5 --- tests/test_smoke_gui.py | 38 ++++++++++++++++++++++++++++++-------- tests/test_ui_tasks.py | 3 --- ui/main_window.py | 2 -- ui/read_view/menus.py | 8 -------- ui/read_view/read_view.py | 14 ++++++++++---- 5 files changed, 40 insertions(+), 25 deletions(-) diff --git a/tests/test_smoke_gui.py b/tests/test_smoke_gui.py index f6aa9dd..b9c62b8 100644 --- a/tests/test_smoke_gui.py +++ b/tests/test_smoke_gui.py @@ -352,19 +352,41 @@ def test_reverse_read_reference_overlay_in_displayed_orientation(qapp): @pytest.mark.skipif(not AB1, reason="no example .ab1 files") -def test_read_view_emits_read_edited_on_edit_and_undo(qapp): +def test_read_view_emits_read_edited(qapp): from chrom_core.config import AppConfig from ui.main_window import MainWindow window = MainWindow(AppConfig(recent_files=[])) emitted = [] window.read_view.read_edited.connect(emitted.append) - assert window.read_view.open_path(AB1[0]) + view = window.read_view + assert view.open_path(AB1[0]) assert emitted == [] # opening is not an edit - assert window.read_view.current_model() is window.read_model - - window.read_view.apply_base_change(0, "N") - assert emitted == [Path(AB1[0])] - window.read_view.undo_read() - assert emitted == [Path(AB1[0])] * 2 + assert view.current_model() is window.read_model + + expected = [Path(AB1[0])] + steps = [ + lambda: view.apply_base_change(0, "N"), + view.undo_read, + view.redo_read, + lambda: view.apply_trim_range(10, 100), + view.reverse_complement_read, + view._save_session, + ] + for count, step in enumerate(steps, start=1): + step() + assert emitted == expected * count window.close() + assert emitted == expected * len(steps) # close-time autosave does not emit + + +@pytest.mark.skipif(not AB1, reason="no example .ab1 files") +def test_bare_read_view_works_without_shell_menus(qapp): + from chrom_core.config import AppConfig + from ui.read_view import ReadView + + view = ReadView(AppConfig(recent_files=[]), lambda *a, **k: None) + assert view.open_path(AB1[0]) + view.apply_base_change(0, "N") + assert view.undo_action.isEnabled() + view.close() diff --git a/tests/test_ui_tasks.py b/tests/test_ui_tasks.py index 5a707b1..4f21ce6 100644 --- a/tests/test_ui_tasks.py +++ b/tests/test_ui_tasks.py @@ -132,7 +132,6 @@ def test_main_window_blast_uses_task_and_cancel_drops_result(qapp, monkeypatch, from ui.main_window import MainWindow monkeypatch.setattr("ui.main_window.save_config", lambda *a, **k: None) - monkeypatch.setattr("ui.read_view.read_view.save_config", lambda *a, **k: None) opened = [] monkeypatch.setattr( @@ -198,7 +197,6 @@ def test_scan_last_start_wins(qapp, monkeypatch, tmp_path): from ui.main_window import MainWindow monkeypatch.setattr("ui.main_window.save_config", lambda *a, **k: None) - monkeypatch.setattr("ui.read_view.read_view.save_config", lambda *a, **k: None) real = batch.scan_folder @@ -229,7 +227,6 @@ def test_second_blast_cancels_first(qapp, monkeypatch): from ui.main_window import MainWindow monkeypatch.setattr("ui.main_window.save_config", lambda *a, **k: None) - monkeypatch.setattr("ui.read_view.read_view.save_config", lambda *a, **k: None) opened = [] monkeypatch.setattr( diff --git a/ui/main_window.py b/ui/main_window.py index 6de6e90..22f0a78 100644 --- a/ui/main_window.py +++ b/ui/main_window.py @@ -135,7 +135,6 @@ def on_done(result: object) -> None: task.finished.connect(on_done) return task - # ------------------------------------------------------------------ menus def _build_menus(self) -> None: file_menu = self.menuBar().addMenu(tr("menu.file")) @@ -228,7 +227,6 @@ def _fill_recent_menu(self) -> None: ) self.recent_menu.addAction(action) - # ------------------------------------------------- delegates to the read view def open_path(self, path: str | Path) -> bool: return self.read_view.open_path(path) diff --git a/ui/read_view/menus.py b/ui/read_view/menus.py index 5d7959a..42a8e01 100644 --- a/ui/read_view/menus.py +++ b/ui/read_view/menus.py @@ -36,15 +36,7 @@ def add_file_actions(view, file_menu: QMenu) -> None: def add_edit_actions(view, edit_menu: QMenu) -> None: - view.undo_action = QAction(tr("menu.edit.undo"), view) - view.undo_action.setShortcut("Ctrl+Z") - view.undo_action.triggered.connect(view.undo_read) - view.undo_action.setEnabled(False) edit_menu.addAction(view.undo_action) - view.redo_action = QAction(tr("menu.edit.redo"), view) - view.redo_action.setShortcut("Ctrl+Y") - view.redo_action.triggered.connect(view.redo_read) - view.redo_action.setEnabled(False) edit_menu.addAction(view.redo_action) edit_menu.addSeparator() find_action = QAction(tr("menu.edit.find"), view) diff --git a/ui/read_view/read_view.py b/ui/read_view/read_view.py index 66e1065..d1d9f09 100644 --- a/ui/read_view/read_view.py +++ b/ui/read_view/read_view.py @@ -85,6 +85,15 @@ def __init__(self, config: AppConfig, start_task: Callable, parent: QWidget | No layout.addWidget(self.scrollbar) self.setCentralWidget(central) + self.undo_action = QAction(tr("menu.edit.undo"), self) + self.undo_action.setShortcut("Ctrl+Z") + self.undo_action.triggered.connect(self.undo_read) + self.undo_action.setEnabled(False) + self.redo_action = QAction(tr("menu.edit.redo"), self) + self.redo_action.setShortcut("Ctrl+Y") + self.redo_action.triggered.connect(self.redo_read) + self.redo_action.setEnabled(False) + self._channel_boxes: dict[str, QCheckBox] = {} self._build_toolbar() self._build_docks() @@ -178,7 +187,6 @@ def _connect(self) -> None: lambda value: self.chrom_view.set_offset(float(value)) ) - def open_path(self, path: str | Path) -> bool: try: chrom = read_ab1(path) @@ -347,7 +355,6 @@ def done(rid: object) -> None: key="blast", ) - def _verify_dialog(self) -> None: if not (self.read_model and self.alignment and self.reference_seq): self._say(tr("verify.need_reference"), 6000) @@ -431,7 +438,6 @@ def _save_verify_xlsx(self) -> None: return self._say(tr("export.done", path=path), 5000) - # ------------------------------------------------------------------ batch def open_folder_dialog(self) -> None: start = str(self._path.parent) if self._path else "" @@ -728,7 +734,7 @@ def _save_session(self) -> None: self.read_edited.emit(self._path) def autosave_session(self) -> None: - """Called by the shell on close: keep unsaved edits in the sidecar.""" + """Called by the shell on close: save the sidecar if modified, else delete a stale one.""" if self.read_model is not None and self._path is not None: sidecar = sessions.session_path(self._path) try: From cf0423e421f0da235302e0b99b162961adcf3897 Mon Sep 17 00:00:00 2001 From: Aleksey Drobin <43707931+adrobi@users.noreply.github.com> Date: Fri, 30 Oct 2026 10:22:19 +0300 Subject: [PATCH 22/44] ui: QSS theme, icons, unified status palette, coloured quality bars Co-Authored-By: Claude Sonnet 5.5 --- ab1kit.spec | 8 ++- i18n.py | 2 + pyproject.toml | 3 + scripts/render_preview.py | 47 +++++++++++++-- tests/test_smoke_gui.py | 83 +++++++++++++++++++++++++++ translations_en.py | 2 + ui/chrom_view.py | 3 +- ui/icons/LICENSE | 43 ++++++++++++++ ui/icons/README.md | 3 + ui/icons/copy.svg | 14 +++++ ui/icons/dna.svg | 23 ++++++++ ui/icons/flask-conical.svg | 15 +++++ ui/icons/folder-open.svg | 13 +++++ ui/icons/globe.svg | 15 +++++ ui/icons/info.svg | 15 +++++ ui/icons/maximize.svg | 16 ++++++ ui/icons/moon.svg | 13 +++++ ui/icons/redo-2.svg | 14 +++++ ui/icons/rotate-ccw.svg | 14 +++++ ui/icons/save.svg | 15 +++++ ui/icons/scissors.svg | 17 ++++++ ui/icons/search.svg | 14 +++++ ui/icons/table-2.svg | 15 +++++ ui/icons/undo-2.svg | 14 +++++ ui/icons/zoom-in.svg | 16 ++++++ ui/icons/zoom-out.svg | 15 +++++ ui/main_window.py | 5 ++ ui/minimap.py | 3 +- ui/read_view/analysis_dock.py | 12 ++-- ui/read_view/batch_dock.py | 14 ++--- ui/read_view/menus.py | 10 ++++ ui/read_view/read_view.py | 39 +++++++++++-- ui/read_view/verify_dock.py | 25 +++++--- ui/status.py | 104 ++++++++++++++++++++++++++++++++++ ui/style.qss | 57 +++++++++++++++++++ ui/style_dark.qss | 57 +++++++++++++++++++ ui/tables.py | 32 +++++++++++ ui/theme.py | 36 ++++++------ 38 files changed, 795 insertions(+), 51 deletions(-) create mode 100644 ui/icons/LICENSE create mode 100644 ui/icons/README.md create mode 100644 ui/icons/copy.svg create mode 100644 ui/icons/dna.svg create mode 100644 ui/icons/flask-conical.svg create mode 100644 ui/icons/folder-open.svg create mode 100644 ui/icons/globe.svg create mode 100644 ui/icons/info.svg create mode 100644 ui/icons/maximize.svg create mode 100644 ui/icons/moon.svg create mode 100644 ui/icons/redo-2.svg create mode 100644 ui/icons/rotate-ccw.svg create mode 100644 ui/icons/save.svg create mode 100644 ui/icons/scissors.svg create mode 100644 ui/icons/search.svg create mode 100644 ui/icons/table-2.svg create mode 100644 ui/icons/undo-2.svg create mode 100644 ui/icons/zoom-in.svg create mode 100644 ui/icons/zoom-out.svg create mode 100644 ui/status.py create mode 100644 ui/style.qss create mode 100644 ui/style_dark.qss create mode 100644 ui/tables.py diff --git a/ab1kit.spec b/ab1kit.spec index 57335b5..f348d0a 100644 --- a/ab1kit.spec +++ b/ab1kit.spec @@ -8,8 +8,12 @@ a = Analysis( ["chrom_cli.py"], pathex=[], binaries=[], - datas=[], - hiddenimports=["chrom_core", "ui", "ui.read_view", "i18n", "translations_en"], + datas=[ + ("ui/style.qss", "ui"), + ("ui/style_dark.qss", "ui"), + ("ui/icons", "ui/icons"), + ], + hiddenimports=["chrom_core", "ui", "ui.read_view", "ui.status", "ui.tables", "i18n", "translations_en"], hookspath=[], excludes=["tkinter", "matplotlib", "numpy.tests"], noarchive=False, diff --git a/i18n.py b/i18n.py index 240a1bc..3cac432 100644 --- a/i18n.py +++ b/i18n.py @@ -94,6 +94,8 @@ "tb.zoom_out": "Отдалить", "tb.fit": "Весь рид", "tb.reset": "Сброс вида", + "tb.quality_legend": "Качество Q:", + "tb.quality_legend.tip": "Цвет полос качества: красный Q<20, жёлтый 20–29, зелёный ≥30", "goto.title": "Перейти к базе", "goto.label": "Номер базы", "search.title": "Поиск подпоследовательности", diff --git a/pyproject.toml b/pyproject.toml index 74be108..2cda6cb 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -25,6 +25,9 @@ ab1kit = "chrom_cli:main" packages = ["chrom_core", "ui", "ui.read_view"] py-modules = ["chrom_cli", "i18n", "translations_en"] +[tool.setuptools.package-data] +ui = ["style.qss", "style_dark.qss", "icons/*.svg", "icons/LICENSE", "icons/README.md"] + [tool.pytest.ini_options] testpaths = ["tests"] pythonpath = ["tests"] diff --git a/scripts/render_preview.py b/scripts/render_preview.py index 7a8da22..1bdb1cd 100644 --- a/scripts/render_preview.py +++ b/scripts/render_preview.py @@ -1,6 +1,8 @@ """Render the chromatogram widget offscreen to a PNG (dev smoke check). -Usage: python scripts/render_preview.py [sample.ab1] [out.png] +Usage: python scripts/render_preview.py [sample.ab1] [out.png] [--theme light|dark] [--window] + +--window renders the whole main window (toolbar, docks, tables) instead of the bare widget. """ from __future__ import annotations @@ -14,16 +16,53 @@ from PySide6.QtWidgets import QApplication # noqa: E402 -from chrom_core import read_ab1 # noqa: E402 +from chrom_core import batch, read_ab1 # noqa: E402 from ui.chrom_view import ChromatogramWidget # noqa: E402 +def render_window(src: Path, out: Path, theme: str) -> None: + from chrom_core.config import AppConfig + from ui.main_window import MainWindow + + app = QApplication.instance() + app.setStyle("Fusion") + window = MainWindow(AppConfig(recent_files=[], theme=theme)) + window.resize(1300, 820) + window.show() + window.open_path(src) + seq = "".join(window.read_model.seq) + ref = list(seq[100:400]) + ref[50] = "A" if ref[50] != "A" else "C" + ref[120] = "G" if ref[120] != "G" else "T" + window._set_reference_seq("".join(ref)) + rows = ["name;pos;ref;alt", f"snp1;51;{seq[150]};T", f"snp2;121;{seq[220]};G"] + window._verify_variants("\n".join(rows) + "\n") + window.batch_dock.show() + window.batch_panel.show_reports(batch.scan_folder(src.parent)) + for _ in range(20): + app.processEvents() + window.grab().save(str(out)) + print(f"{src.name} [{theme}] -> {out}") + window.close() + + def main() -> None: examples = sorted((Path(__file__).resolve().parent.parent / "examples").glob("*.ab1")) - src = Path(sys.argv[1]) if len(sys.argv) > 1 else examples[0] - out = Path(sys.argv[2]) if len(sys.argv) > 2 else Path(tempfile.gettempdir()) / "ab1kit_preview.png" + argv = sys.argv[1:] + theme = "light" + if "--theme" in argv: + i = argv.index("--theme") + theme = argv[i + 1] + del argv[i:i + 2] + window_mode = "--window" in argv + argv = [a for a in argv if a != "--window"] + src = Path(argv[0]) if argv else examples[0] + out = Path(argv[1]) if len(argv) > 1 else Path(tempfile.gettempdir()) / "ab1kit_preview.png" app = QApplication([]) + if window_mode: + render_window(src, out, theme) + return view = ChromatogramWidget() view.resize(1200, 700) view.set_chromatogram(read_ab1(src)) diff --git a/tests/test_smoke_gui.py b/tests/test_smoke_gui.py index b9c62b8..574ae72 100644 --- a/tests/test_smoke_gui.py +++ b/tests/test_smoke_gui.py @@ -390,3 +390,86 @@ def test_bare_read_view_works_without_shell_menus(qapp): view.apply_base_change(0, "N") assert view.undo_action.isEnabled() view.close() + + +# ------------------------------------------------------------------ Task 13: theme +def test_toolbar_actions_have_icons(qapp): + from PySide6.QtWidgets import QToolBar + + from chrom_core.config import AppConfig + from ui.main_window import MainWindow + + window = MainWindow(AppConfig(recent_files=[])) + bar = window.read_view.findChild(QToolBar) + actions = [a for a in bar.actions() if not a.isSeparator() and a.text()] + assert actions + assert all(not a.icon().isNull() for a in actions), [a.text() for a in actions if a.icon().isNull()] + window.close() + + +def test_quality_colour_thresholds_and_palette(qapp): + from chrom_core.clone_report import STATUS_HEX + from ui.status import quality_color, status_color + + for theme in ("light", "dark"): + assert quality_color(15, theme) != quality_color(35, theme) + assert quality_color(19, theme) != quality_color(20, theme) + assert quality_color(20, theme) == quality_color(29, theme) + assert quality_color(29, theme) != quality_color(30, theme) + assert quality_color(30, theme) == quality_color(60, theme) + for verdict, (light, dark) in STATUS_HEX.items(): + assert status_color(verdict, "light").name() == light + assert status_color(verdict, "dark").name() == dark + + +def test_minimap_and_chrom_view_share_quality_buckets(qapp): + from ui.status import quality_bucket + + assert [quality_bucket(q) for q in (0, 19, 20, 29, 30, 99)] == [ + "low_q", "low_q", "mid_q", "mid_q", "high_q", "high_q"] + + +def test_status_chip_is_label(qapp): + from PySide6.QtWidgets import QLabel + + from ui.status import status_chip + + chip = status_chip("ok", "OK") + assert isinstance(chip, QLabel) and chip.text() == "OK" + assert "border-radius" in chip.styleSheet() + + +def test_stylesheet_applies_in_both_themes(qapp): + from chrom_core.config import AppConfig + from ui.main_window import MainWindow + + window = MainWindow(AppConfig(recent_files=[])) + seen = [] + for name in ("light", "dark"): + window.set_theme(name) + assert qapp.styleSheet().strip() + seen.append(qapp.styleSheet()) + assert seen[0] != seen[1] + window.close() + + +def test_tables_stretch_last_column_and_tooltip_notes(qapp): + from PySide6.QtWidgets import QHeaderView + + from chrom_core.config import AppConfig + from ui.main_window import MainWindow + + sample = next(p for p in AB1 if "3730" in p.name) + window = MainWindow(AppConfig(recent_files=[])) + assert window.open_path(sample) + seq = "".join(window.read_model.seq) + ref = seq[100:400] + window._set_reference_seq(ref) + wrong = "A" if ref[50] != "A" else "C" + window._verify_variants(f"name;pos;ref;alt\nsnp;51;{wrong};T\n") + for table in (window.verify_table, window.diff_table, window.batch_panel.table): + assert table.horizontalHeader().stretchLastSection() + assert table.horizontalHeader().sectionResizeMode(0) != QHeaderView.ResizeMode.Fixed + note = window.verify_table.item(0, 7) + assert note.text() and note.toolTip() == note.text() + window.close() diff --git a/translations_en.py b/translations_en.py index a6ec709..a14f9b8 100644 --- a/translations_en.py +++ b/translations_en.py @@ -87,6 +87,8 @@ "tb.zoom_out": "Zoom out", "tb.fit": "Fit read", "tb.reset": "Reset view", + "tb.quality_legend": "Quality Q:", + "tb.quality_legend.tip": "Quality bar colours: red Q<20, yellow 20–29, green ≥30", "goto.title": "Go to base", "goto.label": "Base number", "search.title": "Find subsequence", diff --git a/ui/chrom_view.py b/ui/chrom_view.py index 0478ac5..3ed01f0 100644 --- a/ui/chrom_view.py +++ b/ui/chrom_view.py @@ -10,6 +10,7 @@ from chrom_core import Chromatogram from i18n import tr +from ui.status import quality_bucket from ui.theme import LIGHT MIN_ZOOM = 0.02 @@ -525,7 +526,7 @@ def _paint_bases(self, painter: QPainter, w: int, h: int) -> None: prev_peak = peak continue prev_peak = peak - bucket = "low_q" if q < 10 else "mid_q" if q < 20 else "high_q" + bucket = quality_bucket(q) painter.setPen(Qt.PenStyle.NoPen) painter.setBrush(QColor(self.theme[bucket])) bar_h = int((Q_STRIP_H - 6) * q / max_q) diff --git a/ui/icons/LICENSE b/ui/icons/LICENSE new file mode 100644 index 0000000..718bb3f --- /dev/null +++ b/ui/icons/LICENSE @@ -0,0 +1,43 @@ +ISC License + +Copyright (c) 2026 Lucide Icons and Contributors + +Permission to use, copy, modify, and/or distribute this software for any +purpose with or without fee is hereby granted, provided that the above +copyright notice and this permission notice appear in all copies. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +--- + +The following Lucide icons are derived from the Feather project: + +airplay, alert-circle, alert-octagon, alert-triangle, aperture, arrow-down-circle, arrow-down-left, arrow-down-right, arrow-down, arrow-left-circle, arrow-left, arrow-right-circle, arrow-right, arrow-up-circle, arrow-up-left, arrow-up-right, arrow-up, at-sign, calendar, cast, check, chevron-down, chevron-left, chevron-right, chevron-up, chevrons-down, chevrons-left, chevrons-right, chevrons-up, circle, clipboard, clock, code, columns, command, compass, corner-down-left, corner-down-right, corner-left-down, corner-left-up, corner-right-down, corner-right-up, corner-up-left, corner-up-right, crosshair, database, divide-circle, divide-square, dollar-sign, download, external-link, feather, frown, hash, headphones, help-circle, info, italic, key, layout, life-buoy, link-2, link, loader, lock, log-in, log-out, maximize, meh, minimize, minimize-2, minus-circle, minus-square, minus, monitor, moon, more-horizontal, more-vertical, move, music, navigation-2, navigation, octagon, pause-circle, percent, plus-circle, plus-square, plus, power, radio, rss, search, server, share, shopping-bag, sidebar, smartphone, smile, square, table-2, tablet, target, terminal, trash-2, trash, triangle, tv, type, upload, x-circle, x-octagon, x-square, x, zoom-in, zoom-out + +The MIT License (MIT) (for the icons listed above) + +Copyright (c) 2013-present Cole Bemis + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/ui/icons/README.md b/ui/icons/README.md new file mode 100644 index 0000000..9869754 --- /dev/null +++ b/ui/icons/README.md @@ -0,0 +1,3 @@ +Icons are from Lucide (https://lucide.dev), release 1.65.0, downloaded from +https://raw.githubusercontent.com/lucide-icons/lucide/1.65.0/icons/.svg +License: ISC (some icons MIT, Feather) - see LICENSE in this folder. Only the icons used by ab1kit are included. diff --git a/ui/icons/copy.svg b/ui/icons/copy.svg new file mode 100644 index 0000000..f62ce99 --- /dev/null +++ b/ui/icons/copy.svg @@ -0,0 +1,14 @@ + + + + diff --git a/ui/icons/dna.svg b/ui/icons/dna.svg new file mode 100644 index 0000000..f2e63c0 --- /dev/null +++ b/ui/icons/dna.svg @@ -0,0 +1,23 @@ + + + + + + + + + + + + + diff --git a/ui/icons/flask-conical.svg b/ui/icons/flask-conical.svg new file mode 100644 index 0000000..5917608 --- /dev/null +++ b/ui/icons/flask-conical.svg @@ -0,0 +1,15 @@ + + + + + diff --git a/ui/icons/folder-open.svg b/ui/icons/folder-open.svg new file mode 100644 index 0000000..b01f60f --- /dev/null +++ b/ui/icons/folder-open.svg @@ -0,0 +1,13 @@ + + + diff --git a/ui/icons/globe.svg b/ui/icons/globe.svg new file mode 100644 index 0000000..53c80ee --- /dev/null +++ b/ui/icons/globe.svg @@ -0,0 +1,15 @@ + + + + + diff --git a/ui/icons/info.svg b/ui/icons/info.svg new file mode 100644 index 0000000..2a46eac --- /dev/null +++ b/ui/icons/info.svg @@ -0,0 +1,15 @@ + + + + + diff --git a/ui/icons/maximize.svg b/ui/icons/maximize.svg new file mode 100644 index 0000000..f78ca32 --- /dev/null +++ b/ui/icons/maximize.svg @@ -0,0 +1,16 @@ + + + + + + diff --git a/ui/icons/moon.svg b/ui/icons/moon.svg new file mode 100644 index 0000000..3c4bc31 --- /dev/null +++ b/ui/icons/moon.svg @@ -0,0 +1,13 @@ + + + diff --git a/ui/icons/redo-2.svg b/ui/icons/redo-2.svg new file mode 100644 index 0000000..72371c8 --- /dev/null +++ b/ui/icons/redo-2.svg @@ -0,0 +1,14 @@ + + + + diff --git a/ui/icons/rotate-ccw.svg b/ui/icons/rotate-ccw.svg new file mode 100644 index 0000000..eb0fe34 --- /dev/null +++ b/ui/icons/rotate-ccw.svg @@ -0,0 +1,14 @@ + + + + diff --git a/ui/icons/save.svg b/ui/icons/save.svg new file mode 100644 index 0000000..07af070 --- /dev/null +++ b/ui/icons/save.svg @@ -0,0 +1,15 @@ + + + + + diff --git a/ui/icons/scissors.svg b/ui/icons/scissors.svg new file mode 100644 index 0000000..f87bf20 --- /dev/null +++ b/ui/icons/scissors.svg @@ -0,0 +1,17 @@ + + + + + + + diff --git a/ui/icons/search.svg b/ui/icons/search.svg new file mode 100644 index 0000000..03e442a --- /dev/null +++ b/ui/icons/search.svg @@ -0,0 +1,14 @@ + + + + diff --git a/ui/icons/table-2.svg b/ui/icons/table-2.svg new file mode 100644 index 0000000..fa89be6 --- /dev/null +++ b/ui/icons/table-2.svg @@ -0,0 +1,15 @@ + + + + + diff --git a/ui/icons/undo-2.svg b/ui/icons/undo-2.svg new file mode 100644 index 0000000..3e93594 --- /dev/null +++ b/ui/icons/undo-2.svg @@ -0,0 +1,14 @@ + + + + diff --git a/ui/icons/zoom-in.svg b/ui/icons/zoom-in.svg new file mode 100644 index 0000000..11173c0 --- /dev/null +++ b/ui/icons/zoom-in.svg @@ -0,0 +1,16 @@ + + + + + + diff --git a/ui/icons/zoom-out.svg b/ui/icons/zoom-out.svg new file mode 100644 index 0000000..70abec4 --- /dev/null +++ b/ui/icons/zoom-out.svg @@ -0,0 +1,15 @@ + + + + + diff --git a/ui/main_window.py b/ui/main_window.py index 22f0a78..74b5c27 100644 --- a/ui/main_window.py +++ b/ui/main_window.py @@ -20,6 +20,8 @@ from i18n import set_language, tr from ui.read_view import ReadView from ui.tasks import Task, run_task +from ui import status +from ui.status import bind_icon from ui.theme import app_qss try: @@ -140,6 +142,7 @@ def _build_menus(self) -> None: file_menu = self.menuBar().addMenu(tr("menu.file")) self._file_menu = file_menu open_action = QAction(tr("menu.file.open"), self) + bind_icon(open_action, "folder-open") open_action.setShortcut("Ctrl+O") open_action.triggered.connect(self.read_view.open_dialog) file_menu.addAction(open_action) @@ -159,6 +162,7 @@ def _build_menus(self) -> None: view_menu = self.menuBar().addMenu(tr("menu.view")) self.dark_action = QAction(tr("menu.view.dark_theme"), self) + bind_icon(self.dark_action, "moon") self.dark_action.setCheckable(True) self.dark_action.setChecked(self.config.theme == "dark") self.dark_action.toggled.connect( @@ -194,6 +198,7 @@ def _switch_language(self, code: str) -> None: def set_theme(self, name: str) -> None: self.config.theme = name + status.set_theme(name) self.read_view.apply_theme(name) QApplication.instance().setStyleSheet(app_qss(name == "dark")) save_config(self.config) diff --git a/ui/minimap.py b/ui/minimap.py index 264576f..3acc067 100644 --- a/ui/minimap.py +++ b/ui/minimap.py @@ -7,6 +7,7 @@ from PySide6.QtWidgets import QWidget from chrom_core import Chromatogram +from ui.status import quality_bucket from ui.theme import LIGHT STRIP_H = 18 @@ -107,7 +108,7 @@ def _paint_strip(self, painter: QPainter) -> None: y = self._strip_y() peaks = list(chrom.peak_indices) + [self._total] for i, quality in enumerate(chrom.quality): - bucket = "low_q" if quality < 10 else "mid_q" if quality < 20 else "high_q" + bucket = quality_bucket(quality) painter.setBrush(QColor(self.theme[bucket])) x0 = self._x(peaks[i]) x1 = self._x(peaks[i + 1]) diff --git a/ui/read_view/analysis_dock.py b/ui/read_view/analysis_dock.py index 0877466..7fdb71b 100644 --- a/ui/read_view/analysis_dock.py +++ b/ui/read_view/analysis_dock.py @@ -3,12 +3,12 @@ from __future__ import annotations from PySide6.QtCore import Qt -from PySide6.QtGui import QColor from PySide6.QtWidgets import QDockWidget, QTableWidget, QTableWidgetItem, QWidget from chrom_core.align import ReadAlignment from chrom_core.seqops import reverse_complement from i18n import tr +from ui.tables import configure_table, paint_status, set_full_text_tooltip def reference_overlay( @@ -36,6 +36,9 @@ def displayed_diff_index(alignment: ReadAlignment, diff, read_length: int) -> in return n - diff.read_pos - span +DIFF_VERDICT_STATUS = {"homozygous": "ok", "heterozygous": "mixed", "low_quality": "incomplete"} + + class DiffDock(QDockWidget): def __init__(self, parent: QWidget | None = None) -> None: super().__init__(tr("analysis.diffs.title"), parent) @@ -52,7 +55,7 @@ def __init__(self, parent: QWidget | None = None) -> None: tr("snp.col.ratio"), ] ) - self.diff_table.verticalHeader().setVisible(False) + configure_table(self.diff_table) self.diff_table.setEditTriggers(QTableWidget.EditTrigger.NoEditTriggers) self.diff_table.setSortingEnabled(True) self.setWidget(self.diff_table) @@ -94,8 +97,9 @@ def fill(self, alignment: ReadAlignment | None, snp_calls: list, read_length: in for col, value in enumerate(values): item = QTableWidgetItem() item.setData(Qt.ItemDataRole.DisplayRole, value) - if call is not None and col == 5 and call.kind == "heterozygous": - item.setForeground(QColor("#a05000")) + set_full_text_tooltip(item) + if call is not None and col == 5: + paint_status(item, DIFF_VERDICT_STATUS.get(call.kind, "no_data")) self.diff_table.setItem(row, col, item) self.diff_table.setSortingEnabled(True) diff --git a/ui/read_view/batch_dock.py b/ui/read_view/batch_dock.py index a11ee2e..c5feab9 100644 --- a/ui/read_view/batch_dock.py +++ b/ui/read_view/batch_dock.py @@ -6,13 +6,11 @@ from pathlib import Path from PySide6.QtCore import Qt, Signal -from PySide6.QtGui import QColor from PySide6.QtWidgets import ( QCheckBox, QDockWidget, QFileDialog, QHBoxLayout, - QHeaderView, QPushButton, QTableWidget, QTableWidgetItem, @@ -24,9 +22,10 @@ from chrom_core.batch import FileReport from chrom_core.config import AppConfig from i18n import tr +from ui.tables import configure_table, paint_status, set_full_text_tooltip STATUS_TEXT = {"ok": "✓", "warn": "⚠", "bad": "✗", "error": "✗"} -STATUS_COLOR = {"ok": "#1e9e1e", "warn": "#e0a000", "bad": "#e02020", "error": "#e02020"} +STATUS_VERDICT = {"ok": "ok", "warn": "incomplete", "bad": "errors", "error": "errors"} class BatchPanel(QWidget): @@ -51,10 +50,7 @@ def __init__(self, parent: QWidget | None = None) -> None: tr("batch.col.status"), ] ) - self.table.horizontalHeader().setSectionResizeMode( - 0, QHeaderView.ResizeMode.Stretch - ) - self.table.verticalHeader().setVisible(False) + configure_table(self.table) self.table.setSortingEnabled(True) self.table.setSelectionBehavior(QTableWidget.SelectionBehavior.SelectRows) self.table.setEditTriggers(QTableWidget.EditTrigger.NoEditTriggers) @@ -87,7 +83,8 @@ def show_reports(self, reports: list[FileReport]) -> None: self._set_item(row, 3, report.q20 if not report.error else "") self._set_item(row, 4, report.trimmed_length if not report.error else "") status = QTableWidgetItem(STATUS_TEXT[report.status]) - status.setForeground(QColor(STATUS_COLOR[report.status])) + status.setTextAlignment(Qt.AlignmentFlag.AlignCenter) + paint_status(status, STATUS_VERDICT[report.status]) if report.error: status.setToolTip(report.error) self.table.setItem(row, 5, status) @@ -99,6 +96,7 @@ def _set_item(self, row: int, col: int, value, data=None) -> None: item.setData(Qt.ItemDataRole.DisplayRole, value) if data is not None: item.setData(Qt.ItemDataRole.UserRole, data) + set_full_text_tooltip(item) self.table.setItem(row, col, item) def _apply_filter(self) -> None: diff --git a/ui/read_view/menus.py b/ui/read_view/menus.py index 42a8e01..ba432e9 100644 --- a/ui/read_view/menus.py +++ b/ui/read_view/menus.py @@ -10,11 +10,13 @@ from PySide6.QtWidgets import QMenu from i18n import tr +from ui.status import bind_icon def add_file_actions(view, file_menu: QMenu) -> None: """Save session, export submenu, copy sequence (between 'Recent' and 'Exit').""" save_session = QAction(tr("menu.file.save_session"), view) + bind_icon(save_session, "save") save_session.setShortcut("Ctrl+S") save_session.triggered.connect(view._save_session) file_menu.addAction(save_session) @@ -30,6 +32,7 @@ def add_file_actions(view, file_menu: QMenu) -> None: export_menu.addAction(action) file_menu.addSeparator() copy_action = QAction(tr("menu.file.copy_seq"), view) + bind_icon(copy_action, "copy") copy_action.setShortcut("Ctrl+Shift+C") copy_action.triggered.connect(view._copy_sequence) file_menu.addAction(copy_action) @@ -40,6 +43,7 @@ def add_edit_actions(view, edit_menu: QMenu) -> None: edit_menu.addAction(view.redo_action) edit_menu.addSeparator() find_action = QAction(tr("menu.edit.find"), view) + bind_icon(find_action, "search") find_action.setShortcut("Ctrl+F") find_action.triggered.connect(view._search) edit_menu.addAction(find_action) @@ -57,6 +61,7 @@ def add_edit_actions(view, edit_menu: QMenu) -> None: revcomp_action.triggered.connect(view.reverse_complement_read) edit_menu.addAction(revcomp_action) trim_action = QAction(tr("menu.edit.trim"), view) + bind_icon(trim_action, "scissors") trim_action.setShortcut("Ctrl+T") trim_action.triggered.connect(view._open_trim_dialog) edit_menu.addAction(trim_action) @@ -73,11 +78,13 @@ def add_view_actions(view, view_menu: QMenu) -> None: profile_action.toggled.connect(view.minimap.set_profile) view_menu.addAction(profile_action) info_action = QAction(tr("menu.view.file_info"), view) + bind_icon(info_action, "info") info_action.setCheckable(True) info_action.toggled.connect(view.info_dock.setVisible) view.info_dock.visibilityChanged.connect(info_action.setChecked) view_menu.addAction(info_action) batch_action = QAction(tr("menu.view.batch_panel"), view) + bind_icon(batch_action, "table-2") batch_action.setCheckable(True) batch_action.toggled.connect(view.batch_dock.setVisible) view.batch_dock.visibilityChanged.connect(batch_action.setChecked) @@ -86,6 +93,7 @@ def add_view_actions(view, view_menu: QMenu) -> None: def add_analysis_actions(view, analysis_menu: QMenu) -> None: reference_action = QAction(tr("menu.analysis.reference"), view) + bind_icon(reference_action, "dna") reference_action.setShortcut("Ctrl+L") reference_action.triggered.connect(view._reference_dialog) analysis_menu.addAction(reference_action) @@ -98,10 +106,12 @@ def add_analysis_actions(view, analysis_menu: QMenu) -> None: analysis_menu.addAction(export_aligned) analysis_menu.addSeparator() verify_action = QAction(tr("menu.analysis.verify"), view) + bind_icon(verify_action, "flask-conical") verify_action.setShortcut("Ctrl+Shift+V") verify_action.triggered.connect(view._verify_dialog) analysis_menu.addAction(verify_action) analysis_menu.addSeparator() blast_action = QAction(tr("menu.analysis.blast"), view) + bind_icon(blast_action, "globe") blast_action.triggered.connect(view._blast_submit) analysis_menu.addAction(blast_action) diff --git a/ui/read_view/read_view.py b/ui/read_view/read_view.py index d1d9f09..626e470 100644 --- a/ui/read_view/read_view.py +++ b/ui/read_view/read_view.py @@ -20,6 +20,7 @@ QMenu, QMessageBox, QScrollBar, + QSizePolicy, QToolBar, QVBoxLayout, QWidget, @@ -42,6 +43,8 @@ from ui.read_view.batch_dock import BatchDock from ui.read_view.dialogs import SearchDialog, TrimDialog, ask_reference_text from ui.read_view.verify_dock import VerifyDock +from ui import status +from ui.status import bind_icon, quality_bucket from ui.theme import theme as palette @@ -106,21 +109,28 @@ def _say(self, text: str, timeout: int = 0) -> None: def _build_toolbar(self) -> None: bar = QToolBar() bar.setMovable(False) + bar.setToolButtonStyle(Qt.ToolButtonStyle.ToolButtonTextBesideIcon) self.addToolBar(bar) - def add(text: str, slot, shortcut: str | None = None) -> None: + def add(text: str, icon_name: str, slot, shortcut: str | None = None) -> None: action = QAction(text, self) + bind_icon(action, icon_name) if shortcut: action.setShortcut(shortcut) action.triggered.connect(slot) bar.addAction(action) - add(tr("tb.open"), self.open_dialog) + add(tr("tb.open"), "folder-open", self.open_dialog) bar.addSeparator() - add(tr("tb.zoom_in"), self.chrom_view.zoom_in, "Ctrl++") - add(tr("tb.zoom_out"), self.chrom_view.zoom_out, "Ctrl+-") - add(tr("tb.fit"), self.chrom_view.zoom_fit) - add(tr("tb.reset"), self.chrom_view.zoom_reset) + add(tr("tb.zoom_in"), "zoom-in", self.chrom_view.zoom_in, "Ctrl++") + add(tr("tb.zoom_out"), "zoom-out", self.chrom_view.zoom_out, "Ctrl+-") + add(tr("tb.fit"), "maximize", self.chrom_view.zoom_fit) + add(tr("tb.reset"), "rotate-ccw", self.chrom_view.zoom_reset) + bar.addSeparator() + bind_icon(self.undo_action, "undo-2") + bind_icon(self.redo_action, "redo-2") + bar.addAction(self.undo_action) + bar.addAction(self.redo_action) bar.addSeparator() for base in "ACGT": box = QCheckBox(base) @@ -130,6 +140,13 @@ def add(text: str, slot, shortcut: str | None = None) -> None: ) bar.addWidget(box) self._channel_boxes[base] = box + spacer = QWidget() + spacer.setSizePolicy(QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Preferred) + bar.addWidget(spacer) + self.quality_legend = QLabel() + self.quality_legend.setToolTip(tr("tb.quality_legend.tip")) + bar.addWidget(self.quality_legend) + self._refresh_legend("light") def _build_docks(self) -> None: self.info_dock = QDockWidget(tr("info.title"), self) @@ -459,8 +476,18 @@ def _sync_from_view(self) -> None: self.scrollbar.blockSignals(False) self.minimap.set_view(self.chrom_view.offset, visible, total) + def _refresh_legend(self, name: str) -> None: + """Small colour key for the quality bars (same thresholds everywhere).""" + colors = palette(name) + parts = [tr("tb.quality_legend")] + for q, text in ((0, "<20"), (20, "20–29"), (30, "≥30")): + parts.append(f'■ {text}') + self.quality_legend.setText("  ".join(parts)) + def apply_theme(self, name: str) -> None: + status.set_theme(name) colors = palette(name) + self._refresh_legend(name) self.chrom_view.set_theme(colors) self.minimap.set_theme(colors) for base, box in self._channel_boxes.items(): diff --git a/ui/read_view/verify_dock.py b/ui/read_view/verify_dock.py index 6403fea..584b57c 100644 --- a/ui/read_view/verify_dock.py +++ b/ui/read_view/verify_dock.py @@ -3,7 +3,6 @@ from __future__ import annotations from PySide6.QtCore import Qt -from PySide6.QtGui import QColor from PySide6.QtWidgets import ( QDockWidget, QHBoxLayout, @@ -15,6 +14,18 @@ ) from i18n import tr +from ui.tables import configure_table, paint_status, set_full_text_tooltip + + +VERIFY_VERDICT_STATUS = { + "confirmed": "ok", + "heterozygous": "mixed", + "not_found": "errors", + "ref_mismatch": "errors", + "low_quality": "incomplete", + "no_data": "no_data", + "unsupported": "no_data", +} class VerifyDock(QDockWidget): @@ -33,7 +44,7 @@ def __init__(self, parent: QWidget | None = None) -> None: tr("verify.col.note"), ] ) - self.verify_table.verticalHeader().setVisible(False) + configure_table(self.verify_table) self.verify_table.setEditTriggers(QTableWidget.EditTrigger.NoEditTriggers) self.verify_table.setSortingEnabled(True) buttons = QWidget() @@ -60,11 +71,6 @@ def fill(self, verdicts: list) -> None: "low_quality": tr("verify.low_quality"), "unsupported": tr("verify.unsupported"), } - colors = { - "confirmed": "#1e9e1e", - "heterozygous": "#e0a000", - "not_found": "#e02020", - } self.verify_table.setSortingEnabled(False) self.verify_table.setRowCount(len(verdicts)) for row, v in enumerate(verdicts): @@ -81,7 +87,8 @@ def fill(self, verdicts: list) -> None: for col, value in enumerate(values): item = QTableWidgetItem() item.setData(Qt.ItemDataRole.DisplayRole, value) - if col == 4 and v.verdict in colors: - item.setForeground(QColor(colors[v.verdict])) + set_full_text_tooltip(item) + if col == 4: + paint_status(item, VERIFY_VERDICT_STATUS.get(v.verdict, "no_data")) self.verify_table.setItem(row, col, item) self.verify_table.setSortingEnabled(True) diff --git a/ui/status.py b/ui/status.py new file mode 100644 index 0000000..14963ff --- /dev/null +++ b/ui/status.py @@ -0,0 +1,104 @@ +"""Shared visual language: status palette, quality colours, chips and icons. + +Status colours come from ``chrom_core.clone_report.STATUS_HEX`` (single source of +truth, also used by the XLSX report). Quality colours come from the theme dicts; +``quality_bucket`` is the one place that defines the Q thresholds. +""" + +from __future__ import annotations + +from PySide6.QtCore import QRectF, Qt +from PySide6.QtGui import QAction, QColor, QIcon, QPainter, QPixmap +from PySide6.QtSvg import QSvgRenderer +from PySide6.QtWidgets import QLabel + +from chrom_core.clone_report import STATUS_HEX +from ui.theme import resource_dir, theme as palette + +Q_LOW = 20 # Q below this is red +Q_HIGH = 30 # Q at or above this is green; in between is yellow + +_ICON_SIZES = (16, 20, 24, 32, 48) +_current_theme = "light" +_icon_cache: dict[tuple[str, str], QIcon] = {} +_bound: list[tuple[QAction, str]] = [] + + +def quality_bucket(q: int) -> str: + """Theme key for a phred score: ``low_q`` (<20), ``mid_q`` (20-29), ``high_q`` (>=30).""" + return "low_q" if q < Q_LOW else "mid_q" if q < Q_HIGH else "high_q" + + +def quality_color(q: int, theme: str) -> QColor: + return QColor(palette(theme)[quality_bucket(q)]) + + +def status_color(verdict: str, theme: str) -> QColor: + """Fill colour of a verdict (``ok/errors/incomplete/mixed/no_data``); unknown -> no_data.""" + light, dark = STATUS_HEX.get(verdict, STATUS_HEX["no_data"]) + return QColor(dark if theme == "dark" else light) + + +def status_text_color(verdict: str, theme: str) -> QColor: + """Readable text colour on top of ``status_color``.""" + bg = status_color(verdict, theme) + luminance = 0.299 * bg.red() + 0.587 * bg.green() + 0.114 * bg.blue() + return QColor("#1a1a1a" if luminance > 150 else "#ffffff") + + +def current_theme() -> str: + return _current_theme + + +def status_chip(verdict: str, text: str) -> QLabel: + """Rounded pill in the current theme's status colours.""" + chip = QLabel(text) + bg = status_color(verdict, _current_theme).name() + fg = status_text_color(verdict, _current_theme).name() + chip.setStyleSheet( + f"QLabel {{ background-color: {bg}; color: {fg}; border-radius: 9px;" + " padding: 1px 10px; font-weight: 600; }" + ) + chip.setAlignment(Qt.AlignmentFlag.AlignCenter) + return chip + + +def icon(name: str) -> QIcon: + """Lucide icon ``ui/icons/.svg`` tinted with the current theme's text colour.""" + key = (name, _current_theme) + cached = _icon_cache.get(key) + if cached is not None: + return cached + svg = (resource_dir() / "icons" / f"{name}.svg").read_text(encoding="utf-8") + svg = svg.replace("currentColor", palette(_current_theme)["text"]) + renderer = QSvgRenderer(svg.encode("utf-8")) + result = QIcon() + for size in _ICON_SIZES: + pixmap = QPixmap(size, size) + pixmap.fill(Qt.GlobalColor.transparent) + painter = QPainter(pixmap) + renderer.render(painter, QRectF(0, 0, size, size)) + painter.end() + result.addPixmap(pixmap) + _icon_cache[key] = result + return result + + +def bind_icon(action: QAction, name: str) -> None: + """Give ``action`` the icon and keep it tinted when the theme changes.""" + action.setIcon(icon(name)) + _bound.append((action, name)) + + +def set_theme(name: str) -> None: + """Switch the icon tint and re-icon every bound action.""" + global _current_theme + _current_theme = "dark" if name == "dark" else "light" + alive = [] + for action, icon_name in _bound: + try: + action.setIcon(icon(icon_name)) + except RuntimeError: # underlying QAction already deleted + continue + alive.append((action, icon_name)) + _bound[:] = alive diff --git a/ui/style.qss b/ui/style.qss new file mode 100644 index 0000000..b579eab --- /dev/null +++ b/ui/style.qss @@ -0,0 +1,57 @@ +/* ab1kit light theme. Explicit colours so the chrome never follows the OS mode. */ +QWidget { background-color: #f6f7f9; color: #1a1a1a; font-size: 13px; } +QMainWindow, QDialog { background-color: #f6f7f9; } +QToolTip { background-color: #ffffff; color: #1a1a1a; border: 1px solid #d0d5dd; padding: 4px 6px; } + +QMenuBar { background-color: #eceef2; border-bottom: 1px solid #d0d5dd; } +QMenuBar::item { padding: 5px 10px; background: transparent; } +QMenuBar::item:selected { background-color: #e1e5eb; border-radius: 4px; } +QMenu { background-color: #ffffff; border: 1px solid #d0d5dd; padding: 4px; } +QMenu::item { padding: 5px 24px 5px 24px; border-radius: 4px; } +QMenu::item:selected { background-color: #2f6fed; color: #ffffff; } +QMenu::item:disabled { color: #8a8f98; } +QMenu::separator { height: 1px; background: #d0d5dd; margin: 4px 6px; } + +QToolBar { background-color: #eceef2; border: none; border-bottom: 1px solid #d0d5dd; padding: 3px; spacing: 2px; } +QToolBar > QWidget { background: transparent; } +QToolBar::separator { background-color: #d0d5dd; width: 1px; margin: 4px 6px; } +QToolButton { background: transparent; border: 1px solid transparent; border-radius: 5px; padding: 4px 6px; } +QToolButton:hover { background-color: #e1e5eb; border-color: #d0d5dd; } +QToolButton:pressed { background-color: #cfd5de; } +QToolButton:disabled { color: #8a8f98; } + +QPushButton { background-color: #ffffff; border: 1px solid #d0d5dd; border-radius: 5px; padding: 5px 14px; } +QPushButton:hover { background-color: #e1e5eb; } +QPushButton:pressed { background-color: #cfd5de; } +QPushButton:default { border-color: #2f6fed; } +QPushButton:disabled { color: #8a8f98; } + +QLineEdit, QSpinBox, QDoubleSpinBox, QComboBox, QPlainTextEdit, QTextEdit { + background-color: #ffffff; border: 1px solid #d0d5dd; border-radius: 4px; padding: 3px 6px; + selection-background-color: #2f6fed; selection-color: #ffffff; } +QLineEdit:focus, QSpinBox:focus, QDoubleSpinBox:focus, QComboBox:focus { border-color: #2f6fed; } + +QDockWidget { titlebar-close-icon: none; } +QDockWidget::title { background-color: #eceef2; border-bottom: 1px solid #d0d5dd; padding: 5px 8px; font-weight: 600; } + +QTableView, QTableWidget { background-color: #ffffff; alternate-background-color: #f6f7f9; + gridline-color: #d0d5dd; border: 1px solid #d0d5dd; selection-background-color: #2f6fed; selection-color: #ffffff; } +QHeaderView::section { background-color: #eceef2; color: #1a1a1a; padding: 4px 8px; border: none; + border-right: 1px solid #d0d5dd; border-bottom: 1px solid #d0d5dd; font-weight: 600; } + +QScrollBar:vertical { background: transparent; width: 12px; margin: 0; } +QScrollBar:horizontal { background: transparent; height: 12px; margin: 0; } +QScrollBar::handle:vertical, QScrollBar::handle:horizontal { background: #c3c8d1; border-radius: 5px; min-height: 24px; min-width: 24px; margin: 2px; } +QScrollBar::handle:hover { background: #8a8f98; } +QScrollBar::add-line, QScrollBar::sub-line { width: 0; height: 0; } +QScrollBar::add-page, QScrollBar::sub-page { background: transparent; } + +QProgressBar { background-color: #ffffff; border: 1px solid #d0d5dd; border-radius: 4px; text-align: center; } +QProgressBar::chunk { background-color: #2f6fed; border-radius: 3px; } +QStatusBar { background-color: #eceef2; border-top: 1px solid #d0d5dd; } +QStatusBar::item { border: none; } +QCheckBox { spacing: 6px; background: transparent; } +QCheckBox::indicator { width: 14px; height: 14px; border: 1px solid #8a8f98; border-radius: 3px; background-color: #ffffff; } +QCheckBox::indicator:checked { background-color: #2f6fed; border-color: #2f6fed; } +QCheckBox::indicator:disabled { border-color: #d0d5dd; } +QLabel { background: transparent; } diff --git a/ui/style_dark.qss b/ui/style_dark.qss new file mode 100644 index 0000000..2464c0c --- /dev/null +++ b/ui/style_dark.qss @@ -0,0 +1,57 @@ +/* ab1kit dark theme. Explicit colours so the chrome never follows the OS mode. */ +QWidget { background-color: #252526; color: #d4d4d4; font-size: 13px; } +QMainWindow, QDialog { background-color: #252526; } +QToolTip { background-color: #2d2d30; color: #d4d4d4; border: 1px solid #3f3f46; padding: 4px 6px; } + +QMenuBar { background-color: #2d2d30; border-bottom: 1px solid #3f3f46; } +QMenuBar::item { padding: 5px 10px; background: transparent; } +QMenuBar::item:selected { background-color: #3a3d41; border-radius: 4px; } +QMenu { background-color: #2d2d30; border: 1px solid #3f3f46; padding: 4px; } +QMenu::item { padding: 5px 24px 5px 24px; border-radius: 4px; } +QMenu::item:selected { background-color: #2f6fed; color: #ffffff; } +QMenu::item:disabled { color: #8a8a8a; } +QMenu::separator { height: 1px; background: #3f3f46; margin: 4px 6px; } + +QToolBar { background-color: #2d2d30; border: none; border-bottom: 1px solid #3f3f46; padding: 3px; spacing: 2px; } +QToolBar > QWidget { background: transparent; } +QToolBar::separator { background-color: #3f3f46; width: 1px; margin: 4px 6px; } +QToolButton { background: transparent; border: 1px solid transparent; border-radius: 5px; padding: 4px 6px; } +QToolButton:hover { background-color: #3a3d41; border-color: #3f3f46; } +QToolButton:pressed { background-color: #4a4d52; } +QToolButton:disabled { color: #8a8a8a; } + +QPushButton { background-color: #2d2d30; border: 1px solid #3f3f46; border-radius: 5px; padding: 5px 14px; } +QPushButton:hover { background-color: #3a3d41; } +QPushButton:pressed { background-color: #4a4d52; } +QPushButton:default { border-color: #2f6fed; } +QPushButton:disabled { color: #8a8a8a; } + +QLineEdit, QSpinBox, QDoubleSpinBox, QComboBox, QPlainTextEdit, QTextEdit { + background-color: #1e1e1e; border: 1px solid #3f3f46; border-radius: 4px; padding: 3px 6px; + selection-background-color: #2f6fed; selection-color: #ffffff; } +QLineEdit:focus, QSpinBox:focus, QDoubleSpinBox:focus, QComboBox:focus { border-color: #2f6fed; } + +QDockWidget { titlebar-close-icon: none; } +QDockWidget::title { background-color: #2d2d30; border-bottom: 1px solid #3f3f46; padding: 5px 8px; font-weight: 600; } + +QTableView, QTableWidget { background-color: #1e1e1e; alternate-background-color: #232324; + gridline-color: #3f3f46; border: 1px solid #3f3f46; selection-background-color: #2f6fed; selection-color: #ffffff; } +QHeaderView::section { background-color: #2d2d30; color: #d4d4d4; padding: 4px 8px; border: none; + border-right: 1px solid #3f3f46; border-bottom: 1px solid #3f3f46; font-weight: 600; } + +QScrollBar:vertical { background: transparent; width: 12px; margin: 0; } +QScrollBar:horizontal { background: transparent; height: 12px; margin: 0; } +QScrollBar::handle:vertical, QScrollBar::handle:horizontal { background: #4a4a50; border-radius: 5px; min-height: 24px; min-width: 24px; margin: 2px; } +QScrollBar::handle:hover { background: #8a8a8a; } +QScrollBar::add-line, QScrollBar::sub-line { width: 0; height: 0; } +QScrollBar::add-page, QScrollBar::sub-page { background: transparent; } + +QProgressBar { background-color: #1e1e1e; border: 1px solid #3f3f46; border-radius: 4px; text-align: center; } +QProgressBar::chunk { background-color: #2f6fed; border-radius: 3px; } +QStatusBar { background-color: #2d2d30; border-top: 1px solid #3f3f46; } +QStatusBar::item { border: none; } +QCheckBox { spacing: 6px; background: transparent; } +QCheckBox::indicator { width: 14px; height: 14px; border: 1px solid #8a8f98; border-radius: 3px; background-color: #1e1e1e; } +QCheckBox::indicator:checked { background-color: #2f6fed; border-color: #2f6fed; } +QCheckBox::indicator:disabled { border-color: #3f3f46; } +QLabel { background: transparent; } diff --git a/ui/tables.py b/ui/tables.py new file mode 100644 index 0000000..7e7402e --- /dev/null +++ b/ui/tables.py @@ -0,0 +1,32 @@ +"""Shared table behaviour: content-sized columns, stretching last column, tooltips.""" + +from __future__ import annotations + +from PySide6.QtWidgets import QHeaderView, QTableWidget, QTableWidgetItem + +from ui.status import current_theme, status_color, status_text_color + + +def configure_table(table: QTableWidget) -> None: + """Columns fit their content and the last one takes the remaining width.""" + header = table.horizontalHeader() + header.setSectionResizeMode(QHeaderView.ResizeMode.ResizeToContents) + header.setStretchLastSection(True) + header.setMinimumSectionSize(40) + table.verticalHeader().setVisible(False) + table.setAlternatingRowColors(True) + table.setWordWrap(False) + + +def set_full_text_tooltip(item: QTableWidgetItem) -> None: + """Show the whole text on hover (it may be elided by a narrow column).""" + text = item.text() + if text: + item.setToolTip(text) + + +def paint_status(item: QTableWidgetItem, verdict: str) -> None: + """Colour a cell with the shared status palette (current theme).""" + theme = current_theme() + item.setBackground(status_color(verdict, theme)) + item.setForeground(status_text_color(verdict, theme)) diff --git a/ui/theme.py b/ui/theme.py index 0cb7602..1ee085e 100644 --- a/ui/theme.py +++ b/ui/theme.py @@ -2,6 +2,10 @@ from __future__ import annotations +import sys +from functools import lru_cache +from pathlib import Path + LIGHT = { "bg": "#ffffff", "panel": "#f3f3f3", @@ -37,20 +41,20 @@ def theme(name: str) -> dict: return DARK if name == "dark" else LIGHT +def resource_dir() -> Path: + """Folder holding style*.qss and icons/: next to this module, or under + ``sys._MEIPASS/ui`` in a PyInstaller bundle (see ab1kit.spec datas).""" + frozen = getattr(sys, "_MEIPASS", None) + return Path(frozen) / "ui" if frozen else Path(__file__).resolve().parent + + +@lru_cache(maxsize=2) +def _read_qss(dark: bool) -> str: + name = "style_dark.qss" if dark else "style.qss" + return (resource_dir() / name).read_text(encoding="utf-8") + + def app_qss(dark: bool) -> str: - """Application stylesheet. Both themes set explicit colors so the chrome - never depends on the OS light/dark mode (native dark Windows makes our - fixed light-theme text colors unreadable).""" - if dark: - return ( - "QWidget { background-color: #252526; color: #d4d4d4; }" - "QMenuBar, QMenu, QToolBar { background-color: #2d2d30; }" - "QLineEdit, QSpinBox { background-color: #1e1e1e; }" - "QDockWidget::title { background-color: #2d2d30; }" - ) - return ( - "QWidget { background-color: #f3f3f3; color: #1a1a1a; }" - "QMenuBar, QMenu, QToolBar { background-color: #e9e9e9; }" - "QLineEdit, QSpinBox { background-color: #ffffff; }" - "QDockWidget::title { background-color: #e9e9e9; }" - ) + """Application stylesheet (ui/style.qss or ui/style_dark.qss). Both themes set + explicit colours so the chrome never depends on the OS light/dark mode.""" + return _read_qss(dark) From 6f89ae58d9dc826706c7f42f17aec4de18ff21e7 Mon Sep 17 00:00:00 2001 From: Aleksey Drobin <43707931+adrobi@users.noreply.github.com> Date: Fri, 30 Oct 2026 10:26:17 +0300 Subject: [PATCH 23/44] ui: checkbox ticks in channel colours, theme-aware status cells, weak icon bindings, tooltip/stretch tweaks Co-Authored-By: Claude Sonnet 5.5 --- scripts/render_preview.py | 11 +++++- tests/test_smoke_gui.py | 80 +++++++++++++++++++++++++++++++++++++- ui/icons/check.svg | 13 +++++++ ui/main_window.py | 4 +- ui/read_view/batch_dock.py | 2 +- ui/read_view/read_view.py | 13 +++++-- ui/status.py | 13 +++++-- ui/style.qss | 2 +- ui/style_dark.qss | 2 +- ui/tables.py | 30 +++++++++++--- ui/theme.py | 18 ++++++++- 11 files changed, 166 insertions(+), 22 deletions(-) create mode 100644 ui/icons/check.svg diff --git a/scripts/render_preview.py b/scripts/render_preview.py index 1bdb1cd..e6b8c3e 100644 --- a/scripts/render_preview.py +++ b/scripts/render_preview.py @@ -20,7 +20,7 @@ from ui.chrom_view import ChromatogramWidget # noqa: E402 -def render_window(src: Path, out: Path, theme: str) -> None: +def render_window(src: Path, out: Path, theme: str, uncheck: str = "") -> None: from chrom_core.config import AppConfig from ui.main_window import MainWindow @@ -37,6 +37,8 @@ def render_window(src: Path, out: Path, theme: str) -> None: window._set_reference_seq("".join(ref)) rows = ["name;pos;ref;alt", f"snp1;51;{seq[150]};T", f"snp2;121;{seq[220]};G"] window._verify_variants("\n".join(rows) + "\n") + for base in uncheck: + window.read_view._channel_boxes[base].setChecked(False) window.batch_dock.show() window.batch_panel.show_reports(batch.scan_folder(src.parent)) for _ in range(20): @@ -54,6 +56,11 @@ def main() -> None: i = argv.index("--theme") theme = argv[i + 1] del argv[i:i + 2] + uncheck = "" + if "--uncheck" in argv: + i = argv.index("--uncheck") + uncheck = argv[i + 1] + del argv[i:i + 2] window_mode = "--window" in argv argv = [a for a in argv if a != "--window"] src = Path(argv[0]) if argv else examples[0] @@ -61,7 +68,7 @@ def main() -> None: app = QApplication([]) if window_mode: - render_window(src, out, theme) + render_window(src, out, theme, uncheck) return view = ChromatogramWidget() view.resize(1200, 700) diff --git a/tests/test_smoke_gui.py b/tests/test_smoke_gui.py index 574ae72..762423d 100644 --- a/tests/test_smoke_gui.py +++ b/tests/test_smoke_gui.py @@ -467,9 +467,85 @@ def test_tables_stretch_last_column_and_tooltip_notes(qapp): window._set_reference_seq(ref) wrong = "A" if ref[50] != "A" else "C" window._verify_variants(f"name;pos;ref;alt\nsnp;51;{wrong};T\n") - for table in (window.verify_table, window.diff_table, window.batch_panel.table): + for table in (window.verify_table, window.diff_table): assert table.horizontalHeader().stretchLastSection() assert table.horizontalHeader().sectionResizeMode(0) != QHeaderView.ResizeMode.Fixed note = window.verify_table.item(0, 7) - assert note.text() and note.toolTip() == note.text() + assert len(note.text()) > 40 and note.toolTip() == note.text() window.close() + + +def test_status_cells_repaint_on_theme_switch(qapp): + from chrom_core.config import AppConfig + from ui.main_window import MainWindow + from ui.status import status_color + + sample = next(p for p in AB1 if "3730" in p.name) + window = MainWindow(AppConfig(recent_files=[], theme="light")) + assert window.open_path(sample) + seq = "".join(window.read_model.seq) + ref = seq[100:400] + window._set_reference_seq(ref) + wrong = "A" if ref[50] != "A" else "C" + window._verify_variants(f"name;pos;ref;alt\nsnp;51;{wrong};T\n") + cell = window.verify_table.item(0, 4) + assert cell.background().color() == status_color("errors", "light") + window.set_theme("dark") + assert cell.background().color() == status_color("errors", "dark") + window.close() + + +def test_icon_pixmap_changes_with_theme(qapp): + from PySide6.QtGui import QAction + + from ui import status + + action = QAction("x") + status.bind_icon(action, "undo-2") + try: + status.set_theme("light") + light = action.icon().pixmap(24, 24).toImage() + status.set_theme("dark") + dark = action.icon().pixmap(24, 24).toImage() + assert light != dark + finally: + status.set_theme("light") + + +def test_channel_checkboxes_use_channel_colours_and_tick(qapp): + from chrom_core.config import AppConfig + from ui.main_window import MainWindow + from ui.theme import theme as palette + + window = MainWindow(AppConfig(recent_files=[])) + for name in ("light", "dark"): + window.set_theme(name) + for base, box in window.read_view._channel_boxes.items(): + sheet = box.styleSheet() + colour = palette(name)["bases"][base] + assert f"QCheckBox::indicator:checked {{ background-color: {colour}" in sheet + assert "image: url(" in sheet + assert "image: url(" in qapp.styleSheet() + window.close() + + +def test_batch_table_stretches_file_column(qapp): + from PySide6.QtWidgets import QHeaderView + + from ui.read_view.batch_dock import BatchPanel + + panel = BatchPanel() + header = panel.table.horizontalHeader() + assert header.sectionResizeMode(0) == QHeaderView.ResizeMode.Stretch + assert not header.stretchLastSection() + + +def test_tooltips_only_on_long_cells(qapp): + from PySide6.QtWidgets import QTableWidgetItem + + from ui.tables import set_full_text_tooltip + + short, long_ = QTableWidgetItem("12"), QTableWidgetItem("x" * 60) + set_full_text_tooltip(short) + set_full_text_tooltip(long_) + assert short.toolTip() == "" and long_.toolTip() == "x" * 60 diff --git a/ui/icons/check.svg b/ui/icons/check.svg new file mode 100644 index 0000000..5abe152 --- /dev/null +++ b/ui/icons/check.svg @@ -0,0 +1,13 @@ + + + diff --git a/ui/main_window.py b/ui/main_window.py index 74b5c27..28ef90a 100644 --- a/ui/main_window.py +++ b/ui/main_window.py @@ -18,10 +18,10 @@ from chrom_core.config import AppConfig, load_config, save_config from i18n import set_language, tr -from ui.read_view import ReadView -from ui.tasks import Task, run_task from ui import status +from ui.read_view import ReadView from ui.status import bind_icon +from ui.tasks import Task, run_task from ui.theme import app_qss try: diff --git a/ui/read_view/batch_dock.py b/ui/read_view/batch_dock.py index c5feab9..8818bf7 100644 --- a/ui/read_view/batch_dock.py +++ b/ui/read_view/batch_dock.py @@ -50,7 +50,7 @@ def __init__(self, parent: QWidget | None = None) -> None: tr("batch.col.status"), ] ) - configure_table(self.table) + configure_table(self.table, stretch_column=0) self.table.setSortingEnabled(True) self.table.setSelectionBehavior(QTableWidget.SelectionBehavior.SelectRows) self.table.setEditTriggers(QTableWidget.EditTrigger.NoEditTriggers) diff --git a/ui/read_view/read_view.py b/ui/read_view/read_view.py index 626e470..a3b3412 100644 --- a/ui/read_view/read_view.py +++ b/ui/read_view/read_view.py @@ -36,6 +36,7 @@ from chrom_core.verify import parse_expected, verify_expected, verdicts_csv, verdicts_xlsx from chrom_core.seqops import find_matches from i18n import tr +from ui import status from ui.chrom_view import ChromatogramWidget from ui.minimap import MiniMap from ui.read_view import menus @@ -43,9 +44,9 @@ from ui.read_view.batch_dock import BatchDock from ui.read_view.dialogs import SearchDialog, TrimDialog, ask_reference_text from ui.read_view.verify_dock import VerifyDock -from ui import status from ui.status import bind_icon, quality_bucket -from ui.theme import theme as palette +from ui.tables import repaint_statuses +from ui.theme import theme as palette, tick_image class ReadView(QMainWindow): @@ -491,9 +492,15 @@ def apply_theme(self, name: str) -> None: self.chrom_view.set_theme(colors) self.minimap.set_theme(colors) for base, box in self._channel_boxes.items(): + c = colors["bases"][base] box.setStyleSheet( - f"QCheckBox {{ color: {colors['bases'][base]}; font-weight: bold; padding: 0 4px; }}" + f"QCheckBox {{ color: {c}; font-weight: bold; padding: 0 4px; }}" + f"QCheckBox::indicator {{ border: 1px solid {c}; }}" + f"QCheckBox::indicator:checked {{ background-color: {c}; border-color: {c};" + f" image: url({tick_image(c)}); }}" ) + for table in (self.diff_table, self.verify_table, self.batch_panel.table): + repaint_statuses(table) # --------------------------------------------------------------- editing def _sync_actions(self) -> None: diff --git a/ui/status.py b/ui/status.py index 14963ff..53a43aa 100644 --- a/ui/status.py +++ b/ui/status.py @@ -7,6 +7,8 @@ from __future__ import annotations +import weakref + from PySide6.QtCore import QRectF, Qt from PySide6.QtGui import QAction, QColor, QIcon, QPainter, QPixmap from PySide6.QtSvg import QSvgRenderer @@ -21,7 +23,7 @@ _ICON_SIZES = (16, 20, 24, 32, 48) _current_theme = "light" _icon_cache: dict[tuple[str, str], QIcon] = {} -_bound: list[tuple[QAction, str]] = [] +_bound: list[tuple[weakref.ref, str]] = [] def quality_bucket(q: int) -> str: @@ -87,7 +89,7 @@ def icon(name: str) -> QIcon: def bind_icon(action: QAction, name: str) -> None: """Give ``action`` the icon and keep it tinted when the theme changes.""" action.setIcon(icon(name)) - _bound.append((action, name)) + _bound.append((weakref.ref(action), name)) def set_theme(name: str) -> None: @@ -95,10 +97,13 @@ def set_theme(name: str) -> None: global _current_theme _current_theme = "dark" if name == "dark" else "light" alive = [] - for action, icon_name in _bound: + for ref, icon_name in _bound: + action = ref() + if action is None: + continue try: action.setIcon(icon(icon_name)) except RuntimeError: # underlying QAction already deleted continue - alive.append((action, icon_name)) + alive.append((ref, icon_name)) _bound[:] = alive diff --git a/ui/style.qss b/ui/style.qss index b579eab..cf16e12 100644 --- a/ui/style.qss +++ b/ui/style.qss @@ -52,6 +52,6 @@ QStatusBar { background-color: #eceef2; border-top: 1px solid #d0d5dd; } QStatusBar::item { border: none; } QCheckBox { spacing: 6px; background: transparent; } QCheckBox::indicator { width: 14px; height: 14px; border: 1px solid #8a8f98; border-radius: 3px; background-color: #ffffff; } -QCheckBox::indicator:checked { background-color: #2f6fed; border-color: #2f6fed; } +QCheckBox::indicator:checked { background-color: #2f6fed; border-color: #2f6fed; image: url(@TICK@); } QCheckBox::indicator:disabled { border-color: #d0d5dd; } QLabel { background: transparent; } diff --git a/ui/style_dark.qss b/ui/style_dark.qss index 2464c0c..2b17d35 100644 --- a/ui/style_dark.qss +++ b/ui/style_dark.qss @@ -52,6 +52,6 @@ QStatusBar { background-color: #2d2d30; border-top: 1px solid #3f3f46; } QStatusBar::item { border: none; } QCheckBox { spacing: 6px; background: transparent; } QCheckBox::indicator { width: 14px; height: 14px; border: 1px solid #8a8f98; border-radius: 3px; background-color: #1e1e1e; } -QCheckBox::indicator:checked { background-color: #2f6fed; border-color: #2f6fed; } +QCheckBox::indicator:checked { background-color: #2f6fed; border-color: #2f6fed; image: url(@TICK@); } QCheckBox::indicator:disabled { border-color: #3f3f46; } QLabel { background: transparent; } diff --git a/ui/tables.py b/ui/tables.py index 7e7402e..9c891a0 100644 --- a/ui/tables.py +++ b/ui/tables.py @@ -2,16 +2,25 @@ from __future__ import annotations +from PySide6.QtCore import Qt from PySide6.QtWidgets import QHeaderView, QTableWidget, QTableWidgetItem from ui.status import current_theme, status_color, status_text_color -def configure_table(table: QTableWidget) -> None: - """Columns fit their content and the last one takes the remaining width.""" +STATUS_ROLE = Qt.ItemDataRole.UserRole + 1 +TOOLTIP_MIN_CHARS = 40 + + +def configure_table(table: QTableWidget, stretch_column: int | None = None) -> None: + """Columns fit their content; ``stretch_column`` (default: the last) takes the rest.""" header = table.horizontalHeader() header.setSectionResizeMode(QHeaderView.ResizeMode.ResizeToContents) - header.setStretchLastSection(True) + if stretch_column is None: + header.setStretchLastSection(True) + else: + header.setStretchLastSection(False) + header.setSectionResizeMode(stretch_column, QHeaderView.ResizeMode.Stretch) header.setMinimumSectionSize(40) table.verticalHeader().setVisible(False) table.setAlternatingRowColors(True) @@ -19,14 +28,25 @@ def configure_table(table: QTableWidget) -> None: def set_full_text_tooltip(item: QTableWidgetItem) -> None: - """Show the whole text on hover (it may be elided by a narrow column).""" + """Show the whole text on hover for long cells (a narrow column may elide them).""" text = item.text() - if text: + if len(text) > TOOLTIP_MIN_CHARS: item.setToolTip(text) def paint_status(item: QTableWidgetItem, verdict: str) -> None: """Colour a cell with the shared status palette (current theme).""" + item.setData(STATUS_ROLE, verdict) theme = current_theme() item.setBackground(status_color(verdict, theme)) item.setForeground(status_text_color(verdict, theme)) + + +def repaint_statuses(table: QTableWidget) -> None: + """Re-apply the status palette (after a theme switch) to every status cell.""" + for row in range(table.rowCount()): + for col in range(table.columnCount()): + item = table.item(row, col) + verdict = item.data(STATUS_ROLE) if item is not None else None + if verdict: + paint_status(item, verdict) diff --git a/ui/theme.py b/ui/theme.py index 1ee085e..9c5b68b 100644 --- a/ui/theme.py +++ b/ui/theme.py @@ -3,6 +3,7 @@ from __future__ import annotations import sys +import tempfile from functools import lru_cache from pathlib import Path @@ -54,7 +55,22 @@ def _read_qss(dark: bool) -> str: return (resource_dir() / name).read_text(encoding="utf-8") +def tick_image(background: str) -> str: + """Path of a tick (Lucide ``check``) PNG-free SVG readable on ``background``, + for QSS ``image: url(...)``. Written once per colour to the temp folder.""" + r, g, b = (int(background.lstrip("#")[i:i + 2], 16) for i in (0, 2, 4)) + tick = "#1a1a1a" if 0.299 * r + 0.587 * g + 0.114 * b > 150 else "#ffffff" + folder = Path(tempfile.gettempdir()) / "ab1kit_icons" + folder.mkdir(exist_ok=True) + target = folder / f"check_{tick.lstrip('#')}.svg" + if not target.exists(): + svg = (resource_dir() / "icons" / "check.svg").read_text(encoding="utf-8") + target.write_text(svg.replace("currentColor", tick).replace('stroke-width="2"', 'stroke-width="3"'), + encoding="utf-8") + return target.as_posix() + + def app_qss(dark: bool) -> str: """Application stylesheet (ui/style.qss or ui/style_dark.qss). Both themes set explicit colours so the chrome never depends on the OS light/dark mode.""" - return _read_qss(dark) + return _read_qss(dark).replace("@TICK@", tick_image("#2f6fed")) From a7ca545addfd251ff9f8cd5317f468224953fc69 Mon Sep 17 00:00:00 2001 From: Aleksey Drobin <43707931+adrobi@users.noreply.github.com> Date: Fri, 30 Oct 2026 10:37:13 +0300 Subject: [PATCH 24/44] ui: construct summary bar and clone matrix Co-Authored-By: Claude Opus 5.5 --- ab1kit.spec | 2 +- i18n.py | 26 ++ pyproject.toml | 2 +- tests/test_construct_ui.py | 283 +++++++++++++++++++ translations_en.py | 26 ++ ui/construct/__init__.py | 4 + ui/construct/matrix.py | 548 ++++++++++++++++++++++++++++++++++++ ui/construct/summary_bar.py | 118 ++++++++ ui/theme.py | 14 + 9 files changed, 1021 insertions(+), 2 deletions(-) create mode 100644 tests/test_construct_ui.py create mode 100644 ui/construct/__init__.py create mode 100644 ui/construct/matrix.py create mode 100644 ui/construct/summary_bar.py diff --git a/ab1kit.spec b/ab1kit.spec index f348d0a..ca59ae4 100644 --- a/ab1kit.spec +++ b/ab1kit.spec @@ -13,7 +13,7 @@ a = Analysis( ("ui/style_dark.qss", "ui"), ("ui/icons", "ui/icons"), ], - hiddenimports=["chrom_core", "ui", "ui.read_view", "ui.status", "ui.tables", "i18n", "translations_en"], + hiddenimports=["chrom_core", "ui", "ui.read_view", "ui.construct", "ui.status", "ui.tables", "i18n", "translations_en"], hookspath=[], excludes=["tkinter", "matplotlib", "numpy.tests"], noarchive=False, diff --git a/i18n.py b/i18n.py index 3cac432..55ef466 100644 --- a/i18n.py +++ b/i18n.py @@ -163,6 +163,32 @@ "batch.exported": "Экспортировано: {n}, ошибок: {err}", "batch.export_dir": "Куда экспортировать", "err.open_failed": "Не удалось открыть файл", + "construct.bp": "{n} п.н.", + "construct.circular": "кольцевая", + "construct.linear": "линейная", + "construct.region": "регион {start}–{end}", + "construct.region_all": "регион: весь конструкт", + "construct.count.ok": "Подходят: {n}", + "construct.count.errors": "Ошибки: {n}", + "construct.count.incomplete": "Неполные: {n}", + "construct.count.mixed": "Смесь?: {n}", + "construct.count.no_data": "Нет данных: {n}", + "construct.filter_tip": "Показать или скрыть клоны с этим вердиктом", + "matrix.reference": "референс", + "matrix.chip.ok": "подходит", + "matrix.chip.errors": "{n} расх.", + "matrix.chip.incomplete": "{pct}%", + "matrix.chip.mixed": "смесь?", + "matrix.chip.no_data": "нет данных", + "matrix.legend.cov_both": "две цепи", + "matrix.legend.cov_one": "одна цепь", + "matrix.legend.cov_none": "нет (Q<20)", + "matrix.legend.confirmed": "подтверждено", + "matrix.legend.disputed": "спорно", + "matrix.legend.low_quality": "низкое Q", + "matrix.legend.mixed": "двойной пик", + "matrix.empty": "Нет клонов для показа", + "matrix.hint": "Колёсико — масштаб, перетаскивание — сдвиг, Shift+протяжка по референсу — задать регион", } _lang = "ru" diff --git a/pyproject.toml b/pyproject.toml index 2cda6cb..94ea497 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -22,7 +22,7 @@ dev = ["pytest>=8"] ab1kit = "chrom_cli:main" [tool.setuptools] -packages = ["chrom_core", "ui", "ui.read_view"] +packages = ["chrom_core", "ui", "ui.read_view", "ui.construct"] py-modules = ["chrom_cli", "i18n", "translations_en"] [tool.setuptools.package-data] diff --git a/tests/test_construct_ui.py b/tests/test_construct_ui.py new file mode 100644 index 0000000..c79d545 --- /dev/null +++ b/tests/test_construct_ui.py @@ -0,0 +1,283 @@ +"""Construct screen widgets: summary bar and clone matrix (offscreen Qt). + +Reports come from ``verify_all`` on the real pair ``Achl_ACHLO006-09`` F+R +against its COI reference, with errors / trimming / double peaks introduced +through editing sessions (``write_read``), as in ``test_clone_verify``. +""" + +from __future__ import annotations + +import os + +os.environ.setdefault("QT_QPA_PLATFORM", "offscreen") + +import pytest +from PySide6.QtCore import QEvent, QPoint, QPointF, Qt +from PySide6.QtGui import QColor, QImage, QMouseEvent, QWheelEvent +from PySide6.QtWidgets import QApplication + +from chrom_core.align import align_to_construct +from chrom_core.clones import CloneDifference, CloneReport, Grouping, ReadRef, verify_all +from chrom_core.editing import EditableRead +from chrom_core.reference import load_construct +from clone_fixtures import COI_GB, DATA, real_read, with_secondary_peak, write_read + +F_NAME = "Achl_ACHLO006-09_1_F.ab1" +R_NAME = "Achl_ACHLO006-09_2_R.ab1" +F = DATA / "real" / F_NAME +R = DATA / "real" / R_NAME +REGION = (6, 647) +P = 250 # substitution site inside the region +MIXED_AT = (200, 300, 400) + + +@pytest.fixture(scope="module") +def qapp(): + return QApplication.instance() or QApplication([]) + + +@pytest.fixture(scope="module") +def construct(): + return load_construct(COI_GB) + + +def _f_index(construct, ref_pos: int) -> int: + al = align_to_construct(real_read(F_NAME).seq, construct) + assert al.strand == "+" + return al.ref_to_read[ref_pos] + + +@pytest.fixture(scope="module") +def reports(construct, tmp_path_factory): + """ok (c1), errors confirmed (c2, F only), errors disputed (c3), incomplete (c4), mixed (c5).""" + folder = tmp_path_factory.mktemp("clones") + i = _f_index(construct, P) + # a C peak 4x the called base, then the call edited to C: the trace agrees + # with the edit (no artificial double peak at P) + assert real_read(F_NAME).seq[i] != "C" + edited = EditableRead(with_secondary_peak(real_read(F_NAME), i, "C", 4.0)) + edited.set_base(i, "C") + sub_dir = folder / "sub" + sub_dir.mkdir() + f_sub = write_read(edited.current(), sub_dir, F_NAME) + + trimmed = EditableRead(real_read(F_NAME)) + trimmed.apply_trim(100, 400) + trim_dir = folder / "trim" + trim_dir.mkdir() + f_trim = write_read(trimmed.current(), trim_dir, F_NAME) + + chrom = real_read(F_NAME) + for pos in MIXED_AT: + j = _f_index(construct, pos) + chrom = with_secondary_peak(chrom, j, next(b for b in "ACGT" if b != chrom.seq[j]), 0.5) + mix_dir = folder / "mix" + mix_dir.mkdir() + f_mix = write_read(chrom, mix_dir, F_NAME) + + grouping = Grouping([ + ReadRef(F, "c1", "F"), ReadRef(R, "c1", "R"), + ReadRef(f_sub, "c2", "F"), + ReadRef(f_sub, "c3", "F"), ReadRef(R, "c3", "R"), + ReadRef(f_trim, "c4", "F"), + ReadRef(f_mix, "c5", "F"), ReadRef(R, "c5", "R"), + ]) + out = verify_all(construct, REGION, grouping) + assert [r.verdict for r in out] == ["ok", "errors", "errors", "incomplete", "mixed"] + assert [d.status for d in out[1].region_differences] == ["confirmed"] + assert [d.status for d in out[2].region_differences] == ["disputed"] + return out + + +def _matrix(qapp, construct, reports, width=900, theme="light"): + from ui.construct.matrix import CloneMatrix + + m = CloneMatrix() + m.set_theme(theme) + m.set_data(construct, REGION, reports) + m.resize(width, m.sizeHint().height()) + return m + + +def _send_mouse(widget, kind, pos: QPoint, button, buttons, modifiers=Qt.KeyboardModifier.NoModifier): + local = QPointF(pos) + event = QMouseEvent(kind, local, widget.mapToGlobal(local), button, buttons, modifiers) + QApplication.sendEvent(widget, event) + + +# ------------------------------------------------------------------ summary bar + + +def test_summary_shows_construct_and_counts(qapp, construct, reports): + from i18n import tr + from ui.construct.summary_bar import SummaryBar + + bar = SummaryBar() + bar.set_data(construct, REGION, reports) + assert construct.name in bar.title_text() + info = bar.info_text() + assert "658" in info and "7–647" in info + assert tr("construct.linear") in info + counts = {v: bar.counter(v) for v in ("ok", "errors", "incomplete", "mixed")} + assert "1" in counts["ok"].text() and "2" in counts["errors"].text() + assert "1" in counts["incomplete"].text() and "1" in counts["mixed"].text() + assert bar.counter("no_data").isHidden() # zero counters are not shown + + +def test_summary_counter_toggles_filter(qapp, construct, reports): + from ui.construct.summary_bar import SummaryBar + + bar = SummaryBar() + bar.set_data(construct, REGION, reports) + seen: list[set] = [] + bar.filter_changed.connect(seen.append) + bar.counter("ok").click() + assert seen[-1] == {"errors", "incomplete", "mixed", "no_data"} + bar.counter("errors").click() + assert seen[-1] == {"incomplete", "mixed", "no_data"} + bar.counter("ok").click() + assert seen[-1] == {"ok", "incomplete", "mixed", "no_data"} + + +def test_summary_whole_construct_and_wrapping_region(qapp, construct, reports): + from dataclasses import replace + + from i18n import tr + from ui.construct.summary_bar import SummaryBar + + bar = SummaryBar() + bar.set_data(construct, None, reports) + assert tr("construct.region_all") in bar.info_text() + circ = replace(construct, circular=True) + bar.set_data(circ, (600, 50), reports) + assert "601–50" in bar.info_text() and tr("construct.circular") in bar.info_text() + + +# ------------------------------------------------------------------ matrix + + +def test_filter_hides_rows(qapp, construct, reports): + m = _matrix(qapp, construct, reports) + assert m.visible_clones() == ["c1", "c2", "c3", "c4", "c5"] + m.set_filter({"errors"}) + assert m.visible_clones() == ["c2", "c3"] + assert m.row_rect("c2").top() < m.row_rect("c3").top() + assert m.row_rect("c1").isNull() + m.set_filter({"ok", "mixed"}) + assert m.visible_clones() == ["c1", "c5"] + + +def test_hit_test_on_difference_mark(qapp, construct, reports): + m = _matrix(qapp, construct, reports) + point = m.mark_point("c2", P) + assert m.hit_test(point) == ("c2", P) + assert m.hit_test(m.mark_point("c3", P)) == ("c3", P) + # the same x on the clean clone, and far from any mark: nothing + assert m.hit_test(QPoint(point.x(), m.row_rect("c1").center().y())) is None + away = QPoint(round(m.x_for(500)), m.row_rect("c2").center().y()) + assert m.hit_test(away) is None + # mixed positions are marks too + assert m.hit_test(m.mark_point("c5", 300)) == ("c5", 300) + + +def test_click_on_mark_and_on_row(qapp, construct, reports): + m = _matrix(qapp, construct, reports) + diffs, clones = [], [] + m.difference_clicked.connect(lambda c, p: diffs.append((c, p))) + m.clone_clicked.connect(clones.append) + left, none = Qt.MouseButton.LeftButton, Qt.MouseButton.NoButton + point = m.mark_point("c2", P) + _send_mouse(m, QEvent.Type.MouseButtonPress, point, left, left) + _send_mouse(m, QEvent.Type.MouseButtonRelease, point, left, none) + assert diffs == [("c2", P)] + row = QPoint(round(m.x_for(500)), m.row_rect("c4").center().y()) + _send_mouse(m, QEvent.Type.MouseButtonPress, row, left, left) + _send_mouse(m, QEvent.Type.MouseButtonRelease, row, left, none) + assert clones == ["c4"] + + +def test_shift_drag_on_reference_sets_region(qapp, construct, reports): + m = _matrix(qapp, construct, reports) + regions = [] + m.region_changed.connect(regions.append) + y = m.reference_rect().center().y() + a, b = QPoint(round(m.x_for(300)), y), QPoint(round(m.x_for(100)), y) + left, none = Qt.MouseButton.LeftButton, Qt.MouseButton.NoButton + shift = Qt.KeyboardModifier.ShiftModifier + _send_mouse(m, QEvent.Type.MouseButtonPress, a, left, left, shift) + _send_mouse(m, QEvent.Type.MouseMove, QPoint((a.x() + b.x()) // 2, y), none, left, shift) + _send_mouse(m, QEvent.Type.MouseMove, b, none, left, shift) + _send_mouse(m, QEvent.Type.MouseButtonRelease, b, left, none, shift) + assert len(regions) == 1 + start, end = regions[0] + assert abs(start - 100) <= 2 and abs(end - 300) <= 2 + assert m.view_range() == (0.0, float(len(construct.seq))) # no pan happened + + +def test_wheel_zooms_and_drag_pans(qapp, construct, reports): + m = _matrix(qapp, construct, reports) + L = float(len(construct.seq)) + assert m.view_range() == (0.0, L) + centre = QPointF(m.x_for(329), m.row_rect("c1").center().y()) + wheel = QWheelEvent(centre, m.mapToGlobal(centre), QPoint(), QPoint(0, 240), + Qt.MouseButton.NoButton, Qt.KeyboardModifier.NoModifier, + Qt.ScrollPhase.NoScrollPhase, False) + QApplication.sendEvent(m, wheel) + start, span = m.view_range() + assert span < L and start > 0 + assert abs(m.x_for(329) - centre.x()) < 1.5 # zoom keeps the point under the cursor + left, none = Qt.MouseButton.LeftButton, Qt.MouseButton.NoButton + p = centre.toPoint() + _send_mouse(m, QEvent.Type.MouseButtonPress, p, left, left) + _send_mouse(m, QEvent.Type.MouseMove, p + QPoint(60, 0), none, left) + _send_mouse(m, QEvent.Type.MouseButtonRelease, p + QPoint(60, 0), left, none) + assert m.view_range()[0] < start and m.view_range()[1] == span + # zooming out again never shows more than the construct + out = QWheelEvent(centre, m.mapToGlobal(centre), QPoint(), QPoint(0, -2400), + Qt.MouseButton.NoButton, Qt.KeyboardModifier.NoModifier, + Qt.ScrollPhase.NoScrollPhase, False) + QApplication.sendEvent(m, out) + assert m.view_range() == (0.0, L) + + +@pytest.mark.parametrize("theme", ["light", "dark"]) +def test_renders_in_both_themes(qapp, construct, reports, theme): + from ui.construct.matrix import mark_colors + from ui.status import status_color + + m = _matrix(qapp, construct, reports, theme=theme) + image = QImage(m.size(), QImage.Format.Format_ARGB32) + image.fill(QColor("#123456")) + m.render(image) + assert image.pixelColor(2, 2) != QColor("#123456") # background painted + point = m.mark_point("c2", P) + assert image.pixelColor(point) == mark_colors(theme)["confirmed"] + chip = m.chip_rect("c1") # sample the pill's padding, left of the text + assert image.pixelColor(chip.left() + 8, chip.center().y()) == status_color("ok", theme) + + +def test_wrapping_region_draws_two_segments(): + from ui.construct.matrix import segments + + assert segments(10, 40, 100) == [(10, 40)] + assert segments(90, 5, 100) == [(90, 100), (0, 5)] + assert segments(0, 100, 100) == [(0, 100)] + + +def _synthetic(clone: str, verdict: str, length: int) -> CloneReport: + coverage = {p: ((1, 1) if p % 50 else (1, 0)) for p in range(length)} + diffs = (CloneDifference(100, "substitution", "A", "G", 2, 0, 0, "confirmed", True),) + return CloneReport(clone, (), coverage, diffs if verdict == "errors" else (), (), verdict) + + +def test_twelve_rows_fit_in_600_px(qapp, construct): + from ui.construct.matrix import CloneMatrix + + verdicts = ["ok", "errors", "incomplete", "mixed", "no_data", "ok"] * 2 + reps = [_synthetic(f"clone_{i + 1}", v, len(construct.seq)) for i, v in enumerate(verdicts)] + m = CloneMatrix() + m.set_data(construct, None, reps) + assert m.sizeHint().height() <= 600 + m.resize(900, 600) + assert m.row_rect("clone_12").bottom() < 600 + assert m.hit_test(m.mark_point("clone_2", 100)) == ("clone_2", 100) diff --git a/translations_en.py b/translations_en.py index a14f9b8..e6e4e31 100644 --- a/translations_en.py +++ b/translations_en.py @@ -156,4 +156,30 @@ "batch.exported": "Exported: {n}, errors: {err}", "batch.export_dir": "Export to folder", "err.open_failed": "Failed to open file", + "construct.bp": "{n} bp", + "construct.circular": "circular", + "construct.linear": "linear", + "construct.region": "region {start}–{end}", + "construct.region_all": "region: whole construct", + "construct.count.ok": "OK: {n}", + "construct.count.errors": "Errors: {n}", + "construct.count.incomplete": "Incomplete: {n}", + "construct.count.mixed": "Mixed?: {n}", + "construct.count.no_data": "No data: {n}", + "construct.filter_tip": "Show or hide clones with this verdict", + "matrix.reference": "reference", + "matrix.chip.ok": "OK", + "matrix.chip.errors": "{n} diff.", + "matrix.chip.incomplete": "{pct}%", + "matrix.chip.mixed": "mixed?", + "matrix.chip.no_data": "no data", + "matrix.legend.cov_both": "both strands", + "matrix.legend.cov_one": "one strand", + "matrix.legend.cov_none": "none (Q<20)", + "matrix.legend.confirmed": "confirmed", + "matrix.legend.disputed": "disputed", + "matrix.legend.low_quality": "low Q", + "matrix.legend.mixed": "double peak", + "matrix.empty": "No clones to show", + "matrix.hint": "Wheel: zoom, drag: pan, Shift+drag on the reference: set the region", } diff --git a/ui/construct/__init__.py b/ui/construct/__init__.py new file mode 100644 index 0000000..7d37761 --- /dev/null +++ b/ui/construct/__init__.py @@ -0,0 +1,4 @@ +"""Construct verification screen: summary bar, clone matrix (and later details, grouping).""" + +# verdict order everywhere on this screen (counters, legend, filters) +VERDICTS = ("ok", "errors", "incomplete", "mixed", "no_data") diff --git a/ui/construct/matrix.py b/ui/construct/matrix.py new file mode 100644 index 0000000..050633f --- /dev/null +++ b/ui/construct/matrix.py @@ -0,0 +1,548 @@ +"""Clone matrix: every clone as a row on one shared coordinate axis under the +reference track (layout "B" of the construct screen). + +Colours +------- +- Coverage (per region position, reads with Q >= min_q): both strands -> theme + ``cov_both`` (saturated), one strand -> ``cov_one`` (light), none -> the empty + ``track`` background. Positions outside the region carry no coverage. +- Difference marks (in-region differences only) use the saturated variant of + the status palette (``STATUS_HEX`` dark tone) in both themes, so a thin mark + stays visible on light coverage: ``confirmed`` -> errors red, ``disputed`` -> + red/pale-red horizontal stripes, ``low_quality`` -> no-data grey; mixed + (double-peak) positions -> mixed purple. +- Verdict chips use ``status_color`` of the current theme. + +The axis is linear 0..L also for circular constructs; anything crossing the +origin (``start > end``) is drawn as two segments. +""" + +from __future__ import annotations + +import math + +from PySide6.QtCore import QPoint, QPointF, QRect, QRectF, QSize, Qt, Signal +from PySide6.QtGui import QColor, QFont, QFontMetrics, QMouseEvent, QPainter, QPen, QWheelEvent +from PySide6.QtWidgets import QWidget + +from chrom_core.clones import CloneReport, Region +from chrom_core.reference import Construct +from i18n import tr +from ui import status +from ui.construct import VERDICTS +from ui.theme import theme as palette + +MARGIN = 6 +RULER_H = 16 +REF_ROW_H = 28 +ROW_H = 24 +TRACK_H = 10 # clone coverage bar +REF_TRACK_H = 14 # reference / feature bar +MARK_H = 16 +LEGEND_H = 20 +CHIP_W = 84 +CHIP_H = 16 +GAP = 6 +NAME_MIN, NAME_MAX = 44, 160 +ZOOM_STEP = 1.25 # per wheel notch +MIN_SPAN = 20.0 # bp visible at most zoom +DRAG_SLOP = 3 # px before a press becomes a pan +HIT_SLOP = 4 # px around a mark that still hits it + +_STATUS_ORDER = ("low_quality", "disputed", "confirmed") # drawn bottom -> top + + +def segments(start: int, end: int, length: int) -> list[tuple[int, int]]: + """Linear pieces of a half-open interval; ``start > end`` wraps the origin.""" + if start <= end: + return [(start, end)] + return [(start, length), (0, end)] + + +def mark_colors(theme: str) -> dict[str, QColor]: + """Mark colour per difference status, plus ``mixed`` and the pale stripe of + ``disputed`` (``disputed_stripe``).""" + del theme # same saturated tones in both themes (see module docstring) + return { + "confirmed": status.status_color("errors", "dark"), + "disputed": status.status_color("errors", "dark"), + "disputed_stripe": status.status_color("errors", "light"), + "low_quality": status.status_color("no_data", "dark"), + "mixed": status.status_color("mixed", "dark"), + } + + +def _coverage_runs(report: CloneReport) -> list[tuple[int, int, int]]: + """``(start, end, level)`` runs of consecutive positions; level 2 = both + strands, 1 = one strand (positions without coverage are left out).""" + runs: list[list[int]] = [] + for pos in sorted(report.coverage): + plus, minus = report.coverage[pos] + level = 2 if plus and minus else 1 if plus + minus else 0 + if level == 0: + continue + if runs and runs[-1][1] == pos and runs[-1][2] == level: + runs[-1][1] = pos + 1 + else: + runs.append([pos, pos + 1, level]) + return [tuple(r) for r in runs] + + +class _Row: + def __init__(self, report: CloneReport) -> None: + self.report = report + self.runs = _coverage_runs(report) + self.differences = sorted( # stronger statuses painted last, on top + report.region_differences, + key=lambda d: _STATUS_ORDER.index(d.status) if d.status in _STATUS_ORDER else 0) + self.mixed = report.mixed_positions + + +class CloneMatrix(QWidget): + """Reference track plus one row per clone; custom painted. + + Wheel zooms the shared axis around the cursor, dragging pans it, a Shift+drag + on the reference track picks a region. A click on a mark emits + ``difference_clicked(clone, ref_pos)``, elsewhere on a row ``clone_clicked``. + """ + + difference_clicked = Signal(str, int) + clone_clicked = Signal(str) + region_changed = Signal(object) + + def __init__(self, parent: QWidget | None = None) -> None: + super().__init__(parent) + self._theme = status.current_theme() + self._construct: Construct | None = None + self._region: Region | None = None + self._rows: list[_Row] = [] + self._filter = set(VERDICTS) + self._view_start = 0.0 + self._view_span = 1.0 + self._press: QPoint | None = None + self._press_view = 0.0 + self._mode = "" # "", "click", "pan", "region" + self._band: tuple[float, float] | None = None + self.setToolTip(tr("matrix.hint")) + self.setMinimumWidth(320) + + # ------------------------------------------------------------- public API + def set_data(self, construct: Construct, region: Region | None, + reports: list[CloneReport]) -> None: + self._construct = construct + self._region = region + self._rows = [_Row(r) for r in reports] + self._view_start, self._view_span = 0.0, float(max(1, len(construct.seq))) + self.updateGeometry() + self.update() + + def set_filter(self, verdicts: set[str]) -> None: + self._filter = set(verdicts) + self.updateGeometry() + self.update() + + def set_theme(self, name: str) -> None: + self._theme = "dark" if name == "dark" else "light" + self.update() + + def visible_clones(self) -> list[str]: + return [row.report.clone for row in self._visible()] + + def view_range(self) -> tuple[float, float]: + """``(first position, number of positions)`` shown on the axis.""" + return (self._view_start, self._view_span) + + def x_for(self, pos: float) -> float: + left, width = self._track_left(), self._track_width() + return left + (pos - self._view_start) / self._view_span * width + + def pos_at(self, x: float) -> float: + return self._view_start + (x - self._track_left()) / self._track_width() * self._view_span + + def reference_rect(self) -> QRect: + return QRect(round(self._track_left()), MARGIN + RULER_H, + round(self._track_width()), REF_ROW_H) + + def row_rect(self, clone: str) -> QRect: + """Full-width rectangle of a shown clone's row; null when hidden or unknown.""" + for i, row in enumerate(self._visible()): + if row.report.clone == clone: + return QRect(0, self._rows_top() + i * ROW_H, self.width(), ROW_H) + return QRect() + + def chip_rect(self, clone: str) -> QRect: + row = self.row_rect(clone) + if row.isNull(): + return QRect() + return QRect(self.width() - MARGIN - CHIP_W, row.center().y() - CHIP_H // 2 + 1, + CHIP_W, CHIP_H) + + def mark_point(self, clone: str, ref_pos: int) -> QPoint: + """Centre of the mark drawn for ``ref_pos`` in ``clone``'s row.""" + data = self._row(clone) + diffs = data.differences if data is not None else [] + kind = next((d.kind for d in diffs if d.ref_pos == ref_pos), "substitution") + return QPoint(round(self._mark_x(ref_pos, kind)), self.row_rect(clone).center().y()) + + def hit_test(self, pos: QPoint) -> tuple[str, int] | None: + """``(clone, ref_pos)`` of the difference or mixed mark under ``pos``.""" + index = self._row_index_at(pos.y()) + if index is None or not self._track_left() - HIT_SLOP <= pos.x() <= self._track_right() + HIT_SLOP: + return None + row = self._visible()[index] + slop = max(HIT_SLOP, self._px_per_base() / 2 + 1) + best: tuple[float, int, int] | None = None # (distance, priority, ref_pos) + candidates = [(d.ref_pos, d.kind, 0) for d in row.differences] + candidates += [(p, "substitution", 1) for p in row.mixed] + for ref_pos, kind, priority in candidates: + distance = abs(self._mark_x(ref_pos, kind) - pos.x()) + if distance <= slop and (best is None or (distance, priority) < best[:2]): + best = (distance, priority, ref_pos) + return (row.report.clone, best[2]) if best else None + + def sizeHint(self) -> QSize: # noqa: N802 + return QSize(720, self._content_height()) + + def minimumSizeHint(self) -> QSize: # noqa: N802 + return QSize(320, self._content_height()) + + # --------------------------------------------------------------- geometry + def _visible(self) -> list[_Row]: + return [r for r in self._rows if r.report.verdict in self._filter] + + def _row(self, clone: str) -> _Row | None: + return next((r for r in self._rows if r.report.clone == clone), None) + + def _length(self) -> int: + return len(self._construct.seq) if self._construct else 1 + + def _name_width(self) -> int: + fm = QFontMetrics(self._bold_font()) + widest = max((fm.horizontalAdvance(r.report.clone) for r in self._rows), default=0) + return min(NAME_MAX, max(NAME_MIN, widest + GAP)) + + def _track_left(self) -> float: + return float(MARGIN + self._name_width()) + + def _track_right(self) -> float: + return float(self.width() - MARGIN - CHIP_W - GAP) + + def _track_width(self) -> float: + return max(1.0, self._track_right() - self._track_left()) + + def _px_per_base(self) -> float: + return self._track_width() / self._view_span + + def _rows_top(self) -> int: + return MARGIN + RULER_H + REF_ROW_H + + def _content_height(self) -> int: + rows = max(1, len(self._visible())) + return self._rows_top() + rows * ROW_H + GAP + LEGEND_H + MARGIN + + def _row_index_at(self, y: int) -> int | None: + offset = y - self._rows_top() + if offset < 0: + return None + index = offset // ROW_H + return index if index < len(self._visible()) else None + + def _mark_x(self, ref_pos: int, kind: str) -> float: + # an insertion sits before ``ref_pos``: on the boundary, not the base centre + return self.x_for(ref_pos if kind == "insertion" else ref_pos + 0.5) + + def _bold_font(self) -> QFont: + font = QFont(self.font()) + font.setBold(True) + return font + + def _small_font(self) -> QFont: + font = QFont(self.font()) + font.setPointSizeF(max(6.0, font.pointSizeF() - 1.5)) + return font + + def _set_view(self, start: float, span: float) -> None: + length = float(self._length()) + span = min(length, max(min(MIN_SPAN, length), span)) + start = min(max(0.0, start), length - span) + if (start, span) != (self._view_start, self._view_span): + self._view_start, self._view_span = start, span + self.update() + + # ------------------------------------------------------------------ input + def wheelEvent(self, event: QWheelEvent) -> None: # noqa: N802 + if self._construct is None: + return + steps = event.angleDelta().y() / 120.0 + if not steps: + return + x = event.position().x() + if not self._track_left() <= x <= self._track_right(): + x = (self._track_left() + self._track_right()) / 2 + anchor = self.pos_at(x) + fraction = (x - self._track_left()) / self._track_width() + span = self._view_span / ZOOM_STEP ** steps + length = float(self._length()) + span = min(length, max(min(MIN_SPAN, length), span)) + self._set_view(anchor - fraction * span, span) + event.accept() + + def mousePressEvent(self, event: QMouseEvent) -> None: # noqa: N802 + if event.button() != Qt.MouseButton.LeftButton or self._construct is None: + return + point = event.position().toPoint() + self._press, self._press_view = point, self._view_start + on_reference = self.reference_rect().adjusted(-HIT_SLOP, 0, HIT_SLOP, 0).contains(point) + if event.modifiers() & Qt.KeyboardModifier.ShiftModifier and on_reference: + self._mode = "region" + x = self._clamp_x(point.x()) + self._band = (x, x) + self.update() + else: + self._mode = "click" + + def mouseMoveEvent(self, event: QMouseEvent) -> None: # noqa: N802 + if self._press is None: + return + x = event.position().x() + if self._mode == "region": + self._band = (self._band[0], self._clamp_x(x)) + self.update() + return + dx = x - self._press.x() + if self._mode == "click" and abs(dx) > DRAG_SLOP: + self._mode = "pan" + if self._mode == "pan": + self._set_view(self._press_view - dx / self._track_width() * self._view_span, + self._view_span) + + def mouseReleaseEvent(self, event: QMouseEvent) -> None: # noqa: N802 + if self._press is None or event.button() != Qt.MouseButton.LeftButton: + return + mode, press = self._mode, self._press + self._press, self._mode = None, "" + if mode == "region": + a, b = sorted(self._band or (0.0, 0.0)) + self._band = None + self.update() + start, end = round(self.pos_at(a)), round(self.pos_at(b)) + start, end = max(0, start), min(self._length(), end) + if end > start: + self.region_changed.emit((start, end)) + elif mode == "click": + hit = self.hit_test(press) + if hit is not None: + self.difference_clicked.emit(*hit) + return + index = self._row_index_at(press.y()) + if index is not None: + self.clone_clicked.emit(self._visible()[index].report.clone) + + def _clamp_x(self, x: float) -> float: + lo, hi = self.x_for(0), self.x_for(self._length()) + return min(max(x, max(lo, self._track_left())), min(hi, self._track_right())) + + # --------------------------------------------------------------- painting + def paintEvent(self, event) -> None: # noqa: N802, ARG002 + colors = palette(self._theme) + painter = QPainter(self) + painter.fillRect(self.rect(), QColor(colors["bg"])) + if self._construct is None: + self._paint_empty(painter, colors) + painter.end() + return + self._paint_ruler(painter, colors) + self._paint_reference(painter, colors) + rows = self._visible() + for i, row in enumerate(rows): + self._paint_row(painter, colors, row, self._rows_top() + i * ROW_H) + if not rows: + self._paint_empty(painter, colors) + self._paint_region_lines(painter, colors, len(rows)) + self._paint_legend(painter, colors, max(1, len(rows))) + painter.end() + + def _track_clip(self) -> QRectF: + return QRectF(self._track_left(), 0, self._track_width(), self.height()) + + def _spans(self, start: int, end: int) -> list[QRectF]: + """Pixel x-extents (as zero-height rects) of an interval, split at the origin.""" + return [QRectF(self.x_for(a), 0, self.x_for(b) - self.x_for(a), 0) + for a, b in segments(start, end, self._length())] + + def _paint_empty(self, painter: QPainter, colors: dict) -> None: + painter.setPen(QColor(colors["dim"])) + rect = QRect(0, self._rows_top(), self.width(), ROW_H) + painter.drawText(rect, Qt.AlignmentFlag.AlignCenter, tr("matrix.empty")) + + def _paint_ruler(self, painter: QPainter, colors: dict) -> None: + painter.setFont(self._small_font()) + fm = painter.fontMetrics() + label_w = fm.horizontalAdvance(f"{self._length():,}") + 16 + raw = self._view_span * label_w / self._track_width() + magnitude = 10 ** math.floor(math.log10(max(raw, 1))) + step = next(m * magnitude for m in (1, 2, 5, 10) if m * magnitude >= raw) + y = MARGIN + RULER_H + painter.setPen(QPen(QColor(colors["dim"]), 1)) + painter.save() + painter.setClipRect(self._track_clip().adjusted(-label_w, 0, label_w, 0)) + first = max(step, math.ceil(self._view_start / step) * step) + v = first + while v <= self._view_start + self._view_span: + x = self.x_for(v) + painter.drawLine(QPointF(x, y - 4), QPointF(x, y)) + painter.drawText(QRectF(x - label_w / 2, MARGIN - 2, label_w, RULER_H - 3), + Qt.AlignmentFlag.AlignCenter, f"{int(v):,}".replace(",", " ")) + v += step + painter.restore() + painter.drawLine(QPointF(self._track_left(), y), QPointF(self._track_right(), y)) + + def _paint_reference(self, painter: QPainter, colors: dict) -> None: + top = MARGIN + RULER_H + cy = top + REF_ROW_H / 2 + track = QRectF(self._track_left(), cy - REF_TRACK_H / 2, self._track_width(), REF_TRACK_H) + painter.setFont(self._small_font()) + painter.setPen(QColor(colors["dim"])) + painter.drawText(QRectF(self.width() - MARGIN - CHIP_W, top, CHIP_W, REF_ROW_H), + Qt.AlignmentFlag.AlignCenter, tr("matrix.reference")) + painter.save() + painter.setClipRect(self._track_clip()) + self._fill_axis(painter, track, 0, self._length(), QColor(colors["track"])) + seen = set() + for feature in self._construct.features: + key = (feature.name, feature.start, feature.end) + if feature.kind == "source" or key in seen: + continue + seen.add(key) + colour = QColor(colors["feature_cds" if feature.kind in ("CDS", "gene") else "feature"]) + for span in self._spans(feature.start, feature.end): + rect = QRectF(span.left(), track.top(), span.width(), track.height()) + painter.fillRect(rect, colour) + if rect.width() > 24: + painter.setPen(QColor("#ffffff")) + text = painter.fontMetrics().elidedText( + feature.name, Qt.TextElideMode.ElideRight, int(rect.width()) - 6) + visible = rect.intersected(self._track_clip()) + painter.drawText(visible.adjusted(6, 0, -3, 0), + Qt.AlignmentFlag.AlignVCenter | Qt.AlignmentFlag.AlignLeft, text) + start, end = self._region if self._region is not None else (0, self._length()) + painter.setPen(QPen(QColor(colors["region"]), 2)) + painter.setBrush(Qt.BrushStyle.NoBrush) + for span in self._spans(start, end): + painter.drawRoundedRect(QRectF(span.left(), track.top() - 3, span.width(), + track.height() + 6), 3, 3) + if self._band is not None: + a, b = sorted(self._band) + band = QColor(colors["region"]) + band.setAlpha(80) + painter.fillRect(QRectF(a, track.top() - 3, b - a, track.height() + 6), band) + painter.restore() + + def _fill_axis(self, painter: QPainter, track: QRectF, start: int, end: int, + colour: QColor) -> None: + for span in self._spans(start, end): + painter.fillRect(QRectF(span.left(), track.top(), span.width(), track.height()), colour) + + def _paint_row(self, painter: QPainter, colors: dict, row: _Row, top: int) -> None: + report = row.report + cy = top + ROW_H / 2 + painter.setFont(self._bold_font()) + painter.setPen(QColor(colors["text"])) + name = painter.fontMetrics().elidedText(report.clone, Qt.TextElideMode.ElideRight, + self._name_width() - GAP) + painter.drawText(QRectF(MARGIN, top, self._name_width() - GAP, ROW_H), + Qt.AlignmentFlag.AlignVCenter | Qt.AlignmentFlag.AlignLeft, name) + + track = QRectF(self._track_left(), cy - TRACK_H / 2, self._track_width(), TRACK_H) + painter.save() + painter.setClipRect(self._track_clip()) + self._fill_axis(painter, track, 0, self._length(), QColor(colors["track"])) + shades = {2: QColor(colors["cov_both"]), 1: QColor(colors["cov_one"])} + for start, end, level in row.runs: + self._fill_axis(painter, track, start, end, shades[level]) + marks = mark_colors(self._theme) + width = max(3.0, self._px_per_base()) + for pos in row.mixed: + self._paint_mark(painter, self._mark_x(pos, "substitution"), cy, width, marks["mixed"]) + for d in row.differences: + x = self._mark_x(d.ref_pos, d.kind) + if d.status == "disputed": + self._paint_mark(painter, x, cy, width, marks["disputed_stripe"]) + for k in range(0, MARK_H, 4): + painter.fillRect(QRectF(x - width / 2, cy - MARK_H / 2 + k, width, 2), + marks["disputed"]) + else: + self._paint_mark(painter, x, cy, width, marks.get(d.status, marks["low_quality"])) + painter.restore() + self._paint_chip(painter, report) + + @staticmethod + def _paint_mark(painter: QPainter, x: float, cy: float, width: float, colour: QColor) -> None: + painter.fillRect(QRectF(x - width / 2, cy - MARK_H / 2, width, MARK_H), colour) + + def _chip_text(self, report: CloneReport) -> str: + if report.verdict == "errors": + n = sum(1 for d in report.region_differences if d.status != "low_quality") + return tr("matrix.chip.errors", n=n) + if report.verdict == "incomplete": + return tr("matrix.chip.incomplete", pct=math.floor(report.region_coverage_pct)) + return tr(f"matrix.chip.{report.verdict}") if report.verdict in VERDICTS else report.verdict + + def _paint_chip(self, painter: QPainter, report: CloneReport) -> None: + rect = QRectF(self.chip_rect(report.clone)) + painter.save() + painter.setRenderHint(QPainter.RenderHint.Antialiasing) + painter.setPen(Qt.PenStyle.NoPen) + painter.setBrush(status.status_color(report.verdict, self._theme)) + painter.drawRoundedRect(rect, CHIP_H / 2, CHIP_H / 2) + painter.setPen(status.status_text_color(report.verdict, self._theme)) + painter.setFont(self._small_font()) + text = painter.fontMetrics().elidedText(self._chip_text(report), + Qt.TextElideMode.ElideRight, CHIP_W - 8) + painter.drawText(rect, Qt.AlignmentFlag.AlignCenter, text) + painter.restore() + + def _paint_region_lines(self, painter: QPainter, colors: dict, n_rows: int) -> None: + """Thin dashed region boundaries through the clone rows.""" + if self._region is None or n_rows == 0: + return + top, bottom = self._rows_top(), self._rows_top() + n_rows * ROW_H + pen = QPen(QColor(colors["region"]), 1, Qt.PenStyle.DashLine) + painter.save() + painter.setClipRect(self._track_clip()) + painter.setPen(pen) + for x in {self.x_for(self._region[0]), self.x_for(self._region[1])}: + painter.drawLine(QPointF(x, top), QPointF(x, bottom)) + painter.restore() + + def _paint_legend(self, painter: QPainter, colors: dict, n_rows: int) -> None: + top = self._rows_top() + n_rows * ROW_H + GAP + marks = mark_colors(self._theme) + items = [ + ("block", QColor(colors["cov_both"]), "matrix.legend.cov_both"), + ("block", QColor(colors["cov_one"]), "matrix.legend.cov_one"), + ("block", QColor(colors["track"]), "matrix.legend.cov_none"), + ("mark", marks["confirmed"], "matrix.legend.confirmed"), + ("stripe", marks["disputed"], "matrix.legend.disputed"), + ("mark", marks["low_quality"], "matrix.legend.low_quality"), + ("mark", marks["mixed"], "matrix.legend.mixed"), + ] + painter.setFont(self._small_font()) + fm = painter.fontMetrics() + x, cy = float(self._track_left()), top + LEGEND_H / 2 + for kind, colour, key in items: + if kind == "block": + painter.fillRect(QRectF(x, cy - 4, 14, 8), colour) + x += 18 + else: + if kind == "stripe": + painter.fillRect(QRectF(x, cy - 6, 4, 12), marks["disputed_stripe"]) + for k in range(0, 12, 4): + painter.fillRect(QRectF(x, cy - 6 + k, 4, 2), colour) + else: + painter.fillRect(QRectF(x, cy - 6, 4, 12), colour) + x += 8 + text = tr(key) + painter.setPen(QColor(colors["dim"])) + painter.drawText(QPointF(x, cy + fm.ascent() / 2 - 1), text) + x += fm.horizontalAdvance(text) + 12 diff --git a/ui/construct/summary_bar.py b/ui/construct/summary_bar.py new file mode 100644 index 0000000..cf35be9 --- /dev/null +++ b/ui/construct/summary_bar.py @@ -0,0 +1,118 @@ +"""One-line summary of a construct check: name, length, topology, region and +per-verdict clone counters that double as row filters for the matrix.""" + +from __future__ import annotations + +from collections import Counter + +from PySide6.QtCore import Signal +from PySide6.QtWidgets import QHBoxLayout, QLabel, QPushButton, QWidget + +from chrom_core.clones import CloneReport, Region +from chrom_core.reference import Construct +from i18n import tr +from ui import status +from ui.construct import VERDICTS +from ui.theme import theme as palette + + +def region_text(region: Region | None) -> str: + """``region 7–647`` (1-based, inclusive); ``None`` is the whole construct.""" + if region is None: + return tr("construct.region_all") + start, end = region + return tr("construct.region", start=start + 1, end=end) + + +def _thousands(n: int) -> str: + return f"{n:,}".replace(",", " ") + + +class SummaryBar(QWidget): + """Construct name and facts, then a counter chip per verdict. + + Clicking a counter toggles that verdict in the shown set and emits + ``filter_changed`` with the verdicts still shown. + """ + + filter_changed = Signal(set) + + def __init__(self, parent: QWidget | None = None) -> None: + super().__init__(parent) + self._theme = status.current_theme() + self._shown = set(VERDICTS) + layout = QHBoxLayout(self) + layout.setContentsMargins(8, 4, 8, 4) + layout.setSpacing(8) + self._title = QLabel() + self._title.setStyleSheet("font-weight: 600;") + self._info = QLabel() + layout.addWidget(self._title) + layout.addWidget(self._info) + self._counters: dict[str, QPushButton] = {} + for verdict in VERDICTS: + button = QPushButton() + button.setCheckable(True) + button.setChecked(True) + button.setFlat(True) + button.setToolTip(tr("construct.filter_tip")) + button.toggled.connect(lambda on, v=verdict: self._toggle(v, on)) + button.hide() + layout.addWidget(button) + self._counters[verdict] = button + layout.addStretch(1) + self._restyle() + + # ------------------------------------------------------------- public API + def set_data(self, construct: Construct, region: Region | None, + reports: list[CloneReport]) -> None: + self._title.setText(construct.name) + topology = tr("construct.circular" if construct.circular else "construct.linear") + self._info.setText(" · ".join(( + f"{tr('construct.bp', n=_thousands(len(construct.seq)))}, {topology}", + region_text(region), + ))) + counts = Counter(r.verdict for r in reports) + for verdict, button in self._counters.items(): + n = counts.get(verdict, 0) + button.setText(tr(f"construct.count.{verdict}", n=n)) + button.setVisible(n > 0) + + def counter(self, verdict: str) -> QPushButton: + return self._counters[verdict] + + def shown_verdicts(self) -> set[str]: + return set(self._shown) + + def title_text(self) -> str: + return self._title.text() + + def info_text(self) -> str: + return self._info.text() + + def set_theme(self, name: str) -> None: + self._theme = "dark" if name == "dark" else "light" + self._restyle() + + # --------------------------------------------------------------- private + def _toggle(self, verdict: str, on: bool) -> None: + if on: + self._shown.add(verdict) + else: + self._shown.discard(verdict) + self._restyle() + self.filter_changed.emit(set(self._shown)) + + def _restyle(self) -> None: + dim = palette(self._theme)["dim"] + for verdict, button in self._counters.items(): + bg = status.status_color(verdict, self._theme).name() + fg = status.status_text_color(verdict, self._theme).name() + # shown: filled chip; hidden: outline only, struck through + button.setStyleSheet( + "QPushButton { border-radius: 9px; padding: 1px 10px; font-weight: 600;" + f" border: 1px solid {bg}; background-color: transparent; color: {dim};" + " text-decoration: line-through; }" + f"QPushButton:checked {{ background-color: {bg}; color: {fg};" + " text-decoration: none; }" + ) diff --git a/ui/theme.py b/ui/theme.py index 9c5b68b..73f58ec 100644 --- a/ui/theme.py +++ b/ui/theme.py @@ -20,6 +20,14 @@ "low_q": "#e02020", "mid_q": "#e0a000", "high_q": "#1e9e1e", + # construct matrix: coverage on both strands / one strand, empty track, + # region frame, features (CDS/gene and others) + "cov_both": "#4caf50", + "cov_one": "#b5e0b7", + "track": "#e8e8e8", + "region": "#2563eb", + "feature_cds": "#2e8b57", + "feature": "#7a8290", } DARK = { @@ -35,6 +43,12 @@ "low_q": "#ff5252", "mid_q": "#e0a000", "high_q": "#37d437", + "cov_both": "#43a047", + "cov_one": "#3d6e41", + "track": "#333333", + "region": "#5b8def", + "feature_cds": "#2e7d4f", + "feature": "#5c6370", } From 90d35cd4cedf0d73cf0b5c8f57b6668051054813 Mon Sep 17 00:00:00 2001 From: Aleksey Drobin <43707931+adrobi@users.noreply.github.com> Date: Fri, 30 Oct 2026 10:44:32 +0300 Subject: [PATCH 25/44] ui: matrix review fixes: cached name width, out-of-region marks, hollow disputed, 1-based ruler Co-Authored-By: Claude Opus 5.5 --- i18n.py | 2 + tests/test_construct_ui.py | 140 +++++++++++++++++++++++++++-- translations_en.py | 2 + ui/construct/matrix.py | 174 ++++++++++++++++++++++++++----------- 4 files changed, 257 insertions(+), 61 deletions(-) diff --git a/i18n.py b/i18n.py index 55ef466..153ee40 100644 --- a/i18n.py +++ b/i18n.py @@ -187,6 +187,8 @@ "matrix.legend.disputed": "спорно", "matrix.legend.low_quality": "низкое Q", "matrix.legend.mixed": "двойной пик", + "matrix.legend.unchecked": "не проверяется", + "matrix.legend.outside": "вне региона", "matrix.empty": "Нет клонов для показа", "matrix.hint": "Колёсико — масштаб, перетаскивание — сдвиг, Shift+протяжка по референсу — задать регион", } diff --git a/tests/test_construct_ui.py b/tests/test_construct_ui.py index c79d545..3239595 100644 --- a/tests/test_construct_ui.py +++ b/tests/test_construct_ui.py @@ -28,6 +28,7 @@ R = DATA / "real" / R_NAME REGION = (6, 647) P = 250 # substitution site inside the region +OUTSIDE = 652 # covered by F only, outside the region MIXED_AT = (200, 300, 400) @@ -53,10 +54,15 @@ def reports(construct, tmp_path_factory): folder = tmp_path_factory.mktemp("clones") i = _f_index(construct, P) # a C peak 4x the called base, then the call edited to C: the trace agrees - # with the edit (no artificial double peak at P) - assert real_read(F_NAME).seq[i] != "C" - edited = EditableRead(with_secondary_peak(real_read(F_NAME), i, "C", 4.0)) - edited.set_base(i, "C") + # with the edit (no artificial double peak); same at OUTSIDE + chrom = real_read(F_NAME) + o = _f_index(construct, OUTSIDE) + edits = {i: "C" if chrom.seq[i] != "C" else "G", o: "C" if chrom.seq[o] != "C" else "G"} + for index, base in edits.items(): + chrom = with_secondary_peak(chrom, index, base, 4.0) + edited = EditableRead(chrom) + for index, base in edits.items(): + edited.set_base(index, base) sub_dir = folder / "sub" sub_dir.mkdir() f_sub = write_read(edited.current(), sub_dir, F_NAME) @@ -86,6 +92,7 @@ def reports(construct, tmp_path_factory): assert [r.verdict for r in out] == ["ok", "errors", "errors", "incomplete", "mixed"] assert [d.status for d in out[1].region_differences] == ["confirmed"] assert [d.status for d in out[2].region_differences] == ["disputed"] + assert [d.ref_pos for d in out[1].differences if not d.in_region] == [OUTSIDE] return out @@ -246,16 +253,133 @@ def test_renders_in_both_themes(qapp, construct, reports, theme): from ui.status import status_color m = _matrix(qapp, construct, reports, theme=theme) - image = QImage(m.size(), QImage.Format.Format_ARGB32) - image.fill(QColor("#123456")) - m.render(image) + image = _render(m, QColor("#123456")) assert image.pixelColor(2, 2) != QColor("#123456") # background painted point = m.mark_point("c2", P) - assert image.pixelColor(point) == mark_colors(theme)["confirmed"] + assert image.pixelColor(point) == mark_colors()["confirmed"] chip = m.chip_rect("c1") # sample the pill's padding, left of the text assert image.pixelColor(chip.left() + 8, chip.center().y()) == status_color("ok", theme) +def _render(m, fill=QColor("#123456")) -> QImage: + image = QImage(m.size(), QImage.Format.Format_ARGB32) + image.fill(fill) + m.render(image) + return image + + +def test_disputed_mark_is_hollow(qapp, construct, reports): + from ui.construct.matrix import mark_colors + + m = _matrix(qapp, construct, reports) + image = _render(m) + red = mark_colors()["disputed"] + centre = m.mark_point("c3", P) + assert image.pixelColor(centre) != red # hollow inside + edges = [image.pixelColor(centre + QPoint(dx, 0)) for dx in range(-4, 5)] + assert edges.count(red) == 2 # left and right outline + assert sum(1 for dx in range(-4, 5) if image.pixelColor(centre + QPoint(dx, 0)) != red + and abs(dx) <= 1) == 3 # >= 5 px wide outline + assert image.pixelColor(m.mark_point("c2", P)) == mark_colors()["confirmed"] # solid + + +def test_out_of_region_difference_drawn_and_clickable(qapp, construct, reports): + from ui.theme import theme as palette + + m = _matrix(qapp, construct, reports) + image = _render(m) + point = m.mark_point("c2", OUTSIDE) + colour = image.pixelColor(point) + assert colour.red() > colour.green() + 40 and colour.red() > colour.blue() + 40 + assert m.hit_test(point) == ("c2", OUTSIDE) + clicked = [] + m.difference_clicked.connect(lambda c, p: clicked.append((c, p))) + left, none = Qt.MouseButton.LeftButton, Qt.MouseButton.NoButton + _send_mouse(m, QEvent.Type.MouseButtonPress, point, left, left) + _send_mouse(m, QEvent.Type.MouseButtonRelease, point, left, none) + assert clicked == [("c2", OUTSIDE)] + # outside the region the track is hatched ("not checked"); a gap in the + # region's coverage stays the plain track colour ("no coverage") + track = QColor(palette("light")["track"]) + y = m.row_rect("c1").center().y() + hatched = [image.pixelColor(x, y + dy) for dx in range(10) + for x in [round(m.x_for(647)) + 2 + dx] for dy in range(-4, 5) + if x < round(m.x_for(len(construct.seq)))] + assert hatched and any(c != track for c in hatched) + y4 = m.row_rect("c4").center().y() + assert all(image.pixelColor(x, y4) == track + for x in range(round(m.x_for(450)), round(m.x_for(470)))) + + +def test_hit_test_while_zoomed(qapp, construct, reports): + m = _matrix(qapp, construct, reports) + anchor = QPointF(m.x_for(P + 0.5), m.row_rect("c2").center().y()) + zoom = QWheelEvent(anchor, m.mapToGlobal(anchor), QPoint(), QPoint(0, 120 * 12), + Qt.MouseButton.NoButton, Qt.KeyboardModifier.NoModifier, + Qt.ScrollPhase.NoScrollPhase, False) + QApplication.sendEvent(m, zoom) + assert m.view_range()[1] < 100 + point = m.mark_point("c2", P) + assert m.hit_test(point) == ("c2", P) + neighbour = QPoint(round(m.x_for(P + 3.5)), point.y()) # three bases away + assert m.hit_test(neighbour) is None + assert m.hit_test(QPoint(point.x(), m.row_rect("c1").center().y())) is None + + +def test_ruler_labels_are_one_based(qapp, construct, reports): + m = _matrix(qapp, construct, reports) + ticks = m.ruler_ticks() + assert ticks and all(v % ticks[0][0] == 0 for v, _ in ticks) + for v, x in ticks: + assert int(m.pos_at(x)) + 1 == v # the tick sits on base number v (1-based) + + +def test_mark_at_last_position(qapp, construct): + from ui.construct.matrix import CloneMatrix, mark_colors + + last = len(construct.seq) - 1 + rep = _synthetic("end", "errors", len(construct.seq)) + rep = CloneReport(rep.clone, (), rep.coverage, ( + CloneDifference(last, "substitution", "A", "G", 2, 0, 0, "confirmed", True),), (), "errors") + m = CloneMatrix() + m.set_data(construct, None, [rep]) + m.resize(900, m.sizeHint().height()) + point = m.mark_point("end", last) + assert point.x() < m.chip_rect("end").left() + assert m.hit_test(point) == ("end", last) + assert _render(m).pixelColor(point) == mark_colors()["confirmed"] + + +# measured ~12 ms (best of 5) on the dev machine for 12 rows x 200 runs on 10 kb; +# the bound is about 2x that (it was ~440 ms before name widths were cached) +PAINT_BUDGET_S = 0.025 + + +def test_paint_cost_10kb_12_rows(qapp): + import time + + from chrom_core.reference import Construct + from ui.construct.matrix import CloneMatrix + + length = 10_000 + big = Construct("big", "ACGT" * (length // 4), False, ()) + coverage = {p: ((1, 1) if (p // 50) % 2 else (1, 0)) for p in range(length)} # 200 runs + reps = [CloneReport(f"clone_{i}", (), coverage, (), (), "ok") for i in range(12)] + m = CloneMatrix() + m.set_data(big, None, reps) + m.resize(1200, m.sizeHint().height()) + image = QImage(m.size(), QImage.Format.Format_ARGB32) + m.render(image) # warm-up + best = min(_timed(m, image, time) for _ in range(3)) + assert best < PAINT_BUDGET_S, f"paint took {best * 1000:.0f} ms" + + +def _timed(m, image, time) -> float: + start = time.perf_counter() + m.render(image) + return time.perf_counter() - start + + def test_wrapping_region_draws_two_segments(): from ui.construct.matrix import segments diff --git a/translations_en.py b/translations_en.py index e6e4e31..1d5b226 100644 --- a/translations_en.py +++ b/translations_en.py @@ -180,6 +180,8 @@ "matrix.legend.disputed": "disputed", "matrix.legend.low_quality": "low Q", "matrix.legend.mixed": "double peak", + "matrix.legend.unchecked": "not checked", + "matrix.legend.outside": "outside region", "matrix.empty": "No clones to show", "matrix.hint": "Wheel: zoom, drag: pan, Shift+drag on the reference: set the region", } diff --git a/ui/construct/matrix.py b/ui/construct/matrix.py index 050633f..7f5c725 100644 --- a/ui/construct/matrix.py +++ b/ui/construct/matrix.py @@ -5,12 +5,15 @@ ------- - Coverage (per region position, reads with Q >= min_q): both strands -> theme ``cov_both`` (saturated), one strand -> ``cov_one`` (light), none -> the empty - ``track`` background. Positions outside the region carry no coverage. -- Difference marks (in-region differences only) use the saturated variant of - the status palette (``STATUS_HEX`` dark tone) in both themes, so a thin mark - stays visible on light coverage: ``confirmed`` -> errors red, ``disputed`` -> - red/pale-red horizontal stripes, ``low_quality`` -> no-data grey; mixed - (double-peak) positions -> mixed purple. + ``track`` background. Outside the region the core computes no coverage, so + the track there is hatched as "not checked". +- Difference marks use the saturated variant of the status palette + (``STATUS_HEX`` dark tone) in both themes, so a thin mark stays visible on + light coverage: ``confirmed`` -> solid errors red, ``disputed`` -> hollow + errors-red outline (at least 5 px wide), ``low_quality`` -> solid no-data + grey; mixed (double-peak) positions -> solid mixed purple. Differences + outside the region (they do not affect the verdict) keep their style but are + shorter and translucent. - Verdict chips use ``status_color`` of the current theme. The axis is linear 0..L also for circular constructs; anything crossing the @@ -21,8 +24,8 @@ import math -from PySide6.QtCore import QPoint, QPointF, QRect, QRectF, QSize, Qt, Signal -from PySide6.QtGui import QColor, QFont, QFontMetrics, QMouseEvent, QPainter, QPen, QWheelEvent +from PySide6.QtCore import QEvent, QPoint, QPointF, QRect, QRectF, QSize, Qt, Signal +from PySide6.QtGui import QBrush, QColor, QFont, QFontMetrics, QMouseEvent, QPainter, QPen, QWheelEvent from PySide6.QtWidgets import QWidget from chrom_core.clones import CloneReport, Region @@ -39,6 +42,10 @@ TRACK_H = 10 # clone coverage bar REF_TRACK_H = 14 # reference / feature bar MARK_H = 16 +OUT_MARK_H = 10 # differences outside the region: shorter ... +OUT_ALPHA = 180 # ... and translucent +MARK_MIN_W = 3 +OUTLINE_MIN_W = 5 # hollow (disputed) marks need room for an inside LEGEND_H = 20 CHIP_W = 84 CHIP_H = 16 @@ -59,19 +66,25 @@ def segments(start: int, end: int, length: int) -> list[tuple[int, int]]: return [(start, length), (0, end)] -def mark_colors(theme: str) -> dict[str, QColor]: - """Mark colour per difference status, plus ``mixed`` and the pale stripe of - ``disputed`` (``disputed_stripe``).""" - del theme # same saturated tones in both themes (see module docstring) +def mark_colors() -> dict[str, QColor]: + """Mark colour per difference status, plus ``mixed``. The same saturated + tones are used in both themes (see the module docstring).""" return { "confirmed": status.status_color("errors", "dark"), "disputed": status.status_color("errors", "dark"), - "disputed_stripe": status.status_color("errors", "light"), "low_quality": status.status_color("no_data", "dark"), "mixed": status.status_color("mixed", "dark"), } +def outside(region: tuple[int, int] | None, length: int) -> list[tuple[int, int]]: + """Linear pieces of the construct outside ``region`` (none for ``None``).""" + if region is None: + return [] + start, end = region + return [(a, b) for a, b in segments(end, start, length) if b > a] + + def _coverage_runs(report: CloneReport) -> list[tuple[int, int, int]]: """``(start, end, level)`` runs of consecutive positions; level 2 = both strands, 1 = one strand (positions without coverage are left out).""" @@ -92,9 +105,10 @@ class _Row: def __init__(self, report: CloneReport) -> None: self.report = report self.runs = _coverage_runs(report) - self.differences = sorted( # stronger statuses painted last, on top - report.region_differences, - key=lambda d: _STATUS_ORDER.index(d.status) if d.status in _STATUS_ORDER else 0) + self.differences = sorted( # in-region and stronger statuses painted last, on top + report.differences, + key=lambda d: (d.in_region, + _STATUS_ORDER.index(d.status) if d.status in _STATUS_ORDER else 0)) self.mixed = report.mixed_positions @@ -123,6 +137,7 @@ def __init__(self, parent: QWidget | None = None) -> None: self._press_view = 0.0 self._mode = "" # "", "click", "pan", "region" self._band: tuple[float, float] | None = None + self._name_w = NAME_MIN self.setToolTip(tr("matrix.hint")) self.setMinimumWidth(320) @@ -132,6 +147,7 @@ def set_data(self, construct: Construct, region: Region | None, self._construct = construct self._region = region self._rows = [_Row(r) for r in reports] + self._update_name_width() self._view_start, self._view_span = 0.0, float(max(1, len(construct.seq))) self.updateGeometry() self.update() @@ -159,6 +175,22 @@ def x_for(self, pos: float) -> float: def pos_at(self, x: float) -> float: return self._view_start + (x - self._track_left()) / self._track_width() * self._view_span + def ruler_ticks(self) -> list[tuple[int, float]]: + """``(label, x)`` of the ruler ticks: 1-based base numbers at base centres, + so they read like the summary's region text.""" + fm = QFontMetrics(self._small_font()) + label_w = fm.horizontalAdvance(f"{self._length():,}") + 16 + raw = self._view_span * label_w / self._track_width() + magnitude = 10 ** math.floor(math.log10(max(raw, 1))) + step = next(m * magnitude for m in (1, 2, 5, 10) if m * magnitude >= raw) + end = self._view_start + self._view_span + v = max(step, math.ceil((self._view_start + 0.5) / step) * step) + ticks = [] + while v - 0.5 <= end and v <= self._length(): + ticks.append((int(v), self.x_for(v - 0.5))) + v += step + return ticks + def reference_rect(self) -> QRect: return QRect(round(self._track_left()), MARGIN + RULER_H, round(self._track_width()), REF_ROW_H) @@ -217,9 +249,19 @@ def _length(self) -> int: return len(self._construct.seq) if self._construct else 1 def _name_width(self) -> int: + return self._name_w + + def _update_name_width(self) -> None: + """Measure the clone names once (on new data or a font/style change).""" fm = QFontMetrics(self._bold_font()) widest = max((fm.horizontalAdvance(r.report.clone) for r in self._rows), default=0) - return min(NAME_MAX, max(NAME_MIN, widest + GAP)) + self._name_w = min(NAME_MAX, max(NAME_MIN, widest + GAP)) + + def changeEvent(self, event: QEvent) -> None: # noqa: N802 + if event.type() in (QEvent.Type.FontChange, QEvent.Type.StyleChange): + self._update_name_width() + self.update() + super().changeEvent(event) def _track_left(self) -> float: return float(MARGIN + self._name_width()) @@ -377,23 +419,15 @@ def _paint_empty(self, painter: QPainter, colors: dict) -> None: def _paint_ruler(self, painter: QPainter, colors: dict) -> None: painter.setFont(self._small_font()) - fm = painter.fontMetrics() - label_w = fm.horizontalAdvance(f"{self._length():,}") + 16 - raw = self._view_span * label_w / self._track_width() - magnitude = 10 ** math.floor(math.log10(max(raw, 1))) - step = next(m * magnitude for m in (1, 2, 5, 10) if m * magnitude >= raw) + label_w = painter.fontMetrics().horizontalAdvance(f"{self._length():,}") + 16 y = MARGIN + RULER_H painter.setPen(QPen(QColor(colors["dim"]), 1)) painter.save() painter.setClipRect(self._track_clip().adjusted(-label_w, 0, label_w, 0)) - first = max(step, math.ceil(self._view_start / step) * step) - v = first - while v <= self._view_start + self._view_span: - x = self.x_for(v) + for v, x in self.ruler_ticks(): painter.drawLine(QPointF(x, y - 4), QPointF(x, y)) painter.drawText(QRectF(x - label_w / 2, MARGIN - 2, label_w, RULER_H - 3), - Qt.AlignmentFlag.AlignCenter, f"{int(v):,}".replace(",", " ")) - v += step + Qt.AlignmentFlag.AlignCenter, f"{v:,}".replace(",", "\u202f")) painter.restore() painter.drawLine(QPointF(self._track_left(), y), QPointF(self._track_right(), y)) @@ -457,28 +491,50 @@ def _paint_row(self, painter: QPainter, colors: dict, row: _Row, top: int) -> No painter.save() painter.setClipRect(self._track_clip()) self._fill_axis(painter, track, 0, self._length(), QColor(colors["track"])) + self._paint_unchecked(painter, colors, track) shades = {2: QColor(colors["cov_both"]), 1: QColor(colors["cov_one"])} - for start, end, level in row.runs: - self._fill_axis(painter, track, start, end, shades[level]) - marks = mark_colors(self._theme) - width = max(3.0, self._px_per_base()) + first, last = self._view_start, self._view_start + self._view_span + for start, end, level in row.runs: # runs are linear (never wrap) + if end <= first or start >= last: + continue + x0 = self.x_for(start) + painter.fillRect(QRectF(x0, track.top(), self.x_for(end) - x0, track.height()), + shades[level]) + marks = mark_colors() for pos in row.mixed: - self._paint_mark(painter, self._mark_x(pos, "substitution"), cy, width, marks["mixed"]) + self._paint_mark(painter, self._mark_x(pos, "substitution"), cy, marks["mixed"]) for d in row.differences: - x = self._mark_x(d.ref_pos, d.kind) - if d.status == "disputed": - self._paint_mark(painter, x, cy, width, marks["disputed_stripe"]) - for k in range(0, MARK_H, 4): - painter.fillRect(QRectF(x - width / 2, cy - MARK_H / 2 + k, width, 2), - marks["disputed"]) - else: - self._paint_mark(painter, x, cy, width, marks.get(d.status, marks["low_quality"])) + if not first - 1 <= d.ref_pos <= last: + continue + colour = QColor(marks.get(d.status, marks["low_quality"])) + if not d.in_region: + colour.setAlpha(OUT_ALPHA) + self._paint_mark(painter, self._mark_x(d.ref_pos, d.kind), cy, colour, + hollow=d.status == "disputed", + height=MARK_H if d.in_region else OUT_MARK_H) painter.restore() self._paint_chip(painter, report) - @staticmethod - def _paint_mark(painter: QPainter, x: float, cy: float, width: float, colour: QColor) -> None: - painter.fillRect(QRectF(x - width / 2, cy - MARK_H / 2, width, MARK_H), colour) + def _paint_unchecked(self, painter: QPainter, colors: dict, track: QRectF) -> None: + """Hatch the track outside the region: not checked, not "no coverage".""" + hatch = QColor(colors["dim"]) + hatch.setAlpha(140) + for a, b in outside(self._region, self._length()): + x0 = self.x_for(a) + painter.fillRect(QRectF(x0, track.top(), self.x_for(b) - x0, track.height()), + QBrush(hatch, Qt.BrushStyle.BDiagPattern)) + + def _paint_mark(self, painter: QPainter, x: float, cy: float, colour: QColor, + hollow: bool = False, height: int = MARK_H) -> None: + """A whole-pixel mark centred on ``x``; ``hollow`` draws a 1 px outline.""" + width = max(OUTLINE_MIN_W if hollow else MARK_MIN_W, round(self._px_per_base())) + left, top = round(x - width / 2), round(cy - height / 2) + if not hollow: + painter.fillRect(QRect(left, top, width, height), colour) + return + for rect in (QRect(left, top, width, 1), QRect(left, top + height - 1, width, 1), + QRect(left, top, 1, height), QRect(left + width - 1, top, 1, height)): + painter.fillRect(rect, colour) def _chip_text(self, report: CloneReport) -> str: if report.verdict == "errors": @@ -517,31 +573,43 @@ def _paint_region_lines(self, painter: QPainter, colors: dict, n_rows: int) -> N def _paint_legend(self, painter: QPainter, colors: dict, n_rows: int) -> None: top = self._rows_top() + n_rows * ROW_H + GAP - marks = mark_colors(self._theme) + marks = mark_colors() + dim_red = QColor(marks["confirmed"]) + dim_red.setAlpha(OUT_ALPHA) items = [ ("block", QColor(colors["cov_both"]), "matrix.legend.cov_both"), ("block", QColor(colors["cov_one"]), "matrix.legend.cov_one"), ("block", QColor(colors["track"]), "matrix.legend.cov_none"), + ("hatch", QColor(colors["track"]), "matrix.legend.unchecked"), ("mark", marks["confirmed"], "matrix.legend.confirmed"), - ("stripe", marks["disputed"], "matrix.legend.disputed"), + ("hollow", marks["disputed"], "matrix.legend.disputed"), ("mark", marks["low_quality"], "matrix.legend.low_quality"), ("mark", marks["mixed"], "matrix.legend.mixed"), + ("short", dim_red, "matrix.legend.outside"), ] painter.setFont(self._small_font()) fm = painter.fontMetrics() + hatch = QColor(colors["dim"]) + hatch.setAlpha(140) x, cy = float(self._track_left()), top + LEGEND_H / 2 for kind, colour, key in items: - if kind == "block": + if kind in ("block", "hatch"): painter.fillRect(QRectF(x, cy - 4, 14, 8), colour) + if kind == "hatch": + painter.fillRect(QRectF(x, cy - 4, 14, 8), + QBrush(hatch, Qt.BrushStyle.BDiagPattern)) x += 18 else: - if kind == "stripe": - painter.fillRect(QRectF(x, cy - 6, 4, 12), marks["disputed_stripe"]) - for k in range(0, 12, 4): - painter.fillRect(QRectF(x, cy - 6 + k, 4, 2), colour) + rect = QRect(round(x), round(cy) - 6, 5 if kind == "hollow" else 4, 12) + if kind == "short": + rect = QRect(rect.left(), round(cy) - 4, 4, 8) + if kind == "hollow": + painter.setPen(colour) + painter.setBrush(Qt.BrushStyle.NoBrush) + painter.drawRect(rect.adjusted(0, 0, -1, -1)) else: - painter.fillRect(QRectF(x, cy - 6, 4, 12), colour) - x += 8 + painter.fillRect(rect, colour) + x += 9 text = tr(key) painter.setPen(QColor(colors["dim"])) painter.drawText(QPointF(x, cy + fm.ascent() / 2 - 1), text) From f2c0b60ce42f081ae7903272b98d74e17b062ea0 Mon Sep 17 00:00:00 2001 From: Aleksey Drobin <43707931+adrobi@users.noreply.github.com> Date: Fri, 30 Oct 2026 10:51:15 +0300 Subject: [PATCH 26/44] ui: difference detail pane with stacked chromatograms Co-Authored-By: Claude Sonnet 5.5 --- i18n.py | 9 ++ tests/test_construct_ui.py | 118 +++++++++++++++++ translations_en.py | 9 ++ ui/construct/detail_pane.py | 248 ++++++++++++++++++++++++++++++++++++ 4 files changed, 384 insertions(+) create mode 100644 ui/construct/detail_pane.py diff --git a/i18n.py b/i18n.py index 153ee40..4d10ed8 100644 --- a/i18n.py +++ b/i18n.py @@ -191,6 +191,15 @@ "matrix.legend.outside": "вне региона", "matrix.empty": "Нет клонов для показа", "matrix.hint": "Колёсико — масштаб, перетаскивание — сдвиг, Shift+протяжка по референсу — задать регион", + "detail.col.pos": "Позиция", + "detail.col.change": "Реф.→чтение", + "detail.col.effect": "Эффект", + "detail.col.support": "За / против", + "detail.col.status": "Статус", + "effect.synonymous": "синонимичная", + "effect.frameshift": "сдвиг рамки", + "effect.inframe_ins": "вставка в рамке", + "effect.inframe_del": "делеция в рамке", } _lang = "ru" diff --git a/tests/test_construct_ui.py b/tests/test_construct_ui.py index 3239595..4148808 100644 --- a/tests/test_construct_ui.py +++ b/tests/test_construct_ui.py @@ -8,6 +8,7 @@ from __future__ import annotations import os +from pathlib import Path os.environ.setdefault("QT_QPA_PLATFORM", "offscreen") @@ -405,3 +406,120 @@ def test_twelve_rows_fit_in_600_px(qapp, construct): m.resize(900, 600) assert m.row_rect("clone_12").bottom() < 600 assert m.hit_test(m.mark_point("clone_2", 100)) == ("clone_2", 100) + + +# ------------------------------------------------------------------ detail pane + + +@pytest.fixture(scope="module") +def pane_report(construct, tmp_path_factory): + """ACHLO006-09: F (+) and R (-) with a substitution at P in F's session.""" + folder = tmp_path_factory.mktemp("pane") + i = _f_index(construct, P) + chrom = real_read(F_NAME) + base = "C" if chrom.seq[i] != "C" else "G" + chrom = with_secondary_peak(chrom, i, base, 4.0) + edited = EditableRead(chrom) + edited.set_base(i, base) + f_sub = write_read(edited.current(), folder, F_NAME) + out = verify_all(construct, REGION, Grouping([ReadRef(f_sub, "c1", "F"), ReadRef(R, "c1", "R")])) + report = out[0] + assert [r.alignment.strand for r in report.reads] == ["+", "-"] + assert [d.ref_pos for d in report.region_differences] == [P] + return report + + +def _pane(qapp, construct, report): + from ui.construct.detail_pane import DetailPane + + pane = DetailPane() + pane.resize(1000, 500) + pane.show_clone(report, construct) + return pane + + +def test_displayed_index_converts_once_for_both_strands(): + from chrom_core.align import ReadAlignment + from ui.construct.detail_pane import displayed_index + + def al(strand, mapping): + return ReadAlignment(strand=strand, score=0, ref_start=0, ref_end=10, read_start=0, read_end=10, + ref_to_read=mapping, differences=[], identity=1.0, alternatives=1, + oriented_read="", blocks=[], ref_length=100) + + plus, minus = al("+", {5: 3, 6: 4}), al("-", {5: 3, 6: 4}) + assert displayed_index(plus, 5, 10) == 3 + assert displayed_index(minus, 5, 10) == 10 - 1 - 3 + assert displayed_index(minus, 50, 10) is None # not covered + # a deleted position falls back to the nearest mapped neighbour + gap = al("+", {5: 3, 7: 4}) + assert displayed_index(gap, 6, 10) in (3, 4) + + +def test_pane_one_chromatogram_per_aligned_read(qapp, construct, pane_report): + pane = _pane(qapp, construct, pane_report) + assert len(pane.views()) == 2 + assert pane.table.rowCount() == len(pane_report.differences) + + +def test_pane_centres_every_read_on_the_position(qapp, construct, pane_report): + pane = _pane(qapp, construct, pane_report) + pane.show_position(P) + for result, view in zip(pane_report.reads, pane.views()): + n = len(view.chrom.seq) + idx = result.alignment.ref_to_read[P] + want = idx if result.alignment.strand == "+" else n - 1 - idx + assert view.highlights == [(want, want + 1)] + centre = view.offset + view.width() / view.zoom / 2 + assert abs(centre - view.chrom.peak_indices[want]) <= 1.0 + letters, mapping = view.reference + assert mapping[P] == want + assert len({v.zoom for v in pane.views()}) == 1 # shared scale + + +def test_pane_reference_strip_shows_neighbourhood(qapp, construct, pane_report): + pane = _pane(qapp, construct, pane_report) + pane.show_position(P) + text = pane.reference_text() + assert construct.seq[P - 10:P] in text and construct.seq[P + 1:P + 11] in text + assert f"[{construct.seq[P]}]" in text + + +def test_pane_table_row_selection_shows_position(qapp, construct, pane_report): + pane = _pane(qapp, construct, pane_report) + seen = [] + orig = pane.show_position + pane.show_position = lambda p: (seen.append(p), orig(p)) + pane.table.selectRow(0) + assert seen[-1] == P == pane_report.differences[0].ref_pos + assert pane.table.item(0, 0).text() == str(P + 1) + assert "→" in pane.table.item(0, 1).text() + + +def test_pane_double_click_opens_read(qapp, construct, pane_report): + pane = _pane(qapp, construct, pane_report) + opened = [] + pane.open_read.connect(opened.append) + view = pane.views()[1] + _send_mouse(view, QEvent.Type.MouseButtonDblClick, QPoint(20, 20), + Qt.MouseButton.LeftButton, Qt.MouseButton.LeftButton) + assert opened == [pane_report.reads[1].ref.path] + + +def test_pane_effect_labels_translated(qapp, construct, pane_report): + from dataclasses import replace + from i18n import tr + + d = pane_report.differences[0] + report = replace(pane_report, differences=(replace(d, effect="frameshift"), replace(d, effect="D45N"))) + pane = _pane(qapp, construct, report) + assert pane.table.item(0, 2).text() == tr("effect.frameshift") + assert pane.table.item(1, 2).text() == "D45N" + + +def test_pane_renders_png(qapp, construct, pane_report): + pane = _pane(qapp, construct, pane_report) + pane.show_position(P) + out = Path(__file__).resolve().parents[1] / ".superpowers/sdd/2026-10-25-clone-verification/task-15-light.png" + if out.parent.is_dir(): + assert pane.grab().save(str(out)) diff --git a/translations_en.py b/translations_en.py index 1d5b226..273bb1d 100644 --- a/translations_en.py +++ b/translations_en.py @@ -184,4 +184,13 @@ "matrix.legend.outside": "outside region", "matrix.empty": "No clones to show", "matrix.hint": "Wheel: zoom, drag: pan, Shift+drag on the reference: set the region", + "detail.col.pos": "Position", + "detail.col.change": "Ref→read", + "detail.col.effect": "Effect", + "detail.col.support": "For / against", + "detail.col.status": "Status", + "effect.synonymous": "synonymous", + "effect.frameshift": "frameshift", + "effect.inframe_ins": "in-frame insertion", + "effect.inframe_del": "in-frame deletion", } diff --git a/ui/construct/detail_pane.py b/ui/construct/detail_pane.py new file mode 100644 index 0000000..e27318e --- /dev/null +++ b/ui/construct/detail_pane.py @@ -0,0 +1,248 @@ +"""Difference detail: every read of a clone centred on one reference position, +plus the clone's differences table, so the user can judge an error by eye.""" + +from __future__ import annotations + +from pathlib import Path + +from PySide6.QtCore import QEvent, Qt, Signal +from PySide6.QtGui import QFont +from PySide6.QtWidgets import ( + QAbstractItemView, QLabel, QScrollArea, QSplitter, QTableWidget, QTableWidgetItem, + QVBoxLayout, QWidget, +) + +from chrom_core.align import ReadAlignment +from chrom_core.clones import CloneReport, load_read +from chrom_core.reference import Construct +from i18n import tr +from ui import status +from ui.chrom_view import ChromatogramWidget +from ui.read_view.analysis_dock import reference_overlay +from ui.tables import configure_table, paint_status, repaint_statuses +from ui.theme import theme as palette + +CONTEXT = 10 # reference bases shown on each side of the position +VIEW_HEIGHT = 190 # compact height of one chromatogram +ROW_STATUS = {"confirmed": "errors", "disputed": "incomplete", "low_quality": "no_data"} +STATUS_KEY = {"confirmed": "matrix.legend.confirmed", "disputed": "matrix.legend.disputed", + "low_quality": "matrix.legend.low_quality"} +EFFECT_CODES = ("synonymous", "frameshift", "inframe_ins", "inframe_del") + + +def displayed_index(alignment: ReadAlignment, ref_pos: int, read_length: int) -> int | None: + """Index in the *displayed* read of the base aligned to ``ref_pos``. + + ``ref_to_read`` indexes the aligned orientation (the reverse complement on + '-'), so the displayed index is ``n-1-idx`` there. A position deleted in the + read falls back to the nearest mapped neighbour; ``None`` when not covered. + """ + if not alignment.covers(ref_pos): + return None + mapping, length = alignment.ref_to_read, alignment.ref_length + idx = None + for step in range(len(mapping) + (length or 0) + 1): + for pos in ((ref_pos + step, ref_pos - step) if step else (ref_pos,)): + if length: + pos %= length + if pos in mapping: + idx = mapping[pos] + break + if idx is not None: + break + if idx is None: + return None + return idx if alignment.strand == "+" else read_length - 1 - idx + + +class DetailPane(QWidget): + open_read = Signal(Path) + + def __init__(self, parent: QWidget | None = None) -> None: + super().__init__(parent) + self._report: CloneReport | None = None + self._construct: Construct | None = None + self._views: list[ChromatogramWidget] = [] + self._results: list = [] + self._paths: dict[ChromatogramWidget, Path] = {} + self._ref_pos: int | None = None + self._zoom: float | None = None + self._syncing = False + self._theme_name = status.current_theme() + + self._ref_label = QLabel() + mono = QFont("Consolas") + mono.setStyleHint(QFont.StyleHint.Monospace) + self._ref_label.setFont(mono) + self._ref_label.setTextInteractionFlags(Qt.TextInteractionFlag.TextSelectableByMouse) + + self._stack = QWidget() + self._stack_layout = QVBoxLayout(self._stack) + self._stack_layout.setContentsMargins(0, 0, 0, 0) + self._stack_layout.setSpacing(2) + self._stack_layout.addStretch(1) + scroll = QScrollArea() + scroll.setWidgetResizable(True) + scroll.setWidget(self._stack) + + left = QWidget() + left_layout = QVBoxLayout(left) + left_layout.setContentsMargins(0, 0, 0, 0) + left_layout.addWidget(self._ref_label) + left_layout.addWidget(scroll, 1) + + self.table = QTableWidget(0, 5) + self.table.setHorizontalHeaderLabels([ + tr("detail.col.pos"), tr("detail.col.change"), tr("detail.col.effect"), + tr("detail.col.support"), tr("detail.col.status"), + ]) + configure_table(self.table, stretch_column=2) + self.table.setEditTriggers(QAbstractItemView.EditTrigger.NoEditTriggers) + self.table.setSelectionBehavior(QAbstractItemView.SelectionBehavior.SelectRows) + self.table.setSelectionMode(QAbstractItemView.SelectionMode.SingleSelection) + self.table.itemSelectionChanged.connect(self._row_selected) + + splitter = QSplitter(Qt.Orientation.Horizontal) + splitter.addWidget(left) + splitter.addWidget(self.table) + splitter.setStretchFactor(0, 3) + splitter.setStretchFactor(1, 2) + layout = QVBoxLayout(self) + layout.setContentsMargins(0, 0, 0, 0) + layout.addWidget(splitter) + + # ---------------------------------------------------------------- API + def views(self) -> list[ChromatogramWidget]: + return list(self._views) + + def reference_text(self) -> str: + return self._ref_label.text() + + def set_theme(self, name: str) -> None: + self._theme_name = name + for view in self._views: + view.set_theme(palette(name)) + repaint_statuses(self.table) + + def show_clone(self, report: CloneReport, construct: Construct) -> None: + self._report, self._construct = report, construct + self._ref_pos, self._zoom = None, None + self._ref_label.clear() + for view in self._views: + view.hide() + view.deleteLater() + self._views, self._results, self._paths = [], [], {} + for result in report.reads: + if result.alignment is None: + continue + try: + chrom = load_read(result.ref.path) + except Exception: # unreadable file: nothing to draw for this read + continue + view = ChromatogramWidget() + view.setMinimumSize(0, VIEW_HEIGHT) + view.setMaximumHeight(VIEW_HEIGHT) + view.set_theme(palette(self._theme_name)) + view.set_chromatogram(chrom) + letters, mapping = reference_overlay(result.alignment, construct.seq, len(chrom.seq)) + view.set_reference(letters, mapping) + view.setToolTip(f"{result.ref.primer} · {result.ref.path.name} ({result.alignment.strand})") + view.installEventFilter(self) + view.view_changed.connect(lambda v=view: self._view_changed(v)) + self._paths[view] = result.ref.path + self._views.append(view) + self._results.append(result) + self._stack_layout.insertWidget(self._stack_layout.count() - 1, view) + self._fill_table(report) + + def show_position(self, ref_pos: int) -> None: + if self._report is None or self._construct is None: + return + self._ref_pos = ref_pos + self._zoom = None + self._select_row(ref_pos) + self._ref_label.setText(self._reference_context(ref_pos)) + for view, result in zip(self._views, self._results): + exact = ref_pos in result.alignment.ref_to_read + idx = displayed_index(result.alignment, ref_pos, len(view.chrom.seq)) + view.set_highlights([(idx, idx + 1)] if exact and idx is not None else []) + self._apply_view() + + # ----------------------------------------------------------- internals + def _reference_context(self, ref_pos: int) -> str: + seq, n = self._construct.seq, len(self._construct.seq) + + def around(a: int, b: int) -> str: + if self._construct.circular: + return "".join(seq[i % n] for i in range(a, b)) + return seq[max(0, a):max(0, b)] + + return (f"{ref_pos + 1}: {around(ref_pos - CONTEXT, ref_pos)}[{seq[ref_pos % n]}]" + f"{around(ref_pos + 1, ref_pos + CONTEXT + 1)}") + + def _apply_view(self) -> None: + if self._ref_pos is None or not self._views: + return + if self._zoom is None: + spacing = self._views[0]._avg_spacing + width = max(self._views[0].width(), 200) + self._zoom = width / ((2 * CONTEXT + 1) * spacing) + self._syncing = True + try: + for view, result in zip(self._views, self._results): + view.zoom = self._zoom + idx = displayed_index(result.alignment, self._ref_pos, len(view.chrom.seq)) + if idx is not None: + view.center_on_point(view.chrom.peak_indices[idx]) + view.update() + finally: + self._syncing = False + + def _view_changed(self, source: ChromatogramWidget) -> None: + """A zoom change in one view is applied to all (shared scale).""" + if self._syncing or self._ref_pos is None or source.zoom == self._zoom: + return + self._zoom = source.zoom + self._apply_view() + + def resizeEvent(self, event) -> None: # noqa: N802 + super().resizeEvent(event) + if self._ref_pos is not None: + self._zoom = None + self._apply_view() + + def eventFilter(self, obj, event) -> bool: # noqa: N802 + if event.type() == QEvent.Type.MouseButtonDblClick and obj in self._paths: + self.open_read.emit(self._paths[obj]) + return True + return super().eventFilter(obj, event) + + def _fill_table(self, report: CloneReport) -> None: + self.table.blockSignals(True) + self.table.setRowCount(len(report.differences)) + for row, d in enumerate(report.differences): + effect = tr(f"effect.{d.effect}") if d.effect in EFFECT_CODES else d.effect + cells = [str(d.ref_pos + 1), f"{d.ref_base or '-'}→{d.read_base or '-'}", effect, + f"{d.support} / {d.against}", tr(STATUS_KEY[d.status])] + for col, text in enumerate(cells): + item = QTableWidgetItem(text) + if col == 0: + item.setData(Qt.ItemDataRole.UserRole, d.ref_pos) + if col == 4: + paint_status(item, ROW_STATUS[d.status]) + self.table.setItem(row, col, item) + self.table.blockSignals(False) + + def _row_selected(self) -> None: + rows = self.table.selectionModel().selectedRows() + if rows: + self.show_position(self.table.item(rows[0].row(), 0).data(Qt.ItemDataRole.UserRole)) + + def _select_row(self, ref_pos: int) -> None: + self.table.blockSignals(True) + self.table.clearSelection() + for row in range(self.table.rowCount()): + if self.table.item(row, 0).data(Qt.ItemDataRole.UserRole) == ref_pos: + self.table.selectRow(row) + break + self.table.blockSignals(False) From 03e02825ba730f4d2323901f28ac39aea1deaa25 Mon Sep 17 00:00:00 2001 From: Aleksey Drobin <43707931+adrobi@users.noreply.github.com> Date: Fri, 30 Oct 2026 10:55:13 +0300 Subject: [PATCH 27/44] ui: detail pane review fixes: disputed colour, dimmed out-of-region rows, shared zoom, failed/ambiguous reads Co-Authored-By: Claude Sonnet 5.5 --- i18n.py | 3 + tests/test_construct_ui.py | 93 +++++++++++++++++++++++-- translations_en.py | 3 + ui/construct/detail_pane.py | 131 ++++++++++++++++++++++++++++-------- 4 files changed, 197 insertions(+), 33 deletions(-) diff --git a/i18n.py b/i18n.py index 4d10ed8..0abcf72 100644 --- a/i18n.py +++ b/i18n.py @@ -200,6 +200,9 @@ "effect.frameshift": "сдвиг рамки", "effect.inframe_ins": "вставка в рамке", "effect.inframe_del": "делеция в рамке", + "detail.err.no_alignment": "нет выравнивания", + "detail.ambiguous": "неоднозначно — не учитывается в вердикте", + "detail.uncovered": "позиция не покрыта", } _lang = "ru" diff --git a/tests/test_construct_ui.py b/tests/test_construct_ui.py index 4148808..b7ab93e 100644 --- a/tests/test_construct_ui.py +++ b/tests/test_construct_ui.py @@ -453,7 +453,7 @@ def al(strand, mapping): assert displayed_index(minus, 50, 10) is None # not covered # a deleted position falls back to the nearest mapped neighbour gap = al("+", {5: 3, 7: 4}) - assert displayed_index(gap, 6, 10) in (3, 4) + assert displayed_index(gap, 6, 10) == 4 def test_pane_one_chromatogram_per_aligned_read(qapp, construct, pane_report): @@ -517,9 +517,94 @@ def test_pane_effect_labels_translated(qapp, construct, pane_report): assert pane.table.item(1, 2).text() == "D45N" +def test_pane_status_cells_keep_one_colour_per_meaning(qapp, construct, pane_report): + from dataclasses import replace + from ui import status + + d = pane_report.differences[0] + diffs = tuple(replace(d, status=s) for s in ("confirmed", "disputed", "low_quality")) + pane = _pane(qapp, construct, replace(pane_report, differences=diffs)) + bg = [pane.table.item(r, 4).background().color() for r in range(3)] + red = status.status_color("errors", "light") + assert bg[0] == red + assert bg[1] != red and bg[1].red() > bg[1].green() and bg[1].red() > bg[1].blue() # weaker red tint + assert bg[1] != status.status_color("incomplete", "light") + assert bg[2] == status.status_color("no_data", "light") + pane.set_theme("dark") + assert pane.table.item(0, 4).background().color() == status.status_color("errors", "dark") + + +def test_pane_dims_rows_outside_region(qapp, construct, pane_report): + from dataclasses import replace + from i18n import tr + + d = pane_report.differences[0] + pane = _pane(qapp, construct, replace(pane_report, differences=(d, replace(d, in_region=False)))) + inside, outside = pane.table.item(0, 0), pane.table.item(1, 0) + assert not inside.font().italic() and inside.toolTip() == "" + assert outside.font().italic() and outside.toolTip() == tr("matrix.legend.outside") + assert outside.foreground().color() != inside.foreground().color() + + +def test_pane_zoom_is_shared_and_kept(qapp, construct, pane_report): + pane = _pane(qapp, construct, pane_report) + views = pane.views() + assert len({v.zoom for v in views}) == 1 + views[0].zoom_in() # before any position is shown + assert views[1].zoom == views[0].zoom + pane.show_position(P) + chosen = views[0].zoom + assert views[1].zoom == chosen # show_position keeps the user's zoom + views[0].zoom_in() + assert views[1].zoom == views[0].zoom > chosen + for result, view in zip(pane_report.reads, views): + n = len(view.chrom.seq) + idx = result.alignment.ref_to_read[P] + want = idx if result.alignment.strand == "+" else n - 1 - idx + centre = view.offset + view.width() / view.zoom / 2 + assert abs(centre - view.chrom.peak_indices[want]) <= 1.0 + pane.resize(1100, 500) + assert views[0].zoom == views[1].zoom and views[0].zoom != chosen + + +def test_pane_failed_and_ambiguous_reads_are_shown(qapp, construct, pane_report): + from dataclasses import replace + from PySide6.QtWidgets import QLabel + from chrom_core.clones import ReadResult + from i18n import tr + + f, r = pane_report.reads + bad = ReadResult(ReadRef(Path("bad_read.ab1"), "c1", "F"), None, error="no_alignment") + report = replace(pane_report, reads=(f, bad, replace(r, ambiguous=True))) + pane = _pane(qapp, construct, report) + assert len(pane.views()) == 2 + texts = [lab.text() for lab in pane.findChildren(QLabel)] + assert any("bad_read.ab1" in s and tr("detail.err.no_alignment") in s for s in texts) + assert tr("detail.ambiguous") in pane.views()[1].toolTip() + assert tr("detail.ambiguous") not in pane.views()[0].toolTip() + gone = ReadResult(ReadRef(Path("missing.ab1"), "c1", "F"), r.alignment) + pane = _pane(qapp, construct, replace(pane_report, reads=(f, gone))) + assert len(pane.views()) == 1 + assert any("missing.ab1" in lab.text() for lab in pane.findChildren(QLabel)) + + +def test_pane_dims_read_that_does_not_cover_position(qapp, construct, pane_report): + pane = _pane(qapp, construct, pane_report) + covers = pane_report.reads[1].alignment + outside = next(p for p in range(len(construct.seq)) if not covers.covers(p) + and pane_report.reads[0].alignment.covers(p)) + pane.show_position(outside) + assert pane.views()[1].graphicsEffect() is not None + assert pane.views()[1].highlights == [] + assert pane.views()[0].graphicsEffect() is None + pane.show_position(P) + assert pane.views()[1].graphicsEffect() is None + + def test_pane_renders_png(qapp, construct, pane_report): + target = os.environ.get("AB1KIT_DETAIL_PNG") + if not target: + pytest.skip("set AB1KIT_DETAIL_PNG to render the pane") pane = _pane(qapp, construct, pane_report) pane.show_position(P) - out = Path(__file__).resolve().parents[1] / ".superpowers/sdd/2026-10-25-clone-verification/task-15-light.png" - if out.parent.is_dir(): - assert pane.grab().save(str(out)) + assert pane.grab().save(target) diff --git a/translations_en.py b/translations_en.py index 273bb1d..21f3320 100644 --- a/translations_en.py +++ b/translations_en.py @@ -193,4 +193,7 @@ "effect.frameshift": "frameshift", "effect.inframe_ins": "in-frame insertion", "effect.inframe_del": "in-frame deletion", + "detail.err.no_alignment": "no alignment", + "detail.ambiguous": "ambiguous — not counted in the verdict", + "detail.uncovered": "position not covered", } diff --git a/ui/construct/detail_pane.py b/ui/construct/detail_pane.py index e27318e..63e298f 100644 --- a/ui/construct/detail_pane.py +++ b/ui/construct/detail_pane.py @@ -3,12 +3,13 @@ from __future__ import annotations +import struct from pathlib import Path from PySide6.QtCore import QEvent, Qt, Signal -from PySide6.QtGui import QFont +from PySide6.QtGui import QColor, QFont from PySide6.QtWidgets import ( - QAbstractItemView, QLabel, QScrollArea, QSplitter, QTableWidget, QTableWidgetItem, + QAbstractItemView, QGraphicsOpacityEffect, QLabel, QScrollArea, QSplitter, QTableWidget, QTableWidgetItem, QVBoxLayout, QWidget, ) @@ -17,16 +18,19 @@ from chrom_core.reference import Construct from i18n import tr from ui import status -from ui.chrom_view import ChromatogramWidget +from ui.chrom_view import MAX_ZOOM, MIN_ZOOM, ChromatogramWidget from ui.read_view.analysis_dock import reference_overlay -from ui.tables import configure_table, paint_status, repaint_statuses +from ui.tables import STATUS_ROLE, configure_table from ui.theme import theme as palette CONTEXT = 10 # reference bases shown on each side of the position VIEW_HEIGHT = 190 # compact height of one chromatogram -ROW_STATUS = {"confirmed": "errors", "disputed": "incomplete", "low_quality": "no_data"} +ROW_STATUS = {"confirmed": "errors", "disputed": "errors", "low_quality": "no_data"} STATUS_KEY = {"confirmed": "matrix.legend.confirmed", "disputed": "matrix.legend.disputed", "low_quality": "matrix.legend.low_quality"} +READ_ERRORS = (OSError, ValueError, KeyError, TypeError, struct.error) +DISPUTED_TINT = 0.35 # share of the errors red mixed into the background +UNCOVERED_OPACITY = 0.35 EFFECT_CODES = ("synonymous", "frameshift", "inframe_ins", "inframe_del") @@ -64,9 +68,12 @@ def __init__(self, parent: QWidget | None = None) -> None: self._construct: Construct | None = None self._views: list[ChromatogramWidget] = [] self._results: list = [] + self._rows: list[QWidget] = [] # one container per read (view or placeholder) + self._notes: list[QLabel] = [] # 'position not covered' label per view self._paths: dict[ChromatogramWidget, Path] = {} self._ref_pos: int | None = None self._zoom: float | None = None + self._zoom_chosen = False # the user zoomed: keep it across resizes self._syncing = False self._theme_name = status.current_theme() @@ -122,22 +129,26 @@ def set_theme(self, name: str) -> None: self._theme_name = name for view in self._views: view.set_theme(palette(name)) - repaint_statuses(self.table) + self._paint_table() def show_clone(self, report: CloneReport, construct: Construct) -> None: self._report, self._construct = report, construct - self._ref_pos, self._zoom = None, None + self._ref_pos, self._zoom, self._zoom_chosen = None, None, False self._ref_label.clear() - for view in self._views: - view.hide() - view.deleteLater() - self._views, self._results, self._paths = [], [], {} + for row in self._rows: + row.hide() + row.deleteLater() + self._views, self._results, self._paths, self._rows, self._notes = [], [], {}, [], [] for result in report.reads: + name = result.ref.path.name if result.alignment is None: + error = tr("detail.err.no_alignment") if result.error == "no_alignment" else result.error + self._add_row(QLabel(f"{result.ref.primer} · {name}: {error}")) continue try: chrom = load_read(result.ref.path) - except Exception: # unreadable file: nothing to draw for this read + except READ_ERRORS as exc: + self._add_row(QLabel(f"{result.ref.primer} · {name}: {exc}")) continue view = ChromatogramWidget() view.setMinimumSize(0, VIEW_HEIGHT) @@ -146,26 +157,49 @@ def show_clone(self, report: CloneReport, construct: Construct) -> None: view.set_chromatogram(chrom) letters, mapping = reference_overlay(result.alignment, construct.seq, len(chrom.seq)) view.set_reference(letters, mapping) - view.setToolTip(f"{result.ref.primer} · {result.ref.path.name} ({result.alignment.strand})") + title = f"{result.ref.primer} · {name} ({result.alignment.strand})" + if result.ambiguous: + title += " — " + tr("detail.ambiguous") + view.setToolTip(title) view.installEventFilter(self) view.view_changed.connect(lambda v=view: self._view_changed(v)) + note = QLabel(tr("detail.uncovered")) + note.hide() + container = QWidget() + box = QVBoxLayout(container) + box.setContentsMargins(0, 0, 0, 0) + box.setSpacing(0) + box.addWidget(QLabel(title)) + box.addWidget(note) + box.addWidget(view) self._paths[view] = result.ref.path self._views.append(view) self._results.append(result) - self._stack_layout.insertWidget(self._stack_layout.count() - 1, view) + self._notes.append(note) + self._add_row(container) + self._reset_default_zoom() self._fill_table(report) + def _add_row(self, widget: QWidget) -> None: + self._rows.append(widget) + self._stack_layout.insertWidget(self._stack_layout.count() - 1, widget) + def show_position(self, ref_pos: int) -> None: if self._report is None or self._construct is None: return self._ref_pos = ref_pos - self._zoom = None self._select_row(ref_pos) self._ref_label.setText(self._reference_context(ref_pos)) - for view, result in zip(self._views, self._results): + for view, result, note in zip(self._views, self._results, self._notes): exact = ref_pos in result.alignment.ref_to_read idx = displayed_index(result.alignment, ref_pos, len(view.chrom.seq)) view.set_highlights([(idx, idx + 1)] if exact and idx is not None else []) + note.setVisible(idx is None) + effect = None + if idx is None: + effect = QGraphicsOpacityEffect(view) + effect.setOpacity(UNCOVERED_OPACITY) + view.setGraphicsEffect(effect) self._apply_view() # ----------------------------------------------------------- internals @@ -180,35 +214,42 @@ def around(a: int, b: int) -> str: return (f"{ref_pos + 1}: {around(ref_pos - CONTEXT, ref_pos)}[{seq[ref_pos % n]}]" f"{around(ref_pos + 1, ref_pos + CONTEXT + 1)}") - def _apply_view(self) -> None: - if self._ref_pos is None or not self._views: + def _reset_default_zoom(self) -> None: + """Default scale (about 21 bases visible), unless the user chose one.""" + if not self._views or self._zoom_chosen: return + spacing = self._views[0]._avg_spacing + width = max(self._views[0].width(), 200) + self._zoom = min(MAX_ZOOM, max(MIN_ZOOM, width / ((2 * CONTEXT + 1) * spacing))) + self._apply_view() + + def _apply_view(self) -> None: + """Give every view the shared zoom and centre it on the position.""" if self._zoom is None: - spacing = self._views[0]._avg_spacing - width = max(self._views[0].width(), 200) - self._zoom = width / ((2 * CONTEXT + 1) * spacing) + return self._syncing = True try: for view, result in zip(self._views, self._results): view.zoom = self._zoom - idx = displayed_index(result.alignment, self._ref_pos, len(view.chrom.seq)) - if idx is not None: - view.center_on_point(view.chrom.peak_indices[idx]) + if self._ref_pos is not None: + idx = displayed_index(result.alignment, self._ref_pos, len(view.chrom.seq)) + if idx is not None: + view.center_on_point(view.chrom.peak_indices[idx]) view.update() finally: self._syncing = False def _view_changed(self, source: ChromatogramWidget) -> None: """A zoom change in one view is applied to all (shared scale).""" - if self._syncing or self._ref_pos is None or source.zoom == self._zoom: + if self._syncing or source.zoom == self._zoom: return - self._zoom = source.zoom + self._zoom, self._zoom_chosen = source.zoom, True self._apply_view() def resizeEvent(self, event) -> None: # noqa: N802 super().resizeEvent(event) - if self._ref_pos is not None: - self._zoom = None + self._reset_default_zoom() + if self._zoom_chosen: self._apply_view() def eventFilter(self, obj, event) -> bool: # noqa: N802 @@ -229,9 +270,41 @@ def _fill_table(self, report: CloneReport) -> None: if col == 0: item.setData(Qt.ItemDataRole.UserRole, d.ref_pos) if col == 4: - paint_status(item, ROW_STATUS[d.status]) + item.setData(STATUS_ROLE, d.status) + if not d.in_region: + item.setToolTip(tr("matrix.legend.outside")) + font = item.font() + font.setItalic(True) + item.setFont(font) self.table.setItem(row, col, item) self.table.blockSignals(False) + self._paint_table() + + def _paint_table(self) -> None: + """Status cells: confirmed solid red, disputed a weak red tint, low quality + grey (shared palette); rows outside the region dimmed. Current theme.""" + theme, colours = self._theme_name, palette(self._theme_name) + base = QColor(colours["bg"]) + red = status.status_color("errors", theme) + + def mix(a: int, b: int) -> int: + return round(a * DISPUTED_TINT + b * (1 - DISPUTED_TINT)) + + for row, d in enumerate(self._report.differences if self._report else ()): + for col in range(self.table.columnCount()): + item = self.table.item(row, col) + if item is None: + continue + if col == 4 and d.status == "disputed": + item.setBackground(QColor(mix(red.red(), base.red()), mix(red.green(), base.green()), + mix(red.blue(), base.blue()))) + item.setForeground(QColor(colours["text"])) + elif col == 4: + verdict = ROW_STATUS[d.status] + item.setBackground(status.status_color(verdict, theme)) + item.setForeground(status.status_text_color(verdict, theme)) + elif not d.in_region: + item.setForeground(QColor(colours["dim"])) def _row_selected(self) -> None: rows = self.table.selectionModel().selectedRows() From 94be6c3c07d01361e8c73f9d67d0342cf3f07652 Mon Sep 17 00:00:00 2001 From: Aleksey Drobin <43707931+adrobi@users.noreply.github.com> Date: Fri, 30 Oct 2026 10:58:00 +0300 Subject: [PATCH 28/44] ui: detail pane survives corrupt ab1 (AssertionError/IndexError) Co-Authored-By: Claude Sonnet 5.5 --- tests/test_construct_ui.py | 23 +++++++++++++++++++++++ ui/construct/detail_pane.py | 2 +- 2 files changed, 24 insertions(+), 1 deletion(-) diff --git a/tests/test_construct_ui.py b/tests/test_construct_ui.py index b7ab93e..f20ad72 100644 --- a/tests/test_construct_ui.py +++ b/tests/test_construct_ui.py @@ -608,3 +608,26 @@ def test_pane_renders_png(qapp, construct, pane_report): pane = _pane(qapp, construct, pane_report) pane.show_position(P) assert pane.grab().save(target) + + +def test_pane_survives_corrupt_ab1(qapp, construct, pane_report, tmp_path): + from dataclasses import replace + from PySide6.QtWidgets import QLabel + from chrom_core.abif import read_ab1 + from chrom_core.clones import ReadResult + + raw = bytearray((Path(__file__).resolve().parents[1] / "examples" / "310.ab1").read_bytes()) + directory = int.from_bytes(raw[26:30], "big") + raw[directory + 12] ^= 0xFF # deterministic: BioPython's ABIF parser asserts + corrupt = tmp_path / "corrupt.ab1" + corrupt.write_bytes(raw) + with pytest.raises(AssertionError): + read_ab1(corrupt) + + f, r = pane_report.reads + broken = ReadResult(ReadRef(corrupt, "c1", "F"), f.alignment) + pane = _pane(qapp, construct, replace(pane_report, reads=(broken, r))) + assert len(pane.views()) == 1 + assert any("corrupt.ab1" in lab.text() for lab in pane.findChildren(QLabel)) + pane.show_position(P) + assert pane.views()[0].highlights diff --git a/ui/construct/detail_pane.py b/ui/construct/detail_pane.py index 63e298f..9809fcf 100644 --- a/ui/construct/detail_pane.py +++ b/ui/construct/detail_pane.py @@ -28,7 +28,7 @@ ROW_STATUS = {"confirmed": "errors", "disputed": "errors", "low_quality": "no_data"} STATUS_KEY = {"confirmed": "matrix.legend.confirmed", "disputed": "matrix.legend.disputed", "low_quality": "matrix.legend.low_quality"} -READ_ERRORS = (OSError, ValueError, KeyError, TypeError, struct.error) +READ_ERRORS = (OSError, ValueError, KeyError, TypeError, IndexError, AssertionError, struct.error) # AssertionError: BioPython ABIF parser on corrupt files DISPUTED_TINT = 0.35 # share of the errors red mixed into the background UNCOVERED_OPACITY = 0.35 EFFECT_CODES = ("synonymous", "frameshift", "inframe_ins", "inframe_del") From eb9377ec880ce32fe545c8c3e2e48f070cce7671 Mon Sep 17 00:00:00 2001 From: Aleksey Drobin <43707931+adrobi@users.noreply.github.com> Date: Fri, 30 Oct 2026 16:20:01 +0300 Subject: [PATCH 29/44] ui: construct verification workspace with grouping and project files Co-Authored-By: Claude Opus 5.5 --- README.md | 1 + chrom_core/clones.py | 9 +- docs/screenshots/batch.png | Bin 94966 -> 102148 bytes docs/screenshots/construct.png | Bin 0 -> 112131 bytes docs/screenshots/viewer-dark.png | Bin 89017 -> 91638 bytes docs/screenshots/viewer.png | Bin 87681 -> 90395 bytes i18n.py | 54 ++++ scripts/render_preview.py | 67 +++++ tests/test_construct_ui.py | 298 +++++++++++++++++++ tests/test_smoke_gui.py | 85 ++++++ translations_en.py | 54 ++++ ui/construct/controls.py | 264 +++++++++++++++++ ui/construct/detail_pane.py | 5 + ui/construct/grouping_dialog.py | 161 +++++++++++ ui/construct/session_files.py | 41 +++ ui/construct/workspace.py | 479 +++++++++++++++++++++++++++++++ ui/icons/chevron-down.svg | 13 + ui/icons/chevron-up.svg | 13 + ui/main_window.py | 115 +++++++- ui/style.qss | 9 + ui/style_dark.qss | 9 + ui/theme.py | 28 +- 22 files changed, 1684 insertions(+), 21 deletions(-) create mode 100644 docs/screenshots/construct.png create mode 100644 ui/construct/controls.py create mode 100644 ui/construct/grouping_dialog.py create mode 100644 ui/construct/session_files.py create mode 100644 ui/construct/workspace.py create mode 100644 ui/icons/chevron-down.svg create mode 100644 ui/icons/chevron-up.svg diff --git a/README.md b/README.md index aa04b32..c789139 100644 --- a/README.md +++ b/README.md @@ -5,6 +5,7 @@ chromatograms (`.ab1` files) — a free, offline alternative to FinchTV / Chroma for everyday molecular biology lab work. English/Russian interface. ![viewer](docs/screenshots/viewer.png) +![construct check](docs/screenshots/construct.png) ## Features diff --git a/chrom_core/clones.py b/chrom_core/clones.py index 7002114..efb636b 100644 --- a/chrom_core/clones.py +++ b/chrom_core/clones.py @@ -224,7 +224,8 @@ def region_differences(self) -> tuple[CloneDifference, ...]: return tuple(d for d in self.differences if d.in_region) -def _check_region(region: Region | None, length: int, circular: bool) -> Region: +def check_region(region: Region | None, length: int, circular: bool) -> Region: + """``region`` normalised (``None`` -> whole construct); ``ValueError`` if invalid.""" if region is None: return (0, length) start, end = region @@ -239,7 +240,7 @@ def _check_region(region: Region | None, length: int, circular: bool) -> Region: def region_positions(region: Region | None, length: int) -> list[int]: """Construct positions of ``region`` in order (``None``: the whole construct).""" - start, end = _check_region(region, length, circular=True) + start, end = check_region(region, length, circular=True) if start < end: return list(range(start, end)) return list(range(start, length)) + list(range(end)) @@ -386,7 +387,7 @@ def verify_clone( (default: ``difference_effect``; ``None`` leaves it empty). """ L = len(construct.seq) - positions = region_positions(_check_region(region, L, construct.circular), L) + positions = region_positions(check_region(region, L, construct.circular), L) in_region = set(positions) ref = construct.seq.upper() @@ -471,7 +472,7 @@ def verify_all( polled before each one and, when true, raises ``concurrent.futures.CancelledError``. """ - _check_region(region, len(construct.seq), construct.circular) + check_region(region, len(construct.seq), construct.circular) groups = grouping.clones() reports = [] for done, reads in enumerate(groups.values(), start=1): diff --git a/docs/screenshots/batch.png b/docs/screenshots/batch.png index 74163acdbb17ff4e2c7eff3ccf056ddddc9d669b..c2c1cdf28cd30ab19f89dc43c980a2e1446a0a9a 100644 GIT binary patch literal 102148 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 z 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�PF-&r53$hw;m zwa(tJ_t2i8m5`B@@{SD|lrwx|`B?E~bZPEb+x{!GX1-?H_g#IKRlEILNLTaEcHb{hr`P0>Fta8)zv{dQ|w;LT1^%~fxp>%Uy-m&^r8i`}hVdYHUz3w^L>pe2_(fShe;b+X0hi`JKYHA{_pnvQ7JdXcJ zA$to21>cw$I-eSo&O=u?*w|M73y^~1B7!dsx&(GqzEr=BZ{IY5FbFsmvIM{qVK9MQ zys4p?Ja9T}4a_=j5Dg&03X6uX3P>;+@+P;D_r70I(&MDbk7vGzlU6_Bd6OAl87}6tm3pKz=93_`9iu!O#bJp(Kll0z z3soNZWtTWb_0>4;LY;8gsSVl9kPhOM{oy1}Ijdk7>yFkXsU|jR=Ec|K)8%q>Xrdqn z>{}?N3DaA`4T8-9IVj{-@^s|3ai;uvSIFOghdeF7xdWu60pu|328M>nsQ;9G9V}EU zf2|E?CQ@;SBw)VL%p>L9yK!s8-f+2isGfuD13nh2tD2{8LI@&_=1U5{h8SC9Qh6iQ1?-Jp{dOet$65RD+38z^%;8z^2d zPDYvK8mxb3k-%(bM5g5%C>c-z86O)%kTeK`c7tTApb}lY>BU@*(a^{$w?j?=Ojb7P z!GY&KK62nqf+dC11sM=|(hFAK(DLmAf?$>}%q%Rn-*PyldP@N967=lgyTJj8L5`Nf zG+Bk>^lc*pgM75@0sjn8IDt6$QsmZO$FL*CYOL6Drr_ZhHwCFhsf%_O2T5GzNFV;5 zjB*c{sVk9Vy%kY7|I@{qo>*$o{gWP#ro3i3>1t&|yRqq3TJN>|(Yg6j&Qd#)S-o@J z?qr54V~Jx|dQ}Q`eI+rQDtSScec|EnlPxuqi(CZuE4% z!Yj?UMsN#p1Oxw7w6$FXVIkk5{~f_MC`;tVkc~=1VOc?wzjRi55r7 z+~fmcdJ#$Ymv=xnC6K!A-hG9{q^fDpQ@GBk^s{1Mh$V>VdmILo&;>ve;#M;g6Mrg@ zwFGu2aQ}z=uFdD-7mC)h`^b=sfY`YmP@;uQWPdK*zyCWwIS`r2oM8uivxN9~J?;Af z(FQ7~wctPu)tD=D^d}lQx;=RUV{y_x6coZzUyh^_s(rPfv~FSdnU*k36X_(y(|3x* z*KU3};cH7L)M?APA^7P6=cfzu4zedz-i&9p0-gvP+!Fb1zqflcZ;{ew%ss(4JEA0S01hMNRHrK#=4vaApo(>Lt*gN`eEotC}a(apr8SX zPK*)kjM)0GDsT<2JPn*=#IVMbDMSm*!6?D%fajN;n_Io>FB2$Eg`D+0yaxJn2J!&( zG&TF-OatEIFNE(D=5~_b22&5D^I~uF`NaGPm$u zo!MwUHF>vxSYl;oS}F~Zcpba^BbXJGtgaxU0O^j9F$Wr#@DVJsDBq7ELP;Q*;nQ%= zi?==&- zYi#`R*S8PI*6iA~3priOzQPw|XF)kZ=eExg=S~U;fagthNiq?J5Xg86$TUF6H1bS3 z;3NQc`>V%XwiUtlHEi^0eOH$~b`<6bQ?Z-)fRF*ZeOD$cD0jK1Lr#ccLGj&}7t6Vt;{VCd`Zwun zfkzb_ty8|lBrQh(@T_+JEy*An_vdqs7ZDeFLRb*CN z`2Qzj7(RGUFrkKLdVBdRSt*B=7?-rC|00e3`=aooiLsMA|IHi|WPNp22COktV!<8% zs^qW{*U1uKVtUd%_Hn}!EE&)gaw@SAd>O>F{;&4VJS@lj{rfit5hi=GG)W=blxU(z z6pADj6-Aa-H3+TBOoe19-9#y=XpuxorD6ybTF6pbX0)heNl2ES*OmFse2?Gnd7k6@ z&vX3#dG0^vFm-p`*L{6HpL2Pi@AG|5ai~tUTfx2u1&ZIW{iNGn=iLvBnrm8mR*n9~ zQWM~b`GfZ7@t*q+%K=e#fkHk#nB;JL{8iUIF2nvNkSWQ@&8sls?LNP4Do?fZl_DKy zAqiOUBUetIyh`HDa^fx(d?77UVzSI^^KPkh^IZCNf-^zg?t zbL_DdGTIc|`i;?W#YQQp^(yk4SS%nq2~iM?mrHDc-^jV=-&+{vg8|vKYZv4pu?olb zB6N2W2cVN*zsY*tx`DE? z(-!8sC(fp}?sT2mrC~uq1BVY63Q2^{mT+p19oYRwqN}0V7|{|ZYy+lc9o_9GPE?XO z#0F;Ynz1KW&=G)CAmFl4&9e z$V$nQElAMOEa6LVeV)F9Z4JM9>LINJR|1+!T?lzKMULB@@HVEaoLQ1S3&^(8pCDCe z&k{H~!cY}fW}%MG2&Lkmb=UAqdY_< z!1!?v6Nmk*7j;%yT|e%g;dP>Y`mj>LqCu^kQIT#}dcEYktD=wzW5@o9@k@Me8nTBx zVOHlYxe-;>FD`Y8vDhP=c+5$>Rr#H*83#6-zNCtboM z3_A>&fH)1>5j-27Af95_=+R#=M-#6Dzccmc5E23d2maB}V6$$WTx9dBSKb(Z`Gvp1 z_GL;+9+gSNjg#`)!!yh3YHOd*bbQxTCfor1I@#G@m~>~2j-%&LSH8xw60tYBN+lvbB`^i5&*Rc{0vx^SlPXe44<$c00 zon99CHMjFqE<5LGuD3T^OQ=kOr>}I$GE95-s(S7ZKb(YdqP>@|f=&{fY2&6%^$iV@ za*SF85P8DaVj-<3>CbR{EC3*6SGYscYs*WHJdm&H3l9{v;k%}tD zm;lipdwp}|ZX1<+W^Z=}9XeFZ3iNgCuV=XUQeym|=aZh91n0QdPm^uwm+8?X&NzW| za)xbj4KDM5%#47*K&1bS;*H6(or_Nj4GDy;Ofn=|_md*~!NCdVQK-(qP7~j%6DM1L zNF^rcm|aXye{^p}%j|25GK)HC$A)(eFz}RbNuImX__~r@M}cd(*Ty@#6Zsa}5^m8$ z#Ck(Vjq~COUiFnjeF?vx!?X`n7$)lc+1xzoZr_s15FH5$&5t>-1;-8D~n!bBRNcx&> zP9P*?4zMR`6^u^q&rzw8bPPF_SUcJf8#KeMwU!4VXl+$gP=&3!yhUDB)kQdzTehIF z3;)#U9sw2gct{Beq&#r^kFE$ld>CYTTwO`l#Qoy{yb6TarnE&N-coJ>Z4haL1-bfD zR-)L%7*RXvX6w6m+ficU3L48Tjb7YMVPyrf6dr~~65z_BvlIm{(pazDHZeJN#4}ct zYS-J>uS0)a_sbP)59A@~SRjK1QXp>k8?;ra;O(49JyV4ay`9b?xdkx&{J)pAgvBJZ z1Y%x{46q^8Zs6ne?A<$3eVgK>N%|7Y9Ve%{gP{axWYE;-Jw{fR!rCn8O%n~58;_TE zh6@K2?o=AHnBa<~Hi*zLE18mTg>9UDRd-^h-W)ZM7RWn~9;FjUL1+`mWsv)biAo?B zQnO`^KsaA1p_ z1!1fRJ$eGRB3w>LZ9`Tp*L(Bv?E3^gt9%b;BzF8JGec?o_=OV7*^Z6(kpYj5i(53y z33tl}OMzQJz|rgLGc*rM9MKwZa_P}}Ziukn#3foOnPsD$uK3B54A|qqOO;f@b<*Qn zPbCMQ$yy#jN)#3rW}alQY}q4^0v=DSBX<;`+yDtneby}dqlcIRb0#z_>=BQPaC$0| zhtw4>@d@q@;M7zj8|jVG(z=S2TCQmz*d#G{Pfb7!y_X(f`gUXuXi^4TMOeG*%d#jQ;5))IEkj2Syk$!c? zAvSX&51B;eC|y$XiEs)FAva|B8+Fd8Qxq|^F#Kc$vn@)^0l}=`hqAS%_gD&ZH`Zjm$HX&%f_R{%sY%JVolKK2 zM4|5qxGy0{X$Lj#?OA3yqDN+?~4eU~nvqMV6EVNxaL%iY6cxW#ncKAiPO*d z6@mah8|c)VkxGyNqCd}7tWf~iG?&@5BHp;w;zR444Y3#G%o<q$*4C|nu0>PcP+I%D@{HQc6`BpdM&I<`O|+VOg93EbJ7^EA2wF@K0O* zWKuBIEvDYUz@R8i zc=V83b#-*^lICe@Rx-en;viG{%;^FVjD2Y-j}w47HoSC*EhsUqStH!jcfi6CXu`nC zY+|8oA|rD=GIB22CeVnT`tu8erKN3cY|`1v5PHFoS=K2C^V3eYWRhQZQVj!h+clqU zWG^t=+SSc%aqnp>F03}UQ(eJ(nb#Jgx4ig$V70*8f|}SVw7+mDZ{56^(^@bo(~VXz zSxxtGqu~tjY+Ib~*r&~6d>97AK26w`tv}>IPE!pMfQ(>YwWapS3J6&Tgfv*Lx)fKd|q2-MSjW3n+^;mOx+iBgUHe2 zpzOZXj+7;z5;NX6x)+HFrFq$%0siFxS>`dt(O~M1Q>%}*iI+*Nb8yIlYNbA(I*gwb zNl3{Y{jW1Dn&2o{I?CDBD10G^1XINJ^rbn>sP^tneiacJDa#_PUoSs;vc;vdj8)3J zH0pj;kt2B{v2|J1{^jQuP2G$SIT-(#dv^MEf*%3PDhI!#IZYd!wyO)cPgoZw*Ul7D&_|T!)C40`3(80>VNULt>WUu*2!CShR zk|NklnyaArchrYD1JkY2aM-CDa&@if3g|Be65vjmwu@P_$_cNEw|?XlqKs7l2#o(^ z2(5Kv(H@m-=U@prTwEGB`_rdS_wJP-vMx|BHnz*i%92&zI!;+R<>bk=1bdu4tXd_O z!41=bV-*T;AcM4h#IMP^R24q7^7B@c*0+5&mz_;c-SbN~kxzG_N4vVZ8g=+<*PH79C#*KX@is41{`Z~6CHxxY@9 zA_;D3$Di1!wBCns-MrWzKY<^>ersIQZJtNxbT_$4Zp$v<)Q`#rl~x!_Uys|_1p=J3 z2O%rE_G|CKNZeLsXR%{!>b>iCY`pm@Z-QHW#0G^Qxp8Wu9OSAbpKmL&IYw(^_4y;*i~ZqonP zm+&cQ<_K^ghF13FbBzb{Rh6dE5b)Pm`QG1DWNeA|IweT*_%!`Wt|%V9;w1Q`VE{L8 zY`J7Nk6CM?wQWzWy1XF>#fU=2>i*j=#)^6wx_x_+v3sM2{`1$;-Tv(tBI$qry6YqV zb=mL!?H4?ozdu{ryxTvQ{ZDU-oBN-8)WU~r4g8;8@c(}o|J5w~=PR;l+KzHz&cm`u z%gm+o#5d)451$EXj4(tTev8&443}p)C*Q|DA8q|*qSfF5!OLK`o(NKpl4_OjHe~(h zSBHZ$E?*AOc3>e+I(97dfleH#QQaOc3fWgZh#$s{bM5_?)zIyEl`wOzSBHz4T2HNa z!W10h&Xq2cguh)~G{A=#G#9nYoJ-wZ7k^gaOlsx1>xw3Ot@Cw3Np zZr_Ma^9hLcmaVa-2(789S(rIdl%TfjfN&SqZwCBjUE2ah$rkDNZXZ5S)JN-B`xNfR zry$x@1g&nAe39y$@uH1?rVCy3N<$CR$MR8@E{CH0{P?R6MTUwnWrhzw8sJ3mBudEW z?AzswL~-W=%`w4B7g5;&^&%cLahad6kKoZWqh|=vd^c#23<^r$Rqsm?X zWn9yv3W9X!D{pjDZh!y^c~xFtGQV(g7zhzoHBXfuII{!PxjA3)`hxDwZN}eE%dI`A z8(orJNuv^2gruY-X}}kzrPIeE*|#rM{C1V0;_35`zUBsK?stXBQ0?96MFk(I43#8P z1e_qH?fTNePAXIo0xvq$V?SLqoZ?}Td5WN%-ht-Rxj*mzJgmFucjU%&7!93d3jCK(ESi_6KzFgG=9-Q+U_^Qq?H`@1 z+&fTSW%_hKDWURe;he4D#YC(cvbG3Nvu~9`hP%H5jQ4nUvw!1#z78bv>x67*4x#a+ zy_dk^V@HQxq@setyO)&~dVH5NA(!C?5noBj^%^kh@oIfIb>W>EQ-z7Xbo&bM5#STC zFCD%@1NG6PACR50VhPFCg7w;g&rYDbB_(B;>Gf&#(xE0X>HSMKCrDX?@=(R0o^DN8AWv;@d|HHb6ur-ixsL)sd6(vPgX#jV0Z5Tvt< zbsMWf?4MMW=h@%i+(g-lmV-@qLbre^LuR2_W5cFRzm1r#_|s26(cgaU+B&-H^UB|M zw`?7c<&ie>?8_kP?S82}M3$jWcUa{fNIPfmUce3qC5>5mBe$bz5{H;MOI#21ijR0n z6bo5QU;;_~e(#ADHSV3Iov_)Ub)TnUapc32e46-}BD$1*ayA!hi;c*|_JU+3aXsv-OkW^s*b2!VA z#^!T?CDh0@*kt5TXUU0JU(g$I)P;64Y*56@RQrhvnwr_v^Nj*BGTca@z&w4WNH9_u z(Ru#-q2crG`EEnPQ04;whX$}L$+YPB40^5;p$!1Lg^cv3#6nR3W3`pSOZkk`3=~sP z=#Si=?`cxk6tXz7mC=Y5V|6y)QIL>>4K#y&!%uof_YPg z<3Kq(1St19H6gpUtpF($oY>}v&q!5gd#s#wyQrw>?%nM_|J)Au9&_*ooCyOcl=Y`x z0mQ&d@xo`7<;1;y{Ti7yaCx1qpuF;@>=&Fb;tcE+0i+Jqe@x0PG+rr~o0-uS^E5vn zLXy7B0cb02-d`KMg)#zb)PK}Zuhm~&_g-%7?9gw??uVNbe*JYm5-2-*k*)HLPutp+ z#_aoJ*Ng)FuM2RU^YzAym?cXKfg6I})W5*eDpKtR4;!ZVdZiGp_>)3nKA{K zt7M-(Tefc(@?zi!KPfo7*u6bFcB2qDLO_G8u@(2seCBmi;Z~kOhY!E~{flXT)8FE?o7+as-KD|$!IA_=rb!JpO*pb7=$1T?Gn)GujuZzZ zA3^y`x9_rjQa=G-%n2%ZkiF3T)n2Eg_G(Mg4++RHE()bMy6J_HxT*#lpIbJc%ZVfD2*^k2J`5?GRA>PLf?;-JZP|tN?c4NR!e|Qfz<#r2 z#BD%^jzl6~zkY>wKh?1DB;{C#=Py%eo{g61x`S?zQ{cRD2wFrPjC{_gJX)aV6USUSP_{^_NR1%vEz z9|bP9GqM*Bs>cBdVJ&!fwa^q&JyTIJiY`%gdfE;tut;h!=&cYz)w~k-89yVTG?%0Kkvg%DXwP|C(RY(%wNj5tsqF-kmrj zp%g^zhq((!@4-s4e|k9uMG%&@?vy}2C|hYI_H?XW8js68!5*#DD`bhchY8UQ^b1N& zAKTmMuwZ*<;j(~ck)(W88e1rk7*Rm88)ELHJ8{Pxk;rv%?8WbYMxYCsg+3#=h>f#z zH3BYTJqD?%ZMq{(p@F_s^i%-OjO?y&gVO4AWolu_#1%0gJ&aUmGt2@kYpU6W1z&r~ z`>ujs0~m;O*+k#H`}Q?HPKnOV&6T3}73~Xl#|!Sk%$TB@#5ME0-==Ld&@_B>BpN zn1z6)vjoz#=M|Pv&Q~v%P}}12&rv&Ok}eWd6?BF~G_WD@afW(Zwr#5b0uKod51*_s z)2_4@%h+lLR(;s>MSZk4GjZdR4&t$fkaya|08qDp>K-PbDPfc2O;*hJmyWZx(8>>HxL|0v72a86UcZrMkd<{02w_P2xWKB8h!HQqua>vW5-ZBoG`ku`2s;E z6}g)fUkDjmGbd~BC32-azloviMxyYbpe^mM*R|*|1TRe0uJy`hDTVi8RpRwA!|-;{ z9WRqVolQz=xEuBX-CwHU80CU)`%9gbTr+lAN zqk?8h#bA=JVPe_Mxr5vXW1IPKJ13_qc8fO+Hswc8ep+%Q_ky(Qq(5HG>ATRmhsY-( z(dD$3hr2s%a0@>bH7JP_;JK3g4AE9~csQAnr4(w(FotPU23c9K!qD)CB$u(iwuHq{ zC5V5BQf33}1}9QBH{r|@^0OboO6-~1d`35DnCOli-IU&RWcBY&vjt}AU*w$GMMX4vk8ghxzhZosW3iz$B~;#Ko^Wri-Pb0+ z_OtwQ?Nh1O#BEj+bzV*X*gf!L9{~-wG-_P3dzf~h?A)q?0(-`O!b+x4QqJS96>n9b z?vGo*R@SG{Vm8MuEbnjSKDKot1GIg zlwQ9suc5J;tb2sYIP%ttiY!u3vZx5;C*Kz+Ydc(u(ycB~E>99~)0=ebw%0i?Isd8i z%+HM1(C{Ri#=Q}~1U+gTsJ*DUjVU{N&25Wx?uIHqV+*jMC;jnwQD*jLC#M_^I!Q7N zZU_PJR51SAc_zg1b>}d!h-{C>F9hsb*Bd>X&v}v|L5QMu)dCzYB`sv6Ik^$6ZjOmlT4;x$B zqnJ&$O0zEX$X@eM?|B#4wgd`F zop<=G?Wi?2A8U|4wse|UZw7Hc1jn4mjV3Ee;Q>kXy<+rZjo{92Awr6^a5RC>aKX8H zj$NM#n>RkFxH%zfw$XuCX;GhSV=(VbkArh_`f=C**L5-n>Is3d|0HhiDF>goTrkyc zzFngw?)C>C%(Kv0dUi_I?BBCz#-KS&UMKX5fuvfM zY>rn1;S?BCz1FtvFq;(hwwvf`;iu$*YePi8+Y_ywnIT@t_kL`2hW1#fgbUi{wo4j91xXY6T%0G1vCzJdvi;;`msjp7h z|2x19VA*@lpr8v&k`bY5XJqz3uoohedvBNSHjOv__Y5yiBhwXO8~_S8SJyyf?WRv( zp(n7T(1M1_j}Rrq>YwQ>#>7d;349-7?ZCi578sZ>3)9V~5$%K&ppkvlU@l|@0X|gF z8{b#%$Ye95tKY7kvOM0n^oREXy#R?Gv_9l~gG@$dstQ3FhNPT^0=A!mqM`sP78SiB z-!47l?og6FOzsBhN!qOn6D9GRN2L%GVB_9i+C=*Z)pp`$M~K)%hTs)cW$tdP+$em> zxFZptM%U2$fB_mad&eD!3z$ajy}aAk-yd$@3?xKLN|X@*lGp;$E41Q;&78sytE%P@ zaZg=Gzyg7+==SY)p5UXiW{0~Pv(jnMv@!L<<0DI|>8$T7#WMyxoU^^j7;ewQWGiok zyyO#S8lS8s$c9w`yyAs91e%3biHnp)stnc)e4(vV^3Lf<@D{lP>4Jt`yTd?j4(Tb} zwR=TmNJ#CA7mhHG?&July^np-3%6zGNqgz8h>y4X`RDUo!qoKPKkP)g8wASGc4+S$ zJ#u98vuDo;`FznEiIDn}R7iU-YXlspuUthg;wQzF4Z2r=bzC=<@!&@zGeI&CnW)g( z2$n}M!cUv5vGu357g!{#FlsqrE_ecNPY0-) zM(EJ5aY(y}-^<+2VG&f$G7kQtzZ!_`}BV{;UF%<<41xxu1q*XDgV@C46+vqw4Q9b`?)4hDL9h>th3 zLCLwtHw2w-R~$c{Ct>#KDe4HsRi$@cbS`|MduhScw^&rvgG%X&4oogL+&zdcJVK8} zw^)xuw_M5PUbM9IFFW!U2lKzE zdKWh>eU^A6SttE2u@{^*-0$J~$gUFpxFXG-nF3_AcrnWJuuyxuG5_P%@+&&9|)#O>tHegZE&zPkOCuCWFZ8_bx0Cut;`p5+>isyS*3r& zyM87D`ZOBZV#oyG<%0eEo(26wvAWn7z9@eQe*G09_`|s6>#3s<{LT08S7NdMWt!0R z4xbV;FPlX!l+!JNwst TsckjF8yD*sEI6mV_Lu(!2KREg diff --git a/docs/screenshots/construct.png b/docs/screenshots/construct.png new file mode 100644 index 0000000000000000000000000000000000000000..74d448d2aec934d63de68ea80d1ce0ea4d9bdb1b GIT binary patch literal 112131 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 V=ZN33A8&qxqMWKMT>9;Y{{l$mIRXFx literal 0 HcmV?d00001 diff --git a/docs/screenshots/viewer-dark.png b/docs/screenshots/viewer-dark.png index 5d01858414047ca877f040dd378145d4d39a3b94..b2d69557d3e7386123fc5a3a8c630dc9aa315aa5 100644 GIT binary patch literal 91638 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 literal 89017 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

`tvj1T{FbfRJU)EUpG2PEUFN! zZ>o^&1vM$``zooHLRp#|X8qNixXH;$6|Som7J`p6TJ>xuls(>~FR&JAqEbW!QAL8} z!g#AIxE-bD=g(ECt+fcjc57xv%90()0<+v{VK6M+_1`TCx6<+ zE%da!l}#ZeV}p^*@@`{ubN?C3I!d@pl$2l``Obd*2`z~T`jxhgK5j70DfuJY*{?MF z?%V{FKiQeN?_c(c?zIIN`vX$p^iPs*>vr5$k)(#+5`Qk&Bs~GolkO^CQ2Tj4CYI_Q zk0fB?*7}n8%D2Tb&gQE}Dy#MrE>fW@1n-B92rzVbH~fTdGYU{8m=$la7fbKjeJahJ zmUuXzqDGj*^_!?qP5fZD8MSb+8(eUul>TUK&LAh_ThyBg%0A0mrx87yBbD*Dl`Vqa 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%0A8)+*Zsrmx#^Jwq1UeSh`p?XeVw+12g*DHA5rU@ zjEuOA#KcvSLQ2%Hr*=6yx8NX@s{YxiRH=}1e>QcFO1l>`U!JCbMge1$e(+6=i~JgN z4qXw{FFi__TMU}Qmm}((Z@;9Aa~K-;%KN&&qpOM zEA$@!b;L)p52a5L)AIuV^2S9DMxLhB@BP%@e1|^GoLs5;S;bVGyD0_rR}iENy4X~d z-dmS&*h#&F@A((=~;r!${rISf)8)^pV~b|l%6+H_l(iW z?zn~`MiKE@x#i{E|8{r~kII_8{@Z}S5*ilm*BnlIk)5E%SBH%|J(oJUqPF*!Z|m^F7πk#v0N%aWS^s402K}eMTUQLFfGPz&D-nibKU9_d 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 literal 87681 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 z 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…) и (?P…)", + "grouping.col.file": "Файл", + "grouping.col.clone": "Клон", + "grouping.col.primer": "Праймер", + "grouping.no_clone": "Без клона — рид не участвует в проверке", + "grouping.summary": "Клонов: {clones} · ридов: {reads} · без клона: {unassigned}", + "workspace.empty_title": "Проверка клонов", + "workspace.empty_hint": "Укажите конструкт и риды — вердикт по каждому клону появится сразу", + "workspace.drop_construct": "Перетащите файл конструкта (FASTA, GenBank, SnapGene)", + "workspace.drop_reads": "…и папку или файлы ридов .ab1", + "workspace.click_to_choose": "или нажмите, чтобы выбрать", + "workspace.choose_files": "Выбрать отдельные файлы…", + "workspace.reads_loaded": "ридов: {n}", + "workspace.region_from": "Регион:", + "workspace.region_to": "–", + "workspace.whole": "Весь конструкт", + "workspace.whole_tip": "Проверять всю последовательность конструкта", + "workspace.circular": "Кольцевая", + "workspace.circular_tip": "Конструкт кольцевой: риды и регион могут переходить через начало", + "workspace.min_q": "Мин. Q", + "workspace.min_q_tip": "Базы с качеством ниже порога не подтверждают и не опровергают расхождения", + "workspace.het_ratio": "Двойной пик", + "workspace.het_ratio_tip": "Доля второго пика от основного, начиная с которой позиция считается смешанной", + "workspace.mixed_min": "Смесь от", + "workspace.mixed_min_tip": "Сколько смешанных позиций нужно, чтобы клон получил вердикт «смесь?»", + "workspace.grouping": "Группировка…", + "workspace.add_reads": "Добавить риды…", + "workspace.construct_button": "Конструкт…", + "workspace.construct_failed": "Не удалось открыть конструкт", + "workspace.construct_too_long": "Конструкт слишком длинный: {n} п.н. (предел {limit})", + "workspace.no_new_reads": "Новых файлов .ab1 не найдено", + "workspace.region_invalid": "Недопустимый регион", + "workspace.region_invalid_text": "Регион {start}–{end} нельзя проверить: {reason}", + "workspace.verify_failed": "Ошибка проверки клонов", + "workspace.verified": "Проверено клонов: {n}", + "workspace.project_failed": "Не удалось открыть проект", + "workspace.project_loaded": "Проект открыт: {name}", + "workspace.project_save_failed": "Не удалось сохранить проект", + "workspace.need_construct": "Сначала укажите файл конструкта", + "workspace.project_saved": "Проект сохранён: {name}", + "workspace.export_failed": "Не удалось сохранить отчёт", + "workspace.no_results": "Пока нет результатов проверки", + "workspace.exported": "Отчёт сохранён: {name}", } _lang = "ru" diff --git a/scripts/render_preview.py b/scripts/render_preview.py index e6b8c3e..a4e2c07 100644 --- a/scripts/render_preview.py +++ b/scripts/render_preview.py @@ -1,8 +1,12 @@ """Render the chromatogram widget offscreen to a PNG (dev smoke check). Usage: python scripts/render_preview.py [sample.ab1] [out.png] [--theme light|dark] [--window] + python scripts/render_preview.py --construct [out.png] [--theme light|dark] [--lang ru|en] [--empty] --window renders the whole main window (toolbar, docks, tables) instead of the bare widget. +--construct renders the "construct check" tab: the COI reference of tests/data with one +substitution introduced (so one clone shows an error) against the 8 real reads, with the +detail pane open on that difference; --empty renders the empty state instead. """ from __future__ import annotations @@ -48,6 +52,58 @@ def render_window(src: Path, out: Path, theme: str, uncheck: str = "") -> None: window.close() +ROOT = Path(__file__).resolve().parent.parent +MUTATION_AT = 250 # 0-based reference position of the introduced substitution + + +def _mutated_reference(folder: Path) -> Path: + from Bio import SeqIO + from Bio.Seq import Seq + + record = SeqIO.read(ROOT / "tests" / "data" / "refs" / "coi_HM417896.gb", "genbank") + seq = str(record.seq).upper() + base = "G" if seq[MUTATION_AT] != "G" else "T" + record.seq = Seq(seq[:MUTATION_AT] + base + seq[MUTATION_AT + 1:]) + target = folder / "COI_construct.gb" + SeqIO.write(record, target, "genbank") + return target + + +def render_construct(out: Path, theme: str, lang: str, empty: bool) -> None: + import time + + from chrom_core.config import AppConfig + from ui.main_window import MainWindow + import ui.main_window as main_window + import ui.read_view.read_view as read_view + + main_window.save_config = read_view.save_config = lambda *a, **k: None # keep the user's config + app = QApplication.instance() + app.setStyle("Fusion") + window = MainWindow(AppConfig(recent_files=[], theme=theme, language=lang)) + window.resize(1300, 820) + window.show() + ws = window.workspace + if not empty: + folder = Path(tempfile.mkdtemp(prefix="ab1kit_construct_")) + ws.handle_drop([_mutated_reference(folder), ROOT / "tests" / "data" / "real"]) + deadline = time.monotonic() + 60 + while ws.is_verifying() and time.monotonic() < deadline: + app.processEvents() + time.sleep(0.01) + ws.set_region((6, 647)) + while ws.is_verifying() and time.monotonic() < deadline: + app.processEvents() + time.sleep(0.01) + clone = next(r.clone for r in ws.reports() if r.verdict == "errors") + ws.matrix.difference_clicked.emit(clone, MUTATION_AT) + for _ in range(20): + app.processEvents() + window.grab().save(str(out)) + print(f"construct [{theme}, {lang}{', empty' if empty else ''}] -> {out}") + window.close() + + def main() -> None: examples = sorted((Path(__file__).resolve().parent.parent / "examples").glob("*.ab1")) argv = sys.argv[1:] @@ -61,6 +117,17 @@ def main() -> None: i = argv.index("--uncheck") uncheck = argv[i + 1] del argv[i:i + 2] + lang = "ru" + if "--lang" in argv: + i = argv.index("--lang") + lang = argv[i + 1] + del argv[i:i + 2] + if "--construct" in argv: + rest = [a for a in argv if a not in ("--construct", "--empty")] + out = Path(rest[0]) if rest else Path(tempfile.gettempdir()) / "ab1kit_construct.png" + app = QApplication([]) # noqa: F841 - must outlive the window + render_construct(out, theme, lang, "--empty" in argv) + return window_mode = "--window" in argv argv = [a for a in argv if a != "--window"] src = Path(argv[0]) if argv else examples[0] diff --git a/tests/test_construct_ui.py b/tests/test_construct_ui.py index f20ad72..f8c859c 100644 --- a/tests/test_construct_ui.py +++ b/tests/test_construct_ui.py @@ -631,3 +631,301 @@ def test_pane_survives_corrupt_ab1(qapp, construct, pane_report, tmp_path): assert any("corrupt.ab1" in lab.text() for lab in pane.findChildren(QLabel)) pane.show_position(P) assert pane.views()[0].highlights + + +# ------------------------------------------------------------------ workspace (Task 16) + +REAL_DIR = DATA / "real" + + +@pytest.fixture +def window(qapp, monkeypatch): + """Main window with config writes disabled and message boxes recorded.""" + from PySide6.QtWidgets import QMessageBox + + from chrom_core.config import AppConfig + from ui.main_window import MainWindow + + for target in ("ui.main_window.save_config", "ui.read_view.read_view.save_config", + "ui.construct.workspace.save_config"): + monkeypatch.setattr(target, lambda *a, **k: None) + messages: list[str] = [] + + def record(_parent, title, text, *a, **k): + messages.append(f"{title}: {text}") + return QMessageBox.StandardButton.Ok + + monkeypatch.setattr(QMessageBox, "warning", record) + monkeypatch.setattr(QMessageBox, "critical", record) + w = MainWindow(AppConfig(recent_files=[])) + w.messages = messages + yield w + w._cancel_tasks() + w.close() + + +def _wait_idle(qapp, ws, timeout=30.0): + import time + + deadline = time.monotonic() + timeout + while ws.is_verifying() and time.monotonic() < deadline: + qapp.processEvents() + time.sleep(0.005) + qapp.processEvents() + assert not ws.is_verifying() + + +def _drop(widget, paths): + from PySide6.QtCore import QMimeData, QUrl + from PySide6.QtGui import QDropEvent + + mime = QMimeData() + mime.setUrls([QUrl.fromLocalFile(str(p)) for p in paths]) + event = QDropEvent(QPointF(10, 10), Qt.DropAction.CopyAction, mime, + Qt.MouseButton.LeftButton, Qt.KeyboardModifier.NoModifier) + widget.dropEvent(event) + + +def _count_starts(ws): + calls = [] + original = ws._start_task + + def counting(*a, **k): + calls.append(k.get("key")) + return original(*a, **k) + + ws._start_task = counting + return calls + + +def _loaded(qapp, window, construct_path=COI_GB, reads=(REAL_DIR,)): + ws = window.workspace + _drop(ws, [construct_path, *reads]) + _wait_idle(qapp, ws) + return ws + + +def test_workspace_is_first_tab_and_shows_empty_state(window): + ws = window.workspace + assert window.tabs.indexOf(ws) == 0 + assert window.tabs.currentWidget() is ws + assert window.tabs.indexOf(window.read_view) == 1 + window.show() + assert ws.empty_state.isVisible() + assert not ws.matrix.isVisible() + texts = " ".join(z.text() for z in ws.empty_state.zones()) + assert "FASTA" in texts and ".ab1" in texts + + +def test_drop_construct_and_reads_folder(qapp, window, construct): + ws = _loaded(qapp, window) + window.show() + assert not ws.empty_state.isVisible() and ws.matrix.isVisible() + expected = verify_all(construct, None, ws.grouping()) + assert ws.matrix.visible_clones() == [r.clone for r in expected] + assert len(ws.matrix.visible_clones()) == 4 + assert [r.verdict for r in ws.reports()] == [r.verdict for r in expected] + # same-lineage clones against the unmodified reference: no errors + same = [r for r in ws.reports() if r.clone.startswith(("Achl_ACHLO006", "Achl_ACHLO007"))] + assert len(same) == 2 and all(r.verdict in ("ok", "incomplete") for r in same) + assert ws.summary.title_text() == construct.name + assert window.messages == [] + + +def test_matrix_click_shows_details_and_open_read_switches_tab(qapp, window, tmp_path, construct): + seq = construct.seq + mutant = "G" if seq[P] != "G" else "T" + fasta = tmp_path / "mut.fa" + fasta.write_text(f">mut\n{seq[:P]}{mutant}{seq[P + 1:]}\n") + f_copy = tmp_path / F_NAME + f_copy.write_bytes(F.read_bytes()) + ws = _loaded(qapp, window, fasta, [f_copy]) + ws.set_region((100, 600)) + _wait_idle(qapp, ws) + (report,) = ws.reports() + assert report.verdict == "errors" and [d.ref_pos for d in report.region_differences] == [P] + + ws.matrix.difference_clicked.emit(report.clone, P) + assert len(ws.detail.views()) == 1 + + ws.detail.open_read.emit(f_copy) + assert window.tabs.currentWidget() is window.read_view + assert window.read_model is not None + + # edit the read at the difference: the check re-runs and the verdict changes + window.apply_base_change(_f_index(construct, P), mutant) + assert ws.is_verifying() + _wait_idle(qapp, ws) + assert [r.verdict for r in ws.reports()] == ["ok"] + + window.undo_read() + _wait_idle(qapp, ws) + assert [r.verdict for r in ws.reports()] == ["errors"] + + +def test_read_edit_outside_project_does_not_reverify(qapp, window): + ws = _loaded(qapp, window) + starts = _count_starts(ws) + examples = Path(__file__).resolve().parents[1] / "examples" + window.read_view.read_edited.emit(examples / "310.ab1") + assert starts == [] + + +def test_project_roundtrip_restores_region_grouping_params(qapp, window, tmp_path): + ws = _loaded(qapp, window) + clone = ws.grouping().reads[0] + grouping = ws.grouping() + grouping.assign(clone.path, "renamed", clone.primer) + ws.set_grouping(grouping) + ws.set_region((100, 600)) + ws.controls.min_q.setValue(25) + _wait_idle(qapp, ws) + project = tmp_path / "check.ab1proj" + assert ws.save_project(project) + + ws.clear() + assert ws.reports() == [] and ws.region() is None + assert ws.load_project(project) + _wait_idle(qapp, ws) + assert ws.region() == (100, 600) + assert (ws.controls.start_spin.value(), ws.controls.end_spin.value()) == (101, 600) + assert ws.grouping().to_dict() == grouping.to_dict() + assert ws.params().min_q == 25 and ws.controls.min_q.value() == 25 + assert "renamed" in ws.matrix.visible_clones() + assert window.messages == [] + + +def test_broken_project_shows_message_and_empty_workspace(qapp, window, tmp_path): + ws = _loaded(qapp, window) + bad = tmp_path / "bad.ab1proj" + bad.write_text("{not json", encoding="utf-8") + assert ws.load_project(bad) is False + assert len(window.messages) == 1 and "bad.ab1proj" in window.messages[0] + window.show() + assert ws.empty_state.isVisible() + assert ws.reports() == [] and ws.grouping().reads == [] + + +def test_invalid_region_shows_message_and_does_not_run(qapp, window): + ws = _loaded(qapp, window) # COI .gb is linear + starts = _count_starts(ws) + assert ws.set_region((500, 100)) is False + assert starts == [] and ws.region() is None + assert len(window.messages) == 1 + assert (ws.controls.start_spin.value(), ws.controls.end_spin.value()) == (1, 658) + # the same through the spin boxes (1-based, inclusive): 500..658 is fine ... + ws.controls.start_spin.setValue(500) + assert starts == ["verify"] and ws.region() == (499, 658) + # ... 500..100 wraps the origin of a linear construct: refused, spins restored + ws.controls.end_spin.setValue(100) + assert starts == ["verify"] and ws.region() == (499, 658) and len(window.messages) == 2 + assert (ws.controls.start_spin.value(), ws.controls.end_spin.value()) == (500, 658) + _wait_idle(qapp, ws) + + +def test_region_spins_and_matrix_drag_stay_in_sync(qapp, window): + ws = _loaded(qapp, window) + starts = _count_starts(ws) + ws.matrix.region_changed.emit((50, 400)) + assert ws.region() == (50, 400) and starts == ["verify"] + assert (ws.controls.start_spin.value(), ws.controls.end_spin.value()) == (51, 400) + ws.controls.whole_button.click() + assert ws.region() is None and starts == ["verify", "verify"] + _wait_idle(qapp, ws) + + +def test_cancelled_reverification_keeps_previous_verdicts(qapp, window): + ws = _loaded(qapp, window) + before = ws.reports() + shown = ws.matrix.visible_clones() + info = ws.summary.info_text() + ws.set_region((100, 600)) + assert ws.is_verifying() + window._cancel_tasks() + _wait_idle(qapp, ws) + assert ws.reports() is before + assert ws.matrix.visible_clones() == shown and ws.summary.info_text() == info + + +def test_failed_reverification_keeps_previous_verdicts(qapp, window, monkeypatch): + ws = _loaded(qapp, window) + before = ws.reports() + + def boom(*a, **k): + raise RuntimeError("boom") + + monkeypatch.setattr("ui.construct.workspace.verify_all", boom) + ws.controls.min_q.setValue(30) + _wait_idle(qapp, ws) + assert ws.reports() is before + assert any("boom" in m for m in window.messages) + + +def test_params_and_circular_trigger_reverification(qapp, window): + ws = _loaded(qapp, window) + starts = _count_starts(ws) + ws.controls.het_ratio.setValue(0.5) + ws.controls.mixed_min.setValue(4) + ws.controls.circular.setChecked(True) + assert starts == ["verify"] * 3 + _wait_idle(qapp, ws) + assert ws.params().het_ratio == 0.5 and ws.params().mixed_min_positions == 4 + assert ws.construct().circular is True + + +def test_export_report_csv_and_xlsx(qapp, window, tmp_path): + ws = _loaded(qapp, window) + assert ws.export_report(tmp_path / "report.csv") + assert (tmp_path / "report.csv").read_text(encoding="utf-8").startswith("clone,verdict") + assert (tmp_path / "report_differences.csv").read_text(encoding="utf-8").startswith("clone,") + assert ws.export_report(tmp_path / "report.xlsx") + assert (tmp_path / "report.xlsx").stat().st_size > 0 + + +def test_grouping_dialog_pattern_preview_and_invalid_regex(qapp): + from PySide6.QtWidgets import QDialogButtonBox + + from chrom_core.clones import group_reads + from ui.construct.grouping_dialog import GroupingDialog + + grouping = group_reads(sorted(REAL_DIR.glob("*.ab1"))) + dialog = GroupingDialog(grouping, "", None) + ok = dialog.buttons.button(QDialogButtonBox.StandardButton.Ok) + assert dialog.table.rowCount() == 8 and ok.isEnabled() + + dialog.pattern_edit.setText("([") + assert not ok.isEnabled() and dialog.pattern_invalid() + dialog.pattern_edit.setText("(.*)") # no named groups + assert not ok.isEnabled() and dialog.pattern_invalid() + + pattern = r"Achl_ACHLO00(?P\d-09)_\d_(?P[FR])" + dialog.pattern_edit.setText(pattern) + assert ok.isEnabled() and not dialog.pattern_invalid() + result = dialog.result_grouping() + assert sorted(result.clones()) == ["6-09", "7-09"] + assert len(result.unassigned) == 4 + empty_rows = [r for r in range(8) if dialog.table.item(r, 1).text() == ""] + assert dialog.unassigned_rows() == empty_rows and len(empty_rows) == 4 + assert dialog.result_pattern() == pattern + + # manual edit: clear a clone cell -> that read becomes unassigned + first = next(r for r in range(8) if dialog.table.item(r, 1).text()) + dialog.table.item(first, 1).setText("") + assert first in dialog.unassigned_rows() + assert len(dialog.result_grouping().unassigned) == 5 + + +def test_new_ui_keys_exist_in_both_languages(): + import re as _re + + import i18n + + root = Path(__file__).resolve().parents[1] + files = [root / "ui" / "main_window.py", *sorted((root / "ui" / "construct").glob("*.py"))] + keys = set() + for path in files: + text = path.read_text(encoding="utf-8") + keys |= set(_re.findall(r"""\btr\(\s*["']([a-z_.]+)["']""", text)) + assert {"tab.construct", "menu.project.open", "workspace.drop_construct"} <= keys + assert not (keys - set(i18n.RU)), keys - set(i18n.RU) + assert not (keys - set(i18n.EN)), keys - set(i18n.EN) diff --git a/tests/test_smoke_gui.py b/tests/test_smoke_gui.py index 762423d..cd7019c 100644 --- a/tests/test_smoke_gui.py +++ b/tests/test_smoke_gui.py @@ -549,3 +549,88 @@ def test_tooltips_only_on_long_cells(qapp): set_full_text_tooltip(short) set_full_text_tooltip(long_) assert short.toolTip() == "" and long_.toolTip() == "x" * 60 + + +# ------------------------------------------------------------------ Task 16: tabs, projects +def _coi_project(tmp_path, region): + from chrom_core.clones import Grouping, VerifyParams + from chrom_core.project import Project, save_project + + refs = Path(__file__).resolve().parent / "data" / "refs" + project = tmp_path / "p.ab1proj" + save_project(project, Project(refs / "coi_HM417896.gb", False, region, Grouping(), + VerifyParams())) + return project + + +def test_construct_tab_first_with_project_menu(qapp): + from chrom_core.config import AppConfig + from i18n import tr + from ui.main_window import MainWindow + + window = MainWindow(AppConfig(recent_files=[])) + assert window.tabs.count() == 2 + assert window.tabs.currentIndex() == 0 and window.tabs.currentWidget() is window.workspace + assert window.tabs.tabText(0) == tr("tab.construct") + assert window.tabs.tabText(1) == tr("tab.read") + titles = [a.text() for a in window.project_menu.actions() if not a.isSeparator()] + assert titles == [tr("menu.project.new"), tr("menu.project.open"), tr("menu.project.save"), + tr("menu.project.save_as"), tr("menu.project.export")] + window.close() + + +@pytest.mark.skipif(not AB1, reason="no example .ab1 files") +def test_open_ab1_switches_to_read_tab(qapp): + from chrom_core.config import AppConfig + from ui.main_window import MainWindow + + window = MainWindow(AppConfig(recent_files=[])) + assert window.open_path(AB1[0]) + assert window.tabs.currentWidget() is window.read_view + window.close() + + +def test_open_project_path_goes_to_construct_tab(qapp, tmp_path): + from chrom_core.config import AppConfig + from ui.main_window import MainWindow + + project = _coi_project(tmp_path, (10, 200)) + window = MainWindow(AppConfig(recent_files=[])) + window.tabs.setCurrentWidget(window.read_view) + assert window.open_path(project) + assert window.tabs.currentWidget() is window.workspace + assert window.workspace.region() == (10, 200) + assert window.workspace.construct().name == "HM417896.1" + window.close() + + +def test_run_opens_project_argument(qapp, monkeypatch, tmp_path): + from PySide6.QtWidgets import QApplication + + import ui.main_window as mw + + project = _coi_project(tmp_path, None) + opened = [] + class ExistingApp: # run() must not create a second QApplication or block + instance = staticmethod(QApplication.instance) + + def __init__(self, _args): + pass + + def setStyle(self, _name): # noqa: N802 + pass + + def exec(self): + return 0 + + monkeypatch.setattr(mw, "QApplication", ExistingApp) + from PySide6.QtWidgets import QMessageBox + + for box in ("critical", "warning"): + monkeypatch.setattr(QMessageBox, box, lambda *a, **k: QMessageBox.StandardButton.Ok) + monkeypatch.setattr(mw.MainWindow, "show", lambda self: opened.append(self)) + assert mw.run([str(project)]) == 0 + (window,) = opened + assert window.tabs.currentWidget() is window.workspace + assert window.workspace.construct() is not None + window.close() diff --git a/translations_en.py b/translations_en.py index 21f3320..b16b4fc 100644 --- a/translations_en.py +++ b/translations_en.py @@ -196,4 +196,58 @@ "detail.err.no_alignment": "no alignment", "detail.ambiguous": "ambiguous — not counted in the verdict", "detail.uncovered": "position not covered", + "tab.construct": "Construct check", + "tab.read": "Read viewer", + "menu.project": "&Project", + "menu.project.new": "&New", + "menu.project.open": "&Open project…", + "menu.project.save": "&Save project", + "menu.project.save_as": "Save project &as…", + "menu.project.export": "&Export report…", + "grouping.title": "Group reads into clones", + "grouping.pattern": "Name pattern:", + "grouping.pattern_placeholder": "empty — automatic, by file name", + "grouping.pattern_tip": "Regular expression on the file name without extension, with groups (?P…) and (?P…)", + "grouping.col.file": "File", + "grouping.col.clone": "Clone", + "grouping.col.primer": "Primer", + "grouping.no_clone": "No clone — the read is not checked", + "grouping.summary": "Clones: {clones} · reads: {reads} · without clone: {unassigned}", + "workspace.empty_title": "Clone verification", + "workspace.empty_hint": "Give a construct and reads — every clone gets its verdict right away", + "workspace.drop_construct": "Drop the construct file (FASTA, GenBank, SnapGene)", + "workspace.drop_reads": "…and a folder or files of .ab1 reads", + "workspace.click_to_choose": "or click to choose", + "workspace.choose_files": "Choose individual files…", + "workspace.reads_loaded": "reads: {n}", + "workspace.region_from": "Region:", + "workspace.region_to": "–", + "workspace.whole": "Whole construct", + "workspace.whole_tip": "Check the whole construct sequence", + "workspace.circular": "Circular", + "workspace.circular_tip": "Circular construct: reads and the region may cross the origin", + "workspace.min_q": "Min Q", + "workspace.min_q_tip": "Bases below this quality neither confirm nor dispute a difference", + "workspace.het_ratio": "Double peak", + "workspace.het_ratio_tip": "Second-to-main peak ratio from which a position counts as mixed", + "workspace.mixed_min": "Mixed from", + "workspace.mixed_min_tip": "How many mixed positions make the clone's verdict “mixed?”", + "workspace.grouping": "Grouping…", + "workspace.add_reads": "Add reads…", + "workspace.construct_button": "Construct…", + "workspace.construct_failed": "Cannot open the construct", + "workspace.construct_too_long": "The construct is too long: {n} bp (limit {limit})", + "workspace.no_new_reads": "No new .ab1 files found", + "workspace.region_invalid": "Invalid region", + "workspace.region_invalid_text": "Region {start}–{end} cannot be checked: {reason}", + "workspace.verify_failed": "Clone verification failed", + "workspace.verified": "Clones checked: {n}", + "workspace.project_failed": "Cannot open the project", + "workspace.project_loaded": "Project opened: {name}", + "workspace.project_save_failed": "Cannot save the project", + "workspace.need_construct": "Choose a construct file first", + "workspace.project_saved": "Project saved: {name}", + "workspace.export_failed": "Cannot save the report", + "workspace.no_results": "No verification results yet", + "workspace.exported": "Report saved: {name}", } diff --git a/ui/construct/controls.py b/ui/construct/controls.py new file mode 100644 index 0000000..9088b04 --- /dev/null +++ b/ui/construct/controls.py @@ -0,0 +1,264 @@ +"""Construct-screen controls: drop zones of the empty state and the row of +region / parameter inputs above the matrix.""" + +from __future__ import annotations + +from pathlib import Path + +from PySide6.QtCore import Qt, Signal +from PySide6.QtGui import QDragEnterEvent, QDropEvent, QMouseEvent +from PySide6.QtWidgets import ( + QCheckBox, + QDoubleSpinBox, + QFrame, + QHBoxLayout, + QLabel, + QPushButton, + QSpinBox, + QVBoxLayout, + QWidget, +) + +from chrom_core.clones import Region, VerifyParams +from i18n import tr +from ui.theme import theme as palette + + +def dropped_paths(event: QDropEvent | QDragEnterEvent) -> list[Path]: + return [Path(u.toLocalFile()) for u in event.mimeData().urls() if u.toLocalFile()] + + +class DropZone(QFrame): + """Big dashed area: accepts dropped files/folders and works as a button.""" + + clicked = Signal() + dropped = Signal(list) # list[Path] + + def __init__(self, text: str, parent: QWidget | None = None) -> None: + super().__init__(parent) + self.setAcceptDrops(True) + self.setCursor(Qt.CursorShape.PointingHandCursor) + self.setMinimumSize(280, 180) + self._prompt = text + self._done = "" + self._hover = False + self._theme = "light" + self._label = QLabel(text) + self._label.setWordWrap(True) + self._label.setAlignment(Qt.AlignmentFlag.AlignCenter) + self._detail = QLabel() + self._detail.setAlignment(Qt.AlignmentFlag.AlignCenter) + self._detail.setWordWrap(True) + layout = QVBoxLayout(self) + layout.setContentsMargins(24, 24, 24, 24) + layout.addStretch(1) + layout.addWidget(self._label) + layout.addWidget(self._detail) + self._extra = QVBoxLayout() + layout.addLayout(self._extra) + layout.addStretch(1) + self._restyle() + + def text(self) -> str: + return self._label.text() + + def add_widget(self, widget: QWidget) -> None: + """Extra control under the texts (e.g. a secondary "choose files" button).""" + self._extra.addWidget(widget, 0, Qt.AlignmentFlag.AlignHCenter) + + def detail_text(self) -> str: + return self._detail.text() + + def set_done(self, text: str) -> None: + """Mark the zone as filled (``text`` names what was loaded); "" resets it.""" + self._done = text + self._detail.setText(f"✓ {text}" if text else tr("workspace.click_to_choose")) + self._restyle() + + def set_theme(self, name: str) -> None: + self._theme = name + self._restyle() + + def _restyle(self) -> None: + colors = palette(self._theme) + accent = colors["region"] + border = accent if (self._hover or self._done) else colors["dim"] + self.setStyleSheet( + f"DropZone {{ border: 2px dashed {border}; border-radius: 12px;" + f" background-color: {colors['panel']}; }}" + ) + self._label.setStyleSheet(f"font-size: 15pt; color: {colors['text']};") + self._detail.setStyleSheet(f"color: {accent if self._done else colors['dim']};") + if not self._detail.text(): + self._detail.setText(tr("workspace.click_to_choose")) + + def mouseReleaseEvent(self, event: QMouseEvent) -> None: # noqa: N802 + if event.button() == Qt.MouseButton.LeftButton and self.rect().contains( + event.position().toPoint()): + self.clicked.emit() + + def dragEnterEvent(self, event: QDragEnterEvent) -> None: # noqa: N802 + if dropped_paths(event): + self._hover = True + self._restyle() + event.acceptProposedAction() + + def dragLeaveEvent(self, event) -> None: # noqa: N802 + self._hover = False + self._restyle() + + def dropEvent(self, event: QDropEvent) -> None: # noqa: N802 + self._hover = False + self._restyle() + paths = dropped_paths(event) + if paths: + event.acceptProposedAction() + self.dropped.emit(paths) + + +class EmptyState(QWidget): + """Shown until both a construct and reads are loaded.""" + + def __init__(self, parent: QWidget | None = None) -> None: + super().__init__(parent) + self.construct_zone = DropZone(tr("workspace.drop_construct")) + self.reads_zone = DropZone(tr("workspace.drop_reads")) + self.reads_files = QPushButton(tr("workspace.choose_files")) + self.reads_files.setFlat(True) + self.reads_files.setCursor(Qt.CursorShape.PointingHandCursor) + title = QLabel(tr("workspace.empty_title")) + title.setAlignment(Qt.AlignmentFlag.AlignCenter) + title.setStyleSheet("font-size: 18pt; font-weight: 600;") + hint = QLabel(tr("workspace.empty_hint")) + hint.setAlignment(Qt.AlignmentFlag.AlignCenter) + hint.setWordWrap(True) + self._hint = hint + + zones = QHBoxLayout() + zones.setSpacing(24) + zones.addStretch(1) + zones.addWidget(self.construct_zone, 3) + self.reads_zone.add_widget(self.reads_files) + zones.addWidget(self.reads_zone, 3) + zones.addStretch(1) + layout = QVBoxLayout(self) + layout.setContentsMargins(24, 24, 24, 24) + layout.addStretch(1) + layout.addWidget(title) + layout.addWidget(hint) + layout.addSpacing(16) + layout.addLayout(zones, 2) + layout.addStretch(1) + + def zones(self) -> list[DropZone]: + return [self.construct_zone, self.reads_zone] + + def set_theme(self, name: str) -> None: + for zone in self.zones(): + zone.set_theme(name) + self._hint.setStyleSheet(f"color: {palette(name)['dim']};") + + +class ControlsBar(QWidget): + """Region (1-based, inclusive), circular flag, thresholds and data buttons. + + Spin boxes report only finished input (no keyboard tracking). Programmatic + updates (``set_region`` etc.) emit nothing. + """ + + region_edited = Signal(object) # Region (0-based half-open) + whole_requested = Signal() + params_changed = Signal() + circular_toggled = Signal(bool) + + def __init__(self, parent: QWidget | None = None) -> None: + super().__init__(parent) + self.start_spin = self._spin(1, 1) + self.end_spin = self._spin(1, 1) + self.whole_button = QPushButton(tr("workspace.whole")) + self.whole_button.setToolTip(tr("workspace.whole_tip")) + self.circular = QCheckBox(tr("workspace.circular")) + self.circular.setToolTip(tr("workspace.circular_tip")) + defaults = VerifyParams() + self.min_q = self._spin(0, 60, defaults.min_q) + self.min_q.setToolTip(tr("workspace.min_q_tip")) + self.het_ratio = QDoubleSpinBox() + self.het_ratio.setRange(0.05, 0.95) + self.het_ratio.setSingleStep(0.05) + self.het_ratio.setDecimals(2) + self.het_ratio.setValue(defaults.het_ratio) + self.het_ratio.setKeyboardTracking(False) + self.het_ratio.setToolTip(tr("workspace.het_ratio_tip")) + self.mixed_min = self._spin(1, 99, defaults.mixed_min_positions) + self.mixed_min.setToolTip(tr("workspace.mixed_min_tip")) + self.grouping_button = QPushButton(tr("workspace.grouping")) + self.construct_button = QPushButton(tr("workspace.construct_button")) + self.reads_button = QPushButton(tr("workspace.add_reads")) + + layout = QHBoxLayout(self) + layout.setContentsMargins(8, 2, 8, 2) + layout.setSpacing(6) + for widget in (QLabel(tr("workspace.region_from")), self.start_spin, + QLabel(tr("workspace.region_to")), self.end_spin, self.whole_button): + layout.addWidget(widget) + layout.addSpacing(10) + layout.addWidget(self.circular) + layout.addSpacing(10) + for text, widget in ((tr("workspace.min_q"), self.min_q), + (tr("workspace.het_ratio"), self.het_ratio), + (tr("workspace.mixed_min"), self.mixed_min)): + layout.addWidget(QLabel(text)) + layout.addWidget(widget) + layout.addStretch(1) + # data buttons live in their own strip (placed by the workspace next to + # the summary) so the parameter row stays narrow + self.data_buttons = QWidget() + buttons = QHBoxLayout(self.data_buttons) + buttons.setContentsMargins(0, 0, 8, 0) + for button in (self.grouping_button, self.reads_button, self.construct_button): + buttons.addWidget(button) + + self.start_spin.valueChanged.connect(self._region_from_spins) + self.end_spin.valueChanged.connect(self._region_from_spins) + self.whole_button.clicked.connect(self.whole_requested) + self.circular.toggled.connect(self.circular_toggled) + for spin in (self.min_q, self.het_ratio, self.mixed_min): + spin.valueChanged.connect(lambda _v: self.params_changed.emit()) + + @staticmethod + def _spin(lo: int, hi: int, value: int | None = None) -> QSpinBox: + spin = QSpinBox() + spin.setRange(lo, hi) + spin.setKeyboardTracking(False) + if value is not None: + spin.setValue(value) + return spin + + # ------------------------------------------------------------- public API + def set_region(self, region: Region | None, length: int) -> None: + """Show ``region`` (``None``: 1..length) without emitting ``region_edited``.""" + start, end = (0, length) if region is None else region + for spin, value in ((self.start_spin, start + 1), (self.end_spin, end or length)): + spin.blockSignals(True) + spin.setRange(1, max(1, length)) + spin.setValue(value) + spin.blockSignals(False) + + def set_circular(self, flag: bool) -> None: + self.circular.blockSignals(True) + self.circular.setChecked(flag) + self.circular.blockSignals(False) + + def params(self) -> VerifyParams: + return VerifyParams(self.min_q.value(), round(self.het_ratio.value(), 2), + self.mixed_min.value()) + + def set_params(self, params: VerifyParams) -> None: + for spin, value in ((self.min_q, params.min_q), (self.het_ratio, params.het_ratio), + (self.mixed_min, params.mixed_min_positions)): + spin.blockSignals(True) + spin.setValue(value) + spin.blockSignals(False) + + def _region_from_spins(self) -> None: + self.region_edited.emit((self.start_spin.value() - 1, self.end_spin.value())) diff --git a/ui/construct/detail_pane.py b/ui/construct/detail_pane.py index 9809fcf..2180e17 100644 --- a/ui/construct/detail_pane.py +++ b/ui/construct/detail_pane.py @@ -114,6 +114,8 @@ def __init__(self, parent: QWidget | None = None) -> None: splitter.addWidget(self.table) splitter.setStretchFactor(0, 3) splitter.setStretchFactor(1, 2) + self._splitter = splitter + self._split_set = False # first real width: chromatograms 3/5, table 2/5 layout = QVBoxLayout(self) layout.setContentsMargins(0, 0, 0, 0) layout.addWidget(splitter) @@ -248,6 +250,9 @@ def _view_changed(self, source: ChromatogramWidget) -> None: def resizeEvent(self, event) -> None: # noqa: N802 super().resizeEvent(event) + if not self._split_set and self.isVisible() and self.width() > 100: + self._split_set = True + self._splitter.setSizes([self.width() * 3 // 5, self.width() * 2 // 5]) self._reset_default_zoom() if self._zoom_chosen: self._apply_view() diff --git a/ui/construct/grouping_dialog.py b/ui/construct/grouping_dialog.py new file mode 100644 index 0000000..f3ade6b --- /dev/null +++ b/ui/construct/grouping_dialog.py @@ -0,0 +1,161 @@ +"""Grouping dialog: which read belongs to which clone (and primer). + +A table "file / clone / primer" with editable clone and primer cells; reads +without a clone are highlighted. A custom regex (named groups ``clone`` and +``primer``, matched against the file stem) regroups all reads at once as a +live preview; an invalid pattern gets a red frame and disables OK. +""" + +from __future__ import annotations + +from collections.abc import Iterable +from pathlib import Path + +from PySide6.QtCore import Qt +from PySide6.QtGui import QBrush, QColor +from PySide6.QtWidgets import ( + QAbstractItemView, + QDialog, + QDialogButtonBox, + QHBoxLayout, + QLabel, + QLineEdit, + QTableWidget, + QTableWidgetItem, + QVBoxLayout, + QWidget, +) + +from chrom_core.clones import DEFAULT_PRIMER_TOKENS, Grouping, ReadRef, group_reads +from i18n import tr +from ui import status +from ui.tables import configure_table +from ui.theme import theme as palette + +COL_FILE, COL_CLONE, COL_PRIMER = range(3) +_PATH_ROLE = Qt.ItemDataRole.UserRole + 2 +_INVALID_STYLE = "QLineEdit { border: 2px solid #d32f2f; }" + + +class GroupingDialog(QDialog): + def __init__(self, grouping: Grouping, pattern: str, parent: QWidget | None = None, + primer_tokens: Iterable[str] = DEFAULT_PRIMER_TOKENS) -> None: + super().__init__(parent) + self.setWindowTitle(tr("grouping.title")) + self.resize(640, 480) + self._tokens = tuple(primer_tokens) + self._paths = [r.path for r in grouping.reads] + list(grouping.unassigned) + self._invalid = False + + self.pattern_edit = QLineEdit(pattern) + self.pattern_edit.setPlaceholderText(tr("grouping.pattern_placeholder")) + self.pattern_edit.setToolTip(tr("grouping.pattern_tip")) + self._error = QLabel() + self._error.setStyleSheet("color: #d32f2f;") + self._summary = QLabel() + + self.table = QTableWidget(0, 3) + self.table.setHorizontalHeaderLabels( + [tr("grouping.col.file"), tr("grouping.col.clone"), tr("grouping.col.primer")]) + configure_table(self.table, stretch_column=COL_FILE) + self.table.setAlternatingRowColors(False) # the highlight must stay readable + self.table.setSelectionBehavior(QAbstractItemView.SelectionBehavior.SelectRows) + self.table.itemChanged.connect(self._item_changed) + + self.buttons = QDialogButtonBox( + QDialogButtonBox.StandardButton.Ok | QDialogButtonBox.StandardButton.Cancel) + self.buttons.accepted.connect(self.accept) + self.buttons.rejected.connect(self.reject) + + row = QHBoxLayout() + row.addWidget(QLabel(tr("grouping.pattern"))) + row.addWidget(self.pattern_edit, 1) + layout = QVBoxLayout(self) + layout.addLayout(row) + layout.addWidget(self._error) + layout.addWidget(self.table, 1) + layout.addWidget(self._summary) + layout.addWidget(self.buttons) + + self._fill(grouping) + self._error.hide() + self.pattern_edit.textChanged.connect(self._pattern_changed) + + # ------------------------------------------------------------- public API + def result_grouping(self) -> Grouping: + grouping = Grouping() + for row in range(self.table.rowCount()): + path = Path(self.table.item(row, COL_FILE).data(_PATH_ROLE)) + clone = self.table.item(row, COL_CLONE).text().strip() + primer = self.table.item(row, COL_PRIMER).text().strip() + if clone: + grouping.reads.append(ReadRef(path, clone, primer)) + else: + grouping.unassigned.append(path) + return grouping + + def result_pattern(self) -> str: + return self.pattern_edit.text() + + def pattern_invalid(self) -> bool: + return self._invalid + + def unassigned_rows(self) -> list[int]: + return [row for row in range(self.table.rowCount()) + if not self.table.item(row, COL_CLONE).text().strip()] + + # --------------------------------------------------------------- private + def _pattern_changed(self, text: str) -> None: + try: + grouping = group_reads(self._paths, text or None, self._tokens) + except ValueError as exc: + self._set_invalid(str(exc)) + return + self._set_invalid("") + self._fill(grouping) + + def _set_invalid(self, message: str) -> None: + self._invalid = bool(message) + self.pattern_edit.setStyleSheet(_INVALID_STYLE if message else "") + self._error.setText(message) + self._error.setVisible(bool(message)) + self.buttons.button(QDialogButtonBox.StandardButton.Ok).setEnabled(not message) + + def _fill(self, grouping: Grouping) -> None: + refs = {r.path: r for r in grouping.reads} + self.table.blockSignals(True) + self.table.setRowCount(len(self._paths)) + for row, path in enumerate(self._paths): + ref = refs.get(path) + name = QTableWidgetItem(path.name) + name.setData(_PATH_ROLE, str(path)) + name.setToolTip(str(path)) + name.setFlags(name.flags() & ~Qt.ItemFlag.ItemIsEditable) + self.table.setItem(row, COL_FILE, name) + self.table.setItem(row, COL_CLONE, QTableWidgetItem(ref.clone if ref else "")) + self.table.setItem(row, COL_PRIMER, QTableWidgetItem(ref.primer if ref else "")) + self.table.blockSignals(False) + self._highlight() + + def _item_changed(self, _item: QTableWidgetItem) -> None: + self._highlight() + + def _highlight(self) -> None: + """Rows without a clone get the theme highlight; the summary counts them.""" + colors = palette(status.current_theme()) + mark = QBrush(QColor(colors["highlight"])) + unassigned = set(self.unassigned_rows()) + self.table.blockSignals(True) + for row in range(self.table.rowCount()): + for col in range(3): + item = self.table.item(row, col) + item.setBackground(mark if row in unassigned else QBrush()) + if row in unassigned and col == COL_CLONE: + item.setToolTip(tr("grouping.no_clone")) + elif col == COL_CLONE: + item.setToolTip("") + self.table.blockSignals(False) + clones = {self.table.item(r, COL_CLONE).text().strip() + for r in range(self.table.rowCount())} - {""} + self._summary.setText(tr("grouping.summary", clones=len(clones), + reads=self.table.rowCount(), unassigned=len(unassigned))) diff --git a/ui/construct/session_files.py b/ui/construct/session_files.py new file mode 100644 index 0000000..f298b8e --- /dev/null +++ b/ui/construct/session_files.py @@ -0,0 +1,41 @@ +"""File helpers of the construct workspace: read discovery, path identity, reports.""" + +from __future__ import annotations + +import os +from collections.abc import Iterable +from pathlib import Path + +from chrom_core.clone_report import clone_report_xlsx, clones_csv, differences_csv +from chrom_core.clones import CloneReport + +PROJECT_SUFFIX = ".ab1proj" +CONSTRUCT_FILTER = "Constructs (*.fa *.fasta *.fna *.txt *.gb *.gbk *.genbank *.dna);;All files (*)" + + +def path_key(path: Path | str) -> str: + """Comparable identity of a file path (absolute, case-normalised on Windows).""" + return os.path.normcase(os.path.abspath(path)) + + +def ab1_files(paths: Iterable[Path | str]) -> list[Path]: + """``.ab1`` files among ``paths``; a folder contributes its own ``.ab1`` files.""" + out: list[Path] = [] + for p in map(Path, paths): + if p.is_dir(): + out += sorted(x for x in p.iterdir() if x.suffix.lower() == ".ab1" and x.is_file()) + elif p.suffix.lower() == ".ab1": + out.append(p) + return out + + +def write_report(path: Path, reports: list[CloneReport], construct_name: str) -> None: + """``.xlsx``: one workbook; otherwise ``path`` gets the per-clone CSV and + ``_differences.csv`` next to it the per-difference CSV.""" + path = Path(path) + if path.suffix.lower() == ".xlsx": + clone_report_xlsx(path, reports, construct_name) + return + path.write_text(clones_csv(reports), encoding="utf-8") + path.with_name(f"{path.stem}_differences.csv").write_text( + differences_csv(reports), encoding="utf-8") diff --git a/ui/construct/workspace.py b/ui/construct/workspace.py new file mode 100644 index 0000000..4d4b22a --- /dev/null +++ b/ui/construct/workspace.py @@ -0,0 +1,479 @@ +"""The "construct check" workspace: construct + reads in, per-clone verdicts out. + +Holds the session state (construct file, circular flag, region, grouping, +thresholds), re-runs ``verify_all`` in the background on every change (key +``"verify"``: a newer run cancels the older one; a cancelled or failed run +leaves the previous verdicts on screen) and reads/writes ``.ab1proj`` files. +""" + +from __future__ import annotations + +from collections.abc import Callable, Iterable +from pathlib import Path + +from PySide6.QtCore import Qt, Signal +from PySide6.QtGui import QDragEnterEvent, QDropEvent +from PySide6.QtWidgets import ( + QDialog, + QFileDialog, + QHBoxLayout, + QMessageBox, + QScrollArea, + QSplitter, + QStackedWidget, + QVBoxLayout, + QWidget, +) + +from chrom_core import project as project_io +from chrom_core.align import MAX_REFERENCE_LENGTH +from chrom_core.clones import ( + CloneReport, + Grouping, + Region, + VerifyParams, + check_region, + group_reads, + verify_all, +) +from chrom_core.config import AppConfig, save_config +from chrom_core.reference import Construct, load_construct +from i18n import tr +from ui import status +from ui.construct.controls import ControlsBar, EmptyState, dropped_paths +from ui.construct.detail_pane import DetailPane +from ui.construct.grouping_dialog import GroupingDialog +from ui.construct.matrix import CloneMatrix +from ui.construct.session_files import ( + CONSTRUCT_FILTER, + PROJECT_SUFFIX, + ab1_files, + path_key, + write_report, +) +from ui.construct.summary_bar import SummaryBar + + + +class ConstructWorkspace(QWidget): + open_read = Signal(Path) + status_message = Signal(str, int) + + def __init__(self, config: AppConfig, start_task: Callable, + parent: QWidget | None = None) -> None: + super().__init__(parent) + self.config = config + self._start_task = start_task + self._construct_path: Path | None = None + self._base: Construct | None = None + self._circular = False + self._region: Region | None = None + self._grouping = Grouping() + self._pattern = config.group_pattern + self._reports: list[CloneReport] = [] + self._shown_construct: Construct | None = None + self._task = None + self._generation = 0 + self._loading = False + self._project_path: Path | None = None + self._selected: tuple[str, int | None] | None = None # (clone, ref_pos) + + self.empty_state = EmptyState() + self.summary = SummaryBar() + self.controls = ControlsBar() + self.matrix = CloneMatrix() + self.detail = DetailPane() + self.detail.hide() + scroll = QScrollArea() + scroll.setWidgetResizable(True) + scroll.setFrameShape(QScrollArea.Shape.NoFrame) + scroll.setWidget(self.matrix) + splitter = QSplitter(Qt.Orientation.Vertical) + splitter.addWidget(scroll) + splitter.addWidget(self.detail) + splitter.setStretchFactor(0, 2) + splitter.setStretchFactor(1, 3) + main = QWidget() + box = QVBoxLayout(main) + box.setContentsMargins(0, 0, 0, 0) + box.setSpacing(2) + top = QHBoxLayout() + top.addWidget(self.summary, 1) + top.addWidget(self.controls.data_buttons) + box.addLayout(top) + box.addWidget(self.controls) + box.addWidget(splitter, 1) + self._main_page = main + self._pages = QStackedWidget() + self._pages.addWidget(self.empty_state) + self._pages.addWidget(main) + layout = QVBoxLayout(self) + layout.setContentsMargins(0, 0, 0, 0) + layout.addWidget(self._pages) + self.setAcceptDrops(True) + self._connect() + self.set_theme(status.current_theme()) + self._refresh_zones() + + def _connect(self) -> None: + empty = self.empty_state + empty.construct_zone.clicked.connect(self.choose_construct) + empty.reads_zone.clicked.connect(self.choose_reads_folder) + empty.reads_files.clicked.connect(self.choose_read_files) + for zone in empty.zones(): + zone.dropped.connect(self.handle_drop) + c = self.controls + c.region_edited.connect(self.set_region) + c.whole_requested.connect(lambda: self.set_region(None)) + c.circular_toggled.connect(self.set_circular) + c.params_changed.connect(lambda: self.set_params(c.params())) + c.grouping_button.clicked.connect(self.edit_grouping) + c.reads_button.clicked.connect(self.choose_reads_folder) + c.construct_button.clicked.connect(self.choose_construct) + self.summary.filter_changed.connect(self.matrix.set_filter) + self.matrix.region_changed.connect(self.set_region) + self.matrix.difference_clicked.connect(self._show_difference) + self.matrix.clone_clicked.connect(lambda clone: self._show_difference(clone, None)) + self.detail.open_read.connect(self.open_read) + + # ------------------------------------------------------------- state API + def construct(self) -> Construct | None: + return self._base.with_circular(self._circular) if self._base else None + + def region(self) -> Region | None: + return self._region + + def grouping(self) -> Grouping: + return Grouping(list(self._grouping.reads), list(self._grouping.unassigned)) + + def params(self) -> VerifyParams: + return self.controls.params() + + def reports(self) -> list[CloneReport]: + return self._reports + + def is_verifying(self) -> bool: + return self._task is not None + + def project_path(self) -> Path | None: + return self._project_path + + def has_data(self) -> bool: + return self._base is not None or bool(self._grouping.reads or self._grouping.unassigned) + + def contains_read(self, path: Path | str) -> bool: + key = path_key(path) + return any(path_key(p) == key for p in self._all_paths()) + + # -------------------------------------------------------------- changes + def set_construct(self, path: Path | str) -> bool: + path = Path(path) + try: + construct = load_construct(path) + except (ValueError, OSError) as exc: + self._warn(tr("workspace.construct_failed"), f"{path}:\n{exc}") + return False + if len(construct.seq) > MAX_REFERENCE_LENGTH: + self._warn(tr("workspace.construct_failed"), + tr("workspace.construct_too_long", n=len(construct.seq), + limit=MAX_REFERENCE_LENGTH)) + return False + self._construct_path, self._base, self._circular = path, construct, construct.circular + if not self._region_ok(self._region, construct.circular): + self._region = None + self._sync_controls() + self._reverify() + return True + + def add_reads(self, paths: Iterable[Path | str]) -> int: + known = {path_key(p) for p in self._all_paths()} + new = [p for p in ab1_files(paths) if path_key(p) not in known] + if not new: + self.status_message.emit(tr("workspace.no_new_reads"), 5000) + return 0 + try: + added = group_reads(new, self._pattern or None, self.config.primer_tokens) + except ValueError as exc: # stale custom pattern in the config + self._warn(tr("grouping.title"), str(exc)) + added = group_reads(new, None, self.config.primer_tokens) + self._grouping.reads += added.reads + self._grouping.unassigned += added.unassigned + self._reverify() + return len(new) + + def set_grouping(self, grouping: Grouping) -> None: + self._grouping = Grouping(list(grouping.reads), list(grouping.unassigned)) + self._reverify() + + def set_region(self, region: Region | None) -> bool: + if region is not None: + region = (int(region[0]), int(region[1])) + if not self._region_ok(region, self._circular, warn=True): + self._sync_controls() + return False + if region == self._region: + self._sync_controls() + return True + self._region = region + self._sync_controls() + self._reverify() + return True + + def set_circular(self, flag: bool) -> bool: + if not self._region_ok(self._region, flag, warn=True): + self._sync_controls() + return False + self._circular = bool(flag) + self._sync_controls() + self._reverify() + return True + + def set_params(self, params: VerifyParams) -> None: + self.controls.set_params(params) + self._reverify() + + def read_edited(self, path: Path | str) -> bool: + """A read was edited elsewhere: re-run the check if it is part of this session.""" + if not self.contains_read(path): + return False + self._reverify() + return True + + def clear(self) -> None: + self._cancel_run() + self._construct_path = self._base = None + self._circular, self._region = False, None + self._grouping, self._reports = Grouping(), [] + self._project_path = None + self._selected = None + self.detail.hide() + self.controls.set_params(VerifyParams()) + self._sync_controls() + self._refresh_zones() + + # --------------------------------------------------------------- project + def load_project(self, path: Path | str) -> bool: + path = Path(path) + try: + project = project_io.load_project(path) + except ValueError as exc: + self.clear() + self._warn(tr("workspace.project_failed"), str(exc)) + return False + self.clear() + self._loading = True + try: + ok = self.set_construct(project.construct_path) + self._grouping = project.grouping + self.controls.set_params(project.params) + if ok: + self._circular = project.circular + if self._region_ok(project.region, project.circular, warn=True): + self._region = project.region + self._project_path = path + finally: + self._loading = False + self._sync_controls() + self._reverify() + self.status_message.emit(tr("workspace.project_loaded", name=path.name), 5000) + return ok + + def save_project(self, path: Path | str) -> bool: + path = Path(path) + if self._construct_path is None: + self._warn(tr("workspace.project_save_failed"), tr("workspace.need_construct")) + return False + project = project_io.Project(self._construct_path, self._circular, self._region, + self.grouping(), self.params()) + try: + project_io.save_project(path, project) + except OSError as exc: + self._warn(tr("workspace.project_save_failed"), f"{path}:\n{exc}") + return False + self._project_path = path + self.status_message.emit(tr("workspace.project_saved", name=path.name), 5000) + return True + + def export_report(self, path: Path | str) -> bool: + path = Path(path) + if not self._reports or self._shown_construct is None: + self._warn(tr("workspace.export_failed"), tr("workspace.no_results")) + return False + try: + write_report(path, self._reports, self._shown_construct.name) + except (OSError, RuntimeError) as exc: + self._warn(tr("workspace.export_failed"), f"{path}:\n{exc}") + return False + self.status_message.emit(tr("workspace.exported", name=path.name), 5000) + return True + + # --------------------------------------------------------------- dialogs + def choose_construct(self) -> None: + path, _ = QFileDialog.getOpenFileName( + self, tr("workspace.construct_button"), self._start_dir(), CONSTRUCT_FILTER) + if path: + self.set_construct(path) + + def choose_reads_folder(self) -> None: + folder = QFileDialog.getExistingDirectory(self, tr("workspace.add_reads"), + self._start_dir()) + if folder: + self.add_reads([folder]) + + def choose_read_files(self) -> None: + paths, _ = QFileDialog.getOpenFileNames( + self, tr("workspace.add_reads"), self._start_dir(), + "Sanger chromatograms (*.ab1);;All files (*)") + if paths: + self.add_reads(paths) + + def edit_grouping(self) -> None: + dialog = GroupingDialog(self._grouping, self._pattern, self, self.config.primer_tokens) + if dialog.exec() != QDialog.DialogCode.Accepted: + return + if dialog.result_pattern() != self._pattern: + self._pattern = self.config.group_pattern = dialog.result_pattern() + save_config(self.config) + self.set_grouping(dialog.result_grouping()) + + def handle_drop(self, paths: list[Path]) -> None: + """Projects open, ``.ab1`` files and folders become reads, anything else + is taken as the construct.""" + paths = [Path(p) for p in paths] + project = next((p for p in paths if p.suffix.lower() == PROJECT_SUFFIX), None) + if project is not None: + self.load_project(project) + return + constructs = [p for p in paths if p.is_file() and p.suffix.lower() != ".ab1"] + reads = [p for p in paths if p.is_dir() or p.suffix.lower() == ".ab1"] + self._loading = True + try: + if constructs: + self.set_construct(constructs[0]) + if reads: + self.add_reads(reads) + finally: + self._loading = False + self._reverify() + + def dragEnterEvent(self, event: QDragEnterEvent) -> None: # noqa: N802 + if dropped_paths(event): + event.acceptProposedAction() + + def dropEvent(self, event: QDropEvent) -> None: # noqa: N802 + paths = dropped_paths(event) + if paths: + event.acceptProposedAction() + self.handle_drop(paths) + + def set_theme(self, name: str) -> None: + self.summary.set_theme(name) + self.matrix.set_theme(name) + self.detail.set_theme(name) + self.empty_state.set_theme(name) + + # ------------------------------------------------------------ verification + def _reverify(self) -> None: + if self._loading: + return + self._refresh_zones() + construct = self.construct() + if construct is None: + return + self._cancel_run() + if not self._grouping.reads: + self._show([], construct, self._region) + return + region, grouping, params = self._region, self.grouping(), self.params() + generation = self._generation + + def work(progress, cancelled): + return verify_all(construct, region, grouping, params, progress, cancelled) + + def done(reports): + if generation == self._generation: + self._task = None + self._show(reports, construct, region) + + task = self._start_task(work, done, tr("workspace.verify_failed"), key="verify") + self._task = task + task.cancelled.connect(lambda: self._task_ended(task)) + task.failed.connect(lambda _m: self._task_ended(task)) + + def _task_ended(self, task) -> None: + if self._task is task: + self._task = None + + def _cancel_run(self) -> None: + self._generation += 1 + task, self._task = self._task, None + if task is not None: + task.cancel() + + def _show(self, reports: list[CloneReport], construct: Construct, + region: Region | None) -> None: + self._reports, self._shown_construct = reports, construct + self.summary.set_data(construct, region, reports) + self.matrix.set_data(construct, region, reports) + self.matrix.set_filter(self.summary.shown_verdicts()) + if self._selected is not None: + clone, pos = self._selected + if any(r.clone == clone for r in reports): + self._show_difference(clone, pos) + else: + self._selected = None + self.detail.hide() + if reports: + self.status_message.emit(tr("workspace.verified", n=len(reports)), 5000) + + def _show_difference(self, clone: str, ref_pos: int | None) -> None: + report = next((r for r in self._reports if r.clone == clone), None) + if report is None or self._shown_construct is None: + return + self._selected = (clone, ref_pos) + self.detail.show() + self.detail.show_clone(report, self._shown_construct) + if ref_pos is not None: + self.detail.show_position(ref_pos) + + # --------------------------------------------------------------- helpers + def _region_ok(self, region: Region | None, circular: bool, warn: bool = False) -> bool: + if region is None or self._base is None: + return True + try: + check_region(region, len(self._base.seq), circular) + except ValueError as exc: + if warn: + start, end = region + self._warn(tr("workspace.region_invalid"), + tr("workspace.region_invalid_text", start=start + 1, end=end, + reason=exc)) + return False + return True + + def _sync_controls(self) -> None: + length = len(self._base.seq) if self._base else 1 + self.controls.set_region(self._region, length) + self.controls.set_circular(self._circular) + + def _refresh_zones(self) -> None: + empty = self.empty_state + empty.construct_zone.set_done( + f"{self._base.name} · {self._construct_path.name}" if self._base else "") + n = len(self._grouping.reads) + len(self._grouping.unassigned) + empty.reads_zone.set_done(tr("workspace.reads_loaded", n=n) if n else "") + ready = self._base is not None and n > 0 + self._pages.setCurrentWidget(self._main_page if ready else self.empty_state) + + def _all_paths(self) -> list[Path]: + return [r.path for r in self._grouping.reads] + list(self._grouping.unassigned) + + def _start_dir(self) -> str: + if self._project_path is not None: + return str(self._project_path.parent) + if self._construct_path is not None: + return str(self._construct_path.parent) + return "" + + def _warn(self, title: str, text: str) -> None: + QMessageBox.warning(self, title, text) diff --git a/ui/icons/chevron-down.svg b/ui/icons/chevron-down.svg new file mode 100644 index 0000000..e70d30b --- /dev/null +++ b/ui/icons/chevron-down.svg @@ -0,0 +1,13 @@ + + + diff --git a/ui/icons/chevron-up.svg b/ui/icons/chevron-up.svg new file mode 100644 index 0000000..b011f77 --- /dev/null +++ b/ui/icons/chevron-up.svg @@ -0,0 +1,13 @@ + + + diff --git a/ui/main_window.py b/ui/main_window.py index 28ef90a..0d62a6d 100644 --- a/ui/main_window.py +++ b/ui/main_window.py @@ -1,5 +1,7 @@ -"""ab1kit shell window: File/View/Help menus, language, theme, recent files, -background-task status bar. The single-read viewer lives in ``ui.read_view``.""" +"""ab1kit shell window: tabs "construct check" / "read viewer", File/Project/ +View/Help menus, language, theme, recent files, background-task status bar. +The single-read viewer lives in ``ui.read_view``, the construct check in +``ui.construct.workspace``.""" from __future__ import annotations @@ -10,15 +12,18 @@ from PySide6.QtGui import QAction, QDragEnterEvent, QDropEvent from PySide6.QtWidgets import ( QApplication, + QFileDialog, QMainWindow, QMessageBox, QProgressBar, QPushButton, + QTabWidget, ) from chrom_core.config import AppConfig, load_config, save_config from i18n import set_language, tr from ui import status +from ui.construct.workspace import PROJECT_SUFFIX, ConstructWorkspace from ui.read_view import ReadView from ui.status import bind_icon from ui.tasks import Task, run_task @@ -63,10 +68,19 @@ def __init__(self, config: AppConfig | None = None) -> None: self.setWindowTitle("ab1kit") self.resize(1200, 780) self.read_view = ReadView(self.config, self._start_task) - self.setCentralWidget(self.read_view) + self.workspace = ConstructWorkspace(self.config, self._start_task) + self.tabs = QTabWidget() + self.tabs.setDocumentMode(True) + self.tabs.addTab(self.workspace, tr("tab.construct")) + self.tabs.addTab(self.read_view, tr("tab.read")) + self.setCentralWidget(self.tabs) self.read_view.file_opened.connect(self._push_recent) + self.read_view.file_opened.connect(lambda _p: self.tabs.setCurrentWidget(self.read_view)) self.read_view.status_message.connect(self.statusBar().showMessage) self.read_view.title_changed.connect(self.setWindowTitle) + self.read_view.read_edited.connect(self._read_edited) + self.workspace.status_message.connect(self.statusBar().showMessage) + self.workspace.open_read.connect(self._open_read) self._build_menus() self.setAcceptDrops(True) @@ -144,11 +158,12 @@ def _build_menus(self) -> None: open_action = QAction(tr("menu.file.open"), self) bind_icon(open_action, "folder-open") open_action.setShortcut("Ctrl+O") - open_action.triggered.connect(self.read_view.open_dialog) + open_action.triggered.connect(lambda: self._in_read_tab(self.read_view.open_dialog)) file_menu.addAction(open_action) open_folder = QAction(tr("menu.file.open_folder"), self) open_folder.setShortcut("Ctrl+Shift+O") - open_folder.triggered.connect(self.read_view.open_folder_dialog) + open_folder.triggered.connect( + lambda: self._in_read_tab(self.read_view.open_folder_dialog)) file_menu.addAction(open_folder) self.recent_menu = file_menu.addMenu(tr("menu.file.recent")) self.read_view.add_file_actions(file_menu) @@ -158,6 +173,7 @@ def _build_menus(self) -> None: exit_action.triggered.connect(self.close) file_menu.addAction(exit_action) + self._build_project_menu(self.menuBar().addMenu(tr("menu.project"))) self.read_view.add_edit_menu(self.menuBar().addMenu(tr("menu.edit"))) view_menu = self.menuBar().addMenu(tr("menu.view")) @@ -189,6 +205,81 @@ def _build_menus(self) -> None: ) help_menu.addAction(about_action) + def _build_project_menu(self, menu) -> None: + self.project_menu = menu + for key, shortcut, slot in ( + ("menu.project.new", "", self._project_new), + ("menu.project.open", "Ctrl+Shift+P", self._project_open), + ("menu.project.save", "Ctrl+Shift+S", self._project_save), + ("menu.project.save_as", "", self._project_save_as), + (None, "", None), + ("menu.project.export", "Ctrl+Shift+E", self._project_export), + ): + if key is None: + menu.addSeparator() + continue + action = QAction(tr(key), self) + if shortcut: + action.setShortcut(shortcut) + action.triggered.connect(slot) + menu.addAction(action) + + # --------------------------------------------------------------- projects + def _show_workspace(self) -> None: + self.tabs.setCurrentWidget(self.workspace) + + def _project_new(self) -> None: + self.workspace.clear() + self._show_workspace() + + def _project_open(self) -> None: + path, _ = QFileDialog.getOpenFileName( + self, tr("menu.project.open"), "", f"ab1kit project (*{PROJECT_SUFFIX})") + if path: + self.open_path(path) + + def _project_save(self) -> None: + path = self.workspace.project_path() + if path is None: + self._project_save_as() + elif self.workspace.save_project(path): + self._push_recent(str(path)) + + def _project_save_as(self) -> None: + self._show_workspace() + path, _ = QFileDialog.getSaveFileName( + self, tr("menu.project.save_as"), "", f"ab1kit project (*{PROJECT_SUFFIX})") + if not path: + return + if not path.lower().endswith(PROJECT_SUFFIX): + path += PROJECT_SUFFIX + if self.workspace.save_project(path): + self._push_recent(path) + + def _project_export(self) -> None: + self._show_workspace() + path, chosen = QFileDialog.getSaveFileName( + self, tr("menu.project.export"), "", "Excel (*.xlsx);;CSV (*.csv)") + if not path: + return + if Path(path).suffix.lower() not in (".xlsx", ".csv"): + path += ".csv" if "csv" in chosen.lower() else ".xlsx" + self.workspace.export_report(path) + + def _in_read_tab(self, action) -> None: + self.tabs.setCurrentWidget(self.read_view) + action() + + def _open_read(self, path: Path) -> None: + self.read_view.open_path(path) # file_opened switches to the viewer tab + + def _read_edited(self, path: Path) -> None: + """Edits reach the check through the read's session sidecar: write it + now (or drop it after undoing everything), then re-run the check.""" + if self.workspace.contains_read(path): + self.read_view.autosave_session() + self.workspace.read_edited(path) + def _switch_language(self, code: str) -> None: self.config.language = code save_config(self.config) @@ -200,13 +291,14 @@ def set_theme(self, name: str) -> None: self.config.theme = name status.set_theme(name) self.read_view.apply_theme(name) + self.workspace.set_theme(name) QApplication.instance().setStyleSheet(app_qss(name == "dark")) save_config(self.config) # ----------------------------------------------------------- recent, drops def dragEnterEvent(self, event: QDragEnterEvent) -> None: # noqa: N802 urls = event.mimeData().urls() - if urls and urls[0].toLocalFile().lower().endswith(".ab1"): + if urls and urls[0].toLocalFile().lower().endswith((".ab1", PROJECT_SUFFIX)): event.acceptProposedAction() def dropEvent(self, event: QDropEvent) -> None: # noqa: N802 @@ -234,7 +326,14 @@ def _fill_recent_menu(self) -> None: # ------------------------------------------------- delegates to the read view def open_path(self, path: str | Path) -> bool: - return self.read_view.open_path(path) + """A ``.ab1proj`` opens in the construct check, anything else in the viewer.""" + if str(path).lower().endswith(PROJECT_SUFFIX): + self._show_workspace() + opened = self.workspace.load_project(path) + if opened: + self._push_recent(str(path)) + return opened + return self.read_view.open_path(path) # file_opened switches to the viewer tab def refresh_read(self) -> None: self.read_view.refresh_read() @@ -285,7 +384,7 @@ def _save_verify_csv(self) -> None: self.read_view._save_verify_csv() def _scan_folder(self, folder: Path) -> None: - self.read_view._scan_folder(folder) + self._in_read_tab(lambda: self.read_view._scan_folder(folder)) def _batch_export(self) -> None: self.batch_dock.export_trimmed() diff --git a/ui/style.qss b/ui/style.qss index cf16e12..de122dd 100644 --- a/ui/style.qss +++ b/ui/style.qss @@ -30,6 +30,15 @@ QLineEdit, QSpinBox, QDoubleSpinBox, QComboBox, QPlainTextEdit, QTextEdit { background-color: #ffffff; border: 1px solid #d0d5dd; border-radius: 4px; padding: 3px 6px; selection-background-color: #2f6fed; selection-color: #ffffff; } QLineEdit:focus, QSpinBox:focus, QDoubleSpinBox:focus, QComboBox:focus { border-color: #2f6fed; } +QSpinBox, QDoubleSpinBox { padding-right: 18px; } +QSpinBox::up-button, QDoubleSpinBox::up-button { subcontrol-origin: border; subcontrol-position: top right; + width: 16px; border: none; border-left: 1px solid #d0d5dd; border-top-right-radius: 4px; } +QSpinBox::down-button, QDoubleSpinBox::down-button { subcontrol-origin: border; subcontrol-position: bottom right; + width: 16px; border: none; border-left: 1px solid #d0d5dd; border-bottom-right-radius: 4px; } +QSpinBox::up-button:hover, QDoubleSpinBox::up-button:hover, +QSpinBox::down-button:hover, QDoubleSpinBox::down-button:hover { background-color: #e1e5eb; } +QSpinBox::up-arrow, QDoubleSpinBox::up-arrow { image: url(@UP@); width: 9px; height: 9px; } +QSpinBox::down-arrow, QDoubleSpinBox::down-arrow { image: url(@DOWN@); width: 9px; height: 9px; } QDockWidget { titlebar-close-icon: none; } QDockWidget::title { background-color: #eceef2; border-bottom: 1px solid #d0d5dd; padding: 5px 8px; font-weight: 600; } diff --git a/ui/style_dark.qss b/ui/style_dark.qss index 2b17d35..bdf680a 100644 --- a/ui/style_dark.qss +++ b/ui/style_dark.qss @@ -30,6 +30,15 @@ QLineEdit, QSpinBox, QDoubleSpinBox, QComboBox, QPlainTextEdit, QTextEdit { background-color: #1e1e1e; border: 1px solid #3f3f46; border-radius: 4px; padding: 3px 6px; selection-background-color: #2f6fed; selection-color: #ffffff; } QLineEdit:focus, QSpinBox:focus, QDoubleSpinBox:focus, QComboBox:focus { border-color: #2f6fed; } +QSpinBox, QDoubleSpinBox { padding-right: 18px; } +QSpinBox::up-button, QDoubleSpinBox::up-button { subcontrol-origin: border; subcontrol-position: top right; + width: 16px; border: none; border-left: 1px solid #3f3f46; border-top-right-radius: 4px; } +QSpinBox::down-button, QDoubleSpinBox::down-button { subcontrol-origin: border; subcontrol-position: bottom right; + width: 16px; border: none; border-left: 1px solid #3f3f46; border-bottom-right-radius: 4px; } +QSpinBox::up-button:hover, QDoubleSpinBox::up-button:hover, +QSpinBox::down-button:hover, QDoubleSpinBox::down-button:hover { background-color: #3a3d41; } +QSpinBox::up-arrow, QDoubleSpinBox::up-arrow { image: url(@UP@); width: 9px; height: 9px; } +QSpinBox::down-arrow, QDoubleSpinBox::down-arrow { image: url(@DOWN@); width: 9px; height: 9px; } QDockWidget { titlebar-close-icon: none; } QDockWidget::title { background-color: #2d2d30; border-bottom: 1px solid #3f3f46; padding: 5px 8px; font-weight: 600; } diff --git a/ui/theme.py b/ui/theme.py index 73f58ec..49e9512 100644 --- a/ui/theme.py +++ b/ui/theme.py @@ -69,22 +69,32 @@ def _read_qss(dark: bool) -> str: return (resource_dir() / name).read_text(encoding="utf-8") -def tick_image(background: str) -> str: - """Path of a tick (Lucide ``check``) PNG-free SVG readable on ``background``, - for QSS ``image: url(...)``. Written once per colour to the temp folder.""" - r, g, b = (int(background.lstrip("#")[i:i + 2], 16) for i in (0, 2, 4)) - tick = "#1a1a1a" if 0.299 * r + 0.587 * g + 0.114 * b > 150 else "#ffffff" +def tinted_icon(name: str, color: str, stroke: str = "2") -> str: + """Path of icon ``name`` (``ui/icons/.svg``) drawn in ``color``, for QSS + ``image: url(...)``. Written once per icon and colour to the temp folder.""" folder = Path(tempfile.gettempdir()) / "ab1kit_icons" folder.mkdir(exist_ok=True) - target = folder / f"check_{tick.lstrip('#')}.svg" + target = folder / f"{name}_{color.lstrip('#')}_{stroke}.svg" if not target.exists(): - svg = (resource_dir() / "icons" / "check.svg").read_text(encoding="utf-8") - target.write_text(svg.replace("currentColor", tick).replace('stroke-width="2"', 'stroke-width="3"'), + svg = (resource_dir() / "icons" / f"{name}.svg").read_text(encoding="utf-8") + target.write_text(svg.replace("currentColor", color) + .replace('stroke-width="2"', f'stroke-width="{stroke}"'), encoding="utf-8") return target.as_posix() +def tick_image(background: str) -> str: + """Path of a tick (Lucide ``check``) SVG readable on ``background``.""" + r, g, b = (int(background.lstrip("#")[i:i + 2], 16) for i in (0, 2, 4)) + tick = "#1a1a1a" if 0.299 * r + 0.587 * g + 0.114 * b > 150 else "#ffffff" + return tinted_icon("check", tick, "3") + + def app_qss(dark: bool) -> str: """Application stylesheet (ui/style.qss or ui/style_dark.qss). Both themes set explicit colours so the chrome never depends on the OS light/dark mode.""" - return _read_qss(dark).replace("@TICK@", tick_image("#2f6fed")) + arrow = theme("dark" if dark else "light")["text"] + return (_read_qss(dark) + .replace("@TICK@", tick_image("#2f6fed")) + .replace("@UP@", tinted_icon("chevron-up", arrow, "3")) + .replace("@DOWN@", tinted_icon("chevron-down", arrow, "3"))) From f836f42a7477b82d59178186562484d0b54a631d Mon Sep 17 00:00:00 2001 From: Aleksey Drobin <43707931+adrobi@users.noreply.github.com> Date: Fri, 30 Oct 2026 16:28:45 +0300 Subject: [PATCH 30/44] ui: construct workspace review fixes: inactive viewer actions, clear resets results, drop/project edge cases Co-Authored-By: Claude Opus 5.5 --- tests/test_construct_ui.py | 128 +++++++++++++++++++++++++++++++- tests/test_smoke_gui.py | 19 +++++ ui/construct/controls.py | 6 +- ui/construct/grouping_dialog.py | 4 + ui/construct/matrix.py | 7 ++ ui/construct/summary_bar.py | 6 ++ ui/construct/workspace.py | 19 +++-- ui/main_window.py | 3 + ui/read_view/read_view.py | 13 +++- 9 files changed, 191 insertions(+), 14 deletions(-) diff --git a/tests/test_construct_ui.py b/tests/test_construct_ui.py index f8c859c..979090b 100644 --- a/tests/test_construct_ui.py +++ b/tests/test_construct_ui.py @@ -14,11 +14,13 @@ import pytest from PySide6.QtCore import QEvent, QPoint, QPointF, Qt -from PySide6.QtGui import QColor, QImage, QMouseEvent, QWheelEvent +from PySide6.QtGui import QAction, QColor, QImage, QMouseEvent, QWheelEvent from PySide6.QtWidgets import QApplication from chrom_core.align import align_to_construct -from chrom_core.clones import CloneDifference, CloneReport, Grouping, ReadRef, verify_all +from chrom_core.clones import ( + CloneDifference, CloneReport, Grouping, ReadRef, VerifyParams, verify_all, +) from chrom_core.editing import EditableRead from chrom_core.reference import load_construct from clone_fixtures import COI_GB, DATA, real_read, with_secondary_peak, write_read @@ -662,6 +664,17 @@ def record(_parent, title, text, *a, **k): yield w w._cancel_tasks() w.close() + _delete(qapp, w) + + +def _delete(qapp, widget): + """Really destroy a test window (closed windows otherwise live on and make + every later theme switch restyle them).""" + from PySide6.QtCore import QCoreApplication, QEvent + + widget.deleteLater() + QCoreApplication.sendPostedEvents(None, QEvent.Type.DeferredDelete.value) + qapp.processEvents() def _wait_idle(qapp, ws, timeout=30.0): @@ -929,3 +942,114 @@ def test_new_ui_keys_exist_in_both_languages(): assert {"tab.construct", "menu.project.open", "workspace.drop_construct"} <= keys assert not (keys - set(i18n.RU)), keys - set(i18n.RU) assert not (keys - set(i18n.EN)), keys - set(i18n.EN) + + +# ------------------------------------------------------------------ Task 16 review fixes + + +def test_hidden_viewer_actions_do_nothing_on_construct_tab(qapp, window, tmp_path, construct): + f_copy = tmp_path / F_NAME + f_copy.write_bytes(F.read_bytes()) + ws = _loaded(qapp, window, COI_GB, [f_copy]) + ws.detail.open_read.emit(f_copy) + assert window.tabs.currentWidget() is window.read_view + window.apply_base_change(_f_index(construct, P), "N") + _wait_idle(qapp, ws) + edited = "".join(window.read_model.seq) + assert window.undo_action.isEnabled() + + window.tabs.setCurrentWidget(ws) + starts = _count_starts(ws) + assert not window.undo_action.isEnabled() + window.undo_action.trigger() + for action in window.read_view.findChildren(QAction): + if action.parent() is window.read_view: + assert not action.isEnabled(), action.text() + assert "".join(window.read_model.seq) == edited and starts == [] + + window.tabs.setCurrentWidget(window.read_view) + assert window.undo_action.isEnabled() and not window.redo_action.isEnabled() + + +def test_clear_resets_matrix_and_summary(qapp, window, tmp_path): + ws = _loaded(qapp, window) + assert ws.matrix.visible_clones() + ws.clear() + assert ws.matrix.visible_clones() == [] and ws.summary.title_text() == "" + assert not ws.detail.isVisible() + _drop(ws, [COI_GB, REAL_DIR]) + assert ws.is_verifying() + window._cancel_tasks() + _wait_idle(qapp, ws) + assert ws.matrix.visible_clones() == [] and ws.reports() == [] + assert ws.summary.title_text() == "" + + +def test_project_with_missing_construct_is_not_reported_open(qapp, window, tmp_path): + from chrom_core.project import Project, save_project + + project = tmp_path / "lost.ab1proj" + save_project(project, Project(tmp_path / "gone.gb", False, None, + Grouping([ReadRef(F, "c1", "F")]), VerifyParams())) + said = [] + window.workspace.status_message.connect(lambda text, _ms: said.append(text)) + assert window.workspace.load_project(project) is False + assert window.workspace.project_path() is None + assert len(window.messages) == 1 and "gone.gb" in window.messages[0] + assert not any("lost.ab1proj" in s for s in said) + + +def test_drop_without_changes_does_not_reverify(qapp, window, tmp_path): + ws = _loaded(qapp, window) + starts = _count_starts(ws) + _drop(ws, [REAL_DIR]) # nothing new + bad = tmp_path / "broken.gb" + bad.write_text("LOCUS nonsense\n", encoding="utf-8") + _drop(ws, [bad]) # construct fails to load + assert starts == [] + assert len(window.messages) == 1 + + +def test_wrapping_region_on_circular_construct_survives_project(qapp, window, tmp_path, construct): + fasta = tmp_path / "coi.fa" # FASTA constructs are circular + fasta.write_text(f">coi\n{construct.seq}\n") + ws = _loaded(qapp, window, fasta, [REAL_DIR]) + assert ws.construct().circular + ws.controls.start_spin.setValue(600) + ws.controls.end_spin.setValue(50) + assert ws.region() == (599, 50) + _wait_idle(qapp, ws) + project = tmp_path / "wrap.ab1proj" + assert ws.save_project(project) + ws.clear() + assert ws.load_project(project) + _wait_idle(qapp, ws) + assert ws.region() == (599, 50) and ws.construct().circular + assert (ws.controls.start_spin.value(), ws.controls.end_spin.value()) == (600, 50) + assert window.messages == [] + + +def test_grouping_dialog_flags_invalid_initial_pattern(qapp): + from PySide6.QtWidgets import QDialogButtonBox + + from chrom_core.clones import group_reads + from ui.construct.grouping_dialog import GroupingDialog + + grouping = group_reads(sorted(REAL_DIR.glob("*.ab1"))) + dialog = GroupingDialog(grouping, "(?P[", None) + assert dialog.pattern_invalid() + assert not dialog.buttons.button(QDialogButtonBox.StandardButton.Ok).isEnabled() + assert dialog.table.rowCount() == 8 and dialog.result_grouping().to_dict() == grouping.to_dict() + + +def test_double_spin_follows_ui_language(qapp): + from i18n import set_language + from ui.construct.controls import ControlsBar + + try: + set_language("en") + assert ControlsBar().het_ratio.text() == "0.40" + set_language("ru") + assert ControlsBar().het_ratio.text() == "0,40" + finally: + set_language("ru") diff --git a/tests/test_smoke_gui.py b/tests/test_smoke_gui.py index cd7019c..b36701d 100644 --- a/tests/test_smoke_gui.py +++ b/tests/test_smoke_gui.py @@ -25,11 +25,30 @@ def no_config_writes(monkeypatch, tmp_path): the example files (closing a modified window autosaves one).""" monkeypatch.setattr("ui.main_window.save_config", lambda *a, **k: None) monkeypatch.setattr("ui.read_view.read_view.save_config", lambda *a, **k: None) + monkeypatch.setattr("ui.construct.workspace.save_config", lambda *a, **k: None) from chrom_core import sessions monkeypatch.setattr(sessions, "session_path", lambda _p: tmp_path / "session.json") +@pytest.fixture(autouse=True) +def delete_windows(): + """Destroy the windows a test created: closed windows otherwise stay alive + and every later theme switch restyles all of them.""" + yield + from PySide6.QtCore import QCoreApplication, QEvent + from PySide6.QtWidgets import QApplication + + app = QApplication.instance() + if app is None: + return + for widget in app.topLevelWidgets(): + widget.close() + widget.deleteLater() + QCoreApplication.sendPostedEvents(None, QEvent.Type.DeferredDelete.value) + app.processEvents() + + def _wait_for(app, predicate, timeout=5.0): import time diff --git a/ui/construct/controls.py b/ui/construct/controls.py index 9088b04..cfa3fb2 100644 --- a/ui/construct/controls.py +++ b/ui/construct/controls.py @@ -5,7 +5,7 @@ from pathlib import Path -from PySide6.QtCore import Qt, Signal +from PySide6.QtCore import QLocale, Qt, Signal from PySide6.QtGui import QDragEnterEvent, QDropEvent, QMouseEvent from PySide6.QtWidgets import ( QCheckBox, @@ -20,7 +20,7 @@ ) from chrom_core.clones import Region, VerifyParams -from i18n import tr +from i18n import language, tr from ui.theme import theme as palette @@ -186,6 +186,8 @@ def __init__(self, parent: QWidget | None = None) -> None: self.het_ratio.setRange(0.05, 0.95) self.het_ratio.setSingleStep(0.05) self.het_ratio.setDecimals(2) + self.het_ratio.setLocale(QLocale( + QLocale.Language.English if language() == "en" else QLocale.Language.Russian)) self.het_ratio.setValue(defaults.het_ratio) self.het_ratio.setKeyboardTracking(False) self.het_ratio.setToolTip(tr("workspace.het_ratio_tip")) diff --git a/ui/construct/grouping_dialog.py b/ui/construct/grouping_dialog.py index f3ade6b..339e67b 100644 --- a/ui/construct/grouping_dialog.py +++ b/ui/construct/grouping_dialog.py @@ -79,6 +79,10 @@ def __init__(self, grouping: Grouping, pattern: str, parent: QWidget | None = No self._fill(grouping) self._error.hide() + try: # a stale pattern from the config: flag it, keep the given grouping + group_reads([], pattern or None, self._tokens) + except ValueError as exc: + self._set_invalid(str(exc)) self.pattern_edit.textChanged.connect(self._pattern_changed) # ------------------------------------------------------------- public API diff --git a/ui/construct/matrix.py b/ui/construct/matrix.py index 7f5c725..17587a3 100644 --- a/ui/construct/matrix.py +++ b/ui/construct/matrix.py @@ -152,6 +152,13 @@ def set_data(self, construct: Construct, region: Region | None, self.updateGeometry() self.update() + def clear(self) -> None: + """No construct, no rows (the empty placeholder is painted).""" + self._construct, self._region, self._rows = None, None, [] + self._band, self._press, self._mode = None, None, "" + self.updateGeometry() + self.update() + def set_filter(self, verdicts: set[str]) -> None: self._filter = set(verdicts) self.updateGeometry() diff --git a/ui/construct/summary_bar.py b/ui/construct/summary_bar.py index cf35be9..315887a 100644 --- a/ui/construct/summary_bar.py +++ b/ui/construct/summary_bar.py @@ -78,6 +78,12 @@ def set_data(self, construct: Construct, region: Region | None, button.setText(tr(f"construct.count.{verdict}", n=n)) button.setVisible(n > 0) + def clear(self) -> None: + self._title.clear() + self._info.clear() + for button in self._counters.values(): + button.hide() + def counter(self, verdict: str) -> QPushButton: return self._counters[verdict] diff --git a/ui/construct/workspace.py b/ui/construct/workspace.py index 4d4b22a..816c208 100644 --- a/ui/construct/workspace.py +++ b/ui/construct/workspace.py @@ -158,9 +158,6 @@ def is_verifying(self) -> bool: def project_path(self) -> Path | None: return self._project_path - def has_data(self) -> bool: - return self._base is not None or bool(self._grouping.reads or self._grouping.unassigned) - def contains_read(self, path: Path | str) -> bool: key = path_key(path) return any(path_key(p) == key for p in self._all_paths()) @@ -246,6 +243,9 @@ def clear(self) -> None: self._grouping, self._reports = Grouping(), [] self._project_path = None self._selected = None + self._shown_construct = None + self.matrix.clear() + self.summary.clear() self.detail.hide() self.controls.set_params(VerifyParams()) self._sync_controls() @@ -270,12 +270,13 @@ def load_project(self, path: Path | str) -> bool: self._circular = project.circular if self._region_ok(project.region, project.circular, warn=True): self._region = project.region - self._project_path = path + self._project_path = path finally: self._loading = False self._sync_controls() self._reverify() - self.status_message.emit(tr("workspace.project_loaded", name=path.name), 5000) + if ok: # without its construct the project is not open: Save asks for a file + self.status_message.emit(tr("workspace.project_loaded", name=path.name), 5000) return ok def save_project(self, path: Path | str) -> bool: @@ -346,15 +347,17 @@ def handle_drop(self, paths: list[Path]) -> None: return constructs = [p for p in paths if p.is_file() and p.suffix.lower() != ".ab1"] reads = [p for p in paths if p.is_dir() or p.suffix.lower() == ".ab1"] + changed = False self._loading = True try: if constructs: - self.set_construct(constructs[0]) + changed = self.set_construct(constructs[0]) if reads: - self.add_reads(reads) + changed = self.add_reads(reads) > 0 or changed finally: self._loading = False - self._reverify() + if changed: + self._reverify() def dragEnterEvent(self, event: QDragEnterEvent) -> None: # noqa: N802 if dropped_paths(event): diff --git a/ui/main_window.py b/ui/main_window.py index 0d62a6d..00c430f 100644 --- a/ui/main_window.py +++ b/ui/main_window.py @@ -74,6 +74,8 @@ def __init__(self, config: AppConfig | None = None) -> None: self.tabs.addTab(self.workspace, tr("tab.construct")) self.tabs.addTab(self.read_view, tr("tab.read")) self.setCentralWidget(self.tabs) + self.tabs.currentChanged.connect( + lambda _i: self.read_view.set_active(self.tabs.currentWidget() is self.read_view)) self.read_view.file_opened.connect(self._push_recent) self.read_view.file_opened.connect(lambda _p: self.tabs.setCurrentWidget(self.read_view)) self.read_view.status_message.connect(self.statusBar().showMessage) @@ -88,6 +90,7 @@ def __init__(self, config: AppConfig | None = None) -> None: self.statusBar().showMessage(tr("status.ready")) self._build_task_status() self._fill_recent_menu() + self.read_view.set_active(self.tabs.currentWidget() is self.read_view) # ------------------------------------------------------------------ tasks def _build_task_status(self) -> None: diff --git a/ui/read_view/read_view.py b/ui/read_view/read_view.py index a3b3412..6c0ea10 100644 --- a/ui/read_view/read_view.py +++ b/ui/read_view/read_view.py @@ -67,6 +67,7 @@ def __init__(self, config: AppConfig, start_task: Callable, parent: QWidget | No self.config = config self._start_task = start_task self._path: Path | None = None + self._active = True # False while the shell shows another tab self.read_model: EditableRead | None = None self.trim_dialog: TrimDialog | None = None self.reference_seq: str = "" @@ -503,10 +504,18 @@ def apply_theme(self, name: str) -> None: repaint_statuses(table) # --------------------------------------------------------------- editing + def set_active(self, active: bool) -> None: + """Enable or disable all of the view's own actions (menus, toolbar, + shortcuts), so a hidden view cannot be edited by a stray shortcut.""" + self._active = bool(active) + for action in self.findChildren(QAction, options=Qt.FindChildOption.FindDirectChildrenOnly): + action.setEnabled(self._active) + self._sync_actions() + def _sync_actions(self) -> None: model = self.read_model - self.undo_action.setEnabled(bool(model and model.can_undo)) - self.redo_action.setEnabled(bool(model and model.can_redo)) + self.undo_action.setEnabled(self._active and bool(model and model.can_undo)) + self.redo_action.setEnabled(self._active and bool(model and model.can_redo)) def refresh_read(self) -> None: if self.read_model is None: From faa2c07da0bd354f78d43e68df123f077a17c340 Mon Sep 17 00:00:00 2001 From: Aleksey Drobin <43707931+adrobi@users.noreply.github.com> Date: Fri, 30 Oct 2026 16:38:15 +0300 Subject: [PATCH 31/44] CLI subcommands verify-clones/qc/export; docs and v1.1.0 Co-Authored-By: Claude Sonnet 5.5 --- CHANGELOG.md | 35 ++++++++++ README.md | 58 +++++++++++++++- chrom_cli.py | 174 +++++++++++++++++++++++++++++++++++++++++++++- pyproject.toml | 2 +- tests/test_cli.py | 146 ++++++++++++++++++++++++++++++++++++++ 5 files changed, 410 insertions(+), 5 deletions(-) create mode 100644 tests/test_cli.py diff --git a/CHANGELOG.md b/CHANGELOG.md index 5f201bd..5f4f894 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,41 @@ All notable changes to ab1kit are documented here. The format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/); versioning is [SemVer](https://semver.org/). +## [1.1.0] — 2026-10-30 + +Clone verification: check a plate of clones against a construct, in the GUI or +from the command line. + +### Added +- Reference loading from FASTA, GenBank and SnapGene files, with circular + constructs and reads spanning the origin +- Normalised secondary-peak analysis at any read position +- Grouping of reads into clones by file name (default rules or a custom regex), + per-clone coverage by strand, merged differences and verdicts + (`ok` / `errors` / `incomplete` / `mixed` / `no_data`) +- Amino-acid consequences of differences inside CDS features +- Clone report as CSV and Excel (sheets `Clones` and `Differences`); + `.ab1proj` project files for verification sessions +- Clone-verification workspace: summary bar, clone matrix, difference detail pane with stacked + chromatograms, grouping editor, drag-and-drop of reads and projects +- Background tasks with progress and cancel +- Command-line subcommands `verify-clones`, `qc` and `export` (no Qt import) +- Real-data test corpus (sangeranalyseR reads, COI and pUC19 references) + +### Changed +- Refreshed UI: QSS theme, icons, one status palette everywhere +- Quality colour thresholds are now <20 / 20-29 / >=30 everywhere +- Main window split into the `ui.read_view` package (no behaviour change) +- Alignment counts distinct placements; repeated hits are flagged as ambiguous + +### Fixed +- Reverse-strand reads in expected-SNP verification and the reference overlay + were indexed in the wrong orientation (now correct) +- Reverse-complementing a read misplaced peak positions; editing sessions saved + after a reverse-complement with 1.0.0 or earlier hold wrong peak positions — + re-open the original file and reverse-complement again +- Untranslated verification notes; mean quality for reads without quality data + ## [1.0.0] — 2026-10-24 First feature-complete release: the full cycle «open a chromatogram → inspect → diff --git a/README.md b/README.md index c789139..85de459 100644 --- a/README.md +++ b/README.md @@ -49,6 +49,59 @@ for everyday molecular biology lab work. English/Russian interface. ![dark theme](docs/screenshots/viewer-dark.png) ![batch mode](docs/screenshots/batch.png) +## Clone verification + +Check a set of plasmid or amplicon clones against the expected construct from +their Sanger reads: open the clone-verification workspace, load the reference (FASTA, +GenBank or SnapGene), drop the `.ab1` reads of the whole plate, optionally set +the region of interest, and read the verdict per clone off the colour matrix. + +![clone verification](docs/screenshots/construct.png) + +**Scenario.** Load the construct, add the reads (files or a folder), check the +automatic grouping into clones, choose the region; every clone gets its verdict right away. Click a +difference in the matrix to see the stacked chromatograms of every read at that +position. Export the result as Excel/CSV, or save the whole session as an +`.ab1proj` file. FASTA constructs are treated as circular (reads may span the +origin); GenBank/SnapGene files take the topology from the file; the *Circular* +checkbox (`--linear` on the command line) overrides the topology. + +**File names.** Reads are grouped by name as `_`: the primer is +the last known primer token (`F`, `R`, `T7`, `SP6`, `M13F`, `pUC-F`, ...), the +clone is what precedes it, minus an order digit and a leading plate well: +`A05_clone3_2_R.ab1` is clone `clone3`, primer `R`; `Achl_ACHLO006-09_1_F.ab1` +is clone `Achl_ACHLO006-09`. Files whose name yields no clone stay unassigned +and are skipped. For other conventions give a regular expression with named +groups `clone` and `primer` that matches the whole file name without the +extension, e.g. `(?P\d+)-(?P[A-Za-z0-9]+)`. + +**Verdicts.** + +| Verdict | Meaning | +| --- | --- | +| `ok` (green) | the region is covered and no reliable difference from the construct | +| `errors` (red) | at least one difference in the region, supported by a read of Q >= min Q | +| `incomplete` (yellow) | no difference, but part of the region is not covered by any read | +| `mixed` (purple) | at least 3 positions (default) with a double peak: probably a mixed colony | +| `no_data` (grey) | no read of the clone aligned to the construct | + +A difference is *confirmed* (only supporting reads), *disputed* (another read +shows the reference there) or *low quality* (seen only below min Q; does not +change the verdict). Defaults: min Q 20, double-peak ratio 0.40. + +**Command line** (no GUI, no Qt needed): + +``` +ab1kit verify-clones --construct pET28-gene.gb --region 120-1850 reads/ -o report.xlsx +ab1kit qc reads/ -o qc.csv +ab1kit export reads/ --trim --fasta -o trimmed/ +``` + +`verify-clones` prints a table of clones and exits with 0 if at least one clone +is `ok`, 1 if none is, 2 on invalid input; `-o report.csv` writes `report.csv` +and `report_differences.csv`. Options: `--region A-B` (1-based, inclusive), +`--linear`, `--pattern REGEX`, `--min-q N`, `--het-ratio X`. + ## Getting started Requires Python 3.11+: @@ -97,5 +150,6 @@ Example chromatograms in `examples/` come from the ## Status -v1.0.0 — viewer, editing, trimming, batch mode, alignment, SNP calling and -expected-SNP verification are all implemented. See [CHANGELOG.md](CHANGELOG.md). +v1.1.0 — adds clone verification, a command-line interface, a refreshed UI +and more accurate peak analysis on top of the 1.0 viewer, editing, batch mode, +alignment, SNP calling and expected-SNP verification. See [CHANGELOG.md](CHANGELOG.md). diff --git a/chrom_cli.py b/chrom_cli.py index 66f4fb1..9d564b8 100644 --- a/chrom_cli.py +++ b/chrom_cli.py @@ -1,14 +1,184 @@ -"""ab1kit entry point: the ``ab1kit`` command launches the GUI.""" +"""ab1kit entry point: the GUI by default, plus ``verify-clones`` / ``qc`` / ``export``. + +The subcommands are a thin shell over ``chrom_core`` and never import Qt. +""" from __future__ import annotations +import argparse import sys +from pathlib import Path + +COMMANDS = {"verify-clones", "qc", "export"} + + +class CliError(Exception): + """Bad input: reported on stderr, exit code 2.""" + + +def _prepare_streams() -> None: + """Print Cyrillic safely on any console; attach to the parent console if windowed.""" + if sys.stdout is None or sys.stderr is None: # frozen windowed build + try: + import ctypes + + if ctypes.windll.kernel32.AttachConsole(-1): + if sys.stdout is None: + sys.stdout = open("CONOUT$", "w", encoding="utf-8", errors="replace") + if sys.stderr is None: + sys.stderr = open("CONOUT$", "w", encoding="utf-8", errors="replace") + except (AttributeError, OSError): + pass + for stream in (sys.stdout, sys.stderr): + if stream is not None and hasattr(stream, "reconfigure"): + stream.reconfigure(encoding="utf-8", errors="replace") + + +def _parse_region(text: str) -> tuple[int, int]: + try: + a, b = (int(x) for x in text.split("-")) + except ValueError: + raise CliError(f"invalid --region {text!r}: expected A-B (1-based, inclusive)") from None + if a < 1 or b < 1: + raise CliError(f"invalid --region {text!r}: positions start at 1") + return (a - 1, b) + + +def _reads_in(folder: str) -> list[Path]: + path = Path(folder) + if not path.is_dir(): + raise CliError(f"not a directory: {folder}") + return sorted(p for p in path.iterdir() if p.suffix.lower() == ".ab1") + + +def _verify_clones(args: argparse.Namespace) -> int: + from chrom_core.clone_report import clone_report_xlsx, clones_csv, differences_csv + from chrom_core.clones import VerifyParams, check_region, group_reads, verify_all + from chrom_core.reference import load_construct + + try: + construct = load_construct(args.construct) + except (ValueError, OSError) as exc: + raise CliError(f"cannot load construct: {exc}") from exc + if args.linear: + construct = construct.with_circular(False) + region = _parse_region(args.region) if args.region else None + try: + check_region(region, len(construct.seq), construct.circular) + paths = _reads_in(args.reads_dir) + if not paths: + raise CliError(f"no .ab1 files in {args.reads_dir}") + grouping = group_reads(paths, pattern=args.pattern) + except ValueError as exc: + raise CliError(str(exc)) from exc + for path in grouping.unassigned: + print(f"ab1kit: skipped (clone name not recognised): {path.name}", file=sys.stderr) + if not grouping.reads: + raise CliError("no reads could be assigned to a clone") + params = VerifyParams(min_q=args.min_q, het_ratio=args.het_ratio) + reports = verify_all(construct, region, grouping, params) + + out = Path(args.output) + if out.suffix.lower() == ".xlsx": + clone_report_xlsx(out, reports, construct.name) + elif out.suffix.lower() == ".csv": + out.write_text(clones_csv(reports), encoding="utf-8") + out.with_name(f"{out.stem}_differences.csv").write_text( + differences_csv(reports), encoding="utf-8") + else: + raise CliError("report file must end in .xlsx or .csv") + + width = max(len(r.clone) for r in reports) + for r in reports: + print(f"{r.clone:<{width}} {r.verdict:<10} coverage {r.region_coverage_pct:5.1f}% " + f"differences {len(r.region_differences)}") + return 0 if any(r.verdict == "ok" for r in reports) else 1 + + +def _qc(args: argparse.Namespace) -> int: + from chrom_core import batch + + _reads_in(args.reads_dir) # validates the folder + text = batch.summary_csv(batch.scan_folder(args.reads_dir)) + if args.output: + Path(args.output).write_text(text, encoding="utf-8") + else: + sys.stdout.write(text) + return 0 + + +def _export(args: argparse.Namespace) -> int: + from chrom_core import batch + + if not args.trim: + raise CliError("export currently needs --trim") + reports = batch.scan_folder(args.reads_dir) + if not reports: + raise CliError(f"no .ab1 files in {args.reads_dir}") + results = batch.batch_export(reports, args.output, fmt="fasta" if args.fasta else "fastq") + failed = 0 + for source, _dest, error in results: + if error: + failed += 1 + print(f"ab1kit: {source.name}: {error}", file=sys.stderr) + print(f"exported {len(results) - failed} of {len(results)} reads to {args.output}") + return 1 if failed else 0 + + +def _build_parser() -> argparse.ArgumentParser: + parser = argparse.ArgumentParser(prog="ab1kit") + sub = parser.add_subparsers(dest="command", required=True) + + v = sub.add_parser("verify-clones", help="verify clones against a construct") + v.add_argument("--construct", required=True, help="FASTA, GenBank or SnapGene file") + v.add_argument("--region", help="A-B, 1-based inclusive (default: whole construct)") + v.add_argument("--linear", action="store_true", help="treat the construct as linear") + v.add_argument("--pattern", help="regex with named groups 'clone' and 'primer'") + v.add_argument("--min-q", type=int, default=20) + v.add_argument("--het-ratio", type=float, default=0.40) + v.add_argument("reads_dir", metavar="READS_DIR") + v.add_argument("-o", "--output", required=True, help="report: .xlsx or .csv") + v.set_defaults(func=_verify_clones) + + q = sub.add_parser("qc", help="quality summary of every .ab1 in a folder") + q.add_argument("reads_dir", metavar="READS_DIR") + q.add_argument("-o", "--output", help="CSV file (default: stdout)") + q.set_defaults(func=_qc) + + e = sub.add_parser("export", help="export trimmed reads") + e.add_argument("reads_dir", metavar="READS_DIR") + e.add_argument("--trim", action="store_true") + fmt = e.add_mutually_exclusive_group() + fmt.add_argument("--fasta", action="store_true") + fmt.add_argument("--fastq", action="store_true", help="(default)") + e.add_argument("-o", "--output", required=True, metavar="DIR") + e.set_defaults(func=_export) + return parser + + +def _run_command(argv: list[str]) -> int: + _prepare_streams() + try: + args = _build_parser().parse_args(argv) + except SystemExit as exc: # argparse usage errors and --help + return exc.code if isinstance(exc.code, int) else 2 + try: + return args.func(args) + except CliError as exc: + print(f"ab1kit: {exc}", file=sys.stderr) + return 2 + except OSError as exc: + print(f"ab1kit: {exc}", file=sys.stderr) + return 2 def main(argv: list[str] | None = None) -> int: + args = list(sys.argv[1:] if argv is None else argv) + if args and args[0] in COMMANDS: + return _run_command(args) from ui.main_window import run - return run(argv if argv is not None else sys.argv[1:]) + return run(args) if __name__ == "__main__": diff --git a/pyproject.toml b/pyproject.toml index 94ea497..e5ac9db 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta" [project] name = "ab1kit" -version = "1.0.0" +version = "1.1.0" description = "Open-source desktop tool for viewing, editing and analyzing Sanger sequencing chromatograms (.ab1)" readme = "README.md" license = { file = "LICENSE" } diff --git a/tests/test_cli.py b/tests/test_cli.py new file mode 100644 index 0000000..6ff264a --- /dev/null +++ b/tests/test_cli.py @@ -0,0 +1,146 @@ +"""Command-line subcommands: verify-clones, qc, export (thin shell over the core).""" + +import shutil +import subprocess +import sys +from pathlib import Path + +import pytest +from Bio import SeqIO +from openpyxl import load_workbook + +import chrom_cli +from clone_fixtures import COI_GB, DATA, coi_reference, mutate + +ROOT = Path(__file__).resolve().parent.parent +READS = ["Achl_ACHLO006-09_1_F.ab1", "Achl_ACHLO006-09_2_R.ab1", + "Achl_ACHLO007-09_1_F.ab1", "Achl_ACHLO007-09_2_R.ab1"] + + +@pytest.fixture +def reads_dir(tmp_path: Path) -> Path: + d = tmp_path / "Данные клоны" + d.mkdir() + for name in READS: + shutil.copy(DATA / "real" / name, d / name) + return d + + +def test_verify_clones_xlsx(reads_dir: Path, tmp_path: Path, capsys) -> None: + out = tmp_path / "отчёт.xlsx" + code = chrom_cli.main(["verify-clones", "--construct", str(COI_GB), str(reads_dir), + "-o", str(out)]) + assert code == 0 + book = load_workbook(out) + assert book.sheetnames == ["Clones", "Differences"] + shown = capsys.readouterr().out + assert "Achl_ACHLO006-09" in shown and "ok" in shown + + +def test_verify_clones_csv_region_and_errors(reads_dir: Path, tmp_path: Path, capsys) -> None: + ref = tmp_path / "mutated.fasta" + seq = coi_reference() + ref.write_text(">mut\n" + mutate(seq, 250, "sub", "A" if seq[250] != "A" else "C") + "\n") + out = tmp_path / "rep.csv" + code = chrom_cli.main(["verify-clones", "--construct", str(ref), "--region", "7-647", + "--linear", "--min-q", "20", "--het-ratio", "0.4", + str(reads_dir), "-o", str(out)]) + assert code == 1 # every clone carries the planted difference + assert "errors" in out.read_text(encoding="utf-8") + diffs = tmp_path / "rep_differences.csv" + assert diffs.exists() and "251" in diffs.read_text(encoding="utf-8") + assert "errors" in capsys.readouterr().out + + +def test_verify_clones_input_errors(reads_dir: Path, tmp_path: Path, capsys) -> None: + empty = tmp_path / "empty" + empty.mkdir() + out = tmp_path / "x.xlsx" + base = ["verify-clones", "-o", str(out)] + assert chrom_cli.main(base + ["--construct", str(COI_GB), str(empty)]) == 2 + bad = tmp_path / "bad.gb" + bad.write_text("not a sequence file") + assert chrom_cli.main(base + ["--construct", str(bad), str(reads_dir)]) == 2 + assert chrom_cli.main(base + ["--construct", str(COI_GB), "--region", "9-3", + "--linear", str(reads_dir)]) == 2 + assert chrom_cli.main(base + ["--construct", str(COI_GB), "--region", "abc", + str(reads_dir)]) == 2 + assert chrom_cli.main(base + ["--construct", str(COI_GB), "--pattern", "(", + str(reads_dir)]) == 2 + assert chrom_cli.main(base + ["--construct", str(COI_GB), + str(tmp_path / "missing")]) == 2 + assert capsys.readouterr().err.count("ab1kit:") >= 6 + assert not out.exists() + + +def test_unassigned_files_reported_on_stderr(reads_dir: Path, tmp_path: Path, capsys) -> None: + shutil.copy(DATA / "real" / READS[0], reads_dir / "!.ab1") + out = tmp_path / "r.csv" + chrom_cli.main(["verify-clones", "--construct", str(COI_GB), str(reads_dir), "-o", str(out)]) + assert "!.ab1" in capsys.readouterr().err + + +def test_qc_stdout_and_file(reads_dir: Path, tmp_path: Path, capsys) -> None: + assert chrom_cli.main(["qc", str(reads_dir)]) == 0 + printed = capsys.readouterr().out + assert printed.startswith("file;length;mean_q") and READS[0] in printed + out = tmp_path / "qc.csv" + assert chrom_cli.main(["qc", str(reads_dir), "-o", str(out)]) == 0 + assert READS[1] in out.read_text(encoding="utf-8") + + +def test_export(reads_dir: Path, tmp_path: Path) -> None: + out = tmp_path / "вывод" + assert chrom_cli.main(["export", str(reads_dir), "--trim", "--fasta", "-o", str(out)]) == 0 + files = sorted(p.name for p in out.glob("*.trimmed.fasta")) + assert len(files) == len(READS) + out2 = tmp_path / "fq" + assert chrom_cli.main(["export", str(reads_dir), "--trim", "-o", str(out2)]) == 0 + assert len(list(out2.glob("*.trimmed.fastq"))) == len(READS) + + +@pytest.mark.parametrize("argv", [[], ["x.ab1"]]) +def test_gui_path_unchanged(monkeypatch, argv) -> None: + import ui.main_window as mw + seen = [] + monkeypatch.setattr(mw, "run", lambda a: seen.append(a) or 0) + assert chrom_cli.main(argv) == 0 + assert seen == [argv] + + +def _run_cli(*args, **kw): + return subprocess.run([sys.executable, "-m", "chrom_cli", *map(str, args)], + capture_output=True, cwd=ROOT, **kw) + + +def test_cli_does_not_import_qt_and_survives_legacy_console(reads_dir: Path, tmp_path: Path) -> None: + out = tmp_path / "r.csv" + code = ( + "import sys, chrom_cli\n" + f"rc = chrom_cli.main(['verify-clones','--construct',r'{COI_GB}',r'{reads_dir}','-o',r'{out}'])\n" + "assert not any(m == 'PySide6' or m.startswith('PySide6.') for m in sys.modules), 'Qt imported'\n" + "sys.exit(rc)\n" + ) + env = {**__import__("os").environ, "PYTHONIOENCODING": "cp1251"} + env.pop("PYTHONUTF8", None) + proc = subprocess.run([sys.executable, "-c", code], capture_output=True, cwd=ROOT, env=env) + assert proc.returncode == 0, proc.stderr.decode("utf-8", "replace") + + +def test_cyrillic_paths_on_legacy_console(tmp_path: Path) -> None: + d = tmp_path / "Данные клоны" + d.mkdir() + for name in READS[:2]: + shutil.copy(DATA / "real" / name, d / name) + shutil.copy(DATA / "real" / READS[0], d / "Клон ж_1_F.ab1") + shutil.copy(DATA / "real" / READS[0], d / "Ё!.ab1") + env = {**__import__("os").environ, "PYTHONIOENCODING": "cp437"} # cannot encode Cyrillic + env.pop("PYTHONUTF8", None) + proc = subprocess.run( + [sys.executable, "-m", "chrom_cli", "verify-clones", "--construct", str(COI_GB), + str(d), "-o", str(tmp_path / "o.csv")], + capture_output=True, cwd=ROOT, env=env) + assert proc.returncode in (0, 1), proc.stderr.decode("utf-8", "replace") + assert b"Traceback" not in proc.stderr + assert "Клон ж".encode() in proc.stdout # utf-8 forced regardless of the console + assert "Ё!.ab1".encode() in proc.stderr From 022d969a8f6771d3a78c368db46e7510a2a99e86 Mon Sep 17 00:00:00 2001 From: Aleksey Drobin <43707931+adrobi@users.noreply.github.com> Date: Fri, 30 Oct 2026 16:41:42 +0300 Subject: [PATCH 32/44] CLI review fixes: console code page, early -o check, README exit-code and verdict notes Co-Authored-By: Claude Sonnet 5.5 --- README.md | 43 +++++++++++++++++++++++++---------------- chrom_cli.py | 47 ++++++++++++++++++++++++++++----------------- tests/test_cli.py | 49 +++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 105 insertions(+), 34 deletions(-) diff --git a/README.md b/README.md index 85de459..f954d60 100644 --- a/README.md +++ b/README.md @@ -67,27 +67,30 @@ origin); GenBank/SnapGene files take the topology from the file; the *Circular* checkbox (`--linear` on the command line) overrides the topology. **File names.** Reads are grouped by name as `_`: the primer is -the last known primer token (`F`, `R`, `T7`, `SP6`, `M13F`, `pUC-F`, ...), the -clone is what precedes it, minus an order digit and a leading plate well: -`A05_clone3_2_R.ab1` is clone `clone3`, primer `R`; `Achl_ACHLO006-09_1_F.ab1` -is clone `Achl_ACHLO006-09`. Files whose name yields no clone stay unassigned -and are skipped. For other conventions give a regular expression with named -groups `clone` and `primer` that matches the whole file name without the -extension, e.g. `(?P\d+)-(?P[A-Za-z0-9]+)`. - -**Verdicts.** +the last known primer token (`F`, `R`, `T7`, `SP6`, `M13F`, `pUC-F`, ...); if +the name has none, the last token is taken as the primer. The clone is what +precedes the primer, minus a single-digit order token and a leading plate well +(`A05`), the well being stripped only when another clone token follows it +(`B2_F` is clone `B2`). `A05_clone3_2_R.ab1` is clone `clone3`, primer `R`; +`Achl_ACHLO006-09_1_F.ab1` is clone `Achl_ACHLO006-09`. Files whose name yields +no clone stay unassigned and are skipped. For other conventions give a regular +expression with named groups `clone` and `primer` that matches the whole file +name without the extension, e.g. `(?P\d+)-(?P[A-Za-z0-9]+)`. + +**Verdicts.** Checked in this order, the first match wins: | Verdict | Meaning | | --- | --- | -| `ok` (green) | the region is covered and no reliable difference from the construct | -| `errors` (red) | at least one difference in the region, supported by a read of Q >= min Q | -| `incomplete` (yellow) | no difference, but part of the region is not covered by any read | -| `mixed` (purple) | at least 3 positions (default) with a double peak: probably a mixed colony | | `no_data` (grey) | no read of the clone aligned to the construct | +| `mixed` (purple) | at least 3 positions (default) with a double peak: probably a mixed colony | +| `errors` (red) | at least one difference in the region that is confirmed or disputed | +| `incomplete` (yellow) | no such difference, but part of the region is not covered by any read | +| `ok` (green) | the region is fully covered and shows no reliable difference | -A difference is *confirmed* (only supporting reads), *disputed* (another read -shows the reference there) or *low quality* (seen only below min Q; does not -change the verdict). Defaults: min Q 20, double-peak ratio 0.40. +A difference is *confirmed* (only supporting reads, Q >= min Q), *disputed* +(another read shows the reference there) or *low quality* (seen only below +min Q). Both confirmed and disputed differences give `errors`; only low-quality +ones do not change the verdict. Defaults: min Q 20, double-peak ratio 0.40. **Command line** (no GUI, no Qt needed): @@ -102,6 +105,14 @@ is `ok`, 1 if none is, 2 on invalid input; `-o report.csv` writes `report.csv` and `report_differences.csv`. Options: `--region A-B` (1-based, inclusive), `--linear`, `--pattern REGEX`, `--min-q N`, `--het-ratio X`. +The exit-code contract applies to the `ab1kit` command installed with pip. The +Windows release `ab1kit.exe` is a windowed program: the shell returns to the +prompt immediately, so exit codes and output ordering are unreliable and output +may appear after the prompt. Wait for it explicitly: `start /wait ab1kit.exe +verify-clones ...` (cmd), or `Start-Process -Wait -NoNewWindow` / +`(Start-Process ab1kit.exe -ArgumentList ... -Wait -PassThru).ExitCode` +(PowerShell). + ## Getting started Requires Python 3.11+: diff --git a/chrom_cli.py b/chrom_cli.py index 9d564b8..798efaf 100644 --- a/chrom_cli.py +++ b/chrom_cli.py @@ -16,21 +16,32 @@ class CliError(Exception): """Bad input: reported on stderr, exit code 2.""" +def _attach_console() -> None: + """Frozen windowed build: reuse the parent console, writing in its own code page.""" + try: + import ctypes + + kernel32 = ctypes.windll.kernel32 + if not kernel32.AttachConsole(-1): + return + encoding = f"cp{kernel32.GetConsoleOutputCP()}" # never change the user's code page + if sys.stdout is None: + sys.stdout = open("CONOUT$", "w", encoding=encoding, errors="replace") + if sys.stderr is None: + sys.stderr = open("CONOUT$", "w", encoding=encoding, errors="replace") + except (AttributeError, OSError): + pass + + def _prepare_streams() -> None: - """Print Cyrillic safely on any console; attach to the parent console if windowed.""" - if sys.stdout is None or sys.stderr is None: # frozen windowed build - try: - import ctypes - - if ctypes.windll.kernel32.AttachConsole(-1): - if sys.stdout is None: - sys.stdout = open("CONOUT$", "w", encoding="utf-8", errors="replace") - if sys.stderr is None: - sys.stderr = open("CONOUT$", "w", encoding="utf-8", errors="replace") - except (AttributeError, OSError): - pass + """Print Cyrillic safely on any console.""" + attached = sys.stdout is None or sys.stderr is None + if attached: + _attach_console() for stream in (sys.stdout, sys.stderr): - if stream is not None and hasattr(stream, "reconfigure"): + # an attached console stream keeps the console's own code page + if stream is not None and hasattr(stream, "reconfigure") and not ( + attached and getattr(stream, "name", "") == "CONOUT$"): stream.reconfigure(encoding="utf-8", errors="replace") @@ -62,6 +73,9 @@ def _verify_clones(args: argparse.Namespace) -> int: raise CliError(f"cannot load construct: {exc}") from exc if args.linear: construct = construct.with_circular(False) + out = Path(args.output) + if out.suffix.lower() not in (".xlsx", ".csv"): + raise CliError("report file must end in .xlsx or .csv") region = _parse_region(args.region) if args.region else None try: check_region(region, len(construct.seq), construct.circular) @@ -78,15 +92,12 @@ def _verify_clones(args: argparse.Namespace) -> int: params = VerifyParams(min_q=args.min_q, het_ratio=args.het_ratio) reports = verify_all(construct, region, grouping, params) - out = Path(args.output) if out.suffix.lower() == ".xlsx": clone_report_xlsx(out, reports, construct.name) - elif out.suffix.lower() == ".csv": + else: out.write_text(clones_csv(reports), encoding="utf-8") out.with_name(f"{out.stem}_differences.csv").write_text( differences_csv(reports), encoding="utf-8") - else: - raise CliError("report file must end in .xlsx or .csv") width = max(len(r.clone) for r in reports) for r in reports: @@ -103,7 +114,7 @@ def _qc(args: argparse.Namespace) -> int: if args.output: Path(args.output).write_text(text, encoding="utf-8") else: - sys.stdout.write(text) + print(text, end="") return 0 diff --git a/tests/test_cli.py b/tests/test_cli.py index 6ff264a..1963093 100644 --- a/tests/test_cli.py +++ b/tests/test_cli.py @@ -144,3 +144,52 @@ def test_cyrillic_paths_on_legacy_console(tmp_path: Path) -> None: assert b"Traceback" not in proc.stderr assert "Клон ж".encode() in proc.stdout # utf-8 forced regardless of the console assert "Ё!.ab1".encode() in proc.stderr + + +def test_attached_console_uses_console_code_page(monkeypatch) -> None: + import builtins + import ctypes + import types + + kernel32 = types.SimpleNamespace(AttachConsole=lambda pid: 1, GetConsoleOutputCP=lambda: 866, + SetConsoleOutputCP=lambda cp: pytest.fail("must not change")) + monkeypatch.setattr(ctypes, "windll", types.SimpleNamespace(kernel32=kernel32), raising=False) + opened = [] + monkeypatch.setattr(builtins, "open", lambda *a, **k: opened.append((a, k)) or object()) + monkeypatch.setattr(sys, "stdout", None) + monkeypatch.setattr(sys, "stderr", None) + chrom_cli._attach_console() + assert [a[0] for a, _ in opened] == ["CONOUT$", "CONOUT$"] + assert all(k["encoding"] == "cp866" and k["errors"] == "replace" for _, k in opened) + + +def test_qc_without_stdout(monkeypatch, reads_dir: Path) -> None: + monkeypatch.setattr(sys, "stdout", None) + assert chrom_cli.main(["qc", str(reads_dir)]) == 0 # nowhere to print, must not crash + + +@pytest.mark.parametrize("text, expected", [("1-10", (0, 10)), ("600-50", (599, 50))]) +def test_parse_region(text, expected) -> None: + assert chrom_cli._parse_region(text) == expected + + +@pytest.mark.parametrize("text", ["abc", "5", "0-10", "-3-4", "1-2-3", ""]) +def test_parse_region_rejects(text) -> None: + with pytest.raises(chrom_cli.CliError): + chrom_cli._parse_region(text) + + +def test_wrap_region_circular_ok_linear_rejected(reads_dir: Path, tmp_path: Path) -> None: + base = ["verify-clones", "--construct", str(COI_GB), "--region", "600-50", str(reads_dir)] + assert chrom_cli.main(base + ["--linear", "-o", str(tmp_path / "a.csv")]) == 2 + ref = tmp_path / "circ.fasta" + ref.write_text(">c\n" + coi_reference() + "\n") # FASTA defaults to circular + base[2] = str(ref) + assert chrom_cli.main(base + ["-o", str(tmp_path / "b.csv")]) in (0, 1) + + +def test_bad_output_extension_rejected_before_verifying(reads_dir: Path, tmp_path: Path, monkeypatch) -> None: + import chrom_core.clones as clones + monkeypatch.setattr(clones, "verify_all", lambda *a, **k: pytest.fail("ran verify_all")) + assert chrom_cli.main(["verify-clones", "--construct", str(COI_GB), str(reads_dir), + "-o", str(tmp_path / "r.txt")]) == 2 From 77ec9d301dee9732470bfd83ad104985057190bd Mon Sep 17 00:00:00 2001 From: Aleksey Drobin <43707931+adrobi@users.noreply.github.com> Date: Fri, 30 Oct 2026 16:43:43 +0300 Subject: [PATCH 33/44] CLI: console code page fallback to utf-8, all-or-nothing console attach Co-Authored-By: Claude Sonnet 5.5 --- chrom_cli.py | 34 +++++++++++++++++++++++++++------- tests/test_cli.py | 40 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 67 insertions(+), 7 deletions(-) diff --git a/chrom_cli.py b/chrom_cli.py index 798efaf..9cb4cb5 100644 --- a/chrom_cli.py +++ b/chrom_cli.py @@ -16,21 +16,41 @@ class CliError(Exception): """Bad input: reported on stderr, exit code 2.""" +def _console_encoding(code_page: int) -> str: + """Python codec for a console code page; utf-8 when unknown (0 = query failed).""" + import codecs + + if code_page: + try: + codecs.lookup(f"cp{code_page}") + return f"cp{code_page}" + except LookupError: + pass + return "utf-8" + + def _attach_console() -> None: """Frozen windowed build: reuse the parent console, writing in its own code page.""" + opened = [] try: import ctypes kernel32 = ctypes.windll.kernel32 if not kernel32.AttachConsole(-1): return - encoding = f"cp{kernel32.GetConsoleOutputCP()}" # never change the user's code page - if sys.stdout is None: - sys.stdout = open("CONOUT$", "w", encoding=encoding, errors="replace") - if sys.stderr is None: - sys.stderr = open("CONOUT$", "w", encoding=encoding, errors="replace") - except (AttributeError, OSError): - pass + encoding = _console_encoding(kernel32.GetConsoleOutputCP()) # never change it + wanted = [name for name in ("stdout", "stderr") if getattr(sys, name) is None] + for name in wanted: + opened.append((name, open("CONOUT$", "w", encoding=encoding, errors="replace"))) + except (AttributeError, OSError, LookupError): + for _name, stream in opened: # all or nothing: keep both streams consistent + try: + stream.close() + except (AttributeError, OSError): + pass + return + for name, stream in opened: + setattr(sys, name, stream) def _prepare_streams() -> None: diff --git a/tests/test_cli.py b/tests/test_cli.py index 1963093..78e9e0e 100644 --- a/tests/test_cli.py +++ b/tests/test_cli.py @@ -193,3 +193,43 @@ def test_bad_output_extension_rejected_before_verifying(reads_dir: Path, tmp_pat monkeypatch.setattr(clones, "verify_all", lambda *a, **k: pytest.fail("ran verify_all")) assert chrom_cli.main(["verify-clones", "--construct", str(COI_GB), str(reads_dir), "-o", str(tmp_path / "r.txt")]) == 2 + + +@pytest.mark.parametrize("code_page", [0, 99999]) +def test_attached_console_unknown_code_page_falls_back_to_utf8(monkeypatch, code_page) -> None: + import builtins + import ctypes + import types + + kernel32 = types.SimpleNamespace(AttachConsole=lambda pid: 1, + GetConsoleOutputCP=lambda: code_page) + monkeypatch.setattr(ctypes, "windll", types.SimpleNamespace(kernel32=kernel32), raising=False) + opened = [] + monkeypatch.setattr(builtins, "open", lambda *a, **k: opened.append(k) or object()) + monkeypatch.setattr(sys, "stdout", None) + monkeypatch.setattr(sys, "stderr", None) + chrom_cli._attach_console() + assert len(opened) == 2 + assert all(k["encoding"] == "utf-8" and k["errors"] == "replace" for k in opened) + + +def test_attached_console_is_all_or_nothing(monkeypatch) -> None: + import builtins + import ctypes + import types + + kernel32 = types.SimpleNamespace(AttachConsole=lambda pid: 1, GetConsoleOutputCP=lambda: 866) + monkeypatch.setattr(ctypes, "windll", types.SimpleNamespace(kernel32=kernel32), raising=False) + calls = [] + + def fake_open(*a, **k): + calls.append(a) + if len(calls) == 2: + raise OSError("no console") + return types.SimpleNamespace(close=lambda: None) + + monkeypatch.setattr(builtins, "open", fake_open) + monkeypatch.setattr(sys, "stdout", None) + monkeypatch.setattr(sys, "stderr", None) + chrom_cli._attach_console() + assert sys.stdout is None and sys.stderr is None From 2296531116cccaba93b6269edff749c69ee82ddb Mon Sep 17 00:00:00 2001 From: Aleksey Drobin <43707931+adrobi@users.noreply.github.com> Date: Fri, 30 Oct 2026 16:48:32 +0300 Subject: [PATCH 34/44] App icon: SVG source, PNG/ICO, window and exe icon Co-Authored-By: Claude Sonnet 5.5 --- README.md | 2 +- ab1kit.spec | 1 + pyproject.toml | 2 +- scripts/make_icon.py | 78 ++++++++++++++++++++++++++++++++++++++++ tests/test_app_icon.py | 62 ++++++++++++++++++++++++++++++++ ui/icons/app/ab1kit.ico | Bin 0 -> 29202 bytes ui/icons/app/ab1kit.png | Bin 0 -> 13985 bytes ui/icons/app/ab1kit.svg | 29 +++++++++++++++ ui/main_window.py | 3 +- ui/theme.py | 7 ++++ 10 files changed, 181 insertions(+), 3 deletions(-) create mode 100644 scripts/make_icon.py create mode 100644 tests/test_app_icon.py create mode 100644 ui/icons/app/ab1kit.ico create mode 100644 ui/icons/app/ab1kit.png create mode 100644 ui/icons/app/ab1kit.svg diff --git a/README.md b/README.md index f954d60..dc1a22d 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# ab1kit +# ab1kit Open-source desktop tool for viewing, editing and analyzing Sanger sequencing chromatograms (`.ab1` files) — a free, offline alternative to FinchTV / Chromas diff --git a/ab1kit.spec b/ab1kit.spec index ca59ae4..debc665 100644 --- a/ab1kit.spec +++ b/ab1kit.spec @@ -31,4 +31,5 @@ exe = EXE( strip=False, upx=False, console=False, + icon="ui/icons/app/ab1kit.ico", ) diff --git a/pyproject.toml b/pyproject.toml index e5ac9db..f6b35ad 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -26,7 +26,7 @@ packages = ["chrom_core", "ui", "ui.read_view", "ui.construct"] py-modules = ["chrom_cli", "i18n", "translations_en"] [tool.setuptools.package-data] -ui = ["style.qss", "style_dark.qss", "icons/*.svg", "icons/LICENSE", "icons/README.md"] +ui = ["style.qss", "style_dark.qss", "icons/*.svg", "icons/LICENSE", "icons/README.md", "icons/app/*"] [tool.pytest.ini_options] testpaths = ["tests"] diff --git a/scripts/make_icon.py b/scripts/make_icon.py new file mode 100644 index 0000000..3a4a7c2 --- /dev/null +++ b/scripts/make_icon.py @@ -0,0 +1,78 @@ +"""Regenerate ui/icons/app/ab1kit.png and ab1kit.ico from ab1kit.svg. + +Usage: python scripts/make_icon.py [--out DIR] + +The SVG is the source of truth (letters are vector paths, so no fonts are +needed). The ICO holds PNG-compressed entries, assembled here without extra +dependencies. +""" + +from __future__ import annotations + +import argparse +import os +import struct +import sys +from pathlib import Path + +os.environ.setdefault("QT_QPA_PLATFORM", "offscreen") + +from PySide6.QtCore import QBuffer, QByteArray, QIODevice +from PySide6.QtGui import QGuiApplication, QImage, QPainter +from PySide6.QtSvg import QSvgRenderer + +APP_ICONS = Path(__file__).resolve().parent.parent / "ui" / "icons" / "app" +ICO_SIZES = (16, 24, 32, 48, 64, 128, 256) + + +def render(renderer: QSvgRenderer, size: int) -> QImage: + image = QImage(size, size, QImage.Format.Format_ARGB32) + image.fill(0) + painter = QPainter(image) + painter.setRenderHints(QPainter.RenderHint.Antialiasing + | QPainter.RenderHint.SmoothPixmapTransform) + renderer.render(painter) + painter.end() + return image + + +def png_bytes(image: QImage) -> bytes: + data = QByteArray() + buf = QBuffer(data) + buf.open(QIODevice.OpenModeFlag.WriteOnly) + image.save(buf, "PNG") + buf.close() + return bytes(data) + + +def build_ico(entries: list[tuple[int, bytes]]) -> bytes: + header = struct.pack("= 256 else size + directory += struct.pack(" int: + parser = argparse.ArgumentParser(description=__doc__.splitlines()[0]) + parser.add_argument("--out", type=Path, default=APP_ICONS, help="output folder") + args = parser.parse_args(argv) + + QGuiApplication.instance() or QGuiApplication([]) + renderer = QSvgRenderer(str(APP_ICONS / "ab1kit.svg")) + if not renderer.isValid(): + print("invalid SVG", file=sys.stderr) + return 1 + args.out.mkdir(parents=True, exist_ok=True) + (args.out / "ab1kit.png").write_bytes(png_bytes(render(renderer, 256))) + entries = [(s, png_bytes(render(renderer, s))) for s in ICO_SIZES] + (args.out / "ab1kit.ico").write_bytes(build_ico(entries)) + return 0 + + +if __name__ == "__main__": + sys.exit(main()) diff --git a/tests/test_app_icon.py b/tests/test_app_icon.py new file mode 100644 index 0000000..0302dc7 --- /dev/null +++ b/tests/test_app_icon.py @@ -0,0 +1,62 @@ +"""App icon: committed assets, regeneration script, window icon.""" + +import os + +os.environ.setdefault("QT_QPA_PLATFORM", "offscreen") + +import struct +import subprocess +import sys +from pathlib import Path + +import pytest + +ROOT = Path(__file__).resolve().parent.parent +APP_ICONS = ROOT / "ui" / "icons" / "app" + + +def test_png_and_ico_exist(): + assert (APP_ICONS / "ab1kit.png").is_file() + assert (APP_ICONS / "ab1kit.ico").is_file() + + +def test_ico_has_required_sizes(): + data = (APP_ICONS / "ab1kit.ico").read_bytes() + reserved, kind, count = struct.unpack_from("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 R8GTKh|9-dle}AO+e*lZ#UMc_p literal 0 HcmV?d00001 diff --git a/ui/icons/app/ab1kit.png b/ui/icons/app/ab1kit.png new file mode 100644 index 0000000000000000000000000000000000000000..a772ebba6c519425365e1b2fca791a332b0b3b60 GIT binary patch literal 13985 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 MAJpV(WX(hW52$-%>Hq)$ literal 0 HcmV?d00001 diff --git a/ui/icons/app/ab1kit.svg b/ui/icons/app/ab1kit.svg new file mode 100644 index 0000000..29aa796 --- /dev/null +++ b/ui/icons/app/ab1kit.svg @@ -0,0 +1,29 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/ui/main_window.py b/ui/main_window.py index 00c430f..fb8c259 100644 --- a/ui/main_window.py +++ b/ui/main_window.py @@ -27,7 +27,7 @@ from ui.read_view import ReadView from ui.status import bind_icon from ui.tasks import Task, run_task -from ui.theme import app_qss +from ui.theme import app_icon, app_qss try: VERSION = pkg_version("ab1kit") @@ -65,6 +65,7 @@ def __init__(self, config: AppConfig | None = None) -> None: self.config = config or load_config() set_language(self.config.language) + QApplication.instance().setWindowIcon(app_icon()) self.setWindowTitle("ab1kit") self.resize(1200, 780) self.read_view = ReadView(self.config, self._start_task) diff --git a/ui/theme.py b/ui/theme.py index 49e9512..c50f084 100644 --- a/ui/theme.py +++ b/ui/theme.py @@ -7,6 +7,8 @@ from functools import lru_cache from pathlib import Path +from PySide6.QtGui import QIcon + LIGHT = { "bg": "#ffffff", "panel": "#f3f3f3", @@ -63,6 +65,11 @@ def resource_dir() -> Path: return Path(frozen) / "ui" if frozen else Path(__file__).resolve().parent +def app_icon() -> QIcon: + """The application icon (``ui/icons/app/ab1kit.png``), frozen-safe.""" + return QIcon(str(resource_dir() / "icons" / "app" / "ab1kit.png")) + + @lru_cache(maxsize=2) def _read_qss(dark: bool) -> str: name = "style_dark.qss" if dark else "style.qss" From e6165d1eb5ab0ffd8cd454fcd42cffe2caab727f Mon Sep 17 00:00:00 2001 From: Aleksey Drobin <43707931+adrobi@users.noreply.github.com> Date: Fri, 30 Oct 2026 16:50:39 +0300 Subject: [PATCH 35/44] App icon tests: compare decoded pixels, not bytes Co-Authored-By: Claude Sonnet 5.5 --- scripts/make_icon.py | 3 +++ tests/test_app_icon.py | 42 ++++++++++++++++++++++++++++++++++++++---- ui/main_window.py | 2 ++ 3 files changed, 43 insertions(+), 4 deletions(-) diff --git a/scripts/make_icon.py b/scripts/make_icon.py index 3a4a7c2..9b620d2 100644 --- a/scripts/make_icon.py +++ b/scripts/make_icon.py @@ -5,6 +5,9 @@ The SVG is the source of truth (letters are vector paths, so no fonts are needed). The ICO holds PNG-compressed entries, assembled here without extra dependencies. + +Note: the SVG letter outlines were extracted once from Consolas Bold 22px and are +baked in as paths; this script does not touch them. """ from __future__ import annotations diff --git a/tests/test_app_icon.py b/tests/test_app_icon.py index 0302dc7..4dbc851 100644 --- a/tests/test_app_icon.py +++ b/tests/test_app_icon.py @@ -10,6 +10,7 @@ from pathlib import Path import pytest +from PySide6.QtGui import QIcon, QImage ROOT = Path(__file__).resolve().parent.parent APP_ICONS = ROOT / "ui" / "icons" / "app" @@ -37,13 +38,45 @@ def test_svg_has_no_text_elements(): assert " list[tuple[int, bytes]]: + count = struct.unpack_from(" QImage: + image = QImage.fromData(blob, "PNG") + assert not image.isNull() + return image.convertToFormat(QImage.Format.Format_ARGB32) + + +def _assert_pixels_close(a: QImage, b: QImage) -> None: + """Max per-channel diff <= 2, except at most 0.1% outlier pixels.""" + assert (a.width(), a.height()) == (b.width(), b.height()) + outliers = 0 + for y in range(a.height()): + for x in range(a.width()): + pa, pb = a.pixel(x, y), b.pixel(x, y) + if any(abs(((pa >> s) & 255) - ((pb >> s) & 255)) > 2 for s in (0, 8, 16, 24)): + outliers += 1 + assert outliers <= max(1, a.width() * a.height() // 1000) + + +def test_make_icon_regenerates_same_pixels(tmp_path): env = {k: v for k, v in os.environ.items() if k != "QT_QPA_FONTDIR"} env["QT_QPA_PLATFORM"] = "offscreen" subprocess.run([sys.executable, str(ROOT / "scripts" / "make_icon.py"), "--out", str(tmp_path)], check=True, env=env, cwd=ROOT) - assert (tmp_path / "ab1kit.png").read_bytes() == (APP_ICONS / "ab1kit.png").read_bytes() - assert (tmp_path / "ab1kit.ico").read_bytes() == (APP_ICONS / "ab1kit.ico").read_bytes() + _assert_pixels_close(_decode((tmp_path / "ab1kit.png").read_bytes()), + _decode((APP_ICONS / "ab1kit.png").read_bytes())) + new = _ico_entries((tmp_path / "ab1kit.ico").read_bytes()) + old = _ico_entries((APP_ICONS / "ab1kit.ico").read_bytes()) + assert [size for size, _ in new] == [size for size, _ in old] + for (_, blob_new), (_, blob_old) in zip(new, old): + _assert_pixels_close(_decode(blob_new), _decode(blob_old)) def test_main_window_sets_application_icon(monkeypatch): @@ -53,10 +86,11 @@ def test_main_window_sets_application_icon(monkeypatch): monkeypatch.setattr("ui.main_window.save_config", lambda *a, **k: None) from ui.main_window import MainWindow - app.setWindowIcon(__import__("PySide6.QtGui", fromlist=["QIcon"]).QIcon()) + app.setWindowIcon(QIcon()) window = MainWindow() icon = app.windowIcon() assert not icon.isNull() pix = icon.pixmap(32, 32) assert (pix.width(), pix.height()) == (32, 32) + assert pix.toImage().convertToFormat(QImage.Format.Format_ARGB32).pixelColor(16, 16).alpha() > 0 window.close() diff --git a/ui/main_window.py b/ui/main_window.py index fb8c259..8446515 100644 --- a/ui/main_window.py +++ b/ui/main_window.py @@ -65,6 +65,8 @@ def __init__(self, config: AppConfig | None = None) -> None: self.config = config or load_config() set_language(self.config.language) + # App-wide and idempotent; here (not only in run()) so directly constructed + # windows, e.g. in tests, carry the icon too. QApplication.instance().setWindowIcon(app_icon()) self.setWindowTitle("ab1kit") self.resize(1200, 780) From 12c770f31b633540c2cd484ed71ad082027200bb Mon Sep 17 00:00:00 2001 From: Aleksey Drobin <43707931+adrobi@users.noreply.github.com> Date: Fri, 30 Oct 2026 16:53:57 +0300 Subject: [PATCH 36/44] Release workflow: Windows and Linux builds with smoke test, single release job Co-Authored-By: Claude Sonnet 5.5 --- .github/workflows/release.yml | 105 +++++++++++++++++++++++++++++++--- CHANGELOG.md | 2 + README.md | 13 ++++- ab1kit.spec | 8 ++- 4 files changed, 116 insertions(+), 12 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 627a36c..16fca64 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -6,17 +6,41 @@ on: workflow_dispatch: jobs: - windows-exe: - runs-on: windows-latest + build: + name: build (${{ matrix.artifact }}) + runs-on: ${{ matrix.os }} + strategy: + fail-fast: false + matrix: + include: + - os: windows-latest + artifact: ab1kit-windows + file: dist/ab1kit.exe + - os: ubuntu-22.04 + artifact: ab1kit-linux-x86_64 + file: ab1kit-linux-x86_64.tar.gz permissions: - contents: write + contents: read + env: + QT_QPA_PLATFORM: offscreen steps: - uses: actions/checkout@v4 - uses: actions/setup-python@v5 with: python-version: "3.13" + - name: Install Qt runtime libraries (Linux) + if: runner.os == 'Linux' + run: | + sudo apt-get update + sudo apt-get install -y libegl1 libxkbcommon-x11-0 libxcb-cursor0 \ + libxcb-icccm4 libxcb-image0 libxcb-keysyms1 libxcb-randr0 \ + libxcb-render-util0 libxcb-shape0 libxcb-xinerama0 libxcb-xfixes0 libgl1 - run: python -m pip install -e ".[dev]" "pyinstaller==6.22.3" + - name: Run tests + run: python -m pytest -q + - name: Build exe (errors surfaced as annotations) + if: runner.os == 'Windows' shell: pwsh run: | python -m PyInstaller ab1kit.spec --noconfirm --workpath build-pyinstaller 2>&1 | @@ -26,13 +50,80 @@ jobs: Write-Host "::error::PyInstaller failed, log tail: $tail" exit 1 } + - name: Build binary (errors surfaced as annotations) + if: runner.os == 'Linux' + shell: bash + run: | + set -o pipefail + if ! python -m PyInstaller ab1kit.spec --noconfirm --workpath build-pyinstaller 2>&1 | tee build_log.txt; then + tail_log=$(tail -n 30 build_log.txt | tr '\n' '|') + echo "::error::PyInstaller failed, log tail: ${tail_log}" + exit 1 + fi + + - name: Smoke-test frozen exe (Windows) + if: runner.os == 'Windows' + shell: pwsh + run: | + New-Item -ItemType Directory -Force smoke/reads | Out-Null + Copy-Item tests/data/real/Achl_ACHLO006-09_*.ab1 smoke/reads/ + # The exe is windowed: Start-Process -Wait -PassThru is needed to get the exit code. + $p = Start-Process -FilePath dist/ab1kit.exe -Wait -PassThru -ArgumentList @( + "verify-clones", "--construct", "tests/data/refs/coi_HM417896.gb", + "smoke/reads", "-o", "smoke/report.xlsx") + if ($p.ExitCode -ne 0) { + Write-Host "::error::smoke test: ab1kit.exe verify-clones exited with $($p.ExitCode)" + exit 1 + } + if (-not (Test-Path smoke/report.xlsx)) { + Write-Host "::error::smoke test: smoke/report.xlsx was not created" + exit 1 + } + - name: Smoke-test frozen binary (Linux) + if: runner.os == 'Linux' + shell: bash + run: | + mkdir -p smoke/reads + cp tests/data/real/Achl_ACHLO006-09_*.ab1 smoke/reads/ + rc=0 + dist/ab1kit verify-clones --construct tests/data/refs/coi_HM417896.gb \ + smoke/reads -o smoke/report.xlsx || rc=$? + if [ "$rc" -ne 0 ]; then + echo "::error::smoke test: dist/ab1kit verify-clones exited with $rc" + exit 1 + fi + if [ ! -f smoke/report.xlsx ]; then + echo "::error::smoke test: smoke/report.xlsx was not created" + exit 1 + fi + + - name: Package tarball (Linux) + if: runner.os == 'Linux' + shell: bash + run: | + cp README.md LICENSE dist/ + tar -czf ab1kit-linux-x86_64.tar.gz -C dist ab1kit README.md LICENSE + - uses: actions/upload-artifact@v4 with: - name: ab1kit-windows - path: dist/ab1kit.exe + name: ${{ matrix.artifact }} + path: ${{ matrix.file }} + if-no-files-found: error + + release: + needs: build + if: startsWith(github.ref, 'refs/tags/') + runs-on: ubuntu-latest + permissions: + contents: write + steps: + - uses: actions/download-artifact@v4 + with: + path: artifacts - name: Create GitHub release - if: startsWith(github.ref, 'refs/tags/') uses: softprops/action-gh-release@v2 with: - files: dist/ab1kit.exe + files: | + artifacts/ab1kit-windows/ab1kit.exe + artifacts/ab1kit-linux-x86_64/ab1kit-linux-x86_64.tar.gz generate_release_notes: true diff --git a/CHANGELOG.md b/CHANGELOG.md index 5f4f894..ea2381e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -24,6 +24,8 @@ from the command line. - Background tasks with progress and cancel - Command-line subcommands `verify-clones`, `qc` and `export` (no Qt import) - Real-data test corpus (sangeranalyseR reads, COI and pUC19 references) +- Linux release build (`ab1kit-linux-x86_64.tar.gz`) alongside the Windows exe, built and smoke-tested by GitHub Actions +- Application icon (window and Windows exe) ### Changed - Refreshed UI: QSS theme, icons, one status palette everywhere diff --git a/README.md b/README.md index dc1a22d..290dc66 100644 --- a/README.md +++ b/README.md @@ -124,9 +124,16 @@ python -m venv .venv .venv/Scripts/ab1kit # launch the GUI ``` -`ab1kit` also accepts a file or folder argument. On Windows, a prebuilt -executable is available on the [Releases](https://github.com/adrobi/ab1kit/releases) -page. +`ab1kit` also accepts a file or folder argument. Prebuilt binaries are on the +[Releases](https://github.com/adrobi/ab1kit/releases) page: + +- **Windows:** `ab1kit.exe` (single file, no installation). +- **Linux (x86_64):** `ab1kit-linux-x86_64.tar.gz`. Unpack with + `tar -xzf ab1kit-linux-x86_64.tar.gz` and run `./ab1kit`. Built on Ubuntu + 22.04, so it needs glibc 2.35 or newer. The GUI needs the usual Qt runtime + libraries; on Debian/Ubuntu: + `sudo apt install libegl1 libxkbcommon-x11-0 libxcb-cursor0 libxcb-icccm4 libxcb-image0 libxcb-keysyms1 libxcb-randr0 libxcb-render-util0 libxcb-shape0 libxcb-xinerama0 libxcb-xfixes0 libgl1`. + The Linux binary prints CLI output to the terminal normally. ## Keyboard shortcuts diff --git a/ab1kit.spec b/ab1kit.spec index debc665..06ffbeb 100644 --- a/ab1kit.spec +++ b/ab1kit.spec @@ -1,9 +1,11 @@ # -*- mode: python ; coding: utf-8 -*- -"""PyInstaller spec for the ab1kit one-file Windows executable. +"""PyInstaller spec for the ab1kit one-file executable (Windows exe, Linux ELF). Build: pyinstaller ab1kit.spec --noconfirm """ +import sys + a = Analysis( ["chrom_cli.py"], pathex=[], @@ -30,6 +32,8 @@ exe = EXE( debug=False, strip=False, upx=False, + # console=False only matters on Windows/macOS; a Linux ELF keeps stdout. console=False, - icon="ui/icons/app/ab1kit.ico", + # .ico is a Windows/macOS-only option; PyInstaller does not use it on Linux. + icon="ui/icons/app/ab1kit.ico" if sys.platform == "win32" else None, ) From 8a549c3a928378438aad97995a9d43fc60ba5eea Mon Sep 17 00:00:00 2001 From: Aleksey Drobin <43707931+adrobi@users.noreply.github.com> Date: Fri, 30 Oct 2026 17:05:02 +0300 Subject: [PATCH 37/44] Clone verification: merge deletion runs into one difference (in-frame deletions) Co-Authored-By: Claude Opus 5.5 --- chrom_core/clones.py | 44 ++++++++++++++++++++++++++++++++------ chrom_core/effects.py | 7 +++--- tests/test_clone_verify.py | 42 ++++++++++++++++++++++++++++++++++++ tests/test_effects.py | 2 ++ 4 files changed, 85 insertions(+), 10 deletions(-) diff --git a/chrom_core/clones.py b/chrom_core/clones.py index efb636b..15c1f89 100644 --- a/chrom_core/clones.py +++ b/chrom_core/clones.py @@ -362,6 +362,37 @@ def _status(support: int, against: int) -> str: return "disputed" if against else "confirmed" +def _deletion_runs(found: dict, length: int, circular: bool): + """``(differences, showing reads, their Q)`` per merged difference, in position order. + + Consecutive deleted positions shown by the same set of reads form one run + (across the origin on a circular construct); every other difference is a + run of one. A run's flanking Q is the same at each of its positions. + """ + entries = [] # (sort key, run, showing, quals) + deletions = [] # (position, run, showing, quals, read ids) + for key in sorted(found): + d, showing, quals = found[key] + if d.kind != "deletion": + entries.append((key, [d], showing, quals)) + continue + ids = frozenset(map(id, showing)) + last = deletions[-1] if deletions else None + if last is not None and last[4] == ids and last[1][-1].ref_pos + 1 == d.ref_pos: + last[1].append(d) + else: + deletions.append((d.ref_pos, [d], showing, quals, ids)) + if (circular and len(deletions) > 1 and deletions[0][0] == 0 + and deletions[-1][1][-1].ref_pos == length - 1 + and deletions[0][4] == deletions[-1][4]): + deletions[-1][1].extend(deletions.pop(0)[1]) + for pos, run, showing, quals, _ids in deletions: + entries.append(((pos, "deletion", "-"), run, showing, quals)) + entries.sort(key=lambda e: e[0]) + for _key, run, showing, quals in entries: + yield run, showing, quals + + def _verdict(used, mixed, differences, coverage, params: VerifyParams) -> str: if not used: return "no_data" @@ -425,15 +456,16 @@ def verify_clone( entry[2].append(r.difference_q(d)) differences = [] - for key in sorted(found): - d, showing, quals = found[key] + for run, showing, quals in _deletion_runs(found, L, construct.circular): + d = run[0] support = sum(1 for q in quals if q >= params.min_q) - against = sum(1 for r in used - if r not in showing and r.shows_reference(d, ref, params.min_q)) - inside = d.ref_pos in in_region or ( + against = sum(1 for r in used if r not in showing + and all(r.shows_reference(x, ref, params.min_q) for x in run)) + inside = any(x.ref_pos in in_region for x in run) or ( d.kind == "insertion" and (d.ref_pos - 1) % L in in_region) + ref_base = "".join(x.ref_base for x in run) cd = CloneDifference( - d.ref_pos, d.kind, d.ref_base, d.read_base, support, against, + d.ref_pos, d.kind, ref_base, d.read_base, support, against, len(quals) - support, _status(support, against), inside, ) if annotate is not None: diff --git a/chrom_core/effects.py b/chrom_core/effects.py index cb990df..e4b8678 100644 --- a/chrom_core/effects.py +++ b/chrom_core/effects.py @@ -35,10 +35,9 @@ def difference_effect(construct: Construct, diff: CloneDifference) -> str: Substitution: ``"synonymous"``, ``"D45N"`` (one-letter codes, amino-acid number counted from the CDS start, frame from ``codon_start``) or ``"W12*"`` for a stop. Insertion/deletion: ``"frameshift"`` when the length - is not a multiple of 3, else ``"inframe_ins"`` / ``"inframe_del"``. The - length is that of this one ``CloneDifference``: a multi-base deletion - arrives as several one-base differences, each of which is reported as - ``"frameshift"``. ``""`` outside any CDS, with no features, or when the + is not a multiple of 3, else ``"inframe_ins"`` / ``"inframe_del"``; a + multi-base deletion arrives as one ``CloneDifference`` whose ``ref_base`` is + the whole deleted run. ``""`` outside any CDS, with no features, or when the read base is not A/C/G/T or the codon is incomplete. """ seq = construct.seq.upper() diff --git a/tests/test_clone_verify.py b/tests/test_clone_verify.py index c480cef..c64eeb6 100644 --- a/tests/test_clone_verify.py +++ b/tests/test_clone_verify.py @@ -106,6 +106,30 @@ def test_insertion_and_deletion_found(coi): assert r.verdict == "errors" +def _coi_with_extra(bases: str) -> Construct: + """Annotated COI with ``bases`` inserted before ``P`` (CDS stretched to match): + the unmodified reads then show a ``len(bases)``-bp deletion inside the CDS.""" + c = load_construct(DATA / "refs" / "coi_HM417896.gb") + cds = next(f for f in c.features if f.kind == "CDS") + assert (P - cds.start - (cds.codon_start - 1)) % 3 == 0 # codon-aligned + features = tuple(replace(f, end=f.end + len(bases)) if f.end > P else f + for f in c.features) + return replace(c, seq=mutate(c.seq.upper(), P, "ins", bases), features=features) + + +@pytest.mark.parametrize("extra, effect", [ + ("GCT", "inframe_del"), ("G", "frameshift"), ("GC", "frameshift")]) +def test_multi_base_deletion_is_one_difference(extra, effect): + construct = _coi_with_extra(extra) + r = verify_clone(construct, (6, 647 + len(extra)), _reads()) + d, = r.region_differences + assert (d.kind, d.read_base, d.status, d.support) == ("deletion", "-", "confirmed", 2) + assert len(d.ref_base) == len(extra) + assert construct.seq[d.ref_pos:d.ref_pos + len(extra)].upper() == d.ref_base + assert d.effect == effect + assert r.verdict == "errors" + + def test_disputed_when_reads_disagree(coi, tmp_path): # A C peak 4x the called A under P, then the call edited to C: the trace # agrees with the edit (no artificial double peak at P). @@ -384,3 +408,21 @@ def test_performance_12_clones_x_4_reads(coi): assert all(r.verdict != "no_data" for r in reports) assert not any(x.ambiguous or x.error for r in reports for x in r.reads) assert elapsed < LIMIT + + +def test_deletion_runs_split_by_reads_and_join_across_origin(): + from chrom_core.align import Difference + + a, b = object(), object() + + def dels(*specs): + return {(p, "deletion", "-"): (Difference(p, "deletion", "ACGTACGTAC"[p], "-", None), + list(reads), [30] * len(reads)) + for p, reads in specs} + + found = dels((0, [a]), (1, [a]), (4, [a, b]), (5, [a]), (8, [a]), (9, [a])) + found[(3, "substitution", "T")] = (Difference(3, "substitution", "T", "A", 3), [a], [30]) + runs = lambda circ: [("".join(d.ref_base for d in run), run[0].ref_pos) + for run, _s, _q in clones._deletion_runs(found, 10, circ)] + assert runs(False) == [("AC", 0), ("T", 3), ("A", 4), ("C", 5), ("AC", 8)] + assert runs(True) == [("T", 3), ("A", 4), ("C", 5), ("ACAC", 8)] diff --git a/tests/test_effects.py b/tests/test_effects.py index 26d0935..cdc6463 100644 --- a/tests/test_effects.py +++ b/tests/test_effects.py @@ -84,6 +84,8 @@ def test_frameshift_and_inframe(): assert difference_effect(c, ins1) == "frameshift" assert difference_effect(c, ins3) == "inframe_ins" assert difference_effect(c, del1) == "frameshift" + del3 = replace(del1, ref_base=c.seq[pos:pos + 3]) + assert difference_effect(c, del3) == "inframe_del" def test_minus_strand_cds(): From c05bd450232b356bfd0d026dd7ba4ed54fa779e1 Mon Sep 17 00:00:00 2001 From: Aleksey Drobin <43707931+adrobi@users.noreply.github.com> Date: Fri, 30 Oct 2026 17:06:31 +0300 Subject: [PATCH 38/44] verify-clones: report unusable reads (stderr, read_issues column); differences count = what the verdict uses Co-Authored-By: Claude Opus 5.5 --- README.md | 8 ++++-- chrom_cli.py | 9 +++++-- chrom_core/clone_report.py | 23 +++++++++++++---- chrom_core/clones.py | 5 ++++ tests/test_cli.py | 44 ++++++++++++++++++++++++++++++++ tests/test_clone_report.py | 51 +++++++++++++++++++++++++++++++++----- 6 files changed, 125 insertions(+), 15 deletions(-) diff --git a/README.md b/README.md index 290dc66..cd8be3a 100644 --- a/README.md +++ b/README.md @@ -102,7 +102,10 @@ ab1kit export reads/ --trim --fasta -o trimmed/ `verify-clones` prints a table of clones and exits with 0 if at least one clone is `ok`, 1 if none is, 2 on invalid input; `-o report.csv` writes `report.csv` -and `report_differences.csv`. Options: `--region A-B` (1-based, inclusive), +and `report_differences.csv`. The `differences` count (table and report) is the +in-region differences that are not low quality, i.e. those behind `errors`. +Reads that could not be used (unreadable, not aligned, ambiguous placement) are +listed on stderr as `ab1kit: : ` and in the `read_issues` column. Options: `--region A-B` (1-based, inclusive), `--linear`, `--pattern REGEX`, `--min-q N`, `--het-ratio X`. The exit-code contract applies to the `ab1kit` command installed with pip. The @@ -121,6 +124,7 @@ Requires Python 3.11+: python -m venv .venv .venv/Scripts/pip install -e ".[dev]" # Windows; on POSIX: .venv/bin/pip .venv/Scripts/python -m pytest # run the test suite +.venv/Scripts/python -m pytest -m perf # timing tests (skipped by default) .venv/Scripts/ab1kit # launch the GUI ``` @@ -132,7 +136,7 @@ python -m venv .venv `tar -xzf ab1kit-linux-x86_64.tar.gz` and run `./ab1kit`. Built on Ubuntu 22.04, so it needs glibc 2.35 or newer. The GUI needs the usual Qt runtime libraries; on Debian/Ubuntu: - `sudo apt install libegl1 libxkbcommon-x11-0 libxcb-cursor0 libxcb-icccm4 libxcb-image0 libxcb-keysyms1 libxcb-randr0 libxcb-render-util0 libxcb-shape0 libxcb-xinerama0 libxcb-xfixes0 libgl1`. + `sudo apt install libegl1 libxkbcommon-x11-0 libxcb-cursor0 libxcb-icccm4 libxcb-image0 libxcb-keysyms1 libxcb-randr0 libxcb-render-util0 libxcb-shape0 libxcb-xinerama0 libxcb-xfixes0 libgl1 libfontconfig1 libdbus-1-3 libglib2.0-0 libxcb-xkb1 libxcb-xinput0 libxcb-shm0`. The Linux binary prints CLI output to the terminal normally. ## Keyboard shortcuts diff --git a/chrom_cli.py b/chrom_cli.py index 9cb4cb5..56760d7 100644 --- a/chrom_cli.py +++ b/chrom_cli.py @@ -83,7 +83,8 @@ def _reads_in(folder: str) -> list[Path]: def _verify_clones(args: argparse.Namespace) -> int: - from chrom_core.clone_report import clone_report_xlsx, clones_csv, differences_csv + from chrom_core.clone_report import ( + clone_report_xlsx, clones_csv, differences_csv, read_issue) from chrom_core.clones import VerifyParams, check_region, group_reads, verify_all from chrom_core.reference import load_construct @@ -111,6 +112,10 @@ def _verify_clones(args: argparse.Namespace) -> int: raise CliError("no reads could be assigned to a clone") params = VerifyParams(min_q=args.min_q, het_ratio=args.het_ratio) reports = verify_all(construct, region, grouping, params) + for report in reports: + for read in report.reads: + if read_issue(read): + print(f"ab1kit: {read.ref.path.name}: {read_issue(read)}", file=sys.stderr) if out.suffix.lower() == ".xlsx": clone_report_xlsx(out, reports, construct.name) @@ -122,7 +127,7 @@ def _verify_clones(args: argparse.Namespace) -> int: width = max(len(r.clone) for r in reports) for r in reports: print(f"{r.clone:<{width}} {r.verdict:<10} coverage {r.region_coverage_pct:5.1f}% " - f"differences {len(r.region_differences)}") + f"differences {len(r.error_differences)}") return 0 if any(r.verdict == "ok" for r in reports) else 1 diff --git a/chrom_core/clone_report.py b/chrom_core/clone_report.py index 16fe010..0a9c84a 100644 --- a/chrom_core/clone_report.py +++ b/chrom_core/clone_report.py @@ -3,7 +3,7 @@ from __future__ import annotations from chrom_core.batch import csv_field -from chrom_core.clones import CloneDifference, CloneReport +from chrom_core.clones import CloneDifference, CloneReport, ReadResult # verdict -> (light, dark) hex colours; the single source of the status palette. STATUS_HEX: dict[str, tuple[str, str]] = { @@ -15,7 +15,7 @@ } CLONES_HEADER = ("clone", "verdict", "region_coverage_pct", "both_strands_pct", - "differences", "reads") + "differences", "reads", "read_issues") DIFFERENCES_HEADER = ("clone", "position", "kind", "ref", "read", "effect", "support", "against", "status", "note") @@ -37,11 +37,24 @@ def _note(d: CloneDifference) -> str: return " / ".join(parts) +_ERROR_TEXT = {"no_alignment": "did not align to the construct"} + + +def read_issue(read: ReadResult) -> str: + """Why a read was left out of the verdict, in plain English; ``""`` if it was used.""" + if read.error: + return _ERROR_TEXT.get(read.error, f"unreadable ({read.error})") + return "ambiguous placement" if read.ambiguous else "" + + def _clone_row(r: CloneReport) -> tuple: - # ``reads``: file names of every read of the clone (used or not), joined by "|". + # ``reads``: file names of every read of the clone (used or not), joined by "|"; + # ``differences``: those the verdict counts; ``read_issues``: "name: reason; ...". names = "|".join(read.ref.path.name for read in r.reads) + issues = "; ".join(f"{read.ref.path.name}: {read_issue(read)}" + for read in r.reads if read_issue(read)) return (r.clone, r.verdict, round(r.region_coverage_pct, 1), round(r.both_strands_pct, 1), - len(r.differences), names) + len(r.error_differences), names, issues) def _difference_rows(reports: list[CloneReport]): @@ -100,7 +113,7 @@ def clone_report_xlsx(path, reports: list[CloneReport], construct_name: str) -> "solid", start_color=colour, end_color=colour) for row in _difference_rows(reports): diffs.append(row) - for sheet, widths in ((clones, (16, 12, 20, 18, 12, 50)), + for sheet, widths in ((clones, (16, 12, 20, 18, 12, 50, 50)), (diffs, (16, 10, 14, 8, 8, 14, 9, 9, 12, 30))): for i, width in enumerate(widths): sheet.column_dimensions[chr(ord("A") + i)].width = width diff --git a/chrom_core/clones.py b/chrom_core/clones.py index 15c1f89..6b6051d 100644 --- a/chrom_core/clones.py +++ b/chrom_core/clones.py @@ -223,6 +223,11 @@ def both_strands_pct(self) -> float: def region_differences(self) -> tuple[CloneDifference, ...]: return tuple(d for d in self.differences if d.in_region) + @property + def error_differences(self) -> tuple[CloneDifference, ...]: + """In-region differences that are not low quality: what gives ``errors``.""" + return tuple(d for d in self.region_differences if d.status != "low_quality") + def check_region(region: Region | None, length: int, circular: bool) -> Region: """``region`` normalised (``None`` -> whole construct); ``ValueError`` if invalid.""" diff --git a/tests/test_cli.py b/tests/test_cli.py index 78e9e0e..eb2290c 100644 --- a/tests/test_cli.py +++ b/tests/test_cli.py @@ -233,3 +233,47 @@ def fake_open(*a, **k): monkeypatch.setattr(sys, "stderr", None) chrom_cli._attach_console() assert sys.stdout is None and sys.stderr is None + + +def test_unusable_reads_reported_on_stderr(reads_dir: Path, tmp_path: Path, capsys) -> None: + good = chrom_cli.main(["verify-clones", "--construct", str(COI_GB), str(reads_dir), + "-o", str(tmp_path / "a.csv")]) + capsys.readouterr() + (reads_dir / "Achl_ACHLO006-09_3_F.ab1").write_bytes(b"not an ab1 file at all") + source = (DATA / "real" / READS[0]).read_bytes() + (reads_dir / "Achl_ACHLO006-09_4_F.ab1").write_bytes(source[:len(source) // 3]) + out = tmp_path / "b.csv" + code = chrom_cli.main(["verify-clones", "--construct", str(COI_GB), str(reads_dir), + "-o", str(out)]) + assert code == good + err = capsys.readouterr().err.splitlines() + for name in ("Achl_ACHLO006-09_3_F.ab1", "Achl_ACHLO006-09_4_F.ab1"): + assert any(line.startswith(f"ab1kit: {name}: unreadable") for line in err), err + assert "Achl_ACHLO006-09_3_F.ab1: unreadable" in out.read_text(encoding="utf-8") + + +def test_read_issue_wording() -> None: + from chrom_core.clone_report import read_issue + from chrom_core.clones import ReadRef, ReadResult + + ref = ReadRef(Path("a.ab1"), "c", "F") + assert read_issue(ReadResult(ref, None, error="no_alignment")) == \ + "did not align to the construct" + assert read_issue(ReadResult(ref, None, error="bad header")) == "unreadable (bad header)" + + +def test_cli_difference_count_matches_report(reads_dir: Path, tmp_path: Path, capsys) -> None: + ref = tmp_path / "mutated.fasta" + seq = coi_reference() + alt = lambda b: "A" if b != "A" else "C" + seq = mutate(mutate(seq, 250, "sub", alt(seq[250])), 300, "sub", alt(seq[300])) + ref.write_text(">mut\n" + seq + "\n") + out = tmp_path / "rep.csv" + chrom_cli.main(["verify-clones", "--construct", str(ref), "--region", "7-280", + "--linear", str(reads_dir), "-o", str(out)]) + shown = capsys.readouterr().out + rows = [line.split(",") for line in out.read_text(encoding="utf-8").splitlines()[1:]] + assert rows + for row in rows: + line = next(l for l in shown.splitlines() if l.startswith(row[0] + " ")) + assert line.rstrip().endswith(f"differences {row[4]}") diff --git a/tests/test_clone_report.py b/tests/test_clone_report.py index 1215f48..905768e 100644 --- a/tests/test_clone_report.py +++ b/tests/test_clone_report.py @@ -6,6 +6,8 @@ import io from dataclasses import replace +from pathlib import Path + import pytest from openpyxl import load_workbook @@ -55,20 +57,56 @@ def _rows(text: str) -> list[list[str]]: def test_clones_csv_header_and_rows(reports): rows = _rows(clones_csv(reports)) assert rows[0] == ["clone", "verdict", "region_coverage_pct", "both_strands_pct", - "differences", "reads"] + "differences", "reads", "read_issues"] assert len(rows) == 3 c1, c2 = rows[1], rows[2] assert c1[:2] == ["c1", "ok"] assert c1[2] == "100.0" and c1[3] == "97.0" # F and R overlap on most of the region assert c1[4] == "0" - assert c1[5] == f"{F.name}|{R.name}" + assert c1[5] == f"{F.name}|{R.name}" and c1[6] == "" assert c2[:2] == ["c2", "errors"] - assert c2[4] == str(len(reports[1].differences)) + assert c2[4] == "1" # in-region, not low quality: the outside one is not counted def test_clones_csv_empty(): assert clones_csv([]).splitlines() == [ - "clone,verdict,region_coverage_pct,both_strands_pct,differences,reads"] + "clone,verdict,region_coverage_pct,both_strands_pct,differences,reads,read_issues"] + + +def _diff(**kw): + from chrom_core.clones import CloneDifference + + base = dict(ref_pos=1, kind="substitution", ref_base="A", read_base="G", support=1, + against=0, low_quality=0, status="confirmed", in_region=True) + return CloneDifference(**{**base, **kw}) + + +def test_differences_column_counts_what_the_verdict_uses(): + from chrom_core.clones import CloneReport + + diffs = (_diff(), _diff(ref_pos=2, status="disputed", against=1), + _diff(ref_pos=3, status="low_quality", support=0, low_quality=2), + _diff(ref_pos=4, in_region=False)) + report = CloneReport("c", (), {}, diffs, (), "errors") + assert report.error_differences == diffs[:2] + assert _rows(clones_csv([report]))[1][4] == "2" + + +def test_read_issues_column(): + from chrom_core.clones import CloneReport, ReadResult + + ok = verify_clone(Construct("c", coi_reference(), False), REGION, + _reads("c", (F, "F"))).reads[0] + results = ( + ok, + ReadResult(ReadRef(Path("x.ab1"), "c", "F"), None, error="not an ABIF file"), + ReadResult(ReadRef(Path("n.ab1"), "c", "F"), None, error="no_alignment"), + replace(ok, ref=ReadRef(Path("y.ab1"), "c", "R"), ambiguous=True), + ) + report = CloneReport("c", results, {}, (), (), "no_data") + assert _rows(clones_csv([report]))[1][6] == ( + "x.ab1: unreadable (not an ABIF file); n.ab1: did not align to the construct; " + "y.ab1: ambiguous placement") def test_differences_csv_header_position_and_notes(reports): @@ -108,7 +146,7 @@ def test_csv_quotes_commas_and_quotes(): weird = CloneReport('a,"b"', (), {}, (), (), "no_data") rows = _rows(clones_csv([weird])) assert rows[1][0] == 'a,"b"' - assert len(rows[1]) == 6 + assert len(rows[1]) == 7 assert batch.csv_field("x,y", sep=",") == '"x,y"' assert batch.csv_field("x,y") == "x,y" @@ -120,7 +158,8 @@ def test_xlsx_sheets_and_fill(reports, tmp_path): assert book.sheetnames == ["Clones", "Differences"] clones, diffs = book["Clones"], book["Differences"] assert [c.value for c in clones[1]] == ["clone", "verdict", "region_coverage_pct", - "both_strands_pct", "differences", "reads"] + "both_strands_pct", "differences", "reads", + "read_issues"] assert clones.max_row == 3 assert clones["B2"].value == "ok" and clones["B3"].value == "errors" assert clones["B3"].fill.fgColor.rgb[-6:] == STATUS_HEX["errors"][0].lstrip("#").upper() From 0048eaa2b530e58f46143f2ac5f8d78bee892ffd Mon Sep 17 00:00:00 2001 From: Aleksey Drobin <43707931+adrobi@users.noreply.github.com> Date: Fri, 30 Oct 2026 17:07:22 +0300 Subject: [PATCH 39/44] Tests: timing tests behind a perf marker, bounds scaled by AB1KIT_PERF_FACTOR Co-Authored-By: Claude Opus 5.5 --- pyproject.toml | 2 ++ tests/clone_fixtures.py | 6 ++++++ tests/test_clone_verify.py | 4 +++- tests/test_construct_ui.py | 5 +++-- tests/test_perf_marker.py | 31 +++++++++++++++++++++++++++++++ 5 files changed, 45 insertions(+), 3 deletions(-) create mode 100644 tests/test_perf_marker.py diff --git a/pyproject.toml b/pyproject.toml index f6b35ad..a01357e 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -31,3 +31,5 @@ ui = ["style.qss", "style_dark.qss", "icons/*.svg", "icons/LICENSE", "icons/READ [tool.pytest.ini_options] testpaths = ["tests"] pythonpath = ["tests"] +markers = ["perf: timing-sensitive tests, run with -m perf"] +addopts = "-m 'not perf'" diff --git a/tests/clone_fixtures.py b/tests/clone_fixtures.py index 30dad17..c2842f7 100644 --- a/tests/clone_fixtures.py +++ b/tests/clone_fixtures.py @@ -2,6 +2,7 @@ from __future__ import annotations +import os import shutil import struct from dataclasses import replace @@ -33,6 +34,11 @@ SNAPGENE_DNA = DATA / "refs" / "sample-d.dna" +def perf_factor() -> float: + """Multiplier for timing bounds (``AB1KIT_PERF_FACTOR``, default 1) on slow machines.""" + return float(os.environ.get("AB1KIT_PERF_FACTOR", "1")) + + def real_read(name: str) -> Chromatogram: return read_ab1(DATA / "real" / name) diff --git a/tests/test_clone_verify.py b/tests/test_clone_verify.py index c64eeb6..cc70771 100644 --- a/tests/test_clone_verify.py +++ b/tests/test_clone_verify.py @@ -35,6 +35,7 @@ PUC19_GB, coi_reference, mutate, + perf_factor, real_read, with_secondary_peak, write_read, @@ -391,6 +392,7 @@ def test_load_read_applies_session(tmp_path): LIMIT = 32.0 +@pytest.mark.perf def test_performance_12_clones_x_4_reads(coi): rng = random.Random(1) flank = "".join(rng.choice("ACGT") for _ in range(10_000 - len(coi))) @@ -407,7 +409,7 @@ def test_performance_12_clones_x_4_reads(coi): assert len(reports) == 12 assert all(r.verdict != "no_data" for r in reports) assert not any(x.ambiguous or x.error for r in reports for x in r.reads) - assert elapsed < LIMIT + assert elapsed < LIMIT * perf_factor() def test_deletion_runs_split_by_reads_and_join_across_origin(): diff --git a/tests/test_construct_ui.py b/tests/test_construct_ui.py index 979090b..576f6d5 100644 --- a/tests/test_construct_ui.py +++ b/tests/test_construct_ui.py @@ -23,7 +23,7 @@ ) from chrom_core.editing import EditableRead from chrom_core.reference import load_construct -from clone_fixtures import COI_GB, DATA, real_read, with_secondary_peak, write_read +from clone_fixtures import COI_GB, DATA, perf_factor, real_read, with_secondary_peak, write_read F_NAME = "Achl_ACHLO006-09_1_F.ab1" R_NAME = "Achl_ACHLO006-09_2_R.ab1" @@ -358,6 +358,7 @@ def test_mark_at_last_position(qapp, construct): PAINT_BUDGET_S = 0.025 +@pytest.mark.perf def test_paint_cost_10kb_12_rows(qapp): import time @@ -374,7 +375,7 @@ def test_paint_cost_10kb_12_rows(qapp): image = QImage(m.size(), QImage.Format.Format_ARGB32) m.render(image) # warm-up best = min(_timed(m, image, time) for _ in range(3)) - assert best < PAINT_BUDGET_S, f"paint took {best * 1000:.0f} ms" + assert best < PAINT_BUDGET_S * perf_factor(), f"paint took {best * 1000:.0f} ms" def _timed(m, image, time) -> float: diff --git a/tests/test_perf_marker.py b/tests/test_perf_marker.py new file mode 100644 index 0000000..9469150 --- /dev/null +++ b/tests/test_perf_marker.py @@ -0,0 +1,31 @@ +"""Timing tests are opt-in (``-m perf``) and their bounds scale with AB1KIT_PERF_FACTOR.""" + +import subprocess +import sys +from pathlib import Path + +from clone_fixtures import perf_factor + +ROOT = Path(__file__).resolve().parent.parent +PERF = {"tests/test_clone_verify.py::test_performance_12_clones_x_4_reads", + "tests/test_construct_ui.py::test_paint_cost_10kb_12_rows"} + + +def _collected(*extra: str) -> set[str]: + out = subprocess.run( + [sys.executable, "-m", "pytest", "--collect-only", "-q", "-p", "no:cacheprovider", + "tests/test_clone_verify.py", "tests/test_construct_ui.py", *extra], + cwd=ROOT, capture_output=True, text=True, check=False).stdout + return {line.strip().replace("\\", "/") for line in out.splitlines() if "::" in line} + + +def test_perf_tests_deselected_by_default_and_selected_with_marker(): + assert not PERF & _collected() + assert _collected("-m", "perf") == PERF + + +def test_perf_factor(monkeypatch): + monkeypatch.delenv("AB1KIT_PERF_FACTOR", raising=False) + assert perf_factor() == 1.0 + monkeypatch.setenv("AB1KIT_PERF_FACTOR", "2.5") + assert perf_factor() == 2.5 From 87d96b278e995ca09457ffb30395ac4e479f45ef Mon Sep 17 00:00:00 2001 From: Aleksey Drobin <43707931+adrobi@users.noreply.github.com> Date: Fri, 30 Oct 2026 17:07:41 +0300 Subject: [PATCH 40/44] Project files: a malformed grouping is a ValueError Co-Authored-By: Claude Opus 5.5 --- chrom_core/project.py | 2 +- tests/test_project.py | 11 +++++++++++ 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/chrom_core/project.py b/chrom_core/project.py index 92561da..87b5dc1 100644 --- a/chrom_core/project.py +++ b/chrom_core/project.py @@ -99,5 +99,5 @@ def load_project(path: Path) -> Project: grouping=grouping, params=VerifyParams(**data["params"]), ) - except (KeyError, TypeError, ValueError, IndexError) as e: + except (KeyError, TypeError, ValueError, IndexError, AttributeError) as e: raise ValueError(f"Project file is incomplete or damaged: {path} ({e!r})") from e diff --git a/tests/test_project.py b/tests/test_project.py index 8e8a680..26c46bd 100644 --- a/tests/test_project.py +++ b/tests/test_project.py @@ -107,3 +107,14 @@ def test_missing_fields(tmp_path): f.write_text(json.dumps({"app": "ab1kit", "version": 1}), encoding="utf-8") with pytest.raises(ValueError): load_project(f) + + +@pytest.mark.parametrize("grouping", [None, [], ["x"], {"reads": [None]}]) +def test_malformed_grouping_is_a_value_error(tmp_path, grouping): + f = tmp_path / "s.ab1proj" + save_project(f, _make(tmp_path)) + data = json.loads(f.read_text(encoding="utf-8")) + data["grouping"] = grouping + f.write_text(json.dumps(data), encoding="utf-8") + with pytest.raises(ValueError, match="s.ab1proj"): + load_project(f) From a1a44945b683da7011c30a4a3908c43693528384 Mon Sep 17 00:00:00 2001 From: Aleksey Drobin <43707931+adrobi@users.noreply.github.com> Date: Fri, 30 Oct 2026 17:08:26 +0300 Subject: [PATCH 41/44] Grouping: natural sort uses isdecimal (no crash on superscript digits) Co-Authored-By: Claude Opus 5.5 --- chrom_core/clones.py | 2 +- tests/test_grouping.py | 6 ++++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/chrom_core/clones.py b/chrom_core/clones.py index 6b6051d..3f412d0 100644 --- a/chrom_core/clones.py +++ b/chrom_core/clones.py @@ -42,7 +42,7 @@ class ReadRef: def _natural_key(text: str) -> list: return [ - (0, int(part), "") if part.isdigit() else (1, 0, part.casefold()) + (0, int(part), "") if part.isdecimal() else (1, 0, part.casefold()) for part in re.split(r"(\d+)", text) if part != "" ] diff --git a/tests/test_grouping.py b/tests/test_grouping.py index 9a56421..ffbc480 100644 --- a/tests/test_grouping.py +++ b/tests/test_grouping.py @@ -101,3 +101,9 @@ def test_config_new_fields_and_old_files(tmp_path): f = tmp_path / "c.json" f.write_text('{"theme": "dark"}', encoding="utf-8") assert load_config(f).primer_tokens == list(DEFAULT_PRIMER_TOKENS) + + +def test_natural_sort_with_non_decimal_digits(): + # "²" is a digit to str.isdigit() but not int()-convertible + g = Grouping([ReadRef(Path(f"{c}_F.ab1"), c, "F") for c in ("x1²", "x10", "x2")]) + assert list(g.clones()) == ["x1²", "x2", "x10"] From 39be495b23b75b0e8e2ba06eefbc559fa8f06b59 Mon Sep 17 00:00:00 2001 From: Aleksey Drobin <43707931+adrobi@users.noreply.github.com> Date: Fri, 30 Oct 2026 17:09:26 +0300 Subject: [PATCH 42/44] Theme: no tick/arrow image instead of a crash when TEMP is not writable Co-Authored-By: Claude Opus 5.5 --- tests/test_smoke_gui.py | 27 +++++++++++++++++++++++++++ ui/read_view/read_view.py | 4 ++-- ui/theme.py | 30 ++++++++++++++++++++---------- 3 files changed, 49 insertions(+), 12 deletions(-) diff --git a/tests/test_smoke_gui.py b/tests/test_smoke_gui.py index b36701d..d517168 100644 --- a/tests/test_smoke_gui.py +++ b/tests/test_smoke_gui.py @@ -548,6 +548,33 @@ def test_channel_checkboxes_use_channel_colours_and_tick(qapp): window.close() +def test_unwritable_temp_falls_back_to_no_tick_image(qapp, monkeypatch, tmp_path): + import tempfile + + from chrom_core.config import AppConfig + from ui import theme + from ui.main_window import MainWindow + + def fail(*_a, **_k): + raise OSError("read-only temp") + + monkeypatch.setattr(tempfile, "gettempdir", lambda: str(tmp_path / "nowhere")) + monkeypatch.setattr(Path, "mkdir", fail) + assert theme.tick_image("#2f6fed") == "" + for dark in (False, True): + qss = theme.app_qss(dark) + assert "@" not in qss.replace("@media", "") and "url()" not in qss + window = MainWindow(AppConfig(recent_files=[])) + window.set_theme("dark") + assert all("url(" not in box.styleSheet() + for box in window.read_view._channel_boxes.values()) + window.close() + monkeypatch.undo() + monkeypatch.setattr(tempfile, "gettempdir", lambda: str(tmp_path)) + monkeypatch.setattr(Path, "write_text", fail) + assert theme.tick_image("#2f6fed") == "" + + def test_batch_table_stretches_file_column(qapp): from PySide6.QtWidgets import QHeaderView diff --git a/ui/read_view/read_view.py b/ui/read_view/read_view.py index 6c0ea10..3479429 100644 --- a/ui/read_view/read_view.py +++ b/ui/read_view/read_view.py @@ -46,7 +46,7 @@ from ui.read_view.verify_dock import VerifyDock from ui.status import bind_icon, quality_bucket from ui.tables import repaint_statuses -from ui.theme import theme as palette, tick_image +from ui.theme import image_rule, theme as palette, tick_image class ReadView(QMainWindow): @@ -498,7 +498,7 @@ def apply_theme(self, name: str) -> None: f"QCheckBox {{ color: {c}; font-weight: bold; padding: 0 4px; }}" f"QCheckBox::indicator {{ border: 1px solid {c}; }}" f"QCheckBox::indicator:checked {{ background-color: {c}; border-color: {c};" - f" image: url({tick_image(c)}); }}" + f" {image_rule(tick_image(c))} }}" ) for table in (self.diff_table, self.verify_table, self.batch_panel.table): repaint_statuses(table) diff --git a/ui/theme.py b/ui/theme.py index c50f084..6977b86 100644 --- a/ui/theme.py +++ b/ui/theme.py @@ -78,18 +78,27 @@ def _read_qss(dark: bool) -> str: def tinted_icon(name: str, color: str, stroke: str = "2") -> str: """Path of icon ``name`` (``ui/icons/.svg``) drawn in ``color``, for QSS - ``image: url(...)``. Written once per icon and colour to the temp folder.""" + ``image: url(...)``. Written once per icon and colour to the temp folder; + ``""`` when that folder cannot be written (see ``image_rule``).""" folder = Path(tempfile.gettempdir()) / "ab1kit_icons" - folder.mkdir(exist_ok=True) target = folder / f"{name}_{color.lstrip('#')}_{stroke}.svg" - if not target.exists(): - svg = (resource_dir() / "icons" / f"{name}.svg").read_text(encoding="utf-8") - target.write_text(svg.replace("currentColor", color) - .replace('stroke-width="2"', f'stroke-width="{stroke}"'), - encoding="utf-8") + try: + folder.mkdir(exist_ok=True) + if not target.exists(): + svg = (resource_dir() / "icons" / f"{name}.svg").read_text(encoding="utf-8") + target.write_text(svg.replace("currentColor", color) + .replace('stroke-width="2"', f'stroke-width="{stroke}"'), + encoding="utf-8") + except OSError: + return "" return target.as_posix() +def image_rule(path: str) -> str: + """QSS ``image: url(path);``, or nothing for a missing (``""``) image.""" + return f"image: url({path});" if path else "" + + def tick_image(background: str) -> str: """Path of a tick (Lucide ``check``) SVG readable on ``background``.""" r, g, b = (int(background.lstrip("#")[i:i + 2], 16) for i in (0, 2, 4)) @@ -102,6 +111,7 @@ def app_qss(dark: bool) -> str: explicit colours so the chrome never depends on the OS light/dark mode.""" arrow = theme("dark" if dark else "light")["text"] return (_read_qss(dark) - .replace("@TICK@", tick_image("#2f6fed")) - .replace("@UP@", tinted_icon("chevron-up", arrow, "3")) - .replace("@DOWN@", tinted_icon("chevron-down", arrow, "3"))) + .replace("image: url(@TICK@);", image_rule(tick_image("#2f6fed"))) + .replace("image: url(@UP@);", image_rule(tinted_icon("chevron-up", arrow, "3"))) + .replace("image: url(@DOWN@);", + image_rule(tinted_icon("chevron-down", arrow, "3")))) From d358584b0ad9f4a75f4d7d111af7fcbb35d82963 Mon Sep 17 00:00:00 2001 From: Aleksey Drobin <43707931+adrobi@users.noreply.github.com> Date: Fri, 30 Oct 2026 17:10:33 +0300 Subject: [PATCH 43/44] Detail pane: an index past an edited read counts as not covered Co-Authored-By: Claude Opus 5.5 --- tests/test_construct_ui.py | 27 +++++++++++++++++++++++++++ ui/construct/detail_pane.py | 7 +++++-- 2 files changed, 32 insertions(+), 2 deletions(-) diff --git a/tests/test_construct_ui.py b/tests/test_construct_ui.py index 576f6d5..9f3fd33 100644 --- a/tests/test_construct_ui.py +++ b/tests/test_construct_ui.py @@ -459,6 +459,33 @@ def al(strand, mapping): assert displayed_index(gap, 6, 10) == 4 +def test_displayed_index_out_of_range_is_not_covered(): + from chrom_core.align import ReadAlignment + from ui.construct.detail_pane import displayed_index + + def al(strand): + return ReadAlignment(strand=strand, score=0, ref_start=0, ref_end=10, read_start=0, + read_end=10, ref_to_read={5: 8}, differences=[], identity=1.0, + alternatives=1, oriented_read="", blocks=[], ref_length=100) + + # the chromatogram was shortened by an edit after the alignment was stored + assert displayed_index(al("+"), 5, 6) is None # index 8 >= 6 + assert displayed_index(al("-"), 5, 6) is None # 6 - 1 - 8 < 0 + + +def test_pane_survives_alignment_past_a_shortened_read(qapp, construct, pane_report): + from dataclasses import replace + + first = pane_report.reads[0] + far = {p: i + 100_000 for p, i in first.alignment.ref_to_read.items()} + stale = replace(pane_report, reads=( + replace(first, alignment=replace(first.alignment, ref_to_read=far)), + *pane_report.reads[1:])) + pane = _pane(qapp, construct, stale) + pane.show_position(P) + assert not pane._notes[0].isHidden() and pane._notes[1].isHidden() + + def test_pane_one_chromatogram_per_aligned_read(qapp, construct, pane_report): pane = _pane(qapp, construct, pane_report) assert len(pane.views()) == 2 diff --git a/ui/construct/detail_pane.py b/ui/construct/detail_pane.py index 2180e17..3f681f9 100644 --- a/ui/construct/detail_pane.py +++ b/ui/construct/detail_pane.py @@ -39,7 +39,9 @@ def displayed_index(alignment: ReadAlignment, ref_pos: int, read_length: int) -> ``ref_to_read`` indexes the aligned orientation (the reverse complement on '-'), so the displayed index is ``n-1-idx`` there. A position deleted in the - read falls back to the nearest mapped neighbour; ``None`` when not covered. + read falls back to the nearest mapped neighbour; ``None`` when not covered, + including an index outside ``0..read_length-1`` (the read was edited after + the alignment was stored). """ if not alignment.covers(ref_pos): return None @@ -56,7 +58,8 @@ def displayed_index(alignment: ReadAlignment, ref_pos: int, read_length: int) -> break if idx is None: return None - return idx if alignment.strand == "+" else read_length - 1 - idx + idx = idx if alignment.strand == "+" else read_length - 1 - idx + return idx if 0 <= idx < read_length else None class DetailPane(QWidget): From 5d3d95a2cf8fba98be56ff5bc61273b9355a937e Mon Sep 17 00:00:00 2001 From: Aleksey Drobin <43707931+adrobi@users.noreply.github.com> Date: Fri, 30 Oct 2026 17:11:02 +0300 Subject: [PATCH 44/44] CI: Linux test leg (ubuntu-22.04, Python 3.13); release trigger note; README Linux runtime libraries; changelog Co-Authored-By: Claude Opus 5.5 --- .github/workflows/ci.yml | 18 ++++++++++++++++++ .github/workflows/release.yml | 1 + CHANGELOG.md | 3 ++- 3 files changed, 21 insertions(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 2efc50f..4ce5fc2 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -19,3 +19,21 @@ jobs: python-version: ${{ matrix.python-version }} - run: python -m pip install -e ".[dev]" - run: python -m pytest -q + + tests-linux: + runs-on: ubuntu-22.04 + env: + QT_QPA_PLATFORM: offscreen + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-python@v5 + with: + python-version: "3.13" + - name: Install Qt runtime libraries + run: | + sudo apt-get update + sudo apt-get install -y libegl1 libxkbcommon-x11-0 libxcb-cursor0 \ + libxcb-icccm4 libxcb-image0 libxcb-keysyms1 libxcb-randr0 \ + libxcb-render-util0 libxcb-shape0 libxcb-xinerama0 libxcb-xfixes0 libgl1 + - run: python -m pip install -e ".[dev]" + - run: python -m pytest -q diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 16fca64..53ec85f 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -1,5 +1,6 @@ name: Release +# workflow_dispatch builds and uploads the artifacts; a release is created only for v* tags. on: push: tags: ["v*"] diff --git a/CHANGELOG.md b/CHANGELOG.md index ea2381e..9c68348 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -17,7 +17,8 @@ from the command line. per-clone coverage by strand, merged differences and verdicts (`ok` / `errors` / `incomplete` / `mixed` / `no_data`) - Amino-acid consequences of differences inside CDS features -- Clone report as CSV and Excel (sheets `Clones` and `Differences`); +- Clone report as CSV and Excel (sheets `Clones` and `Differences`; unusable + reads listed per clone in `read_issues` and on the CLI's stderr); `.ab1proj` project files for verification sessions - Clone-verification workspace: summary bar, clone matrix, difference detail pane with stacked chromatograms, grouping editor, drag-and-drop of reads and projects