Journal Club post: Interface between Ig-seq and antibody modelling

Hi everyone! In this blog post, I would like to review a couple of relatively recent papers about antibody modelling and immunoglobulin gene repertoire NGS, also known as Ig-seq. Previously I used to work as a phage display scientist and I initially struggled to understand all new terminology about computational modelling when I joined Charlotte’s group last January. Hence, the paramount aim of my blog post is to decipher commonly used jargon in the computational world into less complicated text.

The three-dimensional structure of an antibody dictates its function. Antibody sequences obtained from Ig-seq cannot be directly translated into antibody folding, aggregation and function. Several ways exist to interrogate antibody structure, including X-ray crystallography and NMR spectroscopy, expression, and computational modelling. These methods vary in throughput as well as precision. Here, I will concentrate my attention on computational modelling. First of all, the most commonly confused term is a decoy. In antibody structure prediction, a decoy is a modelled antibody structure that can be ranked and selected by a tool as the closest to the native antibody structure. A number of antibody modelling tools exist, each employing a different methodology and a number of generated decoys. Good reviews on the antibody structure prediction are here (1,2). I will try to draw a very gross summary about how all these unique modelling tools work. To do so, I assume that people are familiar with antibody sequence/structure relationship – if not please check (3). Antibody framework region are sequence invariant, hence their structure can be deduced from sequence identity with high confidence. PDB (4) act as the source of structures for antibody modelling. Canonical CDRs (all CDRs except for CDR-H3) can be put into a limited number of structures. Several definitions of canonical classes exist (5,6), but, in essence, the canonical CDR must contain residues that define a particular class. Next, antibody orientation is calculated or copied from PDB. CDR-H3 modelling is very challenging and different approaches have been devised (7–9). The structure space of CDR-H3 is very vast (10) and hence, this loop cannot be put into a canonical class. Once CDR-H3 is modelled, the resultant decoy is checked for clashes (like impossible orientation of side chains).

Here, I would like to mention several examples on how antibody modelling can help to accelerate drug discovery. Dekosky et al. (11) mapped two Ig-seq datasets to antibody structures to interrogate how an antibody paratope changes in response to antigenic stimulation. The knowledge of paired full length VH-VL is crucial for the best antibody structure prediction. In this study they employed paired chain Ig-seq (12). However, this technique cannot sequence full length VH/VL, hence the V gene sequence had to be approximated. Computational paratope identification was employed to examine paratope convergences. There were several drawbacks of this paper: only 2,000 models (~1% of Ig-seq data) were modelled in 570,000 CPU time, and antibody sequences with longer than 16 aa long CDR-H3 were not included into analysis. The generation of a reliable configuration of long CDR-H3 is considered a hard task at this moment. Recently, Laffy et al. (13) investigated antibody promiscuity by mapping sequence to structure and validating the results with ELISA. The cohort of 10 antibodies, all with long CDR-H3 >= 15 aa were interrogated. They used a homology modelling tool to devise CDR-H3 structures. However, the availability of the appropriate structural template can be questioned, since CDR-H3 loops deposited in the PDB are predominantly shorter due to crystallographic constraints. As mentioned before, the paired VH/VL data is crucial for structure determination. Here, they used Dekosky et al. (11) data to devise the pairing. The approach can be streamlined once more paired data become available.

