Skip to content

Commit e288342

Browse files
000specificclaude
andcommitted
annogroups: add 9 more source parsers (12 sources total), all validated end-to-end
Expands BLOCK_build_annogroups from 3 to 12 annotation sources (one parser plugin each; sources: "all" auto-discovers them). Full DAG run on species70 validated all 12 PASS. Positional (4 types: feature/combination/architecture/absent): - gene3d, cdd, smart, superfamily, funfam: InterProScan-parsed positional DBs, clones of the panther/pfam parser (identical 15-col schema). - tmbed: 3 segment classes (TM_helix / beta_barrel / signal_peptide) with coords; architecture = N->C membrane topology (e.g. 7-TM receptors group). - metapredict: generic IDRs (single accession 'IDR'); feature/combination collapse to has-IDR, architecture groups by IDR count (user-accepted, low-resolution). Whole-protein (3 types, no architecture): - deeploc: subcellular-localization labels from the final-call 'Localizations' column (CSV); spaces/'/' in labels -> '_' accessions, readable label as definition. - signalp: signal-peptide type (Sec/SPI etc.) from the SLOW model (user decision); '/' -> '_' accessions. The four per-protein tools share one documented caveat: a protein not scored by the tool falls into annogroup_<source>_absent ("no feature in the available output"). Docs (subproject + BLOCK + workflow READMEs/AI_GUIDEs + config) updated: source inventory, per-source feature-type table, input locations, and the RUN_7 12-source validation result (per-source annogroup counts). The concurrent-session phyla->clades edits in composite_clades_manifest.tsv and upload_manifest.tsv are intentionally left unstaged for that session. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
1 parent 1883b54 commit e288342

15 files changed

Lines changed: 1093 additions & 38 deletions

File tree

gigantic_project-COPYME/subprojects/annogroups/AI_GUIDE.md

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -91,13 +91,19 @@ BLOCK guide.
9191
Built 2026-06-18. **pfam validated end-to-end** (137,762 annogroups across the
9292
four types; validation PASS; full NextFlow DAG run).
9393

94-
2026-06-28: two more parsers added and validated (scripts 001–003, PASS):
95-
- **panther** — positional PTHR families (4 types): feature 11,033 / combination
96-
11,033 / architecture 11,051 / absent 418,016.
97-
- **go** — whole-protein Gene Ontology terms from the **raw** InterProScan results
98-
(3 types, no architecture by design): feature 8,994 / combination 27,974 / absent
99-
539,984. GO origin selection (InterPro / PANTHER union, default both) is a
100-
documented config knob (`go_term_origins`).
94+
2026-06-28: expanded to **12 sources**, all validated end-to-end (full DAG,
95+
species70, validation PASS):
96+
- positional (4 types): **pfam, panther, gene3d, cdd, smart, superfamily, funfam**
97+
(InterProScan domains/families), **tmbed** (membrane topology — architecture is
98+
the TM/barrel/signal segment order), **metapredict** (IDRs — one accession `IDR`,
99+
so architecture groups by IDR count).
100+
- whole-protein (3 types, no architecture): **go** (GO terms; names from the
101+
go-basic.obo mapping; origins via the `go_term_origins` knob, default InterPro +
102+
PANTHER union; plus 6 GO-aspect split columns), **deeploc** (subcellular
103+
localization), **signalp** (signal-peptide type, SLOW model).
104+
- The per-protein tools (tmbed/signalp/deeploc/metapredict) carry one caveat:
105+
proteins not scored by the tool fall into `annogroup_<source>_absent` (absent =
106+
"no feature in the available output").
101107

102108
One known, user-accepted data caveat: a handful of truncated multi-locus annotation
103109
IDs are dropped — see

gigantic_project-COPYME/subprojects/annogroups/BLOCK_build_annogroups/AI_GUIDE.md

Lines changed: 22 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -109,12 +109,21 @@ Conventions a parser must follow:
109109
WARNING note).
110110

