GithubHelp home page GithubHelp logo

ivis-at-bilkent / cytoscape.js-cosep Goto Github PK

View Code? Open in Web Editor NEW
5.0 6.0 0.0 4.77 MB

Compound Spring Embedder with Ports (CoSEP)

License: MIT License

JavaScript 100.00%
graphviz graph-algorithms graph-drawing

cytoscape.js-cosep's Introduction

cytoscape.js-cosep

Description

Compound Spring Embedder with Ports (CoSEP) is a force-directed layout algorithm based on the CoSE (Compound Spring Embedder) to support port constraints on compound graphs. Further improvements are achieved by various heuristics such as shifting port constrained edges around the node and by rotating nodes. Below is an example where the same graph is laid out without (left) paying attention to port constraints on edge ends and when (right) paying attention to these constraints using CoSEP.

               

Here is a demo illustrating CoSEP's capabilities. You may use samples available for testing or upload your own graph in GraphML format and add constraints manually. Quality metrics such as ratio of properly oriented edge ends (an edge end is deemed as properly oriented if its edge does not intersect with its end node.) and edge-edge crossing count are provided after layout as well as the total running time. Many options, some inherited from CoSEP's predecessor CoSE, are exposed to the user to fine tune the algorithm.

Dependencies

  • Cytoscape.js: ^3.2.0
  • cose-base ^2.0.0

Documentation

Port constraints are associated with edges and can have two port constraints defined on each of its endpoints. When an edge endpoint does not have a specified port constraint, it is assumed that it connects to the center of the source/target node (the edge is typically rendered w.r.t. to the source/target node shape’s boundaries however).

The ports are realized as discrete points distributed evenly around a node. The ports then can be indexed clock-wise as {0, 1, 2, … , 4k-1} starting at the top-left where k > 0 is the number of ports on each side, specified by the user. For instance, ports are distributed as follows when k = 5:

Various degrees of port constraints can be defined on edge endpoints:

  • Free: The specified end of the edge can be placed at any port of the associated node
  • Fixed Side(s): A set s of directions from {top, left, bottom, right} can be assigned to an edge end
  • Absolute Position: Using the indices of ports, edge ends can be assigned to specific / static positions

Usage instructions

Download the library:

  • via npm: npm install cytoscape-cosep,
  • via bower: bower install cytoscape-cosep, or
  • via direct download in the repository (probably from a tag).

Import the library as appropriate for your project:

ES import:

import cytoscape from 'cytoscape';
import cosep from 'cytoscape-cosep';

cytoscape.use( cosep );

CommonJS require:

let cytoscape = require('cytoscape');
let cosep = require('cytoscape-cosep');

cytoscape.use( cosep ); // register extension

AMD:

require(['cytoscape', 'cytoscape-cosep'], function( cytoscape, cosep ){
  cosep( cytoscape ); // register extension
});

Plain HTML/JS has the extension registered for you automatically, because no require() is needed.

API

When calling the layout, e.g. cy.layout({ name: 'cosep', ... }), the following options are supported:

var options = {
    // -------- Mandatory parameters --------
    name = 'cosep',
    
    // This is the number specifying the number of ports on one node's side. If three is given, there would be 
    // twelve ports around one node.
    portsPerNodeSide: 3,
        
    // Port constraints information has to be given as a function.
    // For the fcn, it would be given a Cytoscape edge and is expected to return constraint info about that edge.
    // Since both endpoints of an edge can have port constraints, this fcn returns an array. (See below)
    portConstraints: portInfo,
    
    /* The format of the array that "portInfo" returns has to be in the following way:
    [{
      "endpoint": "Target",             // or "Source"
      "portConstraintType": "Sided",    // or "Free" or "Absolute"
      "portConstraintParameter": [      // or any combination of node sides.                               
        "Top",                          // If it is "Free", this line doesn't matter. If "Absolute", any number 
        "Bottom"]                       // denoting the port location will do. e.g. "3"
    },
    {
      "endpoint": "Source",             // Here both endpoints are port constrained. If only "Target" or "Source"
      "portConstraintType": "Absolute", // is to be constrained, omit the other object from the array.
      "portConstraintParameter": "3"
    }]
    */
    
    /*
    ---------------- Optional parameters ----------------
    Don't include anything if you are not going to change the value
    Otherwise, you can add the specific line with changed parametre
    */
    
    // Whether to animate the layout
    // - true : Animate while the layout is running
    // - false : Just show the end result
    // - 'end' : Animate directly to the end result
    animate: false,
    
    // number of ticks per frame; higher is faster but more jerky
    refresh: 30,
    
    // Used to slow down time in animation:'during'
    fps: 30, 
    
    // so you can't drag nodes during layout
    ungrabifyWhileSimulating: false, 
    
    // on every layout reposition of nodes, fit the viewport
    fit: true, 
   
    // padding around the simulation
    padding: 30, 

    // positioning options
    randomize: true, // use random node positions at beginning of layout
    
    // Node repulsion (non overlapping) multiplier
    nodeRepulsion: node => 4500,
    
    // Ideal edge (non nested) length
    idealEdgeLength: edge => 50,
    
    // Divisor to compute edge forces
    edgeElasticity: edge => 0.45,
    
    // Nesting factor (multiplier) to compute ideal edge length for nested edges
    nestingFactor: 0.1,
    
    // Gravity force (constant)
    gravity: 0.25,
    
    // Whether to tile disconnected nodes
    tile: true,
    
    // Represents the amount of the vertical space to put between the zero degree members during the tiling operation
    // Can also be a function
    tilingPaddingVertical: 10,
    
    // Represents the amount of the horizontal space to put between the zero degree members during the tiling operation
    // Can also be a function
    tilingPaddingHorizontal: 10,
    
    // Gravity range (constant) for compounds
    gravityRangeCompound: 1.5,
    
    // Gravity force (constant) for compounds
    gravityCompound: 1.0,
    
    // Gravity range (constant)
    gravityRange: 3.8,

    // Whether a node can be rotated/swapped
    nodeRotations: node => true,
    
    // Thresholds for force in Phase II
    edgeEndShiftingForceThreshold: 1,
    nodeRotationForceThreshold: 20,
    rotation180RatioThreshold: 0.5,
    rotation180AngleThreshold: 130,

    // Periods for Phase II
    edgeEndShiftingPeriod: 5,
    nodeRotationPeriod: 15,

    // Polishing Force
    polishingForce: 0.1,

    // Grouping 1-Degree Nodes Across Ports
    furtherHandlingOneDegreeNodes: true,
    furtherHandlingOneDegreeNodesPeriod: 50,
    
    // layout event callbacks
    ready: function(){}, // on layoutready
    stop: function(){}, // on layoutstop
}