In conclusion, antibody modelling enables researchers to circumvent the cost and time associated with experimental approaches of antibody characterizations. The field of antibody modelling still needs improvements for faster and better structure prediction to achieve tasks such as modelling the entirety of Ig-seq data or long CDR-H3 loops. Currently, the fastest tool of antibody modelling is ABodyBuilder (8). It generates a model in 30 sec and its version is available online (http://opig.stats.ox.ac.uk/webapps/sabdab-sabpred/Modelling.php). The availability of more structural information as well as algorithm improvements will facilitate more confident antibody modelling.

 

  1. Kuroda D, Shirai H, Jacobson MP, Nakamura H. Computer-aided antibody design. Protein Eng Des Sel (2012) 25:507–521. doi:10.1093/protein/gzs024
  2. Krawczyk K, Dunbar J, Deane CM. “Computational Tools for Aiding Rational Antibody Design,” in Methods in molecular biology (Clifton, N.J.), 399–416. doi:10.1007/978-1-4939-6637-0_21
  3. Georgiou G, Ippolito GC, Beausang J, Busse CE, Wardemann H, Quake SR. The promise and challenge of high-throughput sequencing of the antibody repertoire. Nat Biotech (2014) 32:158–168. doi:10.1038/nbt.2782
  4. Berman H, Henrick K, Nakamura H, Markley JL. The worldwide Protein Data Bank (wwPDB): Ensuring a single, uniform archive of PDB data. Nucleic Acids Res (2007) 35: doi:10.1093/nar/gkl971
  5. Nowak J, Baker T, Georges G, Kelm S, Klostermann S, Shi J, Sridharan S, Deane CM. Length-independent structural similarities enrich the antibody CDR canonical class model. MAbs (2016) 8:751–760. doi:10.1080/19420862.2016.1158370
  6. North B, Lehmann A, Dunbrack RL. A new clustering of antibody CDR loop conformations. J Mol Biol (2011) 406:228–256. doi:10.1016/j.jmb.2010.10.030
  7. Weitzner BD, Jeliazkov JR, Lyskov S, Marze N, Kuroda D, Frick R, Adolf-Bryfogle J, Biswas N, Dunbrack RL, Gray JJ. Modeling and docking of antibody structures with Rosetta. Nat Protoc (2017) 12:401–416. doi:10.1038/nprot.2016.180
  8. Leem J, Dunbar J, Georges G, Shi J, Deane CM. ABodyBuilder: Automated antibody structure prediction with data–driven accuracy estimation. MAbs (2016) 8:1259–1268. doi:10.1080/19420862.2016.1205773
  9. Marks C, Nowak J, Klostermann S, Georges G, Dunbar J, Shi J, Kelm S, Deane CM. Sphinx: merging knowledge-based and ab initio approaches to improve protein loop prediction. Bioinformatics (2017) 33:1346–1353. doi:10.1093/bioinformatics/btw823
  10. Regep C, Georges G, Shi J, Popovic B, Deane CM. The H3 loop of antibodies shows unique structural characteristics. Proteins Struct Funct Bioinforma (2017) 85:1311–1318. doi:10.1002/prot.25291
  11. DeKosky BJ, Lungu OI, Park D, Johnson EL, Charab W, Chrysostomou C, Kuroda D, Ellington AD, Ippolito GC, Gray JJ, et al. Large-scale sequence and structural comparisons of human naive and antigen-experienced antibody repertoires. Proc Natl Acad Sci U S A (2016)1525510113-. doi:10.1073/pnas.1525510113
  12. Dekosky BJ, Kojima T, Rodin A, Charab W, Ippolito GC, Ellington AD, Georgiou G. In-depth determination and analysis of the human paired heavy- and light-chain antibody repertoire. Nat Med (2014) 21:1–8. doi:10.1038/nm.3743
  13. Laffy JMJ, Dodev T, Macpherson JA, Townsend C, Lu HC, Dunn-Walters D, Fraternali F. Promiscuous antibodies characterised by their physico-chemical properties: From sequence to structure and back. Prog Biophys Mol Biol (2016) doi:10.1016/j.pbiomolbio.2016.09.002

Journal club: Human enterovirus 71 protein interaction network prompts antiviral drug repositioning

Viruses are small infectious agents, which possess genetic code but have no independent metabolism. They propagate by infecting host cells and hijacking their machinery, often killing the cells in the process. One of the key challenges in developing effective antiviral therapies is the high mutation rate observed in viral genomes. A way to circumvent this issue is to target host proteins involved in virion assembly (also known as essential host factors, or EHFs), rather than the virion itself.

In their recent paper, Lu Han et al. [1] consider human virus protein-protein interactions in order to explore possible host drug targets, as well as drugs which could potentially be re-purposed as antivirals. Their study focuses on enterovirus 71 (EV71), one of the leading causes of hand, foot, and mouth disease.

Human virus protein-protein interactions and target identification

EHFs are typically detected by knocking out genes in the host organism and determining which of the knockouts result in virus control. Low repeat rates and high costs make this technique unsuitable for large scale studies. Instead, the authors use an extensive yeast two-hybrid screen to identify 37 unique protein-protein interactions between 7 of the 11 virus proteins and 29 human proteins. Pathway enrichment suggests that the human proteins interacting with EV71 are involved in a wide range of functions in the cell. Despite this range in functionality, as many as 17 are also associated with other viruses, either through known physical interactions, or as EHFs (Fig 1).

Fig. 1. Interactions between viral and human proteins (denoted as EIPs), and their connection to different viruses.

One of these is ATP6V0C, a subunit of vacuole ATP-ase. It interacts with the EV71 3A protein, and is a known essential host factor for five other viruses. The authors analyse the interaction further, and show that downregulating ATP6V0C gene expression inhibits EV71 propagation, while overexpressing it enhances virus propagation. Moreover, treating cells with bafilomycin A1, a selective inhibitor for vacuole ATP-ase, inhibits EV71 infection in a dose-dependent manner. The paper suggests that therefore ATP6V0C may be a suitable drug target, not only against EV71, but also perhaps even for a broad-spectrum antiviral. While this is encouraging, bafilomycin A1 is a toxic antibiotic used in research, but not suitable for human or drug use. Rather than exploring other compounds targeting ATP6V0C, the paper shifts focus to re-purposing known drugs as antivirals.

Drug prediction using CMap

A potential antiviral will ideally disturb most or all interactions between host cell and virion. One way to do this would be to inhibit the proteins known to interact with EV71. In order to check whether any known compounds already do so, the authors apply gene set enrichment analysis (GSEA) to data from the connectivity map (CMap). CMap is a database of gene expression profiles representing cellular response to a set of 1309 different compounds.  Enrichment analysis of the database reveals 27 potential EV71 drugs, of which the authors focus on the top ranking result, tanespimycin.

Tanespimycin is an orphan cancer drug, originally designed to target tumor cells by inhibiting HSP90. Its complex effects on the cell, however, may make it an effective antiviral. Following their CMap analysis, the authors show that tanespimycin reduces viral count and virus-induced cytopathic effects in a dose-dependent manner, without evidence of cytotoxicity.

Overall, the paper presents two different ways to think about target investigation and drug choice in antiviral therapeutics — by integrating different types of known host virus protein-protein interactions, and by analysing cell response to known compounds. While extensive further study is needed to determine whether the results are directly clinically relevant to the treatment of EV71, the paper shows how  interaction data analysis can be employed in drug discovery.

References:

[1] Han, Lu, et al. “Human enterovirus 71 protein interaction network prompts antiviral drug repositioning.” Scientific Reports 7 (2017).

 

Drawing Networks in LaTeX with tikz-network

While researching on protein interaction networks it is often important to illustrate networks. For this many different tools are available, for example, Python’s NetworkX and Matlab, that allow the export of figures as pixelated images or vector graphics. Usually, these figures are then incorporated in the papers, which are commonly written in LaTeX. In this post, I want to present `tikz-network’, which is a novel tool to code and illustrate networks directly in LaTeX.

To create an illustration you define the network’s nodes with their positions and edges between these nodes. An example of a simple network is

\begin{tikzpicture}
   \Vertex[color = blue]{A}
   \Vertex[x=3,y=1,color=red]{B}
   \Vertex[x=0,y=2,color=orange]{C}
   \Edge[lw=5pt](A)(B)
   \Edge[lw=3pt,bend=15,Direct](A)(C)
\end{tikzpicture}

The illustrations can be much more complex and allow dashed lines, opacity, and many other features. Importantly, the properties do not need to be specified in the LaTeX file itself but can also be saved in an external file and imported with the  \Vertices{data/vertices.csv}command. This allows the representation of more complex networks, for example the multilayer network below is created from the two files, the first representing the nodes

id, x, y ,size, color,opacity,label,layer 
A, 0, 0, .4 , green, .9 , a , 1
B, 1, .7, .6 , , .5 , b , 1
C, 2, 1, .8 ,orange, .3 , c , 1
D, 2, 0, .5 , red, .7 , d , 2
E,.2,1.5, .5 , gray, , e , 1
F,.1, .5, .7 , blue, .3 , f , 2
G, 2, 1, .4 , cyan, .7 , g , 2
H, 1, 1, .4 ,yellow, .7 , h , 2

and the second having the edge information:

u,v,label,lw,color ,opacity,bend,Direct
A,B, ab  ,.5,red   ,   1   ,  30,false
B,C, bc  ,.7,blue  ,   1   , -60,false
A,E, ae  , 1,green ,   1   ,  45,true
C,E, ce  , 2,orange,   1   ,   0,false
A,A, aa  ,.3,black ,  .5   ,  75,false
C,G, cg  , 1,blue  ,  .5   ,   0,false
E,H, eh  , 1,gray  ,  .5   ,   0,false
F,A, fa  ,.7,red   ,  .7   ,   0,true
D,F, df  ,.7,cyan  ,   1   ,   30,true
F,H, fh  ,.7,purple,   1   ,   60,false
D,G, dg  ,.7,blue  ,  .7   ,   60,false

For details, please see the extensive manual on the GitHub page of the project. It is a very new project and I only started using it but I like it so far for a couple of reasons:

  • it is easy to use, especially for small example graphs
  • the multilayer functionality is very convenient
  • included texts are automatically in the correct size and font with the rest of the LaTeX document
  • it can be combined with regular tikz commands to create more complex illustrations

Comparing naive and immunised antibody repertoire

Hi! This is my first post on Blopig as I joined OPIG in July 2017 for my second rotation project and DPhil.

During immune reactions to foreign molecules known as antigens, surface receptors of activated B-cells undergo somatic hypermutation to attain its high binding affinity and specificity to the target antigen. To discover how somatic hypermutation occurs to adapt the antibody from its germline conformation, we can compare the naive and antigen-experienced antibody repertoires. In this paper, the authors developed a protocol to carry out such comparison, detected, synthesised, expressed and validated the observed antibody genes against their target antigen.

What they have done:

  1. Mice immunisation: Naive (no antigens), CGG (a large protein), NP-CGG (hapten attached to a large protein).
  2. Sequencing: Total RNA was extracted from each spleen, cDNA was synthesised according to standard procedures, and amplified with the universal 5’-RACE primer (as oppose to the degenerate 5’-Vh primers) and the 3’-CH1 primer to distinguish between immunoglobulin-classes (IgG1, IgG2c and IgM). High throughput pyrosequencing was then used to recover the heavy chain sequences only.
  3. VDJ recombination analysis: V, D and J segments were assigned and the frequency of the VDJ combinations were plotted in a 3D graph.
  4. Commonality of the VDJ combination: For each VDJ combination, the “commonality” was counted from the average occurrence if n mice have the combination: if n=1, it’s the average occurrence if any 1 mouse has the combination; if n=5, the combination must be observed in all mice to generate a degree of commonality – otherwise it’s 0.
    • The effect of increasing n on commonality scores in IgG1 class: As we tighten the requirement for the commonality calculation, it becomes clear that IGHV9-3 is likely to target the CGG carrier, while IGHV1-72 is against the NP hapten.
    • IGHV9-3 can accommodate a wider range of D gene when targeting CGG alone. IGHV1-72 only uses IGHD1-1.
  5. Clustering V gene usage: Sequences were aligned to the longest sequence in the set (of VDJ combination), and the pairwise distance between sequences in the set were used to cluster the sequences using the UPGMA method.
    • A number of sequences were commonly found in different individuals. Among these sequences, one was randomly selected to proceed to the next step.
  6. Synthesis and validation of the detected antibody against the NP hapten: by comparing the antibody repertoires against the CGG and NP-CGG, the gene of the antibody against NP can be recovered. The authors in this paper chose to pair 3 different light chains to the chosen heavy chain, and assess the binding of the 3 antibodies.
    • NP-CGG bind well to both IGHV1-72 and IGHV9-3 antibodies; NP-BSA to IGHV1-72 only; and CGG to IGHV9-3 only.
    • The binding capabilities are affected by the light chain in the pair.

Key takeaway:

This work presented a metric of defining the “commonality” between individuals’ antibody repertoire and validated the identified antibody against its target antigen by combining with different light chains.

Proteins evolve on the edge of supramolecular self-assembly

Inspired by Eoin’s interesting talks on prions and prion diseases, and Nick’s discussion of how Cyro-Electron microscopy is going to be the end of an era for Crystallography. I thought I’d look at a paper that discusses aggregation of protein complexes, with some cryo-electron microscopy thrown in for good measure.

Supramolecular assembbly

a, A molecule gaining a single self-interacting patch forms a finite dimer. A self-interacting patch repeated on opposite sides of a symmetric molecule can result in infinite assembly. b, A point mutation in a dihedral octamer creates a new self-interacting patch (red), triggering assembly into a fibre.

Supramolecular assemblies are folded protein complexes forming into much larger units. This formation can be triggered by a mutation on a copy of the constituent homomers of the complex, acting as a self-interacting patch. If this patch were to form in a non-symmetric complex, it would likely form a finite assemble with a limited number of copies of the complex. However, if the complex has dihedral symmetry such that a patch is accessible at multiple separated locations, then complex can potentially form near infinite supramolecular assemblies. Continue reading

Slowing the progress of prion diseases

At present, the jury is still out on how prion diseases affect the body let alone how to cure them. We don’t know if amyloid plaques cause neurodegeneration or if they’re the result of it. Due to highly variable glycophosphatidylinositol (GPI) anchors, we don’t know the structure of prions. Due to their incredible resistance to proteolysis, we don’t know a simple way to destroy prions even using in an autoclave. The current recommendation[0] by the World Health Organisation includes the not so subtle: “Immerse in a pan containing 1N sodium hydroxide and heat in a gravity displacement autoclave at 121°C”.

There are several species including Water Buffalo, Horses and Dogs which are immune to prion diseases. Until relatively recently it was thought that rabbits were immune too. “Despite rabbits no longer being able to be classified as resistant to TSEs, an outbreak of ‘mad rabbit disease’ is unlikely”.[1] That being said, other than the addition of some salt bridges and additional H-bonds, we don’t know if that’s why some animals are immune.

We do know at least two species of lichen (P. sulcata and L. plumonaria) have not only discovered a way to naturally break down prions, but they’ve evolved two completely independent pathways to do so. How they accomplish this? We’re still not sure in fact, it was only last year that it was discovered that lichens may be composed of three symbiotic partnerships and not two as previously thought.[3]

With all this uncertainty, one thing is known: PrPSc, the pathogenic form of the Prion converts PrPC, the cellular form. Just preventing the production of PrPC may not be a good idea, mainly because we don’t know what it’s there for in the first place. Previous studies using PrP-knockout have shown hints that:

  • Hematopoietic stem cells express PrP on their cell membrane. PrP-null stem cells exhibit increased sensitivity to cell depletion. [4]
  • In mice, cleavage of PrP proteins in peripheral nerves causes the activation of myelin repair in Schwann Cells. Lack of PrP proteins caused demyelination in those cells. [5]
  • Mice lacking genes for PrP show altered long-term potentiation in the hippocampus. [6]
  • Prions have been indicated to play an important role in cell-cell adhesion and intracellular signalling.[7]

However, an alternative approach which bypasses most of the unknowns above is if it were possible to make off with the substrate which PrPSc uses, the progress of the disease might be slowed. A study by R Diaz-Espinoza et al. was able to show that by infecting animals with a self-replicating non-pathogenic prion disease it was possible to slow the fatal 263K scrapie agent. From their paper [8], “results show that a prophylactic inoculation of prion-infected animals with an anti-prion delays the onset of the disease and in some animals completely prevents the development of clinical symptoms and brain damage.”

[0] https://www.cdc.gov/prions/cjd/infection-control.html
[1] https://www.ncbi.nlm.nih.gov/pmc/articles/PMC3323982/
[2] https://blogs.scientificamerican.com/artful-amoeba/httpblogsscientificamericancomartful-amoeba20110725lichens-vs-the-almighty-prion/
[3] http://science.sciencemag.org/content/353/6298/488
[4] “Prion protein is expressed on long-term repopulating hematopoietic stem cells and is important for their self-renewal”. PNAS. 103 (7): 2184–9. doi:10.1073/pnas.0510577103
[5] Abbott A (2010-01-24). “Healthy prions protect nerves”. Nature. doi:10.1038/news.2010.29
[6] Maglio LE, Perez MF, Martins VR, Brentani RR, Ramirez OA (Nov 2004). “Hippocampal synaptic plasticity in mice devoid of cellular prion protein”. Brain Research. Molecular Brain Research. 131 (1-2): 58–64. doi:10.1016/j.molbrainres.2004.08.004
[7] Málaga-Trillo E, Solis GP, et al. (Mar 2009). Weissmann C, ed. “Regulation of embryonic cell adhesion by the prion protein”. PLoS Biology. 7 (3): e55. doi:10.1371/journal.pbio.1000055
[8] http://www.nature.com/mp/journal/vaop/ncurrent/full/mp201784a.html

Journal Club: Statistical database analysis of the role of loop dynamics for protein-protein complex formation and allostery

As I’ve mentioned on this blog a few (ok, more than a few) times before, loops are often very important regions of a protein, allowing it to carry out its function effectively. In my own research, I develop methods for loop structure prediction (in particular for antibody CDR H3), and look at loop conformational changes and flexibility. So, when I came across a paper that has the words ‘loops’, ‘flexibility’ and ‘antibody’ in its abstract, it was the obvious choice to present at my most recent journal club!

In the paper, entitled “Statistical database analysis of the role of loop dynamics for protein-protein complex formation and allostery”, the authors focus on how loop dynamics change upon the formation of protein-protein complexes. To do this, they use an algorithm they previously published called ToeLoop – given a protein structure, this classifies the loop regions as static, slow, or fast, based on both sequential and structural features:

  • relative amino acid frequencies;
  • the frequency of loop secondary structure types as annotated by DSSP (bends, β-bridges etc.);
  • the average solvent accessible surface area;
  • the average hydrophobicity index for the loop residues;
  • loop length;
  • contacts between atoms of the loop and the rest of the protein.

Two scores are calculated using the properties listed above: one that distinguishes ‘static’ loops from ‘mobile’ loops (with a reported 81% accuracy), and another that further categorises the mobile loops into ‘slow’ and ‘fast’ (74% accuracy). Results from the original ToeLoop paper indicate that fast loops are shorter, have more negatively charged residues, larger solvent accessibilities, lower hydrophobicity, and fewer contacts.

Gu et al. use ToeLoop to investigate the dynamic behaviour of loops during protein-protein complex formation. For a set of 230 protein complexes, they classified the loops of the proteins in both their free and complexed forms (illustrated by the figure below).

The loops from 230 protein complexes, in both free and bound forms, were categorised as fast, slow, or static using the ToeLoop algorithm. The loops are coloured according to their predicted dynamics. Allosteric loops, defined as those whose mobility increases upon binding, are indicated using blue arrows.

In the uncomplexed form, the majority of loops were annotated as static (63.6%), followed by slow (26.2%) and finally fast (10.2%). This indicates that most loops are inflexible. After complex formation, the number of static loops increases and the number of mobile loops decreases (67.8%, 23.0%, and 9.2% for static, slow and fast respectively). Mobility, on the whole, is therefore reduced upon binding, which is as expected – the presence of a binding partner restricts the range of possible movement.

The authors then divided the loops into two groups, interface and non-interface, according to the average minimum distance of each loop residue to the binding partner (cutoff values from 4 to 8 Å were tested and each gave broadly similar results). The dynamics of non-interface loops changed less upon binding than those of the interface loops (again, this was as expected). However, an interesting result is that slow loops are more common at the interface than any other parts of the protein, with 37.2% of interface loops being annotated as slow compared to 24.8% of non-interface loops. It is suggested by the authors that this is due to protein promiscuity; i.e. slow loops allow proteins to bind to different partners.

The 4600 loops analysed in the study were split into two groups based on their proximity to the interface. As expected, interface loops are affected more by binding than non-interface loops. Slow loops are more prevalent at the interface than elsewhere on the protein.

Binding-induced dynamic changes were then investigated in more detail, by dividing the loops into 9 categories based on the transition (i.e. static-static, slow-static, slow-fast etc.). The dynamic behaviour of most loops (4120 out of 4600) does not change, and those loops whose mobility decreased upon binding were found close to the interface (average distance of ~12 Å). A small subset of the loops (termed allosteric by the authors) demonstrated an increase in flexibility upon complex formation (142 out of 4600); these tended to be located further away from the interface (average distance of ~30 Å).

One of these allosteric loops was investigated further as part of a case study. The complex in question was an antibody-antigen complex, in which one loop distant from the binding site transitioned from static to slow upon binding. The loops directly involved in binding (the CDRs) either displayed reduced flexibility or remained static. The presence of an allosteric loop was supported by experimental data – the loop is shown to change conformation upon binding (RMSD of 3.6 Å between bound and unbound crystal structures from the PDB), and the average B-factor for the loop atoms increased on complex formation from around 26 Å2 to approximately 140 Å2. The authors also carried out MD simulations of the unbound antibody and antigen as well as the complex, and showed that the loop moved more in the complex than in the free antibody. The authors propose that the increased flexibility of the loop offsets the entropy loss that occurs due to binding, thereby increasing the strength of binding. ToeLoop could, therefore, be a useful tool in the development of antibody therapies (or other protein drugs) – it could be used in tandem with an antibody modelling protocol, allowing the dynamic behaviour of loop regions to be monitored and possibly designed to increase affinities.

Finally, the authors explored the link between loop dynamics and binding affinity. Again, they used ToeLoop to predict the flexibility of loops, but this time the complexes were from a set of 170 with known affinity. They demonstrated that affinity is correlated with the number of static loop residues present at the interface – ‘strong’ binders (those with picomolar affinity) tend to contain more static residues than more weakly binding pairs of proteins. This is in accordance with the theory that the rigidification of flexible loops upon binding leads to lower affinities, due to the loss of entropy.

Typography in graphs.

Typography [tʌɪˈpɒɡrəfi]
    n.: the style and appearance of printed matter.

Perhaps a “glossed” feature of making graphs, having the right font goes a long way. Not only do we have the advantage of using a “pretty” font that we like, it also provides an aesthetic satisfaction of having everything (e.g. in a PhD thesis) in the same font, i.e. both the text and graph use the same font.

Fonts can be divided into two types: serif and sans-serif. Basically, serif fonts are those where the letters have little “bits” at the end; think of Times New Roman or Garamond as the classic examples. Sans-serif fonts are those that lack these bits, and give it a more “blocky”, clean finish – think of Arial or Helvetica as a classic example.

Typically, serif fonts are better for books/printed materials, whereas sans-serif fonts are better for web/digital content. As it follows, then what about graphs? Especially those that may go out in the public domain (whether it’s through publishing, or in a web site)?

This largely bottles down to user preference, and choosing the right font is not trivial. Supposing that you have (say, from Google Fonts), then there are a few things we need to do (e.g. make sure that your TeX distribution and Illustrator have the font). However, this post is concerned with how we can use custom fonts in a graph generated by Matplotlib, and why this is useful. My favourite picks for fonts include Roboto and Palatino.

The default font in matplotlib isn’t the prettiest ( I think) for publication/keeping purposes, but I digress…

To start, let’s generate a histogram of 1000 random numbers from a normal distribution.

The default font in matplotlib, bitstream sans, isn’t the prettiest thing on earth. Does the job but it isn’t my go-to choice if I can change it. Plus, with lots of journals asking for Type 1/TrueType fonts for images, there’s even more reason to change this anyway (matplotlib, by default, generates graphs using Type 3 fonts!). If we now change to Roboto or Palatino, we get the following:

Sans-serif Roboto.

Serif font Palatino.

Basically, the bits we need to include at the beginning of our code are here:

# Need to import matplotlib options setting method
# Set PDF font types - not necessary but useful for publications
from matplotlib import rcParams
rcParams['pdf.fonttype'] = 42

# For sans-serif
from matplotlib import rc
rc("font", **{"sans-serif": ["Roboto"]}

# For serif - matplotlib uses sans-serif family fonts by default
# To render serif fonts, you also need to tell matplotlib to use LaTeX in the backend.
rc("font", **{"family": "serif", "serif": ["Palatino"]})
rc("text", usetex = True)

This not only guarantees that images are generated using a font of our choice, but it gives a Type 1/TrueType font too. Ace!

Happy plotting.

Using Random Forests in Python with Scikit-Learn

I spend a lot of time experimenting with machine learning tools in my research; in particular I seem to spend a lot of time chasing data into random forests and watching the other side to see what comes out. In my many hours of Googling “random forest foobar” a disproportionate number of hits offer solutions implemented in R. As a young Pythonista in the present year I find this a thoroughly unacceptable state of affairs, so I decided to write a crash course in how to build random forest models in Python using the machine learning library scikit-learn (or sklearn to friends). This is far from exhaustive, and I won’t be delving into the machinery of how and why we might want to use a random forest. Rather, the hope is that this will be useful to anyone looking for a hands-on introduction to random forests (or machine learning in general) in Python.

In the future I’ll write a more in-depth post on how a few libraries turn Python into a powerful environment for data handling and machine learning. Until then, though, let’s jump into random forests!

Toy datasets

Sklearn comes with several nicely formatted real-world toy data sets which we can use to experiment with the tools at our disposal. We’ll be using the venerable iris dataset for classification and the Boston housing set for regression. Sklearn comes with a nice selection of data sets and tools for generating synthetic data, all of which are well-documented. Now, let’s write some Python!

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns

from sklearn import datasets
iris = datasets.load_iris()

Classification using random forests

First we’ll look at how to do solve a simple classification problem using a random forest. The iris dataset is probably the most widely-used example for this problem and nicely illustrates the problem of classification when some classes are not linearly separable from the others.

First we’ll load the iris dataset into a pandas dataframe. Pandas is a nifty Python library which provides a data structure comparable to the dataframes found in R with database style querying. As an added bonus, the seaborn visualization library integrates nicely with pandas allowing us to generate a nice scatter matrix of our data with minimal fuss.

df = pd.DataFrame(iris.data, columns=iris.feature_names)

# sklearn provides the iris species as integer values since this is required for classification
# here we're just adding a column with the species names to the dataframe for visualisation
df['species'] = np.array([iris.target_names[i] for i in iris.target])

sns.pairplot(df, hue='species')

Neat. Notice that iris-setosa is easily identifiable by petal length and petal width, while the other two species are much more difficult to distinguish. We could do all sorts of pre-processing and exploratory analysis at this stage, but since this is such a simple dataset let’s just fire on. We’ll do a bit of pre-processing later when we come to the Boston data set.

First, let’s split the data into training and test sets. We’ll used stratified sampling by iris class to ensure both the training and test sets contain a balanced number of representatives of each of the three classes. Sklearn requires that all features and targets be numeric, so the three classes are represented as integers (0, 1, 2). Here we’re doing a simple 50/50 split because the data are so nicely behaved. Typically however we might use a 75/25 or even 80/20 training/test split to ensure we have enough training data. In true Python style this is a one-liner.

from sklearn.model_selection import train_test_split

X_train, X_test, y_train, y_test = train_test_split(df[iris.feature_names], iris.target, test_size=0.5, stratify=iris.target, random_state=123456)

Now let’s fit a random forest classifier to our training set. For the most part we’ll use the default settings since they’re quite robust. One exception is the out-of-bag estimate: by default an out-of-bag error estimate is not computed, so we need to tell the classifier object that we want this.

If you’re used to the R implementation, or you ever find yourself having to compare results using the two, be aware that some parameter names and default settings are different between the two. Fortunately both have excellent documentation so it’s easy to ensure you’re using the right parameters if you ever need to compare models.

from sklearn.ensemble import RandomForestClassifier

rf = RandomForestClassifier(n_estimators=100, oob_score=True, random_state=123456)
rf.fit(X_train, y_train)

Let’s see how well our model performs when classifying our unseen test data. For a random forest classifier, the out-of-bag score computed by sklearn is an estimate of the classification accuracy we might expect to observe on new data. We’ll compare this to the actual score obtained on our test data.

from sklearn.metrics import accuracy_score

predicted = rf.predict(X_test)
accuracy = accuracy_score(y_test, predicted)

print(f'Out-of-bag score estimate: {rf.oob_score_:.3}')
print(f'Mean accuracy score: {accuracy:.3}')
Out-of-bag score estimate: 0.973
Mean accuracy score: 0.933

Not bad. However, this doesn’t really tell us anything about where we’re doing well. A useful technique for visualising performance is the confusion matrix. This is simply a matrix whose diagonal values are true positive counts, while off-diagonal values are false positive and false negative counts for each class against the other.

from sklearn.metrics import confusion_matrix

cm = pd.DataFrame(confusion_matrix(y_test, predicted), columns=iris.target_names, index=iris.target_names)
sns.heatmap(cm, annot=True)

This lets us know that our model correctly separates the setosa examples, but exhibits a small amount of confusion when attempting to distinguish between versicolor and virginica.

Random forest regression

Now let’s look at using a random forest to solve a regression problem. The Boston housing data set consists of census housing price data in the region of Boston, Massachusetts, together with a series of values quantifying various properties of the local area such as crime rate, air pollution, and student-teacher ratio in schools. The question for us is whether we can use these data to accurately predict median house prices. One caveat of this data set is that the median house price is truncated at $50,000 which suggests that there may be considerable noise in this region of the data. You might want to remove all data with a median house price of $50,000 from the set and see if the regression improves at all.

As before we’ll load the data into a pandas dataframe. This time, however, we’re going to do some pre-processing of our data by independently transforming each feature to have zero mean and unit variance. The values of different features vary greatly in order of magnitude. If we were to analyse the raw data as-is, we run the risk of our analysis being skewed by certain features dominating the variance. This isn’t strictly necessary for a random forest, but will enable us to perform a more meaningful principal component analysis later. Performing this transformation in sklearn is super simple using the StandardScaler class of the preprocessing module. This time we’re going to use an 80/20 split of our data. You could bin the house prices to perform stratified sampling, but we won’t worry about that for now.

boston = datasets.load_boston()

features = pd.DataFrame(boston.data, columns=boston.feature_names)
targets = boston.target

As before, we’ve loaded our data into a pandas dataframe. Notice how I have to construct new dataframes from the transformed data. This is because sklearn is built around numpy arrays. While it’s possible to return a view of a dataframe as an array, transforming the contents of a dataframe requires a little more work. Of course, there’s a library for that, but I’m lazy so I didn’t use it this time.

from sklearn.preprocessing import StandardScaler

X_train, X_test, y_train, y_test = train_test_split(features, targets, train_size=0.8, random_state=42)

scaler = StandardScaler().fit(X_train)
X_train_scaled = pd.DataFrame(scaler.transform(X_train), index=X_train.index.values, columns=X_train.columns.values)
X_test_scaled = pd.DataFrame(scaler.transform(X_test), index=X_test.index.values, columns=X_test.columns.values)

With the data standardised, let’s do a quick principal-component analysis to see if we could reduce the dimensionality of the problem. This is quick and easy in sklearn using the PCA class of the decomposition module.

from sklearn.decomposition import PCA

pca = PCA()
pca.fit(X_train)
cpts = pd.DataFrame(pca.transform(X_train))
x_axis = np.arange(1, pca.n_components_+1)
pca_scaled = PCA()
pca_scaled.fit(X_train_scaled)
cpts_scaled = pd.DataFrame(pca.transform(X_train_scaled))

# matplotlib boilerplate goes here

Notice how without data standardisation the variance is completely dominated by the first principal component. With standardisation, however, we see that in fact we must consider multiple features in order to explain a significant proportion of the variance. You might want to experiment with building regression models using the principal components (or indeed just combinations of the raw features) to see how well you can do with less information. For now though we’re going to use all of the (scaled) features as the regressors for our model. As with the classification problem fitting the random forest is simple using the RandomForestRegressor class.

from sklearn.ensemble import RandomForestRegressor

rf = RandomForestRegressor(n_estimators=500, oob_score=True, random_state=0)
rf.fit(X_train, y_train)

Now let’s see how we do on our test set. As before we’ll compare the out-of-bag estimate (this time it’s an R-squared score) to the R-squared score for our predictions. We’ll also compute Spearman rank and Pearson correlation coefficients for our predictions to get a feel for how we’re doing.

from sklearn.metrics import r2_score
from scipy.stats import spearmanr, pearsonr

predicted_train = rf.predict(X_train)
predicted_test = rf.predict(X_test)

test_score = r2_score(y_test, predicted_test)
spearman = spearmanr(y_test, predicted_test)
pearson = pearsonr(y_test, predicted_test)

print(f'Out-of-bag R-2 score estimate: {rf.oob_score_:>5.3}')
print(f'Test data R-2 score: {test_score:>5.3}')
print(f'Test data Spearman correlation: {spearman[0]:.3}')
print(f'Test data Pearson correlation: {pearson[0]:.3}')
Out-of-bag R-2 score estimate: 0.841
Test data R-2 score: 0.886
Test data Spearman correlation: 0.904
Test data Pearson correlation: 0.942

Not too bad, though there are a few outliers that would be worth looking into. Your challenge, should you choose to accept it, is to see if removing the $50,000 data improves the regression.

Wrapping up

Congratulations on making it this far. Now you know how to pre-process your data and build random forest models all from the comfort of your iPython session. I plan on writing more in the future about how to use Python for machine learning, and in particular how to make use of some of the powerful tools available in sklearn (a pipeline for data preparation, model fitting, prediction, in one line of Python? Yes please!), and how to make sklearn and pandas play nicely with minimal hassle. If you’re lucky, and if I can bring myself to process the data nicely, I might include some fun examples from less well-behaved real-world data sets.

Until then, though, happy Pythoning!

Biological Space – a starting point in in-silico drug design and in experimentally exploring biological systems

What is the “biological space” and why is this space so important for all researchers interested in developing novel drugs? In the following, I will first establish a definition of the biological space and then highlight its use in computationally developing novel drug compounds and as a starting point in the experimental exploration of biological systems.

While chemical space has been defined as the entirety of all possible chemical compounds which could ever exist, the definition of biological space is less clear. In the following, I define biological space as the area(s) of chemical space that possess biologically active (”bioactive”) compounds for a specific target or target class1. As such, they can modulate a given biological system and subsequently influence disease development and progression. In literature, this space has also been called “biologically relevant chemical space”2.

Only a small percentage of the vast chemical space has been estimated to be biologically active and is thus relevant for drug development, as randomly searching bioactive compounds in chemical space with no prior information resembles the search for “the needle in a haystack”. Hence, it should come as no surprise that bioactive molecules are often used as a starting point in in-silico explorations of biological space.
The plethora of in-silico methods for this task includes similarity and pharmacophore searching methods3-6 for novel compounds, scaffold-hopping approaches to derive novel chemotypes7-8 or the development of quantitative structure-activity relationships (QSAR)9-10 to explore the interplay between the 3D chemical structure and its biological activity towards a specific target.

The biological space is comprised of small molecules which are active on specific targets. If researchers want to explore the role the role of targets in a given biological system experimentally, they can use small molecules which are potent and selective towards a specific target (thus confided to a particular area in chemical space)11-12.
Due to their high selectivity ( f.e. a greater than 30-fold selectivity towards proteins of the same family12), these so-called “tool compounds” can help establish the biological tractability – the relationship between the target and a given phenotype – and its clinical tractability – the availability of biomarkers – of a target11. They are thus highly complementary to methods such as RNAi, CRISPR12 and knock-out animals11. Consequently, tool compounds are used in drug target validation and the information they provide on the biological system can increase the probability of a successful drug 11. Most importantly, tool compounds are particularly important to annotate targets in currently unexplored biological systems and thus important for novel drug development13.

  1. Sophie Petit-Zeman, http://www.nature.com/horizon/chemicalspace/background/figs/explore_b1.html, accessed on 03.07.2016.
  2. Koch, M. A. et al. Charting biologically relevant chemical space: a structural classification of natural products (SCONP). Proceedings of the National Academy of Sciences of the United States of America 102, 17272–17277 (2005).
  3. Stumpfe, D. & Bajorath, J. Similarity searching. Wiley Interdisciplinary Reviews: Computational Molecular Science 1, 260–282 (2011).
  4. Bender, A. et al. How Similar Are Similarity Searching Methods? A Principal Component Analysis of Molecular Descriptor Space. Journal of Chemical Information and Modeling 49, 108–119 (2009).
  5. Ai, G. et al. A combination of 2D similarity search, pharmacophore, and molecular docking techniques for the identification of vascular endothelial growth factor receptor-2 inhibitors: Anti-Cancer Drugs 26, 399–409 (2015).
  6. Willett, P., Barnard, J. M. & Downs, G. M. Chemical Similarity Searching. Journal of Chemical Information and Computer Sciences 38, 983–996 (1998)
  7. Sun, H., Tawa, G. & Wallqvist, A. Classification of scaffold-hopping approaches. Drug Discovery Today 17, 310–324 (2012).
  8. Hu, Y., Stumpfe, D. & Bajorath, J. Recent Advances in Scaffold Hopping: Miniperspective. Journal of Medicinal Chemistry 60, 1238–1246 (2017)
  9. Cruz-Monteagudo, M. et al. Activity cliffs in drug discovery: Dr Jekyll or Mr Hyde? Drug Discovery Today 19, 1069–1080 (2014).
  10. Bradley, A. R., Wall, I. D., Green, D. V. S., Deane, C. M. & Marsden, B. D. OOMMPPAA: A Tool To Aid Directed Synthesis by the Combined Analysis of Activity and Structural Data. Journal of Chemical Information and Modeling 54, 2636–2646 (2014).
  11. Garbaccio, R. & Parmee, E. The Impact of Chemical Probes in Drug Discovery: A Pharmaceutical Industry Perspective. Cell Chemical Biology 23, 10–17 (2016).
  12. Arrowsmith, C. H. et al. The promise and peril of chemical probes. Nature Chemical Biology 11, 536–541 (2015).
  13. Fedorov, O., Müller, S. & Knapp, S. The (un) targeted cancer kinome. Nature chemical biology 6, 166–169 (2010).