The Globin family revisited

Last lab class we used HBB (beta globin) as a search query of the RefSeq database using PSI-BLAST. This allowed us to find distant human globin sequences such as neuroglobin, cytoglobin and of course myoglobin. Critically we could not find these more distant (i.e. diverged in sequence) globins with a regular BLAST search.

We also examined and compared the atomic resolution structures of beta globin and myoglobin and found them to be remarkably similar. A key findings here was that the traces of common ancestry are very much apparent at the structural level even when the sequences of these homologues have diverged beyond the detection limits of conventional methods like protein BLAST. Recall that we had to do quite a bit of extra work with PSI-BLAST to find these homologues sequences. If this does not sound familiar please go back to the lab section for class 3.

Here we use the results from PSI-BLAST (last lab session end of section 3) together with some R code to dig deeper into these results for mechanistic insight into important functional features of all globins.

Step 1. Read our globin alignment

We will use the bio3d R package to read the FASTA formatted alignment we generated last day. Note that you will need to have the bio3d package installed (via the R command install.packages("bio3d") for this to work on your computer). We will talk more about R packages in a couple of classes time.

library(bio3d)
## Warning: package 'bio3d' was built under R version 4.1.2
# Feel free to use your own alignment input here
inputfile <- "https://bioboot.github.io/bimm143_F21/class-material/globin_alignment.fa"

aln <- read.fasta( inputfile )

Examine a print out of this alignment, note visually any conserved positions.