111111
`parsers/pfam.py` is the reference implementation (positional domains, all four
112-
types). **Implemented parsers**: `pfam` + `panther` (both
113-
`BLOCK_interproscan_parsed/<db>/`, positional, 4 types) and `go` (see below).
114-
Per-source input locations for further parsers:
115-
`gene3d/cdd/smart/superfamily/funfam``BLOCK_interproscan_parsed/<db>/`;
116-
`tmbed``BLOCK_tmbed/`; `signalp``BLOCK_signalp/`; `deeploc`
117-
`BLOCK_deeploc/`; `metapredict``BLOCK_metapredict/`.
112+
types). **All 12 sources are implemented.** Input locations (all under the config
113+
`annotations_hmms_dir` root):
114+
115+
- `pfam, panther, gene3d, cdd, smart, superfamily, funfam``BLOCK_interproscan_parsed/<db>/<db>-*.tsv` (15-col schema; positional clones)
116+
- `go` → raw `BLOCK_interproscan/*_interproscan_results.tsv` (see below)
117+
- `tmbed``BLOCK_tmbed/*_tmbed_predictions.tsv` (3 positional segment classes)
118+
- `signalp``BLOCK_signalp/*_signalp_SLOW_predictions.tsv` (whole-protein SP type; SLOW model)
119+
- `deeploc``BLOCK_deeploc/*_deeploc_predictions.csv` (whole-protein localization labels; CSV)
120+
- `metapredict``BLOCK_metapredict/*_metapredict_predictions.tsv` (generic positional IDRs)
121+
122+
The per-protein tools (tmbed/signalp/deeploc/metapredict) share one caveat: a
123+
protein not scored by the tool (e.g. dropped upstream by the long-header filter)
124+
has no feature and so falls into `annogroup_<source>_absent` — i.e. `absent` means
125+
"no feature in the available output", which can include a few not-evaluated
126+
proteins (analogous to the dropped-orphan caveat).
118127

119128
**`parsers/go.py` (special).** GO is not a standalone parsed database. The go
120129
parser reads the **raw** per-species results (`BLOCK_interproscan/*_interproscan_results.tsv`,
@@ -147,11 +156,14 @@ and 6-output (composite-clade per-annogroup + detail tables). Sources without
147156
(the N→C *ordered* arrangement, needs coordinates). Non-positional sources yield
148157
no architecture (3 types).
149158

150-
| Source kind | Example | is_positional | Types |
159+
All 12 sources below are **implemented** (one parser plugin each; `sources: "all"`
160+
builds them all).
161+
162+
| Source kind | Sources | is_positional | Types |
151163
|-------------|---------|---------------|-------|
152-
| positional domains/families | **pfam**, **panther** (implemented); gene3d, cdd, smart, superfamily, funfam | True | feature + combination + architecture + absent |
153-
| positional segments/regions | tmbed (TM segments), metapredict (IDRs), signalp (cleavage region) | True | all four (architecture = segment order) |
154-
| whole-protein label | **go** (Gene Ontology terms, implemented); deeploc (localization) | False | feature + combination + absent (no architecture) |
164+
| positional domains/families | pfam, panther, gene3d, cdd, smart, superfamily, funfam | True | feature + combination + architecture + absent |
165+
| positional segments/regions | tmbed (TM_helix / beta_barrel / signal_peptide; architecture = membrane topology), metapredict (IDRs; one accession `IDR`, so architecture = IDR count) | True | all four |
166+
| whole-protein label | go (GO terms), deeploc (subcellular localization), signalp (signal-peptide type, SLOW model) | False | feature + combination + absent (no architecture) |
155167

156168
## Validation (Script 003, fail-fast)
157169

gigantic_project-COPYME/subprojects/annogroups/BLOCK_build_annogroups/README.md

Lines changed: 23 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -77,13 +77,29 @@ Built 2026-06-18 — scaffold, scripts, docs, and the NextFlow workflow complete
7777
10,635 feature + 46,846 combination + 80,280 architecture + 1 absent; validation
7878
PASS).
7979

