by Keiichiro Ono - University of California, San Diego Trey Ideker Lab
from py2cytoscape.data.cynetwork import CyNetwork
from py2cytoscape.data.cyrest_client import CyRestClient
from py2cytoscape.data.style import StyleUtil
import py2cytoscape.util.cytoscapejs as cyjs
import py2cytoscape.cytoscapejs as renderer
import networkx as nx
import pandas as pd
import json
Couldn't import dot_parser, loading of dot files will not be possible.
# !!!!!!!!!!!!!!!!! Step 0: Start Cytoscape 3 with cyREST App !!!!!!!!!!!!!!!!!!!!!!!!!!
# Step 1: Create py2cytoscape client
cy = CyRestClient()
# Reset
cy.session.delete()
# Step 2: Load network from somewhere
yeast_net = cy.network.create_from('../tests/data/galFiltered.json')
# Step 3: Load table as pandas' DataFrame
table_data = pd.read_csv('sample_data_table.csv', index_col=0)
table_data.head()
alias | annotation.DB_Object_Name | annotation.GO BIOLOGICAL_PROCESS | annotation.GO CELLULAR_COMPONENT | annotation.GO MOLECULAR_FUNCTION | label | kegg | uniprot | sgd | entrez | |
---|---|---|---|---|---|---|---|---|---|---|
YAL003W | translation elongation factor EF-1beta, EF-1 b... | EF-1 beta, translation elongation factor EF-1beta | translational elongation | eukaryotic translation elongation factor 1 com... | translation elongation factor activity | EF1B | sce:YAL003W | EF1B_YEAST | S000000003 | 851260 |
YAL030W | S000000028, SNC1 | NaN | Golgi to plasma membrane transport, endocytosi... | Golgi trans face, SNARE complex, endosome, tra... | v-SNARE activity | SNC1 | sce:YAL030W | SNC1_YEAST | S000000028 | 851203 |
YAL038W | CDC19, PYK1, S000000036, pyruvate kinase | pyruvate kinase | glycolysis, pyruvate metabolic process | cytosol | pyruvate kinase activity | KPYK1 | sce:YAL038W | KPYK1_YEAST | S000000036 | 851193 |
YAL040C | CLN3, DAF1, FUN10, G1 cyclin, S000000038, WHI1 | G1 cyclin | G1/S transition of mitotic cell cycle, regulat... | nucleus | cyclin-dependent protein kinase regulator acti... | CG13 | sce:YAL040C | CG13_YEAST | S000000038 | 851191 |
YAR007C | heterotrimeric RPA (RF-A) single-stranded DNA ... | RF-A, heterotrimeric RPA (RF-A) single-strande... | DNA recombination, DNA replication, synthesis ... | DNA replication factor A complex, chromosome, ... | damaged DNA binding, single-stranded DNA binding | RFA1 | sce:YAR007C | RFA1_YEAST | S000000065 | 851266 |
# Step 4: Merge them in Cytoscape
yeast_net.update_node_table(df=table_data, network_key_col='name')
# Step 5: Apply layout
cy.layout.apply(name='force-directed', network=yeast_net)
# Step 6: Create Visual Style as code (or by hand if you prefer)
my_yeast_style = cy.style.create('GAL Style')
basic_settings = {
# You can set default values as key-value pairs.
'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_yeast_style.update_defaults(basic_settings)
# Create some mappings
my_yeast_style.create_passthrough_mapping(column='COMMON', vp='NODE_LABEL', col_type='String')
degrees = yeast_net.get_node_column('Degree')
color_gradient = StyleUtil.create_2_color_gradient(min=degrees.min(), max=degrees.max(), colors=('white', '#6AACB8'))
degree_to_size = StyleUtil.create_slope(min=degrees.min(), max=degrees.max(), values=(10, 100))
my_yeast_style.create_continuous_mapping(column='Degree', vp='NODE_FILL_COLOR', col_type='Integer', points=color_gradient)
my_yeast_style.create_continuous_mapping(column='Degree', vp='NODE_SIZE', col_type='Integer', points=degree_to_size)
my_yeast_style.create_continuous_mapping(column='Degree', vp='NODE_LABEL_FONT_SIZE', col_type='Integer', points=degree_to_size)
cy.style.apply(my_yeast_style, yeast_net)
# Step 7: (Optional) Embed as interactive Cytoscape.js widget
yeast_net_view = yeast_net.get_first_view()
style_for_widget = cy.style.get(my_yeast_style.get_name(), data_format='cytoscapejs')
renderer.render(yeast_net_view, style=style_for_widget['style'], background='radial-gradient(#FFFFFF 15%, #DDDDDD 105%)')
From version 0.4.0, ___py2cytoscape___ has wrapper modules for cyREST RESTful API. This means you can access Cytoscape features in more Pythonic way instead of calling raw REST API via HTTP.
Since pandas is a standard library for data mangling/analysis in Python, this new version uses its DataFrame as its basic data object.
You can use Cytoscape.js widget to embed your final result as a part of your notebook.
cyREST provides language-agnostic RESTful API, but you need to use a lot of template code to access raw API. Here is an example. Both of the following do the same task, which is creating an empty network in Cytoscape. You will notice it is significantly simpler if you use py2cytoscape wrapper API.
# HTTP Client for Python
import requests
# Standard JSON library
import json
# Basic Setup
PORT_NUMBER = 1234
BASE = 'http://localhost:' + str(PORT_NUMBER) + '/v1/'
# Header for posting data to the server as JSON
HEADERS = {'Content-Type': 'application/json'}
# Define dictionary of empty network
empty_network = {
'data': {
'name': 'I\'m empty!'
},
'elements': {
'nodes':[],
'edges':[]
}
}
res = requests.post(BASE + 'networks?collection=My%20Collection', data=json.dumps(empty_network), headers=HEADERS)
new_network_id = res.json()['networkSUID']
print('New network created with raw REST API. Its SUID is ' + str(new_network_id))
New network created with raw REST API. Its SUID is 239076
network = cy.network.create(name='My Network', collection='My network collection')
print('New network created with py2cytoscape. Its SUID is ' + str(network.get_id()))
New network created with py2cytoscape. Its SUID is 239104
As of 6/4/2015, this is still in alpha status and feature requests are always welcome. If youi have questions or feature requests, please send them to our Google Groups:
# Create an instance of cyREST client. Default IP is 'localhost', and port number is 1234.
# cy = CyRestClient() - This default constructor creates connection to http://localhost:1234/v1
cy = CyRestClient(ip='127.0.0.1', port=1234)
# Cleanup: Delete all existing networks and tables in current Cytoscape session
cy.session.delete()
# Empty network
empty1 = cy.network.create()
# With name
empty2 = cy.network.create(name='Created in Jupyter Notebook')
# With name and collection name
empty3 = cy.network.create(name='Also created in Jupyter', collection='New network collection')
# Load a single local file
net_from_local2 = cy.network.create_from('../tests/data/galFiltered.json')
net_from_local1 = cy.network.create_from('sample_yeast_network.xgmml', collection='My Collection')
net_from_local2 = cy.network.create_from('../tests/data/galFiltered.gml', collection='My Collection')
# Load from multiple locations
network_locations = [
'sample_yeast_network.xgmml', # Local file
'http://chianti.ucsd.edu/cytoscape-data/galFiltered.sif', # Static file on a web server
'http://www.ebi.ac.uk/Tools/webservices/psicquic/intact/webservices/current/search/query/brca1?format=xml25' # or a web service
]
# This requrns Series
networks = cy.network.create_from(network_locations)
pd.DataFrame(networks, columns=['CyNetwork'])
CyNetwork | |
---|---|
file:////Users/kono/git/py2cytoscape/examples/sample_yeast_network.xgmml | <py2cytoscape.data.cynetwork.CyNetwork object ... |
http://chianti.ucsd.edu/cytoscape-data/galFiltered.sif | <py2cytoscape.data.cynetwork.CyNetwork object ... |
http://www.ebi.ac.uk/Tools/webservices/psicquic/intact/webservices/current/search/query/brca1?format=xml25 | <py2cytoscape.data.cynetwork.CyNetwork object ... |
Currently, py2cytoscape accepts the following data as input:
Cytoscape.js
NetworkX
Pandas DataFrame
igraph (TBD)
Numpy adjacency matrix (binary or weighted) (TBD)
GraphX (TBD)
# Cytoscape.js JSON
n1 = cy.network.create(data=cyjs.get_empty_network(), name='Created from Cytoscape.js JSON')
# Pandas DataFrame
# Example 1: From a simple text table
df_from_sif = pd.read_csv('../tests/data/galFiltered.sif', names=['source', 'interaction', 'target'], sep=' ')
df_from_sif.head()
source | interaction | target | |
---|---|---|---|
0 | YKR026C | pp | YGL122C |
1 | YGR218W | pp | YGL097W |
2 | YGL097W | pp | YOR204W |
3 | YLR249W | pp | YPR080W |
4 | YLR249W | pp | YBR118W |
# By default, it uses 'source' for source node column, 'target' for target node column, and 'interaction' for interaction
yeast1 = cy.network.create_from_dataframe(df_from_sif, name='Yeast network created from pandas DataFrame')
# Example 2: from more complicated table
df_from_mitab = pd.read_csv('intact_pubid_22094256.txt', sep='\t')
df_from_mitab.head()
#ID(s) interactor A | ID(s) interactor B | Alt. ID(s) interactor A | Alt. ID(s) interactor B | Alias(es) interactor A | Alias(es) interactor B | Interaction detection method(s) | Publication 1st author(s) | Publication Identifier(s) | Taxid interactor A | ... | Checksum(s) interactor A | Checksum(s) interactor B | Interaction Checksum(s) | Negative | Feature(s) interactor A | Feature(s) interactor B | Stoichiometry(s) interactor A | Stoichiometry(s) interactor B | Identification method participant A | Identification method participant B | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | uniprotkb:Q8IZC7 | uniprotkb:P11802 | intact:EBI-5278328|uniprotkb:C9JU83|uniprotkb:... | intact:EBI-295644|uniprotkb:B2R9A0|uniprotkb:B... | psi-mi:zn101_human(display_long)|uniprotkb:ZNF... | psi-mi:cdk4_human(display_long)|uniprotkb:CDK4... | psi-mi:"MI:0424"(protein kinase assay) | Anders et al. (2011) | pubmed:22094256|imex:IM-16628 | taxid:9606(human)|taxid:9606(Homo sapiens) | ... | rogid:mZLXs/PbWbfgLzkjwZfoE2c6jy09606 | rogid:pxIzF9EkX+gMz7zj/TDiytYtsOc9606 | intact-crc:0486DE729E5A8158|rigid:3gdrHm0coV8S... | False | glutathione s tranferase tag:?-? | sufficient binding region:4-303|glutathione s ... | - | - | psi-mi:"MI:0821"(molecular weight estimation b... | psi-mi:"MI:0821"(molecular weight estimation b... |
1 | uniprotkb:P01106 | uniprotkb:Q00534 | intact:EBI-447544|intact:EBI-1058440|uniprotkb... | intact:EBI-295663|uniprotkb:A4D1G0 | psi-mi:myc_human(display_long)|uniprotkb:BHLHE... | psi-mi:cdk6_human(display_long)|uniprotkb:CDK6... | psi-mi:"MI:0424"(protein kinase assay) | Anders et al. (2011) | pubmed:22094256|imex:IM-16628 | taxid:9606(human)|taxid:9606(Homo sapiens) | ... | rogid:CCk+p9FN7JV6cTmJDlin2hRp1tg9606 | rogid:IlAJCZ9bvB5RaBdS1rlPnqDL9xg9606 | intact-crc:20A3DCC8419B269E|rigid:bfSR2lJKa/lY... | False | glutathione s tranferase tag:?-? | his tag:n-n | - | - | psi-mi:"MI:0821"(molecular weight estimation b... | psi-mi:"MI:0821"(molecular weight estimation b... |
2 | uniprotkb:Q00534 | uniprotkb:P28698 | intact:EBI-295663|uniprotkb:A4D1G0 | intact:EBI-5278283|uniprotkb:M0QXU0|uniprotkb:... | psi-mi:cdk6_human(display_long)|uniprotkb:CDK6... | psi-mi:mzf1_human(display_long)|uniprotkb:MZF1... | psi-mi:"MI:0424"(protein kinase assay) | Anders et al. (2011) | pubmed:22094256|imex:IM-16628 | taxid:9606(human)|taxid:9606(Homo sapiens) | ... | rogid:IlAJCZ9bvB5RaBdS1rlPnqDL9xg9606 | rogid:1rq+ga/Uew705r63KlORpqBObbw9606 | intact-crc:578214FA683591D0|rigid:8AADqx3NNAXF... | False | his tag:n-n | glutathione s tranferase tag:?-? | - | - | psi-mi:"MI:0821"(molecular weight estimation b... | psi-mi:"MI:0821"(molecular weight estimation b... |
3 | uniprotkb:P11802 | uniprotkb:Q9H165 | intact:EBI-295644|uniprotkb:B2R9A0|uniprotkb:B... | intact:EBI-765567|uniprotkb:Q86W14|uniprotkb:Q... | psi-mi:cdk4_human(display_long)|uniprotkb:CDK4... | psi-mi:bc11a_human(display_long)|uniprotkb:B-c... | psi-mi:"MI:0424"(protein kinase assay) | Anders et al. (2011) | pubmed:22094256|imex:IM-16628 | taxid:9606(human)|taxid:9606(Homo sapiens) | ... | rogid:pxIzF9EkX+gMz7zj/TDiytYtsOc9606 | rogid:xASsLQWykg/7ZpyjLsQP8GlQ/H09606 | intact-crc:F173ABFF34E61592|rigid:5u6F7IwnpEEf... | False | sufficient binding region:4-303|glutathione s ... | glutathione s tranferase tag:?-? | - | - | psi-mi:"MI:0821"(molecular weight estimation b... | psi-mi:"MI:0821"(molecular weight estimation b... |
4 | uniprotkb:Q14980 | uniprotkb:Q00534 | intact:EBI-521611|uniprotkb:H0YH75|uniprotkb:Q... | intact:EBI-295663|uniprotkb:A4D1G0 | psi-mi:numa1_human(display_long)|uniprotkb:SP-... | psi-mi:cdk6_human(display_long)|uniprotkb:CDK6... | psi-mi:"MI:0424"(protein kinase assay) | Anders et al. (2011) | pubmed:22094256|imex:IM-16628 | taxid:9606(human)|taxid:9606(Homo sapiens) | ... | rogid:goAKbcTz6vzGy3T7RlpGPnTCbdk9606 | rogid:IlAJCZ9bvB5RaBdS1rlPnqDL9xg9606 | intact-crc:43D7B9AE4E55FAA0|rigid:mLhZxkGnjrpK... | False | glutathione s tranferase tag:?-? | his tag:n-n | - | - | psi-mi:"MI:0821"(molecular weight estimation b... | psi-mi:"MI:0821"(molecular weight estimation b... |
5 rows × 42 columns
source = df_from_mitab.columns[0]
target = df_from_mitab.columns[1]
interaction = 'Interaction identifier(s)'
title='A Systematic Screen for CDK4/6 Substrates Links FOXM1 Phosphorylation to Senescence Suppression in Cancer Cells.'
human1 = cy.network.create_from_dataframe(df_from_mitab, source_col=source, target_col=target, interaction_col=interaction, name=title)
# Import edge attributes and node attributes at the same time (TBD)
# NetworkX
nx_graph = nx.scale_free_graph(100)
nx.set_node_attributes(nx_graph, 'Degree', nx.degree(nx_graph))
nx.set_node_attributes(nx_graph, 'Betweenness_Centrality', nx.betweenness_centrality(nx_graph))
scale_free100 = cy.network.create_from_networkx(nx_graph, collection='Generated by NetworkX')
# TODO: igraph
# TODO: Numpy adj. martix
# TODO: GraphX
You can get network data in the following forms:
# As Cytoscape.js (dict)
yeast1_json = yeast1.to_json()
# print(json.dumps(yeast1_json, indent=4))
# As NetworkX graph object
sf100 = scale_free100.to_networkx()
num_nodes = sf100.number_of_nodes()
num_edges = sf100.number_of_edges()
print('Number of Nodes: ' + str(num_nodes))
print('Number of Edges: ' + str(num_edges))
Number of Nodes: 100 Number of Edges: 197
# As a simple, SIF-like DataFrame
yeast1_df = yeast1.to_dataframe()
yeast1_df.head()
source | interaction | target | |
---|---|---|---|
0 | YDR277C | pp | YDL194W |
1 | YDR277C | pp | YJR022W |
2 | YPR145W | pp | YMR117C |
3 | YER054C | pp | YBR045C |
4 | YER054C | pp | YER133W |
___CyNetwork___ class is a simple wrapper for network-related cyREST raw REST API. It does not hold the actual network data. It's a reference to a network in current Cytoscape session. With CyNetwork API, you can access Cytoscape data objects in more Pythonista-friendly way.
network_suid = yeast1.get_id()
print('This object references to Cytoscape network with SUID ' + str(network_suid) + '\n')
print('And its name is: ' + str(yeast1.get_network_value(column='name')) + '\n')
nodes = yeast1.get_nodes()
edges = yeast1.get_edges()
print('* This network has ' + str(len(nodes)) + ' nodes and ' + str(len(edges)) + ' edges\n')
# Get a row in the node table as pandas Series object
node0 = nodes[0]
row = yeast1.get_node_value(id=node0)
print(row)
# Or, pick one cell in the table
cell = yeast1.get_node_value(id=node0, column='name')
print('\nThis node has name: ' + str(cell))
This object references to Cytoscape network with SUID 246460 And its name is: b'Yeast network created from pandas DataFrame' * This network has 331 nodes and 362 edges SUID 246470 id YKR026C name YKR026C selected False shared_name YKR026C dtype: object This node has name: b'YKR026C'
And of course, you can grab references to existing Cytoscape networks:
# Create a new CyNetwork object from existing network
network_ref1 = cy.network.create(suid=yeast1.get_id())
# And they are considered as same objects.
print(network_ref1 == yeast1)
print(network_ref1.get_network_value(column='name'))
True b'Yeast network created from pandas DataFrame'
Cytoscape has two main data types: ___Network___ and ___Table___. Network is the graph topology, and Tables are properties for those graphs. For simplicity, this library has access to three basic table objects:
For 99% of your use cases, you can use these three to store properties. Since pandas is extremely useful to handle table data, default data type for tables is DataFrame. However, you can also use other data types including:
# Get table from Cytoscape
node_table = scale_free100.get_node_table()
edge_table = scale_free100.get_edge_table()
network_table = scale_free100.get_network_table()
node_table.head()
shared name | name | selected | id | Degree | Betweenness_Centrality | |
---|---|---|---|---|---|---|
SUID | ||||||
248218 | 0 | 0 | False | 0 | 63 | 0.032124 |
248219 | 1 | 1 | False | 1 | 94 | 0.085927 |
248220 | 2 | 2 | False | 2 | 24 | 0.013760 |
248221 | 3 | 3 | False | 3 | 7 | 0.000000 |
248222 | 4 | 4 | False | 4 | 13 | 0.016595 |
network_table.transpose().head()
SUID | 248208 |
---|---|
shared name | directed_scale_free_graph(100,alpha=0.41,beta=... |
name | directed_scale_free_graph(100,alpha=0.41,beta=... |
selected | True |
__Annotations | NaN |
names = scale_free100.get_node_column('Degree')
print(names.head())
# Node Column information. "name" is the unique Index
scale_free100.get_node_columns()
0 94 1 63 2 7 3 13 4 7 dtype: float64
immutable | primaryKey | type | |
---|---|---|---|
name | |||
SUID | True | True | Long |
shared name | True | False | String |
name | True | False | String |
selected | True | False | Boolean |
id | False | False | String |
Degree | False | False | Double |
Betweenness_Centrality | False | False | Double |
# Add new nodes: Simply send the list of node names. NAMES SHOULD BE UNIQUE!
new_node_names = ['a', 'b', 'c']
# Return value contains dictionary from name to SUID.
new_nodes = scale_free100.add_nodes(new_node_names)
# Add new edges
# Send a list of tuples: (source node SUID, target node SUID, interaction type
new_edges = []
new_edges.append((new_nodes['a'], new_nodes['b'], 'type1'))
new_edges.append((new_nodes['a'], new_nodes['c'], 'type2'))
new_edges.append((new_nodes['b'], new_nodes['c'], 'type3'))
new_edge_ids = scale_free100.add_edges(new_edges)
new_edge_ids
source | target | |
---|---|---|
SUID | ||
248820 | 248814 | 248815 |
248821 | 248814 | 248816 |
248822 | 248815 | 248816 |
# Delete node
scale_free100.delete_node(new_nodes['a'])
# Delete edge
scale_free100.delete_edge(new_edge_ids.index[0])
Let's do something a bit more realistic. You can update any Tables by using DataFrame objects.
Let's use ID Conversion web service by Uniprot to add more information to existing yeast network in current session.
# Small utility function to convert ID sets
import requests
def uniprot_id_mapping_service(query=None, from_id=None, to_id=None):
# Uniprot ID Mapping service
url = 'http://www.uniprot.org/mapping/'
payload = {
'from': from_id,
'to': to_id,
'format':'tab',
'query': query
}
res = requests.get(url, params=payload)
df = pd.read_csv(res.url, sep='\t')
res.close()
return df
# Get node table from Cytoscape
yeast_node_table = yeast1.get_node_table()
# From KEGG ID to UniprotKB ID
query1 = ' '.join(yeast_node_table['name'].map(lambda gene_id: 'sce:' + gene_id).values)
id_map_kegg2uniprot = uniprot_id_mapping_service(query1, from_id='KEGG_ID', to_id='ID')
id_map_kegg2uniprot.columns = ['kegg', 'uniprot']
# From UniprotKB to SGD
query2 = ' '.join(id_map_kegg2uniprot['uniprot'].values)
id_map_uniprot2sgd = uniprot_id_mapping_service(query2, from_id='ID', to_id='SGD_ID')
id_map_uniprot2sgd.columns = ['uniprot', 'sgd']
# From UniprotKB to Entrez Gene ID
query3 = ' '.join(id_map_kegg2uniprot['uniprot'].values)
id_map_uniprot2ncbi = uniprot_id_mapping_service(query3, from_id='ID', to_id='P_ENTREZGENEID')
id_map_uniprot2ncbi.columns = ['uniprot', 'entrez']
# Merge them
merged = pd.merge(id_map_kegg2uniprot, id_map_uniprot2sgd, on='uniprot')
merged = pd.merge(merged, id_map_uniprot2ncbi, on='uniprot')
# Add key column by removing prefix
merged['name'] = merged['kegg'].map(lambda kegg_id : kegg_id[4:])
merged.head()
kegg | uniprot | sgd | entrez | name | |
---|---|---|---|---|---|
0 | sce:YKR026C | EI2BA_YEAST | S000001734 | 853896 | YKR026C |
1 | sce:YGL122C | NAB2_YEAST | S000003090 | 852755 | YGL122C |
2 | sce:YGR218W | XPO1_YEAST | S000003450 | 853133 | YGR218W |
3 | sce:YGL097W | RCC1_YEAST | S000003065 | 852782 | YGL097W |
4 | sce:YOR204W | DED1_YEAST | S000005730 | 854379 | YOR204W |
update_url = BASE + 'networks/' + str(yeast1.get_id()) + '/tables/defaultnode'
print(update_url)
ut = {
'key': 'name',
'dataKey': 'name',
'data': [
{
'name': 'YBR112C',
'foo': 'aaaaaaaa'
}
]
}
requests.put(update_url, json=ut, headers=HEADERS)
http://localhost:1234/v1/networks/246460/tables/defaultnode
<Response [200]>
# Now update existing node table with the data frame above.
yeast1.update_node_table(merged, network_key_col='name', data_key_col='name')
# Check the table is actually updated
yeast1.get_node_table().head()
shared name | name | selected | id | foo | kegg | entrez | uniprot | sgd | |
---|---|---|---|---|---|---|---|---|---|
SUID | |||||||||
246470 | YKR026C | YKR026C | False | YKR026C | NaN | sce:YKR026C | 853896 | EI2BA_YEAST | S000001734 |
246471 | YGL122C | YGL122C | False | YGL122C | NaN | sce:YGL122C | 852755 | NAB2_YEAST | S000003090 |
246472 | YGR218W | YGR218W | False | YGR218W | NaN | sce:YGR218W | 853133 | XPO1_YEAST | S000003450 |
246473 | YGL097W | YGL097W | False | YGL097W | NaN | sce:YGL097W | 852782 | RCC1_YEAST | S000003065 |
246474 | YOR204W | YOR204W | False | YOR204W | NaN | sce:YOR204W | 854379 | DED1_YEAST | S000005730 |
Currently, ___you cannot delete the table or rows___ due to the Cytoscape data model design. However, it is easy to create / delete columns:
# Delete columns
yeast1.delete_node_table_column('kegg')
# Create columns
yeast1.create_node_column(name='New Empty Double Column', data_type='Double', is_immutable=False, is_list=False)
# Default is String, mutable column.
yeast1.create_node_column(name='Empty String Col')
yeast1.get_node_table().head()
shared name | name | selected | id | foo | entrez | uniprot | sgd | New Empty Double Column | Empty String Col | |
---|---|---|---|---|---|---|---|---|---|---|
SUID | ||||||||||
246470 | YKR026C | YKR026C | False | YKR026C | NaN | 853896 | EI2BA_YEAST | S000001734 | NaN | NaN |
246471 | YGL122C | YGL122C | False | YGL122C | NaN | 852755 | NAB2_YEAST | S000003090 | NaN | NaN |
246472 | YGR218W | YGR218W | False | YGR218W | NaN | 853133 | XPO1_YEAST | S000003450 | NaN | NaN |
246473 | YGL097W | YGL097W | False | YGL097W | NaN | 852782 | RCC1_YEAST | S000003065 | NaN | NaN |
246474 | YOR204W | YOR204W | False | YOR204W | NaN | 854379 | DED1_YEAST | S000005730 | NaN | NaN |
You can also use wrapper API to access Visual Styles.
Current limitations are:
# Get all existing Visual Styles
import json
styles = cy.style.get_all()
print(json.dumps(styles, indent=4))
# Create a new style
style1 = cy.style.create('sample_style1')
# Get a reference to the existing style
default_style = cy.style.create('default')
print(style1.get_name())
print(default_style.get_name())
# Get all available Visual Properties
print(len(cy.style.vps.get_all()))
# Get Visual Properties for each data type
node_vps = cy.style.vps.get_node_visual_props()
edge_vps = cy.style.vps.get_edge_visual_props()
network_vps = cy.style.vps.get_network_visual_props()
print(pd.Series(edge_vps).head())
[ "Universe", "Sample1", "Ripple", "Minimal", "default", "Solid", "Big Labels", "Nested Network Style", "Directed", "default black" ] sample_style1 default 103 0 EDGE 1 EDGE_BEND 2 EDGE_CURVED 3 EDGE_LABEL 4 EDGE_LABEL_COLOR dtype: object
To set default values for Visual Properties, simply pass key-value pairs as dictionary.
# Prepare key-value pair for Style defaults
new_defaults = {
# Node defaults
'NODE_FILL_COLOR': '#eeeeff',
'NODE_SIZE': 20,
'NODE_BORDER_WIDTH': 0,
'NODE_TRANSPARENCY': 120,
'NODE_LABEL_COLOR': 'white',
# Edge defaults
'EDGE_WIDTH': 3,
'EDGE_STROKE_UNSELECTED_PAINT': '#aaaaaa',
'EDGE_LINE_TYPE': 'LONG_DASH',
'EDGE_TRANSPARENCY': 120,
# Network defaults
'NETWORK_BACKGROUND_PAINT': 'black'
}
# Update
style1.update_defaults(new_defaults)
# Apply the new style
cy.style.apply(style1, yeast1)
# Passthrough mapping
style1.create_passthrough_mapping(column='name', col_type='String', vp='NODE_LABEL')
# Discrete mapping: Simply prepare key-value pairs and send it
kv_pair = {
'pp': 'pink',
'pd': 'green'
}
style1.create_discrete_mapping(column='interaction',
col_type='String', vp='EDGE_STROKE_UNSELECTED_PAINT', mappings=kv_pair)
# Continuous mapping
points = [
{
'value': '1.0',
'lesser':'white',
'equal':'white',
'greater': 'white'
},
{
'value': '20.0',
'lesser':'green',
'equal':'green',
'greater': 'green'
}
]
minimal_style = cy.style.create('Minimal')
minimal_style.create_continuous_mapping(column='Degree', col_type='Double', vp='NODE_FILL_COLOR', points=points)
# Or, use utility for simple mapping
simple_slope = StyleUtil.create_slope(min=1, max=20, values=(10, 60))
minimal_style.create_continuous_mapping(column='Degree', col_type='Double', vp='NODE_SIZE', points=simple_slope)
# Apply the new style
cy.style.apply(minimal_style, scale_free100)
Currently, this supports automatic layouts with default parameters.
# Get list of available layout algorithms
layouts = cy.layout.get_all()
print(json.dumps(layouts, indent=4))
[ "attribute-circle", "stacked-node-layout", "degree-circle", "circular", "attributes-layout", "kamada-kawai", "force-directed", "grid", "hierarchical", "fruchterman-rheingold", "isom" ]
# Apply layout
cy.layout.apply(name='circular', network=yeast1)
yeast1.get_views()
yeast_view1 = yeast1.get_first_view()
node_views = yeast_view1['elements']['nodes']
df3 = pd.DataFrame(node_views)
df3.head()
data | position | selected | |
---|---|---|---|
0 | {'sgd': 'S000002353', 'name': 'YDL194W', 'sele... | {'y': 337.3408049125783, 'x': -816.2080368805437} | False |
1 | {'sgd': 'S000002685', 'name': 'YDR277C', 'sele... | {'y': 283.5470442679916, 'x': -768.351675592697} | False |
2 | {'sgd': 'S000000247', 'name': 'YBR043C', 'sele... | {'y': 700.0122446801881, 'x': 166.44780103059588} | False |
3 | {'sgd': 'S000006349', 'name': 'YPR145W', 'sele... | {'y': 549.1767770841686, 'x': -524.6571716355409} | False |
4 | {'sgd': 'S000000856', 'name': 'YER054C', 'sele... | {'y': -104.59739351311714, 'x': 1446.504571276... | False |
from py2cytoscape.cytoscapejs import viewer as cyjs
cy.layout.apply(network=scale_free100)
view1 = scale_free100.get_first_view()
view2 = yeast1.get_first_view()
# print(view1)
cyjs.render(view2, 'default2', background='#efefef')
# Use Cytoscape.js style JSON
cyjs_style = cy.style.get(minimal_style.get_name(), data_format='cytoscapejs')
cyjs.render(view1, style=cyjs_style['style'], background='white')