aln
##                 1        .         .         .         .         .         60 
## beta            ---------------MVHLTPEEKSAVTALWGKV--NVDEVGGEALGRLLVVYPWTQRFF
## delta           ---------------MVHLTPEEKTAVNALWGKV--NVDAVGGEALGRLLVVYPWTQRFF
## gamma-2         ---------------MGHFTEEDKATITSLWGKV--NVEDAGGETLGRLLVVYPWTQRFF
## epsilon         ---------------MVHFTAEEKAAVTSLWSKM--NVEEAGGEALGRLLVVYPWTQRFF
## gamma-1         ---------------MGHFTEEDKATITSLWGKV--NVEDAGGETLGRLLVVYPWTQRFF
## zeta            ----------------MSLTKTERTIIVSMWAKISTQADTIGTETLERLFLSHPQTKTYF
## alpha           ----------------MVLSPADKTNVKAAWGKVGAHAGEYGAEALERMFLSFPTTKTYF
## cytoglobin-X1   MEKVPGEMEIERRERSEELSEAERKAVQAMWARLYANCEDVGVAILVRFFVNFPSAKQYF
## mu              -----------------MLSAQERAQIAQVWDLIAGHEAQFGAELLLRLFTVYPSTKVYF
## theta-1         ----------------MALSAEDRALVRALWKKLGSNVGVYTTEALERTFLAFPATKTYF
## cytoglobin      MEKVPGEMEIERRERSEELSEAERKAVQAMWARLYANCEDVGVAILVRFFVNFPSAKQYF
## cytoglobin-X2   ------------------------------------------------------------
## myoglobin-1     ----------------MGLSDGEWQLVLNVWGKVEADIPGHGQEVLIRLFKGHPETLEKF
## neuroglobin     ------------------MERPEPELIRQSWRAVSRSPLEHGTVLFARLFALEPDLLPLF
## myoglobin-2     ------------------------------------------------------------
##                                                                              
##                 1        .         .         .         .         .         60 
## 
##                61        .         .         .         .         .         120 
## beta            E-SFGDLSTPDAVM-GNPKVKAHGKKVLGAFSDGLAHLDNLKGT---FATLSELHCDKLH
## delta           E-SFGDLSSPDAVM-GNPKVKAHGKKVLGAFSDGLAHLDNLKGT---FSQLSELHCDKLH
## gamma-2         D-SFGNLSSASAIM-GNPKVKAHGKKVLTSLGDAIKHLDDLKGT---FAQLSELHCDKLH
## epsilon         D-SFGNLSSPSAIL-GNPKVKAHGKKVLTSFGDAIKNMDNLKPA---FAKLSELHCDKLH
## gamma-1         D-SFGNLSSASAIM-GNPKVKAHGKKVLTSLGDATKHLDDLKGT---FAQLSELHCDKLH
## zeta            P-HF-------DLHPGSAQLRAHGSKVVAAVGDAVKSIDDIGGA---LSKLSELHAYILR
## alpha           P-HF-------DLSHGSAQVKGHGKKVADALTNAVAHVDDMPNA---LSALSDLHAHKLR
## cytoglobin-X1   S-QFKHMEDPLEME-RSPQLRKHACRVMGALNTVVENLHDPDKVSSVLALVGKAHALKHK
## mu              P-HL------SACQ-DATQLLSHGQRMLAAVGAAVQHVDNLRAA---LSPLADLHALVLR
## theta-1         S-H-------LDLSPGSSQVRAHGQKVADALSLAVERLDDLPHA---LSALSHLHACQLR
## cytoglobin      S-QFKHMEDPLEME-RSPQLRKHACRVMGALNTVVENLHDPDKVSSVLALVGKAHALKHK
## cytoglobin-X2   ------MEDPLEME-RSPQLRKHACRVMGALNTVVENLHDPDKVSSVLALVGKAHALKHK
## myoglobin-1     D-KFKHLKSEDEMK-ASEDLKKHGATVLTALGGILKKKGHHEAE---IKPLAQSHATKHK
## neuroglobin     QYNCRQFSSPEDCL-SSPEFLDHIRKVMLVIDAAVTNVEDLSSLEEYLASLGRKHRA-VG
## myoglobin-2     ------------MK-ASEDLKKHGATVLTALGGILKKKGHHEAE---IKPLAQSHATKHK
##                                       *   ^                       ^   *      
##                61        .         .         .         .         .         120 
## 
##               121        .         .         .         .         .         180 
## beta            VDPENFRLLGNVLVCVLAHHFGKEFTPPVQAAYQKVVAGVANALAHKYH-----------
## delta           VDPENFRLLGNVLVCVLARNFGKEFTPQMQAAYQKVVAGVANALAHKYH-----------
## gamma-2         VDPENFKLLGNVLVTVLAIHFGKEFTPEVQASWQKMVTGVASALSSRYH-----------
## epsilon         VDPENFKLLGNVMVIILATHFGKEFTPEVQAAWQKLVSAVAIALAHKYH-----------
## gamma-1         VDPENFKLLGNVLVTVLAIHFGKEFTPEVQASWQKMVTAVASALSSRYH-----------
## zeta            VDPVNFKLLSHCLLVTLAARFPADFTAEAHAAWDKFLSVVSSVLTEKYR-----------
## alpha           VDPVNFKLLSHCLLVTLAAHLPAEFTPAVHASLDKFLASVSTVLTSKYR-----------
## cytoglobin-X1   VEPVYFKILSGVILEVVAEEFASDFPPETQRAWAKLRGLIYSHVTAAYKEVGWVQQVPNA
## mu              VDPANFPLLIQCFHVVLASHLQDEFTVQMQAAWDKFLTGVAVVLTEKYR-----------
## theta-1         VDPASFQLLGHCLLVTLARHYPGDFSPALQASLDKFLSHVISALVSEYR-----------
## cytoglobin      VEPVYFKILSGVILEVVAEEFASDFPPETQRAWAKLRGLIYSHVTAAYKEVGWVQQVPNA
## cytoglobin-X2   VEPVYFKILSGVILEVVAEEFASDFPPETQRAWAKLRGLIYSHVTAAYKEVGWVQQVPNA
## myoglobin-1     IPVKYLEFISECIIQVLQSKHPGDFGADAQGAMNKALELFRKDMASNYKELGFQG-----
## neuroglobin     VKLSSFSTVGESLLYMLEKCLGPAFTPATRAAWSQLYGAVVQAMSRGWDGE---------
## myoglobin-2     IPVKYLEFISECIIQVLQSKHPGDFGADAQGAMNKALELFRKDMASNYKELGFQG-----
##                 ^       ^       ^       *                  ^   ^             
##               121        .         .         .         .         .         180 
## 
##               181        .         .    205 
## beta            -------------------------
## delta           -------------------------
## gamma-2         -------------------------
## epsilon         -------------------------
## gamma-1         -------------------------
## zeta            -------------------------
## alpha           -------------------------
## cytoglobin-X1   TTHSSWRRSPEGSWGRQASCPSCC-
## mu              -------------------------
## theta-1         -------------------------
## cytoglobin      TTPP-------------ATLPSSGP
## cytoglobin-X2   TTHSSWRRSPEGSWGRQASCPSCC-
## myoglobin-1     -------------------------
## neuroglobin     -------------------------
## myoglobin-2     -------------------------
##                                           
##               181        .         .    205 
## 
## Call:
##   read.fasta(file = inputfile)
## 
## Class:
##   fasta
## 
## Alignment dimensions:
##   15 sequence rows; 205 position columns (92 non-gap, 113 gap) 
## 
## + attr: id, ali, call

