Basic definitions

A data attribute is a key-value pair, where the key is a string identifying the attribute and the value is a number, String, or other type of object. A data attribute is attached to a name, which itself is associated with a particular graph object, but the class of a particular data attribute will be the same for all graph objects of the same type. For example, the "interaction" attribute for edges is of the same type for every edge (a String, in this case). Cytoscape holds two data structures, one for all node attributes and one for all edge attributes. Usage is of the form

   1 nodeAttributes.set(objectName, attributeName, value);
   2 Object value = nodeAttributes.get(objectName, attributeName);
   3 

A Network is an object that contains a Graph and the associated node and edge attribute structures.

A visual attribute is a single atomic component of the visual appearance of the objects in the graph. For example, the shape of a node is one visual attribute, while the fill color of the node is a different visual attribute. There are many visual attributes for nodes and edges, and there are also a few global visual attributes, such as the background color of the window in which the graph is displayed.

A calculator is an object that, given a Network and a particular node or edge of interest, can calculate a value of an appropriate type for a particular visual attribute. Calculators are typed by the graph object type (Node or Edge) and by the class of the value to return: for example, Color, String, or LineType. Some visual attributes use the same type of calculator; for example, calculators for the node fill color and node border color are both NodeColorCalculator objects. Currently there are no calculators for the global visual attributes. Calculators are referenced by name and stored in a global catalog.

An appearance calculator is an object that holds default values and calculators for a set of related individual visual attributes, and methods to apply these given a particular node or edge of interest. There are three different appearance calculators: one for nodes, one for edges, and one for global visual attributes.

A visual style bundles one each of the three appearance calculators and thus contains a complete definition of all the customizable visual attributes. Visual styles are also referenced by name and stored in the global catalog. A common usage is to define a visual style for each distinct Cytoscape project, often sharing individual attribute calculators.

Conceptual overview

Cytoscape maintains a catalog of all the known visual styles and all the known calculators. Each of these has an identifying name which is unique among its type; for example, every NodeColorCalculator has a unique name, but NodeLabelCalculators can use those names as well. Cytoscape itself constructs a visual style called "default" which is used in the absence of any user-specified style.

At any point in time, one particular visual style is being used by Cytoscape to control the appearance of the graph. A visual style is represented by an object of class VisualStyle and contains three other objects, one for the node appearance, one for the edge appearance, and one for the global appearance. The first two of these can compute, for a given node or edge, a data bundle (formally a class with public members) that contains a full set of values to use for the visual attributes of that particular node or edge. Similarly, the global appearance member of the visual style can construct a data object holding the global visual attribute values. These data objects are then used by Cytoscape, via calls to the graph visualization library, to set the visual appearance of the whole graph.

Thus, except for the very top-level class that applies the appearances, the visual package is conceptually independent of the details of the graph library used to display the graph. This independence is broken in two ways:

  1. The particular names and types of visual attributes have been chosen to be meaningful with respect to to the particular graph library (GINY) we're currently using;
  2. The references to Node and Edge objects, plus certain special visual attributes like Arrow, require importing the defintion of these objects from the graph library.