80-
**2026-06-28: panther + go parsers added and validated** (build + validate,
81-
scripts 001–003, species70, validation PASS):
82-
- **panther** (positional, 4 types): 11,033 feature + 11,033 combination + 11,051
83-
architecture + 1 absent (418,016 absent sequences).
84-
- **go** (whole-protein, 3 types — no architecture): 8,994 feature + 27,974
85-
combination + 1 absent (539,984 absent sequences); GO origins = InterPro + PANTHER
86-
union (default `go_term_origins`).
80+
**2026-06-28: expanded to 12 sources, all validated end-to-end** (full DAG,
81+
species70, validation PASS — universe 1,375,926 sequences). Total annogroups per
82+
source (feature / combination / architecture):
83+
84+
| Source | annot% | feature | combination | architecture |
85+
|--------|-------:|--------:|------------:|-------------:|
86+
| pfam | 67.0 | 10,635 | 46,846 | 80,280 |
87+
| panther | 69.6 | 11,033 | 11,033 | 11,051 |
88+
| gene3d | 61.1 | 3,289 | 25,748 | 50,886 |
89+
| cdd | 28.5 | 11,239 | 18,657 | 26,037 |
90+
| smart | 31.4 | 1,171 | 10,974 | 35,042 |
91+
| superfamily | 58.4 | 1,412 | 18,386 | 37,579 |
92+
| funfam | 23.1 | 36,784 | 51,917 | 56,422 |
93+
| go | 60.8 | 8,994 | 27,974 ||
94+
| deeploc | 100.0 | 10 | 177 ||
95+
| signalp | 12.0 | 1 | 1 ||
96+
| tmbed | 29.4 | 3 | 7 | 122 |
97+
| metapredict | 78.7 | 1 | 1 | 85 |
98+
99+
(`` = whole-protein source, no architecture. signalp/metapredict feature counts are
100+
small by nature: one signal-peptide type called in species70, one generic `IDR`
101+
accession; tmbed's 3 = TM_helix / beta_barrel / signal_peptide. go carries 6
102+
GO-aspect split columns.)
87103

88104
One known, user-accepted caveat: truncated multi-locus annotation IDs are
89105
dropped — see [`workflow-COPYME-build_annogroups/ai/ai_FYIs/WARNING-truncated_orphan_annotations.md`](workflow-COPYME-build_annogroups/ai/ai_FYIs/WARNING-truncated_orphan_annotations.md).

gigantic_project-COPYME/subprojects/annogroups/BLOCK_build_annogroups/workflow-COPYME-build_annogroups/README.md

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -74,13 +74,15 @@ pfam-annotated = 922,233; **137,762 annogroups** (10,635 feature + 46,846
7474
combination + 80,280 architecture + 1 absent holding 453,693 sequences); validation
7575
**PASS**; 7 truncated orphan IDs dropped (audited).
7676

77-
**panther + go** (2026-06-28, build + validate, scripts 001–003): same universe.
78-
- panther (positional, 4 types): 11,033 feature + 11,033 combination + 11,051
79-
architecture + 1 absent (418,016 seqs); validation **PASS**; 7 orphans dropped.
80-
- go (whole-protein, 3 types — no architecture): 8,994 feature + 27,974 combination
81-
+ 1 absent (539,984 seqs); validation **PASS**; 6 orphans dropped; GO origins =
82-
InterPro + PANTHER (default union, `go_term_origins`). GO build ≈ 45 s (reads the
83-
raw per-species InterProScan results).
77+
**12 sources** (2026-06-28, full DAG, SLURM, ~11 min): same universe; all 12
78+
validated **PASS** — pfam, panther, gene3d, cdd, smart, superfamily, funfam (IPS
79+
positional → 4 types), tmbed + metapredict (positional segments → 4 types), go,
80+
deeploc, signalp (whole-protein → 3 types). See the per-source annogroup-count
81+
table in [`../README.md`](../README.md). New since the pfam-only run:
82+
- `go` GO term names + 6 GO-aspect (MF/BP/CC) split columns; origins via `go_term_origins`.
83+
- `tmbed` architecture = membrane topology; `deeploc` = subcellular localization
84+
(100% annotated); `signalp` = signal-peptide type (SLOW model); `metapredict`
85+
architecture = IDR count.
8486