Doing things visually and manually counting characters in an alignment such as this is not much fun and very susceptible to making mistakes. Let’s use some code to help.

Step 2. Identifying conserved positions

First we will score positional conservation in the alignment with the conserv() function.

sim <- conserv(aln)

Make a quick plot of alignment position vs conservation score.

plot(sim, typ="h", xlab="Alignment position", ylab="Conservation score")

Here the high bars represent the most conserved amino-acid positions.

Let’s order our sim vector of conservation scores to put the most conserved (highest scoring) first. What positions are the most conserved?

inds <- order(sim, decreasing=TRUE)
head(sim[inds])
## [1] 1.0000000 1.0000000 1.0000000 0.8933333 0.8933333 0.8666667

The top three positions are absolutely invariant here. Let’s use the ordering indices determened with the order() function above to find out more about the positions.

To help we can make a dataframe that has all the information we might want, such as position number in the alignment, the amino acid in our first beta globin sequence and conservation score.

positions <- data.frame(pos=1:length(sim),
                        aa=aln$ali[1,],
                        score=sim)

head(positions)
##   pos aa      score
## 1   1  - 0.00952381
## 2   2  - 0.00952381
## 3   3  - 0.00952381
## 4   4  - 0.00952381
## 5   5  - 0.00952381
## 6   6  - 0.00952381

Note the first 6 positions of the alignment are gap characters in the beta globin sequence and have very low (close to zero) conservation scores.

Let’s use the ordering vector from above to look at the most conserved positions:

head( positions[inds,] )
##     pos aa     score
## 83   83  H 1.0000000
## 115 115  H 1.0000000
## 145 145  F 1.0000000
## 87   87  V 0.8933333
## 155 155  K 0.8933333
## 168 168  Y 0.8666667

Nice, this shows us that positions 83, 115 and 145 are indeed very conserved.

Let’s convert the one-letter code for these amino acids to 3 letter code.

aa123(positions[inds,]$aa)[1:3]
## [1] "HIS" "HIS" "PHE"

In the figure below I mapped these top two Histidne amino acids to atomic structure (we will see how to do this in R later in the course). Note that these conserved positions are responsible for coordinating the all important iron containing heam group (a.k.a. Porphyrin ring).

Beta globin structure with two conserved Histidine resides (blue spheres) and Porphyrin ring (cyan) shown.

Step 3. Relationship between sequences

Here we calculate the sequence identity between all pairs of sequences (with the seqidentity() function) and use the resulting matrix of identity scores to generate a heatmap visualization of the relationship between sequences. This is a common visualization in bioinformatcs and we will revisit it several times in the course (especially with NGS data analysis).

