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.

  1. Public databases
  • NDEx
  • PSICQUIC
  • STRING/STITCH
  • WikiPathways
  1. Local and remote files
  2. 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:

getInstalledApps()

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:

getEdgeCount()

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:

getEdgeCount() 

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:

library(rWikiPathways)

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.

head(statin.pathways)

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:

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