8587
See [`ai/AI_GUIDE.md`](ai/AI_GUIDE.md) for execution detail and troubleshooting,
8688
and [`../AI_GUIDE.md`](../AI_GUIDE.md) for the parser contract.

gigantic_project-COPYME/subprojects/annogroups/BLOCK_build_annogroups/workflow-COPYME-build_annogroups/START_HERE-user_config.yaml

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,9 +22,10 @@ species_set_name: "species70"
2222
# Which annotation sources to build annogroups for.
2323
# "all" - every source that has a parser plugin AND data available
2424
# [ pfam, gene3d ] - an explicit subset (each must have parsers/<source>.py)
25-
# Parser plugins present: pfam, panther (positional -> 4 types) and go (whole-
26-
# protein -> 3 types). "all" auto-includes every parser, so new parsers need no
27-
# edit here.
25+
# Parser plugins present (12): positional (4 types) pfam, panther, gene3d, cdd,
26+
# smart, superfamily, funfam, tmbed, metapredict; whole-protein (3 types) go,
27+
# deeploc, signalp. "all" auto-includes every parser, so new parsers need no edit
28+
# here. A subset is a list, e.g. [ pfam, go, tmbed ].
2829
sources: "all"
2930

3031
# =============================================================================
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,116 @@
1+
# AI: Claude Code | Opus 4.8 (1M context) | 2026 June 28 | Purpose: annogroups source parser for CDD (per-species InterProScan-parsed cdd files)
2+
# Human: Eric Edsinger
3+
4+
"""
5+
annogroups source parser — cdd.
6+
7+
Reads the per-species CDD annotation files exposed by annotations_hmms at
8+
annotations_hmms/output_to_input/BLOCK_interproscan_parsed/cdd/cdd-<phyloname>.tsv
9+
and returns, per sequence, the list of CDD features (all positional).
10+
11+
NCBI Conserved Domain Database domains (cd accessions). Each match carries residue coordinates (Match_Start / Match_End), so
12+
cdd participates in all four annogroup types (feature, combination,
13+
architecture, absent) -- combination groups by the whole-protein set of CDD
14+
accessions, architecture by their sub-protein N->C arrangement.
15+
16+
The parsed cdd files share the identical 15-column self-documenting schema as
17+
the pfam files, so this parser mirrors parsers/pfam.py (only SOURCE and the source
18+
subpath differ). Example accession: cd05751.
19+
20+
Parser-plugin contract (see utils_annogroups): expose SOURCE and
21+
parse_source_features( workflow_root, config ) -> { sequence_id: [ Feature, ... ] }.
22+
"""
23+
24+
import sys
25+
from pathlib import Path
26+
27+
sys.path.insert( 0, str( Path( __file__ ).parent.parent ) )
28+
import utils_annogroups as U
29+
30+
SOURCE = "cdd"
31+
32+
# Path to this source's annotation files, relative to the workflow root. The config
33+
# exposes the annotations_hmms output_to_input root; each parser appends its own
34+
# source-specific subpath.
35+
RELATIVE_SUBPATH = "BLOCK_interproscan_parsed/cdd"
36+
37+
38+
def parse_source_features( workflow_root: Path, config: dict ) -> dict:
39+
"""sequence_identifier -> [ Feature(accession, start, stop, is_positional=True) ]."""
40+
annotations_dir = U.resolve_input_path(
41+
workflow_root, config[ "inputs" ][ "annotations_hmms_dir" ]
42+
) / RELATIVE_SUBPATH
43+
44+
if not annotations_dir.is_dir():
45+
print( f"CRITICAL ERROR: cdd annotation directory not found: {annotations_dir}", file = sys.stderr )
46+
print( " Verify annotations_hmms exposed BLOCK_interproscan_parsed/cdd/ in output_to_input.", file = sys.stderr )
47+
sys.exit( 1 )
48+
49+
source_files = sorted( annotations_dir.glob( "cdd-*.tsv" ) )
50+
if not source_files:
51+
print( f"CRITICAL ERROR: no cdd-*.tsv files in {annotations_dir}", file = sys.stderr )
52+
sys.exit( 1 )
53+
54+
proteins___features = {}
55+
for source_file in source_files:
56+
with open( source_file, 'r' ) as input_source:
57+
# Protein_Identifier (...)\tMD5 (...)\tSequence_Length (...)\tAnalysis_Database (...)\tAccession (...)\tDescription (...)\tMatch_Start (...)\tMatch_End (...)\t...
58+
header_ids___indices = U.build_header_index( input_source.readline() )
59+
index_protein = header_ids___indices[ "Protein_Identifier" ]
60+
index_accession = header_ids___indices[ "Accession" ]
61+
index_start = header_ids___indices[ "Match_Start" ]
62+
index_stop = header_ids___indices[ "Match_End" ]
63+
for line in input_source:
64+
line = line.rstrip( '\n' )
65+
if not line:
66+
continue
67+
parts = line.split( '\t' )
68+
protein = parts[ index_protein ]
69+
accession = parts[ index_accession ]
70+
try:
71+
start = int( parts[ index_start ] )
72+
stop = int( parts[ index_stop ] )
73+
except ( ValueError, IndexError ):
74+
# A positional match must have integer coordinates; a malformed
75+
# row is a genuine upstream data problem -- fail fast (section 36).
76+
print( f"CRITICAL ERROR: non-integer Match_Start/Match_End in {source_file.name}: {line[ :120 ]}", file = sys.stderr )
77+
sys.exit( 1 )
78+
proteins___features.setdefault( protein, [] ).append(
79+
U.Feature( accession = accession, start = start, stop = stop, is_positional = True )
80+
)
81+
82+
return proteins___features
83+
84+
85+
def parse_source_definitions( workflow_root: Path, config: dict ) -> dict:
86+
"""
87+
accession -> human-readable definition (CDD signature description, column
88+
'Description'). First non-empty description seen per accession wins.
89+
90+
Optional half of the parser contract: a source that exposes this lets the builder
91+
attach Annotation_Definitions to the annogroup map. Sources without descriptions
92+
can omit this function (the builder then emits empty definitions).
93+
"""
94+
annotations_dir = U.resolve_input_path(
95+
workflow_root, config[ "inputs" ][ "annotations_hmms_dir" ]
96+
) / RELATIVE_SUBPATH
97+
98+
source_files = sorted( annotations_dir.glob( "cdd-*.tsv" ) )
99+
100+
accessions___definitions = {}
101+
for source_file in source_files:
102+
with open( source_file, 'r' ) as input_source:
103+
header_ids___indices = U.build_header_index( input_source.readline() )
104+
index_accession = header_ids___indices[ "Accession" ]
105+
index_description = header_ids___indices[ "Description" ]
106+
for line in input_source:
107+
line = line.rstrip( '\n' )
108+
if not line:
109+
continue
110+
parts = line.split( '\t' )
111+
accession = parts[ index_accession ]
112+
description = U.sanitize_annotation_text( parts[ index_description ] ) if index_description < len( parts ) else ''
113+
if description and description != '-' and accession not in accessions___definitions:
114+
accessions___definitions[ accession ] = description
115+
116+
return accessions___definitions

0 commit comments

Comments
 (0)