GSoC mid-term: new Preview API

My name is Yudi Xue and during this Google Summer of Code am glad to work on the Core evolution of Gephi.

Current API in the Preview module provides too many granular methods and classes. Developers are clueless about how they may extend the component. In this project, we do not seek to expand what the Preview module already have to offer. Rather, we focus on making the Preview module easy to learn, easy to use and easy to extend to the Gephi developers. The new API will allow developers to focus on particular parts of the module. They may specify a new visual algorithms just by implementing a new type of Renderer, such as edge bundling and convex hull. They may also extend the RenderTarget to allow display or export visualization to different platform.

The user story

We took the infovis reference model into consideration when we started designing the new infrastructure. The infrastructure aims to provide support to a visualization-preview workflow:

raw data -> the data builder -> renderers -> render targets.

In particular, the raw data is the graph associated with the current gephi workspace. The data builder (DataBuilder) will interpret information associated with the nodes and edges and generate Item objects for Preview use. The Item objects are immutable objects that are either node item (NodeItem), edge item (EdgeItem) or item group (GroupItem) specified from the graph workspace or data lab. We append “Item” to refer that they are data rather than display objects. After the data has been imported, the preview controller (PreviewController) will associate each type of entity items with Renderer objects. Renderer objects are functional procedures that describe how an item should be drew. While we give information to an Renderer object what it is going to draw, we also tell it what RenderTarget it will use. By default, we provide ProcessingRenderTarget, PDFRenderTarget and SVGRenderTarget. All RenderTarget objects contribute to the RenderTarget API, which provide granular drawing functions that can be used by developers to form advanced visual algorithm. In addition to the workflow, we will provide a flexible properties structure to the Preview module so it may be used to provide listener to user interface commands. The property will allow dynamic dependency where grouped properties can listen for a single parent property.

The code below demonstrates how a Renderer to a particular Item type could be updated at runtime.

Code sample:

PreviewController prc = (PreviewController)Lookup.getDefault().lookupItem(
                                                       PreviewController.DEFAULT_IMPL).getInstance();
prc.loadGraph();
// Load graph from workspace
prc.updateRenderer(NodeItem.class, new Renderer() {
    // How I want to draw a node, edge, or item types.
    // Specify your procedural visualization algorithm here
    @Override
    public void render(Item item, RenderTarget rt) {
        NodeItem ni = (NodeItem) item;
        rt.drawImage(..);
        rt.drawline(..);
    }
    // The RenderTarget will pick up the properties and draw the rest..
});

The big picture

Speaking of API flexibility, the Preview API goes from constrained to flexible in the direction from DataBuilder to RenderTarget. Here is the big picture:

Current progress

  • done:
    • a working copy based on the new architecture
    • added ProcessingRengerTarget
    • added GroupRenderer (Convex hull)
    • added ImageRenderer
    • basic unit testing
    • basic functional testing against updating Renderer in Preview API at runtime
  • in progress:
    • Property support
    • Selfloop, curved edge drawing
    • PDF and SVG RenderTarget implementation

Here is a screenshot of the new system with convex-hull enabled:

Code practice

The code base is under active development at https://code.launchpad.net/~yudi-xue/gephi/gephi-preview. The code base includes the PreviewAPI module and the PreviewImpl module.

Lookup API

We make use of Netbeans Lookup API to instantiate singleton and use Lookup. Template to ensure the correct implementation been called.

For example, to call the default PreviewController constructor, we call:

/*
* DEFAULT_IMPL is defined in the interface.
* It refers to default implementation class
* "org.gephi.preview.PreviewControllerImpl"
*/
(PreviewController)Lookup.getDefault().lookupItem(PreviewController.DEFAULT_IMPL).getInstance();

Accordingly, you may choose to use the API with your implementation by creating a Template that points your implementation class.

Functional Tests

During the development, we are creating functional tests against our own API for the purpose of both flexibility and stability. the “PreviewAPIFunctionalTest”

Conclusions

Our goal is to bring modularity and extensibility to the Preview module. We aim to deliver the freedom in defining your own visual algorithms (Renderer) and user interaction (Property) and make use of API without thinking about the detailed mechanism. I would like to give my thanks to Dr. Christian Tominski, Mathieu Bastian and Sébastien Heymann for their support and feedback, which is critical during the development for the new architecture.

2 Comments

  1. Hi Jérémy,

    Thank you for your support! Thank you for your support in answer my questions at early development stage. Please take a look at the Renderer and RenderTargets and let me know of any improvement that I can do.

    Reply

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s