The R markdown is available from the pulldown menu for Code
at the upper-right, choose “Download Rmd”, or download
the Rmd from GitHub.
In Cytoscape, network data can be loaded from a variety of sources,
and in several different formats. Where you get your network data
depends on your biological question and analysis plan. This tutorial
outlines how to load network data from several popular sources and
formats.
- Public databases
- NDEx
- PSICQUIC
- STRING/STITCH
- WikiPathways
- Local and remote files
- Cytoscape apps (Biopax, KEGG and other formats)
Installation
if (!requireNamespace("BiocManager", quietly = TRUE))
install.packages("BiocManager")
if(!"RCy3" %in% installed.packages())
BiocManager::install("RCy3")
library(RCy3)
Getting started
First, launch Cytoscape and keep it running whenever using RCy3.
Confirm that you have everything installed and running:
cytoscapePing()
cytoscapeVersionInfo()
Prerequisites
The exercises require you to have certain Cytoscape apps and R
packages installed.
installApp('stringApp')
installApp('WikiPathways')
if (!requireNamespace("BiocManager", quietly = TRUE))
install.packages("BiocManager")
BiocManager::install("ndexr")
BiocManager::install("rWikiPathways")
install.packages("httr")
Networks from Public Data
Cytoscape includes a Network Search tool for easy
import of public network data. In addition to core apps that are
included with your Cytoscape installation (NDEx and PSICQUIC), the
resources listed here will depend on which apps you have installed.
Find out which apps you have installed:
NDEx
The NDEx Project provides an
open-source framework where scientists and organizations can share,
store, manipulate, and publish biological network knowledge.
Search NDEx for “TP53 AND BARD1”:
library(ndexr)
ndexcon <- ndex_connect()
networks <- ndex_find_networks(ndexcon, "TP53 AND BARD1")
print(networks[,c("name","externalId","nodeCount","edgeCount")])
We can work with this list. Let’s use the first hit. Note:
you are going to get different hits as this database changes over time,
so proceed with any hit you like.
networkId = networks$externalId[1]
network = ndex_get_network(ndexcon, networkId)
print(network)
Import the network into Cytoscape:
importNetworkFromNDEx(networkId)
For more detailed information about working with NDEx networks in
Cytoscape, see the Cytoscape-and-NDEx
protocol.
STRING/STITCH
STRING is a database of known and predicted protein-protein
interactions, and STITCH stored known and predicted interactions between
chemicals and proteins. Data types include:
- Genomic Context Predictions
- High-throughput Lab Experiments
- (Conserved) Co-Expression
- Automated Textmining
- Previous Knowledge in Databases
Search STRING with the disease keyword “ovarian cancer”. The
resulting network will load automatically.
string.cmd = 'string disease query disease="ovarian cancer"'
commandsRun(string.cmd)
STRING networks load with a STRING-specific style, which includes 3D
protein structure diagrams.
Export the image as a png. This will save the png to your current
directory.
exportImage('ovarian_cancer', 'PNG')
STRING networks also include data as node/interaction attributes,
that can be used to create a Style. Let’s save the
attributes as a dataframe and take a look at the first few rows:
df <- getTableColumns()
head(df)
The STRING app includes options to change interaction confidence
level, expand the network etc.
Before changing interaction confidence level, let’s find the number
of interactions in the network:
Let’s increase the confidence level to 0.9, from the default 0.4:
string.cmd = 'string change confidence confidence=0.9 network=CURRENT'
commandsRun(string.cmd)
Now let’s get an edge count after changing interaction confidence
level:
Again, we can export a figure:
exportImage('before_expand', 'PNG')
For more detailed information about working with STRING networks in
Cytoscape, see the stringApp
protocol.
WikiPathways
WikiPathways is a
collaborative wiki platform with manually pathway models. It currently
covers over 2,800 pathways in 29 species-specific collections.
First, load the WikiPathways R library:
Search WikiPathways for ‘statin’:
statin.pathways <- findPathwaysByText('statin')
WikiPathways search results are displayed as a list of all available
pathway models matching the search term.
We can restrict the results to Homo sapiens:
human.filter <- lapply(statin.pathways, function(x) x$species == "Homo sapiens")
human.statin.pathways <- statin.pathways[unlist(human.filter)]
Loading the pathways will by default preserve the original pathway
layout:
lapply(human.statin.pathways, function(x) commandsRun(paste('wikipathways import-as-pathway id=', x$id, sep = '')))
The pathway can also be opened as a network:
lapply(human.statin.pathways, function(x) commandsRun(paste('wikipathways import-as-network id=', x$id, sep = '')))
WikiPathways model imported as
pathway and
network.
For more detailed information about working with WikiPathways in
Cytoscape, see the rWikiPathways
and rCy3 protocol.
Local and Remote Files
Cytoscape can load locally and remotely stored network data files in
a variety of file formats:
- SIF: Simple interaction format
- NNF: Nested network format
- GML and XGMML formats
- CYS: Cytoscape session file
- Delimited text and Excel format
Loading SIF files
SIF is a simple interaction format consisting of
three columns of data: source, interaction and target. To learn more
about the SIF format, see the Cytoscape
manual.
Download galFiltered.sif
and load the network via:
library(httr)
sif_url = "https://cytoscape.github.io/cytoscape-tutorials/protocols/data/galFiltered.sif"
GET(sif_url, write_disk(tf <- tempfile(fileext = ".sif")))
importNetworkFromFile(tf)
To see the whole network, use fitContent:
Loading XGMML files
XGMML is an XML format and can includes node and
edge attributes as well as visual style properties. To learn more about
the XGMML format, see the Cytoscape
manual.
Download https://raw.githubusercontent.com/cytoscape/cytoscape-tutorials/gh-pages/protocols/data/BasicDataVizDemo.xgmml
and load the network via
xgmml_url = "https://raw.githubusercontent.com/cytoscape/cytoscape-tutorials/gh-pages/protocols/data/BasicDataVizDemo.xgmml"
GET(xgmml_url, write_disk(tf <- tempfile(fileext = ".xgmml")))
importNetworkFromFile(tf)
This is the same network as in the previous step, but with node fill
color corresponding to expression values.
LS0tCnRpdGxlOiAiTG9hZGluZyBOZXR3b3JrcyIKYXV0aG9yOiAiS296byBOaXNoaWRhLCBLcmlzdGluYSBIYW5zcGVycyBhbmQgQWxleCBQaWNvIgpkYXRlOiAiYHIgU3lzLkRhdGUoKWAiCm91dHB1dDoKICBodG1sX25vdGVib29rOgogICAgdG9jX2Zsb2F0OiB0cnVlCiAgICBjb2RlX2ZvbGRpbmc6ICJub25lIgotLS0KYGBge3IsIGVjaG8gPSBGQUxTRX0Ka25pdHI6Om9wdHNfY2h1bmskc2V0KAogIGV2YWw9RkFMU0UKKQpgYGAKCipUaGUgUiBtYXJrZG93biBpcyBhdmFpbGFibGUgZnJvbSB0aGUgcHVsbGRvd24gbWVudSBmb3IqIENvZGUgKmF0IHRoZSB1cHBlci1yaWdodCwgY2hvb3NlICJEb3dubG9hZCBSbWQiLCBvciBbZG93bmxvYWQgdGhlIFJtZCBmcm9tIEdpdEh1Yl0oaHR0cHM6Ly9yYXcuZ2l0aHVidXNlcmNvbnRlbnQuY29tL2N5dG9zY2FwZS9jeXRvc2NhcGUtYXV0b21hdGlvbi9tYXN0ZXIvZm9yLXNjcmlwdGVycy9SL25vdGVib29rcy9sb2FkaW5nLW5ldHdvcmtzLlJtZCkuKgoKPGhyIC8+CgpJbiBDeXRvc2NhcGUsIG5ldHdvcmsgZGF0YSBjYW4gYmUgbG9hZGVkIGZyb20gYSB2YXJpZXR5IG9mIHNvdXJjZXMsIGFuZCBpbiBzZXZlcmFsIGRpZmZlcmVudCBmb3JtYXRzLiBXaGVyZSB5b3UgZ2V0IHlvdXIgbmV0d29yayBkYXRhIGRlcGVuZHMgb24geW91ciBiaW9sb2dpY2FsIHF1ZXN0aW9uIGFuZCBhbmFseXNpcyBwbGFuLiBUaGlzIHR1dG9yaWFsIG91dGxpbmVzIGhvdyB0byBsb2FkIG5ldHdvcmsgZGF0YSBmcm9tIHNldmVyYWwgcG9wdWxhciBzb3VyY2VzIGFuZCBmb3JtYXRzLgoKMS4gUHVibGljIGRhdGFiYXNlcwogIC0gKipOREV4KioKICAtICoqUFNJQ1FVSUMqKgogIC0gKipTVFJJTkcvU1RJVENIKioKICAtICoqV2lraVBhdGh3YXlzKioKMi4gTG9jYWwgYW5kIHJlbW90ZSBmaWxlcwozLiBDeXRvc2NhcGUgYXBwcyAoQmlvcGF4LCBLRUdHIGFuZCBvdGhlciBmb3JtYXRzKQoKPGhyIC8+CgojIEluc3RhbGxhdGlvbgpgYGB7ciwgZXZhbCA9IEZBTFNFfQppZiAoIXJlcXVpcmVOYW1lc3BhY2UoIkJpb2NNYW5hZ2VyIiwgcXVpZXRseSA9IFRSVUUpKQogIGluc3RhbGwucGFja2FnZXMoIkJpb2NNYW5hZ2VyIikKCmlmKCEiUkN5MyIgJWluJSBpbnN0YWxsZWQucGFja2FnZXMoKSkKICBCaW9jTWFuYWdlcjo6aW5zdGFsbCgiUkN5MyIpCgpsaWJyYXJ5KFJDeTMpCmBgYAoKIyBHZXR0aW5nIHN0YXJ0ZWQKRmlyc3QsIGxhdW5jaCBDeXRvc2NhcGUgYW5kIGtlZXAgaXQgcnVubmluZyB3aGVuZXZlciB1c2luZyBSQ3kzLiBDb25maXJtIHRoYXQgeW91IGhhdmUgZXZlcnl0aGluZyBpbnN0YWxsZWQgYW5kIHJ1bm5pbmc6CmBgYHtyfQpjeXRvc2NhcGVQaW5nKCkKY3l0b3NjYXBlVmVyc2lvbkluZm8oKQpgYGAKCiMgUHJlcmVxdWlzaXRlcwoKVGhlIGV4ZXJjaXNlcyByZXF1aXJlIHlvdSB0byBoYXZlIGNlcnRhaW4gQ3l0b3NjYXBlIGFwcHMgYW5kIFIgcGFja2FnZXMgaW5zdGFsbGVkLgoKYGBge3J9Cmluc3RhbGxBcHAoJ3N0cmluZ0FwcCcpCmluc3RhbGxBcHAoJ1dpa2lQYXRod2F5cycpCgppZiAoIXJlcXVpcmVOYW1lc3BhY2UoIkJpb2NNYW5hZ2VyIiwgcXVpZXRseSA9IFRSVUUpKQogICAgaW5zdGFsbC5wYWNrYWdlcygiQmlvY01hbmFnZXIiKQoKQmlvY01hbmFnZXI6Omluc3RhbGwoIm5kZXhyIikKQmlvY01hbmFnZXI6Omluc3RhbGwoInJXaWtpUGF0aHdheXMiKQoKaW5zdGFsbC5wYWNrYWdlcygiaHR0ciIpCmBgYAoKIyBOZXR3b3JrcyBmcm9tIFB1YmxpYyBEYXRhCgpDeXRvc2NhcGUgaW5jbHVkZXMgYSAqKk5ldHdvcmsgU2VhcmNoKiogdG9vbCBmb3IgZWFzeSBpbXBvcnQgb2YgcHVibGljIG5ldHdvcmsgZGF0YS4KSW4gYWRkaXRpb24gdG8gY29yZSBhcHBzIHRoYXQgYXJlIGluY2x1ZGVkIHdpdGggeW91ciBDeXRvc2NhcGUgaW5zdGFsbGF0aW9uIChOREV4IGFuZCBQU0lDUVVJQyksIHRoZSByZXNvdXJjZXMgbGlzdGVkIGhlcmUgd2lsbCBkZXBlbmQgb24gd2hpY2ggYXBwcyB5b3UgaGF2ZSBpbnN0YWxsZWQuCgpGaW5kIG91dCB3aGljaCBhcHBzIHlvdSBoYXZlIGluc3RhbGxlZDoKCmBgYHtyfQpnZXRJbnN0YWxsZWRBcHBzKCkKYGBgCgojIE5ERXgKClRoZSBbTkRFeCBQcm9qZWN0XShodHRwOi8vd3d3Lm5kZXhiaW8ub3JnLykgcHJvdmlkZXMgYW4gb3Blbi1zb3VyY2UgZnJhbWV3b3JrIHdoZXJlIHNjaWVudGlzdHMgYW5kIG9yZ2FuaXphdGlvbnMgY2FuIHNoYXJlLCBzdG9yZSwgbWFuaXB1bGF0ZSwgYW5kIHB1Ymxpc2ggYmlvbG9naWNhbCBuZXR3b3JrIGtub3dsZWRnZS4KClNlYXJjaCBOREV4IGZvciAiVFA1MyBBTkQgQkFSRDEiOgoKYGBge3J9CmxpYnJhcnkobmRleHIpCm5kZXhjb24gPC0gbmRleF9jb25uZWN0KCkKbmV0d29ya3MgPC0gbmRleF9maW5kX25ldHdvcmtzKG5kZXhjb24sICJUUDUzIEFORCBCQVJEMSIpCnByaW50KG5ldHdvcmtzWyxjKCJuYW1lIiwiZXh0ZXJuYWxJZCIsIm5vZGVDb3VudCIsImVkZ2VDb3VudCIpXSkKYGBgCgpXZSBjYW4gd29yayB3aXRoIHRoaXMgbGlzdC4gTGV04oCZcyB1c2UgdGhlIGZpcnN0IGhpdC4gKipOb3RlOiB5b3UgYXJlIGdvaW5nIHRvIGdldCBkaWZmZXJlbnQgaGl0cyBhcyB0aGlzIGRhdGFiYXNlIGNoYW5nZXMgb3ZlciB0aW1lLCBzbyBwcm9jZWVkIHdpdGggYW55IGhpdCB5b3UgbGlrZS4qKgoKYGBge3J9Cm5ldHdvcmtJZCA9IG5ldHdvcmtzJGV4dGVybmFsSWRbMV0KbmV0d29yayA9IG5kZXhfZ2V0X25ldHdvcmsobmRleGNvbiwgbmV0d29ya0lkKQpwcmludChuZXR3b3JrKQpgYGAKCkltcG9ydCB0aGUgbmV0d29yayBpbnRvIEN5dG9zY2FwZToKCmBgYHtyfQppbXBvcnROZXR3b3JrRnJvbU5ERXgobmV0d29ya0lkKQpgYGAKCkZvciBtb3JlIGRldGFpbGVkIGluZm9ybWF0aW9uIGFib3V0IHdvcmtpbmcgd2l0aCBOREV4IG5ldHdvcmtzIGluIEN5dG9zY2FwZSwgc2VlIHRoZSBbQ3l0b3NjYXBlLWFuZC1OREV4XShodHRwczovL2N5dG9zY2FwZS5vcmcvY3l0b3NjYXBlLWF1dG9tYXRpb24vZm9yLXNjcmlwdGVycy9SL25vdGVib29rcy9DeXRvc2NhcGUtYW5kLU5ERXgubmIuaHRtbCkgcHJvdG9jb2wuCgojIFNUUklORy9TVElUQ0gKClNUUklORyBpcyBhIGRhdGFiYXNlIG9mIGtub3duIGFuZCBwcmVkaWN0ZWQgcHJvdGVpbi1wcm90ZWluIGludGVyYWN0aW9ucywgYW5kIFNUSVRDSCBzdG9yZWQga25vd24gYW5kIHByZWRpY3RlZCBpbnRlcmFjdGlvbnMgYmV0d2VlbiBjaGVtaWNhbHMgYW5kIHByb3RlaW5zLiBEYXRhIHR5cGVzIGluY2x1ZGU6CgotIEdlbm9taWMgQ29udGV4dCBQcmVkaWN0aW9ucwotIEhpZ2gtdGhyb3VnaHB1dCBMYWIgRXhwZXJpbWVudHMKLSAoQ29uc2VydmVkKSBDby1FeHByZXNzaW9uCi0gQXV0b21hdGVkIFRleHRtaW5pbmcKLSBQcmV2aW91cyBLbm93bGVkZ2UgaW4gRGF0YWJhc2VzCgpTZWFyY2ggU1RSSU5HIHdpdGggdGhlIGRpc2Vhc2Uga2V5d29yZCAib3ZhcmlhbiBjYW5jZXIiLiBUaGUgcmVzdWx0aW5nIG5ldHdvcmsgd2lsbCBsb2FkIGF1dG9tYXRpY2FsbHkuCgpgYGB7cn0Kc3RyaW5nLmNtZCA9ICdzdHJpbmcgZGlzZWFzZSBxdWVyeSBkaXNlYXNlPSJvdmFyaWFuIGNhbmNlciInCmNvbW1hbmRzUnVuKHN0cmluZy5jbWQpCmBgYAoKU1RSSU5HIG5ldHdvcmtzIGxvYWQgd2l0aCBhIFNUUklORy1zcGVjaWZpYyBzdHlsZSwgd2hpY2ggaW5jbHVkZXMgM0QgcHJvdGVpbiBzdHJ1Y3R1cmUgZGlhZ3JhbXMuIAoKRXhwb3J0IHRoZSBpbWFnZSBhcyBhIHBuZy4gVGhpcyB3aWxsIHNhdmUgdGhlIHBuZyB0byB5b3VyIGN1cnJlbnQgZGlyZWN0b3J5LgoKYGBge3J9CmV4cG9ydEltYWdlKCdvdmFyaWFuX2NhbmNlcicsICdQTkcnKQpgYGAKClNUUklORyBuZXR3b3JrcyBhbHNvIGluY2x1ZGUgZGF0YSBhcyBub2RlL2ludGVyYWN0aW9uIGF0dHJpYnV0ZXMsIHRoYXQgY2FuIGJlIHVzZWQgdG8gY3JlYXRlIGEgKipTdHlsZSoqLiAKTGV0J3Mgc2F2ZSB0aGUgYXR0cmlidXRlcyBhcyBhIGRhdGFmcmFtZSBhbmQgdGFrZSBhIGxvb2sgYXQgdGhlIGZpcnN0IGZldyByb3dzOgoKYGBge3J9CmRmIDwtIGdldFRhYmxlQ29sdW1ucygpCmhlYWQoZGYpCmBgYAoKVGhlIFNUUklORyBhcHAgaW5jbHVkZXMgb3B0aW9ucyB0byBjaGFuZ2UgaW50ZXJhY3Rpb24gY29uZmlkZW5jZSBsZXZlbCwgZXhwYW5kIHRoZSBuZXR3b3JrIGV0Yy4KCkJlZm9yZSBjaGFuZ2luZyBpbnRlcmFjdGlvbiBjb25maWRlbmNlIGxldmVsLCBsZXQncyBmaW5kIHRoZSBudW1iZXIgb2YgaW50ZXJhY3Rpb25zIGluIHRoZSBuZXR3b3JrOgoKYGBge3J9CmdldEVkZ2VDb3VudCgpCmBgYAoKTGV0J3MgaW5jcmVhc2UgdGhlIGNvbmZpZGVuY2UgbGV2ZWwgdG8gMC45LCBmcm9tIHRoZSBkZWZhdWx0IDAuNDoKCmBgYHtyfQpzdHJpbmcuY21kID0gJ3N0cmluZyBjaGFuZ2UgY29uZmlkZW5jZSBjb25maWRlbmNlPTAuOSBuZXR3b3JrPUNVUlJFTlQnCmNvbW1hbmRzUnVuKHN0cmluZy5jbWQpCmBgYAoKTm93IGxldCdzIGdldCBhbiBlZGdlIGNvdW50IGFmdGVyIGNoYW5naW5nIGludGVyYWN0aW9uIGNvbmZpZGVuY2UgbGV2ZWw6CgpgYGB7cn0KZ2V0RWRnZUNvdW50KCkgCmBgYAoKQWdhaW4sIHdlIGNhbiBleHBvcnQgYSBmaWd1cmU6CgpgYGB7cn0KZXhwb3J0SW1hZ2UoJ2JlZm9yZV9leHBhbmQnLCAnUE5HJykKYGBgCgpGb3IgbW9yZSBkZXRhaWxlZCBpbmZvcm1hdGlvbiBhYm91dCB3b3JraW5nIHdpdGggU1RSSU5HIG5ldHdvcmtzIGluIEN5dG9zY2FwZSwgc2VlIHRoZSBbc3RyaW5nQXBwXShodHRwczovL2N5dG9zY2FwZS5vcmcvY3l0b3NjYXBlLWF1dG9tYXRpb24vZm9yLXNjcmlwdGVycy9SL25vdGVib29rcy9zdHJpbmdBcHAubmIuaHRtbCkgcHJvdG9jb2wuCgojIFdpa2lQYXRod2F5cwoKW1dpa2lQYXRod2F5c10oaHR0cHM6Ly93d3cud2lraXBhdGh3YXlzLm9yZy8pIGlzIGEgY29sbGFib3JhdGl2ZSB3aWtpIHBsYXRmb3JtIHdpdGggbWFudWFsbHkgcGF0aHdheSBtb2RlbHMuIEl0IGN1cnJlbnRseSBjb3ZlcnMgb3ZlciAyLDgwMCBwYXRod2F5cyBpbiAyOSBzcGVjaWVzLXNwZWNpZmljIGNvbGxlY3Rpb25zLgoKRmlyc3QsIGxvYWQgdGhlIFdpa2lQYXRod2F5cyBSIGxpYnJhcnk6CgpgYGB7cn0KbGlicmFyeShyV2lraVBhdGh3YXlzKQpgYGAKClNlYXJjaCBXaWtpUGF0aHdheXMgZm9yICdzdGF0aW4nOgoKYGBge3J9CnN0YXRpbi5wYXRod2F5cyA8LSBmaW5kUGF0aHdheXNCeVRleHQoJ3N0YXRpbicpCmBgYAoKV2lraVBhdGh3YXlzIHNlYXJjaCByZXN1bHRzIGFyZSBkaXNwbGF5ZWQgYXMgYSBsaXN0IG9mIGFsbCBhdmFpbGFibGUgcGF0aHdheSBtb2RlbHMgbWF0Y2hpbmcgdGhlIHNlYXJjaCB0ZXJtLgoKYGBge3J9CmhlYWQoc3RhdGluLnBhdGh3YXlzKQpgYGAKCldlIGNhbiByZXN0cmljdCB0aGUgcmVzdWx0cyB0byAqKkhvbW8gc2FwaWVucyoqOgoKYGBge3J9Cmh1bWFuLmZpbHRlciA8LSBsYXBwbHkoc3RhdGluLnBhdGh3YXlzLCBmdW5jdGlvbih4KSB4JHNwZWNpZXMgPT0gIkhvbW8gc2FwaWVucyIpCmh1bWFuLnN0YXRpbi5wYXRod2F5cyA8LSBzdGF0aW4ucGF0aHdheXNbdW5saXN0KGh1bWFuLmZpbHRlcildCmBgYAoKTG9hZGluZyB0aGUgcGF0aHdheXMgd2lsbCBieSBkZWZhdWx0IHByZXNlcnZlIHRoZSBvcmlnaW5hbCBwYXRod2F5IGxheW91dDoKCmBgYHtyfQpsYXBwbHkoaHVtYW4uc3RhdGluLnBhdGh3YXlzLCBmdW5jdGlvbih4KSBjb21tYW5kc1J1bihwYXN0ZSgnd2lraXBhdGh3YXlzIGltcG9ydC1hcy1wYXRod2F5IGlkPScsIHgkaWQsIHNlcCA9ICcnKSkpCmBgYAoKVGhlIHBhdGh3YXkgY2FuIGFsc28gYmUgb3BlbmVkIGFzIGEgbmV0d29yazoKCmBgYHtyfQpsYXBwbHkoaHVtYW4uc3RhdGluLnBhdGh3YXlzLCBmdW5jdGlvbih4KSBjb21tYW5kc1J1bihwYXN0ZSgnd2lraXBhdGh3YXlzIGltcG9ydC1hcy1uZXR3b3JrIGlkPScsIHgkaWQsIHNlcCA9ICcnKSkpCmBgYAoKV2lraVBhdGh3YXlzIG1vZGVsIGltcG9ydGVkIGFzICoqcGF0aHdheSoqIGFuZCAqKm5ldHdvcmsqKi4KPGNlbnRlcj4KIVtdKGh0dHBzOi8vY3l0b3NjYXBlLm9yZy9jeXRvc2NhcGUtdHV0b3JpYWxzL3Byb3RvY29scy9sb2FkaW5nLW5ldHdvcmtzL1dQLXBhdGh3YXkucG5nKXt3aWR0aD03MCV9ICFbXShodHRwczovL2N5dG9zY2FwZS5vcmcvY3l0b3NjYXBlLXR1dG9yaWFscy9wcm90b2NvbHMvbG9hZGluZy1uZXR3b3Jrcy9XUC1uZXR3b3JrLnBuZyl7d2lkdGg9NzAlfQo8L2NlbnRlcj4KCkZvciBtb3JlIGRldGFpbGVkIGluZm9ybWF0aW9uIGFib3V0IHdvcmtpbmcgd2l0aCBXaWtpUGF0aHdheXMgaW4gQ3l0b3NjYXBlLCBzZWUgdGhlIFtyV2lraVBhdGh3YXlzIGFuZCByQ3kzXShodHRwczovL2N5dG9zY2FwZS5vcmcvY3l0b3NjYXBlLWF1dG9tYXRpb24vZm9yLXNjcmlwdGVycy9SL25vdGVib29rcy9yV2lraVBhdGh3YXlzLWFuZC1SQ3kzLm5iLmh0bWwpIHByb3RvY29sLgoKIyBMb2NhbCBhbmQgUmVtb3RlIEZpbGVzCgpDeXRvc2NhcGUgY2FuIGxvYWQgbG9jYWxseSBhbmQgcmVtb3RlbHkgc3RvcmVkIG5ldHdvcmsgZGF0YSBmaWxlcyBpbiBhIHZhcmlldHkgb2YgZmlsZSBmb3JtYXRzOgoKLSAqKlNJRioqOiBTaW1wbGUgaW50ZXJhY3Rpb24gZm9ybWF0Ci0gKipOTkYqKjogTmVzdGVkIG5ldHdvcmsgZm9ybWF0Ci0gKipHTUwqKiBhbmQgKipYR01NTCoqIGZvcm1hdHMKLSAqKkNZUyoqOiBDeXRvc2NhcGUgc2Vzc2lvbiBmaWxlCi0gRGVsaW1pdGVkIHRleHQgYW5kIEV4Y2VsIGZvcm1hdAoKIyMgTG9hZGluZyBTSUYgZmlsZXMKCioqU0lGKiogaXMgYSBzaW1wbGUgaW50ZXJhY3Rpb24gZm9ybWF0IGNvbnNpc3Rpbmcgb2YgdGhyZWUgY29sdW1ucyBvZiBkYXRhOiBzb3VyY2UsIGludGVyYWN0aW9uIGFuZCB0YXJnZXQuIFRvIGxlYXJuIG1vcmUgYWJvdXQgdGhlIFNJRiBmb3JtYXQsIHNlZSB0aGUgW0N5dG9zY2FwZSBtYW51YWxdKGh0dHA6Ly9tYW51YWwuY3l0b3NjYXBlLm9yZy9lbi9zdGFibGUvU3VwcG9ydGVkX05ldHdvcmtfRmlsZV9Gb3JtYXRzLmh0bWwjc2lmLWZvcm1hdCkuCgpEb3dubG9hZCBbKmdhbEZpbHRlcmVkLnNpZipdKGh0dHBzOi8vY3l0b3NjYXBlLmdpdGh1Yi5pby9jeXRvc2NhcGUtdHV0b3JpYWxzL3Byb3RvY29scy9kYXRhL2dhbEZpbHRlcmVkLnNpZikgYW5kIGxvYWQgdGhlIG5ldHdvcmsgdmlhOgoKYGBge3J9CmxpYnJhcnkoaHR0cikKc2lmX3VybCA9ICJodHRwczovL2N5dG9zY2FwZS5naXRodWIuaW8vY3l0b3NjYXBlLXR1dG9yaWFscy9wcm90b2NvbHMvZGF0YS9nYWxGaWx0ZXJlZC5zaWYiCkdFVChzaWZfdXJsLCB3cml0ZV9kaXNrKHRmIDwtIHRlbXBmaWxlKGZpbGVleHQgPSAiLnNpZiIpKSkKaW1wb3J0TmV0d29ya0Zyb21GaWxlKHRmKQpgYGAKClRvIHNlZSB0aGUgd2hvbGUgbmV0d29yaywgdXNlIGZpdENvbnRlbnQ6CgpgYGB7cn0KZml0Q29udGVudCgpCmBgYAoKIyMgTG9hZGluZyBYR01NTCBmaWxlcwoKKipYR01NTCoqIGlzIGFuIFhNTCBmb3JtYXQgYW5kIGNhbiBpbmNsdWRlcyBub2RlIGFuZCBlZGdlIGF0dHJpYnV0ZXMgYXMgd2VsbCBhcyB2aXN1YWwgc3R5bGUgcHJvcGVydGllcy4gVG8gbGVhcm4gbW9yZSBhYm91dCB0aGUgWEdNTUwgZm9ybWF0LCBzZWUgdGhlIFtDeXRvc2NhcGUgbWFudWFsXShodHRwOi8vbWFudWFsLmN5dG9zY2FwZS5vcmcvZW4vc3RhYmxlL1N1cHBvcnRlZF9OZXR3b3JrX0ZpbGVfRm9ybWF0cy5odG1sI3hnbW1sLWZvcm1hdCkuCgpEb3dubG9hZCBodHRwczovL3Jhdy5naXRodWJ1c2VyY29udGVudC5jb20vY3l0b3NjYXBlL2N5dG9zY2FwZS10dXRvcmlhbHMvZ2gtcGFnZXMvcHJvdG9jb2xzL2RhdGEvQmFzaWNEYXRhVml6RGVtby54Z21tbCBhbmQgbG9hZCB0aGUgbmV0d29yayB2aWEKCmBgYHtyfQp4Z21tbF91cmwgPSAiaHR0cHM6Ly9yYXcuZ2l0aHVidXNlcmNvbnRlbnQuY29tL2N5dG9zY2FwZS9jeXRvc2NhcGUtdHV0b3JpYWxzL2doLXBhZ2VzL3Byb3RvY29scy9kYXRhL0Jhc2ljRGF0YVZpekRlbW8ueGdtbWwiCkdFVCh4Z21tbF91cmwsIHdyaXRlX2Rpc2sodGYgPC0gdGVtcGZpbGUoZmlsZWV4dCA9ICIueGdtbWwiKSkpCmltcG9ydE5ldHdvcmtGcm9tRmlsZSh0ZikKYGBgCgpUaGlzIGlzIHRoZSBzYW1lIG5ldHdvcmsgYXMgaW4gdGhlIHByZXZpb3VzIHN0ZXAsIGJ1dCB3aXRoIG5vZGUgZmlsbCBjb2xvciBjb3JyZXNwb25kaW5nIHRvIGV4cHJlc3Npb24gdmFsdWVzLiAhW10oaHR0cHM6Ly9jeXRvc2NhcGUub3JnL2N5dG9zY2FwZS10dXRvcmlhbHMvcHJvdG9jb2xzL2xvYWRpbmctbmV0d29ya3MvZ2FsRmlsdGVyZWQyTG9hZGVkLnBuZykK