mirror of
https://github.com/galaxyproject/galaxy.git
synced 2026-09-24 16:30:27 +08:00
Add chart plugins back to plugins directory of visualization framework
This commit is contained in:
@@ -1,24 +0,0 @@
|
||||
// NOTE: use 'sudo npm install .', then 'grunt' to use this file
|
||||
module.exports = function(grunt) {
|
||||
grunt.initConfig({
|
||||
pkg: grunt.file.readJSON('package.json'),
|
||||
requirejs: {
|
||||
compile: {
|
||||
options: {
|
||||
baseUrl : "../../../../static/scripts/",
|
||||
paths : {
|
||||
"plugin": "../../config/plugins/visualizations/charts/static"
|
||||
},
|
||||
shim : {
|
||||
"libs/underscore": { exports: "_" },
|
||||
"libs/backbone": { exports: "Backbone" }
|
||||
},
|
||||
name : "plugin/app",
|
||||
out : "static/build-app.js",
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
grunt.loadNpmTasks('grunt-contrib-requirejs');
|
||||
grunt.registerTask( 'default', [ 'requirejs' ]);
|
||||
};
|
||||
@@ -1,18 +1,41 @@
|
||||
{
|
||||
"name": "galaxy-charts",
|
||||
"version": "0.0.0",
|
||||
"description": "Charts visualization plugin for the Galaxy informatics framework",
|
||||
"main": " ",
|
||||
"name": "galaxy-charts-plugins",
|
||||
"version": "0.1.0",
|
||||
"description": "Charts visualization plugin.",
|
||||
"keywords": [
|
||||
"galaxy",
|
||||
"visualization",
|
||||
"d3"
|
||||
],
|
||||
"author": "Aysam Guerler",
|
||||
"license": "BSD",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/guerler/galaxy-charts"
|
||||
},
|
||||
"license": "AFL-3.0",
|
||||
"dependencies": {
|
||||
"amdi18n-loader": "^0.2.0",
|
||||
"grunt": "^0.4.5",
|
||||
"grunt-bower-install-simple": "^1.1.0",
|
||||
"grunt-check-modules": "^1.0.0",
|
||||
"grunt-cli": "^0.1.13",
|
||||
"grunt-contrib-clean": "^0.6.0",
|
||||
"grunt-contrib-copy": "^0.5.0",
|
||||
"grunt-contrib-less": "^1.1.0",
|
||||
"grunt-contrib-uglify": "^0.8.0",
|
||||
"grunt-contrib-watch": "^0.6.1",
|
||||
"grunt-exec": "^0.4.6",
|
||||
"grunt-spritesmith": "^4.7.1",
|
||||
"i18n-webpack-plugin": "^0.2.7",
|
||||
"webpack": "^1.10.1",
|
||||
"webpack-dev-server": "^1.7.0",
|
||||
"backbone": "^1.3.3",
|
||||
"bootstrap": "^3.3.7",
|
||||
"cytoscape": "^2.7.10",
|
||||
"jquery": "^3.1.1",
|
||||
"cytoscape-edgehandles": "^2.6.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"grunt": "~0.4.1",
|
||||
"grunt-cli": "~0.1.9",
|
||||
"grunt-contrib-requirejs": "~0.4.3"
|
||||
"css-loader": "^0.24.0",
|
||||
"style-loader": "^0.13.1"
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -31,7 +31,7 @@ define( [ 'mvc/ui/ui-modal', 'mvc/ui/ui-portlet', 'mvc/ui/ui-misc', 'utils/utils
|
||||
}, function( err ) {
|
||||
self.$el.append( $( '<div/>' ).addClass( 'errormessagelarge' )
|
||||
.append( $( '<p/>' ).text( 'Unable to access the plugin repository:' ) )
|
||||
.append( $( '<pre/>' ).text( 'charts_repository_url = ' + repository_root + 'package.json' ) )
|
||||
.append( $( '<pre/>' ).text( 'charts_repository_url = ' + repository_root ) )
|
||||
.append( $( '<p/>' ).html( 'Please verify that your internet connection works properly and that the above url is correct. Contact your admin if this error persists.' ) ) );
|
||||
});
|
||||
},
|
||||
+1
-1
@@ -14,7 +14,7 @@ define( [ 'utils/utils' ], function( Utils ) {
|
||||
},
|
||||
render: function() {
|
||||
if ( this.chart.get( 'type' ) ) {
|
||||
this.$image.attr( 'src', repository_root + 'src/visualizations/' + this.app.split( this.chart.get( 'type' ) ) + '/logo.png' );
|
||||
this.$image.attr( 'src', repository_root + '/visualizations/' + this.app.split( this.chart.get( 'type' ) ) + '/logo.png' );
|
||||
this.$title.html( this.chart.definition.title + ' (' + this.chart.definition.library + ')' );
|
||||
this.$text.html( Utils.linkify( this.chart.definition.description || '' ) );
|
||||
this.$el.show();
|
||||
+2
-2
@@ -33,7 +33,7 @@ define( [ 'utils/utils', 'mvc/ui/ui-misc', 'mvc/ui/ui-tabs' ], function( Utils,
|
||||
$el.append( $( self._templateThumbnailItem( {
|
||||
id : type_id,
|
||||
title : ( type.zoomable ? '<span class="fa fa-search-plus"/>' : '' ) + title + ' (' + type.library + ')',
|
||||
url : repository_root + 'src/visualizations/' + self.app.split( type_id ) + '/logo.png'
|
||||
url : repository_root + '/visualizations/' + self.app.split( type_id ) + '/logo.png'
|
||||
})).tooltip( { title: type.description, placement: 'bottom' } ) );
|
||||
}
|
||||
});
|
||||
@@ -50,7 +50,7 @@ define( [ 'utils/utils', 'mvc/ui/ui-misc', 'mvc/ui/ui-tabs' ], function( Utils,
|
||||
id : type_id,
|
||||
title : ( type.zoomable ? '<span class="fa fa-search-plus"/>' : '' ) + type.title + ' (' + type.library + ')',
|
||||
description : type.description || 'No description available.',
|
||||
url : repository_root + 'src/visualizations/' + self.app.split( type_id ) + '/logo.png'
|
||||
url : repository_root + '/visualizations/' + self.app.split( type_id ) + '/logo.png'
|
||||
});
|
||||
});
|
||||
if ( index.length > 0 ) {
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+10
File diff suppressed because one or more lines are too long
+1
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+1
File diff suppressed because one or more lines are too long
+8
File diff suppressed because one or more lines are too long
+1
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+8
File diff suppressed because one or more lines are too long
+1
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+1
File diff suppressed because one or more lines are too long
+8
File diff suppressed because one or more lines are too long
+1
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+1
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -0,0 +1 @@
|
||||
define( [], function() { return {nvd3_bar:require( "visualizations/nvd3/bar/config" ), nvd3_bar_horizontal:require( "visualizations/nvd3/bar_horizontal/config" ), nvd3_bar_horizontal_stacked:require( "visualizations/nvd3/bar_horizontal_stacked/config" ), nvd3_bar_stacked:require( "visualizations/nvd3/bar_stacked/config" ), nvd3_line:require( "visualizations/nvd3/line/config" ), nvd3_line_focus:require( "visualizations/nvd3/line_focus/config" ), nvd3_scatter:require( "visualizations/nvd3/scatter/config" ), nvd3_stackedarea:require( "visualizations/nvd3/stackedarea/config" ), nvd3_stackedarea_full:require( "visualizations/nvd3/stackedarea_full/config" ), nvd3_stackedarea_stream:require( "visualizations/nvd3/stackedarea_stream/config" ), nvd3_pie:require( "visualizations/nvd3/pie/config" ), nvd3_histogram:require( "visualizations/nvd3/histogram/config" ), nvd3_histogram_discrete:require( "visualizations/nvd3/histogram_discrete/config" ), jqplot_bar:require( "visualizations/jqplot/bar/config" ), jqplot_boxplot:require( "visualizations/jqplot/boxplot/config" ), jqplot_histogram_discrete:require( "visualizations/jqplot/histogram_discrete/config" ), jqplot_line:require( "visualizations/jqplot/line/config" ), jqplot_scatter:require( "visualizations/jqplot/scatter/config" ), biojs_msa:require( "visualizations/biojs/msa/config" ), biojs_drawrnajs:require( "visualizations/biojs/drawrnajs/config" ), others_example:require( "visualizations/others/example/config" ), others_heatmap:require( "visualizations/others/heatmap/config" ), others_heatmap_cluster:require( "visualizations/others/heatmap_cluster/config" ), cytoscape_basic:require( "visualizations/cytoscape/basic/config" ), pv_viewer:require( "visualizations/pv/viewer/config" ), benfred_venn:require( "visualizations/benfred/venn/config" ),} } );
|
||||
@@ -0,0 +1,14 @@
|
||||
.venntooltip {
|
||||
position: absolute;
|
||||
text-align: center;
|
||||
width: 128px;
|
||||
height: 22px;
|
||||
background: #333;
|
||||
color: #ddd;
|
||||
border: 0px;
|
||||
border-radius: 8px;
|
||||
opacity: 0;
|
||||
}
|
||||
.venn-area > .label {
|
||||
font-size: 1em;
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
+21
File diff suppressed because one or more lines are too long
+15
@@ -0,0 +1,15 @@
|
||||
var Backbone = require("backbone");
|
||||
var Structure = require("./models/structure");
|
||||
var Vispanel = require("./views/vispanel");
|
||||
|
||||
var Drawrnajs = Backbone.View.extend({
|
||||
initialize: function(opts){
|
||||
this.struct = new Structure(opts.seq, opts.dotbr, 'naview');
|
||||
this.vis = new Vispanel({ el: opts.el, struct: this.struct, resindex: opts.resindex });
|
||||
},
|
||||
render: function(){
|
||||
this.vis.render();
|
||||
}
|
||||
});
|
||||
|
||||
module.exports = Drawrnajs;
|
||||
+24
@@ -0,0 +1,24 @@
|
||||
var radiate = require("./radiate/getradiate");
|
||||
var naview = require("./naview/getnaview");
|
||||
|
||||
var Layout = function(layout, nodes, links){
|
||||
this.layout = layout;
|
||||
this.nodes = nodes;
|
||||
this.links = links;
|
||||
}
|
||||
|
||||
Layout.prototype.getCoords = function(){
|
||||
var coords = null;
|
||||
if(this.layout === "radiate"){
|
||||
coords = radiate(this.nodes, this.links);
|
||||
}
|
||||
else if(this.layout === "naview"){
|
||||
coords = naview(this.nodes, this.links);
|
||||
}
|
||||
else {
|
||||
throw new Error("Invalid layout");
|
||||
}
|
||||
return coords;
|
||||
}
|
||||
|
||||
module.exports = Layout;
|
||||
+49
@@ -0,0 +1,49 @@
|
||||
var Region = require("./region");
|
||||
|
||||
var Base = module.exports = function(){
|
||||
this.mate = null;
|
||||
this.x = null;
|
||||
this.y = null;
|
||||
this.extracted = null;
|
||||
this.region = new Region();
|
||||
}
|
||||
|
||||
Base.prototype.getMate = function(){
|
||||
return this.mate;
|
||||
}
|
||||
|
||||
Base.prototype.setMate = function(mate){
|
||||
this.mate = mate;
|
||||
}
|
||||
|
||||
Base.prototype.getX = function(){
|
||||
return this.x;
|
||||
}
|
||||
|
||||
Base.prototype.setX = function(x){
|
||||
this.x = x;
|
||||
}
|
||||
|
||||
Base.prototype.getY = function(){
|
||||
return this.y;
|
||||
}
|
||||
|
||||
Base.prototype.setY = function(y){
|
||||
this.y = y;
|
||||
}
|
||||
|
||||
Base.prototype.isExtracted = function(){
|
||||
return this.extracted;
|
||||
}
|
||||
|
||||
Base.prototype.setExtracted = function(extracted){
|
||||
this.extracted = extracted;
|
||||
}
|
||||
|
||||
Base.prototype.getRegion = function(){
|
||||
return this.region;
|
||||
}
|
||||
|
||||
Base.prototype.setRegion = function(region){
|
||||
this.region = region;
|
||||
}
|
||||
+100
@@ -0,0 +1,100 @@
|
||||
var Loop = require("./loop");
|
||||
var Region = require("./region");
|
||||
|
||||
var Connection = module.exports = function(){
|
||||
this.loop = new Loop();
|
||||
this.region = new Region();
|
||||
// Start and end form the 1st base pair of the region.
|
||||
this.start = null;
|
||||
this.end = null;
|
||||
this.xrad = null;
|
||||
this.yrad = null;
|
||||
this.angle = null;
|
||||
// True if segment between this connection and the
|
||||
// next must be extruded out of the circle
|
||||
this.extruded = null;
|
||||
// True if the extruded segment must be drawn long.
|
||||
this.broken = null;
|
||||
|
||||
this._isNull = false;
|
||||
}
|
||||
|
||||
Connection.prototype.isNull = function(){
|
||||
return this._isNull;
|
||||
}
|
||||
|
||||
Connection.prototype.setNull = function(isNull){
|
||||
this._isNull = isNull;
|
||||
}
|
||||
|
||||
Connection.prototype.getLoop = function(){
|
||||
return this.loop;
|
||||
}
|
||||
|
||||
Connection.prototype.setLoop = function(loop) {
|
||||
this.loop = loop;
|
||||
}
|
||||
|
||||
Connection.prototype.getRegion = function(){
|
||||
return this.region;
|
||||
}
|
||||
|
||||
Connection.prototype.setRegion = function(region){
|
||||
this.region = region;
|
||||
}
|
||||
|
||||
Connection.prototype.getStart = function(){
|
||||
return this.start;
|
||||
}
|
||||
|
||||
Connection.prototype.setStart = function(start) {
|
||||
this.start = start;
|
||||
}
|
||||
|
||||
Connection.prototype.getEnd = function(){
|
||||
return this.end;
|
||||
}
|
||||
|
||||
Connection.prototype.setEnd = function(end){
|
||||
this.end = end;
|
||||
}
|
||||
|
||||
Connection.prototype.getXrad = function(){
|
||||
return this.xrad;
|
||||
}
|
||||
|
||||
Connection.prototype.setXrad = function(xrad){
|
||||
this.xrad = xrad;
|
||||
}
|
||||
|
||||
Connection.prototype.getYrad = function(){
|
||||
return this.yrad;
|
||||
}
|
||||
|
||||
Connection.prototype.setYrad = function(yrad) {
|
||||
this.yrad = yrad;
|
||||
}
|
||||
|
||||
Connection.prototype.getAngle = function(){
|
||||
return this.angle;
|
||||
}
|
||||
|
||||
Connection.prototype.setAngle = function(angle){
|
||||
this.angle = angle;
|
||||
}
|
||||
|
||||
Connection.prototype.isExtruded = function(){
|
||||
return this.extruded;
|
||||
}
|
||||
|
||||
Connection.prototype.setExtruded = function(extruded){
|
||||
this.extruded = extruded;
|
||||
}
|
||||
|
||||
Connection.prototype.isBroken = function(){
|
||||
return this.broken;
|
||||
}
|
||||
|
||||
Connection.prototype.setBroken = function(broken){
|
||||
this.broken = broken;
|
||||
}
|
||||
+44
@@ -0,0 +1,44 @@
|
||||
var NAView = require("./naview");
|
||||
|
||||
getCoordsNAVIEW = module.exports = function(nodes, links){
|
||||
//Calculates coordinates according to the NAView layout
|
||||
var pairTable = [];
|
||||
|
||||
for(var i=0; i<nodes.length; i++){
|
||||
pairTable.push(getPartner(i, links));
|
||||
}
|
||||
var naView = new NAView();
|
||||
var xy = naView.naview_xy_coordinates(pairTable);
|
||||
|
||||
// Updating individual base positions
|
||||
var coords = []
|
||||
for (var i = 0; i < nodes.length; i++) {
|
||||
coords.push({
|
||||
x: Math.round(xy.x[i] * 2.5),
|
||||
y: Math.round(xy.y[i] * 2.5)
|
||||
});
|
||||
}
|
||||
return coords;
|
||||
}
|
||||
|
||||
function getPartner(srcIndex, links){
|
||||
//Returns the partner of a nucleotide:
|
||||
//-1 means there is no partner
|
||||
var partner = -1;
|
||||
for(var i = 0; i < links.length; i++){
|
||||
if(links[i].type !== "phosphodiester" && links[i].type !== "index"){
|
||||
if(links[i].source === srcIndex){
|
||||
partner = links[i].target;
|
||||
break;
|
||||
}
|
||||
else if(links[i].target === srcIndex){
|
||||
partner = links[i].source;
|
||||
break;
|
||||
}
|
||||
else {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
return partner;
|
||||
}
|
||||
+98
@@ -0,0 +1,98 @@
|
||||
var Loop = module.exports = function(){
|
||||
this.nconnection = null;
|
||||
this.connections = [];
|
||||
this._connections = [];
|
||||
this.number = null;
|
||||
this.depth = null;
|
||||
this.mark = null;
|
||||
this.x = null;
|
||||
this.y = null;
|
||||
this.radius = null;
|
||||
}
|
||||
|
||||
Loop.prototype.getNconnection = function() {
|
||||
return this.nconnection;
|
||||
}
|
||||
|
||||
Loop.prototype.setNconnection = function(nconnection) {
|
||||
this.nconnection = nconnection;
|
||||
}
|
||||
|
||||
Loop.prototype.setConnection = function(i, c){
|
||||
var Connection = require("./connection");
|
||||
if (c != null){
|
||||
this._connections[i] = c;
|
||||
}
|
||||
else {
|
||||
if (!this._connections[i]){
|
||||
this._connections[i] = new Connection();
|
||||
}
|
||||
this._connections[i].setNull(true);
|
||||
}
|
||||
}
|
||||
|
||||
Loop.prototype.getConnection = function(i){
|
||||
var Connection = require("./connection");
|
||||
if (!this._connections[i]){
|
||||
this._connections[i] = new Connection();
|
||||
}
|
||||
var c = this._connections[i];
|
||||
if (c.isNull()){
|
||||
return null;
|
||||
}
|
||||
else {
|
||||
return c;
|
||||
}
|
||||
}
|
||||
|
||||
Loop.prototype.addConnection = function(i, c){
|
||||
this._connections.push(c);
|
||||
}
|
||||
|
||||
Loop.prototype.getNumber = function(){
|
||||
return this.number;
|
||||
}
|
||||
|
||||
Loop.prototype.setNumber = function(number){
|
||||
this.number = number;
|
||||
}
|
||||
|
||||
Loop.prototype.getDepth = function(){
|
||||
return this.depth;
|
||||
}
|
||||
|
||||
Loop.prototype.setDepth = function(depth){
|
||||
this.depth = depth;
|
||||
}
|
||||
|
||||
Loop.prototype.isMark = function(){
|
||||
return this.mark;
|
||||
}
|
||||
|
||||
Loop.prototype.setMark = function(mark){
|
||||
this.mark = mark;
|
||||
}
|
||||
|
||||
Loop.prototype.getX = function(){
|
||||
return this.x;
|
||||
}
|
||||
|
||||
Loop.prototype.setX = function(x){
|
||||
this.x = x;
|
||||
}
|
||||
|
||||
Loop.prototype.getY = function(){
|
||||
return this.y;
|
||||
}
|
||||
|
||||
Loop.prototype.setY = function(y){
|
||||
this.y = y;
|
||||
}
|
||||
|
||||
Loop.prototype.getRadius = function(){
|
||||
return this.radius;
|
||||
}
|
||||
|
||||
Loop.prototype.setRadius = function(radius){
|
||||
this.radius = radius;
|
||||
}
|
||||
+1098
File diff suppressed because it is too large
Load Diff
+38
@@ -0,0 +1,38 @@
|
||||
var Radloop = module.exports = function(){
|
||||
this.radius = null;
|
||||
this.loopnumber = null;
|
||||
this.next = null;
|
||||
this.prev = null;
|
||||
}
|
||||
|
||||
Radloop.prototype.getRadius = function(){
|
||||
return this.radius;
|
||||
}
|
||||
|
||||
Radloop.prototype.setRadius = function(radius){
|
||||
this.radius = radius;
|
||||
}
|
||||
|
||||
Radloop.prototype.getLoopnumber = function(){
|
||||
return this.loopnumber;
|
||||
}
|
||||
|
||||
Radloop.prototype.setLoopnumber = function(loopnumber){
|
||||
this.loopnumber = loopnumber;
|
||||
}
|
||||
|
||||
Radloop.prototype.getNext = function(){
|
||||
return this.next;
|
||||
}
|
||||
|
||||
Radloop.prototype.setNext = function(next){
|
||||
this.next = next;
|
||||
}
|
||||
|
||||
Radloop.prototype.getPrev = function(){
|
||||
return this.prev;
|
||||
}
|
||||
|
||||
Radloop.prototype.setPrev = function(prev){
|
||||
this.prev = prev;
|
||||
}
|
||||
+38
@@ -0,0 +1,38 @@
|
||||
var Region = module.exports = function(){
|
||||
this._start1 = null;
|
||||
this._end1 = null;
|
||||
this._start2 = null;
|
||||
this._end2 = null;
|
||||
}
|
||||
|
||||
Region.prototype.getStart1 = function(){
|
||||
return this._start1;
|
||||
}
|
||||
|
||||
Region.prototype.setStart1 = function(start1){
|
||||
this._start1 = start1;
|
||||
}
|
||||
|
||||
Region.prototype.getEnd1 = function(){
|
||||
return this._end1;
|
||||
}
|
||||
|
||||
Region.prototype.setEnd1 = function(end1){
|
||||
this._end1 = end1;
|
||||
}
|
||||
|
||||
Region.prototype.getStart2 = function(){
|
||||
return this._start2;
|
||||
}
|
||||
|
||||
Region.prototype.setStart2 = function(start2){
|
||||
this._start2 = start2;
|
||||
}
|
||||
|
||||
Region.prototype.getEnd2 = function(){
|
||||
return this._end2;
|
||||
}
|
||||
|
||||
Region.prototype.setEnd2 = function(end2){
|
||||
this._end2 = end2;
|
||||
}
|
||||
+271
@@ -0,0 +1,271 @@
|
||||
var calculateCoords = module.exports = function(seq, dotbr, links){
|
||||
//This function calculates the coordinates for each nucleotide
|
||||
//according to the radiate layout
|
||||
var coords = [];
|
||||
var centers = [];
|
||||
var angles = [];
|
||||
var dirAngle = -1;
|
||||
|
||||
for(var i = 0; i < seq.length; i++){
|
||||
coords[i] = {x: 0, y: 0};
|
||||
centers[i] = {x: 0, y: 0};
|
||||
}
|
||||
|
||||
if(2>1){
|
||||
dirAngle += 1.0 - Math.PI / 2.0;
|
||||
var i = 0;
|
||||
var x = 0.0;
|
||||
var y = 0.0;
|
||||
var vx = -Math.sin(dirAngle);
|
||||
var vy = Math.cos(dirAngle);
|
||||
|
||||
while(i < seq.length){
|
||||
coords[i].x = x;
|
||||
coords[i].y = y;
|
||||
centers[i].x = x + 65 * vy;
|
||||
centers[i].y = y - 65 * vx;
|
||||
var j = getPartner(i, links);
|
||||
|
||||
if(j > i){
|
||||
drawLoop(i, j, x + (65 * vx / 2.0), y
|
||||
+ (65 * vy / 2.0), dirAngle,
|
||||
coords, centers, angles, seq, links);
|
||||
centers[i].x = coords[i].x + 65 * vy;
|
||||
centers[i].y = y - 65 * vx;
|
||||
i = j;
|
||||
x += 65 * vx;
|
||||
y += 65 * vy;
|
||||
centers[i].x = coords[i].x + 65 * vy;
|
||||
centers[i].y = y - 65 * vx;
|
||||
}
|
||||
x += 35 * vx;
|
||||
y += 35 * vy;
|
||||
i += 1;
|
||||
}
|
||||
}
|
||||
else{
|
||||
drawLoop(0, seq.length-1, 0, 0, dirAngle, coords, centers, angles, seq, links);
|
||||
}
|
||||
return coords;
|
||||
}
|
||||
|
||||
function getPartner(srcIndex, links){
|
||||
//Returns the partner of a nucleotide:
|
||||
//-1 means there is no partner
|
||||
var partner = -1;
|
||||
for(var i = 0; i < links.length; i++){
|
||||
if(links[i].type != "phosphodiester"){
|
||||
if(links[i].source === srcIndex){
|
||||
partner = links[i].target;
|
||||
break;
|
||||
}
|
||||
else if(links[i].target === srcIndex){
|
||||
partner = links[i].source;
|
||||
break;
|
||||
}
|
||||
else {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
return partner;
|
||||
}
|
||||
|
||||
function drawLoop(i, j, x, y, dirAngle, coords, centers, angles, seq, links){
|
||||
//Calculates loop coordinates
|
||||
if (i > j) {
|
||||
return;
|
||||
}
|
||||
|
||||
// BasePaired
|
||||
if (getPartner(i, links) === j) {
|
||||
var normalAngle = Math.PI / 2.0;
|
||||
centers[i] = {x: x, y: y};
|
||||
centers[j] = {x: x, y: y};
|
||||
coords[i].x = (x + 65 * Math.cos(dirAngle - normalAngle) / 2.0);
|
||||
coords[i].y = (y + 65 * Math.sin(dirAngle - normalAngle) / 2.0);
|
||||
coords[j].x = (x + 65 * Math.cos(dirAngle + normalAngle) / 2.0);
|
||||
coords[j].y = (y + 65 * Math.sin(dirAngle + normalAngle) / 2.0);
|
||||
drawLoop(i + 1, j - 1, x + 40 * Math.cos(dirAngle), y + 40 * Math.sin(dirAngle), dirAngle, coords,
|
||||
centers, angles, seq, links);
|
||||
}
|
||||
else {
|
||||
//multi loop now
|
||||
var k = i;
|
||||
var basesMultiLoop = [];
|
||||
var helices = [];
|
||||
var l;
|
||||
while (k <= j) {
|
||||
l = getPartner(k, links);
|
||||
if (l > k) {
|
||||
basesMultiLoop.push(k);
|
||||
basesMultiLoop.push(l);
|
||||
helices.push(k);
|
||||
k = l + 1;
|
||||
}
|
||||
else {
|
||||
basesMultiLoop.push(k);
|
||||
k++;
|
||||
}
|
||||
}
|
||||
var mlSize = basesMultiLoop.length + 2;
|
||||
var numHelices = helices.length + 1;
|
||||
var totalLength = 35 * (mlSize - numHelices) + 65 * numHelices;
|
||||
var multiLoopRadius;
|
||||
var angleIncrementML;
|
||||
var angleIncrementBP;
|
||||
if (mlSize > 3) {
|
||||
multiLoopRadius = determineRadius(numHelices, mlSize - numHelices, (totalLength) / (2.0 * Math.PI), 65, 35);
|
||||
angleIncrementML = -2.0 * Math.asin(35 / (2.0 * multiLoopRadius));
|
||||
angleIncrementBP = -2.0 * Math.asin(65 / (2.0 * multiLoopRadius));
|
||||
}
|
||||
else {
|
||||
multiLoopRadius = 35.0;
|
||||
angleIncrementBP = -2.0 * Math.asin(65 / (2.0 * multiLoopRadius));
|
||||
angleIncrementML = (-2.0 * Math.PI - angleIncrementBP) / 2.0;
|
||||
}
|
||||
var centerDist = Math.sqrt(Math.max(Math.pow(multiLoopRadius, 2) - Math.pow(65 / 2.0, 2), 0.0)) - 40;
|
||||
var mlCenter = {x: x + (centerDist * Math.cos(dirAngle)),
|
||||
y: y + (centerDist * Math.sin(dirAngle))}
|
||||
// Base directing angle for (multi|hairpin) loop, from the center's
|
||||
// perspective
|
||||
var baseAngle = dirAngle
|
||||
// U-turn
|
||||
+ Math.PI
|
||||
// Account for already drawn supporting base-pair
|
||||
+ 0.5 * angleIncrementBP
|
||||
// Base cannot be paired twice, so next base is at
|
||||
// "unpaired base distance"
|
||||
+ 1.0 * angleIncrementML;
|
||||
|
||||
var currUnpaired = [];
|
||||
var currInterval = {el1: 0, el2: baseAngle-1.0 * angleIncrementML};
|
||||
var intervals = [];
|
||||
|
||||
for (k = basesMultiLoop.length - 1; k >= 0; k--) {
|
||||
l = basesMultiLoop[k];
|
||||
centers[l] = mlCenter;
|
||||
var isPaired = (getPartner(i, links) != -1);
|
||||
var isPaired3 = isPaired && (getPartner(i, links) < l);
|
||||
var isPaired5 = isPaired && !isPaired3;
|
||||
if (isPaired3) {
|
||||
baseAngle = correctHysteresis(baseAngle+angleIncrementBP/2.)-angleIncrementBP/2.;
|
||||
currInterval.el1 = baseAngle;
|
||||
intervals.push({el1: currUnpaired, el2: currInterval });
|
||||
currInterval = { el1: -1.0, el2: -1.0 };
|
||||
currUnpaired = [];
|
||||
}
|
||||
else if (isPaired5)
|
||||
{
|
||||
currInterval.el2 = baseAngle;
|
||||
}
|
||||
else
|
||||
{
|
||||
currUnpaired.push(l);
|
||||
}
|
||||
angles[l] = baseAngle;
|
||||
if (isPaired3)
|
||||
{
|
||||
baseAngle += angleIncrementBP;
|
||||
}
|
||||
else {
|
||||
baseAngle += angleIncrementML;
|
||||
}
|
||||
}
|
||||
currInterval.el1 = dirAngle - Math.PI - 0.5 * angleIncrementBP;
|
||||
intervals.push( {el1: currUnpaired, el2: currInterval } );
|
||||
|
||||
for(var z = 0; z < intervals.length; z++){
|
||||
var mina = intervals[z].el2.el1;
|
||||
var maxa = normalizeAngle(intervals[z].el2.el2, mina);
|
||||
|
||||
for (var n = 0; n < intervals[z].el1.length; n++){
|
||||
var ratio = (1. + n)/(1. + intervals[z].el1.length);
|
||||
var b = intervals[z].el1[n];
|
||||
angles[b] = mina + (1.-ratio)*(maxa-mina);
|
||||
}
|
||||
}
|
||||
|
||||
for (k = basesMultiLoop.length - 1; k >= 0; k--) {
|
||||
l = basesMultiLoop[k];
|
||||
coords[l].x = mlCenter.x + multiLoopRadius * Math.cos(angles[l]);
|
||||
coords[l].y = mlCenter.y + multiLoopRadius * Math.sin(angles[l]);
|
||||
}
|
||||
|
||||
var newAngle;
|
||||
var m, n;
|
||||
for (k = 0; k < helices.length; k++) {
|
||||
m = helices[k];
|
||||
n = getPartner(m, links);
|
||||
newAngle = (angles[m] + angles[n]) / 2.0;
|
||||
drawLoop(m + 1, n - 1, (40 * Math.cos(newAngle)) + (coords[m].x + coords[n].x) / 2.0,
|
||||
(40 * Math.sin(newAngle))
|
||||
+ (coords[m].y + coords[n].y) / 2.0, newAngle,
|
||||
coords, centers, angles, seq, links);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function determineRadius(nbHel, nbUnpaired, startRadius, bpdist, multidist) {
|
||||
var xmin = bpdist / 2.0;
|
||||
var xmax = 3.0 * multidist + 1;
|
||||
var x = (xmin + xmax) / 2.0;
|
||||
var y = 10000.0;
|
||||
var ymin = -1000.0;
|
||||
var ymax = 1000.0;
|
||||
var numIt = 0;
|
||||
var precision = 0.00001;
|
||||
while ((Math.abs(y) > precision) && (numIt < 10000)) {
|
||||
x = (xmin + xmax) / 2.0;
|
||||
y = objFun(nbHel, nbUnpaired, x, bpdist, multidist);
|
||||
ymin = objFun(nbHel, nbUnpaired, xmax, bpdist, multidist);
|
||||
ymax = objFun(nbHel, nbUnpaired, xmin, bpdist, multidist);
|
||||
if (ymin > 0.0) {
|
||||
xmax = xmax + (xmax - xmin);
|
||||
} else if ((y <= 0.0) && (ymax > 0.0)) {
|
||||
xmax = x;
|
||||
} else if ((y >= 0.0) && (ymin < 0.0)) {
|
||||
xmin = x;
|
||||
} else if (ymax < 0.0) {
|
||||
xmin = Math.max(xmin - (x - xmin),
|
||||
Math.max(bpdist / 2.0, multidist / 2.0));
|
||||
xmax = x;
|
||||
}
|
||||
numIt++;
|
||||
}
|
||||
return x;
|
||||
}
|
||||
|
||||
function objFun(n1, n2, r, bpdist, multidist) {
|
||||
return ( n1 * 2.0 * Math.asin(bpdist / (2.0 * r)) + n2 * 2.0
|
||||
* Math.asin( multidist / (2.0 * r)) - (2.0 * Math.PI));
|
||||
}
|
||||
|
||||
function correctHysteresis(angle){
|
||||
var hystAttr = [ 0.0, Math.PI/4.0, Math.PI/2.0, 3.0*Math.PI/4.0, Math.PI, 5.0*(Math.PI)/4.0, 3.0*(Math.PI)/2.0, 7.0*(Math.PI)/4.0];
|
||||
var result = normalizeAngleSec(angle);
|
||||
for (var i = 0; i < hystAttr.length; i++){
|
||||
var att = hystAttr[i];
|
||||
if (Math.abs(t.normalizeAngle(att-result,-Math.PI)) < 0.15){
|
||||
result = att;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
function normalizeAngleSec(angle){
|
||||
return t.normalizeAngle(angle,0.0);
|
||||
}
|
||||
|
||||
function normalizeAngle(angle,fromVal) {
|
||||
var toVal = fromVal +2.0*Math.PI;
|
||||
var result = angle;
|
||||
while(result<fromVal){
|
||||
result += 2.0*Math.PI;
|
||||
}
|
||||
while(result >= toVal)
|
||||
{
|
||||
result -= 2.0*Math.PI;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
+17
@@ -0,0 +1,17 @@
|
||||
var Backbone = require("backbone");
|
||||
|
||||
var Link = Backbone.Model.extend({
|
||||
defaults: {
|
||||
group: "edges"
|
||||
},
|
||||
initialize: function(data){
|
||||
this.set("id", data.id);
|
||||
this.set("source", data.source);
|
||||
this.set("target", data.target);
|
||||
this.set("label", data.label);
|
||||
this.set("weight", data.weight);
|
||||
this.set("color", data.color);
|
||||
}
|
||||
})
|
||||
|
||||
module.exports = Link;
|
||||
+28
@@ -0,0 +1,28 @@
|
||||
var Backbone = require("backbone");
|
||||
var Link = require("./link");
|
||||
var pdbr = require("../utils/parsedbr");
|
||||
|
||||
var LinkCol = Backbone.Collection.extend({
|
||||
model: Link,
|
||||
initialize: function(model, stl, residues){
|
||||
this.style = stl;
|
||||
this.residues = residues;
|
||||
},
|
||||
newBond: function(src, target){
|
||||
var res1 = this.residues.at(parseInt(src));
|
||||
var res2 = this.residues.at(parseInt(target));
|
||||
var type = pdbr.getType(pdbr.isWatsonCrick(res1, res2));
|
||||
var style = this.style;
|
||||
|
||||
this.add(new Link({
|
||||
id: src + "to" + target,
|
||||
source: src,
|
||||
target: target,
|
||||
label: type,
|
||||
weight: style.getWeight(type),
|
||||
color: style.getColor(type)
|
||||
}));
|
||||
}
|
||||
});
|
||||
|
||||
module.exports = LinkCol;
|
||||
+36
@@ -0,0 +1,36 @@
|
||||
var Backbone = require("backbone");
|
||||
|
||||
var Anno = Backbone.Model.extend({
|
||||
defaults: {
|
||||
base1: "wc",
|
||||
base2: "wc",
|
||||
stericity: "cis",
|
||||
edge: null
|
||||
},
|
||||
initialize: function(b1, b2, st, edge){
|
||||
this.set("base1", b1);
|
||||
this.set("base2", b2);
|
||||
this.set("edge", edge);
|
||||
this.set("stericity", st);
|
||||
},
|
||||
getLabels: function(){
|
||||
var labels = [];
|
||||
for(var i=1; i<3; i++){
|
||||
switch(this.get("base" + i)){
|
||||
case "wc":
|
||||
labels.push("Watson-Crick");
|
||||
break;
|
||||
case "hg":
|
||||
labels.push("Hoogsteen");
|
||||
break;
|
||||
case "sg":
|
||||
labels.push("Sugar");
|
||||
break;
|
||||
}
|
||||
}
|
||||
labels.push(this.get("stericity"));
|
||||
return labels;
|
||||
}
|
||||
})
|
||||
|
||||
module.exports = Anno;
|
||||
+19
@@ -0,0 +1,19 @@
|
||||
var Backbone = require("backbone");
|
||||
|
||||
var Residue = Backbone.Model.extend({
|
||||
defaults: {
|
||||
group: "nodes",
|
||||
selectable: true,
|
||||
locked: false,
|
||||
grabbable: true
|
||||
},
|
||||
initialize: function(data){
|
||||
this.set("name", data.name);
|
||||
this.set("color", data.color);
|
||||
this.set("x", data.x);
|
||||
this.set("y", data.y);
|
||||
this.set("id", data.id);
|
||||
}
|
||||
})
|
||||
|
||||
module.exports = Residue;
|
||||
+21
@@ -0,0 +1,21 @@
|
||||
var Backbone = require("backbone");
|
||||
var Residue = require("./residue");
|
||||
var _ = require("underscore");
|
||||
|
||||
var ResidueCol = Backbone.Collection.extend({
|
||||
model: Residue,
|
||||
setResidueColor: function(group, color){
|
||||
_.each(this.where({name: group}),
|
||||
function(el){ el.set("color", color); });
|
||||
},
|
||||
setSelectionColor: function(group, color){
|
||||
var el = null;
|
||||
|
||||
for(var i=0; i<group.length; i++){
|
||||
el = group[i];
|
||||
this.where({id: el.id()})[0].set("color", color);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
module.exports = ResidueCol;
|
||||
+158
@@ -0,0 +1,158 @@
|
||||
var Backbone = require("backbone");
|
||||
var parseStruct = require("../utils/parsedbr");
|
||||
var Layout = require("../layouts/layout.js");
|
||||
var Style = require("../utils/style");
|
||||
var Link = require("./link");
|
||||
var LinkCol = require("./linkcol");
|
||||
var Residue = require("./residue");
|
||||
var ResidueCol = require("./residuecol");
|
||||
|
||||
var Structure = Backbone.Model.extend({
|
||||
initialize: function(seq, dotbr, layout){
|
||||
this.set("seq", seq);
|
||||
this.set("dotbr", dotbr);
|
||||
this.set("layout", layout);
|
||||
this.set("style", new Style("standard"));
|
||||
this.set("renderSwitch", true);
|
||||
this.defineStructure();
|
||||
//event listening
|
||||
this.on("change:renderSwitch", this.defineStructure);
|
||||
},
|
||||
reconstruct: function(){
|
||||
//This function is used to update String/Dot-Bracket Notation
|
||||
//after a hbond was inserted
|
||||
var seq = "";
|
||||
var dotbr = [];
|
||||
var partner;
|
||||
var res = this.get("residues");
|
||||
|
||||
for(var i=0; i<res.length; i++){
|
||||
seq += res.at(i).get("name");
|
||||
partner = this.getPartner(i.toString());
|
||||
if(partner === -1){
|
||||
dotbr[i] = ".";
|
||||
}
|
||||
else if(partner > i){
|
||||
dotbr[i] = "(";
|
||||
dotbr[partner] = ")";
|
||||
}
|
||||
else {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
this.set("seq", seq);
|
||||
this.set("dotbr", dotbr.join(""));
|
||||
this.set("renderSwitch", !this.get("renderSwitch"));
|
||||
},
|
||||
defineStructure: function(){
|
||||
var seq = this.get("seq"),
|
||||
dotbr = this.get("dotbr"),
|
||||
layout = this.get("layout"),
|
||||
style = this.get("style");
|
||||
|
||||
//set residues
|
||||
var resCol = new ResidueCol();
|
||||
var graph = parseStruct.parseDbr(seq, dotbr);
|
||||
var coords = new Layout(layout, graph.nodes, graph.links).getCoords();
|
||||
for(var i=0; i<graph.nodes.length; i++){
|
||||
resCol.add(new Residue({
|
||||
name: graph.nodes[i].name,
|
||||
color: style.getColor(graph.nodes[i].name),
|
||||
x: coords[i].x,
|
||||
y: coords[i].y,
|
||||
id: i.toString()
|
||||
}));
|
||||
}
|
||||
this.set("residues", resCol);
|
||||
|
||||
//set bonds
|
||||
var linkCol = new LinkCol(null, style, resCol);
|
||||
for(var i=0; i<graph.links.length; i++){
|
||||
linkCol.add(new Link({
|
||||
id: graph.links[i].source + "to" + graph.links[i].target,
|
||||
source: graph.links[i].source.toString(),
|
||||
target: graph.links[i].target.toString(),
|
||||
label: graph.links[i].type,
|
||||
weight: style.getWeight(graph.links[i].type),
|
||||
color: style.getColor(graph.links[i].type)
|
||||
}));
|
||||
}
|
||||
this.set("links", linkCol);
|
||||
this.listenTo(this.get("links"), "update", this.reconstruct);
|
||||
},
|
||||
toCytoscape: function(){
|
||||
//Create a JSON structure from a graph object built by the
|
||||
//transformDotBracket function
|
||||
//The JSON structure fits the requirements of CytoscapeJS
|
||||
var elements = [];
|
||||
var el;
|
||||
|
||||
var nodes = this.get("residues");
|
||||
for(var i = 0; i < nodes.length; i++){
|
||||
el = nodes.at(i);
|
||||
elements.push({
|
||||
group: el.get("group"),
|
||||
data: {
|
||||
id: el.get("id"),
|
||||
label: el.get("name"),
|
||||
type: "residue"
|
||||
},
|
||||
position: {
|
||||
x: el.get("x"),
|
||||
y: el.get("y")
|
||||
},
|
||||
selected: el.get("selected"),
|
||||
selectable: el.get("selectable"),
|
||||
locked: el.get("locked"),
|
||||
grabbable: el.get("grabbable"),
|
||||
css: {
|
||||
'background-color': el.get("color")
|
||||
}
|
||||
});
|
||||
}
|
||||
var links = this.get("links");
|
||||
for(var i = 0; i < links.length; i++){
|
||||
el = links.at(i);
|
||||
elements.push({
|
||||
group: el.get("group"),
|
||||
data: {
|
||||
id: el.get("id"),
|
||||
source: el.get("source"),
|
||||
target: el.get("target"),
|
||||
label: el.get("label"),
|
||||
weight: el.get("weight")
|
||||
},
|
||||
css: {
|
||||
'line-color': el.get("color"),
|
||||
'width': el.get("weight")
|
||||
}
|
||||
});
|
||||
}
|
||||
return elements;
|
||||
},
|
||||
getPartner: function(srcIndex){
|
||||
//Returns the partner of a nucleotide:
|
||||
//-1 means there is no partner
|
||||
var links = this.get("links");
|
||||
var partner = -1;
|
||||
|
||||
for(var i=0; i<links.length; i++){
|
||||
if(links.at(i).get("label") !== "phosphodiester"){
|
||||
if(links.at(i).get("source") === srcIndex){
|
||||
partner = links.at(i).get("target");
|
||||
break;
|
||||
}
|
||||
else if(links.at(i).get("target") === srcIndex){
|
||||
partner = links.at(i).get("source");
|
||||
break;
|
||||
}
|
||||
else {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
return partner;
|
||||
}
|
||||
});
|
||||
|
||||
module.exports = Structure;
|
||||
+34
@@ -0,0 +1,34 @@
|
||||
var setupLasso = module.exports = function($){
|
||||
//Lasso Functionality
|
||||
var $ = require( 'jquery' );
|
||||
$.fn.extend({
|
||||
lasso: function () {
|
||||
this.mousedown(function (e) {
|
||||
// left mouse down switches on "capturing mode"
|
||||
if (e.which === 1 && !$(this).is(".lassoRunning")) {
|
||||
$(this).addClass("lassoRunning");
|
||||
$(this).data("lassoPoints", []);
|
||||
$(this).trigger("lassoBegin");
|
||||
}
|
||||
});
|
||||
this.mouseup(function (e) {
|
||||
// left mouse up ends "capturing mode" + triggers "Done" event
|
||||
if (e.which === 1 && $(this).is(".lassoRunning")) {
|
||||
$(this).removeClass("lassoRunning");
|
||||
$(this).trigger("lassoDone", [$(this).data("lassoPoints")]);
|
||||
}
|
||||
});
|
||||
this.mousemove(function (e) {
|
||||
// mouse move captures co-ordinates + triggers "Point" event
|
||||
if ($(this).is(".lassoRunning")) {
|
||||
var px = (e.offsetX || e.clientX - $(e.target).offset().left + window.pageXOffset);
|
||||
var py = (e.offsetY || e.clientY - $(e.target).offset().top + window.pageYOffset);
|
||||
var point = [px, py];
|
||||
$(this).data("lassoPoints").push(point);
|
||||
$(this).trigger("lassoPoint", [point]);
|
||||
}
|
||||
});
|
||||
return this;
|
||||
}
|
||||
});
|
||||
}
|
||||
+58
@@ -0,0 +1,58 @@
|
||||
var exp = {};
|
||||
|
||||
exp.parseDbr = function(seq, dotbr){
|
||||
var round = [],
|
||||
nodes = [],
|
||||
links = [];
|
||||
|
||||
var src, type;
|
||||
//Indices corresponding to opening brackets are pushed onto a stack
|
||||
//and are popped when a closing bracket is read.
|
||||
//Links (hbonds, phosphodiester bonds) are created as needed.
|
||||
for(var i = 0; i < seq.length; i++){
|
||||
nodes.push({name: seq[i].toUpperCase()});
|
||||
if(i > 0){
|
||||
links.push({source: i-1, target: i, type: "phosphodiester"});
|
||||
}
|
||||
switch(dotbr[i]){
|
||||
case "(":
|
||||
round.push(i);
|
||||
break;
|
||||
case ")":
|
||||
src = round.pop();
|
||||
type = exp.getType(exp.isWatsonCrick(seq[src], seq[i]));
|
||||
links.push({source: src, target: i, type: type});
|
||||
break;
|
||||
case ".":
|
||||
break;
|
||||
}
|
||||
}
|
||||
//Return graph in object format
|
||||
return {
|
||||
nodes: nodes,
|
||||
links: links
|
||||
};
|
||||
}
|
||||
|
||||
exp.isWatsonCrick = function(nucOne, nucTwo){
|
||||
var watsonCrick = false;
|
||||
if(nucOne === "G" && nucTwo === "C" ||
|
||||
nucOne === "C" && nucTwo === "G" ||
|
||||
nucOne === "A" && nucTwo === "U" ||
|
||||
nucOne === "U" && nucTwo === "A" ||
|
||||
nucOne === "A" && nucTwo === "T" ||
|
||||
nucOne === "T" && nucTwo === "A") {
|
||||
watsonCrick = true;
|
||||
}
|
||||
return watsonCrick;
|
||||
}
|
||||
|
||||
exp.getType = function(watsonCrick){
|
||||
if(watsonCrick){
|
||||
return "hbond";
|
||||
} else {
|
||||
return "violation";
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = exp;
|
||||
+2287
File diff suppressed because it is too large
Load Diff
+235
@@ -0,0 +1,235 @@
|
||||
var $ = jQuery = require("jquery");
|
||||
var cytoscape = require("cytoscape");
|
||||
|
||||
var Style = module.exports = function(theme){
|
||||
this.theme = theme;
|
||||
}
|
||||
|
||||
Style.prototype.getColor = function(element){
|
||||
//Get color for a certain nucleotide as specified by the color
|
||||
//picker in the options column of the page.
|
||||
var col = "black";
|
||||
if($("#acolor").length > 0){
|
||||
if (element === "A"){
|
||||
col = $("#acolor").spectrum('get').toHexString();
|
||||
}
|
||||
else if (element === "C"){
|
||||
col = $("#ccolor").spectrum('get').toHexString();
|
||||
}
|
||||
else if (element === "U"){
|
||||
col = $("#ucolor").spectrum('get').toHexString();
|
||||
}
|
||||
else if (element === "G"){
|
||||
col = $("#gcolor").spectrum('get').toHexString();
|
||||
}
|
||||
else if (element === "hbond"){
|
||||
col = "#3A9AD9";
|
||||
}
|
||||
else if(element === "violation") {
|
||||
col = "red";
|
||||
}
|
||||
} else {
|
||||
if (element === "A"){
|
||||
col = "#64F73F";
|
||||
}
|
||||
else if (element === "C"){
|
||||
col = "#FFB340";
|
||||
}
|
||||
else if (element === "U"){
|
||||
col = "#3C88EE";
|
||||
}
|
||||
else if (element === "G"){
|
||||
col = "#EB413C";
|
||||
}
|
||||
else if (element === "hbond"){
|
||||
col = "#3A9AD9";
|
||||
}
|
||||
else if(element === "violation") {
|
||||
col = "red";
|
||||
}
|
||||
}
|
||||
return col;
|
||||
}
|
||||
|
||||
Style.prototype.getWeight = function(type){
|
||||
//Get weight for a certain bond type
|
||||
var weight;
|
||||
if(type=== "hbond" || type === "violation"){
|
||||
weight = 4;
|
||||
} else {
|
||||
weight = 5;
|
||||
}
|
||||
return weight;
|
||||
}
|
||||
|
||||
Style.prototype.getCytoscapeStyle = function(){
|
||||
var css = cytoscape.stylesheet()
|
||||
.selector("node")
|
||||
.css({
|
||||
"content": "data(label)",
|
||||
"text-valign": "center",
|
||||
"color": "white",
|
||||
"text-outline-width": 2,
|
||||
"text-outline-color": "#778899"
|
||||
})
|
||||
.selector("edge")
|
||||
.css({
|
||||
"background-color": "white"
|
||||
})
|
||||
.selector(".chosen")
|
||||
.css({
|
||||
"background-color": "black",
|
||||
"opacity": 0.6
|
||||
})
|
||||
.selector(".edgehandles-hover")
|
||||
.css({
|
||||
"background-color": "red"
|
||||
})
|
||||
.selector(".edgehandles-source")
|
||||
.css({
|
||||
"border-width": 2,
|
||||
"border-color": "red"
|
||||
})
|
||||
.selector(".edgehandles-target")
|
||||
.css({
|
||||
"border-width": 2,
|
||||
"border-color": "red"
|
||||
})
|
||||
.selector(".edgehandles-preview, .edgehandles-ghost-edge")
|
||||
.css({
|
||||
"line-color": "red",
|
||||
"target-arrow-color": "red",
|
||||
"target-arrow-color": "red"
|
||||
})
|
||||
.selector(".wcwccis")
|
||||
.css({
|
||||
"mid-target-arrow-shape": "circle",
|
||||
"mid-target-arrow-color": "red"
|
||||
})
|
||||
.selector(".wcsgcis")
|
||||
.css({
|
||||
"source-arrow-shape": "circle",
|
||||
"source-arrow-color": "red",
|
||||
"target-arrow-shape": "triangle",
|
||||
"target-arrow-color": "red"
|
||||
})
|
||||
.selector(".sgwccis")
|
||||
.css({
|
||||
"target-arrow-shape": "circle",
|
||||
"target-arrow-color": "red",
|
||||
"source-arrow-shape": "triangle",
|
||||
"source-arrow-color": "red"
|
||||
})
|
||||
.selector(".hgsgcis")
|
||||
.css({
|
||||
"source-arrow-shape": "square",
|
||||
"source-arrow-color": "red",
|
||||
"target-arrow-shape": "triangle",
|
||||
"target-arrow-color": "red"
|
||||
})
|
||||
.selector(".sghgcis")
|
||||
.css({
|
||||
"target-arrow-shape": "square",
|
||||
"target-arrow-color": "red",
|
||||
"source-arrow-shape": "triangle",
|
||||
"source-arrow-color": "red"
|
||||
})
|
||||
.selector(".wchgcis")
|
||||
.css({
|
||||
"source-arrow-shape": "circle",
|
||||
"source-arrow-color": "red",
|
||||
"target-arrow-shape": "square",
|
||||
"target-arrow-color": "red"
|
||||
})
|
||||
.selector(".hgwccis")
|
||||
.css({
|
||||
"target-arrow-shape": "circle",
|
||||
"target-arrow-color": "red",
|
||||
"source-arrow-shape": "square",
|
||||
"source-arrow-color": "red"
|
||||
})
|
||||
.selector(".sgsgcis")
|
||||
.css({
|
||||
"mid-target-arrow-shape": "triangle",
|
||||
"mid-target-arrow-color": "red"
|
||||
})
|
||||
.selector(".wcwctrans")
|
||||
.css({
|
||||
"mid=target-arrow-shape": "circle",
|
||||
"mid-target-arrow-color": "red",
|
||||
"mid-target-arrow-fill": "hollow"
|
||||
})
|
||||
.selector(".wcsgtrans")
|
||||
.css({
|
||||
"source-arrow-shape": "circle",
|
||||
"source-arrow-color": "red",
|
||||
"target-arrow-shape": "triangle",
|
||||
"target-arrow-color": "red",
|
||||
"target-arrow-fill": "hollow",
|
||||
"source-arrow-fill": "hollow"
|
||||
})
|
||||
.selector(".sgwctrans")
|
||||
.css({
|
||||
"target-arrow-shape": "circle",
|
||||
"target-arrow-color": "red",
|
||||
"source-arrow-shape": "triangle",
|
||||
"source-arrow-color": "red",
|
||||
"source-arrow-fill": "hollow",
|
||||
"target-arrow-fill": "hollow"
|
||||
})
|
||||
.selector(".hgsgtrans")
|
||||
.css({
|
||||
"source-arrow-shape": "square",
|
||||
"source-arrow-color": "red",
|
||||
"target-arrow-shape": "triangle",
|
||||
"target-arrow-color": "red",
|
||||
"target-arrow-fill": "hollow",
|
||||
"source-arrow-fill": "hollow"
|
||||
})
|
||||
.selector(".sghgtrans")
|
||||
.css({
|
||||
"target-arrow-shape": "square",
|
||||
"target-arrow-color": "red",
|
||||
"source-arrow-shape": "triangle",
|
||||
"source-arrow-color": "red",
|
||||
"source-arrow-fill": "hollow",
|
||||
"target-arrow-fill": "hollow"
|
||||
})
|
||||
.selector(".wchgtrans")
|
||||
.css({
|
||||
"source-arrow-shape": "circle",
|
||||
"source-arrow-color": "red",
|
||||
"target-arrow-shape": "square",
|
||||
"target-arrow-color": "red",
|
||||
"target-arrow-fill": "hollow",
|
||||
"source-arrow-fill": "hollow"
|
||||
})
|
||||
.selector(".hgwctrans")
|
||||
.css({
|
||||
"target-arrow-shape": "circle",
|
||||
"target-arrow-color": "red",
|
||||
"source-arrow-shape": "square",
|
||||
"source-arrow-color": "red",
|
||||
"source-arrow-fill": "hollow",
|
||||
"target-arrow-fill": "hollow"
|
||||
})
|
||||
.selector(".sgsgtrans")
|
||||
.css({
|
||||
"mid-target-arrow-shape": "triangle",
|
||||
"mid-target-arrow-color": "red",
|
||||
"mid-target-arrow-fill": "hollow"
|
||||
})
|
||||
.selector(".hghgcis")
|
||||
.css({
|
||||
"mid-target-arrow-shape": "square",
|
||||
"mid-target-arrow-color": "red",
|
||||
})
|
||||
.selector(".hghgtrans")
|
||||
.css({
|
||||
"mid-target-arrow-shape": "square",
|
||||
"mid-target-arrow-color": "red",
|
||||
"mid-target-arrow-fill": "hollow"
|
||||
});
|
||||
|
||||
return css;
|
||||
}
|
||||
+129
@@ -0,0 +1,129 @@
|
||||
var Backbone = require("backbone");
|
||||
var NCAnno = require("../models/ncanno");
|
||||
var $ = jQuery = require("jquery");
|
||||
var bootstrap = require("bootstrap");
|
||||
|
||||
var AnnoView = Backbone.View.extend({
|
||||
events: {
|
||||
"click #annook": "applyAnno",
|
||||
"click #wc1": "selectWc1",
|
||||
"click #hg1": "selectHg1",
|
||||
"click #sg1": "selectSg1",
|
||||
"click #wc2": "selectWc2",
|
||||
"click #hg2": "selectHg2",
|
||||
"click #sg2": "selectSg2",
|
||||
"click #st1": "selectStericityCis",
|
||||
"click #st2": "selectStericityTrans"
|
||||
},
|
||||
initialize: function(b1, b2, st, edge, cyEle){
|
||||
var el = document.createElement("div");
|
||||
cyEle.parentNode.appendChild(el);
|
||||
this.setElement(el);
|
||||
this.anno = new NCAnno(b1, b2, st, edge);
|
||||
//CSS
|
||||
this.defineStyle();
|
||||
this.render();
|
||||
},
|
||||
applyAnno: function(){
|
||||
var e1 = this.anno.get("base1");
|
||||
var e2 = this.anno.get("base2");
|
||||
var st = this.anno.get("stericity");
|
||||
this.anno.get("edge")._private.classes = {};
|
||||
this.anno.get("edge").addClass(e1 + e2 + st);
|
||||
this.remove();
|
||||
},
|
||||
render: function(){
|
||||
//HTML SETUP
|
||||
var res1 = this.anno.get("edge").source().data("label");
|
||||
var res2 = this.anno.get("edge").target().data("label");
|
||||
var edefs = this.anno.getLabels();
|
||||
|
||||
this.el.innerHTML += "<div class='col-md-4'>"
|
||||
+ "<span>Residue: " + res1 + "</span>"
|
||||
+ "<div class='dropdown'>"
|
||||
+ "<button class='btn btn-default dropdown-toggle' type='button' id='menu1' data-toggle='dropdown'>" + edefs[0]
|
||||
+ "<span class='caret'></span></button>"
|
||||
+ "<ul class='dropdown-menu' role='menu' aria-labelledby='menu1'>"
|
||||
+ "<li role='presentation'><span class='text-muted' id='wc1' style='cursor: pointer;'>Watson-Crick</span></li>"
|
||||
+ "<li role='presentation'><span class='text-muted' id='hg1' style='cursor: pointer;'>Hoogsteen</span></li>"
|
||||
+ "<li role='presentation'><span class='text-muted' id='sg1' style='cursor: pointer;'>Sugar</span></li>"
|
||||
+ "</ul>"
|
||||
+ "</div>"
|
||||
+ "</div>";
|
||||
this.el.innerHTML += "<div class='col-md-4'>"
|
||||
+ "<span>Residue: " + res2 + "</span>"
|
||||
+ "<div class='dropdown'>"
|
||||
+ "<button class='btn btn-default dropdown-toggle' type='button' id='menu2' data-toggle='dropdown'>" + edefs[1]
|
||||
+ "<span class='caret'></span></button>"
|
||||
+ "<ul class='dropdown-menu' role='menu' aria-labelledby='menu2'>"
|
||||
+ "<li role='presentation'><span class='text-muted' id='wc2' style='cursor: pointer;'>Watson-Crick</span></li>"
|
||||
+ "<li role='presentation'><span class='text-muted' id='hg2' style='cursor: pointer;'>Hoogsteen</span></li>"
|
||||
+ "<li role='presentation'><span class='text-muted' id='sg2' style='cursor: pointer;'>Sugar</span></li>"
|
||||
+ "</ul>"
|
||||
+ "</div>"
|
||||
+ "</div>";
|
||||
this.el.innerHTML += ""
|
||||
+ "<div class='col-md-3'><div class='dropdown'>"
|
||||
+ "<button class='btn btn-default dropdown-toggle' type='button' id='menu3' data-toggle='dropdown' style='margin-top: 19px;'>" + edefs[2]
|
||||
+ "<span class='caret'></span></button>"
|
||||
+ "<ul class='dropdown-menu'>"
|
||||
+ "<li role='presentation'><span class='text-muted' id='st1' style='cursor: pointer;'>cis</span></li>"
|
||||
+ "<li role='presentation'><span class='text-muted' id='st2' style='cursor: pointer;'>trans</span></li>"
|
||||
+ "</ul>"
|
||||
+ "</div></div>";
|
||||
|
||||
this.el.innerHTML += "<div class='col-md-1'><button class='btn btn-default' type='button' id='annook' style='margin-top: 19px;'>OK"
|
||||
+ "</button></div>";
|
||||
},
|
||||
defineStyle: function(){
|
||||
var st = this.el.style;
|
||||
st.display = "block";
|
||||
st.position = "absolute";
|
||||
st.left = "1%";
|
||||
st.width = "435px";
|
||||
st.height = "170px";
|
||||
st.padding = "10px";
|
||||
st.paddingRight = "55px";
|
||||
st.border = "1px solid black";
|
||||
st.borderRadius = "1px";
|
||||
st.backgroundColor = "#F6F6F6";
|
||||
st.overflow = "auto";
|
||||
st.fontWeight = "bold";
|
||||
st.textAlign = "center";
|
||||
st.zIndex = 1002;
|
||||
},
|
||||
selectWc1: function(){
|
||||
this.anno.set("base1", "wc");
|
||||
document.getElementById("menu1").innerHTML = "Watson-Crick<span class='caret'></span>";
|
||||
},
|
||||
selectHg1: function(){
|
||||
this.anno.set("base1", "hg");
|
||||
document.getElementById("menu1").innerHTML = "Hoogsteen<span class='caret'></span>";
|
||||
},
|
||||
selectSg1: function(){
|
||||
this.anno.set("base1", "sg");
|
||||
document.getElementById("menu1").innerHTML = "Sugar<span class='caret'></span>";
|
||||
},
|
||||
selectWc2: function(){
|
||||
this.anno.set("base2", "wc");
|
||||
document.getElementById("menu2").innerHTML = "Watson-Crick<span class='caret'></span>";
|
||||
},
|
||||
selectHg2: function(){
|
||||
this.anno.set("base2", "hg");
|
||||
document.getElementById("menu2").innerHTML = "Hoogsteen<span class='caret'></span>";
|
||||
},
|
||||
selectSg2: function(){
|
||||
this.anno.set("base2", "sg");
|
||||
document.getElementById("menu2").innerHTML = "Sugar<span class='caret'></span>";
|
||||
},
|
||||
selectStericityCis: function(){
|
||||
this.anno.set("stericity", "cis");
|
||||
document.getElementById("menu3").innerHTML = "Cis<span class='caret'></span>";
|
||||
},
|
||||
selectStericityTrans: function(){
|
||||
this.anno.set("stericity", "trans");
|
||||
document.getElementById("menu3").innerHTML = "Trans<span class='caret'></span>";
|
||||
}
|
||||
});
|
||||
|
||||
module.exports = AnnoView;
|
||||
+189
@@ -0,0 +1,189 @@
|
||||
var Backbone = require("backbone");
|
||||
var $ = jQuery = require("jquery");
|
||||
var spectrum = require("../utils/spectrum");
|
||||
var lassotool = require("../utils/lasso");
|
||||
var _ = require("underscore");
|
||||
var tooltip = require("tooltip");
|
||||
|
||||
var Optspanel = Backbone.View.extend({
|
||||
events: {
|
||||
"click #export": "exportAsPNG",
|
||||
"click #center": "center",
|
||||
"click #lasso": "activateLasso",
|
||||
"click #discovery": "activateDiscovery",
|
||||
"click #newbond": "activateBondDrawing"
|
||||
},
|
||||
initialize: function(opts){
|
||||
this.el = opts.el;
|
||||
this.el.className += "container-fluid";
|
||||
this.el.id = "opts";
|
||||
this.struct = opts.struct;
|
||||
this.vis = opts.vis;
|
||||
|
||||
this.listenTo(this.vis, "rendered", this.checkMode)
|
||||
},
|
||||
render: function(){
|
||||
tooltip({
|
||||
showDelay: 100,
|
||||
offset: {
|
||||
x: -85,
|
||||
y: 0
|
||||
},
|
||||
style: {
|
||||
"border-radius": "5px"
|
||||
}
|
||||
});
|
||||
this.el.innerHTML += '<div class="cntrl"><button class="icon" id="discovery" data-tooltip="Exploration mode" value="Discovery mode" readonly="readonly"><img class="mode" src="http://www.cipherpoint.com/wp-content/uploads/2014/07/search.png"></button>'
|
||||
+ '<button class="icon" id="lasso" value="Lasso mode" data-tooltip="Selection mode" readonly="readonly"><img class="mode" src="https://d30y9cdsu7xlg0.cloudfront.net/png/21906-200.png"></button>'
|
||||
+ '<button class="icon" id="newbond" value="Bond drawing mode" data-tooltip="Editing mode" readonly="readonly"><img class="mode" src="http://vseo.vn/dao-tao-seo/uploads/tin-tuc/anchor-link.png"></button></div>';
|
||||
this.el.innerHTML += '<div class="col-md-3"><p class="res">A</p></div>';
|
||||
this.el.innerHTML += '<div class="col-md-3"><p class="res">C</p></div>';
|
||||
this.el.innerHTML += '<div class="col-md-3"><p class="res">G</p></div>';
|
||||
this.el.innerHTML += '<div class="col-md-3"><p class="res">U</p></div>';
|
||||
this.el.innerHTML += '<div class="col-md-3"><input type="text" id="acolor"></div>';
|
||||
this.el.innerHTML += '<div class="col-md-3"><input type="text" id="ccolor"></div>';
|
||||
this.el.innerHTML += '<div class="col-md-3"><input type="text" id="gcolor"></div>';
|
||||
this.el.innerHTML += '<div class="col-md-3"><input type="text" id="ucolor"></div>';
|
||||
this.el.innerHTML += '<div class="col-md-9 colsel"><p>Color of selected nucleic acids</p></div>';
|
||||
this.el.innerHTML += '<div class="col-md-3 colsel"><input type="text" id="selcolor"></div>';
|
||||
this.el.innerHTML += '<div class="cntrl"><input class="button" id="center" value="Reset viewport" readonly="readonly">'
|
||||
+ '<input class="button" id="export" value="Export as PNG" readonly="readonly"></div>';
|
||||
|
||||
//init colors
|
||||
this.initColors(this);
|
||||
},
|
||||
initColors: function(self){
|
||||
var res = self.struct.get("residues");
|
||||
var cy = self;
|
||||
$("#acolor").spectrum({
|
||||
color: "#64F73F",
|
||||
change: function(color){
|
||||
res.setResidueColor("A", color.toHexString());
|
||||
cy.vis.cy.nodes("[label='A']").css("background-color", color.toHexString());
|
||||
}
|
||||
});
|
||||
$("#ccolor").spectrum({
|
||||
color: "#FFB340",
|
||||
change: function(color){
|
||||
res.setResidueColor("C", color.toHexString());
|
||||
cy.vis.cy.nodes("[label='C']").css("background-color", color.toHexString());
|
||||
}
|
||||
});
|
||||
$("#gcolor").spectrum({
|
||||
color: "#EB413C",
|
||||
change: function(color){
|
||||
res.setResidueColor("G", color.toHexString());
|
||||
cy.vis.cy.nodes("[label='G']").css("background-color", color.toHexString());
|
||||
}
|
||||
});
|
||||
$("#ucolor").spectrum({
|
||||
color: "#3C88EE",
|
||||
change: function(color){
|
||||
res.setResidueColor("U", color.toHexString());
|
||||
cy.vis.cy.nodes("[label='U']").css("background-color", color.toHexString());
|
||||
}
|
||||
});
|
||||
$("#selcolor").spectrum({
|
||||
color: "#F6F6F6",
|
||||
change: function(color){
|
||||
var sel = cy.vis.cy.$(".chosen");
|
||||
res.setSelectionColor(sel, color.toHexString());
|
||||
sel.css("background-color", color.toHexString());
|
||||
}
|
||||
});
|
||||
},
|
||||
exportAsPNG: function(){
|
||||
var cy = this.vis.cy;
|
||||
var png64 = cy.png({scale: 5});
|
||||
var newTab = window.open();
|
||||
newTab.document.write("<img src=" + png64 + " />");
|
||||
newTab.focus();
|
||||
},
|
||||
center: function(){
|
||||
var cy = this.vis.cy;
|
||||
cy.center();
|
||||
cy.fit();
|
||||
},
|
||||
activateLasso: function(){
|
||||
var polygon = [];
|
||||
var cy = this.vis.cy;
|
||||
var self = this;
|
||||
//turn off panning and zoom
|
||||
cy.userPanningEnabled(false);
|
||||
cy.userZoomingEnabled(false);
|
||||
cy.nodes().lock();
|
||||
//disable edge drawing
|
||||
cy.edgehandles("disable");
|
||||
this.bondDrawing = false;
|
||||
//add lasso
|
||||
$(".cy")
|
||||
.lasso()
|
||||
.on("lassoBegin", function(e, lassoPoints) {
|
||||
polygon = [];
|
||||
canvas = self.vis.el.childNodes[1];
|
||||
c2 = canvas.getContext('2d');
|
||||
c2.fillStyle = "rgba(100, 100, 100, 0.02)";
|
||||
c2.beginPath();
|
||||
|
||||
c2.moveTo(e.pageX, e.pageY);
|
||||
})
|
||||
.bind("lassoPoint", function(e, lassoPoint) {
|
||||
c2.lineTo(lassoPoint[0], lassoPoint[1] );
|
||||
c2.fill();
|
||||
polygon.push({x: lassoPoint[0], y: lassoPoint[1]});
|
||||
})
|
||||
.on("lassoDone", function(e, lassoPoints) {
|
||||
// do something with lassoPoints
|
||||
c2.closePath();
|
||||
c2.clearRect(0,0,canvas.width,canvas.height);
|
||||
var graphNodes = cy.nodes("[type!='index']");
|
||||
var nd = null;
|
||||
for(var i=0; i<graphNodes.length; i++){
|
||||
if(self.isPointInPoly(polygon, cy.$("#" + graphNodes[i].id()).renderedPosition())){
|
||||
cy.$("#" + graphNodes[i].id()).addClass("chosen");
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
isPointInPoly: function(poly, pt){
|
||||
var i, j, c = false;
|
||||
for (i = 0, j = poly.length-1; i < poly.length; j = i++) {
|
||||
if ( ((poly[i].y>pt.y) != (poly[j].y>pt.y)) &&
|
||||
(pt.x < (poly[j].x-poly[i].x) * (pt.y-poly[i].y) / (poly[j].y-poly[i].y) + poly[i].x) )
|
||||
c = !c;
|
||||
}
|
||||
return c;
|
||||
},
|
||||
activateDiscovery: function(){
|
||||
var cy = this.vis.cy;
|
||||
//remove lasso
|
||||
this.removeLasso();
|
||||
//disable edge drawing
|
||||
cy.edgehandles("disable");
|
||||
//turn zooming and panning back on
|
||||
cy.userPanningEnabled(true);
|
||||
cy.userZoomingEnabled(true);
|
||||
cy.nodes().unlock();
|
||||
this.bondDrawing = false;
|
||||
},
|
||||
activateBondDrawing: function(){
|
||||
var cy = this.vis.cy;
|
||||
//remove lasso
|
||||
this.removeLasso();
|
||||
cy.edgehandles("enable");
|
||||
this.bondDrawing = true;
|
||||
},
|
||||
removeLasso: function(){
|
||||
//remove lasso
|
||||
$(".cy").lasso().off("lassoBegin");
|
||||
$(".cy").lasso().off("lassoDone");
|
||||
$(".cy").lasso().unbind("lassoPoint");
|
||||
},
|
||||
checkMode: function(){
|
||||
if(this.bondDrawing){
|
||||
this.vis.cy.edgehandles("enable");
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
module.exports = Optspanel;
|
||||
+78
@@ -0,0 +1,78 @@
|
||||
var Backbone = require("backbone");
|
||||
|
||||
var Seqpanel = Backbone.View.extend({
|
||||
events: {
|
||||
"click #perform": "drawInput"
|
||||
},
|
||||
initialize: function(opts){
|
||||
this.struct = opts.struct;
|
||||
this.el = opts.el;
|
||||
this.el.className += "container-fluid";
|
||||
this.el.id = "seqinput";
|
||||
|
||||
this.listenTo(this.struct, "change:seq", this.updateSeq);
|
||||
this.listenTo(this.struct, "change:dotbr", this.updateDotbr);
|
||||
},
|
||||
render: function(){
|
||||
this.el.innerHTML += '<div class="col-md-11 seqin"><input type="text" class="alertfield" id="alert" readonly>'
|
||||
+ '<input class="textbox" id="seqbox">'
|
||||
+ '<input class="textbox" id="dotbrbox"></div>';
|
||||
this.el.innerHTML += '<div class="col-md-1 seqin">'
|
||||
+ '<input class="button" id="perform" value="Display" readonly="readonly">'
|
||||
+ '</div>';
|
||||
document.getElementById("seqbox").value = this.struct.get("seq");
|
||||
document.getElementById("dotbrbox").value = this.struct.get("dotbr");
|
||||
this.el.style.paddingBottom = "20px";
|
||||
},
|
||||
updateSeq: function(){
|
||||
document.getElementById("seqbox").value = this.struct.get("seq");
|
||||
},
|
||||
updateDotbr: function(){
|
||||
document.getElementById("dotbrbox").value = this.struct.get("dotbr");
|
||||
},
|
||||
drawInput: function(){
|
||||
var sequ = [
|
||||
document.getElementById("seqbox").value,
|
||||
document.getElementById("dotbrbox").value
|
||||
];
|
||||
var state = this.checkInput(sequ);
|
||||
if(state.fine){
|
||||
this.struct.set("seq", sequ[0]);
|
||||
this.struct.set("dotbr", sequ[1]);
|
||||
this.struct.set("renderSwitch", !this.struct.get("renderSwitch"));
|
||||
}
|
||||
else {
|
||||
var al = document.getElementById("alert");
|
||||
if(al){
|
||||
al.value = state.msg;
|
||||
}
|
||||
}
|
||||
},
|
||||
checkInput: function(sequences){
|
||||
var isFine = true;
|
||||
var errMsg = "";
|
||||
|
||||
if(sequences[0].length === 0 || sequences[1].length === 0){
|
||||
isFine = false;
|
||||
errMsg = "Please enter a sequence!";
|
||||
}
|
||||
else if(sequences[0].length != sequences[1].length){
|
||||
isFine = false;
|
||||
errMsg = "Sequences must have equal length!";
|
||||
}
|
||||
else if(! sequences[1].match('^[().]+$')){
|
||||
isFine = false;
|
||||
errMsg = "Dot-bracket sequence may only contain \"(\", \")\", or \".\"!";
|
||||
}
|
||||
else if(! sequences[0].match('^[ACGUTRYSWKMBDHVNacgutryswkmbdhvn-]+$')){
|
||||
isFine = false;
|
||||
errMsg = "Sequence may only contain IUPAC-characters!";
|
||||
}
|
||||
return {
|
||||
fine: isFine,
|
||||
msg: errMsg
|
||||
};
|
||||
}
|
||||
});
|
||||
|
||||
module.exports = Seqpanel;
|
||||
+218
@@ -0,0 +1,218 @@
|
||||
var Backbone = require("backbone");
|
||||
var cytoscape = require("cytoscape");
|
||||
var $ = jQuery = require("jquery");
|
||||
var Link = require("../models/link");
|
||||
var AnnoView = require("./annoview");
|
||||
var edgehandles = require("cytoscape-edgehandles")(cytoscape, $);
|
||||
var Style = require("../utils/style");
|
||||
|
||||
var Vispanel = Backbone.View.extend({
|
||||
initialize: function(opts){
|
||||
this.el = opts.el;
|
||||
this.struct = opts.struct;
|
||||
this.resindex = opts.resindex;
|
||||
this.annotate = true;
|
||||
|
||||
//events
|
||||
this.listenTo(this.struct, "change:renderSwitch", this.render);
|
||||
},
|
||||
render: function(){
|
||||
var self = this;
|
||||
var srcNode = null;
|
||||
var targetNode = null;
|
||||
self.innerHTML = "";
|
||||
|
||||
this.cy = cytoscape({
|
||||
container: self.el,
|
||||
style: (new Style()).getCytoscapeStyle(),
|
||||
elements: self.struct.toCytoscape(),
|
||||
layout: {
|
||||
//Use preset layout with precalculated
|
||||
//nucleotide coordinates
|
||||
name: 'preset',
|
||||
},
|
||||
ready: function(){
|
||||
this.edges("[label='violation']").each(function(index, ele){
|
||||
if(Object.keys(ele._private.classes).length === 0){
|
||||
ele.addClass("wcwccis");
|
||||
}
|
||||
});
|
||||
//events
|
||||
this.on("tapstart", function(evt){
|
||||
this.$(".chosen").removeClass("chosen");
|
||||
});
|
||||
this.on("tapdragover", "node", function(evt){
|
||||
var seqbox = document.getElementById("seqbox");
|
||||
if(seqbox && (this.id() < seqbox.value.length)){
|
||||
seqbox.selectionStart = parseInt(this.id());
|
||||
seqbox.selectionEnd = parseInt(this.id())+1;
|
||||
}
|
||||
});
|
||||
this.on("tapdragout", "node", function(evt){
|
||||
var seqbox = document.getElementById("seqbox");
|
||||
if(seqbox && (this.id() < seqbox.value.length)){
|
||||
seqbox.selectionEnd = -1;
|
||||
}
|
||||
});
|
||||
this.on("tap", "edge", function(evt){
|
||||
if(self.annotate && this.data("label") === "violation"){
|
||||
var obj = this._private.classes;
|
||||
for(var c in obj) break;
|
||||
new AnnoView(c.substring(0, 2), c.substring(2, 4), c.substring(4, c.length+1), this, self.el);
|
||||
}
|
||||
});
|
||||
|
||||
//Residue Nodes
|
||||
if(self.resindex){
|
||||
self.setResidueNodes(this);
|
||||
}
|
||||
},
|
||||
userPanningEnabled: true,
|
||||
userZoomingEnabled: true
|
||||
});
|
||||
|
||||
this.cy.edgehandles({
|
||||
loopAllowed: function(node){
|
||||
// for the specified node, return whether edges from itself to itself are allowed
|
||||
return false;
|
||||
},
|
||||
complete: function(srcNode, targetNode, addedEntities){
|
||||
// fired when edgehandles is done and entities are added
|
||||
self.struct.get("links").newBond(srcNode[0].id(), targetNode[0].id());
|
||||
},
|
||||
enabled: false,
|
||||
preview: false
|
||||
});
|
||||
|
||||
this.trigger("rendered");
|
||||
},
|
||||
setResidueNodes: function(cy){
|
||||
//index nodes
|
||||
for(var i=1; i<this.struct.get("seq").length/5; i++){
|
||||
pos = this.getPos(this.struct, (i*5)-1);
|
||||
this.cy.add({
|
||||
group: "nodes",
|
||||
data: {
|
||||
id: (this.struct.get("seq").length + i).toString(),
|
||||
label: (i*5) + "",
|
||||
type: "index"
|
||||
},
|
||||
position: {
|
||||
x: pos[0],
|
||||
y: pos[1]
|
||||
},
|
||||
selected: false,
|
||||
selectable: false,
|
||||
locked: false,
|
||||
grabbable: true,
|
||||
css: {
|
||||
"background-color": "#fff"
|
||||
}
|
||||
});
|
||||
cy.add({
|
||||
group: "edges",
|
||||
data: {
|
||||
id: "index" + i,
|
||||
source: (i*5) - 1,
|
||||
target: this.struct.get("seq").length + i,
|
||||
label: i*5,
|
||||
weight: 4
|
||||
},
|
||||
css: {
|
||||
'line-color': "black",
|
||||
'width': 4
|
||||
}
|
||||
});
|
||||
}
|
||||
},
|
||||
getPos: function(struct, target){
|
||||
var distance = 50;
|
||||
var found = false;
|
||||
var originX = struct.get("residues").at(target).get("x");
|
||||
var originY = struct.get("residues").at(target).get("y");
|
||||
var angleFactor = 0.0;
|
||||
var angle, x, y, tx, ty;
|
||||
while(!found && angleFactor<1){
|
||||
angle = angleFactor*Math.PI*2;
|
||||
x = Math.cos(angle)*distance + originX;
|
||||
y = Math.sin(angle)*distance + originY;
|
||||
for(var i=0; i<struct.get("seq").length+1; i++){
|
||||
if(i === struct.get("seq").length){
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
tx = struct.get("residues").at(i).get("x");
|
||||
ty = struct.get("residues").at(i).get("y");
|
||||
if(Math.pow((x - tx), 2) + Math.pow((y - ty), 2) < Math.pow(distance, 2)){
|
||||
break;
|
||||
}
|
||||
}
|
||||
angleFactor += 0.05
|
||||
}
|
||||
return [x, y];
|
||||
},
|
||||
changeBondType: function(bondid, type){
|
||||
if(type === "canonical"){
|
||||
this.cy.$("#" + bondid)[0].style("line-color", "#3A9AD9")
|
||||
this.cy.$("#" + bondid)[0].style("width", 4);
|
||||
this.cy.$("#" + bondid)[0]._private.classes = {};
|
||||
}
|
||||
else if(type === "non-canonical"){
|
||||
this.cy.$("#" + bondid)[0].style("line-color", "red");
|
||||
this.cy.$("#" + bondid)[0].style("width", 4);
|
||||
this.cy.$("#" + bondid)[0].addClass("wcwccis");
|
||||
}
|
||||
else {
|
||||
throw new Error("Type must be 'canoncial' or 'non-canonical'");
|
||||
}
|
||||
},
|
||||
addNCBond: function(source, target){
|
||||
this.cy.add({
|
||||
group: "edges",
|
||||
data: {
|
||||
id: source + "to" + target,
|
||||
source: source.toString(),
|
||||
target: target.toString()
|
||||
},
|
||||
css: {
|
||||
"line-color": "red",
|
||||
"width": 4
|
||||
}
|
||||
});
|
||||
this.cy.$("#" + source + "to" + target)[0].addClass("wcwccis");
|
||||
},
|
||||
setLeontisWesthof: function(edge, lwclass){
|
||||
var validClasses = [
|
||||
"wcwccis",
|
||||
"wcwctrans",
|
||||
"sgsgcis",
|
||||
"sgsgtrans",
|
||||
"hghgcis",
|
||||
"hghgtrans",
|
||||
"wcsgcis",
|
||||
"wcsgtrans",
|
||||
"sgwccis",
|
||||
"sgwctrans",
|
||||
"wchgcis",
|
||||
"wchgtrans",
|
||||
"hgwccis",
|
||||
"hgwctrans",
|
||||
"hgsgcis",
|
||||
"hgsgtrans",
|
||||
"sghgcis",
|
||||
"sghgtrans"
|
||||
];
|
||||
if(validClasses.indexOf(lwclass) === -1){
|
||||
throw new Error("LW-Class must be one of " + validClasses);
|
||||
}
|
||||
else {
|
||||
var classes = Object.keys(this.cy.$("#" + edge)[0]._private.classes);
|
||||
for(var i=0; i<classes.length; i++){
|
||||
this.cy.$("#" + edge)[0].removeClass(classes[i]);
|
||||
}
|
||||
this.cy.$("#" + edge)[0].addClass(lwclass);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
module.exports = Vispanel;
|
||||
File diff suppressed because one or more lines are too long
+261
@@ -0,0 +1,261 @@
|
||||
/*rules for the plot target div. These will be cascaded down to all plot elements according to css rules*/
|
||||
.jqplot-target {
|
||||
position: relative;
|
||||
color: #666666;
|
||||
font-family: "Trebuchet MS", Arial, Helvetica, sans-serif;
|
||||
font-size: 1em;
|
||||
/* height: 300px;
|
||||
width: 400px;*/
|
||||
}
|
||||
|
||||
/*rules applied to all axes*/
|
||||
.jqplot-axis {
|
||||
font-size: 0.75em;
|
||||
}
|
||||
|
||||
.jqplot-xaxis {
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
||||
.jqplot-x2axis {
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.jqplot-yaxis {
|
||||
margin-right: 10px;
|
||||
}
|
||||
|
||||
.jqplot-y2axis, .jqplot-y3axis, .jqplot-y4axis, .jqplot-y5axis, .jqplot-y6axis, .jqplot-y7axis, .jqplot-y8axis, .jqplot-y9axis, .jqplot-yMidAxis {
|
||||
margin-left: 10px;
|
||||
margin-right: 10px;
|
||||
}
|
||||
|
||||
/*rules applied to all axis tick divs*/
|
||||
.jqplot-axis-tick, .jqplot-xaxis-tick, .jqplot-yaxis-tick, .jqplot-x2axis-tick, .jqplot-y2axis-tick, .jqplot-y3axis-tick, .jqplot-y4axis-tick, .jqplot-y5axis-tick, .jqplot-y6axis-tick, .jqplot-y7axis-tick, .jqplot-y8axis-tick, .jqplot-y9axis-tick, .jqplot-yMidAxis-tick {
|
||||
position: absolute;
|
||||
white-space: pre;
|
||||
}
|
||||
|
||||
|
||||
.jqplot-xaxis-tick {
|
||||
top: 0px;
|
||||
/* initial position untill tick is drawn in proper place */
|
||||
left: 15px;
|
||||
/* padding-top: 10px;*/
|
||||
vertical-align: top;
|
||||
}
|
||||
|
||||
.jqplot-x2axis-tick {
|
||||
bottom: 0px;
|
||||
/* initial position untill tick is drawn in proper place */
|
||||
left: 15px;
|
||||
/* padding-bottom: 10px;*/
|
||||
vertical-align: bottom;
|
||||
}
|
||||
|
||||
.jqplot-yaxis-tick {
|
||||
right: 0px;
|
||||
/* initial position untill tick is drawn in proper place */
|
||||
top: 15px;
|
||||
/* padding-right: 10px;*/
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.jqplot-yaxis-tick.jqplot-breakTick {
|
||||
right: -20px;
|
||||
margin-right: 0px;
|
||||
padding:1px 5px 1px 5px;
|
||||
/* background-color: white;*/
|
||||
z-index: 2;
|
||||
font-size: 1.5em;
|
||||
}
|
||||
|
||||
.jqplot-y2axis-tick, .jqplot-y3axis-tick, .jqplot-y4axis-tick, .jqplot-y5axis-tick, .jqplot-y6axis-tick, .jqplot-y7axis-tick, .jqplot-y8axis-tick, .jqplot-y9axis-tick {
|
||||
left: 0px;
|
||||
/* initial position untill tick is drawn in proper place */
|
||||
top: 15px;
|
||||
/* padding-left: 10px;*/
|
||||
/* padding-right: 15px;*/
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.jqplot-yMidAxis-tick {
|
||||
text-align: center;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.jqplot-xaxis-label {
|
||||
margin-top: 10px;
|
||||
font-size: 11pt;
|
||||
position: absolute;
|
||||
}
|
||||
|
||||
.jqplot-x2axis-label {
|
||||
margin-bottom: 10px;
|
||||
font-size: 11pt;
|
||||
position: absolute;
|
||||
}
|
||||
|
||||
.jqplot-yaxis-label {
|
||||
margin-right: 10px;
|
||||
/* text-align: center;*/
|
||||
font-size: 11pt;
|
||||
position: absolute;
|
||||
}
|
||||
|
||||
.jqplot-yMidAxis-label {
|
||||
font-size: 11pt;
|
||||
position: absolute;
|
||||
}
|
||||
|
||||
.jqplot-y2axis-label, .jqplot-y3axis-label, .jqplot-y4axis-label, .jqplot-y5axis-label, .jqplot-y6axis-label, .jqplot-y7axis-label, .jqplot-y8axis-label, .jqplot-y9axis-label {
|
||||
/* text-align: center;*/
|
||||
font-size: 11pt;
|
||||
margin-left: 10px;
|
||||
position: absolute;
|
||||
}
|
||||
|
||||
.jqplot-meterGauge-tick {
|
||||
font-size: 0.75em;
|
||||
color: #999999;
|
||||
}
|
||||
|
||||
.jqplot-meterGauge-label {
|
||||
font-size: 1em;
|
||||
color: #999999;
|
||||
}
|
||||
|
||||
table.jqplot-table-legend {
|
||||
margin-top: 12px;
|
||||
margin-bottom: 12px;
|
||||
margin-left: 12px;
|
||||
margin-right: 12px;
|
||||
}
|
||||
|
||||
table.jqplot-table-legend, table.jqplot-cursor-legend {
|
||||
background-color: rgba(255,255,255,0.6);
|
||||
border: 1px solid #cccccc;
|
||||
position: absolute;
|
||||
font-size: 0.75em;
|
||||
}
|
||||
|
||||
td.jqplot-table-legend {
|
||||
vertical-align:middle;
|
||||
}
|
||||
|
||||
/*
|
||||
These rules could be used instead of assigning
|
||||
element styles and relying on js object properties.
|
||||
*/
|
||||
|
||||
/*
|
||||
td.jqplot-table-legend-swatch {
|
||||
padding-top: 0.5em;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
tr.jqplot-table-legend:first td.jqplot-table-legend-swatch {
|
||||
padding-top: 0px;
|
||||
}
|
||||
*/
|
||||
|
||||
td.jqplot-seriesToggle:hover, td.jqplot-seriesToggle:active {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.jqplot-table-legend .jqplot-series-hidden {
|
||||
text-decoration: line-through;
|
||||
}
|
||||
|
||||
div.jqplot-table-legend-swatch-outline {
|
||||
border: 1px solid #cccccc;
|
||||
padding:1px;
|
||||
}
|
||||
|
||||
div.jqplot-table-legend-swatch {
|
||||
width:0px;
|
||||
height:0px;
|
||||
border-top-width: 5px;
|
||||
border-bottom-width: 5px;
|
||||
border-left-width: 6px;
|
||||
border-right-width: 6px;
|
||||
border-top-style: solid;
|
||||
border-bottom-style: solid;
|
||||
border-left-style: solid;
|
||||
border-right-style: solid;
|
||||
}
|
||||
|
||||
.jqplot-title {
|
||||
top: 0px;
|
||||
left: 0px;
|
||||
padding-bottom: 0.5em;
|
||||
font-size: 1.2em;
|
||||
}
|
||||
|
||||
table.jqplot-cursor-tooltip {
|
||||
border: 1px solid #cccccc;
|
||||
font-size: 0.75em;
|
||||
}
|
||||
|
||||
|
||||
.jqplot-cursor-tooltip {
|
||||
border: 1px solid #cccccc;
|
||||
font-size: 0.75em;
|
||||
white-space: nowrap;
|
||||
background: rgba(208,208,208,0.5);
|
||||
padding: 1px;
|
||||
}
|
||||
|
||||
.jqplot-highlighter-tooltip, .jqplot-canvasOverlay-tooltip {
|
||||
border: 1px solid #cccccc;
|
||||
font-size: 1.2em;
|
||||
font-weight: bold;
|
||||
white-space: nowrap;
|
||||
background: rgba(235,235,235,1);
|
||||
padding: 1px;
|
||||
border-radius: 5px;
|
||||
}
|
||||
|
||||
.jqplot-point-label {
|
||||
font-size: 0.75em;
|
||||
z-index: 2;
|
||||
}
|
||||
|
||||
td.jqplot-cursor-legend-swatch {
|
||||
vertical-align: middle;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
div.jqplot-cursor-legend-swatch {
|
||||
width: 1.2em;
|
||||
height: 0.7em;
|
||||
}
|
||||
|
||||
.jqplot-error {
|
||||
/* Styles added to the plot target container when there is an error go here.*/
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.jqplot-error-message {
|
||||
/* Styling of the custom error message div goes here.*/
|
||||
position: relative;
|
||||
top: 46%;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
div.jqplot-bubble-label {
|
||||
font-size: 0.8em;
|
||||
/* background: rgba(90%, 90%, 90%, 0.15);*/
|
||||
padding-left: 2px;
|
||||
padding-right: 2px;
|
||||
color: rgb(20%, 20%, 20%);
|
||||
}
|
||||
|
||||
div.jqplot-bubble-label.jqplot-bubble-label-highlight {
|
||||
background: rgba(90%, 90%, 90%, 0.7);
|
||||
}
|
||||
|
||||
div.jqplot-noData-container {
|
||||
text-align: center;
|
||||
background-color: rgba(96%, 96%, 96%, 0.3);
|
||||
}
|
||||
File diff suppressed because one or more lines are too long
+151
File diff suppressed because one or more lines are too long
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user