For every visual attribute defined, the visual style will contain (within one of it's three members) a default value; there may also be a calculator for that visual attribute that can compute a value based on the available data attributes.

Typical usage includes: creating a new visual style or copying an existing one; changing the default values for a particular visual attribute; getting a calculator from the catalog and installing it in the visual style; modifying the parameters of an existing calculator; or creating a new calculator and adding it to both the catalog and the visual style.

The visual package contains utilities to store the catalog of known visual styles and calculators as a Java properties file, and to reconstruct the catalog from this file. This allows visual style defintions to be persistent across Cytoscape sessions. The CytoscapeWindow class contains methods that use these features, for example saving the catalog when the program exits and reconstructing it at startup.

The next section will give a quick presentation of the classes that provide these features.

Top-down class descriptions

A basic understanding of how the conceptual model is implemented in Java classes

In the previous section, we presented the conceptual model of the visual pacakge. Here, we'll see how this model is implemented in concrete Java classes. The objective here is to give you a general understanding of the responsibilities of each class, without going into detail concerning implementations or the full API of each class. Refer to the class documentation for more information on any of these classes.

This section begins at the top-level class and continues to the level of abstract calculators; a later section will describe how individual calculators are implemented within the visual package. The figure below illustrates the relationships of the classes we will describe here.

VisualMappingManger

At the top is the VisualMappingManager class. CytoscapeWindow holds one instance of this class, which encapsulates all the data structures relevant to visual mapping. VisualMappingManager contains a CalculatorCatalog, which contains all of the known VisualStyle and calculator objects, and one VisualStyle object which represents the current visual style.

CalculatorCatalog

CalculatorCatalog contains a Map structure for visual styles and a Map for each type of calculator. Within each Map the key is the name and the value is the VisualStyle or calculator object. This class includes the obvious methods to add a new object or get one with a specified name, as well as a number of helper methods for the user interface to the visual package.

VisualStyle, Appearances, and AppearanceCalculators

The VisualStyle object has a name and contains three member objects; a NodeAppearanceCalculator, an EdgeAppearanceCalculator, and a GlobalAppearanceCalculator. Each of these objects, in turn, contains a default value for each visual attribute and a (possibly null) reference to a calculator for each visual attribute.

Each of these three appearance calculators has a method for calculating an appearance object; the signatures are, respectively,

   1 public NodeAppearance calculateNodeAppearance(Network network, Node node);
   2 public EdgeAppearance calculateEdgeAppearance(Network network, Edge edge);
   3 public GlobalAppearance calculateGlobalAppearance(Network network);
   4 

These methods work by calling the appropriate calculator (if it exists) for each visual attribute; using the default value if no calculator is installed or if it returns a null value; and storing the resulting value in the constructed appearance object. These three appearance objects are simply data bundles, classes with all public members, each holding a value for a particular visual attribute.

When the top-level VisualMappingManager is told to apply its visual appearances, it calls the calculate methods on the three appearance calculator objects in its VisualStyle to get the appearance objects, then uses the data within those objects in calls to the graph library to set the visual appearance of the displayed graph. This code is contained in the applyAppearances method of VisualMappingManager.

Thus, everything below VisualMappingManager is conceptually independent of the particular graph library in use. In practice, the default values and calculators that the appearance calculators recognize are tuned to the particular visual attributes supported by the graph library. In addition, some specific classes such as Node, Edge, Arrow, and LineType are defined within the graph package itself, so the appearance calculators, as well as the invididual attribute calculators, import these classes from the graph library.

Attribute Calculators

Individual attribute calculators are identified by an interface whose name contains the type of graph object (Node or Edge) and the type of the visual attribute value. Examples include NodeColorCalculator, NodeLabelCalculator, and EdgeLineTypeCalculator. Each interface specifies a method that calculates the visual attribute value; the signatures for these three examples are, respectively,

   1 public Color calculateNodeColor(Network network, Node node);
   2 public String calculateNodeLabel(Network network, Node node);
   3 public LineType calculateEdgeLineType(Network network, Edge edge);
   4 

Currently there are no calculators for global visual attributes; this is only because there is currently no need for this feature, but the calculator design could easily be extended to support such calculators.

in addition to the main calculate method, these interfaces all inherit from the abstract Calculator interface that defines several methods all calculators must support. These include a getUI() method that returns a user interface to the calculator; methods to get and set the name of the calculator, and methods to convert the calculator to and from a Properties object, to support storing calculators as a properties file.

Note that in some cases, different visual attributes use the same type of calculator. For example, NodeAppearanceCalculator contains a nodeFillColorCalculator and a nodeBorderColorCalculator; both of these are instances of NodeColorCalculator, since it makes perfect sense to apply the same calculator to either of these visual attributes that share the same type. However, edge colors are calculated by instances of EdgeColorCalculator; this difference exists because these calculators expect to operate on different data attributes (edge attributes instead of node attributes).

The node width and node height visual attributes require special mention. In some cases it's desired for these attributes to be independent (allowing arbitrary aspect ratios), while in other cases these attributes should always hold the same value to produce symmetric shapes. This often depends on the node shape; for example, rectangles require a width different from the height, while circles require the two to be equal. This is supported within NodeAppearanceCalculator by a boolean flag which, if true, uses only the default node height and node height calculator for both the width and height of a node, thus forcing the width of every node to be equal to the height. In either case, a NodeSizeCalculator is used for either or both of these visual attributes.

Input and Output from file

Input and output of the CalculatorCatalog from a properties file is provided by the CalculatorIO class. This class contains static methods that, given a properties file and a catalog, either load the definitions from the file and install them in the catalog, or represent the catalog as properties and save it to file. These methods work by grouping the properties that define each object and delegating to helper methods and factory objects that convert between calculator objects and their properties description.

Before this visual package was created, a different package (called cytoscape.vizmap) was used to specify visual mappings, which used entries in the cytoscape.props file. The class OldStyleCalculatorIO contains methods to handle this old format. They search the properties object read from the various cytoscape.props files for these old-style mappings, and guide the user (via a window interface) to convert them to the new format. This works by converting key-value pairs of the old properties format into the new format, then sending these converted properties through the machinery of CalculatorIO. This functionality is expected to go away once all users have had a chance to convert their visual specifications into the new format.

Common usage of the visual package

Code snippets that show how to do common operations

In this section, we present code snippets that illustrate the calls a plugin writer would use to perform some common operations.

To access the top-level objects:

   1 //returns CytoscapeWindow's VisualMappingManager object
   2 VisualMappingManager vmm = cytoscapeWindow.getVizMapManager();
   3 
   4 //gets the global catalog of visual styles and calculators
   5 CalculatorCatalog catalog = vmm.getCalculatorCatalog();
   6 
   7 //gets the currently active visual style
   8 VisualStyle currentStyle = vmm.getVisualStyle();
   9 
  10 //methods to access the node, edge, and global appearance calculators
  11 NodeAppearanceCalculator nodeAC = currentStyle.getNodeAppearanceCalculator();
  12 EdgeAppearanceCalculator edgeAC = currentStyle.getEdgeAppearanceCalculator();
  13 GlobalAppearanceCalculator globalAC = currentStyle.getGlobalAppearanceCalculator();
  14 

Default values:

   1 nodeAC.setDefaultNodeHeight(50.0);
   2 nodeAC.setDefaultNodeShape(ShapeNodeRealizer.ELLIPSE);
   3 nodeAC.setNodeSizeLocked(true); //width==height, so default will be a circle
   4 edgeAC.setDefaultEdgeArrow(Arrow.STANDARD);
   5 globalAC.setDefaultBackgroundColor( new Color(255,255,204) );//pale yellow
   6 
   7 Color defaultNodeFillColor = nodeAC.getDefaultNodeFillColor();
   8 LineType defaultEdgeLineType = edgeAC.getDefaultEdgeLineType();
   9 Color newBackgroundColor = globalAC.getDefaultBackgroundColor();//pale yellow
  10 

Calculators:

   1 NodeColorCalculator ncc = catalog.getNodeColorCalculator("myFillColor");
   2 nodeAC.setNodeFillColorCalculator(ncc);
   3 EdgeArrowCalculator eac = catalog.getEdgeArrowCalculator("mySourceArrow");
   4 edgeAC.setEdgeSourceArrowCalculator(eac);
   5 
   6 NodeLabelCalculator nlc = nodeAC.getNodeLabelCalculator();
   7 EdgeFontCalculator efc = edgeAC.getEdgeFontCalculator();
   8 

Changing styles:

   1 VisualStyle newStyle = catalog.getVisualStyle("Project B");
   2 vmm.setVisualStyle(newStyle);
   3 

Creating a new style with default settings:

   1 VisualStyle newStyle = new VisualStyle("name of new style");
   2 catalog.addVisualStyle(newStyle);
   3 

Copying an existing style:

   1 VisualStyle newStyle = new VisualStyle(oldStyle);
   2 newStyle.setName("name of new style");
   3 vatalog.addVisualStyle(newStyle);
   4 

Generic calculators and mappings

How calculators are implemented within the visual package, and how to set their parameters

The top-level classes of the visual package were described in a previous section. The actual calculation of visual attribute values from data attribute values is performed by calculator objects, which are described here. The relevant classes are found in the visual.calculators and visual.mappings packages.

Formally, a calculator object is any object that implements one of the interfaces defined in the visual.calculators package. The names of these interfaces are all of the form

<object type><return type>Calculator

where the object type is either "Node" or "Edge" and the return type is the name of the returned type class. Examples include NodeColorCalculator and EdgeArrowCalculator.

Each of these interfaces defines a particular calculate method that takes appropriate arguments and returns an object of the correct type. For example, the methods in NodeColorCalculator and EdgeArrowCalculator have the following signatures:

   1 public Color calculateNodeColor(Network network, Node node);
   2 public Arrow calculatorEdgeArrow(Network network, Edge edge);
   3 

Recall that a Network object contains the graph and data attributes, and thus contains all the data needed to calculate the return value.

All of these interfaces extend the generic Calculator interface, which defines other methods shared by all calculators. A key pair of methods allow getting and setting the name of the calculator. Every calculator must have a name, which is used to uniquely identify that calculator. For example, the name of the calculator is used in the CalculatorCatalog as the key to the Map of calculator objects, and in the property keys used to save the calculator to file. Note that two calculators of different types may share the same name, but two calculators that implement the same interface should have different names. When creating a new calculator, it is essential to make sure that a unique name is provided to prevent collisions with an existing calculator. For this reason, CalculatorCatalog provides methods of the form

public String checkNodeColorCalculatorName(String name);

If no NodeColorCalculator currently has the given name, then that name is returned. Otherwise, this method adds an integer to the end of the name to make a unique name (for example, "myCalc", "myCalc2", "myCalc3", etc.).

Implementation

The calculator interfaces, by themselves, do not specify how the actual calculation of the return value should be done. Thus, in theory, any arbitrarily complex function could be used; for example, calculating the color of a node based on the data attributes of the nodes in its graph neighborhood. The visual package provides a generic implementation that is useful in many circumstances.

The basic idea of the generic calculator implementations is to delegate to another object that performs two services:

  1. Given the data attributes for the particular node or edge of interest, it extracts one of the data attributes by name
  2. Using that data value, it gets an Object according to some kind of lookup table and returns it. The generic calculators then cast that Object to the desired type and return it. Type safety is ensured by controlling the entries in the lookup table.

The advantage of this implementation is that all of the different types of calculators can be supported with a small set of objects that provide different types of mappings. This makes the job of implementation (especially of the user interface to these objects) much simpler. The disadvantage is that these implementations only allow the visual attribute value to depend on a single data attribute of the particular node or edge being considered.

All of the generic calculator class names are of the form

Generic<interface name>

For example, GenericNodeColorCalculator or GenericEdgeArrowCalculator. Each of these classes inherit either from NodeCalculator or EdgeCalculator, which in turn inherit from AbstractCalculator. These abstract superclasses provide utilities used by all the generic calculators, for example holding the calculator name.

Each generic calculator wraps an instance of the ObjectMapping interface. The key method defined in this interface is

public Object calculateRangeValue(Map attrBundle);

Here, the argument is the set of attributes defined for the particular node or edge being considered. All instances of ObjectMapping extract one attribute from this Map using the name defined by

   1 public String getControllingAttributeName();
   2 public void setControllingAttributeName(String attrName, Network network, boolean preserveMapping);
   3 

To get the data value. (In the set method, the extra arguments are provided to allow the mapping to get the existing data values for the new attribute to help in building the lookup table.) How this data value is used depends on the particular instance; the visual package defines three instances, PassthroughMapping, DiscreteMapping, and ContinuousMapping.

In a PassthroughMapping, the data value is itself type-checked and returned. This kind of mapping is most commonly used for labels, where one data attribute of the node or edge is a String name, and that String itself should be returned as the label. This type of mapping can be used whenever the data attribute holds the actual value to use for the visual attribute.

In a DiscreteMapping, the data value is used as the key in a lookup table (formally a Map structure). The entries in a DiscreteMapping are restricted so that the keys are of the same type as the data value, and the values are of the correct return type. Currently, only String and Number data attributes are supported. This kind of mapping is best used when the data attribute can have a small number of discrete values, and one wants to define a visual attribute value to use for each different case. For example, if there are a few different types of edges, a DiscreteMapping can be used to set the color to use for each edge type.

In a ContinuousMapping, the data attribute must be a number (formally, an instance of java.lang.Number). Certain special data values, termed boundary values, are defined and mapped to visual attribute values. If the visual attribute is itself continuous (like Color or Number), then a data value associated with a particular node or edge is used in a linear interpolation between the boundary values to compute the visual attribute value. For example, if the data value 0.0 is mapped to white and 1.0 is mapped to green, then the data value 0.5 would map to 50% green. If the visual attribute is instead discrete, for example node shape, then a range of input values maps to a particular visual attribute value.

Building and using your own calculator class

To be filled in

Visual_Mapping_System_Guide (last edited 2009-02-12 01:03:56 by localhost)

MoinMoin Appliance - Powered by TurnKey Linux