Build targets

  • npm run test : Run Mocha tests in ./test
  • npm run build : Build ./src/** into cytoscape-cosep.js
  • npm run watch : Automatically build on changes with live reloading (N.b. you must already have an HTTP server running)
  • npm run dev : Automatically build on changes with live reloading with webpack dev server
  • npm run lint : Run eslint on the source

N.b. all builds use babel, so modern ES features can be used in the src.

Publishing instructions

This project is set up to automatically be published to npm and bower. To publish:

  1. Build the extension : npm run build:release
  2. Commit the build : git commit -am "Build for release"
  3. Bump the version number and tag: npm version major|minor|patch
  4. Push to origin: git push && git push --tags
  5. Publish to npm: npm publish .
  6. If publishing to bower for the first time, you'll need to run bower register cytoscape-cosep https://github.com/iVis-at-Bilkent/cytoscape.js-cosep.git
  7. Make a new release for Zenodo.

Credits

Icons in the demo are by Freepik.

Team

cytoscape.js-cosep's People

Contributors

alihanokka avatar hasanbalci avatar ugurdogrusoz avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar

cytoscape.js-cosep's Issues

To do before paper submission

  • Review the README

  • Demo improvements:

    • "CoSE Bilkent Layout" -> "CoSE Layout"
    • Consistently capitalize text in buttons, etc. ("Import Constraints from File" instead of "Import constraints from file")
    • Add some help about how one can interactively add constraints to our demo. This can go as text ("Click on an edge and follow instructions") under the "Add Random Constraints to Graph" button?
    • "Import constraints from file" will not fit on a single line on a 15inch laptop, please widen the button slightly so that it does. Screen Shot 2020-08-09 at 22 11 38
  • Merge unstable branch to master

Absolute port constraints not working correctly

When there are two or more edges with absolute port constraints in all terminal points between a node pair, only one edge seems to satisfy the constraints after doing a layout.

This problem can be replicated using,
graphandconstraintsForReplicaGraph.zip

The steps to replicate:

  1. Load replica40to40.graphml on demo.
  2. Import the constraint file constraintsForReplicaGraph.json
  3. Do Layout with rotations off.

After the layout, i.e, e2 isn't drawn with respect to its constraint and when node 4 is dragged, e2s terminal points change location when they shouldn't.

Real life data for testing

Currently we do have a bunch of SBGN maps with which we can test our algorithm but it'd be great if we had real life data from some other domain as well. Preferably one where the constraint types are different (on all four sides would be great).

During animation not working correctly

When the layout is applied with the animation option 'true' (that is, during layout), it doesn't generate correct results. For example, a few nodes are positioned far from the rest of the graph sometimes.

Invalid array length

Hello,

I was trying to use cosep Layout in a working Cytoscape.js solution (working with ELK, CoSe,...).
But I'm getting the following error:

layout-base.js:3737 Uncaught RangeError: Invalid array length
    at CoSEPLayout.FDLayout.calcGrid (layout-base.js:3737)
    at CoSEPLayout.FDLayout.updateGrid (layout-base.js:3777)
    at CoSEPLayout.FDLayout.calcRepulsionForces (layout-base.js:3493)
    at CoSEPLayout.CoSELayout.tick (cose-base.js:1552)
    at CoSEPLayout.CoSELayout.runSpringEmbedder (cose-base.js:1589)
    at CoSEPLayout.CoSELayout.classicLayout (cose-base.js:1468)
    at CoSEPLayout.CoSELayout.layout (cose-base.js:1414)
    at CoSEPLayout.Layout.runLayout (layout-base.js:2718)
    at a.prerun (cytoscape-cosep.js:1863)
    at a.run (cytoscape-cosep.js:2342)

The value of sizeX and sizeY is both -42949672. I've added a check (lesser 0 than 0) but then an error occurs in another place.

What could lead to such an error? Any hints where I can continue to analye what's going wrong?

Best regards!

Evaluation scripts

Prepare a README for explaining how to run the evaluation scripts (for measuring performance of CoSEP) and commit all related code, documentation etc. to this repository (a separate branch?)

Demo improvements

  • 1. One can conveniently add port constraints but cannot delete existing ones. Can we add support for that?
  • 2. Are nodes assumed to be allowed to rotate by default? In any case, I think we should provide a way for node rotations to be specified through the user interface.
  • 3. It is nice to be able to export and import back as .json file but the output is not human readable since there is no line break. Can we add line breaks to make them more readable? Let's also rename these buttons as "Import constraint from file" and "Export constraint to file".
  • 4. Add a new button for importing sample constraints (a set that can be used for testing)
  • 5. Let's put a legend at the end of the Port Info tab to define what each arrow head means.
  • 6. How about using color on arrows to separate sources and targets of edges? So if source (target) of an edge is side constrained for instance we use a fixed color for the source (target) arrow head. I am suggesting to color arrow heads independent from their edge line colors.
  • 7. Duration not updated for regular CoSE layout

Separate rotation and swap options

Currently, a single option controls whether or not nodes can be rotated or swapped during layout. However, one might allow rotations but not swaps. Let's separate these as two options.

Nodes not rotate around their centers

During the rotation operation, width and height values of a node are swapped here. However, since cose uses left-top point of a node as the node position, only swapping these values doesn't rotate the node around its center. After swapping these values, node position should be set to keep its previous center.

Random graph data for testing

We have Rome benchmark graphs which are simple biconnnected planar graphs but don't have any port information. If we can't find any benchmark graph set with port information, let's think about how to add ports to these graphs.

We also need some random compound graphs. We need to add ports to these as well.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.