Differences between revisions 17 and 18
Revision 17 as of 2010-04-12 19:44:14
Size: 9719
Editor: KeiichiroOno
Comment:
Revision 18 as of 2010-04-12 22:59:08
Size: 10489
Editor: KeiichiroOno
Comment:
Deletions are marked like this. Additions are marked like this.
Line 4: Line 4:
|| '''Title''' : RFC Custom Graphics in the VizMapper || '''Editor(s)''': Mike Smoot KeiichiroOno || '''Date''': 2/12/2010 ||'''Status''': init || || '''Title''' : RFC Custom Graphics in the VizMapper and Dynamic Mapping || '''Editor(s)''': Mike Smoot KeiichiroOno || '''Date''': 2/12/2010 ||'''Status''': init ||
Line 9: Line 9:
Line 44: Line 45:

==== CyCustomGraphics Interface ====
To implement this function, I defined a new interface called ''CyCustomGraphics''
{{{#!java
public interface CyCustomGraphics <T> {
 /**
  * Display name is a simple description of this image object.
  *
  * May not be unique.
  *
  * @return display name as String.
  */
 public String getDisplayName();
 public void setDisplayName(final String displayName);
 
 public Collection<T> getCustomGraphics();
 
 public Image getImage();
 public Image resizeImage(int width, int height);
 
 /**
  * List of properties, i.e., details of this object.
  *
  * @return
  */
 public Collection<CustomGraphicsProperty<?>> getProps();
}
}}}

and then we can define a new Visual Property

Title : RFC Custom Graphics in the VizMapper and Dynamic Mapping

Editor(s): Mike Smoot KeiichiroOno

Date: 2/12/2010

Status: init

Status

3/9/2010 - KeiichiroOno: start working on actual design and implementation

4/9/2010 - KeiichiroOno: start designing dynamic graphics function.

Proposal

We would like to provide some mechanism for allowing users to specify custom graphic images that can be applied to a network using the VizMapper.

Background

The goal of this RFC is to explore ideas for bringing custom graphics out of the programmer-only domain and allow normal users to specify custom graphics for nodes using normal Cytoscape tools like the VizMapper.

Use Cases

customNode1.png

http://www.mathworks.com/products/demos/shipping/bioinfo/biographdemo_10_thumbnail.png

  • A user wants to draw expression values as histogram on nodes (see the pictures above)
  • A user wants a node shape that we don't supply by default.

http://www.yworks.com/img/gallery/autogen/yedscreen22_800x500.png

  • A user wants some non-standard graphic to be applied on or around a node (Like yEd. See the screenshot above).

http://s3.amazonaws.com/data.tumblr.com/tumblr_kz1x6srsNR1qzbqezo1_1280.png?AWSAccessKeyId=0RYTHV9YYQ4W5Q3HQMG2&Expires=1268286166&Signature=Ul6yuhzrhK5XHaOaJtsui6UwwYE=

  • Draw complex graphics using multiple custom graphic objects.

Implementation Plan

  • The general idea is to create a new NODE_CUSTOM_GRAPHIC visual property that would allow users to map specific images to nodes.
  • This visual property would behave the same as other discrete properties like node shape or line type. This implies that most of the existing VizMapper GUI widgets could be used with minimal modification.

  • We would provide a new menu option that would allow users to load image files and make them accessible to the VizMapper.

  • We would need to consider I/O issues related to Session saving and loading.
    • One thought is to make a Custom Graphic a new type of CyAttribute. The advantage is that we could use the existing I/O mechanisms and we also allow passthrough mappings to point to the image. However, that might not buy us much as we'd need to add support in MANY places. It also doesn't make much sense to have graphics attached to specific nodes from the outset.

Specific Ideas

CyCustomGraphics Interface

