Numbering schemes and region definitions¶
Two separate choices decide which residues of an antibody variable domain form each CDR:
A numbering scheme gives each residue a position, so that equivalent residues in different antibodies share a number. Positions with an insertion code, such as 111A, hold residues that some antibodies have and others lack.
A region definition says which positions belong to each complementarity-determining region (CDR) and framework region.
Several definitions were first published alongside a scheme of the same name, which makes the two easy to confuse, but they are independent: antibody-utils applies any definition to sequences numbered in any scheme.
Numbering schemes¶
Scheme |
Reference |
|---|---|
|
Lefranc M-P et al., IMGT unique numbering for immunoglobulin and T cell receptor variable domains and Ig superfamily V-like domains, Dev Comp Immunol 27:55–77 (2003) |
|
Kabat EA et al., Sequences of Proteins of Immunological Interest, 5th edition, NIH publication 91-3242 (1991) |
|
Chothia C and Lesk AM, Canonical structures for the hypervariable regions of immunoglobulins, J Mol Biol 196:901–917 (1987) |
|
Abhinandan KR and Martin ACR, Analysis and improvements to Kabat and structurally correct numbering of antibody variable domains, Mol Immunol 45:3832–3839 (2008) |
ANARCII numbers sequences in all four (see Quick start). IMGT is the default throughout antibody-utils, and it is the scheme of SAbDab’s structure files.
A position is a number and an optional insertion code:
>>> from antibody_utils.numbering import Position, parse_chain_position
>>> Position.parse("111A")
Position(number=111, insertion='A')
>>> str(Position(111, "A"))
'111A'
>>> parse_chain_position("H100A")
(<Chain.HEAVY: 'H'>, Position(number=100, insertion='A'))
Region definitions¶
Definition |
Reference |
|---|---|
|
Lefranc et al. (2003), above |
|
Kabat et al. (1991), above |
|
Chothia and Lesk (1987), above |
|
MacCallum RM, Martin ACR and Thornton JM, Antibody-antigen interactions: contact analysis and binding site topography, J Mol Biol 262:732–745 (1996) |
|
North B, Lehmann A and Dunbrack RL Jr, A new clustering of antibody CDR loop conformations, J Mol Biol 406:228–256 (2011) |
antibody-utils stores each definition as ranges of IMGT positions, and maps positions in the other schemes on to IMGT positions. In IMGT positions, the CDRs are:
Definition |
CDR-H1 |
CDR-H2 |
CDR-H3 |
CDR-L1 |
CDR-L2 |
CDR-L3 |
|---|---|---|---|---|---|---|
|
27–38 |
56–65 |
105–117 |
27–38 |
56–65 |
105–117 |
|
36–40 |
55–74 |
107–117 |
24–40 |
56–69 |
105–117 |
|
27–37 |
57–64 |
107–117 |
24–40 |
56–69 |
105–117 |
|
31–40 |
52–66 |
105–116 |
36–42 |
52–68 |
105–116 |
|
24–40 |
55–66 |
105–117 |
24–40 |
55–69 |
105–117 |
The definitions published in another scheme are exact in IMGT positions
except where the schemes place insertions differently, around CDR-H1 and
CDR-L2. There, annotate_regions uses the rest of the sequence to give the
CDR that the definition gives in its own scheme.
Assigning regions¶
annotate_regions assigns every residue of a numbered domain to its region,
and is what the rest of antibody-utils uses. NumberedSequence has it as a
method, and antibody_utils.sequence.region_sequences and cdr_sequences
build on it.
get_region looks up one position on its own. It can’t see insertions
elsewhere in the sequence, so near CDR-H1 and CDR-L2 it can differ from
annotate_regions when the definition and the scheme differ. The same
Chothia position falls in different regions under different definitions:
>>> from antibody_utils.regions import get_region
>>> for definition in ["imgt", "kabat", "chothia", "contact", "north"]:
... print(definition, get_region("35", "H", scheme="chothia", definition=definition))
imgt fwh2
kabat cdrh1
chothia fwh2
contact cdrh1
north cdrh1
Regions are named fwh1–fwh4, cdrh1–cdrh3, fwl1–fwl4 and
cdrl1–cdrl3. Wherever antibody-utils takes region names, it also takes
these groups:
Group |
Regions |
|---|---|
|
the CDRs of the heavy chain, light chain or both |
|
the framework regions likewise |
|
the whole heavy domain, light domain, or both |
RegionSelector selects positions by region, and can add or exclude
individual positions:
>>> from antibody_utils.regions import RegionSelector
>>> selector = RegionSelector(["cdrs"], scheme="imgt", definition="north")
>>> selector.accepts("111A", "H"), selector.accepts("50", "H")
(True, False)