Note here we use the pheatmap package, which again needs to be installed on your computer with the R code install.packages("pheatmap").

library(pheatmap)

ide <- seqidentity(aln)
pheatmap((1-ide))

LS0tCnRpdGxlOiAiR2xvYmluIGNvbnNlcnZhdGlvbiBhbmFseXNpcyIKb3V0cHV0OiAKICBodG1sX2RvY3VtZW50OgogICAgdG9jOiB0cnVlCiAgICBoaWdobGlnaHQ6IHB5Z21lbnRzCiAgICBjb2RlX2Rvd25sb2FkOiB0cnVlCi0tLQoKIyMgVGhlIEdsb2JpbiBmYW1pbHkgcmV2aXNpdGVkCgpMYXN0IGxhYiBjbGFzcyB3ZSB1c2VkIEhCQiAoYmV0YSBnbG9iaW4pIGFzIGEgc2VhcmNoIHF1ZXJ5IG9mIHRoZSBSZWZTZXEgZGF0YWJhc2UgdXNpbmcgUFNJLUJMQVNULiBUaGlzIGFsbG93ZWQgdXMgdG8gZmluZCBkaXN0YW50IGh1bWFuIGdsb2JpbiBzZXF1ZW5jZXMgc3VjaCBhcyBuZXVyb2dsb2JpbiwgY3l0b2dsb2JpbiBhbmQgb2YgY291cnNlIG15b2dsb2Jpbi4gQ3JpdGljYWxseSB3ZSBjb3VsZCBub3QgZmluZCB0aGVzZSBtb3JlIGRpc3RhbnQgKGkuZS4gZGl2ZXJnZWQgaW4gc2VxdWVuY2UpIGdsb2JpbnMgd2l0aCBhIHJlZ3VsYXIgQkxBU1Qgc2VhcmNoLgoKV2UgYWxzbyBleGFtaW5lZCBhbmQgY29tcGFyZWQgdGhlIGF0b21pYyByZXNvbHV0aW9uIHN0cnVjdHVyZXMgb2YgYmV0YSBnbG9iaW4gYW5kIG15b2dsb2JpbiBhbmQgZm91bmQgdGhlbSB0byBiZSByZW1hcmthYmx5IHNpbWlsYXIuIEEga2V5IGZpbmRpbmdzIGhlcmUgd2FzIHRoYXQgdGhlIHRyYWNlcyBvZiBjb21tb24gYW5jZXN0cnkgYXJlIHZlcnkgbXVjaCBhcHBhcmVudCBhdCB0aGUgc3RydWN0dXJhbCBsZXZlbCBldmVuIHdoZW4gdGhlIHNlcXVlbmNlcyBvZiB0aGVzZSBob21vbG9ndWVzIGhhdmUgZGl2ZXJnZWQgYmV5b25kIHRoZSBkZXRlY3Rpb24gbGltaXRzIG9mIGNvbnZlbnRpb25hbCBtZXRob2RzIGxpa2UgcHJvdGVpbiBCTEFTVC4gUmVjYWxsIHRoYXQgd2UgaGFkIHRvIGRvIHF1aXRlIGEgYml0IG9mIGV4dHJhIHdvcmsgd2l0aCBQU0ktQkxBU1QgdG8gZmluZCB0aGVzZSBob21vbG9ndWVzIHNlcXVlbmNlcy4gSWYgdGhpcyBkb2VzIG5vdCBzb3VuZCBmYW1pbGlhciBwbGVhc2UgZ28gYmFjayB0byB0aGUgbGFiIHNlY3Rpb24gZm9yIGNsYXNzIDMuCgpIZXJlIHdlIHVzZSB0aGUgcmVzdWx0cyBmcm9tIFBTSS1CTEFTVCAobGFzdCBsYWIgc2Vzc2lvbiBlbmQgb2Ygc2VjdGlvbiAzKSB0b2dldGhlciB3aXRoIHNvbWUgUiBjb2RlIHRvIGRpZyBkZWVwZXIgaW50byB0aGVzZSByZXN1bHRzIGZvciBtZWNoYW5pc3RpYyBpbnNpZ2h0IGludG8gaW1wb3J0YW50IGZ1bmN0aW9uYWwgZmVhdHVyZXMgb2YgYWxsIGdsb2JpbnMuCgojIyMgU3RlcCAxLiBSZWFkIG91ciBnbG9iaW4gYWxpZ25tZW50CgpXZSB3aWxsIHVzZSB0aGUgYmlvM2QgUiBwYWNrYWdlIHRvIHJlYWQgdGhlIEZBU1RBIGZvcm1hdHRlZCBhbGlnbm1lbnQgd2UgZ2VuZXJhdGVkIGxhc3QgZGF5LiBOb3RlIHRoYXQgeW91IHdpbGwgbmVlZCB0byBoYXZlIHRoZSBiaW8zZCBwYWNrYWdlIGluc3RhbGxlZCAodmlhIHRoZSBSIGNvbW1hbmQgYGluc3RhbGwucGFja2FnZXMoImJpbzNkIilgIGZvciB0aGlzIHRvIHdvcmsgb24geW91ciBjb21wdXRlcikuIFdlIHdpbGwgdGFsayBtb3JlIGFib3V0IFIgcGFja2FnZXMgaW4gYSBjb3VwbGUgb2YgY2xhc3NlcyB0aW1lLgoKYGBge3J9CmxpYnJhcnkoYmlvM2QpCgojIEZlZWwgZnJlZSB0byB1c2UgeW91ciBvd24gYWxpZ25tZW50IGlucHV0IGhlcmUKaW5wdXRmaWxlIDwtICJodHRwczovL2Jpb2Jvb3QuZ2l0aHViLmlvL2JpbW0xNDNfRjIxL2NsYXNzLW1hdGVyaWFsL2dsb2Jpbl9hbGlnbm1lbnQuZmEiCgphbG4gPC0gcmVhZC5mYXN0YSggaW5wdXRmaWxlICkKCmBgYAoKRXhhbWluZSBhIHByaW50IG91dCBvZiB0aGlzIGFsaWdubWVudCwgbm90ZSB2aXN1YWxseSBhbnkgY29uc2VydmVkIHBvc2l0aW9ucy4KCmBgYHtyfQphbG4KYGBgCgpEb2luZyB0aGluZ3MgdmlzdWFsbHkgYW5kIG1hbnVhbGx5IGNvdW50aW5nIGNoYXJhY3RlcnMgaW4gYW4gYWxpZ25tZW50IHN1Y2ggYXMgdGhpcyBpcyBub3QgbXVjaCBmdW4gYW5kIHZlcnkgc3VzY2VwdGlibGUgdG8gbWFraW5nIG1pc3Rha2VzLiBMZXQncyB1c2Ugc29tZSBjb2RlIHRvIGhlbHAuCgojIyMgU3RlcCAyLiBJZGVudGlmeWluZyBjb25zZXJ2ZWQgcG9zaXRpb25zCgpGaXJzdCB3ZSB3aWxsIHNjb3JlIHBvc2l0aW9uYWwgY29uc2VydmF0aW9uIGluIHRoZSBhbGlnbm1lbnQgd2l0aCB0aGUgYGNvbnNlcnYoKWAgZnVuY3Rpb24uCgpgYGB7cn0Kc2ltIDwtIGNvbnNlcnYoYWxuKQpgYGAKCk1ha2UgYSBxdWljayBwbG90IG9mIGFsaWdubWVudCBwb3NpdGlvbiB2cyBjb25zZXJ2YXRpb24gc2NvcmUuCgpgYGB7cn0KcGxvdChzaW0sIHR5cD0iaCIsIHhsYWI9IkFsaWdubWVudCBwb3NpdGlvbiIsIHlsYWI9IkNvbnNlcnZhdGlvbiBzY29yZSIpCmBgYAoKSGVyZSB0aGUgaGlnaCBiYXJzIHJlcHJlc2VudCB0aGUgbW9zdCBjb25zZXJ2ZWQgYW1pbm8tYWNpZCBwb3NpdGlvbnMuCgpMZXQncyBvcmRlciBvdXIgYHNpbWAgdmVjdG9yIG9mIGNvbnNlcnZhdGlvbiBzY29yZXMgdG8gcHV0IHRoZSBtb3N0IGNvbnNlcnZlZCAoaGlnaGVzdCBzY29yaW5nKSBmaXJzdC4gV2hhdCBwb3NpdGlvbnMgYXJlIHRoZSBtb3N0IGNvbnNlcnZlZD8KCmBgYHtyfQppbmRzIDwtIG9yZGVyKHNpbSwgZGVjcmVhc2luZz1UUlVFKQpoZWFkKHNpbVtpbmRzXSkKYGBgCgpUaGUgdG9wIHRocmVlIHBvc2l0aW9ucyBhcmUgYWJzb2x1dGVseSBpbnZhcmlhbnQgaGVyZS4gTGV0J3MgdXNlIHRoZSBvcmRlcmluZyBpbmRpY2VzIGRldGVybWVuZWQgd2l0aCB0aGUgYG9yZGVyKClgIGZ1bmN0aW9uIGFib3ZlIHRvIGZpbmQgb3V0IG1vcmUgYWJvdXQgdGhlIHBvc2l0aW9ucy4KClRvIGhlbHAgd2UgY2FuIG1ha2UgYSBkYXRhZnJhbWUgdGhhdCBoYXMgYWxsIHRoZSBpbmZvcm1hdGlvbiB3ZSBtaWdodCB3YW50LCBzdWNoIGFzICpwb3NpdGlvbiBudW1iZXIgaW4gdGhlIGFsaWdubWVudCosIHRoZSAqYW1pbm8gYWNpZCogaW4gb3VyIGZpcnN0IGJldGEgZ2xvYmluIHNlcXVlbmNlIGFuZCAqY29uc2VydmF0aW9uIHNjb3JlKi4KCmBgYHtyfQpwb3NpdGlvbnMgPC0gZGF0YS5mcmFtZShwb3M9MTpsZW5ndGgoc2ltKSwKICAgICAgICAgICAgICAgICAgICAgICAgYWE9YWxuJGFsaVsxLF0sCiAgICAgICAgICAgICAgICAgICAgICAgIHNjb3JlPXNpbSkKCmhlYWQocG9zaXRpb25zKQpgYGAKCk5vdGUgdGhlIGZpcnN0IDYgcG9zaXRpb25zIG9mIHRoZSBhbGlnbm1lbnQgYXJlIGdhcCBjaGFyYWN0ZXJzIGluIHRoZSBiZXRhIGdsb2JpbiBzZXF1ZW5jZSBhbmQgaGF2ZSB2ZXJ5IGxvdyAoY2xvc2UgdG8gemVybykgY29uc2VydmF0aW9uIHNjb3Jlcy4KCkxldCdzIHVzZSB0aGUgb3JkZXJpbmcgdmVjdG9yIGZyb20gYWJvdmUgdG8gbG9vayBhdCB0aGUgbW9zdCBjb25zZXJ2ZWQgcG9zaXRpb25zOgoKYGBge3J9CmhlYWQoIHBvc2l0aW9uc1tpbmRzLF0gKQpgYGAKCk5pY2UsIHRoaXMgc2hvd3MgdXMgdGhhdCBwb3NpdGlvbnMgODMsIDExNSBhbmQgMTQ1IGFyZSBpbmRlZWQgdmVyeSBjb25zZXJ2ZWQuCgpMZXQncyBjb252ZXJ0IHRoZSBvbmUtbGV0dGVyIGNvZGUgZm9yIHRoZXNlIGFtaW5vIGFjaWRzIHRvIDMgbGV0dGVyIGNvZGUuCgpgYGB7cn0KYWExMjMocG9zaXRpb25zW2luZHMsXSRhYSlbMTozXQpgYGAKCkluIHRoZSBmaWd1cmUgYmVsb3cgSSBtYXBwZWQgdGhlc2UgdG9wIHR3byBIaXN0aWRuZSBhbWlubyBhY2lkcyB0byBhdG9taWMgc3RydWN0dXJlICh3ZSB3aWxsIHNlZSBob3cgdG8gZG8gdGhpcyBpbiBSIGxhdGVyIGluIHRoZSBjb3Vyc2UpLiBOb3RlIHRoYXQgdGhlc2UgY29uc2VydmVkIHBvc2l0aW9ucyBhcmUgcmVzcG9uc2libGUgZm9yIGNvb3JkaW5hdGluZyB0aGUgYWxsIGltcG9ydGFudCBpcm9uIGNvbnRhaW5pbmcgaGVhbSBncm91cCAoYS5rLmEuIFBvcnBoeXJpbiByaW5nKS4KCiFbQmV0YSBnbG9iaW4gc3RydWN0dXJlIHdpdGggdHdvIGNvbnNlcnZlZCBIaXN0aWRpbmUgcmVzaWRlcyAoYmx1ZSBzcGhlcmVzKSBhbmQgUG9ycGh5cmluIHJpbmcgKGN5YW4pIHNob3duLl0oaGJiX2NvbnNlcnZhdGlvbi5wbmcgIkNvbnNlcnZlZCBhbWlubyBhY2lkcyBpbiBnbG9iaW5zIG1hcHBlZCB0byBiZXRhIGdsb2JpbiIpe3dpZHRoPSIxMmNtIn0KCiMjIyBTdGVwIDMuIFJlbGF0aW9uc2hpcCBiZXR3ZWVuIHNlcXVlbmNlcwoKSGVyZSB3ZSBjYWxjdWxhdGUgdGhlIHNlcXVlbmNlIGlkZW50aXR5IGJldHdlZW4gYWxsIHBhaXJzIG9mIHNlcXVlbmNlcyAod2l0aCB0aGUgYHNlcWlkZW50aXR5KClgIGZ1bmN0aW9uKSBhbmQgdXNlIHRoZSByZXN1bHRpbmcgbWF0cml4IG9mIGlkZW50aXR5IHNjb3JlcyB0byBnZW5lcmF0ZSBhIGhlYXRtYXAgdmlzdWFsaXphdGlvbiBvZiB0aGUgcmVsYXRpb25zaGlwIGJldHdlZW4gc2VxdWVuY2VzLiBUaGlzIGlzIGEgY29tbW9uIHZpc3VhbGl6YXRpb24gaW4gYmlvaW5mb3JtYXRjcyBhbmQgd2Ugd2lsbCByZXZpc2l0IGl0IHNldmVyYWwgdGltZXMgaW4gdGhlIGNvdXJzZSAoZXNwZWNpYWxseSB3aXRoIE5HUyBkYXRhIGFuYWx5c2lzKS4KCk5vdGUgaGVyZSB3ZSB1c2UgdGhlIGBwaGVhdG1hcGAgcGFja2FnZSwgd2hpY2ggYWdhaW4gbmVlZHMgdG8gYmUgaW5zdGFsbGVkIG9uIHlvdXIgY29tcHV0ZXIgd2l0aCB0aGUgUiBjb2RlIGBpbnN0YWxsLnBhY2thZ2VzKCJwaGVhdG1hcCIpYC4KCmBgYHtyfQpsaWJyYXJ5KHBoZWF0bWFwKQoKaWRlIDwtIHNlcWlkZW50aXR5KGFsbikKcGhlYXRtYXAoKDEtaWRlKSkKYGBgCg==