To implement this function, I defined a new interface called CyCustomGraphics

   1 public interface CyCustomGraphics <T> {
   2         /**
   3          * Display name is a simple description of this image object.
   4          * 
   5          * May not be unique.
   6          * 
   7          * @return display name as String.
   8          */
   9         public String getDisplayName();
  10         public void setDisplayName(final String displayName);
  11         
  12         public Collection<T> getCustomGraphics();
  13         
  14         public Image getImage();
  15         public Image resizeImage(int width, int height);
  16         
  17         /**
  18          * List of properties, i.e., details of this object.
  19          * 
  20          * @return
  21          */
  22         public Collection<CustomGraphicsProperty<?>> getProps();
  23 }
  24 

and then we can define a new Visual Property

Mapping Problem

Simple use case is mapping to a static image.

 Attr value 1 = Image URL 1
 Attr value 2 = Image URL 2
 Attr value 3 = Image URL 1
 Attr value 4 = Image URL 3
 .
 .
 .

However, this is not efficient for the following case. Suppose a user has expression values as a list attribute. If there are N nodes in the network and he/she wants to map this attribute value to pi charts, the user needs to create N images and have to create a map like this:

 List 1 = Chart image URL 1
 List 2 = Chart image URL 2
 List 3 = Chart image URL 3
 
 .
 .
 .
 List N = Chart image URL N

In addition, in this case, images are bitmap and could not maintain the chart image quality when user export it as a vector image. To solve this issue, we can use CustomGraphicsBuilder interface.

   1 public interface CustomGraphicsBuilder<T> {
   2         public Collection<CustomGraphic> createCustomGraphics(final T constraint);
   3 }
   4 

And implementations look like the following:

   1 public class URLImageBuilder implements CustomGraphicsBuilder<URL> {
   2 
   3         @Override
   4         public Collection<CustomGraphic> createCustomGraphics(final URL constraint) {
   5                 
   6                 final Rectangle2D bound = new java.awt.geom.Rectangle2D.Double(-11.0, -15.0, 22.0, 30.0);
   7                 Paint paint = null;
   8                 try {
   9                         paint = new TexturePaint(ImageIO.read(constraint), bound);
  10                 } catch (IOException e) {
  11                         e.printStackTrace();
  12                 }
  13                 final List<CustomGraphic> graphics = new ArrayList<CustomGraphic>();
  14                 graphics.add(new CustomGraphic(bound, paint, NodeDetails.ANCHOR_WEST));
  15                 
  16                 return graphics;
  17         }
  18 }
  19 

   1 public class HistogramGraphicsBuilder implements CustomGraphicsBuilder<List<Double>> {
   2 
   3         @Override
   4         public Collection<CustomGraphic> createCustomGraphics(final List<Double> constraint) {
   5                 final List<CustomGraphic> graphics = new ArrayList<CustomGraphic>();
   6                 
   7                 // Draw histogram using double value here.
   8                 
   9                 return graphics;
  10         }
  11 }
  12 

This enables user maximum flexibility. They can mix multiple builders in a mapping when necessary.

By default, core provides URL image mapping and some very simple CustomGraphicsBuilder implementations. Plugin author can create their own builder if they need custom nodes.

