In [29]:
# necessary libraries and dependencies
import sys
from py2cytoscape.data.cyrest_client import CyRestClient
from py2cytoscape.data.style import StyleUtil
import networkx as nx
import pandas as pd
import json
import requests
print("python version: " + sys.version)
# The py2cytoscape module doesn't have a version. I installed it 2018-04-13
#print("py2cytoscape version: " + py2cytoscape.__version__)
print("networkx version: " + nx.__version__)
print("pandas version: " + pd.__version__)
print("requests version: " + requests.__version__)
In [34]:
# !!!!!!!!!!!!!!!!! Step 0: Start Cytoscape 3.6 with cyREST App !!!!!!!!!!!!!!!!!!!!!!!!!!
# Cytoscape must be running to use the automation features
# Step 1: create an instance of cyRest client
cy = CyRestClient()
# Reset the session
#cy.session.delete()
This example uses the small and simple network found here: network-example-undirected.txt.
In [60]:
# Step 2: Import/Create the network that PathLinker will run on
network_file = 'network-example-undirected.txt'
# create a new network by importing the data from a sample using pandas
df = pd.read_csv(network_file, sep='\t', lineterminator='\n')
# and create the networkx Graph from the pandas dataframe
G = nx.from_pandas_edgelist(df, "source", "target")
# create the CyNetwork object from the networkx in CytoScape
cy_network = cy.network.create_from_networkx(G, name = 'network-example-undirected', collection = 'F1000 PathLinker Use Case')
# obtain the CyNetwork object SUID
cy_network_suid = cy_network.get_id()
In [59]:
# give the network some style and a layout
my_style = cy.style.create('defaut')
# copied from here: https://github.com/cytoscape/cytoscape-automation/blob/master/for-scripters/Python/basic-fundamentals.ipynb
basic_settings = {
'NODE_FILL_COLOR': '#6AACB8',
'NODE_SIZE': 55,
'NODE_BORDER_WIDTH': 0,
'NODE_LABEL_COLOR': '#555555',
'EDGE_WIDTH': 2,
'EDGE_TRANSPARENCY': 100,
'EDGE_STROKE_UNSELECTED_PAINT': '#333333',
'NETWORK_BACKGROUND_PAINT': '#FFFFEA'
}
my_style.update_defaults(basic_settings)
# Create some mappings
my_style.create_passthrough_mapping(column='name', vp='NODE_LABEL', col_type='String')
cy.layout.apply(name="force-directed", network=cy_network)
cy.style.apply(my_style, cy_network)
#cy.layout.fit(network=cy_network)
The network shown below will be generated in Cytoscape with the above code.
The function takes user sources, targets, and a set of parameters, and computes the k shortest paths. The function returns the paths in JSON format. Based on the user input, the function could generate a subnetwork (and view) containing those paths, and returns the computed paths and subnetwork/view SUIDs.
Additional description of the parameters are available in the PathLinker app documentation.
In [37]:
# Step 3: Construct input data to pass to PathLinker API function
# construct PathLinker input data for API request
# For a description of all of the parameters, please see below
params = {
'sources': 'a',
'targets': 'e h',
'k': 2, # the number of shortest path to compute
'treatNetworkAsUndirected': True, # Our graph is undirected, so use this option
'includeTiedPaths': True, # This option is not necessary. I'm including it here just to show what it does
}
# construct REST API request url
url = "http://localhost:1234/pathlinker/v1/" + str(cy_network_suid) + "/run"
# to just run on the network currently in view on cytoscape, use the following:
# url = "http://localhost:1234/pathlinker/v1/currentView/run"
headers = {'Content-Type': 'application/json', 'Accept': 'application/json'}
# perform the REST API call
result_json = requests.request("POST",
url,
data = json.dumps(params),
params = None,
headers = headers)
In [ ]:
# ------------ Description of all parameters ------------------
# the node names for the sources and targets are space separated
# and must match the "name" column in the Node Table in Cytoscape
params["sources"] = "a"
params["targets"] = "e h"
# the number of shortest path to compute, must be greater than 0
# Default: 50
params["k"] = 2
# Edge weight type, must be one of the three: [UNWEIGHTED, ADDITIVE, PROBABILITIES]
params["edgeWeightType"] = "UNWEIGHTED"
# Edge penalty. Not needed for UNWEIGHTED
# Must be 0 or greater for ADDITIVE, and 1 or greater for PROBABILITIES
params["edgePenalty"] = 0
# The column name in the Edge Table in Cytoscape containing edge weight property,
# column type must be numerical type
params["edgeWeightColumnName"] = "weight"
# The option to ignore directionality of edges when computing paths
# Default: False
params["treatNetworkAsUndirected"] = True
# Allow source/target nodes to appear as intermediate nodes in computed paths
# Default: False
params["allowSourcesTargetsInPaths"] = False
# Include more than k paths if the path length/score is equal to kth path length/score
# Default: False
params["includeTiedPaths"] = False
# Option to disable the generation of the subnetwork/view, path rank column, and result panel
# and only return the path result in JSON format
# Default: False
params["skipSubnetworkGeneration"] = False
The app will generate the following (shown below):
The API will return:
In [62]:
# Step 4: Store result, parse, and print
results = json.loads(result_json.content)
print("Output:\n")
# access the suid, references, and path rank column name
subnetwork_suid = results["subnetworkSUID"]
subnetwork_view_suid = results["subnetworkViewSUID"]
# The path rank column shows for each edge, the rank of the first path in which it appears
path_rank_column_name = results["pathRankColumnName"]
print("subnetwork SUID: %s" % (subnetwork_suid))
print("subnetwork view SUID: %s" % (subnetwork_view_suid))
print("Path rank column name: %s" % (path_rank_column_name))
print("")
# access the paths generated by PathLinker
paths = results["paths"]
# print the paths found
for path in paths:
print("path rank: %d" % (path['rank']))
print("path score: %s" % (str(path['score'])))
print("path: %s" % ("|".join(path['nodeList'])))
In [ ]:
# write them to a file
paths_file = "use-case-images/paths.txt"
print("Writing paths to %s" % (paths_file))
with open(paths_file, 'w') as out:
out.write("path rank\tpath score\tpath\n")
for path in paths:
out.write('%d\t%s\t%s\n' % (path['rank'], str(path['score']), "|".join(path['nodeList'])))
In [54]:
# access network and network view references
subnetwork = cy.network.create(suid=subnetwork_suid)
#subnetwork_view = subnetwork.get_first_view()
# TODO copy the layout of the original graph to this graph to better visualize the results.
# The copycat layout doesn't seem to be working
# for now, just apply the cose layout to get a little better layout (see image below)
cy.layout.apply(name="cose", network=subnetwork)
The subnetwork with "cose" layout will look something like this:
In [21]:
# *** Currently the function does not work therefore is commented out. ***
# import py2cytoscape.cytoscapejs as renderer
# # visualize the subnetwork view using CytoScape.js
# renderer.render(subnetwork_view, 'Directed', background='radial-gradient(#FFFFFF 15%, #DDDDDD 105%)')
In [ ]:
# png
subnetwork_image_png = subnetwork.get_png()
subnetwork_image_file = 'use-case-images/subnetwork-image.png'
print("Writing PNG to %s" % (subnetwork_image_file))
with open(subnetwork_image_file, 'wb') as f:
f.write(subnetwork_image_png)
from IPython.display import Image
Image(subnetwork_image_png)
# # pdf
# subnetwork_image_pdf = subnetwork.get_pdf()
# subnetwork_image_file = subnetwork_image_file.replace('.png', '.pdf')
# print("Writing PDF to %s" % (subnetwork_image_file))
# with open(subnetwork_image_file, 'wb') as f:
# f.write(subnetwork_image_pdf)
# # display the pdf in frame
# from IPython.display import IFrame
# IFrame('use_case_images/subnetwork_image.pdf', width=600, height=300)
# # svg
# subnetwork_image_svg = subnetwork.get_svg()
# from IPython.display import SVG
# SVG(subnetwork_image_svg)