<> === Concept 1: Networks === Cytoscape is written using the Java programming language, and therefore uses the Object-Oriented paradigm. The central object in Cytoscape is a {{{CyNetwork}}}. The {{{CyNetwork}}} is a combination of a graph, consisting of Nodes and Edges, and the data that is associated with individual graph elements, or the graph itself. {{{CyNetworks}}} inherit from the {{{GraphPerspective}}} which is part of the underlying GINY graph library. All {{{CyNetworks}}} operate on the same set of Nodes and Edges, although not all Nodes and Edges will be in every {{{CyNetwork}}}. This means that if you create a Node in one {{{CyNetwork}}}, it can be added to another {{{CyNetwork}}}, and will have all of its data and connections associated with it. The following diagram shows the classes and their relationships that will be used most. {{attachment:Cytoscape_classes.png}} === Concept 2: Creating and Modifying and Destroying Networks === The creation of {{{CyNetworks}}} is handled by factory methods found in the {{{cytoscape.Cytoscape}}} class. Cytoscape is an abstract static class and cannot be instantiated. However, it does handle all of the creation methods and fires the appropriate events to its listeners. {{{CyNetworks}}} can be created in a variety of ways, but they all work in a similar fashion. What they will do is, given a set of nodes and edges, create the nodes and edges, as necessary, in the shared set of nodes and edges that all {{{CyNetworks}}} use, and then return a {{{CyNetwork}}} that only has the requested nodes and edges. The following are the methods for creating a {{{CyNetwork}}}: {{{ #!java // return an empty network CyNetwork network = Cytoscape.createNetwork("My Network"); // return a new Network from a SIF file CyNetwork network = Cytoscape.createNetwork( file_name, Cytoscape.FILE_SIF, canonicalize, biodataserver, species ); // return a new Network from a GML file CyNetwork network = Cytoscape.createNetwork( file_name, Cytoscape.FILE_GML, canonicalize, biodataserver, species ); // return a new Network from a file, with a standard // suffix, using the default values CyNetwork network = Cytoscape.createNetwork( file_name ); // return a new Network with a subset of Nodes and Edges // from an existing Network, and make the new Network a // a child of the old Network in the Network Panel CyNetwork new_network = Cytoscape.createNetwork( nodes, edges, child_title, parent_network ); }}} When modifying a {{{CyNetwork}}}, it is necessary to operate directly on that {{{CyNetwork}}}, rather than using the {{{Cytoscape}}} class. There are two types of removal that can be done. Using the "removeNode/Edge" method Cytoscape will attempt to completely remove the Node/Edge from both the {{{CyNetwork}}} and the shared set of Nodes and Edges that all {{{CyNetworks}}} have access to. A Node/Edge will not be removed completely if another {{{CyNetwork}}} has a reference to it. The removal can be forced by passing a Boolean "true" to force the removal. {{{ #!java // remove the node, unless used by another CyNetwork network.removeNode( nodeIndex, false ); // remove the node, even if used by another CyNetwork network.removeNode( nodeIndex, true ); }}} If you want the Node/Edge only removed the current {{{CyNetwork}}}, but still available for other {{{CyNetworks}}} ( or even the one it was removed from ) at a later time. The "hide" methods are used. These methods are part of the GINY API, but are linked in the [[http://www.cbio.mskcc.org/cytoscape/javadoc/|JavaDoc]]. {{{ #!java // remove the node from this CyNetwork, but allow it to // be re-used later. network.hideNode( node ); }}} Creating Nodes/Edges can happen in several ways. Since there is a set of Nodes/Edges that are available to all {{{CyNetworks}}}, there is nothing wrong with creating Nodes/Edges that are not a part of any {{{CyNetwork}}}. This is done using the static Cytoscape class, just like {{{CyNetwork}}} creation. {{{ #!java // create a CyNode, Boolean passed so the "create" flag // is enabled CyNode node = Cytoscape.getCyNode( identifier, true ); }}} The same function can also be used to query if a {{{CyNode}}} exists for a particular alias. This is the default behavior, or can be explicitly used by passing a "false" value for the create flag. {{{ #!java // Return a CyNode if one exists, or null if not. CyNode node = Cytoscape.getCyNode( identifier ); if ( node == null ) // there is no node for this identifier }}} Destroying a {{{CyNetwork}}} is also done via the static Cytoscape class using the "destroyNetwork" methods. When a {{{CyNetwork}}} is destroyed all of the Nodes/Edges are hidden, so they are still available for other {{{CyNetworks}}}. Destroying a {{{CyNetwork}}} will also destroy any {{{CyNetworkView}}} that is was created to view this {{{CyNetwork}}}. {{{ #!java // Destroy a CyNetwork Cytoscape.destroyNetwork( network ); // Destroy a CyNetwork using its "getIdentifier" method Cytoscape.destroyNetwork( network.getIdentifier() ); }}} === Concept 3: NetworkView Creation, Modifying and Destruction === While {{{CyNetwork}}} represent the unification of the graph and data, the {{{CyNetworkView}}} is the Visualization of the {{{CyNetwork}}}. Working with {{{CyNetworkView}}} is very similar to working with {{{CyNetwork}}}. As with the {{{CyNetwork}}}, a {{{CyNetworkView}}} is created using the static Cytoscape class, and destroyed in the same way. {{{ #!java // create a CyNetworkView from a CyNetwork CyNetworkView view = Cytoscape.createNetworkView( network ); // ways to destroy a CyNetworkView, given: CyNetwork network; CyNetworkView view; Cytoscape.destroyNetworkView( view ); Cytoscape.destroyNetworkView( view.getIdentifier() ); Cytoscape.destroyNetworkView( network ); // implicit destruction by destroying the network // it is based on Cytoscape.destroyNetwork( network ); Cytoscape.destroyNetwork( network.getIdentifier() ); }}} Modification of a {{{CyNetworkView}}} is not directly possible. It is a WYSIWYG view on a {{{CyNetwork}}}, so hiding a {{{NodeView}}} in a {{{CyNetworkView}}} only makes that {{{NodeView}}} temporarily invisible. To actually remove a {{{NodeView}}} from a {{{CyNetworkView}}}, the Node that it is a view on must be hidden/removed from the {{{CyNetwork}}}. This behavior can be changed, but is beyond the scope of this document. === Concept 4: CyNetwork(View) Client Data === {{{CyNetworks}}} and {{{CyNetworkViews}}} will be used by a variety of plugins, and plugins will use a variety of {{{CyNetworks}}} and {{{CyNetworkViews}}}. Therefore, the concept of client data allows a plugin to store information that it needs about a particular {{{CyNetwork(View)}}}, with that Object. An example of this is a plugin that calculates an APSP matrix, and runs an analysis on it. Obviously each {{{CyNetwork}}} has a different APSP matrix, so if a new {{{CyNetwork}}} is being used, then a new matrix needs to be calculated. {{{ #!java // Sample method for a plugin performing an action CyNetwork network = Cytoscape.getCurrentNetwork(); APSP matrix; Object apsp = network.getClientData( "APSP" ); if ( apsp == null ) { // there is no apsp matrix available, create one matrix = new APSP( network ); // store it for later use network.putClientData( "APSP", matrix ); } // use the matrix we already had, or the one we just made doSomething( matrix ); }}} === Concept 5: Loading, and Using Data === Data can be thought of in many different ways. Usually we refer to data as specific attributes loaded by the user, that refer to one specific Node or Edge. Common attributes are Expression data from Microarray experiments, other laboratory measurements, and ontology information. Data can be loaded in a variety of ways and from a variety of sources. We will only discuss loading from files, and by calculation. Database connections and other things are handled via other methods such as the Data Services Plugin from MSKCC. The most common way to load Node and Edge attributes is from Node and Edge attributes files, and from expression "matrix" files. Both are possible using the static Cytoscape class. {{{ #!java // load Node and Edge Attributes from a set of files. String[] node_atts = { "file1", "file2" }; String[] edge_atts = { "file3", "file4" }; Cytoscape.loadAttributes( node_atts, edge_atts ); // load Expression Data Cytoscape.loadExpressionData( file_name, true ); // right now setting individual attributes is a little // hacky, since we just use the old GraphObjAttributes //class. // @deprecated DO NOT USE!!!! ( unless you have to ) Cytoscape.getNodeNetworkData().set( attribute, node, value ); }}} The more supported way for adding attributes for individual Nodes and Edges (e.g. a calculated value from a Plugin ), is to use the method provided by {{{CyNetwork}}}. {{{ #!java // set a value for a node, for a given attribute String attribute; Object value; CyNode node; // note that the method name is the argument order network.setNodeAttributeValue( node, attribute, value ); }}} {{{CyNetwork}}} also provides methods for getting attributes for nodes. The methods are structured the same as for setting. {{{ #!java // get a value for a node, for a given attribute String attribute; CyNode node; // note that the method name is the argument order Object value = network.getNodeAttributeValue( node, attribute ); }}} Several convenience methods are also available, look at the API. What methods are here are open for debate. Please let us know what you want/need/like/use. === Concept 6: Focus === Since many {{{CyNetworks}}} can exist in one Cytoscape instance it is necessary to know with which {{{CyNetwork}}} and {{{CyNetworkView}}} you are working. For a plugin that operates when a button/menu is selected, and wants to use whichever {{{CyNetwork}}} and {{{CyNetworkView}}} the user choses, then the following methods should be used: {{{ #!java //action method public void actionPerformed ( ActionEvent e ) { CyNetwork network = Cytoscape.getCurrentNetwork(); CyNetworkView view = Cytoscape.getCurrentNetworkView(); } }}} Note that if a {{{CyNetworkView}}} was last focused then the current {{{CyNetwork}}} will always be the {{{CyNetwork}}} of that {{{CyNetworkView}}}. However if a {{{CyNetwork}}} was last focused with no view, then the current {{{CyNetworkView}}} will return {{{Cytoscape.nullNetworkView}}}. === Concept 7: CytoscapeDesktop === The {{{CytoscapeDesktop}}} is responsible for managing all of the {{{CyNetworkViews}}} and for updating the focus. There is only one instance of {{{CytoscapeDesktop}}} and it is available via: {{{ // get the CytoscapeDesktop Cytoscape.getDesktop(); }}} The {{{CytoscapeDesktop}}} will not normally be used, but is useful for being the parent for Dialogs, since it is a JFrame. === Concept 8: Events === Events are a useful way to update an Object when a property changes. Any event listener needs to implement {{{java.beans.PropertyChangeListener}}}. Here are the available events: ||Event ||Firing Class || ||CYTOSCAPE_EXIT ||Cytoscape || ||NETWORK_CREATED ||Cytoscape || ||NETWORK_DESTROYED ||Cytoscape || ||ATTRIBUTES_CHANGED ||Cytoscape || ||NETWORK_VIEW_CREATED ||Cytoscape{{{}}}Desktop || ||NETWORK_VIEW_DESTROYED ||Cytoscape{{{}}}Desktop || ||NETWORK_VIEW_FOCUS ||Cytoscape{{{}}}Desktop || ||NETWORK_VIEW_FOCUSED ||Cytoscape{{{}}}Desktop || This is an example implementation of a class that is a listener to both Cytoscape and {{{CytoscapeDesktop}}}. {{{ #!java public class MyClass implements java.beans.PropertyChangeListener { public MyClass () { // add as listener to Cytoscape Cytoscape.getSwingPropertyChangeSupport(). addPropertyChangeListener(this); // add as listener to CytoscapeDesktop Cytoscape.getDesktop().getSwingPropertyChangeSupport(). addPropertyChangeListener(this); } public void propertyChange ( PropertyChangeEvent e ) { //respond } } }}}