In this design, mapping is attribute value to builder + constraint.

 Attr value 1 = (URLImageGraphicsBuilder, http://cytoscape.org/images/image1.png)
  • Images could be specified using URLs or local files. This implies we'd use the Bookmarks API and the normal FileUtil for loading images into Cytoscape.

  • We would use the session plugin file saving mechanism for storing loaded images.
  • Write all UI functionality (menu items, etc.) as a plugin. Only touch the core for adding new visual properties.
  • Setting custom images would simply use the existing custom graphic API in Ding.

Generate Dynamic Custom Graphics using custom mapping

  • Original Object Mapping

   1 public interface ObjectMapping<V> extends Cloneable {
   2 
   3         /**
   4          * Class of mapped object.  For example, if this is an Node Color mapping,
   5          * this value is Color.class.
   6          * 
   7          * @return
   8          */
   9     public Class<V> getRangeClass();
  10 
  11     /**
  12      * Return the classes that the ObjectMapping can map from, eg. the contents
  13      * of the data of the controlling attribute.
  14      * <p>
  15      * For example, DiscreteMapping {@link DiscreteMapping} can only accept
  16      * String types in the mapped attribute data. Likewise, ContinuousMapping
  17      * {@link ContinuousMapping} can only accept numeric types in the mapped
  18      * attribute data since it must interpolate.
  19      * <p>
  20      * Return null if this mapping has no restrictions on the domain type.
  21      *
  22      * @return Array of accepted attribute data class types
  23      */
  24     public Class<?>[] getAcceptedDataClasses();
  25 
  26     
  27     /**
  28      * Set controlling attribute of this mapping.
  29      * 
  30      * @param controllingAttrName - name of the attribute associated with this mapping.
  31      * 
  32      */
  33     public void setControllingAttributeName(final String controllingAttrName);
  34     
  35     
  36     /**
  37      * Get the controlling attribute name
  38      */
  39     public String getControllingAttributeName();
  40 
  41     /**
  42      * Add a ChangeListener to the mapping. When the state underlying the
  43      * mapping changes, all ChangeListeners will be notified.
  44      *
  45      * This is used in the UI classes to ensure that the UI panes stay consistent
  46      * with the data held in the mappings.
  47      *
  48      * @param    l    ChangeListener to add
  49      */
  50     public void addChangeListener(ChangeListener l);
  51 
  52     /**
  53      * Remove a ChangeListener from the mapping. When the state underlying the
  54      * mapping changes, all ChangeListeners will be notified.
  55      *
  56      * This is used in the UI classes to ensure that the UI panes stay consistent
  57      * with the data held in the mappings.
  58      *
  59      * @param    l    ChangeListener to add
  60      */
  61     public void removeChangeListener(ChangeListener l);
  62 
  63     /**
  64      * Create a mapped visual representation from the given attribute value.
  65      * 
  66      * @param attrBundle
  67      * @return
  68      */
  69     public V calculateRangeValue(final Map<String, Object> attrBundle);
  70 
  71     public JPanel getLegend(VisualPropertyType type);
  72 
  73     public Object clone();
  74 
  75     public void applyProperties(Properties props, String baseKey, ValueParser<V> parser);
  76 
  77     public Properties getProperties(String baseKey);
  78 }
  79 

To generate variety of custom graphics, we need a mechanism to map multiple attribute values to a graphics. For example, if user wants to generate histograms for nodes, it requires List attributes one for x-axis, and the other one for y-axis.

List Attr 1 = {t1, t2, ...., tn}
List Attr 2 = {0.21, 0.53, ..., m}

To solve this problem, we can define a new mapping type called CustomMapping:

   1 public interface CustomMapping<V> {
   2         
   3         public Component getEditor();
   4 }
   5 

Custom Mapping Editor

Each custom mapping should have a GUI editor component.

customEditor1.png

Project Management

Project Dependencies

  • This depends on the CustomGraphic API present in !DNodeView, something we might want to expose in GINY instead.

Issues

  • What sort of image types will we support? PNG and JPG should be easy, but what about vector graphics like PDF or SVG?
  • Would we want to provide facilities for scaling or other affine transforms for manipulating the images once they're loaded?
  • We might want a separate visual property for setting custom graphic position. If not then we might need to extend current discrete VizMapper widgets to allow use to choose North/South/East/West positioning. Either way, this might be messy given the current API.

  • What about background images?
    • Can we provide a minimal API that allows users to set background images?
    • How would this integrate with the VizMapper?

Comments

RFC_Custom_Graphics_VizMapper (last edited 2010-06-15 20:25:34 by KeiichiroOno)

Funding for Cytoscape is provided by a federal grant from the U.S. National Institute of General Medical Sciences (NIGMS) of the Na tional Institutes of Health (NIH) under award number GM070743-01. Corporate funding is provided through a contract from Unilever PLC.

MoinMoin Appliance - Powered by TurnKey Linux